mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-03 20:35:57 -05:00
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v6.2. Major changes: ath11k * support configuring channel dwell time during scan
This commit is contained in:
@@ -241,6 +241,11 @@ static void ar5523_cmd_tx_cb(struct urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
static void ar5523_cancel_tx_cmd(struct ar5523 *ar)
|
||||
{
|
||||
usb_kill_urb(ar->tx_cmd.urb_tx);
|
||||
}
|
||||
|
||||
static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
|
||||
int ilen, void *odata, int olen, int flags)
|
||||
{
|
||||
@@ -280,6 +285,7 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
|
||||
}
|
||||
|
||||
if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) {
|
||||
ar5523_cancel_tx_cmd(ar);
|
||||
cmd->odata = NULL;
|
||||
ar5523_err(ar, "timeout waiting for command %02x reply\n",
|
||||
code);
|
||||
|
||||
@@ -99,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA988X_HW_2_0_VERSION,
|
||||
@@ -138,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9887_HW_1_0_VERSION,
|
||||
@@ -178,6 +180,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
@@ -213,6 +216,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = true,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
@@ -252,6 +256,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
@@ -291,6 +296,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_0_VERSION,
|
||||
@@ -330,6 +336,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
@@ -373,6 +380,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = true,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
@@ -418,6 +426,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9984_HW_1_0_DEV_VERSION,
|
||||
@@ -470,6 +479,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
@@ -519,6 +529,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
@@ -558,6 +569,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
@@ -599,6 +611,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
@@ -631,6 +644,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = QCA4019_HW_1_0_DEV_VERSION,
|
||||
@@ -677,6 +691,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
.delay_unmap_buffer = false,
|
||||
},
|
||||
{
|
||||
.id = WCN3990_HW_1_0_DEV_VERSION,
|
||||
@@ -709,6 +724,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.dynamic_sar_support = true,
|
||||
.hw_restart_disconnect = true,
|
||||
.use_fw_tx_credits = false,
|
||||
.delay_unmap_buffer = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -56,6 +56,15 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
|
||||
ep->eid, skb);
|
||||
|
||||
/* A corner case where the copy completion is reaching to host but still
|
||||
* copy engine is processing it due to which host unmaps corresponding
|
||||
* memory and causes SMMU fault, hence as workaround adding delay
|
||||
* the unmapping memory to avoid SMMU faults.
|
||||
*/
|
||||
if (ar->hw_params.delay_unmap_buffer &&
|
||||
ep->ul_pipe_id == 3)
|
||||
mdelay(2);
|
||||
|
||||
hdr = (struct ath10k_htc_hdr *)skb->data;
|
||||
ath10k_htc_restore_tx_skb(ep->htc, skb);
|
||||
|
||||
|
||||
@@ -1108,8 +1108,10 @@ struct htt_rx_in_ord_ind {
|
||||
u8 reserved;
|
||||
__le16 msdu_count;
|
||||
union {
|
||||
struct htt_rx_in_ord_msdu_desc msdu_descs32[0];
|
||||
struct htt_rx_in_ord_msdu_desc_ext msdu_descs64[0];
|
||||
DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc,
|
||||
msdu_descs32);
|
||||
DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc_ext,
|
||||
msdu_descs64);
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
|
||||
@@ -637,6 +637,8 @@ struct ath10k_hw_params {
|
||||
bool hw_restart_disconnect;
|
||||
|
||||
bool use_fw_tx_credits;
|
||||
|
||||
bool delay_unmap_buffer;
|
||||
};
|
||||
|
||||
struct htt_resp;
|
||||
|
||||
@@ -584,7 +584,14 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_warn(ar, "did not find station from tdls peer event");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
|
||||
if (!arvif) {
|
||||
ath10k_warn(ar, "no vif for vdev_id %d found",
|
||||
__le32_to_cpu(ev->vdev_id));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ieee80211_tdls_oper_request(
|
||||
arvif->vif, station->addr,
|
||||
NL80211_TDLS_TEARDOWN,
|
||||
|
||||
@@ -1641,7 +1641,7 @@ static void ath11k_update_11d(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
|
||||
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
@@ -1677,6 +1677,10 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
|
||||
ath11k_mac_tx_mgmt_pending_free, ar);
|
||||
idr_destroy(&ar->txmgmt_idr);
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
|
||||
ar->monitor_vdev_id = -1;
|
||||
clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
|
||||
clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
|
||||
}
|
||||
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
@@ -1730,9 +1734,6 @@ static void ath11k_core_restart(struct work_struct *work)
|
||||
struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
|
||||
int ret;
|
||||
|
||||
if (!ab->is_reset)
|
||||
ath11k_core_pre_reconfigure_recovery(ab);
|
||||
|
||||
ret = ath11k_core_reconfigure_on_crash(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
|
||||
|
||||
@@ -505,6 +505,8 @@ struct ath11k_sta {
|
||||
u64 ps_start_jiffies;
|
||||
u64 ps_total_duration;
|
||||
bool peer_current_ps_valid;
|
||||
|
||||
u32 bw_prev;
|
||||
};
|
||||
|
||||
#define ATH11K_MIN_5G_FREQ 4150
|
||||
@@ -1157,6 +1159,7 @@ int ath11k_core_check_smbios(struct ath11k_base *ab);
|
||||
void ath11k_core_halt(struct ath11k *ar);
|
||||
int ath11k_core_resume(struct ath11k_base *ab);
|
||||
int ath11k_core_suspend(struct ath11k_base *ab);
|
||||
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
|
||||
|
||||
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
|
||||
const char *filename);
|
||||
|
||||
@@ -241,7 +241,10 @@ const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default = {
|
||||
#define ath11k_a_rates (ath11k_legacy_rates + 4)
|
||||
#define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4)
|
||||
|
||||
#define ATH11K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */
|
||||
#define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD 200 /* in msecs */
|
||||
|
||||
/* Overhead due to the processing of channel switch events from FW */
|
||||
#define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* in msecs */
|
||||
|
||||
static const u32 ath11k_smps_map[] = {
|
||||
[WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC,
|
||||
@@ -3612,6 +3615,7 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
||||
struct scan_req_params arg;
|
||||
int ret = 0;
|
||||
int i;
|
||||
u32 scan_timeout;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
@@ -3681,6 +3685,26 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
||||
ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);
|
||||
}
|
||||
|
||||
/* if duration is set, default dwell times will be overwritten */
|
||||
if (req->duration) {
|
||||
arg.dwell_time_active = req->duration;
|
||||
arg.dwell_time_active_2g = req->duration;
|
||||
arg.dwell_time_active_6g = req->duration;
|
||||
arg.dwell_time_passive = req->duration;
|
||||
arg.dwell_time_passive_6g = req->duration;
|
||||
arg.burst_duration = req->duration;
|
||||
|
||||
scan_timeout = min_t(u32, arg.max_rest_time *
|
||||
(arg.num_chan - 1) + (req->duration +
|
||||
ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
|
||||
arg.num_chan, arg.max_scan_time);
|
||||
} else {
|
||||
scan_timeout = arg.max_scan_time;
|
||||
}
|
||||
|
||||
/* Add a margin to account for event/command processing */
|
||||
scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD;
|
||||
|
||||
ret = ath11k_start_scan(ar, &arg);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
|
||||
@@ -3689,10 +3713,8 @@ static int ath11k_mac_op_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 +
|
||||
ATH11K_MAC_SCAN_TIMEOUT_MSECS));
|
||||
msecs_to_jiffies(scan_timeout));
|
||||
|
||||
exit:
|
||||
kfree(arg.chan_list);
|
||||
@@ -4215,10 +4237,11 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
const u8 *ht_mcs_mask;
|
||||
const u16 *vht_mcs_mask;
|
||||
const u16 *he_mcs_mask;
|
||||
u32 changed, bw, nss, smps;
|
||||
u32 changed, bw, nss, smps, bw_prev;
|
||||
int err, num_vht_rates, num_he_rates;
|
||||
const struct cfg80211_bitrate_mask *mask;
|
||||
struct peer_assoc_params peer_arg;
|
||||
enum wmi_phy_mode peer_phymode;
|
||||
|
||||
arsta = container_of(wk, struct ath11k_sta, update_wk);
|
||||
sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
|
||||
@@ -4239,6 +4262,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
arsta->changed = 0;
|
||||
|
||||
bw = arsta->bw;
|
||||
bw_prev = arsta->bw_prev;
|
||||
nss = arsta->nss;
|
||||
smps = arsta->smps;
|
||||
|
||||
@@ -4252,26 +4276,57 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
ath11k_mac_max_he_nss(he_mcs_mask)));
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||
/* Send peer assoc command before set peer bandwidth param to
|
||||
* avoid the mismatch between the peer phymode and the peer
|
||||
* bandwidth.
|
||||
*/
|
||||
ath11k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true);
|
||||
/* Get the peer phymode */
|
||||
ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
|
||||
peer_phymode = peer_arg.peer_phymode;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n",
|
||||
sta->addr, bw, peer_phymode);
|
||||
|
||||
if (bw > bw_prev) {
|
||||
/* BW is upgraded. In this case we send WMI_PEER_PHYMODE
|
||||
* followed by WMI_PEER_CHWIDTH
|
||||
*/
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n",
|
||||
sta->addr, bw, bw_prev);
|
||||
|
||||
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
|
||||
WMI_PEER_PHYMODE, peer_phymode);
|
||||
|
||||
if (err) {
|
||||
ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
|
||||
sta->addr, peer_phymode, err);
|
||||
goto err_rc_bw_changed;
|
||||
}
|
||||
|
||||
peer_arg.is_assoc = false;
|
||||
err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
|
||||
if (err) {
|
||||
ath11k_warn(ar->ab, "failed to send peer assoc for STA %pM vdev %i: %d\n",
|
||||
sta->addr, arvif->vdev_id, err);
|
||||
} else if (wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
|
||||
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
|
||||
WMI_PEER_CHWIDTH, bw);
|
||||
|
||||
if (err)
|
||||
ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
|
||||
sta->addr, bw, err);
|
||||
} else {
|
||||
ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
/* BW is downgraded. In this case we send WMI_PEER_CHWIDTH
|
||||
* followed by WMI_PEER_PHYMODE
|
||||
*/
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n",
|
||||
sta->addr, bw, bw_prev);
|
||||
|
||||
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
|
||||
WMI_PEER_CHWIDTH, bw);
|
||||
|
||||
if (err) {
|
||||
ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",
|
||||
sta->addr, bw, err);
|
||||
goto err_rc_bw_changed;
|
||||
}
|
||||
|
||||
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
|
||||
WMI_PEER_PHYMODE, peer_phymode);
|
||||
|
||||
if (err)
|
||||
ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n",
|
||||
sta->addr, peer_phymode, err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4352,6 +4407,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
|
||||
}
|
||||
}
|
||||
|
||||
err_rc_bw_changed:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
@@ -4505,6 +4561,34 @@ static int ath11k_mac_station_add(struct ath11k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
u32 bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
|
||||
switch (sta->deflink.bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
bw = WMI_PEER_CHWIDTH_40MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
bw = WMI_PEER_CHWIDTH_80MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
bw = WMI_PEER_CHWIDTH_160MHZ;
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n",
|
||||
sta->deflink.bandwidth, sta->addr);
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
}
|
||||
|
||||
return bw;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -4590,6 +4674,12 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
|
||||
sta->addr);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
/* Set arsta bw and prev bw */
|
||||
arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
|
||||
arsta->bw_prev = arsta->bw;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
@@ -4713,28 +4803,8 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
|
||||
switch (sta->deflink.bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
bw = WMI_PEER_CHWIDTH_40MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
bw = WMI_PEER_CHWIDTH_80MHZ;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
bw = WMI_PEER_CHWIDTH_160MHZ;
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
|
||||
sta->deflink.bandwidth, sta->addr);
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
break;
|
||||
}
|
||||
|
||||
bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta);
|
||||
arsta->bw_prev = arsta->bw;
|
||||
arsta->bw = bw;
|
||||
}
|
||||
|
||||
@@ -6163,6 +6233,40 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif)
|
||||
{
|
||||
unsigned long time_left;
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
reinit_completion(&ar->vdev_delete_done);
|
||||
|
||||
ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
|
||||
ATH11K_VDEV_DELETE_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id);
|
||||
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
ar->num_created_vdevs--;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
|
||||
vif->addr, arvif->vdev_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@@ -6373,18 +6477,16 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
ath11k_dp_vdev_tx_attach(ar, arvif);
|
||||
|
||||
ath11k_debugfs_add_interface(arvif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_MONITOR &&
|
||||
test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) {
|
||||
ret = ath11k_mac_monitor_vdev_create(ar);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d",
|
||||
ret);
|
||||
goto err_peer_del;
|
||||
}
|
||||
}
|
||||
|
||||
ath11k_debugfs_add_interface(arvif);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -6400,16 +6502,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
err_vdev_del:
|
||||
ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
ar->num_created_vdevs--;
|
||||
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
ab->free_vdev_map |= 1LL << arvif->vdev_id;
|
||||
ath11k_mac_vdev_delete(ar, arvif);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_del(&arvif->list);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
err:
|
||||
ath11k_debugfs_remove_interface(arvif);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
@@ -6432,7 +6530,6 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
unsigned long time_left;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@@ -6453,29 +6550,13 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
|
||||
arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
reinit_completion(&ar->vdev_delete_done);
|
||||
|
||||
ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
ret = ath11k_mac_vdev_delete(ar, arvif);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n",
|
||||
ath11k_warn(ab, "failed to delete vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
goto err_vdev_del;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->vdev_delete_done,
|
||||
ATH11K_VDEV_DELETE_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath11k_warn(ab, "Timeout in receiving vdev delete response\n");
|
||||
goto err_vdev_del;
|
||||
}
|
||||
|
||||
ab->free_vdev_map |= 1LL << (arvif->vdev_id);
|
||||
ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
ar->num_created_vdevs--;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n",
|
||||
vif->addr, arvif->vdev_id);
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
|
||||
clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
|
||||
ar->monitor_vdev_id = -1;
|
||||
@@ -9015,6 +9096,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
|
||||
}
|
||||
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
|
||||
ath11k_reg_init(ar);
|
||||
|
||||
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
||||
|
||||
@@ -218,9 +218,16 @@ int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end)
|
||||
if (wakeup_required && ab->pci.ops->wakeup) {
|
||||
ret = ab->pci.ops->wakeup(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n",
|
||||
start, ret);
|
||||
return ret;
|
||||
ath11k_warn(ab,
|
||||
"wakeup failed, data may be invalid: %d",
|
||||
ret);
|
||||
/* Even though wakeup() failed, continue processing rather
|
||||
* than returning because some parts of the data may still
|
||||
* be valid and useful in some cases, e.g. could give us
|
||||
* some clues on firmware crash.
|
||||
* Mislead due to invalid data could be avoided because we
|
||||
* are aware of the wakeup failure.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
|
||||
#define HOST_CSTATE_BIT 0x04
|
||||
#define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08
|
||||
#define PLATFORM_CAP_PCIE_PME_D3COLD 0x10
|
||||
|
||||
#define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING="
|
||||
|
||||
@@ -1752,6 +1753,8 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
|
||||
if (ab->hw_params.global_reset)
|
||||
req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET;
|
||||
|
||||
req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n");
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
@@ -1961,7 +1964,7 @@ static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)
|
||||
continue;
|
||||
|
||||
dma_free_coherent(ab->dev,
|
||||
ab->qmi.target_mem[i].size,
|
||||
ab->qmi.target_mem[i].prev_size,
|
||||
ab->qmi.target_mem[i].vaddr,
|
||||
ab->qmi.target_mem[i].paddr);
|
||||
ab->qmi.target_mem[i].vaddr = NULL;
|
||||
@@ -1982,12 +1985,12 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
||||
* in such case, no need to allocate memory for FW again.
|
||||
*/
|
||||
if (chunk->vaddr) {
|
||||
if (chunk->prev_type == chunk->type ||
|
||||
if (chunk->prev_type == chunk->type &&
|
||||
chunk->prev_size == chunk->size)
|
||||
continue;
|
||||
|
||||
/* cannot reuse the existing chunk */
|
||||
dma_free_coherent(ab->dev, chunk->size,
|
||||
dma_free_coherent(ab->dev, chunk->prev_size,
|
||||
chunk->vaddr, chunk->paddr);
|
||||
chunk->vaddr = NULL;
|
||||
}
|
||||
@@ -3158,6 +3161,9 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
||||
case ATH11K_QMI_EVENT_SERVER_EXIT:
|
||||
set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
||||
set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
||||
|
||||
if (!ab->is_reset)
|
||||
ath11k_core_pre_reconfigure_recovery(ab);
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_REQUEST_MEM:
|
||||
ret = ath11k_qmi_event_mem_request(qmi);
|
||||
|
||||
@@ -287,11 +287,7 @@ int ath11k_regd_update(struct ath11k *ar)
|
||||
goto err;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
wiphy_lock(ar->hw->wiphy);
|
||||
ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy);
|
||||
wiphy_unlock(ar->hw->wiphy);
|
||||
rtnl_unlock();
|
||||
ret = regulatory_set_wiphy_regd(ar->hw->wiphy, regd_copy);
|
||||
|
||||
kfree(regd_copy);
|
||||
|
||||
|
||||
@@ -6829,7 +6829,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
|
||||
"peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
|
||||
ev->peer_macaddr.addr, ev->peer_ps_state,
|
||||
ev->ps_supported_bitmap, ev->peer_ps_valid,
|
||||
ev->peer_ps_timestamp);
|
||||
|
||||
@@ -45,11 +45,6 @@ ath9k_hw-y:= \
|
||||
ar9003_eeprom.o \
|
||||
ar9003_paprd.o
|
||||
|
||||
# FIXME: temporarily silence -Warray-bounds on non W=1+ builds
|
||||
ifndef KBUILD_EXTRA_WARN
|
||||
CFLAGS_mac.o += -Wno-array-bounds
|
||||
endif
|
||||
|
||||
ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o
|
||||
|
||||
ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
|
||||
|
||||
@@ -708,14 +708,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||
struct rx_buf *rx_buf = (struct rx_buf *)urb->context;
|
||||
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
|
||||
struct sk_buff *skb = rx_buf->skb;
|
||||
struct sk_buff *nskb;
|
||||
int ret;
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
if (!hif_dev)
|
||||
goto free;
|
||||
goto free_skb;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
@@ -724,7 +723,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||
case -ECONNRESET:
|
||||
case -ENODEV:
|
||||
case -ESHUTDOWN:
|
||||
goto free;
|
||||
goto free_skb;
|
||||
default:
|
||||
skb_reset_tail_pointer(skb);
|
||||
skb_trim(skb, 0);
|
||||
@@ -735,25 +734,27 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||
if (likely(urb->actual_length != 0)) {
|
||||
skb_put(skb, urb->actual_length);
|
||||
|
||||
/* Process the command first */
|
||||
/*
|
||||
* Process the command first.
|
||||
* skb is either freed here or passed to be
|
||||
* managed to another callback function.
|
||||
*/
|
||||
ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
|
||||
skb->len, USB_REG_IN_PIPE);
|
||||
|
||||
|
||||
nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
|
||||
if (!nskb) {
|
||||
skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: REG_IN memory allocation failure\n");
|
||||
urb->context = NULL;
|
||||
return;
|
||||
goto free_rx_buf;
|
||||
}
|
||||
|
||||
rx_buf->skb = nskb;
|
||||
rx_buf->skb = skb;
|
||||
|
||||
usb_fill_int_urb(urb, hif_dev->udev,
|
||||
usb_rcvintpipe(hif_dev->udev,
|
||||
USB_REG_IN_PIPE),
|
||||
nskb->data, MAX_REG_IN_BUF_SIZE,
|
||||
skb->data, MAX_REG_IN_BUF_SIZE,
|
||||
ath9k_hif_usb_reg_in_cb, rx_buf, 1);
|
||||
}
|
||||
|
||||
@@ -762,12 +763,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (ret) {
|
||||
usb_unanchor_urb(urb);
|
||||
goto free;
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
return;
|
||||
free:
|
||||
free_skb:
|
||||
kfree_skb(skb);
|
||||
free_rx_buf:
|
||||
kfree(rx_buf);
|
||||
urb->context = NULL;
|
||||
}
|
||||
@@ -780,14 +782,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
|
||||
&hif_dev->tx.tx_buf, list) {
|
||||
usb_get_urb(tx_buf->urb);
|
||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||
usb_kill_urb(tx_buf->urb);
|
||||
list_del(&tx_buf->list);
|
||||
usb_free_urb(tx_buf->urb);
|
||||
kfree(tx_buf->buf);
|
||||
kfree(tx_buf);
|
||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||
|
||||
@@ -1329,10 +1327,24 @@ static int send_eject_command(struct usb_interface *interface)
|
||||
static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out;
|
||||
struct usb_device *udev = interface_to_usbdev(interface);
|
||||
struct usb_host_interface *alt;
|
||||
struct hif_device_usb *hif_dev;
|
||||
int ret = 0;
|
||||
|
||||
/* Verify the expected endpoints are present */
|
||||
alt = interface->cur_altsetting;
|
||||
if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 ||
|
||||
usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE ||
|
||||
usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE ||
|
||||
usb_endpoint_num(int_in) != USB_REG_IN_PIPE ||
|
||||
usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) {
|
||||
dev_err(&udev->dev,
|
||||
"ath9k_htc: Device endpoint numbers are not the expected ones\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (id->driver_info == STORAGE_DEVICE)
|
||||
return send_eject_command(interface);
|
||||
|
||||
|
||||
@@ -266,7 +266,9 @@ static void ath_mci_set_concur_txprio(struct ath_softc *sc)
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_NONE] =
|
||||
ATH_MCI_INQUIRY_PRIO;
|
||||
} else {
|
||||
u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */
|
||||
static const u8 prof_prio[] = {
|
||||
50, 90, 94, 52
|
||||
}; /* RFCOMM, A2DP, HID, PAN */
|
||||
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_LOW] =
|
||||
stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff;
|
||||
@@ -644,7 +646,9 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
|
||||
static const u32 channelmap[] = {
|
||||
0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff
|
||||
};
|
||||
int i;
|
||||
s16 chan_start, chan_end;
|
||||
u16 wlan_chan;
|
||||
|
||||
@@ -3,8 +3,3 @@ carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o
|
||||
carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o
|
||||
|
||||
obj-$(CONFIG_CARL9170) += carl9170.o
|
||||
|
||||
# FIXME: temporarily silence -Warray-bounds on non W=1+ builds
|
||||
ifndef KBUILD_EXTRA_WARN
|
||||
CFLAGS_cmd.o += -Wno-array-bounds
|
||||
endif
|
||||
|
||||
@@ -271,7 +271,7 @@ struct ar9170_tx_frame {
|
||||
|
||||
union {
|
||||
struct ieee80211_hdr i3e;
|
||||
u8 payload[0];
|
||||
DECLARE_FLEX_ARRAY(u8, payload);
|
||||
} data;
|
||||
} __packed;
|
||||
|
||||
|
||||
@@ -2154,7 +2154,7 @@ static const struct file_operations fops_led_blink_time = {
|
||||
};
|
||||
|
||||
/*---------FW capabilities------------*/
|
||||
static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data)
|
||||
static int fw_capabilities_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
|
||||
@@ -2163,22 +2163,10 @@ static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_fw_capabilities_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_fw_capabilities_debugfs_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_fw_capabilities = {
|
||||
.open = wil_fw_capabilities_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(fw_capabilities);
|
||||
|
||||
/*---------FW version------------*/
|
||||
static int wil_fw_version_debugfs_show(struct seq_file *s, void *data)
|
||||
static int fw_version_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
|
||||
@@ -2189,19 +2177,7 @@ static int wil_fw_version_debugfs_show(struct seq_file *s, void *data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_fw_version_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_fw_version_debugfs_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_fw_version = {
|
||||
.open = wil_fw_version_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(fw_version);
|
||||
|
||||
/*---------suspend_stats---------*/
|
||||
static ssize_t wil_write_suspend_stats(struct file *file,
|
||||
@@ -2366,8 +2342,8 @@ static const struct {
|
||||
{"recovery", 0644, &fops_recovery},
|
||||
{"led_cfg", 0644, &fops_led_cfg},
|
||||
{"led_blink_time", 0644, &fops_led_blink_time},
|
||||
{"fw_capabilities", 0444, &fops_fw_capabilities},
|
||||
{"fw_version", 0444, &fops_fw_version},
|
||||
{"fw_capabilities", 0444, &fw_capabilities_fops},
|
||||
{"fw_version", 0444, &fw_version_fops},
|
||||
{"suspend_stats", 0644, &fops_suspend_stats},
|
||||
{"compressed_rx_status", 0644, &fops_compressed_rx_status},
|
||||
{"srings", 0444, &srings_fops},
|
||||
|
||||
Reference in New Issue
Block a user