|
@@ -2205,30 +2205,113 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb,
|
|
|
+ struct wmi_svc_rdy_ev_arg *arg)
|
|
|
+{
|
|
|
+ struct wmi_service_ready_event *ev;
|
|
|
+ size_t i, n;
|
|
|
+
|
|
|
+ if (skb->len < sizeof(*ev))
|
|
|
+ return -EPROTO;
|
|
|
+
|
|
|
+ ev = (void *)skb->data;
|
|
|
+ skb_pull(skb, sizeof(*ev));
|
|
|
+ arg->min_tx_power = ev->hw_min_tx_power;
|
|
|
+ arg->max_tx_power = ev->hw_max_tx_power;
|
|
|
+ arg->ht_cap = ev->ht_cap_info;
|
|
|
+ arg->vht_cap = ev->vht_cap_info;
|
|
|
+ arg->sw_ver0 = ev->sw_version;
|
|
|
+ arg->sw_ver1 = ev->sw_version_1;
|
|
|
+ arg->phy_capab = ev->phy_capability;
|
|
|
+ arg->num_rf_chains = ev->num_rf_chains;
|
|
|
+ arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
|
|
+ arg->num_mem_reqs = ev->num_mem_reqs;
|
|
|
+ arg->service_map = ev->wmi_service_bitmap;
|
|
|
+
|
|
|
+ n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
|
|
|
+ ARRAY_SIZE(arg->mem_reqs));
|
|
|
+ for (i = 0; i < n; i++)
|
|
|
+ arg->mem_reqs[i] = &ev->mem_reqs[i];
|
|
|
+
|
|
|
+ if (skb->len <
|
|
|
+ __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
|
|
|
+ return -EPROTO;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb,
|
|
|
+ struct wmi_svc_rdy_ev_arg *arg)
|
|
|
+{
|
|
|
+ struct wmi_10x_service_ready_event *ev;
|
|
|
+ int i, n;
|
|
|
+
|
|
|
+ if (skb->len < sizeof(*ev))
|
|
|
+ return -EPROTO;
|
|
|
+
|
|
|
+ ev = (void *)skb->data;
|
|
|
+ skb_pull(skb, sizeof(*ev));
|
|
|
+ arg->min_tx_power = ev->hw_min_tx_power;
|
|
|
+ arg->max_tx_power = ev->hw_max_tx_power;
|
|
|
+ arg->ht_cap = ev->ht_cap_info;
|
|
|
+ arg->vht_cap = ev->vht_cap_info;
|
|
|
+ arg->sw_ver0 = ev->sw_version;
|
|
|
+ arg->phy_capab = ev->phy_capability;
|
|
|
+ arg->num_rf_chains = ev->num_rf_chains;
|
|
|
+ arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
|
|
+ arg->num_mem_reqs = ev->num_mem_reqs;
|
|
|
+ arg->service_map = ev->wmi_service_bitmap;
|
|
|
+
|
|
|
+ n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
|
|
|
+ ARRAY_SIZE(arg->mem_reqs));
|
|
|
+ for (i = 0; i < n; i++)
|
|
|
+ arg->mem_reqs[i] = &ev->mem_reqs[i];
|
|
|
+
|
|
|
+ if (skb->len <
|
|
|
+ __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
|
|
|
+ return -EPROTO;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
|
|
|
struct sk_buff *skb)
|
|
|
{
|
|
|
- struct wmi_service_ready_event *ev = (void *)skb->data;
|
|
|
+ struct wmi_svc_rdy_ev_arg arg = {};
|
|
|
+ u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
|
|
|
DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
|
|
|
+ int ret;
|
|
|
|
|
|
- if (skb->len < sizeof(*ev)) {
|
|
|
- ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
|
|
|
- skb->len, sizeof(*ev));
|
|
|
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
|
|
|
+ ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
|
|
|
+ wmi_10x_svc_map(arg.service_map, svc_bmap);
|
|
|
+ } else {
|
|
|
+ ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg);
|
|
|
+ wmi_main_svc_map(arg.service_map, svc_bmap);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret) {
|
|
|
+ ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
|
|
|
- ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
|
|
|
- ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
|
|
|
- ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
|
|
|
+ ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power);
|
|
|
+ ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
|
|
|
+ ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
|
|
|
+ ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
|
|
|
ar->fw_version_major =
|
|
|
- (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
|
|
|
- ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
|
|
|
+ (__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
|
|
|
+ ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
|
|
|
ar->fw_version_release =
|
|
|
- (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16;
|
|
|
- ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff);
|
|
|
- ar->phy_capability = __le32_to_cpu(ev->phy_capability);
|
|
|
- ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
|
|
|
+ (__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16;
|
|
|
+ ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
|
|
|
+ ar->phy_capability = __le32_to_cpu(arg.phy_capab);
|
|
|
+ ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
|
|
|
+ ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
|
|
|
+
|
|
|
+ ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
|
|
|
+ ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
|
|
+ arg.service_map, sizeof(arg.service_map));
|
|
|
|
|
|
/* only manually set fw features when not using FW IE format */
|
|
|
if (ar->fw_api == 1 && ar->fw_version_build > 636)
|
|
@@ -2243,14 +2326,6 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
|
|
|
ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
|
|
|
ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
|
|
|
|
|
|
- ar->ath_common.regulatory.current_rd =
|
|
|
- __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
|
|
|
-
|
|
|
- wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap);
|
|
|
- ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
|
|
|
- ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
|
|
- ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
|
|
|
-
|
|
|
if (strlen(ar->hw->wiphy->fw_version) == 0) {
|
|
|
snprintf(ar->hw->wiphy->fw_version,
|
|
|
sizeof(ar->hw->wiphy->fw_version),
|
|
@@ -2261,96 +2336,18 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
|
|
|
ar->fw_version_build);
|
|
|
}
|
|
|
|
|
|
- /* FIXME: it probably should be better to support this */
|
|
|
- if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
|
|
|
- ath10k_warn(ar, "target requested %d memory chunks; ignoring\n",
|
|
|
- __le32_to_cpu(ev->num_mem_reqs));
|
|
|
- }
|
|
|
-
|
|
|
- ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
- "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
|
|
|
- __le32_to_cpu(ev->sw_version),
|
|
|
- __le32_to_cpu(ev->sw_version_1),
|
|
|
- __le32_to_cpu(ev->abi_version),
|
|
|
- __le32_to_cpu(ev->phy_capability),
|
|
|
- __le32_to_cpu(ev->ht_cap_info),
|
|
|
- __le32_to_cpu(ev->vht_cap_info),
|
|
|
- __le32_to_cpu(ev->vht_supp_mcs),
|
|
|
- __le32_to_cpu(ev->sys_cap_info),
|
|
|
- __le32_to_cpu(ev->num_mem_reqs),
|
|
|
- __le32_to_cpu(ev->num_rf_chains));
|
|
|
-
|
|
|
- complete(&ar->wmi.service_ready);
|
|
|
-}
|
|
|
-
|
|
|
-static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
|
|
|
- struct sk_buff *skb)
|
|
|
-{
|
|
|
- u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
|
|
|
- int ret;
|
|
|
- struct wmi_service_ready_event_10x *ev = (void *)skb->data;
|
|
|
- DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
|
|
|
-
|
|
|
- if (skb->len < sizeof(*ev)) {
|
|
|
- ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
|
|
|
- skb->len, sizeof(*ev));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
|
|
|
- ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
|
|
|
- ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
|
|
|
- ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
|
|
|
- ar->fw_version_major =
|
|
|
- (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
|
|
|
- ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
|
|
|
- ar->phy_capability = __le32_to_cpu(ev->phy_capability);
|
|
|
- ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
|
|
|
-
|
|
|
- if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
|
|
|
- ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
|
|
|
- ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
|
|
|
- ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
|
|
|
- }
|
|
|
-
|
|
|
- ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
|
|
|
- ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
|
|
|
-
|
|
|
- ar->ath_common.regulatory.current_rd =
|
|
|
- __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
|
|
|
-
|
|
|
- wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap);
|
|
|
- ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
|
|
|
- ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
|
|
- ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
|
|
|
-
|
|
|
- if (strlen(ar->hw->wiphy->fw_version) == 0) {
|
|
|
- snprintf(ar->hw->wiphy->fw_version,
|
|
|
- sizeof(ar->hw->wiphy->fw_version),
|
|
|
- "%u.%u",
|
|
|
- ar->fw_version_major,
|
|
|
- ar->fw_version_minor);
|
|
|
- }
|
|
|
-
|
|
|
- num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs);
|
|
|
-
|
|
|
- if (num_mem_reqs > ATH10K_MAX_MEM_REQS) {
|
|
|
+ num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs);
|
|
|
+ if (num_mem_reqs > WMI_MAX_MEM_REQS) {
|
|
|
ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n",
|
|
|
num_mem_reqs);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (!num_mem_reqs)
|
|
|
- goto exit;
|
|
|
-
|
|
|
- ath10k_dbg(ar, ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n",
|
|
|
- num_mem_reqs);
|
|
|
-
|
|
|
for (i = 0; i < num_mem_reqs; ++i) {
|
|
|
- req_id = __le32_to_cpu(ev->mem_reqs[i].req_id);
|
|
|
- num_units = __le32_to_cpu(ev->mem_reqs[i].num_units);
|
|
|
- unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size);
|
|
|
- num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info);
|
|
|
+ req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
|
|
|
+ num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
|
|
|
+ unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
|
|
|
+ num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
|
|
|
|
|
|
if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
|
|
|
/* number of units to allocate is number of
|
|
@@ -2364,7 +2361,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
|
|
|
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
"wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
|
|
|
req_id,
|
|
|
- __le32_to_cpu(ev->mem_reqs[i].num_units),
|
|
|
+ __le32_to_cpu(arg.mem_reqs[i]->num_units),
|
|
|
num_unit_info,
|
|
|
unit_size,
|
|
|
num_units);
|
|
@@ -2375,18 +2372,18 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-exit:
|
|
|
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
|
|
- "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
|
|
|
- __le32_to_cpu(ev->sw_version),
|
|
|
- __le32_to_cpu(ev->abi_version),
|
|
|
- __le32_to_cpu(ev->phy_capability),
|
|
|
- __le32_to_cpu(ev->ht_cap_info),
|
|
|
- __le32_to_cpu(ev->vht_cap_info),
|
|
|
- __le32_to_cpu(ev->vht_supp_mcs),
|
|
|
- __le32_to_cpu(ev->sys_cap_info),
|
|
|
- __le32_to_cpu(ev->num_mem_reqs),
|
|
|
- __le32_to_cpu(ev->num_rf_chains));
|
|
|
+ "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
|
|
|
+ __le32_to_cpu(arg.min_tx_power),
|
|
|
+ __le32_to_cpu(arg.max_tx_power),
|
|
|
+ __le32_to_cpu(arg.ht_cap),
|
|
|
+ __le32_to_cpu(arg.vht_cap),
|
|
|
+ __le32_to_cpu(arg.sw_ver0),
|
|
|
+ __le32_to_cpu(arg.sw_ver1),
|
|
|
+ __le32_to_cpu(arg.phy_capab),
|
|
|
+ __le32_to_cpu(arg.num_rf_chains),
|
|
|
+ __le32_to_cpu(arg.eeprom_rd),
|
|
|
+ __le32_to_cpu(arg.num_mem_reqs));
|
|
|
|
|
|
complete(&ar->wmi.service_ready);
|
|
|
}
|
|
@@ -2634,7 +2631,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
|
|
|
ath10k_wmi_event_vdev_resume_req(ar, skb);
|
|
|
break;
|
|
|
case WMI_10X_SERVICE_READY_EVENTID:
|
|
|
- ath10k_wmi_10x_service_ready_event_rx(ar, skb);
|
|
|
+ ath10k_wmi_service_ready_event_rx(ar, skb);
|
|
|
break;
|
|
|
case WMI_10X_READY_EVENTID:
|
|
|
ath10k_wmi_ready_event_rx(ar, skb);
|
|
@@ -2745,7 +2742,7 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
|
|
|
ath10k_wmi_event_vdev_resume_req(ar, skb);
|
|
|
break;
|
|
|
case WMI_10_2_SERVICE_READY_EVENTID:
|
|
|
- ath10k_wmi_10x_service_ready_event_rx(ar, skb);
|
|
|
+ ath10k_wmi_service_ready_event_rx(ar, skb);
|
|
|
break;
|
|
|
case WMI_10_2_READY_EVENTID:
|
|
|
ath10k_wmi_ready_event_rx(ar, skb);
|