mirror of https://gitee.com/openkylin/linux.git
Merge ath-next from ath.git
ath.git patches for 4.7. Major changes: ath6kl * add ability to set debug uart baud rate with a module parameter wil6210 * add debugfs file to configure firmware led functionality
This commit is contained in:
commit
52776a700b
|
@ -202,6 +202,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.name = "qca4019 hw1.0",
|
||||
.patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.has_shifted_cc_wraparound = true,
|
||||
.otp_exe_param = 0x0010000,
|
||||
.continuous_frag_desc = true,
|
||||
.channel_counters_freq_hz = 125000,
|
||||
|
@ -686,6 +687,9 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
|||
if (!IS_ERR(ar->cal_file))
|
||||
release_firmware(ar->cal_file);
|
||||
|
||||
if (!IS_ERR(ar->pre_cal_file))
|
||||
release_firmware(ar->pre_cal_file);
|
||||
|
||||
ath10k_swap_code_seg_release(ar);
|
||||
|
||||
ar->normal_mode_fw.fw_file.otp_data = NULL;
|
||||
|
@ -696,6 +700,7 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
|||
ar->normal_mode_fw.fw_file.firmware_len = 0;
|
||||
|
||||
ar->cal_file = NULL;
|
||||
ar->pre_cal_file = NULL;
|
||||
}
|
||||
|
||||
static int ath10k_fetch_cal_file(struct ath10k *ar)
|
||||
|
@ -1392,6 +1397,7 @@ static void ath10k_core_restart(struct work_struct *work)
|
|||
complete_all(&ar->install_key_done);
|
||||
complete_all(&ar->vdev_setup_done);
|
||||
complete_all(&ar->thermal.wmi_sync);
|
||||
complete_all(&ar->bss_survey_done);
|
||||
wake_up(&ar->htt.empty_tx_wq);
|
||||
wake_up(&ar->wmi.tx_credits_wq);
|
||||
wake_up(&ar->peer_mapping_wq);
|
||||
|
@ -1724,6 +1730,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
|||
if (ath10k_peer_stats_enabled(ar))
|
||||
val = WMI_10_4_PEER_STATS;
|
||||
|
||||
if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map))
|
||||
val |= WMI_10_4_BSS_CHANNEL_INFO_64;
|
||||
|
||||
status = ath10k_mac_ext_resource_config(ar, val);
|
||||
if (status) {
|
||||
ath10k_err(ar,
|
||||
|
@ -1758,6 +1767,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
|||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
|
||||
|
||||
INIT_LIST_HEAD(&ar->arvifs);
|
||||
|
||||
/* we don't care about HTT in UTF mode */
|
||||
if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
|
||||
status = ath10k_htt_setup(&ar->htt);
|
||||
|
@ -1771,10 +1784,6 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
|||
if (status)
|
||||
goto err_hif_stop;
|
||||
|
||||
ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
|
||||
|
||||
INIT_LIST_HEAD(&ar->arvifs);
|
||||
|
||||
return 0;
|
||||
|
||||
err_hif_stop:
|
||||
|
@ -2085,6 +2094,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
|||
init_completion(&ar->install_key_done);
|
||||
init_completion(&ar->vdev_setup_done);
|
||||
init_completion(&ar->thermal.wmi_sync);
|
||||
init_completion(&ar->bss_survey_done);
|
||||
|
||||
INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);
|
||||
|
||||
|
|
|
@ -876,6 +876,7 @@ struct ath10k {
|
|||
* avoid reporting garbage data.
|
||||
*/
|
||||
bool ch_info_can_report_survey;
|
||||
struct completion bss_survey_done;
|
||||
|
||||
struct dfs_pattern_detector *dfs_detector;
|
||||
|
||||
|
@ -883,8 +884,6 @@ struct ath10k {
|
|||
|
||||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
struct ath10k_debug debug;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
/* relay(fs) channel for spectral scan */
|
||||
struct rchan *rfs_chan_spec_scan;
|
||||
|
@ -893,6 +892,7 @@ struct ath10k {
|
|||
enum ath10k_spectral_mode mode;
|
||||
struct ath10k_spec_scan config;
|
||||
} spectral;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
/* protected by conf_mutex */
|
||||
|
|
|
@ -4278,9 +4278,6 @@ static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar)
|
|||
if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
|
||||
band = &ar->mac.sbands[NL80211_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[NL80211_BAND_5GHZ];
|
||||
|
@ -4346,7 +4343,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
|||
|
||||
/*
|
||||
* This makes sense only when restarting hw. It is harmless to call
|
||||
* uncoditionally. This is necessary to make sure no HTT/WMI tx
|
||||
* unconditionally. This is necessary to make sure no HTT/WMI tx
|
||||
* commands will be submitted while restarting.
|
||||
*/
|
||||
ath10k_drain_tx(ar);
|
||||
|
@ -6407,6 +6404,39 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
|
|||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_mac_update_bss_chan_survey(struct ath10k *ar,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
int ret;
|
||||
enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
if (!test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map) ||
|
||||
(ar->rx_channel != channel))
|
||||
return;
|
||||
|
||||
if (ar->scan.state != ATH10K_SCAN_IDLE) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "ignoring bss chan info request while scanning..\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reinit_completion(&ar->bss_survey_done);
|
||||
|
||||
ret = ath10k_wmi_pdev_bss_chan_info_request(ar, type);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to send pdev bss chan info request\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->bss_survey_done, 3 * HZ);
|
||||
if (!ret) {
|
||||
ath10k_warn(ar, "bss channel survey timed out\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
|
@ -6431,6 +6461,8 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ath10k_mac_update_bss_chan_survey(ar, survey->channel);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
memcpy(survey, ar_survey, sizeof(*survey));
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
|
|
@ -191,6 +191,9 @@ struct wmi_ops {
|
|||
u32 fw_feature_bitmap);
|
||||
int (*get_vdev_subtype)(struct ath10k *ar,
|
||||
enum wmi_vdev_subtype subtype);
|
||||
struct sk_buff *(*gen_pdev_bss_chan_info_req)
|
||||
(struct ath10k *ar,
|
||||
enum wmi_bss_survey_req_type type);
|
||||
};
|
||||
|
||||
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
||||
|
@ -1361,4 +1364,22 @@ ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype)
|
|||
return ar->wmi.ops->get_vdev_subtype(ar, subtype);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pdev_bss_chan_info_request(struct ath10k *ar,
|
||||
enum wmi_bss_survey_req_type type)
|
||||
{
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!wmi->ops->gen_pdev_bss_chan_info_req)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = wmi->ops->gen_pdev_bss_chan_info_req(ar, type);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
wmi->cmd->pdev_bss_chan_info_request_cmdid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -521,7 +521,8 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
|
|||
.vdev_filter_neighbor_rx_packets_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_bss_chan_info_request_cmdid =
|
||||
WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
||||
};
|
||||
|
||||
/* 10.4 WMI cmd track */
|
||||
|
@ -1633,6 +1634,7 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
|
|||
ch->max_power = arg->max_power;
|
||||
ch->reg_power = arg->max_reg_power;
|
||||
ch->antenna_max = arg->max_antenna_gain;
|
||||
ch->max_tx_power = arg->max_power;
|
||||
|
||||
/* mode & flags share storage */
|
||||
ch->mode = arg->mode;
|
||||
|
@ -4792,6 +4794,58 @@ static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_event_pdev_bss_chan_info(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_pdev_bss_chan_info_event *ev;
|
||||
struct survey_info *survey;
|
||||
u64 busy, total, tx, rx, rx_bss;
|
||||
u32 freq, noise_floor;
|
||||
u32 cc_freq_hz = ar->hw_params.channel_counters_freq_hz;
|
||||
int idx;
|
||||
|
||||
ev = (struct wmi_pdev_bss_chan_info_event *)skb->data;
|
||||
if (WARN_ON(skb->len < sizeof(*ev)))
|
||||
return -EPROTO;
|
||||
|
||||
freq = __le32_to_cpu(ev->freq);
|
||||
noise_floor = __le32_to_cpu(ev->noise_floor);
|
||||
busy = __le64_to_cpu(ev->cycle_busy);
|
||||
total = __le64_to_cpu(ev->cycle_total);
|
||||
tx = __le64_to_cpu(ev->cycle_tx);
|
||||
rx = __le64_to_cpu(ev->cycle_rx);
|
||||
rx_bss = __le64_to_cpu(ev->cycle_rx_bss);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi event pdev bss chan info:\n freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n",
|
||||
freq, noise_floor, busy, total, tx, rx, rx_bss);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
idx = freq_to_idx(ar, freq);
|
||||
if (idx >= ARRAY_SIZE(ar->survey)) {
|
||||
ath10k_warn(ar, "bss chan info: invalid frequency %d (idx %d out of bounds)\n",
|
||||
freq, idx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
survey = &ar->survey[idx];
|
||||
|
||||
survey->noise = noise_floor;
|
||||
survey->time = div_u64(total, cc_freq_hz);
|
||||
survey->time_busy = div_u64(busy, cc_freq_hz);
|
||||
survey->time_rx = div_u64(rx_bss, cc_freq_hz);
|
||||
survey->time_tx = div_u64(tx, cc_freq_hz);
|
||||
survey->filled |= (SURVEY_INFO_NOISE_DBM |
|
||||
SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_TX);
|
||||
exit:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
complete(&ar->bss_survey_done);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
|
@ -5135,6 +5189,9 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_10_2_PDEV_TEMPERATURE_EVENTID:
|
||||
ath10k_wmi_event_temperature(ar, skb);
|
||||
break;
|
||||
case WMI_10_2_PDEV_BSS_CHAN_INFO_EVENTID:
|
||||
ath10k_wmi_event_pdev_bss_chan_info(ar, skb);
|
||||
break;
|
||||
case WMI_10_2_RTT_KEEPALIVE_EVENTID:
|
||||
case WMI_10_2_GPIO_INPUT_EVENTID:
|
||||
case WMI_10_2_PEER_RATECODE_LIST_EVENTID:
|
||||
|
@ -5212,6 +5269,7 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
ath10k_wmi_event_vdev_stopped(ar, skb);
|
||||
break;
|
||||
case WMI_10_4_WOW_WAKEUP_HOST_EVENTID:
|
||||
case WMI_10_4_PEER_RATECODE_LIST_EVENTID:
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"received event id %d not implemented\n", id);
|
||||
break;
|
||||
|
@ -5221,6 +5279,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_10_4_PDEV_TEMPERATURE_EVENTID:
|
||||
ath10k_wmi_event_temperature(ar, skb);
|
||||
break;
|
||||
case WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID:
|
||||
ath10k_wmi_event_pdev_bss_chan_info(ar, skb);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
||||
break;
|
||||
|
@ -5606,6 +5667,9 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
|
|||
if (ath10k_peer_stats_enabled(ar))
|
||||
features |= WMI_10_2_PEER_STATS;
|
||||
|
||||
if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map))
|
||||
features |= WMI_10_2_BSS_CHAN_INFO;
|
||||
|
||||
cmd->resource_config.feature_mask = __cpu_to_le32(features);
|
||||
|
||||
memcpy(&cmd->resource_config.common, &config, sizeof(config));
|
||||
|
@ -6636,6 +6700,26 @@ ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
|
|||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_10_2_op_gen_pdev_bss_chan_info(struct ath10k *ar,
|
||||
enum wmi_bss_survey_req_type type)
|
||||
{
|
||||
struct wmi_pdev_chan_info_req_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cmd = (struct wmi_pdev_chan_info_req_cmd *)skb->data;
|
||||
cmd->type = __cpu_to_le32(type);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi pdev bss info request type %d\n", type);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
/* This function assumes the beacon is already DMA mapped */
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, const void *bcn,
|
||||
|
@ -7735,6 +7819,7 @@ static const struct wmi_ops wmi_10_2_4_ops = {
|
|||
.gen_init = ath10k_wmi_10_2_op_gen_init,
|
||||
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
|
||||
.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
|
||||
.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
|
||||
|
||||
/* shared with 10.1 */
|
||||
.map_svc = wmi_10x_svc_map,
|
||||
|
@ -7861,6 +7946,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
|||
.gen_request_stats = ath10k_wmi_op_gen_request_stats,
|
||||
.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
|
||||
.get_vdev_subtype = ath10k_wmi_10_4_op_get_vdev_subtype,
|
||||
.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
|
||||
};
|
||||
|
||||
int ath10k_wmi_attach(struct ath10k *ar)
|
||||
|
|
|
@ -1444,6 +1444,7 @@ enum wmi_10_2_cmd_id {
|
|||
WMI_10_2_MU_CAL_START_CMDID,
|
||||
WMI_10_2_SET_LTEU_CONFIG_CMDID,
|
||||
WMI_10_2_SET_CCA_PARAMS,
|
||||
WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
||||
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
|
||||
};
|
||||
|
||||
|
@ -1487,6 +1488,8 @@ enum wmi_10_2_event_id {
|
|||
WMI_10_2_WDS_PEER_EVENTID,
|
||||
WMI_10_2_PEER_STA_PS_STATECHG_EVENTID,
|
||||
WMI_10_2_PDEV_TEMPERATURE_EVENTID,
|
||||
WMI_10_2_MU_REPORT_EVENTID,
|
||||
WMI_10_2_PDEV_BSS_CHAN_INFO_EVENTID,
|
||||
WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
|
@ -1795,6 +1798,7 @@ struct wmi_channel {
|
|||
__le32 reginfo1;
|
||||
struct {
|
||||
u8 antenna_max;
|
||||
u8 max_tx_power;
|
||||
} __packed;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
@ -2450,6 +2454,7 @@ enum wmi_10_2_feature_mask {
|
|||
WMI_10_2_RX_BATCH_MODE = BIT(0),
|
||||
WMI_10_2_ATF_CONFIG = BIT(1),
|
||||
WMI_10_2_COEX_GPIO = BIT(3),
|
||||
WMI_10_2_BSS_CHAN_INFO = BIT(6),
|
||||
WMI_10_2_PEER_STATS = BIT(7),
|
||||
};
|
||||
|
||||
|
@ -6280,6 +6285,17 @@ struct wmi_pdev_temperature_event {
|
|||
__le32 temperature;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_bss_chan_info_event {
|
||||
__le32 freq;
|
||||
__le32 noise_floor;
|
||||
__le64 cycle_busy;
|
||||
__le64 cycle_total;
|
||||
__le64 cycle_tx;
|
||||
__le64 cycle_rx;
|
||||
__le64 cycle_rx_bss;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/* WOW structures */
|
||||
enum wmi_wow_wakeup_event {
|
||||
WOW_BMISS_EVENT = 0,
|
||||
|
@ -6483,6 +6499,16 @@ enum wmi_host_platform_type {
|
|||
WMI_HOST_PLATFORM_LOW_PERF,
|
||||
};
|
||||
|
||||
enum wmi_bss_survey_req_type {
|
||||
WMI_BSS_SURVEY_REQ_TYPE_READ = 1,
|
||||
WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR,
|
||||
};
|
||||
|
||||
struct wmi_pdev_chan_info_req_cmd {
|
||||
__le32 type;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct ath10k;
|
||||
struct ath10k_vif;
|
||||
struct ath10k_fw_stats_pdev;
|
||||
|
|
|
@ -31,6 +31,7 @@ unsigned int debug_mask;
|
|||
static unsigned int suspend_mode;
|
||||
static unsigned int wow_mode;
|
||||
static unsigned int uart_debug;
|
||||
static unsigned int uart_rate = 115200;
|
||||
static unsigned int ath6kl_p2p;
|
||||
static unsigned int testmode;
|
||||
static unsigned int recovery_enable;
|
||||
|
@ -40,6 +41,7 @@ module_param(debug_mask, uint, 0644);
|
|||
module_param(suspend_mode, uint, 0644);
|
||||
module_param(wow_mode, uint, 0644);
|
||||
module_param(uart_debug, uint, 0644);
|
||||
module_param(uart_rate, uint, 0644);
|
||||
module_param(ath6kl_p2p, uint, 0644);
|
||||
module_param(testmode, uint, 0644);
|
||||
module_param(recovery_enable, uint, 0644);
|
||||
|
@ -180,6 +182,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
|
|||
|
||||
if (uart_debug)
|
||||
ar->conf_flags |= ATH6KL_CONF_UART_DEBUG;
|
||||
ar->hw.uarttx_rate = uart_rate;
|
||||
|
||||
set_bit(FIRST_BOOT, &ar->flag);
|
||||
|
||||
|
|
|
@ -781,6 +781,7 @@ struct ath6kl {
|
|||
u32 board_addr;
|
||||
u32 refclk_hz;
|
||||
u32 uarttx_pin;
|
||||
u32 uarttx_rate;
|
||||
u32 testscript_addr;
|
||||
u8 tx_ant;
|
||||
u8 rx_ant;
|
||||
|
|
|
@ -173,6 +173,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.reserved_ram_size = 7168,
|
||||
.board_addr = 0x436400,
|
||||
.testscript_addr = 0,
|
||||
.uarttx_pin = 11,
|
||||
.flags = 0,
|
||||
|
||||
.fw = {
|
||||
|
@ -650,6 +651,14 @@ int ath6kl_configure_target(struct ath6kl *ar)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
/* Only set the baud rate if we're actually doing debug */
|
||||
if (ar->conf_flags & ATH6KL_CONF_UART_DEBUG) {
|
||||
status = ath6kl_bmi_write_hi32(ar, hi_desired_baud_rate,
|
||||
ar->hw.uarttx_rate);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Configure target refclk_hz */
|
||||
if (ar->hw.refclk_hz != 0) {
|
||||
status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
|
||||
|
|
|
@ -75,6 +75,26 @@ config ATH9K_STATION_STATISTICS
|
|||
---help---
|
||||
This option enables detailed statistics for association stations.
|
||||
|
||||
config ATH9K_TX99
|
||||
bool "Atheros ath9k TX99 testing support"
|
||||
depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS
|
||||
default n
|
||||
---help---
|
||||
Say N. This should only be enabled on systems undergoing
|
||||
certification testing and evaluation in a controlled environment.
|
||||
Enabling this will only enable TX99 support, all other modes of
|
||||
operation will be disabled.
|
||||
|
||||
TX99 support enables Specific Absorption Rate (SAR) testing.
|
||||
SAR is the unit of measurement for the amount of radio frequency(RF)
|
||||
absorbed by the body when using a wireless device. The RF exposure
|
||||
limits used are expressed in the terms of SAR, which is a measure
|
||||
of the electric and magnetic field strength and power density for
|
||||
transmitters operating at frequencies from 300 kHz to 100 GHz.
|
||||
Regulatory bodies around the world require that wireless device
|
||||
be evaluated to meet the RF exposure limits set forth in the
|
||||
governmental SAR regulations.
|
||||
|
||||
config ATH9K_DFS_CERTIFIED
|
||||
bool "Atheros DFS support for certified platforms"
|
||||
depends on ATH9K && CFG80211_CERTIFICATION_ONUS
|
||||
|
@ -103,26 +123,6 @@ config ATH9K_DYNACK
|
|||
based on ACK frame RX timestamp, TX frame timestamp and frame
|
||||
duration
|
||||
|
||||
config ATH9K_TX99
|
||||
bool "Atheros ath9k TX99 testing support"
|
||||
depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS
|
||||
default n
|
||||
---help---
|
||||
Say N. This should only be enabled on systems undergoing
|
||||
certification testing and evaluation in a controlled environment.
|
||||
Enabling this will only enable TX99 support, all other modes of
|
||||
operation will be disabled.
|
||||
|
||||
TX99 support enables Specific Absorption Rate (SAR) testing.
|
||||
SAR is the unit of measurement for the amount of radio frequency(RF)
|
||||
absorbed by the body when using a wireless device. The RF exposure
|
||||
limits used are expressed in the terms of SAR, which is a measure
|
||||
of the electric and magnetic field strength and power density for
|
||||
transmitters operating at frequencies from 300 kHz to 100 GHz.
|
||||
Regulatory bodies around the world require that wireless device
|
||||
be evaluated to meet the RF exposure limits set forth in the
|
||||
governmental SAR regulations.
|
||||
|
||||
config ATH9K_WOW
|
||||
bool "Wake on Wireless LAN support (EXPERIMENTAL)"
|
||||
depends on ATH9K && PM
|
||||
|
|
|
@ -4402,7 +4402,7 @@ static void ar9003_hw_selfgen_tpc_txpower(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
/* Set tx power registers to array of values passed in */
|
||||
static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
|
||||
int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
|
||||
{
|
||||
#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
|
||||
/* make sure forced gain is not set */
|
||||
|
|
|
@ -355,5 +355,6 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
|
|||
struct ath9k_channel *chan);
|
||||
|
||||
void ar9003_hw_internal_regulator_apply(struct ath_hw *ah);
|
||||
int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/export.h>
|
||||
#include "hw.h"
|
||||
#include "ar9003_phy.h"
|
||||
#include "ar9003_eeprom.h"
|
||||
|
||||
#define AR9300_OFDM_RATES 8
|
||||
#define AR9300_HT_SS_RATES 8
|
||||
|
@ -1009,7 +1010,7 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah,
|
|||
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
|
||||
rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
|
||||
|
||||
if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF))
|
||||
if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
|
||||
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
|
||||
AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW, 3);
|
||||
|
||||
|
@ -1840,73 +1841,14 @@ static void ar9003_hw_tx99_stop(struct ath_hw *ah)
|
|||
|
||||
static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower)
|
||||
{
|
||||
static s16 p_pwr_array[ar9300RateSize] = { 0 };
|
||||
static u8 p_pwr_array[ar9300RateSize] = { 0 };
|
||||
unsigned int i;
|
||||
|
||||
if (txpower <= MAX_RATE_POWER) {
|
||||
for (i = 0; i < ar9300RateSize; i++)
|
||||
p_pwr_array[i] = txpower;
|
||||
} else {
|
||||
for (i = 0; i < ar9300RateSize; i++)
|
||||
p_pwr_array[i] = MAX_RATE_POWER;
|
||||
}
|
||||
txpower = txpower <= MAX_RATE_POWER ? txpower : MAX_RATE_POWER;
|
||||
for (i = 0; i < ar9300RateSize; i++)
|
||||
p_pwr_array[i] = txpower;
|
||||
|
||||
REG_WRITE(ah, 0xa458, 0);
|
||||
|
||||
REG_WRITE(ah, 0xa3c0,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0));
|
||||
REG_WRITE(ah, 0xa3c4,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_54], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_48], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_36], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0));
|
||||
REG_WRITE(ah, 0xa3c8,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0));
|
||||
REG_WRITE(ah, 0xa3cc,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11S], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11L], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_5S], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0));
|
||||
REG_WRITE(ah, 0xa3d0,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_5], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_4], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8)|
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0));
|
||||
REG_WRITE(ah, 0xa3d4,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_13], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_12], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_7], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_6], 0));
|
||||
REG_WRITE(ah, 0xa3e4,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_21], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_20], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_15], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_14], 0));
|
||||
REG_WRITE(ah, 0xa3e8,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_23], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_22], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_23], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_22], 0));
|
||||
REG_WRITE(ah, 0xa3d8,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_5], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_4], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0));
|
||||
REG_WRITE(ah, 0xa3dc,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_13], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_12], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_7], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_6], 0));
|
||||
REG_WRITE(ah, 0xa3ec,
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_21], 24) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_20], 16) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_15], 8) |
|
||||
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0));
|
||||
ar9003_hw_tx_power_regwrite(ah, p_pwr_array);
|
||||
}
|
||||
|
||||
static void ar9003_hw_init_txpower_cck(struct ath_hw *ah, u8 *rate_array)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#define WCN36XX_HAL_BUF_SIZE 4096
|
||||
|
||||
#define HAL_MSG_TIMEOUT 500
|
||||
#define HAL_MSG_TIMEOUT 10000
|
||||
#define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400
|
||||
#define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200
|
||||
/* The PNO version info be contained in the rsp msg */
|
||||
|
|
|
@ -375,8 +375,9 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* scan on P2P_DEVICE is handled as p2p search */
|
||||
if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
/* social scan on P2P_DEVICE is handled as p2p search */
|
||||
if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
|
||||
wil_p2p_is_social_scan(request)) {
|
||||
wil->scan_request = request;
|
||||
wil->radio_wdev = wdev;
|
||||
rc = wil_p2p_search(wil, request);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "wil6210.h"
|
||||
#include "trace.h"
|
||||
|
||||
void wil_err(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
void __wil_err(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct va_format vaf = {
|
||||
|
@ -32,7 +32,7 @@ void wil_err(struct wil6210_priv *wil, const char *fmt, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
if (net_ratelimit()) {
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
@ -49,7 +49,23 @@ void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
|
|||
}
|
||||
}
|
||||
|
||||
void wil_info(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
if (!net_ratelimit())
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
netdev_dbg(wil_to_ndev(wil), "%pV", &vaf);
|
||||
trace_wil6210_log_dbg(&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void __wil_info(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct va_format vaf = {
|
||||
|
|
|
@ -171,6 +171,8 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
|
|||
int rsize;
|
||||
uint i;
|
||||
|
||||
wil_halp_vote(wil);
|
||||
|
||||
wil_memcpy_fromio_32(&r, off, sizeof(r));
|
||||
wil_mbox_ring_le2cpus(&r);
|
||||
/*
|
||||
|
@ -236,6 +238,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
|
|||
}
|
||||
out:
|
||||
seq_puts(s, "}\n");
|
||||
wil_halp_unvote(wil);
|
||||
}
|
||||
|
||||
static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
|
||||
|
@ -500,9 +503,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
enum { max_count = 4096 };
|
||||
struct debugfs_blob_wrapper *blob = file->private_data;
|
||||
struct wil_blob_wrapper *wil_blob = file->private_data;
|
||||
loff_t pos = *ppos;
|
||||
size_t available = blob->size;
|
||||
size_t available = wil_blob->blob.size;
|
||||
void *buf;
|
||||
size_t ret;
|
||||
|
||||
|
@ -521,8 +524,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
|
|||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data +
|
||||
pos, count);
|
||||
wil_memcpy_fromio_halp_vote(wil_blob->wil, buf,
|
||||
(const volatile void __iomem *)
|
||||
wil_blob->blob.data + pos, count);
|
||||
|
||||
ret = copy_to_user(user_buf, buf, count);
|
||||
kfree(buf);
|
||||
|
@ -545,9 +549,9 @@ static
|
|||
struct dentry *wil_debugfs_create_ioblob(const char *name,
|
||||
umode_t mode,
|
||||
struct dentry *parent,
|
||||
struct debugfs_blob_wrapper *blob)
|
||||
struct wil_blob_wrapper *wil_blob)
|
||||
{
|
||||
return debugfs_create_file(name, mode, parent, blob, &fops_ioblob);
|
||||
return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob);
|
||||
}
|
||||
|
||||
/*---reset---*/
|
||||
|
@ -1437,6 +1441,118 @@ static const struct file_operations fops_sta = {
|
|||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static ssize_t wil_read_file_led_cfg(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char buf[80];
|
||||
int n;
|
||||
|
||||
n = snprintf(buf, sizeof(buf),
|
||||
"led_id is set to %d, echo 1 to enable, 0 to disable\n",
|
||||
led_id);
|
||||
|
||||
n = min_t(int, n, sizeof(buf));
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos,
|
||||
buf, n);
|
||||
}
|
||||
|
||||
static ssize_t wil_write_file_led_cfg(struct file *file,
|
||||
const char __user *buf_,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wil6210_priv *wil = file->private_data;
|
||||
int val;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoint_from_user(buf_, count, 0, &val);
|
||||
if (rc) {
|
||||
wil_err(wil, "Invalid argument\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
wil_info(wil, "%s led %d\n", val ? "Enabling" : "Disabling", led_id);
|
||||
rc = wmi_led_cfg(wil, val);
|
||||
if (rc) {
|
||||
wil_info(wil, "%s led %d failed\n",
|
||||
val ? "Enabling" : "Disabling", led_id);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_led_cfg = {
|
||||
.read = wil_read_file_led_cfg,
|
||||
.write = wil_write_file_led_cfg,
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
/* led_blink_time, write:
|
||||
* "<blink_on_slow> <blink_off_slow> <blink_on_med> <blink_off_med> <blink_on_fast> <blink_off_fast>
|
||||
*/
|
||||
static ssize_t wil_write_led_blink_time(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
int rc;
|
||||
char *kbuf = kmalloc(len + 1, GFP_KERNEL);
|
||||
|
||||
if (!kbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
|
||||
if (rc != len) {
|
||||
kfree(kbuf);
|
||||
return rc >= 0 ? -EIO : rc;
|
||||
}
|
||||
|
||||
kbuf[len] = '\0';
|
||||
rc = sscanf(kbuf, "%d %d %d %d %d %d",
|
||||
&led_blink_time[WIL_LED_TIME_SLOW].on_ms,
|
||||
&led_blink_time[WIL_LED_TIME_SLOW].off_ms,
|
||||
&led_blink_time[WIL_LED_TIME_MED].on_ms,
|
||||
&led_blink_time[WIL_LED_TIME_MED].off_ms,
|
||||
&led_blink_time[WIL_LED_TIME_FAST].on_ms,
|
||||
&led_blink_time[WIL_LED_TIME_FAST].off_ms);
|
||||
kfree(kbuf);
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (rc < 6)
|
||||
return -EINVAL;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t wil_read_led_blink_time(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
static char text[400];
|
||||
|
||||
snprintf(text, sizeof(text),
|
||||
"To set led blink on/off time variables write:\n"
|
||||
"<blink_on_slow> <blink_off_slow> <blink_on_med> "
|
||||
"<blink_off_med> <blink_on_fast> <blink_off_fast>\n"
|
||||
"The current values are:\n"
|
||||
"%d %d %d %d %d %d\n",
|
||||
led_blink_time[WIL_LED_TIME_SLOW].on_ms,
|
||||
led_blink_time[WIL_LED_TIME_SLOW].off_ms,
|
||||
led_blink_time[WIL_LED_TIME_MED].on_ms,
|
||||
led_blink_time[WIL_LED_TIME_MED].off_ms,
|
||||
led_blink_time[WIL_LED_TIME_FAST].on_ms,
|
||||
led_blink_time[WIL_LED_TIME_FAST].off_ms);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, text,
|
||||
sizeof(text));
|
||||
}
|
||||
|
||||
static const struct file_operations fops_led_blink_time = {
|
||||
.read = wil_read_led_blink_time,
|
||||
.write = wil_write_led_blink_time,
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
/*----------------*/
|
||||
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
|
||||
struct dentry *dbg)
|
||||
|
@ -1445,16 +1561,18 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
|
|||
char name[32];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
|
||||
struct debugfs_blob_wrapper *blob = &wil->blobs[i];
|
||||
struct wil_blob_wrapper *wil_blob = &wil->blobs[i];
|
||||
struct debugfs_blob_wrapper *blob = &wil_blob->blob;
|
||||
const struct fw_map *map = &fw_mapping[i];
|
||||
|
||||
if (!map->name)
|
||||
continue;
|
||||
|
||||
wil_blob->wil = wil;
|
||||
blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
|
||||
blob->size = map->to - map->from;
|
||||
snprintf(name, sizeof(name), "blob_%s", map->name);
|
||||
wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
|
||||
wil_debugfs_create_ioblob(name, S_IRUGO, dbg, wil_blob);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1483,6 +1601,8 @@ static const struct {
|
|||
{"link", S_IRUGO, &fops_link},
|
||||
{"info", S_IRUGO, &fops_info},
|
||||
{"recovery", S_IRUGO | S_IWUSR, &fops_recovery},
|
||||
{"led_cfg", S_IRUGO | S_IWUSR, &fops_led_cfg},
|
||||
{"led_blink_time", S_IRUGO | S_IWUSR, &fops_led_blink_time},
|
||||
};
|
||||
|
||||
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
|
||||
|
@ -1545,6 +1665,7 @@ static const struct dbg_off dbg_statics[] = {
|
|||
{"mem_addr", S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32},
|
||||
{"vring_idle_trsh", S_IRUGO | S_IWUSR, (ulong)&vring_idle_trsh,
|
||||
doff_u32},
|
||||
{"led_polarity", S_IRUGO | S_IWUSR, (ulong)&led_polarity, doff_u8},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -35,15 +35,19 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL)
|
||||
#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL)
|
||||
#define WIL6210_IRQ_DISABLE_NO_HALP (0xF7FFFFFFUL)
|
||||
#define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \
|
||||
BIT_DMA_EP_RX_ICR_RX_HTRSH)
|
||||
#define WIL6210_IMC_RX_NO_RX_HTRSH (WIL6210_IMC_RX & \
|
||||
(~(BIT_DMA_EP_RX_ICR_RX_HTRSH)))
|
||||
#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
|
||||
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
|
||||
#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \
|
||||
ISR_MISC_MBOX_EVT | \
|
||||
ISR_MISC_FW_ERROR)
|
||||
|
||||
#define WIL6210_IMC_MISC_NO_HALP (ISR_MISC_FW_READY | \
|
||||
ISR_MISC_MBOX_EVT | \
|
||||
ISR_MISC_FW_ERROR)
|
||||
#define WIL6210_IMC_MISC (WIL6210_IMC_MISC_NO_HALP | \
|
||||
BIT_DMA_EP_MISC_ICR_HALP)
|
||||
#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
|
||||
BIT_DMA_PSEUDO_CAUSE_TX | \
|
||||
BIT_DMA_PSEUDO_CAUSE_MISC))
|
||||
|
@ -51,6 +55,7 @@
|
|||
#if defined(CONFIG_WIL6210_ISR_COR)
|
||||
/* configure to Clear-On-Read mode */
|
||||
#define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL)
|
||||
#define WIL_ICR_ICC_MISC_VALUE (0xF7FFFFFFUL)
|
||||
|
||||
static inline void wil_icr_clear(u32 x, void __iomem *addr)
|
||||
{
|
||||
|
@ -58,6 +63,7 @@ static inline void wil_icr_clear(u32 x, void __iomem *addr)
|
|||
#else /* defined(CONFIG_WIL6210_ISR_COR) */
|
||||
/* configure to Write-1-to-Clear mode */
|
||||
#define WIL_ICR_ICC_VALUE (0UL)
|
||||
#define WIL_ICR_ICC_MISC_VALUE (0UL)
|
||||
|
||||
static inline void wil_icr_clear(u32 x, void __iomem *addr)
|
||||
{
|
||||
|
@ -86,10 +92,21 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
|
|||
WIL6210_IRQ_DISABLE);
|
||||
}
|
||||
|
||||
static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
|
||||
static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp)
|
||||
{
|
||||
wil_dbg_irq(wil, "%s: mask_halp(%s)\n", __func__,
|
||||
mask_halp ? "true" : "false");
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS),
|
||||
WIL6210_IRQ_DISABLE);
|
||||
mask_halp ? WIL6210_IRQ_DISABLE : WIL6210_IRQ_DISABLE_NO_HALP);
|
||||
}
|
||||
|
||||
static void wil6210_mask_halp(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS),
|
||||
BIT_DMA_EP_MISC_ICR_HALP);
|
||||
}
|
||||
|
||||
static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
|
||||
|
@ -109,14 +126,27 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
|
|||
|
||||
void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
|
||||
{
|
||||
bool unmask_rx_htrsh = test_bit(wil_status_fwconnected, wil->status);
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC),
|
||||
WIL6210_IMC_RX);
|
||||
unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH);
|
||||
}
|
||||
|
||||
static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
|
||||
static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
|
||||
{
|
||||
wil_dbg_irq(wil, "%s: unmask_halp(%s)\n", __func__,
|
||||
unmask_halp ? "true" : "false");
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC),
|
||||
WIL6210_IMC_MISC);
|
||||
unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP);
|
||||
}
|
||||
|
||||
static void wil6210_unmask_halp(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_irq(wil, "%s()\n", __func__);
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC),
|
||||
BIT_DMA_EP_MISC_ICR_HALP);
|
||||
}
|
||||
|
||||
static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
|
||||
|
@ -134,7 +164,7 @@ void wil_mask_irq(struct wil6210_priv *wil)
|
|||
|
||||
wil6210_mask_irq_tx(wil);
|
||||
wil6210_mask_irq_rx(wil);
|
||||
wil6210_mask_irq_misc(wil);
|
||||
wil6210_mask_irq_misc(wil, true);
|
||||
wil6210_mask_irq_pseudo(wil);
|
||||
}
|
||||
|
||||
|
@ -147,12 +177,12 @@ void wil_unmask_irq(struct wil6210_priv *wil)
|
|||
wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC),
|
||||
WIL_ICR_ICC_VALUE);
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC),
|
||||
WIL_ICR_ICC_VALUE);
|
||||
WIL_ICR_ICC_MISC_VALUE);
|
||||
|
||||
wil6210_unmask_irq_pseudo(wil);
|
||||
wil6210_unmask_irq_tx(wil);
|
||||
wil6210_unmask_irq_rx(wil);
|
||||
wil6210_unmask_irq_misc(wil);
|
||||
wil6210_unmask_irq_misc(wil, true);
|
||||
}
|
||||
|
||||
void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
|
||||
|
@ -228,11 +258,8 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
|||
*/
|
||||
if (likely(isr & (BIT_DMA_EP_RX_ICR_RX_DONE |
|
||||
BIT_DMA_EP_RX_ICR_RX_HTRSH))) {
|
||||
wil_dbg_irq(wil, "RX done\n");
|
||||
|
||||
if (unlikely(isr & BIT_DMA_EP_RX_ICR_RX_HTRSH))
|
||||
wil_err_ratelimited(wil,
|
||||
"Received \"Rx buffer is in risk of overflow\" interrupt\n");
|
||||
wil_dbg_irq(wil, "RX done / RX_HTRSH received, ISR (0x%x)\n",
|
||||
isr);
|
||||
|
||||
isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
|
||||
BIT_DMA_EP_RX_ICR_RX_HTRSH);
|
||||
|
@ -344,7 +371,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
wil6210_mask_irq_misc(wil);
|
||||
wil6210_mask_irq_misc(wil, false);
|
||||
|
||||
if (isr & ISR_MISC_FW_ERROR) {
|
||||
u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE);
|
||||
|
@ -372,12 +399,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
|||
isr &= ~ISR_MISC_FW_READY;
|
||||
}
|
||||
|
||||
if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
|
||||
wil_dbg_irq(wil, "%s: HALP IRQ invoked\n", __func__);
|
||||
wil6210_mask_halp(wil);
|
||||
isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
|
||||
complete(&wil->halp.comp);
|
||||
}
|
||||
|
||||
wil->isr_misc = isr;
|
||||
|
||||
if (isr) {
|
||||
return IRQ_WAKE_THREAD;
|
||||
} else {
|
||||
wil6210_unmask_irq_misc(wil);
|
||||
wil6210_unmask_irq_misc(wil, false);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
@ -414,7 +448,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
|
|||
|
||||
wil->isr_misc = 0;
|
||||
|
||||
wil6210_unmask_irq_misc(wil);
|
||||
wil6210_unmask_irq_misc(wil, false);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -556,6 +590,23 @@ void wil6210_clear_irq(struct wil6210_priv *wil)
|
|||
wmb(); /* make sure write completed */
|
||||
}
|
||||
|
||||
void wil6210_set_halp(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS),
|
||||
BIT_DMA_EP_MISC_ICR_HALP);
|
||||
}
|
||||
|
||||
void wil6210_clear_halp(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR),
|
||||
BIT_DMA_EP_MISC_ICR_HALP);
|
||||
wil6210_unmask_halp(wil);
|
||||
}
|
||||
|
||||
int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
|
||||
{
|
||||
int rc;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "wmi.h"
|
||||
#include "boot_loader.h"
|
||||
|
||||
#define WAIT_FOR_HALP_VOTE_MS 100
|
||||
|
||||
bool debug_fw; /* = false; */
|
||||
module_param(debug_fw, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
|
||||
|
@ -132,6 +134,14 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
|
|||
*d++ = __raw_readl(s++);
|
||||
}
|
||||
|
||||
void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst,
|
||||
const volatile void __iomem *src, size_t count)
|
||||
{
|
||||
wil_halp_vote(wil);
|
||||
wil_memcpy_fromio_32(dst, src, count);
|
||||
wil_halp_unvote(wil);
|
||||
}
|
||||
|
||||
void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
|
||||
size_t count)
|
||||
{
|
||||
|
@ -142,6 +152,15 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
|
|||
__raw_writel(*s++, d++);
|
||||
}
|
||||
|
||||
void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil,
|
||||
volatile void __iomem *dst,
|
||||
const void *src, size_t count)
|
||||
{
|
||||
wil_halp_vote(wil);
|
||||
wil_memcpy_toio_32(dst, src, count);
|
||||
wil_halp_unvote(wil);
|
||||
}
|
||||
|
||||
static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
|
||||
u16 reason_code, bool from_event)
|
||||
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
||||
|
@ -194,6 +213,18 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
memset(&sta->stats, 0, sizeof(sta->stats));
|
||||
}
|
||||
|
||||
static bool wil_ap_is_connected(struct wil6210_priv *wil)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
|
||||
if (wil->sta[i].status == wil_sta_connected)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
|
||||
u16 reason_code, bool from_event)
|
||||
{
|
||||
|
@ -247,6 +278,11 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
|
|||
}
|
||||
clear_bit(wil_status_fwconnecting, wil->status);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
if (!wil_ap_is_connected(wil))
|
||||
clear_bit(wil_status_fwconnected, wil->status);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -457,9 +493,11 @@ int wil_priv_init(struct wil6210_priv *wil)
|
|||
mutex_init(&wil->wmi_mutex);
|
||||
mutex_init(&wil->probe_client_mutex);
|
||||
mutex_init(&wil->p2p_wdev_mutex);
|
||||
mutex_init(&wil->halp.lock);
|
||||
|
||||
init_completion(&wil->wmi_ready);
|
||||
init_completion(&wil->wmi_call);
|
||||
init_completion(&wil->halp.comp);
|
||||
|
||||
wil->bcast_vring = -1;
|
||||
setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
|
||||
|
@ -555,11 +593,10 @@ static inline void wil_release_cpu(struct wil6210_priv *wil)
|
|||
static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable)
|
||||
{
|
||||
wil_info(wil, "%s: enable=%d\n", __func__, enable);
|
||||
if (enable) {
|
||||
if (enable)
|
||||
wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
|
||||
} else {
|
||||
else
|
||||
wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
static int wil_target_reset(struct wil6210_priv *wil)
|
||||
|
@ -804,6 +841,9 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
wil_bcast_fini(wil);
|
||||
|
||||
/* Disable device led before reset*/
|
||||
wmi_led_cfg(wil, false);
|
||||
|
||||
/* prevent NAPI from being scheduled and prevent wmi commands */
|
||||
mutex_lock(&wil->wmi_mutex);
|
||||
bitmap_zero(wil->status, wil_status_last);
|
||||
|
@ -871,6 +911,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
wil->ap_isolate = 0;
|
||||
reinit_completion(&wil->wmi_ready);
|
||||
reinit_completion(&wil->wmi_call);
|
||||
reinit_completion(&wil->halp.comp);
|
||||
|
||||
if (load_fw) {
|
||||
wil_configure_interrupt_moderation(wil);
|
||||
|
@ -1061,3 +1102,51 @@ int wil_find_cid(struct wil6210_priv *wil, const u8 *mac)
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void wil_halp_vote(struct wil6210_priv *wil)
|
||||
{
|
||||
unsigned long rc;
|
||||
unsigned long to_jiffies = msecs_to_jiffies(WAIT_FOR_HALP_VOTE_MS);
|
||||
|
||||
mutex_lock(&wil->halp.lock);
|
||||
|
||||
wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__,
|
||||
wil->halp.ref_cnt);
|
||||
|
||||
if (++wil->halp.ref_cnt == 1) {
|
||||
wil6210_set_halp(wil);
|
||||
rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
|
||||
if (!rc)
|
||||
wil_err(wil, "%s: HALP vote timed out\n", __func__);
|
||||
else
|
||||
wil_dbg_misc(wil,
|
||||
"%s: HALP vote completed after %d ms\n",
|
||||
__func__,
|
||||
jiffies_to_msecs(to_jiffies - rc));
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__,
|
||||
wil->halp.ref_cnt);
|
||||
|
||||
mutex_unlock(&wil->halp.lock);
|
||||
}
|
||||
|
||||
void wil_halp_unvote(struct wil6210_priv *wil)
|
||||
{
|
||||
WARN_ON(wil->halp.ref_cnt == 0);
|
||||
|
||||
mutex_lock(&wil->halp.lock);
|
||||
|
||||
wil_dbg_misc(wil, "%s: start, HALP ref_cnt (%d)\n", __func__,
|
||||
wil->halp.ref_cnt);
|
||||
|
||||
if (--wil->halp.ref_cnt == 0) {
|
||||
wil6210_clear_halp(wil);
|
||||
wil_dbg_misc(wil, "%s: HALP unvote\n", __func__);
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "%s: end, HALP ref_cnt (%d)\n", __func__,
|
||||
wil->halp.ref_cnt);
|
||||
|
||||
mutex_unlock(&wil->halp.lock);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
#define P2P_SEARCH_DURATION_MS 500
|
||||
#define P2P_DEFAULT_BI 100
|
||||
|
||||
bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request)
|
||||
{
|
||||
return (request->n_channels == 1) &&
|
||||
(request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL);
|
||||
}
|
||||
|
||||
void wil_p2p_discovery_timer_fn(ulong x)
|
||||
{
|
||||
struct wil6210_priv *wil = (void *)x;
|
||||
|
|
|
@ -1759,7 +1759,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_ratelimited(wil, "FW not connected\n");
|
||||
wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n");
|
||||
goto drop;
|
||||
}
|
||||
if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) {
|
||||
|
|
|
@ -168,6 +168,7 @@ struct RGF_ICR {
|
|||
#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */
|
||||
#define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0)
|
||||
#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1)
|
||||
#define BIT_DMA_EP_MISC_ICR_HALP BIT(27)
|
||||
#define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */
|
||||
|
||||
/* Legacy interrupt moderation control (before Sparrow v2)*/
|
||||
|
@ -534,6 +535,41 @@ struct pmc_ctx {
|
|||
int descriptor_size;
|
||||
};
|
||||
|
||||
struct wil_halp {
|
||||
struct mutex lock; /* protect halp ref_cnt */
|
||||
unsigned int ref_cnt;
|
||||
struct completion comp;
|
||||
};
|
||||
|
||||
struct wil_blob_wrapper {
|
||||
struct wil6210_priv *wil;
|
||||
struct debugfs_blob_wrapper blob;
|
||||
};
|
||||
|
||||
#define WIL_LED_MAX_ID (2)
|
||||
#define WIL_LED_INVALID_ID (0xF)
|
||||
#define WIL_LED_BLINK_ON_SLOW_MS (300)
|
||||
#define WIL_LED_BLINK_OFF_SLOW_MS (300)
|
||||
#define WIL_LED_BLINK_ON_MED_MS (200)
|
||||
#define WIL_LED_BLINK_OFF_MED_MS (200)
|
||||
#define WIL_LED_BLINK_ON_FAST_MS (100)
|
||||
#define WIL_LED_BLINK_OFF_FAST_MS (100)
|
||||
enum {
|
||||
WIL_LED_TIME_SLOW = 0,
|
||||
WIL_LED_TIME_MED,
|
||||
WIL_LED_TIME_FAST,
|
||||
WIL_LED_TIME_LAST,
|
||||
};
|
||||
|
||||
struct blink_on_off_time {
|
||||
u32 on_ms;
|
||||
u32 off_ms;
|
||||
};
|
||||
|
||||
extern struct blink_on_off_time led_blink_time[WIL_LED_TIME_LAST];
|
||||
extern u8 led_id;
|
||||
extern u8 led_polarity;
|
||||
|
||||
struct wil6210_priv {
|
||||
struct pci_dev *pdev;
|
||||
struct wireless_dev *wdev;
|
||||
|
@ -606,7 +642,7 @@ struct wil6210_priv {
|
|||
atomic_t isr_count_rx, isr_count_tx;
|
||||
/* debugfs */
|
||||
struct dentry *debug;
|
||||
struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
|
||||
struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
|
||||
u8 discovery_mode;
|
||||
|
||||
void *platform_handle;
|
||||
|
@ -622,6 +658,10 @@ struct wil6210_priv {
|
|||
struct wireless_dev *p2p_wdev;
|
||||
struct mutex p2p_wdev_mutex; /* protect @p2p_wdev */
|
||||
struct wireless_dev *radio_wdev;
|
||||
|
||||
/* High Access Latency Policy voting */
|
||||
struct wil_halp halp;
|
||||
|
||||
};
|
||||
|
||||
#define wil_to_wiphy(i) (i->wdev->wiphy)
|
||||
|
@ -635,11 +675,13 @@ struct wil6210_priv {
|
|||
__printf(2, 3)
|
||||
void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void wil_err(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
void __wil_err(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
void __wil_info(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...);
|
||||
#define wil_dbg(wil, fmt, arg...) do { \
|
||||
netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
|
||||
wil_dbg_trace(wil, fmt, ##arg); \
|
||||
|
@ -650,6 +692,10 @@ void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
|
|||
#define wil_dbg_wmi(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
|
||||
#define wil_dbg_misc(wil, fmt, arg...) wil_dbg(wil, "DBG[MISC]" fmt, ##arg)
|
||||
#define wil_dbg_pm(wil, fmt, arg...) wil_dbg(wil, "DBG[ PM ]" fmt, ##arg)
|
||||
#define wil_err(wil, fmt, arg...) __wil_err(wil, "%s: " fmt, __func__, ##arg)
|
||||
#define wil_info(wil, fmt, arg...) __wil_info(wil, "%s: " fmt, __func__, ##arg)
|
||||
#define wil_err_ratelimited(wil, fmt, arg...) \
|
||||
__wil_err_ratelimited(wil, "%s: " fmt, __func__, ##arg)
|
||||
|
||||
/* target operations */
|
||||
/* register read */
|
||||
|
@ -707,6 +753,12 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
|
|||
size_t count);
|
||||
void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
|
||||
size_t count);
|
||||
void wil_memcpy_fromio_halp_vote(struct wil6210_priv *wil, void *dst,
|
||||
const volatile void __iomem *src,
|
||||
size_t count);
|
||||
void wil_memcpy_toio_halp_vote(struct wil6210_priv *wil,
|
||||
volatile void __iomem *dst,
|
||||
const void *src, size_t count);
|
||||
|
||||
void *wil_if_alloc(struct device *dev);
|
||||
void wil_if_free(struct wil6210_priv *wil);
|
||||
|
@ -772,6 +824,7 @@ void wil_disable_irq(struct wil6210_priv *wil);
|
|||
void wil_enable_irq(struct wil6210_priv *wil);
|
||||
|
||||
/* P2P */
|
||||
bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request);
|
||||
void wil_p2p_discovery_timer_fn(ulong x);
|
||||
int wil_p2p_search(struct wil6210_priv *wil,
|
||||
struct cfg80211_scan_request *request);
|
||||
|
@ -805,6 +858,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
|
|||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
|
||||
u8 chan, u8 hidden_ssid, u8 is_go);
|
||||
int wmi_pcp_stop(struct wil6210_priv *wil);
|
||||
int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
|
||||
u16 reason_code, bool from_event);
|
||||
void wil_probe_client_flush(struct wil6210_priv *wil);
|
||||
|
@ -842,4 +896,9 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime);
|
|||
int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
|
||||
void wil_fw_core_dump(struct wil6210_priv *wil);
|
||||
|
||||
void wil_halp_vote(struct wil6210_priv *wil);
|
||||
void wil_halp_unvote(struct wil6210_priv *wil);
|
||||
void wil6210_set_halp(struct wil6210_priv *wil);
|
||||
void wil6210_clear_halp(struct wil6210_priv *wil);
|
||||
|
||||
#endif /* __WIL6210_H__ */
|
||||
|
|
|
@ -32,6 +32,11 @@ module_param(agg_wsize, int, S_IRUGO | S_IWUSR);
|
|||
MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
|
||||
" 0 - use default; < 0 - don't auto-establish");
|
||||
|
||||
u8 led_id = WIL_LED_INVALID_ID;
|
||||
module_param(led_id, byte, S_IRUGO);
|
||||
MODULE_PARM_DESC(led_id,
|
||||
" 60G device led enablement. Set the led ID (0-2) to enable");
|
||||
|
||||
/**
|
||||
* WMI event receiving - theory of operations
|
||||
*
|
||||
|
@ -94,6 +99,14 @@ const struct fw_map fw_mapping[] = {
|
|||
*/
|
||||
};
|
||||
|
||||
struct blink_on_off_time led_blink_time[] = {
|
||||
{WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
|
||||
{WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
|
||||
{WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
|
||||
};
|
||||
|
||||
u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
|
||||
|
||||
/**
|
||||
* return AHB address for given firmware/ucode internal (linker) address
|
||||
* @x - internal address
|
||||
|
@ -194,6 +207,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
void __iomem *dst;
|
||||
void __iomem *head = wmi_addr(wil, r->head);
|
||||
uint retry;
|
||||
int rc = 0;
|
||||
|
||||
if (sizeof(cmd) + len > r->entry_size) {
|
||||
wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
|
||||
|
@ -212,6 +226,9 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_halp_vote(wil);
|
||||
|
||||
/* read Tx head till it is not busy */
|
||||
for (retry = 5; retry > 0; retry--) {
|
||||
wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
|
||||
|
@ -221,7 +238,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
}
|
||||
if (d_head.sync != 0) {
|
||||
wil_err(wil, "WMI head busy\n");
|
||||
return -EBUSY;
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
/* next head */
|
||||
next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
|
||||
|
@ -230,7 +248,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
for (retry = 5; retry > 0; retry--) {
|
||||
if (!test_bit(wil_status_fwready, wil->status)) {
|
||||
wil_err(wil, "WMI: cannot send command while FW not ready\n");
|
||||
return -EAGAIN;
|
||||
rc = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
r->tail = wil_r(wil, RGF_MBOX +
|
||||
offsetof(struct wil6210_mbox_ctl, tx.tail));
|
||||
|
@ -240,13 +259,15 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
}
|
||||
if (next_head == r->tail) {
|
||||
wil_err(wil, "WMI ring full\n");
|
||||
return -EBUSY;
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
dst = wmi_buffer(wil, d_head.addr);
|
||||
if (!dst) {
|
||||
wil_err(wil, "invalid WMI buffer: 0x%08x\n",
|
||||
le32_to_cpu(d_head.addr));
|
||||
return -EINVAL;
|
||||
rc = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
|
||||
/* set command */
|
||||
|
@ -269,7 +290,9 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
|||
wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
|
||||
SW_INT_MBOX);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
wil_halp_unvote(wil);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
|
||||
|
@ -961,6 +984,60 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
|
|||
return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct wmi_led_cfg_cmd cmd = {
|
||||
.led_mode = enable,
|
||||
.id = led_id,
|
||||
.slow_blink_cfg.blink_on =
|
||||
cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
|
||||
.slow_blink_cfg.blink_off =
|
||||
cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
|
||||
.medium_blink_cfg.blink_on =
|
||||
cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
|
||||
.medium_blink_cfg.blink_off =
|
||||
cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
|
||||
.fast_blink_cfg.blink_on =
|
||||
cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
|
||||
.fast_blink_cfg.blink_off =
|
||||
cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
|
||||
.led_polarity = led_polarity,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_led_cfg_done_event evt;
|
||||
} __packed reply;
|
||||
|
||||
if (led_id == WIL_LED_INVALID_ID)
|
||||
goto out;
|
||||
|
||||
if (led_id > WIL_LED_MAX_ID) {
|
||||
wil_err(wil, "Invalid led id %d\n", led_id);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wil_dbg_wmi(wil,
|
||||
"%s led %d\n",
|
||||
enable ? "enabling" : "disabling", led_id);
|
||||
|
||||
rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
|
||||
WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
|
||||
100);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
if (reply.evt.status) {
|
||||
wil_err(wil, "led %d cfg failed with status %d\n",
|
||||
led_id, le32_to_cpu(reply.evt.status));
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
|
||||
u8 chan, u8 hidden_ssid, u8 is_go)
|
||||
{
|
||||
|
@ -1003,11 +1080,21 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
|
|||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
|
||||
rc = -EINVAL;
|
||||
|
||||
if (wmi_nettype != WMI_NETTYPE_P2P)
|
||||
/* Don't fail due to error in the led configuration */
|
||||
wmi_led_cfg(wil, true);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wmi_pcp_stop(struct wil6210_priv *wil)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = wmi_led_cfg(wil, false);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
|
||||
WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ enum wmi_command_id {
|
|||
WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855,
|
||||
WMI_OTP_READ_CMDID = 0x856,
|
||||
WMI_OTP_WRITE_CMDID = 0x857,
|
||||
WMI_LED_CFG_CMDID = 0x858,
|
||||
/* Performance monitoring commands */
|
||||
WMI_BF_CTRL_CMDID = 0x862,
|
||||
WMI_NOTIFY_REQ_CMDID = 0x863,
|
||||
|
@ -868,6 +869,7 @@ enum wmi_event_id {
|
|||
WMI_RX_MGMT_PACKET_EVENTID = 0x1840,
|
||||
WMI_TX_MGMT_PACKET_EVENTID = 0x1841,
|
||||
WMI_OTP_READ_RESULT_EVENTID = 0x1856,
|
||||
WMI_LED_CFG_DONE_EVENTID = 0x1858,
|
||||
/* Performance monitoring events */
|
||||
WMI_DATA_PORT_OPEN_EVENTID = 0x1860,
|
||||
WMI_WBE_LINK_DOWN_EVENTID = 0x1861,
|
||||
|
@ -1349,4 +1351,63 @@ enum wmi_hidden_ssid {
|
|||
WMI_HIDDEN_SSID_CLEAR = 0xFE,
|
||||
};
|
||||
|
||||
/* WMI_LED_CFG_CMDID
|
||||
*
|
||||
* Configure LED On\Off\Blinking operation
|
||||
*
|
||||
* Returned events:
|
||||
* - WMI_LED_CFG_DONE_EVENTID
|
||||
*/
|
||||
enum led_mode {
|
||||
LED_DISABLE = 0x00,
|
||||
LED_ENABLE = 0x01,
|
||||
};
|
||||
|
||||
/* The names of the led as
|
||||
* described on HW schemes.
|
||||
*/
|
||||
enum wmi_led_id {
|
||||
WMI_LED_WLAN = 0x00,
|
||||
WMI_LED_WPAN = 0x01,
|
||||
WMI_LED_WWAN = 0x02,
|
||||
};
|
||||
|
||||
/* Led polarity mode. */
|
||||
enum wmi_led_polarity {
|
||||
LED_POLARITY_HIGH_ACTIVE = 0x00,
|
||||
LED_POLARITY_LOW_ACTIVE = 0x01,
|
||||
};
|
||||
|
||||
/* Combination of on and off
|
||||
* creates the blinking period
|
||||
*/
|
||||
struct wmi_led_blink_mode {
|
||||
__le32 blink_on;
|
||||
__le32 blink_off;
|
||||
} __packed;
|
||||
|
||||
/* WMI_LED_CFG_CMDID */
|
||||
struct wmi_led_cfg_cmd {
|
||||
/* enum led_mode_e */
|
||||
u8 led_mode;
|
||||
/* enum wmi_led_id_e */
|
||||
u8 id;
|
||||
/* slow speed blinking combination */
|
||||
struct wmi_led_blink_mode slow_blink_cfg;
|
||||
/* medium speed blinking combination */
|
||||
struct wmi_led_blink_mode medium_blink_cfg;
|
||||
/* high speed blinking combination */
|
||||
struct wmi_led_blink_mode fast_blink_cfg;
|
||||
/* polarity of the led */
|
||||
u8 led_polarity;
|
||||
/* reserved */
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
/* WMI_LED_CFG_DONE_EVENTID */
|
||||
struct wmi_led_cfg_done_event {
|
||||
/* led config status */
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
#endif /* __WILOCITY_WMI_H__ */
|
||||
|
|
Loading…
Reference in New Issue