From 815ddd8110e03496192c171f3058f85096fb2049 Mon Sep 17 00:00:00 2001 From: Ramya Gnanasekar Date: Wed, 7 Oct 2020 20:08:49 +0530 Subject: [PATCH] ath11k: custom aggregation size support over WMI This patch is to support custom aggregation size config for A-MPDU and A-MSDU through WMI command per vdev_id. rx_aggr_size_disable is set true to avoid fw from considering rx_aggr_size paramater. AC is set to all by default. Upon configuring 0, firmware will default AMPDU aggregation size to 1 and AMDSU to 7. Default aggregation limit is: * AMPDU : 0 - 255 * AMSDU : 0 - 7 echo 64 > /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/ampdu_aggr_size echo 6 > /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/amsdu_aggr_size Signed-off-by: Ramya Gnanasekar --- drivers/net/wireless/ath/ath11k/debugfs.c | 86 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/debugfs.h | 2 + drivers/net/wireless/ath/ath11k/mac.c | 2 + drivers/net/wireless/ath/ath11k/wmi.c | 54 +++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 52 ++++++++++++++++++++ 5 files changed, 196 insertions(+) --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -250,6 +250,92 @@ void ath11k_debugfs_twt(struct ath11k_vi } #endif +static ssize_t ath11k_write_ampdu_aggr_size(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath11k_vif *arvif = file->private_data; + struct ath11k_base *ab = arvif->ar->ab; + unsigned int tx_aggr_size = 0; + int ret; + struct set_custom_aggr_size_params params = {0}; + + if (kstrtouint_from_user(ubuf, count, 0, &tx_aggr_size)) + return -EINVAL; + + if (tx_aggr_size > ATH11K_CONFIG_AGGR_MAX_AMPDU_SIZE) { + ath11k_warn(ab, "Valid AMPDU Aggregation Size is in the range 0-255"); + return -EINVAL; + } + + params.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU; + params.tx_aggr_size = tx_aggr_size; + params.rx_aggr_size_disable = true; + params.vdev_id = arvif->vdev_id; + + ret = ath11k_wmi_send_aggr_size_cmd(arvif->ar, ¶ms); + if (ret) + ath11k_warn(ab, "Failed to set ampdu config vdev_id %d" + "ret %d \n",params.vdev_id, ret); + + return ret ? ret : count; +} + +static const struct file_operations fops_ampdu_aggr_size = { + .write = ath11k_write_ampdu_aggr_size, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t ath11k_write_amsdu_aggr_size(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath11k_vif *arvif = file->private_data; + struct ath11k_base *ab = arvif->ar->ab; + unsigned int tx_aggr_size = 0; + int ret; + struct set_custom_aggr_size_params params = {0}; + + if (kstrtouint_from_user(ubuf, count, 0, &tx_aggr_size)) + return -EINVAL; + + if (tx_aggr_size > ATH11K_CONFIG_AGGR_MAX_AMSDU_SIZE) { + ath11k_warn(ab, "Valid AMSDU Aggregation size is in the range 0-7"); + return -EINVAL; + } + + params.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU; + params.tx_aggr_size = tx_aggr_size; + params.rx_aggr_size_disable = true; + params.vdev_id = arvif->vdev_id; + + ret = ath11k_wmi_send_aggr_size_cmd(arvif->ar, ¶ms); + if (ret) + ath11k_warn(ab, "Failed to set amsdu config vdev_id %d" + "ret %d \n",params.vdev_id, ret); + + return ret ? ret : count; +} + +static const struct file_operations fops_amsdu_aggr_size = { + .write = ath11k_write_amsdu_aggr_size, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +void ath11k_debug_aggr_size_config_init(struct ath11k_vif *arvif) +{ + debugfs_create_file("ampdu_aggr_size", 0644, + arvif->vif->debugfs_dir, arvif, + &fops_ampdu_aggr_size); + debugfs_create_file("amsdu_aggr_size", 0644, + arvif->vif->debugfs_dir, arvif, + &fops_amsdu_aggr_size); +} + static void ath11k_fw_stats_pdevs_free(struct list_head *head) { struct ath11k_fw_stats_pdev *i, *tmp; --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h @@ -155,6 +155,8 @@ static inline void ath11k_debugfs_twt(st } #endif +void ath11k_debug_aggr_size_config_init(struct ath11k_vif *arvif); + #ifdef CPTCFG_ATH11K_DEBUGFS int ath11k_debugfs_create(void); void ath11k_debugfs_destroy(void); --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5987,6 +5987,8 @@ static int ath11k_mac_op_add_interface(s goto err_peer_del; } + ath11k_debug_aggr_size_config_init(arvif); + mutex_unlock(&ar->conf_mutex); return ret; --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -3791,6 +3791,58 @@ int ath11k_wmi_send_bss_color_change_ena return ret; } +int ath11k_wmi_send_aggr_size_cmd(struct ath11k *ar, + struct set_custom_aggr_size_params *params) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_set_custom_aggr_size_params_cmd *cmd = NULL; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (void *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_VDEV_SET_CUSTOM_AGGR_SIZE_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + + cmd->vdev_id = params->vdev_id; + cmd->tx_aggr_size = params->tx_aggr_size; + cmd->rx_aggr_size = params->rx_aggr_size; + cmd->enable_bitmap = FIELD_PREP(WMI_VDEV_AGGR_AC, params->ac) | + FIELD_PREP(WMI_VDEV_AGGR_TYPE, params->aggr_type) | + FIELD_PREP(WMI_VDEV_TX_AGGR_SZ_DISABLE, + params->tx_aggr_size_disable) | + FIELD_PREP(WMI_VDEV_RX_AGGR_SZ_DISABLE, + params->rx_aggr_size_disable) | + FIELD_PREP(WMI_VDEV_AGGR_AC_ENABLE, + params->tx_ac_enable); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "WMI set aggr size vdev_id %d tx aggr size %d rx_aggr_size %d " + "access category %d aggr type %d tx_aggr_size_disable %d " + "rx_aggr_size_disable %d tx_ac_enable %d ", params->vdev_id, + params->tx_aggr_size, params->rx_aggr_size, params->ac, + params->aggr_type, params->tx_aggr_size_disable, + params->rx_aggr_size_disable, params->tx_ac_enable); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID); + + if (ret) { + ath11k_warn(ab, + "Failed to send WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id, struct sk_buff *tmpl) { --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5244,6 +5244,56 @@ struct wmi_pdev_obss_pd_bitmap_cmd { u32 bitmap[2]; } __packed; +#define WMI_VDEV_AGGR_AC GENMASK(2, 0) +#define WMI_VDEV_AGGR_TYPE GENMASK(3, 2) +#define WMI_VDEV_TX_AGGR_SZ_DISABLE GENMASK(4, 3) +#define WMI_VDEV_RX_AGGR_SZ_DISABLE GENMASK(5, 4) +#define WMI_VDEV_AGGR_AC_ENABLE GENMASK(6, 5) + +struct set_custom_aggr_size_params { + u32 vdev_id; + u32 tx_aggr_size; + u32 rx_aggr_size; + u32 ac; + u32 aggr_type; + u32 tx_aggr_size_disable; + u32 rx_aggr_size_disable; + u32 tx_ac_enable; +}; + +struct wmi_set_custom_aggr_size_params_cmd { + u32 tlv_header; /* TLV tag and len */ + u32 vdev_id; /* vdev id indicating to which aggregation size will be applied. */ + /* Size for tx aggregation for the vdev mentioned in vdev id + * (max MPDUs per A-MPDU or max MSDUs per A-MSDU based on aggr_type field) + */ + u32 tx_aggr_size; + + u32 rx_aggr_size; /* Size for rx aggregation (block ack window size limit)for vdev id */ + + /* To set TX aggregation size limits per VDEV per AC + * bits 1:0 (ac): + * Access Category (0x0=BE, 0x1=BK, 0x2=VI, 0x3=VO) + * If tx_ac_enable bit is not set, tx_aggr_size is applied + * for all Access Categories + * bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) + * bit 3 (tx_aggr_size_disable): If set tx_aggr_size is invalid + * bit 4 (rx_aggr_size_disable): If set rx_aggr_size is invalid + * bit 5 (tx_ac_enable): If set, above ac bitmap is valid. + * bits 31:6: Reserved bits. should be set to zero. + */ + u32 enable_bitmap; +} __packed; + +enum wmi_vdev_aggr_type { + WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU = 0, + WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU = 1, + WMI_VDEV_CUSTOM_AGGR_TYPE_MAX, +}; + +#define ATH11K_CONFIG_AGGR_MAX_AMPDU_SIZE 255 /* Maximum Frames for Custom AMPDU Size */ +#define ATH11K_CONFIG_AGGR_MAX_AMSDU_SIZE 7 /* Maximum Frames for Custom AMSDU Size */ + #define ATH11K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION 1 @@ -6007,5 +6057,7 @@ int ath11k_wmi_wow_enable(struct ath11k int ath11k_wmi_pdev_m3_dump_enable(struct ath11k *ar, u32 enable); int ath11k_wmi_pdev_get_tpc_table_cmdid(struct ath11k *ar); void ath11k_wmi_free_tpc_stats_mem(struct ath11k *ar); +int ath11k_wmi_send_aggr_size_cmd(struct ath11k *ar, + struct set_custom_aggr_size_params *params); #endif