* [PATCH] ath10k: add set_bitrate_mask callback
@ 2013-12-21 19:25 Janusz Dziedzic
2013-12-23 7:01 ` Kalle Valo
0 siblings, 1 reply; 4+ messages in thread
From: Janusz Dziedzic @ 2013-12-21 19:25 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Janusz Dziedzic
Add set_bitrate_mask callback. Currently
ath10k HW is limited to handle only single
fixed rate setting or limit number of used
spatial streams.
Example:
iw wlanX set bitrates legacy-5 ht-mcs-5 vht-mcs-5 2:9
will setup VHT, nss=2, mcs=9
iw wlanX set bitrates legacy-5 18 ht-mcs-5 vht-mcs-5
will setup legacy, 18Mbps
iw wlanX set bitrates legacy-5 ht-mcs-5 3 vht-mcs-5
will setup HT, nss=1, mcs=3
iw wlanX set bitrate legacy-5 ht-mcs-5 vht-mcs-5 1:0-9
will setup nss=1
iw wlanX set bitrate legacy-5 ht-mcs-5 vht-mcs-5 1:0-9 2:0-9
will setup nss=2
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
---
Depends on, nl80211: add VHT support for set_bitrate_mask
iw setup example base on, iw: add VHT MCS/NSS set support to set bitrates
drivers/net/wireless/ath/ath10k/core.h | 3 +
drivers/net/wireless/ath/ath10k/mac.c | 294 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.h | 18 ++
3 files changed, 315 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 79726e0..3817e32 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -253,6 +253,9 @@ struct ath10k_vif {
u8 bssid[ETH_ALEN];
} ibss;
} u;
+
+ u8 fixed_rate;
+ u8 fixed_nss;
};
struct ath10k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index ce9ef349..5d289d4 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3310,6 +3310,299 @@ exit:
return ret;
}
+/* Helper table for legacy fixed_rate/bitrate_mask */
+static const u8 cck_ofdm_rate[] = {
+ /* CCK */
+ 3, /* 1Mbps */
+ 2, /* 2Mbps */
+ 1, /* 5.5Mbps */
+ 0, /* 11Mbps */
+ /* OFDM */
+ 3, /* 6Mbps */
+ 7, /* 9Mbps */
+ 2, /* 12Mbps */
+ 6, /* 18Mbps */
+ 1, /* 24Mbps */
+ 5, /* 36Mbps */
+ 0, /* 48Mbps */
+ 4, /* 54Mbps */
+};
+
+/* Check if only one bit set */
+static int ath10k_check_single_mask(u32 mask)
+{
+ int bit;
+
+ bit = ffs(mask);
+ if (!bit)
+ return 0;
+
+ mask &= ~BIT(bit - 1);
+ if (mask)
+ return 2;
+
+ return 1;
+}
+
+static bool
+ath10k_default_bitrate_mask(struct ath10k *ar,
+ enum ieee80211_band band,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ u32 legacy = 0x00ff;
+ u8 ht = 0xff, i;
+ u16 vht = 0x3ff;
+
+ switch (band) {
+ case IEEE80211_BAND_2GHZ:
+ legacy = 0x00fff;
+ vht = 0;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ break;
+ default:
+ return false;
+ }
+
+ if (mask->control[band].legacy != legacy)
+ return false;
+
+ for (i = 0; i < ar->num_rf_chains; i++)
+ if (mask->control[band].ht_mcs[i] != ht)
+ return false;
+
+ for (i = 0; i < ar->num_rf_chains; i++)
+ if (mask->control[band].vht_mcs[i] != vht)
+ return false;
+
+ return true;
+}
+
+static bool
+ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
+ enum ieee80211_band band,
+ u8 *fixed_nss)
+{
+ int ht_nss = 0, vht_nss = 0, i;
+
+ /* check legacy */
+ if (ath10k_check_single_mask(mask->control[band].legacy))
+ return false;
+
+ /* check HT */
+ for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+ if (mask->control[band].ht_mcs[i] == 0xff)
+ continue;
+ else if (mask->control[band].ht_mcs[i] == 0x00)
+ break;
+ else
+ return false;
+ }
+
+ ht_nss = i;
+
+ /* check VHT */
+ for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
+ if (mask->control[band].vht_mcs[i] == 0x03ff)
+ continue;
+ else if (mask->control[band].vht_mcs[i] == 0x0000)
+ break;
+ else
+ return false;
+ }
+
+ vht_nss = i;
+
+ if (ht_nss > 0 && vht_nss > 0)
+ return false;
+
+ if (ht_nss)
+ *fixed_nss = ht_nss;
+ else if (vht_nss)
+ *fixed_nss = vht_nss;
+ else
+ return false;
+
+ return true;
+}
+
+static bool
+ath10k_bitrate_mask_correct(const struct cfg80211_bitrate_mask *mask,
+ enum ieee80211_band band,
+ enum wmi_rate_preamble *preamble)
+{
+ int legacy = 0, ht = 0, vht = 0, i;
+
+ *preamble = WMI_RATE_PREAMBLE_OFDM;
+
+ /* check legacy */
+ legacy = ath10k_check_single_mask(mask->control[band].legacy);
+ if (legacy > 1)
+ return false;
+
+ /* check HT */
+ for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
+ ht += ath10k_check_single_mask(mask->control[band].ht_mcs[i]);
+ if (ht > 1)
+ return false;
+
+ /* check VHT */
+ for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
+ vht += ath10k_check_single_mask(mask->control[band].vht_mcs[i]);
+ if (vht > 1)
+ return false;
+
+ /* Currently we support only one fixed_rate */
+ if ((legacy + ht + vht) != 1)
+ return false;
+
+ if (ht)
+ *preamble = WMI_RATE_PREAMBLE_HT;
+ else if (vht)
+ *preamble = WMI_RATE_PREAMBLE_VHT;
+
+ return true;
+}
+
+static bool
+ath10k_bitrate_mask_rate(const struct cfg80211_bitrate_mask *mask,
+ enum ieee80211_band band,
+ u8 *fixed_rate,
+ u8 *fixed_nss)
+{
+ u8 rate = 0, pream = 0, nss = 0, i;
+ enum wmi_rate_preamble preamble;
+
+ /* Check if single rate correct */
+ if (!ath10k_bitrate_mask_correct(mask, band, &preamble))
+ return false;
+
+ pream = preamble;
+
+ switch (preamble) {
+ case WMI_RATE_PREAMBLE_CCK:
+ case WMI_RATE_PREAMBLE_OFDM:
+ i = ffs(mask->control[band].legacy) - 1;
+
+ if (band == IEEE80211_BAND_2GHZ && i < 4)
+ pream = WMI_RATE_PREAMBLE_CCK;
+
+ if (band == IEEE80211_BAND_5GHZ)
+ i += 4;
+
+ WARN_ON(i >= ARRAY_SIZE(cck_ofdm_rate));
+ rate = cck_ofdm_rate[i];
+ break;
+ case WMI_RATE_PREAMBLE_HT:
+ for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
+ if (mask->control[band].ht_mcs[i])
+ break;
+
+ rate = ffs(mask->control[band].ht_mcs[i]) - 1;
+ nss = i;
+ break;
+ case WMI_RATE_PREAMBLE_VHT:
+ for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
+ if (mask->control[band].vht_mcs[i])
+ break;
+
+ rate = ffs(mask->control[band].vht_mcs[i]) - 1;
+ nss = i;
+ break;
+ }
+
+ *fixed_nss = nss + 1;
+ nss <<= 4;
+ pream <<= 6;
+
+ ath10k_dbg(ATH10K_DBG_MAC, "mac fixed rate pream 0x%02x nss 0x%02x rate 0x%02x\n",
+ pream, nss, rate);
+
+ *fixed_rate = pream | nss | rate;
+
+ return true;
+}
+
+static bool ath10k_get_fixed_rate_nss(const struct cfg80211_bitrate_mask *mask,
+ enum ieee80211_band band,
+ u8 *fixed_rate,
+ u8 *fixed_nss)
+{
+ /* First check full NSS mask, if we can simply limit NSS */
+ if (ath10k_bitrate_mask_nss(mask, band, fixed_nss))
+ return true;
+
+ /* Next Check single rate is set */
+ return ath10k_bitrate_mask_rate(mask, band, fixed_rate, fixed_nss);
+}
+
+static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif,
+ u8 fixed_rate,
+ u8 fixed_nss)
+{
+ struct ath10k *ar = arvif->ar;
+ u32 vdev_param;
+ int ret = 0;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (arvif->fixed_rate == fixed_rate &&
+ arvif->fixed_nss == fixed_nss)
+ goto exit;
+
+ if (fixed_rate == WMI_FIXED_RATE_NONE)
+ ath10k_dbg(ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n");
+
+ vdev_param = ar->wmi.vdev_param->fixed_rate;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
+ vdev_param, fixed_rate);
+ if (ret) {
+ ath10k_warn("Could not set fixed_rate param 0x%02x: %d\n",
+ fixed_rate, ret);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ arvif->fixed_rate = fixed_rate;
+
+ vdev_param = ar->wmi.vdev_param->nss;
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
+ vdev_param, fixed_nss);
+
+ if (ret) {
+ ath10k_warn("Could not set fixed_nss param %d: %d\n",
+ fixed_nss, ret);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ arvif->fixed_nss = fixed_nss;
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k *ar = arvif->ar;
+ enum ieee80211_band band = ar->hw->conf.chandef.chan->band;
+ struct wmi_vdev_fixed_rate fixed_rate = { .rate = WMI_FIXED_RATE_NONE };
+ u8 fixed_nss = ar->num_rf_chains;
+
+ if (!ath10k_default_bitrate_mask(ar, band, mask)) {
+ if (!ath10k_get_fixed_rate_nss(mask, band,
+ &fixed_rate.rate,
+ &fixed_nss))
+ return -EINVAL;
+ }
+
+ return ath10k_set_fixed_rate_param(arvif, fixed_rate.rate, fixed_nss);
+}
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_tx,
.start = ath10k_start,
@@ -3332,6 +3625,7 @@ static const struct ieee80211_ops ath10k_ops = {
.tx_last_beacon = ath10k_tx_last_beacon,
.restart_complete = ath10k_restart_complete,
.get_survey = ath10k_get_survey,
+ .set_bitrate_mask = ath10k_set_bitrate_mask,
#ifdef CONFIG_PM
.suspend = ath10k_suspend,
.resume = ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 0087d69..ee9afb9 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3003,6 +3003,24 @@ struct wmi_vdev_install_key_arg {
const void *key_data;
};
+/*
+ * CCK: 0 - 11Mbps, 1 - 5,5Mbps, 2 - 2Mbps, 3 - 1Mbps,
+ * 4 - 11Mbps (s), 5 - 5,5Mbps (s), 6 - 2Mbps (s)
+ * OFDM: 0 - 48Mbps, 1 - 24Mbps, 2 - 12Mbps, 3 - 6Mbps,
+ * 4 - 54Mbps, 5 - 36Mbps, 6 - 18Mbps, 7 - 9Mbps
+ * HT/VHT: MCS index
+ */
+struct wmi_vdev_fixed_rate {
+ union {
+ u8 rate;
+ struct {
+ u8 preamble:2, /* %WMI_RATE_PREAMBLE_ */
+ nss:2,
+ rate_mcs:4; /* see above */
+ } __packed;
+ } __packed;
+} __packed;
+
/* Preamble types to be used with VDEV fixed rate configuration */
enum wmi_rate_preamble {
WMI_RATE_PREAMBLE_OFDM,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] ath10k: add set_bitrate_mask callback
2013-12-21 19:25 [PATCH] ath10k: add set_bitrate_mask callback Janusz Dziedzic
@ 2013-12-23 7:01 ` Kalle Valo
2013-12-23 13:55 ` Janusz Dziedzic
0 siblings, 1 reply; 4+ messages in thread
From: Kalle Valo @ 2013-12-23 7:01 UTC (permalink / raw)
To: Janusz Dziedzic; +Cc: ath10k, linux-wireless
Janusz Dziedzic <janusz.dziedzic@tieto.com> writes:
> Add set_bitrate_mask callback. Currently
> ath10k HW is limited to handle only single
> fixed rate setting or limit number of used
> spatial streams.
>
> Example:
> iw wlanX set bitrates legacy-5 ht-mcs-5 vht-mcs-5 2:9
> will setup VHT, nss=2, mcs=9
>
> iw wlanX set bitrates legacy-5 18 ht-mcs-5 vht-mcs-5
> will setup legacy, 18Mbps
>
> iw wlanX set bitrates legacy-5 ht-mcs-5 3 vht-mcs-5
> will setup HT, nss=1, mcs=3
>
> iw wlanX set bitrate legacy-5 ht-mcs-5 vht-mcs-5 1:0-9
> will setup nss=1
>
> iw wlanX set bitrate legacy-5 ht-mcs-5 vht-mcs-5 1:0-9 2:0-9
> will setup nss=2
>
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
I see a new warning with this patch:
ath10k/mac.c:3593:52: error: unknown field name in initializer
> Depends on, nl80211: add VHT support for set_bitrate_mask
Good, I need to always know this. I now merged wireless-next to ath-next
to get the dependency included.
> --- a/drivers/net/wireless/ath/ath10k/wmi.h
> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
> @@ -3003,6 +3003,24 @@ struct wmi_vdev_install_key_arg {
> const void *key_data;
> };
>
> +/*
> + * CCK: 0 - 11Mbps, 1 - 5,5Mbps, 2 - 2Mbps, 3 - 1Mbps,
> + * 4 - 11Mbps (s), 5 - 5,5Mbps (s), 6 - 2Mbps (s)
> + * OFDM: 0 - 48Mbps, 1 - 24Mbps, 2 - 12Mbps, 3 - 6Mbps,
> + * 4 - 54Mbps, 5 - 36Mbps, 6 - 18Mbps, 7 - 9Mbps
> + * HT/VHT: MCS index
> + */
> +struct wmi_vdev_fixed_rate {
> + union {
> + u8 rate;
> + struct {
> + u8 preamble:2, /* %WMI_RATE_PREAMBLE_ */
> + nss:2,
> + rate_mcs:4; /* see above */
> + } __packed;
> + } __packed;
> +} __packed;
Bitfields are frowned upon in kernel, better to use SM() and MS().
--
Kalle Valo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ath10k: add set_bitrate_mask callback
2013-12-23 7:01 ` Kalle Valo
@ 2013-12-23 13:55 ` Janusz Dziedzic
2013-12-23 14:04 ` Kalle Valo
0 siblings, 1 reply; 4+ messages in thread
From: Janusz Dziedzic @ 2013-12-23 13:55 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
On 23 December 2013 08:01, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> Janusz Dziedzic <janusz.dziedzic@tieto.com> writes:
>
>> Add set_bitrate_mask callback. Currently
>> ath10k HW is limited to handle only single
>> fixed rate setting or limit number of used
>> spatial streams.
>>
>> Example:
>> iw wlanX set bitrates legacy-5 ht-mcs-5 vht-mcs-5 2:9
>> will setup VHT, nss=2, mcs=9
>>
>> iw wlanX set bitrates legacy-5 18 ht-mcs-5 vht-mcs-5
>> will setup legacy, 18Mbps
>>
>> iw wlanX set bitrates legacy-5 ht-mcs-5 3 vht-mcs-5
>> will setup HT, nss=1, mcs=3
>>
>> iw wlanX set bitrate legacy-5 ht-mcs-5 vht-mcs-5 1:0-9
>> will setup nss=1
>>
>> iw wlanX set bitrate legacy-5 ht-mcs-5 vht-mcs-5 1:0-9 2:0-9
>> will setup nss=2
>>
>> Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
>
> I see a new warning with this patch:
>
> ath10k/mac.c:3593:52: error: unknown field name in initializer
>
Will fix this.
>> Depends on, nl80211: add VHT support for set_bitrate_mask
>
> Good, I need to always know this. I now merged wireless-next to ath-next
> to get the dependency included.
>
>> --- a/drivers/net/wireless/ath/ath10k/wmi.h
>> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
>> @@ -3003,6 +3003,24 @@ struct wmi_vdev_install_key_arg {
>> const void *key_data;
>> };
>>
>> +/*
>> + * CCK: 0 - 11Mbps, 1 - 5,5Mbps, 2 - 2Mbps, 3 - 1Mbps,
>> + * 4 - 11Mbps (s), 5 - 5,5Mbps (s), 6 - 2Mbps (s)
>> + * OFDM: 0 - 48Mbps, 1 - 24Mbps, 2 - 12Mbps, 3 - 6Mbps,
>> + * 4 - 54Mbps, 5 - 36Mbps, 6 - 18Mbps, 7 - 9Mbps
>> + * HT/VHT: MCS index
>> + */
>> +struct wmi_vdev_fixed_rate {
>> + union {
>> + u8 rate;
>> + struct {
>> + u8 preamble:2, /* %WMI_RATE_PREAMBLE_ */
>> + nss:2,
>> + rate_mcs:4; /* see above */
>> + } __packed;
>> + } __packed;
>> +} __packed;
>
> Bitfields are frowned upon in kernel, better to use SM() and MS().
>
I don't use them, just put as a documentation.
Will add note that this bitfields should not be used.
BR
Janusz
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ath10k: add set_bitrate_mask callback
2013-12-23 13:55 ` Janusz Dziedzic
@ 2013-12-23 14:04 ` Kalle Valo
0 siblings, 0 replies; 4+ messages in thread
From: Kalle Valo @ 2013-12-23 14:04 UTC (permalink / raw)
To: Janusz Dziedzic; +Cc: ath10k, linux-wireless
Janusz Dziedzic <janusz.dziedzic@tieto.com> writes:
>> Bitfields are frowned upon in kernel, better to use SM() and MS().
>>
> I don't use them, just put as a documentation.
Ok, then you can just document that within comments.
--
Kalle Valo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-12-23 14:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-21 19:25 [PATCH] ath10k: add set_bitrate_mask callback Janusz Dziedzic
2013-12-23 7:01 ` Kalle Valo
2013-12-23 13:55 ` Janusz Dziedzic
2013-12-23 14:04 ` Kalle Valo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).