mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 09:51:26 +00:00
This series is based on * 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef Add support for * qsdk kernel/v4.4 * qsdk ethernet subsystem * v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0) * ath11k-firmware * hostapd/iw/... Feature support * full boot, system detection * sysupgrade to nand * HE support via latest hostapd * driver support for usb, crypto, hwmon, cpufreq, ... Missing * NSS/HW flow offloading - FW blob is not redistributable Using the qsdk v4.4 is an intermediate solution while the vanilla is being tested. Vanilla kernel is almost on feature par. Work has already started to upstream the ethernet and switch drivers. Once complete the target will be fully upstream. Signed-off-by: John Crispin <john@phrozen.org>
292 lines
8.9 KiB
Diff
292 lines
8.9 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
|
@@ -688,6 +688,7 @@ static void ath11k_core_restart(struct w
|
|
complete(&ar->peer_assoc_done);
|
|
complete(&ar->install_key_done);
|
|
complete(&ar->vdev_setup_done);
|
|
+ complete(&ar->vdev_delete_done);
|
|
complete(&ar->bss_survey_done);
|
|
complete(&ar->thermal.wmi_sync);
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -430,9 +430,11 @@ struct ath11k_per_peer_tx_stats {
|
|
};
|
|
|
|
#define ATH11K_FLUSH_TIMEOUT (5 * HZ)
|
|
+#define ATH11K_VDEV_DELETE_TIMEOUT_HZ (5 * HZ)
|
|
|
|
-struct ath11k_vdev_stop_status {
|
|
+struct ath11k_vdev_stop_delete_status {
|
|
bool stop_in_progress;
|
|
+ bool delete_in_progress;
|
|
u32 vdev_id;
|
|
};
|
|
|
|
@@ -524,8 +526,9 @@ struct ath11k {
|
|
struct completion install_key_done;
|
|
|
|
int last_wmi_vdev_start_status;
|
|
- struct ath11k_vdev_stop_status vdev_stop_status;
|
|
+ struct ath11k_vdev_stop_delete_status vdev_stop_delete_status;
|
|
struct completion vdev_setup_done;
|
|
+ struct completion vdev_delete_done;
|
|
|
|
int num_peers;
|
|
int max_num_peers;
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -448,8 +448,8 @@ struct ath11k *ath11k_mac_get_ar_by_pdev
|
|
return NULL;
|
|
}
|
|
|
|
-struct ath11k *ath11k_mac_get_ar_vdev_stop_status(struct ath11k_base *ab,
|
|
- u32 vdev_id)
|
|
+struct ath11k *ath11k_mac_get_ar_vdev_stop_delete_status(struct ath11k_base *ab,
|
|
+ u32 vdev_id)
|
|
{
|
|
int i;
|
|
struct ath11k_pdev *pdev;
|
|
@@ -461,9 +461,15 @@ struct ath11k *ath11k_mac_get_ar_vdev_st
|
|
ar = pdev->ar;
|
|
|
|
spin_lock_bh(&ar->data_lock);
|
|
- if (ar->vdev_stop_status.stop_in_progress &&
|
|
- ar->vdev_stop_status.vdev_id == vdev_id) {
|
|
- ar->vdev_stop_status.stop_in_progress = false;
|
|
+ if (ar->vdev_stop_delete_status.stop_in_progress &&
|
|
+ ar->vdev_stop_delete_status.vdev_id == vdev_id) {
|
|
+ ar->vdev_stop_delete_status.stop_in_progress = false;
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+ return ar;
|
|
+ }
|
|
+ if (ar->vdev_stop_delete_status.delete_in_progress &&
|
|
+ ar->vdev_stop_delete_status.vdev_id == vdev_id) {
|
|
+ ar->vdev_stop_delete_status.delete_in_progress = false;
|
|
spin_unlock_bh(&ar->data_lock);
|
|
return ar;
|
|
}
|
|
@@ -4416,6 +4422,7 @@ static void ath11k_mac_op_remove_interfa
|
|
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;
|
|
|
|
@@ -4424,10 +4431,6 @@ static void ath11k_mac_op_remove_interfa
|
|
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
|
|
arvif->vdev_id);
|
|
|
|
- spin_lock_bh(&ar->data_lock);
|
|
- list_del(&arvif->list);
|
|
- spin_unlock_bh(&ar->data_lock);
|
|
-
|
|
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
|
ret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
|
|
if (ret)
|
|
@@ -4435,14 +4438,29 @@ static void ath11k_mac_op_remove_interfa
|
|
arvif->vdev_id, ret);
|
|
}
|
|
|
|
+ reinit_completion(&ar->vdev_delete_done);
|
|
+
|
|
ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n",
|
|
arvif->vdev_id, ret);
|
|
+ goto err_vdev_del;
|
|
+ }
|
|
|
|
- ar->num_created_vdevs--;
|
|
- ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
|
- ab->free_vdev_map |= 1LL << (arvif->vdev_id);
|
|
+ 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");
|
|
+ } else {
|
|
+ ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id);
|
|
+ ab->free_vdev_map |= 1LL << (arvif->vdev_id);
|
|
+ ar->num_created_vdevs--;
|
|
+ }
|
|
+
|
|
+err_vdev_del:
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+ list_del(&arvif->list);
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
|
ath11k_peer_cleanup(ar, arvif->vdev_id);
|
|
|
|
@@ -4640,6 +4658,7 @@ ath11k_mac_vdev_start_restart(struct ath
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
reinit_completion(&ar->vdev_setup_done);
|
|
+ reinit_completion(&ar->vdev_delete_done);
|
|
|
|
arg.vdev_id = arvif->vdev_id;
|
|
arg.dtim_period = arvif->dtim_period;
|
|
@@ -4740,11 +4759,12 @@ static int ath11k_mac_vdev_stop(struct a
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
reinit_completion(&ar->vdev_setup_done);
|
|
+ reinit_completion(&ar->vdev_delete_done);
|
|
|
|
spin_lock_bh(&ar->data_lock);
|
|
|
|
- ar->vdev_stop_status.stop_in_progress = true;
|
|
- ar->vdev_stop_status.vdev_id = arvif->vdev_id;
|
|
+ ar->vdev_stop_delete_status.stop_in_progress = true;
|
|
+ ar->vdev_stop_delete_status.vdev_id = arvif->vdev_id;
|
|
|
|
spin_unlock_bh(&ar->data_lock);
|
|
|
|
@@ -4775,7 +4795,7 @@ static int ath11k_mac_vdev_stop(struct a
|
|
return 0;
|
|
err:
|
|
spin_lock_bh(&ar->data_lock);
|
|
- ar->vdev_stop_status.stop_in_progress = false;
|
|
+ ar->vdev_stop_delete_status.stop_in_progress = false;
|
|
spin_unlock_bh(&ar->data_lock);
|
|
|
|
return ret;
|
|
@@ -6172,6 +6192,7 @@ int ath11k_mac_allocate(struct ath11k_ba
|
|
INIT_LIST_HEAD(&ar->ppdu_stats_info);
|
|
mutex_init(&ar->conf_mutex);
|
|
init_completion(&ar->vdev_setup_done);
|
|
+ init_completion(&ar->vdev_delete_done);
|
|
init_completion(&ar->peer_assoc_done);
|
|
init_completion(&ar->install_key_done);
|
|
init_completion(&ar->bss_survey_done);
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -123,6 +123,8 @@ static const struct wmi_tlv_policy wmi_t
|
|
= { .min_len = sizeof(struct wmi_stats_event) },
|
|
[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT]
|
|
= { .min_len = sizeof(struct wmi_pdev_ctl_failsafe_chk_event) },
|
|
+ [WMI_TAG_VDEV_DELETE_RESP_EVENT]
|
|
+ = { .min_len = sizeof(struct wmi_vdev_delete_resp_event) },
|
|
};
|
|
|
|
#define PRIMAP(_hw_mode_) \
|
|
@@ -4207,6 +4209,33 @@ static int ath11k_pull_peer_del_resp_ev(
|
|
return 0;
|
|
}
|
|
|
|
+static int ath11k_pull_vdev_del_resp_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
|
+ u32 *vdev_id)
|
|
+{
|
|
+ const void **tb;
|
|
+ const struct wmi_vdev_delete_resp_event *ev;
|
|
+ int ret;
|
|
+
|
|
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
|
+ if (IS_ERR(tb)) {
|
|
+ ret = PTR_ERR(tb);
|
|
+ ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ev = tb[WMI_TAG_VDEV_DELETE_RESP_EVENT];
|
|
+ if (!ev) {
|
|
+ ath11k_warn(ab, "failed to fetch vdev delete resp ev");
|
|
+ kfree(tb);
|
|
+ return -EPROTO;
|
|
+ }
|
|
+
|
|
+ *vdev_id = ev->vdev_id;
|
|
+
|
|
+ kfree(tb);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int ath11k_pull_bcn_tx_status_ev(struct ath11k_base *ab, void *evt_buf,
|
|
u32 len, u32 *vdev_id,
|
|
u32 *tx_status)
|
|
@@ -5551,6 +5580,32 @@ static void ath11k_peer_delete_resp_even
|
|
*/
|
|
}
|
|
|
|
+static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab, struct sk_buff *skb)
|
|
+{
|
|
+ struct ath11k *ar;
|
|
+ u32 vdev_id = 0;
|
|
+
|
|
+ if (ath11k_pull_vdev_del_resp_ev(ab, skb, &vdev_id) != 0) {
|
|
+ ath11k_warn(ab, "failed to extract vdev delete resp");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ rcu_read_lock();
|
|
+ ar = ath11k_mac_get_ar_vdev_stop_delete_status(ab, vdev_id);
|
|
+ if (!ar) {
|
|
+ ath11k_warn(ab, "invalid vdev id in vdev delete resp ev %d",
|
|
+ vdev_id);
|
|
+ rcu_read_unlock();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ complete(&ar->vdev_delete_done);
|
|
+
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "vdev delete resp for vdev id %d", vdev_id);
|
|
+}
|
|
+
|
|
static inline const char *ath11k_wmi_vdev_resp_print(u32 vdev_resp_status)
|
|
{
|
|
switch (vdev_resp_status) {
|
|
@@ -5627,7 +5682,7 @@ static void ath11k_vdev_stopped_event(st
|
|
}
|
|
|
|
rcu_read_lock();
|
|
- ar = ath11k_mac_get_ar_vdev_stop_status(ab, vdev_id);
|
|
+ ar = ath11k_mac_get_ar_vdev_stop_delete_status(ab, vdev_id);
|
|
if (!ar) {
|
|
ath11k_warn(ab, "invalid vdev id in vdev stopped ev %d",
|
|
vdev_id);
|
|
@@ -6521,7 +6576,6 @@ static void ath11k_wmi_tlv_op_rx(struct
|
|
break;
|
|
/* add Unsupported events here */
|
|
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
|
|
- case WMI_VDEV_DELETE_RESP_EVENTID:
|
|
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
|
|
case WMI_TWT_ENABLE_EVENTID:
|
|
case WMI_TWT_DISABLE_EVENTID:
|
|
@@ -6532,6 +6586,9 @@ static void ath11k_wmi_tlv_op_rx(struct
|
|
case WMI_PDEV_DFS_RADAR_DETECTION_EVENTID:
|
|
ath11k_wmi_pdev_dfs_radar_detected_event(ab, skb);
|
|
break;
|
|
+ case WMI_VDEV_DELETE_RESP_EVENTID:
|
|
+ ath11k_vdev_delete_resp_event(ab, skb);
|
|
+ break;
|
|
/* TODO: Add remaining events */
|
|
default:
|
|
ath11k_warn(ab, "Unknown eventid: 0x%x\n", id);
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
@@ -3919,6 +3919,10 @@ struct wmi_peer_delete_resp_event {
|
|
struct wmi_mac_addr peer_macaddr;
|
|
} __packed;
|
|
|
|
+struct wmi_vdev_delete_resp_event {
|
|
+ u32 vdev_id;
|
|
+} __packed;
|
|
+
|
|
struct wmi_bcn_tx_status_event {
|
|
u32 vdev_id;
|
|
u32 tx_status;
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.h
|
|
@@ -141,7 +141,8 @@ struct ath11k *ath11k_mac_get_ar_by_vdev
|
|
struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id);
|
|
struct ath11k *ath11k_mac_get_ar_vdev_stop_status(struct ath11k_base *ab,
|
|
u32 vdev_id);
|
|
-
|
|
+struct ath11k *ath11k_mac_get_ar_vdev_stop_delete_status(struct ath11k_base *ab,
|
|
+ u32 vdev_id);
|
|
void ath11k_mac_drain_tx(struct ath11k *ar);
|
|
void ath11k_mac_peer_cleanup_all(struct ath11k *ar);
|
|
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
|