aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c302
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h12
3 files changed, 317 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 3721c43e2941..ade1781c7186 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -253,6 +253,9 @@ struct ath10k_vif {
253 u8 bssid[ETH_ALEN]; 253 u8 bssid[ETH_ALEN];
254 } ibss; 254 } ibss;
255 } u; 255 } u;
256
257 u8 fixed_rate;
258 u8 fixed_nss;
256}; 259};
257 260
258struct ath10k_vif_iter { 261struct ath10k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index ce0f1db24731..7aa6c4d702d6 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3339,6 +3339,307 @@ exit:
3339 return ret; 3339 return ret;
3340} 3340}
3341 3341
3342/* Helper table for legacy fixed_rate/bitrate_mask */
3343static const u8 cck_ofdm_rate[] = {
3344 /* CCK */
3345 3, /* 1Mbps */
3346 2, /* 2Mbps */
3347 1, /* 5.5Mbps */
3348 0, /* 11Mbps */
3349 /* OFDM */
3350 3, /* 6Mbps */
3351 7, /* 9Mbps */
3352 2, /* 12Mbps */
3353 6, /* 18Mbps */
3354 1, /* 24Mbps */
3355 5, /* 36Mbps */
3356 0, /* 48Mbps */
3357 4, /* 54Mbps */
3358};
3359
3360/* Check if only one bit set */
3361static int ath10k_check_single_mask(u32 mask)
3362{
3363 int bit;
3364
3365 bit = ffs(mask);
3366 if (!bit)
3367 return 0;
3368
3369 mask &= ~BIT(bit - 1);
3370 if (mask)
3371 return 2;
3372
3373 return 1;
3374}
3375
3376static bool
3377ath10k_default_bitrate_mask(struct ath10k *ar,
3378 enum ieee80211_band band,
3379 const struct cfg80211_bitrate_mask *mask)
3380{
3381 u32 legacy = 0x00ff;
3382 u8 ht = 0xff, i;
3383 u16 vht = 0x3ff;
3384
3385 switch (band) {
3386 case IEEE80211_BAND_2GHZ:
3387 legacy = 0x00fff;
3388 vht = 0;
3389 break;
3390 case IEEE80211_BAND_5GHZ:
3391 break;
3392 default:
3393 return false;
3394 }
3395
3396 if (mask->control[band].legacy != legacy)
3397 return false;
3398
3399 for (i = 0; i < ar->num_rf_chains; i++)
3400 if (mask->control[band].ht_mcs[i] != ht)
3401 return false;
3402
3403 for (i = 0; i < ar->num_rf_chains; i++)
3404 if (mask->control[band].vht_mcs[i] != vht)
3405 return false;
3406
3407 return true;
3408}
3409
3410static bool
3411ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
3412 enum ieee80211_band band,
3413 u8 *fixed_nss)
3414{
3415 int ht_nss = 0, vht_nss = 0, i;
3416
3417 /* check legacy */
3418 if (ath10k_check_single_mask(mask->control[band].legacy))
3419 return false;
3420
3421 /* check HT */
3422 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3423 if (mask->control[band].ht_mcs[i] == 0xff)
3424 continue;
3425 else if (mask->control[band].ht_mcs[i] == 0x00)
3426 break;
3427 else
3428 return false;
3429 }
3430
3431 ht_nss = i;
3432
3433 /* check VHT */
3434 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
3435 if (mask->control[band].vht_mcs[i] == 0x03ff)
3436 continue;
3437 else if (mask->control[band].vht_mcs[i] == 0x0000)
3438 break;
3439 else
3440 return false;
3441 }
3442
3443 vht_nss = i;
3444
3445 if (ht_nss > 0 && vht_nss > 0)
3446 return false;
3447
3448 if (ht_nss)
3449 *fixed_nss = ht_nss;
3450 else if (vht_nss)
3451 *fixed_nss = vht_nss;
3452 else
3453 return false;
3454
3455 return true;
3456}
3457
3458static bool
3459ath10k_bitrate_mask_correct(const struct cfg80211_bitrate_mask *mask,
3460 enum ieee80211_band band,
3461 enum wmi_rate_preamble *preamble)
3462{
3463 int legacy = 0, ht = 0, vht = 0, i;
3464
3465 *preamble = WMI_RATE_PREAMBLE_OFDM;
3466
3467 /* check legacy */
3468 legacy = ath10k_check_single_mask(mask->control[band].legacy);
3469 if (legacy > 1)
3470 return false;
3471
3472 /* check HT */
3473 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
3474 ht += ath10k_check_single_mask(mask->control[band].ht_mcs[i]);
3475 if (ht > 1)
3476 return false;
3477
3478 /* check VHT */
3479 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
3480 vht += ath10k_check_single_mask(mask->control[band].vht_mcs[i]);
3481 if (vht > 1)
3482 return false;
3483
3484 /* Currently we support only one fixed_rate */
3485 if ((legacy + ht + vht) != 1)
3486 return false;
3487
3488 if (ht)
3489 *preamble = WMI_RATE_PREAMBLE_HT;
3490 else if (vht)
3491 *preamble = WMI_RATE_PREAMBLE_VHT;
3492
3493 return true;
3494}
3495
3496static bool
3497ath10k_bitrate_mask_rate(const struct cfg80211_bitrate_mask *mask,
3498 enum ieee80211_band band,
3499 u8 *fixed_rate,
3500 u8 *fixed_nss)
3501{
3502 u8 rate = 0, pream = 0, nss = 0, i;
3503 enum wmi_rate_preamble preamble;
3504
3505 /* Check if single rate correct */
3506 if (!ath10k_bitrate_mask_correct(mask, band, &preamble))
3507 return false;
3508
3509 pream = preamble;
3510
3511 switch (preamble) {
3512 case WMI_RATE_PREAMBLE_CCK:
3513 case WMI_RATE_PREAMBLE_OFDM:
3514 i = ffs(mask->control[band].legacy) - 1;
3515
3516 if (band == IEEE80211_BAND_2GHZ && i < 4)
3517 pream = WMI_RATE_PREAMBLE_CCK;
3518
3519 if (band == IEEE80211_BAND_5GHZ)
3520 i += 4;
3521
3522 if (i >= ARRAY_SIZE(cck_ofdm_rate))
3523 return false;
3524
3525 rate = cck_ofdm_rate[i];
3526 break;
3527 case WMI_RATE_PREAMBLE_HT:
3528 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
3529 if (mask->control[band].ht_mcs[i])
3530 break;
3531
3532 if (i == IEEE80211_HT_MCS_MASK_LEN)
3533 return false;
3534
3535 rate = ffs(mask->control[band].ht_mcs[i]) - 1;
3536 nss = i;
3537 break;
3538 case WMI_RATE_PREAMBLE_VHT:
3539 for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
3540 if (mask->control[band].vht_mcs[i])
3541 break;
3542
3543 if (i == NL80211_VHT_NSS_MAX)
3544 return false;
3545
3546 rate = ffs(mask->control[band].vht_mcs[i]) - 1;
3547 nss = i;
3548 break;
3549 }
3550
3551 *fixed_nss = nss + 1;
3552 nss <<= 4;
3553 pream <<= 6;
3554
3555 ath10k_dbg(ATH10K_DBG_MAC, "mac fixed rate pream 0x%02x nss 0x%02x rate 0x%02x\n",
3556 pream, nss, rate);
3557
3558 *fixed_rate = pream | nss | rate;
3559
3560 return true;
3561}
3562
3563static bool ath10k_get_fixed_rate_nss(const struct cfg80211_bitrate_mask *mask,
3564 enum ieee80211_band band,
3565 u8 *fixed_rate,
3566 u8 *fixed_nss)
3567{
3568 /* First check full NSS mask, if we can simply limit NSS */
3569 if (ath10k_bitrate_mask_nss(mask, band, fixed_nss))
3570 return true;
3571
3572 /* Next Check single rate is set */
3573 return ath10k_bitrate_mask_rate(mask, band, fixed_rate, fixed_nss);
3574}
3575
3576static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif,
3577 u8 fixed_rate,
3578 u8 fixed_nss)
3579{
3580 struct ath10k *ar = arvif->ar;
3581 u32 vdev_param;
3582 int ret = 0;
3583
3584 mutex_lock(&ar->conf_mutex);
3585
3586 if (arvif->fixed_rate == fixed_rate &&
3587 arvif->fixed_nss == fixed_nss)
3588 goto exit;
3589
3590 if (fixed_rate == WMI_FIXED_RATE_NONE)
3591 ath10k_dbg(ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n");
3592
3593 vdev_param = ar->wmi.vdev_param->fixed_rate;
3594 ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
3595 vdev_param, fixed_rate);
3596 if (ret) {
3597 ath10k_warn("Could not set fixed_rate param 0x%02x: %d\n",
3598 fixed_rate, ret);
3599 ret = -EINVAL;
3600 goto exit;
3601 }
3602
3603 arvif->fixed_rate = fixed_rate;
3604
3605 vdev_param = ar->wmi.vdev_param->nss;
3606 ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
3607 vdev_param, fixed_nss);
3608
3609 if (ret) {
3610 ath10k_warn("Could not set fixed_nss param %d: %d\n",
3611 fixed_nss, ret);
3612 ret = -EINVAL;
3613 goto exit;
3614 }
3615
3616 arvif->fixed_nss = fixed_nss;
3617
3618exit:
3619 mutex_unlock(&ar->conf_mutex);
3620 return ret;
3621}
3622
3623static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw,
3624 struct ieee80211_vif *vif,
3625 const struct cfg80211_bitrate_mask *mask)
3626{
3627 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
3628 struct ath10k *ar = arvif->ar;
3629 enum ieee80211_band band = ar->hw->conf.chandef.chan->band;
3630 u8 fixed_rate = WMI_FIXED_RATE_NONE;
3631 u8 fixed_nss = ar->num_rf_chains;
3632
3633 if (!ath10k_default_bitrate_mask(ar, band, mask)) {
3634 if (!ath10k_get_fixed_rate_nss(mask, band,
3635 &fixed_rate,
3636 &fixed_nss))
3637 return -EINVAL;
3638 }
3639
3640 return ath10k_set_fixed_rate_param(arvif, fixed_rate, fixed_nss);
3641}
3642
3342static const struct ieee80211_ops ath10k_ops = { 3643static const struct ieee80211_ops ath10k_ops = {
3343 .tx = ath10k_tx, 3644 .tx = ath10k_tx,
3344 .start = ath10k_start, 3645 .start = ath10k_start,
@@ -3361,6 +3662,7 @@ static const struct ieee80211_ops ath10k_ops = {
3361 .tx_last_beacon = ath10k_tx_last_beacon, 3662 .tx_last_beacon = ath10k_tx_last_beacon,
3362 .restart_complete = ath10k_restart_complete, 3663 .restart_complete = ath10k_restart_complete,
3363 .get_survey = ath10k_get_survey, 3664 .get_survey = ath10k_get_survey,
3665 .set_bitrate_mask = ath10k_set_bitrate_mask,
3364#ifdef CONFIG_PM 3666#ifdef CONFIG_PM
3365 .suspend = ath10k_suspend, 3667 .suspend = ath10k_suspend,
3366 .resume = ath10k_resume, 3668 .resume = ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 4aa1489f4eb2..4b5e7d3d32b6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3003,6 +3003,18 @@ struct wmi_vdev_install_key_arg {
3003 const void *key_data; 3003 const void *key_data;
3004}; 3004};
3005 3005
3006/*
3007 * vdev fixed rate format:
3008 * - preamble - b7:b6 - see WMI_RATE_PREMABLE_
3009 * - nss - b5:b4 - ss number (0 mean 1ss)
3010 * - rate_mcs - b3:b0 - as below
3011 * CCK: 0 - 11Mbps, 1 - 5,5Mbps, 2 - 2Mbps, 3 - 1Mbps,
3012 * 4 - 11Mbps (s), 5 - 5,5Mbps (s), 6 - 2Mbps (s)
3013 * OFDM: 0 - 48Mbps, 1 - 24Mbps, 2 - 12Mbps, 3 - 6Mbps,
3014 * 4 - 54Mbps, 5 - 36Mbps, 6 - 18Mbps, 7 - 9Mbps
3015 * HT/VHT: MCS index
3016 */
3017
3006/* Preamble types to be used with VDEV fixed rate configuration */ 3018/* Preamble types to be used with VDEV fixed rate configuration */
3007enum wmi_rate_preamble { 3019enum wmi_rate_preamble {
3008 WMI_RATE_PREAMBLE_OFDM, 3020 WMI_RATE_PREAMBLE_OFDM,