Commit bff621fd authored by Pradeep Kumar Chitrapu's avatar Pradeep Kumar Chitrapu Committed by Kalle Valo

ath11k: Send multiple scan_chan_list messages if required

With addition of 6Ghz channels, it is possible that wmi buffer size can
exceed the maximum wmi buffer size. So iterate over the channel list,
and send multiple messages till channel list is empty.
Also mark PSC channel flag for 6GHz channels accordingly.
Signed-off-by: default avatarPradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200603001724.12161-8-pradeepc@codeaurora.org
parent 194b8ea1
......@@ -2195,91 +2195,110 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
struct wmi_tlv *tlv;
void *ptr;
int i, ret, len;
u16 num_send_chans, num_sends = 0, max_chan_limit = 0;
u32 *reg1, *reg2;
len = sizeof(*cmd) + TLV_HDR_SIZE +
sizeof(*chan_info) * chan_list->nallchans;
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
tchan_info = &chan_list->ch_param[0];
while (chan_list->nallchans) {
len = sizeof(*cmd) + TLV_HDR_SIZE;
max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /
sizeof(*chan_info);
cmd = (struct wmi_scan_chan_list_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_SCAN_CHAN_LIST_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
if (chan_list->nallchans > max_chan_limit)
num_send_chans = max_chan_limit;
else
num_send_chans = chan_list->nallchans;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI no.of chan = %d len = %d\n", chan_list->nallchans, len);
cmd->pdev_id = chan_list->pdev_id;
cmd->num_scan_chans = chan_list->nallchans;
chan_list->nallchans -= num_send_chans;
len += sizeof(*chan_info) * num_send_chans;
ptr = skb->data + sizeof(*cmd);
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
len = sizeof(*chan_info) * chan_list->nallchans;
tlv = ptr;
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
ptr += TLV_HDR_SIZE;
cmd = (struct wmi_scan_chan_list_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_SCAN_CHAN_LIST_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->pdev_id = chan_list->pdev_id;
cmd->num_scan_chans = num_send_chans;
if (num_sends)
cmd->flags |= WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG;
tchan_info = &chan_list->ch_param[0];
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI no.of chan = %d len = %d pdev_id = %d num_sends = %d\n",
num_send_chans, len, cmd->pdev_id, num_sends);
for (i = 0; i < chan_list->nallchans; ++i) {
chan_info = ptr;
memset(chan_info, 0, sizeof(*chan_info));
len = sizeof(*chan_info);
chan_info->tlv_header = FIELD_PREP(WMI_TLV_TAG,
WMI_TAG_CHANNEL) |
FIELD_PREP(WMI_TLV_LEN,
len - TLV_HDR_SIZE);
reg1 = &chan_info->reg_info_1;
reg2 = &chan_info->reg_info_2;
chan_info->mhz = tchan_info->mhz;
chan_info->band_center_freq1 = tchan_info->cfreq1;
chan_info->band_center_freq2 = tchan_info->cfreq2;
if (tchan_info->is_chan_passive)
chan_info->info |= WMI_CHAN_INFO_PASSIVE;
if (tchan_info->allow_he)
chan_info->info |= WMI_CHAN_INFO_ALLOW_HE;
else if (tchan_info->allow_vht)
chan_info->info |= WMI_CHAN_INFO_ALLOW_VHT;
else if (tchan_info->allow_ht)
chan_info->info |= WMI_CHAN_INFO_ALLOW_HT;
if (tchan_info->half_rate)
chan_info->info |= WMI_CHAN_INFO_HALF_RATE;
if (tchan_info->quarter_rate)
chan_info->info |= WMI_CHAN_INFO_QUARTER_RATE;
chan_info->info |= FIELD_PREP(WMI_CHAN_INFO_MODE,
tchan_info->phy_mode);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_MIN_PWR,
tchan_info->minpower);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_MAX_PWR,
tchan_info->maxpower);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_MAX_REG_PWR,
tchan_info->maxregpower);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_REG_CLS,
tchan_info->reg_class_id);
*reg2 |= FIELD_PREP(WMI_CHAN_REG_INFO2_ANT_MAX,
tchan_info->antennamax);
ptr = skb->data + sizeof(*cmd);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI chan scan list chan[%d] = %u\n",
i, chan_info->mhz);
len = sizeof(*chan_info) * num_send_chans;
tlv = ptr;
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
ptr += TLV_HDR_SIZE;
ptr += sizeof(*chan_info);
for (i = 0; i < num_send_chans; ++i) {
chan_info = ptr;
memset(chan_info, 0, sizeof(*chan_info));
len = sizeof(*chan_info);
chan_info->tlv_header = FIELD_PREP(WMI_TLV_TAG,
WMI_TAG_CHANNEL) |
FIELD_PREP(WMI_TLV_LEN,
len - TLV_HDR_SIZE);
reg1 = &chan_info->reg_info_1;
reg2 = &chan_info->reg_info_2;
chan_info->mhz = tchan_info->mhz;
chan_info->band_center_freq1 = tchan_info->cfreq1;
chan_info->band_center_freq2 = tchan_info->cfreq2;
if (tchan_info->is_chan_passive)
chan_info->info |= WMI_CHAN_INFO_PASSIVE;
if (tchan_info->allow_he)
chan_info->info |= WMI_CHAN_INFO_ALLOW_HE;
else if (tchan_info->allow_vht)
chan_info->info |= WMI_CHAN_INFO_ALLOW_VHT;
else if (tchan_info->allow_ht)
chan_info->info |= WMI_CHAN_INFO_ALLOW_HT;
if (tchan_info->half_rate)
chan_info->info |= WMI_CHAN_INFO_HALF_RATE;
if (tchan_info->quarter_rate)
chan_info->info |= WMI_CHAN_INFO_QUARTER_RATE;
if (tchan_info->psc_channel)
chan_info->info |= WMI_CHAN_INFO_PSC;
chan_info->info |= FIELD_PREP(WMI_CHAN_INFO_MODE,
tchan_info->phy_mode);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_MIN_PWR,
tchan_info->minpower);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_MAX_PWR,
tchan_info->maxpower);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_MAX_REG_PWR,
tchan_info->maxregpower);
*reg1 |= FIELD_PREP(WMI_CHAN_REG_INFO1_REG_CLS,
tchan_info->reg_class_id);
*reg2 |= FIELD_PREP(WMI_CHAN_REG_INFO2_ANT_MAX,
tchan_info->antennamax);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI chan scan list chan[%d] = %u, chan_info->info %8x\n",
i, chan_info->mhz, chan_info->info);
ptr += sizeof(*chan_info);
tchan_info++;
}
tchan_info++;
}
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SCAN_CHAN_LIST_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_SCAN_CHAN_LIST cmd\n");
dev_kfree_skb(skb);
return ret;
}
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SCAN_CHAN_LIST_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_SCAN_CHAN_LIST cmd\n");
dev_kfree_skb(skb);
num_sends++;
}
return ret;
return 0;
}
int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id,
......
......@@ -54,6 +54,8 @@ struct wmi_tlv {
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
#define WMI_BA_MODE_BUFFER_SIZE_256 3
/*
* HW mode config type replicated from FW header
......@@ -3271,6 +3273,7 @@ struct wmi_bcn_send_from_host_cmd {
#define WMI_CHAN_INFO_QUARTER_RATE BIT(15)
#define WMI_CHAN_INFO_DFS_FREQ2 BIT(16)
#define WMI_CHAN_INFO_ALLOW_HE BIT(17)
#define WMI_CHAN_INFO_PSC BIT(18)
#define WMI_CHAN_REG_INFO1_MIN_PWR GENMASK(7, 0)
#define WMI_CHAN_REG_INFO1_MAX_PWR GENMASK(15, 8)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment