summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorSarada Prasanna Garnayak <sgarna@codeaurora.org>2016-03-15 17:19:22 +0530
committerKyle Yan <kyan@codeaurora.org>2016-05-31 15:25:05 -0700
commitca8c9aac25b70091c5f193a960201bf6102f6363 (patch)
tree068f3e528eecaebd5f34e698e3d8414602a037b1 /drivers/net
parent1b18e29caa3f890a314414a50ee2c8cd5a9bb8ef (diff)
net: cnss: add bus bandwidth support for sdio wlan module
Add cnss sdio platform driver support to vote for bus bandwidth as per throughput requirement from wlan driver. The cnss sdio platform driver export bus bandwidth api for wlan host driver. CRs-Fixed: 990173 Change-Id: Ied2e5a78487b6f6076cd19f32c959a69050e055c Signed-off-by: Sarada Prasanna Garnayak <sgarna@codeaurora.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/cnss/cnss_sdio.c145
1 files changed, 142 insertions, 3 deletions
diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c
index f9402e7a165f..8510699b2702 100644
--- a/drivers/net/wireless/cnss/cnss_sdio.c
+++ b/drivers/net/wireless/cnss/cnss_sdio.c
@@ -29,6 +29,8 @@
#include <net/cnss.h>
#include <net/cnss_common.h>
#include <linux/pm_qos.h>
+#include <linux/msm-bus.h>
+#include <linux/msm-bus-board.h>
#define WLAN_VREG_NAME "vdd-wlan"
#define WLAN_VREG_DSRC_NAME "vdd-wlan-dsrc"
@@ -83,6 +85,12 @@ struct cnss_wlan_pinctrl_info {
struct pinctrl_state *active;
};
+struct cnss_sdio_bus_bandwidth {
+ struct msm_bus_scale_pdata *bus_scale_table;
+ u32 bus_client;
+ int current_bandwidth_vote;
+};
+
static struct cnss_sdio_data {
struct cnss_sdio_regulator regulator;
struct platform_device *pdev;
@@ -90,6 +98,7 @@ static struct cnss_sdio_data {
struct cnss_ssr_info ssr_info;
struct pm_qos_request qos_request;
struct cnss_wlan_pinctrl_info pinctrl_info;
+ struct cnss_sdio_bus_bandwidth bus_bandwidth;
} *cnss_pdata;
#define WLAN_RECOVERY_DELAY 1
@@ -150,7 +159,37 @@ EXPORT_SYMBOL(cnss_sdio_request_pm_qos_type);
int cnss_sdio_request_bus_bandwidth(int bandwidth)
{
- return 0;
+ int ret;
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
+
+ if (!cnss_pdata)
+ return -ENODEV;
+
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ if (!bus_bandwidth->bus_client)
+ return -ENODEV;
+
+ switch (bandwidth) {
+ case CNSS_BUS_WIDTH_NONE:
+ case CNSS_BUS_WIDTH_LOW:
+ case CNSS_BUS_WIDTH_MEDIUM:
+ case CNSS_BUS_WIDTH_HIGH:
+ ret = msm_bus_scale_client_update_request(
+ bus_bandwidth->bus_client, bandwidth);
+ if (!ret) {
+ bus_bandwidth->current_bandwidth_vote = bandwidth;
+ } else {
+ pr_debug(
+ "%s: could not set bus bandwidth %d, ret = %d\n",
+ __func__, bandwidth, ret);
+ }
+ break;
+ default:
+ pr_debug("%s: Invalid request %d", __func__, bandwidth);
+ ret = -EINVAL;
+ }
+
+ return ret;
}
void cnss_sdio_request_pm_qos(u32 qos_val)
@@ -177,7 +216,37 @@ EXPORT_SYMBOL(cnss_sdio_remove_pm_qos);
int cnss_request_bus_bandwidth(int bandwidth)
{
- return 0;
+ int ret;
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
+
+ if (!cnss_pdata)
+ return -ENODEV;
+
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ if (!bus_bandwidth->bus_client)
+ return -ENODEV;
+
+ switch (bandwidth) {
+ case CNSS_BUS_WIDTH_NONE:
+ case CNSS_BUS_WIDTH_LOW:
+ case CNSS_BUS_WIDTH_MEDIUM:
+ case CNSS_BUS_WIDTH_HIGH:
+ ret = msm_bus_scale_client_update_request(
+ bus_bandwidth->bus_client, bandwidth);
+ if (!ret) {
+ bus_bandwidth->current_bandwidth_vote = bandwidth;
+ } else {
+ pr_debug(
+ "%s: could not set bus bandwidth %d, ret = %d\n",
+ __func__, bandwidth, ret);
+ }
+ break;
+ default:
+ pr_debug("%s: Invalid request %d", __func__, bandwidth);
+ ret = -EINVAL;
+ }
+
+ return ret;
}
EXPORT_SYMBOL(cnss_request_bus_bandwidth);
@@ -616,11 +685,18 @@ static void cnss_sdio_wlan_removed(struct sdio_func *func)
static int cnss_sdio_wlan_suspend(struct device *dev)
{
struct cnss_sdio_wlan_driver *wdrv;
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
int error = 0;
if (!cnss_pdata)
return -ENODEV;
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ if (bus_bandwidth->bus_client) {
+ msm_bus_scale_client_update_request(
+ bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE);
+ }
+
wdrv = cnss_pdata->cnss_sdio_info.wdrv;
if (!wdrv) {
/* This can happen when no wlan driver loaded (no register to
@@ -641,11 +717,19 @@ static int cnss_sdio_wlan_suspend(struct device *dev)
static int cnss_sdio_wlan_resume(struct device *dev)
{
struct cnss_sdio_wlan_driver *wdrv;
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
int error = 0;
if (!cnss_pdata)
return -ENODEV;
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ if (bus_bandwidth->bus_client) {
+ msm_bus_scale_client_update_request(
+ bus_bandwidth->bus_client,
+ bus_bandwidth->current_bandwidth_vote);
+ }
+
wdrv = cnss_pdata->cnss_sdio_info.wdrv;
if (!wdrv) {
/* This can happen when no wlan driver loaded (no register to
@@ -746,10 +830,17 @@ void
cnss_sdio_wlan_unregister_driver(struct cnss_sdio_wlan_driver *driver)
{
struct cnss_sdio_info *cnss_info;
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
if (!cnss_pdata)
return;
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ if (bus_bandwidth->bus_client) {
+ msm_bus_scale_client_update_request(
+ bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE);
+ }
+
cnss_info = &cnss_pdata->cnss_sdio_info;
if (!cnss_info->wdrv) {
pr_err("%s: driver not registered\n", __func__);
@@ -827,6 +918,18 @@ static void cnss_sdio_wlan_exit(void)
sdio_unregister_driver(&cnss_ar6k_driver);
}
+static void cnss_sdio_deinit_bus_bandwidth(void)
+{
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
+
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ if (bus_bandwidth->bus_client) {
+ msm_bus_scale_client_update_request(
+ bus_bandwidth->bus_client, CNSS_BUS_WIDTH_NONE);
+ msm_bus_scale_unregister_client(bus_bandwidth->bus_client);
+ }
+}
+
static int cnss_sdio_configure_wlan_enable_regulator(void)
{
int error;
@@ -1022,6 +1125,29 @@ release_pinctrl:
return ret;
}
+static int cnss_sdio_init_bus_bandwidth(void)
+{
+ int ret = 0;
+ struct cnss_sdio_bus_bandwidth *bus_bandwidth;
+ struct device *dev = &cnss_pdata->pdev->dev;
+
+ bus_bandwidth = &cnss_pdata->bus_bandwidth;
+ bus_bandwidth->bus_scale_table = msm_bus_cl_get_pdata(cnss_pdata->pdev);
+ if (!bus_bandwidth->bus_scale_table) {
+ dev_err(dev, "Failed to get the bus scale platform data\n");
+ ret = -EINVAL;
+ }
+
+ bus_bandwidth->bus_client = msm_bus_scale_register_client(
+ bus_bandwidth->bus_scale_table);
+ if (!bus_bandwidth->bus_client) {
+ dev_err(dev, "Failed to register with bus_scale client\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int cnss_sdio_probe(struct platform_device *pdev)
{
int error;
@@ -1097,8 +1223,20 @@ static int cnss_sdio_probe(struct platform_device *pdev)
goto err_subsys_init;
}
+ if (of_property_read_bool(
+ pdev->dev.of_node, "qcom,cnss-enable-bus-bandwidth")) {
+ error = cnss_sdio_init_bus_bandwidth();
+ if (error) {
+ dev_err(&pdev->dev, "Failed to init bus bandwidth\n");
+ goto err_bus_bandwidth_init;
+ }
+ }
+
dev_info(&pdev->dev, "CNSS SDIO Driver registered");
return 0;
+
+err_bus_bandwidth_init:
+ cnss_subsys_exit();
err_subsys_init:
cnss_ramdump_cleanup();
err_ramdump_create:
@@ -1117,11 +1255,12 @@ static int cnss_sdio_remove(struct platform_device *pdev)
if (!cnss_pdata)
return -ENODEV;
+ cnss_sdio_deinit_bus_bandwidth();
cnss_sdio_wlan_exit();
-
cnss_subsys_exit();
cnss_ramdump_cleanup();
cnss_sdio_release_resource();
+
return 0;
}