From patchwork Thu Mar 12 21:47:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Greear X-Patchwork-Id: 5999661 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 255739F318 for ; Thu, 12 Mar 2015 21:47:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C448202B8 for ; Thu, 12 Mar 2015 21:47:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0715D201F4 for ; Thu, 12 Mar 2015 21:47:43 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YWAx4-0005LB-Vm; Thu, 12 Mar 2015 21:47:34 +0000 Received: from mail2.candelatech.com ([208.74.158.173]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YWAx3-0005IC-77 for ath10k@lists.infradead.org; Thu, 12 Mar 2015 21:47:34 +0000 Received: from ben-dt2.candelatech.com. (unknown [50.251.239.81]) by mail2.candelatech.com (Postfix) with ESMTP id E146640BC03; Thu, 12 Mar 2015 14:47:10 -0700 (PDT) From: greearb@candelatech.com To: ath10k@lists.infradead.org Subject: [RFC] ath10k: Allow setting bcast, mcast, mgt fixed tx rates. Date: Thu, 12 Mar 2015 14:47:07 -0700 Message-Id: <1426196827-15802-1-git-send-email-greearb@candelatech.com> X-Mailer: git-send-email 1.7.11.7 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150312_144733_314969_C5B5D1FF X-CRM114-Status: GOOD ( 16.30 ) X-Spam-Score: -0.0 (/) Cc: Ben Greear , linux-wireless@vger.kernel.org X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Ben Greear The default behaviour when setting a fixed transmit rate in ath10k is to only set the 'ucast' rate. This does not affect beacons, multicast, or broadcast traffic. In order to allow a back-door way to set these other types of traffic as well, provide a debugfs file that can set the traffic type. Then, use can use the normal 'iw' commands to set the rate to the desired value. Upstream firmware *should* support all of this, but at least 10.1 does NOT have support for the WMI_10X_VDEV_PARAM_MGMT_RATE parameter. I added this to the CT firmware so it works there. Possibly other upstream firmware have fixed this as well. Signed-off-by: Ben Greear --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 102 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/mac.c | 22 +++++-- 3 files changed, 119 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 69fa7b4..f54a4bc 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -477,6 +477,7 @@ struct ath10k { u32 ht_cap_info; u32 vht_cap_info; u32 num_rf_chains; + u32 set_rate_type; /* override for set-rate behaviour */ DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index f4c60d6..08d0330 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -893,6 +893,105 @@ static const struct file_operations fops_simulate_fw_crash = { .llseek = default_llseek, }; +static ssize_t ath10k_read_set_rates(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + const char buf[] = + "To set unicast, beacon/mgt, multicast, and broadcast,\n" + "select a type below and then use 'iw' as normal to set\n" + "the desired rate.\n" + "beacon # Beacons and management frames\n" + "bcast # Broadcast frames\n" + "mcast # Multicast frames\n" + "ucast # Unicast frames (normal traffic, default)\n"; + + char tmpbuf[strlen(buf) + 80]; + char* str = "ucast"; + + if (ar->set_rate_type == ar->wmi.vdev_param->mgmt_rate) { + str = "beacon"; + } + else if (ar->set_rate_type == ar->wmi.vdev_param->bcast_data_rate) { + str = "bcast"; + } + else if (ar->set_rate_type == ar->wmi.vdev_param->mcast_data_rate) { + str = "mcast"; + } + sprintf(tmpbuf, "%sCurrent: %s\n", buf, str); + + return simple_read_from_buffer(user_buf, count, ppos, tmpbuf, strlen(tmpbuf)); +} + +/* Set the rates for specific types of traffic. + */ +static ssize_t ath10k_write_set_rates(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + char buf[32]; + int ret; + + mutex_lock(&ar->conf_mutex); + + memset(buf, 0, sizeof(buf)); + + simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); + + /* make sure that buf is null terminated */ + buf[sizeof(buf) - 1] = 0; + + /* drop the possible '\n' from the end */ + if (buf[count - 1] == '\n') + buf[count - 1] = 0; + + /* Ignore empty lines, 'echo' appends them sometimes at least. */ + if (buf[0] == 0) { + ret = count; + goto exit; + } + + if (ar->state != ATH10K_STATE_ON && + ar->state != ATH10K_STATE_RESTARTED) { + ret = -ENETDOWN; + goto exit; + } + + if (strncmp(buf, "beacon", strlen("beacon")) == 0) { + ar->set_rate_type = ar->wmi.vdev_param->mgmt_rate; + } + else if (strncmp(buf, "bcast", strlen("bcast")) == 0) { + ar->set_rate_type = ar->wmi.vdev_param->bcast_data_rate; + } + else if (strncmp(buf, "mcast", strlen("mcast")) == 0) { + ar->set_rate_type = ar->wmi.vdev_param->mcast_data_rate; + } + else if (strncmp(buf, "ucast", strlen("ucast")) == 0) { + ar->set_rate_type = 0; + } + else { + ath10k_warn(ar, "set-rate, invalid rate type: %s count: %d %02hx:%02hx:%02hx:%02hx\n", + buf, (int)count, (int)(buf[0]), (int)(buf[1]), (int)(buf[2]), (int)(buf[3])); + ret = -EINVAL; + goto exit; + } + ret = count; + +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static const struct file_operations fops_set_rates = { + .read = ath10k_read_set_rates, + .write = ath10k_write_set_rates, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1733,6 +1832,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_wmi_services); + debugfs_create_file("set_rates", S_IRUSR, ar->debug.debugfs_phy, + ar, &fops_set_rates); + debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ec74429..0718d4a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4481,11 +4481,12 @@ static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, mutex_lock(&ar->conf_mutex); - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac set fixed rate, current: rt: %i nss: %i sgi: %i new: rt: %i nss: %i sgi: %i\n", + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac set fixed rate, current: rt: %i nss: %i sgi: %i new: rt: %i nss: %i sgi: %i set-rate-type: %d\n", (int)(arvif->fixed_rate), (int)(arvif->fixed_nss), (int)(arvif->force_sgi), - (int)(fixed_rate), (int)(fixed_nss), (int)(force_sgi)); + (int)(fixed_rate), (int)(fixed_nss), (int)(force_sgi), ar->set_rate_type); - if (arvif->fixed_rate == fixed_rate && + if (ar->set_rate_type == 0 && + arvif->fixed_rate == fixed_rate && arvif->fixed_nss == fixed_nss && arvif->force_sgi == force_sgi) goto exit; @@ -4496,16 +4497,25 @@ static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, if (force_sgi) ath10k_dbg(ar, ATH10K_DBG_MAC, "mac force sgi\n"); - vdev_param = ar->wmi.vdev_param->fixed_rate; + if (ar->set_rate_type) + vdev_param = ar->set_rate_type; + else + 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(ar, "failed to set fixed rate param 0x%02x: %d\n", - fixed_rate, ret); + ath10k_warn(ar, "failed to set fixed rate (0x%x) param 0x%02x: %d\n", + vdev_param, fixed_rate, ret); ret = -EINVAL; goto exit; } + /* If we are setting one of the specialized rates (mgmt, ucast, bcast) + * then we do not need to set the other values, so skip to exit. + */ + if (ar->set_rate_type != 0) + goto exit; + arvif->fixed_rate = fixed_rate; vdev_param = ar->wmi.vdev_param->nss;