Re: [PATCH 11/12] ath10k: Add wlan mode on/off qmi message

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:41 PDT 2018, Govind Singh wrote:

> Add qmi message required for enabling and disabling
> target to qmi server running in Q6.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 226 
> +-
>  drivers/net/wireless/ath/ath10k/qmi.h |  62 ++
>  2 files changed, 264 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index f23d0fe..331a528 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -35,7 +35,30 @@
>  #define WLFW_CLIENT_ID   0x4b4e454c
>  #define WLFW_TIMEOUT 500
>  
> -static struct ath10k_qmi *qmi;
> +static struct ath10k_qmi {
> + struct platform_device *pdev;
> + struct qmi_handle qmi_hdl;
> + struct sockaddr_qrtr sq;
> + bool fw_ready;
> + bool msa_ready;
> + struct work_struct work_svc_arrive;
> + struct work_struct work_svc_exit;
> + struct work_struct work_msa_ready;
> + struct workqueue_struct *event_wq;
> + spinlock_t event_lock; /* spinlock for fw ready status*/
> + u32 nr_mem_region;
> + struct ath10k_msa_mem_region_info
> + mem_region[MAX_NUM_MEMORY_REGIONS];
> + phys_addr_t msa_pa;
> + u32 msa_mem_size;
> + void *msa_va;
> + struct ath10k_qmi_chip_info chip_info;
> + struct ath10k_qmi_board_info board_info;
> + struct ath10k_qmi_soc_info soc_info;
> + struct ath10k_qmi_fw_version_info fw_version_info;
> + char fw_build_id[MAX_BUILD_ID_LEN + 1];
> + struct ath10k_qmi_cal_data cal_data[MAX_NUM_CAL_V01];
> +} *qmi;

Don't end your patch series with a move of this structure, fold it back
into each patch.

>  
>  static int
>  ath10k_qmi_map_msa_permissions(struct ath10k_msa_mem_region_info *mem_region)
> @@ -444,6 +467,207 @@ int ath10k_qmi_send_cal_report_req(struct ath10k_qmi 
> *qmi)
>   return ret;
>  }
>  
> +static int
> +ath10k_qmi_mode_send_sync_msg(enum wlfw_driver_mode_enum_v01 mode)
> +{
> + struct wlfw_wlan_mode_resp_msg_v01 *resp;

4 bytes

> + struct wlfw_wlan_mode_req_msg_v01 *req;

6 bytes, use the stack.

> + struct qmi_txn txn;
> + int ret;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + ret = qmi_txn_init(>qmi_hdl, ,
> +wlfw_wlan_mode_resp_msg_v01_ei,
> +resp);
> + if (ret < 0) {
> + pr_err("fail to init txn for mode req %d ret %d\n", mode, ret);
> + goto out;
> + }
> +
> + req->mode = mode;
> + req->hw_debug_valid = 1;
> + req->hw_debug = 0;
> +
> + ret = qmi_send_request(>qmi_hdl, NULL, ,
> +QMI_WLFW_WLAN_MODE_REQ_V01,
> +WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN,
> +wlfw_wlan_mode_req_msg_v01_ei, req);
> + if (ret < 0) {
> + qmi_txn_cancel();
> + pr_err("send mode req failed, mode: %d ret: %d\n",
> +mode, ret);
> + goto out;
> + }
> +
> + ret = qmi_txn_wait(, WLFW_TIMEOUT * HZ);
> + if (ret < 0)
> + goto out;
> +
> + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
> + pr_err("qmi mode request rejected:");
> + pr_err("mode:%d result:%d error:%d\n",
> +mode, resp->resp.result, resp->resp.error);
> + ret = resp->resp.result;
> + goto out;
> + }
> +
> + pr_debug("wlan Mode request completed, mode: %d\n", mode);
> + kfree(resp);
> + kfree(req);
> + return 0;
> +
> +out:
> + kfree(resp);
> + kfree(req);
> + return ret;
> +}
> +
> +static int
> +ath10k_qmi_cfg_send_sync_msg(struct wlfw_wlan_cfg_req_msg_v01 *data)
> +{
> + struct wlfw_wlan_cfg_resp_msg_v01 *resp;

4 bytes, use stack

> + struct wlfw_wlan_cfg_req_msg_v01 *req;

This is larger, use heap

> + struct qmi_txn txn;
> + int ret;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + ret = qmi_txn_init(>qmi_hdl, ,
> +wlfw_wlan_cfg_resp_msg_v01_ei,
> +resp);
> + if (ret < 0) {
> + pr_err("fail to init txn for config req %d\n", ret);
> + goto out;
> + }
> +
> + memcpy(req, data, sizeof(*req));

I see no reason to create a local copy of this struct, just pass data to
qmi_send_request.

> +
> + ret = qmi_send_request(>qmi_hdl, NULL, ,
> +

Re: [PATCH 10/12] ath10k: add bdf/cal indication support

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:41 PDT 2018, Govind Singh wrote:

> Add support for bdf download and cold boot
> calibration trigger qmi message support.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 195 
> ++
>  drivers/net/wireless/ath/ath10k/qmi.h |  10 ++
>  2 files changed, 205 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index a33681d..f23d0fe 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -28,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "qmi.h"
>  #include "qmi_svc_v01.h"
>  
> @@ -270,6 +271,179 @@ static int ath10k_qmi_msa_ready_send_sync_msg(struct 
> ath10k_qmi *qmi)
>   return ret;
>  }
>  
> +int ath10k_qmi_bdf_dnld_send_sync(struct ath10k_qmi *qmi)
> +{
> + struct wlfw_bdf_download_resp_msg_v01 *resp;

4 bytes, use stack.

> + struct wlfw_bdf_download_req_msg_v01 *req;

And this is approx 7kB, so that makes sense to allocate on the heap.

> + const struct firmware *fw_entry;
> + unsigned int remaining;
> + struct qmi_txn txn;
> + const u8 *temp;
> + int ret;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + ret = request_firmware(_entry, BDF_FILE_NAME, >pdev->dev);
> + if (ret < 0) {
> + pr_err("fail to load bdf: %s\n", BDF_FILE_NAME);
> + goto err_req_fw;
> + }
> +
> + temp = fw_entry->data;
> + remaining = fw_entry->size;
> +
> + pr_debug("downloading bdf: %s, size: %u\n",
> +  BDF_FILE_NAME, remaining);
> +
> + while (remaining) {
> + req->valid = 1;
> + req->file_id_valid = 1;
> + req->file_id = 0;
> + req->total_size_valid = 1;
> + req->total_size = fw_entry->size;
> + req->seg_id_valid = 1;
> + req->data_valid = 1;
> + req->end_valid = 1;
> +
> + if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
> + req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
> + } else {
> + req->data_len = remaining;
> + req->end = 1;
> + }
> +
> + memcpy(req->data, temp, req->data_len);
> +
> + ret = qmi_txn_init(>qmi_hdl, ,
> +wlfw_bdf_download_resp_msg_v01_ei,
> +resp);
> + if (ret < 0) {
> + pr_err("fail to init txn for bdf download %d\n", ret);
> + goto out;
> + }
> +
> + ret =

Don't indent wrapped lines like that.

> + qmi_send_request(>qmi_hdl, NULL, ,
> +  QMI_WLFW_BDF_DOWNLOAD_REQ_V01,
> +  WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
> +  wlfw_bdf_download_req_msg_v01_ei, req);
> + if (ret < 0) {
> + qmi_txn_cancel();
> + goto err_send;
> + }
> +
> + ret = qmi_txn_wait(, WLFW_TIMEOUT * HZ);
> +
> + if (ret < 0)
> + goto err_send;
> +
> + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
> + pr_err("bdf download failed, res:%d, err:%d\n",
> +resp->resp.result, resp->resp.error);
> + ret = resp->resp.result;
> + goto err_send;
> + }
> +
> + remaining -= req->data_len;
> + temp += req->data_len;
> + req->seg_id++;
> + }
> +
> + pr_debug("bdf download request completed\n");

You're leaking fw_entry, consider merging the two exit paths.

> +
> + kfree(resp);
> + kfree(req);
> + return 0;
> +
> +err_send:
> + release_firmware(fw_entry);
> +
> +err_req_fw:
> + kfree(req);
> + kfree(resp);
> +
> +out:
> + return ret;
> +}
> +
> +int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)
> +{
> + struct wlfw_cal_report_resp_msg_v01 *resp;

4 bytes

> + struct wlfw_cal_report_req_msg_v01 *req;

26 bytes, use the stack for both

> + struct qmi_txn txn;
> + int i, j = 0;
> + int ret;
> +
[..]
>  static struct qmi_msg_handler qmi_msg_handler[] = {
> @@ -599,6 +774,24 @@ static void ath10k_qmi_event_server_exit(struct 
> work_struct *work)
>   pr_info("wlan fw service disconnected\n");
>  }
>  
> +static void ath10k_qmi_event_msa_ready(struct work_struct *work)
> +{
> + struct ath10k_qmi *qmi = container_of(work, struct ath10k_qmi,
> +   work_msa_ready);
> + int ret;
> +
> + ret = 

Re: [PATCH 09/12] ath10k: Add QMI HOST CAP request support

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:41 PDT 2018, Govind Singh wrote:

> Add support for host capablity request
> qmi message for wcn3990 target.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 65 
> +++
>  1 file changed, 65 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index 65a43af..a33681d 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -357,6 +357,67 @@ static int ath10k_qmi_cap_send_sync_msg(struct 
> ath10k_qmi *qmi)
>   return ret;
>  }
>  
> +static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
> +{
> + struct wlfw_host_cap_resp_msg_v01 *resp;

This is 4 bytes,

> + struct wlfw_host_cap_req_msg_v01 *req;

and this is 2 bytes, use the stack.

> + struct qmi_txn txn;
> + int ret;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + req->daemon_support_valid = 1;
> + req->daemon_support = 0;
> +
> + pr_debug("daemon_support is %d\n", req->daemon_support);

This print seems unnecessary.

> +
> + ret = qmi_txn_init(>qmi_hdl, ,
> +wlfw_host_cap_resp_msg_v01_ei, resp);
> + if (ret < 0) {
> + pr_err("Fail to init txn for Capability resp %d\n", ret);

Same comments the rest of the function as given on previous patches.

> + goto out;
> + }

Regards,
Bjorn


Re: [PATCH 08/12] ath10k: Add QMI CAP request support

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:40 PDT 2018, Govind Singh wrote:

> Add support for target capablity request
> qmi message for wcn3990 target.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 91 
> +++
>  drivers/net/wireless/ath/ath10k/qmi.h | 25 ++
>  2 files changed, 116 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index 763b812..65a43af 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -270,6 +270,93 @@ static int ath10k_qmi_msa_ready_send_sync_msg(struct 
> ath10k_qmi *qmi)
>   return ret;
>  }
>  
> +static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
> +{
> + struct wlfw_cap_resp_msg_v01 *resp;

I think this is 207 bytes, so it makes sense to allocate this on the
heap.

> + struct wlfw_cap_req_msg_v01 *req;

But this is 1 bytes, so keep it on the stack.

> + struct qmi_txn txn;
> + int ret;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + ret = qmi_txn_init(>qmi_hdl, , wlfw_cap_resp_msg_v01_ei, resp);
> + if (ret < 0) {
> + pr_err("fail to init txn for capability resp %d\n", ret);

Same comments as in previous patches.

> + goto out;
> + }
> +
> + ret = qmi_send_request(>qmi_hdl, NULL, ,
> +QMI_WLFW_CAP_REQ_V01,
> +WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN,
> +wlfw_cap_req_msg_v01_ei, req);
> + if (ret < 0) {
> + qmi_txn_cancel();
> + pr_err("fail to send capability req %d\n", ret);
> + goto out;
> + }
> +
> + ret = qmi_txn_wait(, WLFW_TIMEOUT * HZ);
> + if (ret < 0)
> + goto out;
> +
> + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
> + pr_err("qmi capability request rejected, result:%d error:%d\n",
> +resp->resp.result, resp->resp.error);
> + ret = -resp->resp.result;
> + goto out;
> + }
> +
> + if (resp->chip_info_valid) {
> + qmi->chip_info.chip_id = resp->chip_info.chip_id;
> + qmi->chip_info.chip_family = resp->chip_info.chip_family;
> + }
> +
> + if (resp->board_info_valid)
> + qmi->board_info.board_id = resp->board_info.board_id;
> + else
> + qmi->board_info.board_id = 0xFF;
> +
> + if (resp->soc_info_valid)
> + qmi->soc_info.soc_id = resp->soc_info.soc_id;
> +
> + if (resp->fw_version_info_valid) {
> + qmi->fw_version_info.fw_version =
> + resp->fw_version_info.fw_version;
> + strlcpy(qmi->fw_version_info.fw_build_timestamp,
> + resp->fw_version_info.fw_build_timestamp,
> + MAX_TIMESTAMP_LEN + 1);

Use sizeof(qmi->fw_version_info.fw_build_timestamp) to remove the risk
of them getting out of sync.

> + }
> +
> + if (resp->fw_build_id_valid)
> + strlcpy(qmi->fw_build_id, resp->fw_build_id,
> + MAX_BUILD_ID_LEN + 1);
> +
> + pr_debug("chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 
> 0x%x, fw_version: 0x%x, fw_build_timestamp: %s, fw_build_id: %s",
> +  qmi->chip_info.chip_id, qmi->chip_info.chip_family,
> +  qmi->board_info.board_id, qmi->soc_info.soc_id,
> +  qmi->fw_version_info.fw_version,
> +  qmi->fw_version_info.fw_build_timestamp,
> +  qmi->fw_build_id);

Use dev_dbg(), but perhaps this could even be a dev_info()?

> +
> + pr_debug("target cap request completed\n");
> + kfree(resp);
> + kfree(req);
> +
> + return 0;
> +out:
> + kfree(resp);
> + kfree(req);
> + return ret;
> +}
> +
>  static int
>  ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
>  {
> @@ -425,6 +512,10 @@ static void ath10k_qmi_event_server_arrive(struct 
> work_struct *work)
>   if (ret)
>   goto err_setup_msa;
>  
> + ret = ath10k_qmi_cap_send_sync_msg(qmi);
> + if (ret)
> + goto err_setup_msa;
> +
>   return;
>  
>  err_setup_msa:
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.h 
> b/drivers/net/wireless/ath/ath10k/qmi.h
> index 47af020..09d20a0 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.h
> +++ b/drivers/net/wireless/ath/ath10k/qmi.h
> @@ -17,6 +17,8 @@
>  #define _QMI_H_
>  
>  #define MAX_NUM_MEMORY_REGIONS   2
> +#define MAX_TIMESTAMP_LEN32
> +#define MAX_BUILD_ID_LEN 128
>  
>  enum ath10k_qmi_driver_event_type {
>   ATH10K_QMI_EVENT_SERVER_ARRIVE,
> @@ -31,6 +33,24 @@ struct 

Re: [PATCH 07/12] ath10k: Add MSA handshake QMI mgs support

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:40 PDT 2018, Govind Singh wrote:

> HOST allocates 2mb of region for modem and WCN3990
> secure access and provides the address and access
> control to target for secure access.
> Add MSA handshake request/response messages.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 288 
> +-
>  drivers/net/wireless/ath/ath10k/qmi.h |  14 ++
>  2 files changed, 300 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index bc80b8f..763b812 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -26,6 +26,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include "qmi.h"
>  #include "qmi_svc_v01.h"
>  
> @@ -35,6 +37,240 @@
>  static struct ath10k_qmi *qmi;
>  
>  static int
> +ath10k_qmi_map_msa_permissions(struct ath10k_msa_mem_region_info *mem_region)
> +{
> + struct qcom_scm_vmperm dst_perms[3];
> + unsigned int src_perms;
> + phys_addr_t addr;
> + u32 perm_count;
> + u32 size;
> + int ret;
> +
> + addr = mem_region->reg_addr;
> + size = mem_region->size;

Skip the local variables.

> +
> + src_perms = BIT(QCOM_SCM_VMID_HLOS);
> +
> + dst_perms[0].vmid = QCOM_SCM_VMID_MSS_MSA;
> + dst_perms[0].perm = QCOM_SCM_PERM_RW;
> + dst_perms[1].vmid = QCOM_SCM_VMID_WLAN;
> + dst_perms[1].perm = QCOM_SCM_PERM_RW;
> +
> + if (!mem_region->secure_flag) {

So with secure_flag equal to 0 we give less subsystems access to the
data? Is this logic inverted?

> + dst_perms[2].vmid = QCOM_SCM_VMID_WLAN_CE;
> + dst_perms[2].perm = QCOM_SCM_PERM_RW;
> + perm_count = 3;
> + } else {
> + dst_perms[2].vmid = 0;
> + dst_perms[2].perm = 0;
> + perm_count = 2;

If you set perm_count to 2 you don't need to clear vmid and perm of
dst_perms[2].

> + }
> +
> + ret = qcom_scm_assign_mem(addr, size, _perms,
> +   dst_perms, perm_count);
> + if (ret < 0)
> + pr_err("msa map permission failed=%d\n", ret);

Use dev_err()

> +
> + return ret;
> +}
> +
> +static int
> +ath10k_qmi_unmap_msa_permissions(struct ath10k_msa_mem_region_info 
> *mem_region)
> +{
> + struct qcom_scm_vmperm dst_perms;
> + unsigned int src_perms;
> + phys_addr_t addr;
> + u32 size;
> + int ret;
> +
> + addr = mem_region->reg_addr;
> + size = mem_region->size;

Skip the local variables.

> +
> + src_perms = BIT(QCOM_SCM_VMID_MSS_MSA) | BIT(QCOM_SCM_VMID_WLAN);
> +
> + if (!mem_region->secure_flag)
> + src_perms |= BIT(QCOM_SCM_VMID_WLAN_CE);
> +
> + dst_perms.vmid = QCOM_SCM_VMID_HLOS;
> + dst_perms.perm = QCOM_SCM_PERM_RW;
> +
> + ret = qcom_scm_assign_mem(addr, size, _perms, _perms, 1);
> + if (ret < 0)
> + pr_err("msa unmap permission failed=%d\n", ret);
> +
> + return ret;
> +}
> +
> +static int ath10k_qmi_setup_msa_permissions(struct ath10k_qmi *qmi)
> +{
> + int ret;
> + int i;
> +
> + for (i = 0; i < qmi->nr_mem_region; i++) {
> + ret = ath10k_qmi_map_msa_permissions(>mem_region[i]);
> + if (ret)
> + goto err_unmap;
> + }
> +
> + return 0;
> +
> +err_unmap:
> + for (i--; i >= 0; i--)
> + ath10k_qmi_unmap_msa_permissions(>mem_region[i]);
> + return ret;
> +}
> +
> +static void ath10k_qmi_remove_msa_permissions(struct ath10k_qmi *qmi)
> +{
> + int i;
> +
> + for (i = 0; i < qmi->nr_mem_region; i++)
> + ath10k_qmi_unmap_msa_permissions(>mem_region[i]);
> +}
> +
> +static int
> + ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
> +{
> + struct wlfw_msa_info_resp_msg_v01 *resp;

This is 40 bytes,

> + struct wlfw_msa_info_req_msg_v01 *req;

This is 6 bytes.

So just put them on the stack and skip the memory management.

> + struct qmi_txn txn;
> + int ret;
> + int i;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + req->msa_addr = qmi->msa_pa;
> + req->size = qmi->msa_mem_size;
> +
> + ret = qmi_txn_init(>qmi_hdl, ,
> +wlfw_msa_info_resp_msg_v01_ei, resp);
> + if (ret < 0) {
> + pr_err("fail to init txn for MSA mem info resp %d\n",
> +ret);

Unless we have 2 billion outstanding transactions "ret" is going to be
ENOMEM here, in which case there is already a printout telling you about
the problem.

> + goto out;
> + }
> +
> + ret = qmi_send_request(>qmi_hdl, NULL, ,
> +QMI_WLFW_MSA_INFO_REQ_V01,
> +  

Re: [PATCH 05/12] ath10k: Add support of QMI indication message

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:40 PDT 2018, Govind Singh wrote:

> Add support of indication qmi message to communicate
> with wlan qmi server. Indication message request
> describes client capability and in response client
> gets the state of wlan qmi service.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 71 
> ++-
>  1 file changed, 70 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index 3a7fcc6..bc80b8f 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -29,8 +29,76 @@
>  #include "qmi.h"
>  #include "qmi_svc_v01.h"
>  
> +#define WLFW_CLIENT_ID   0x4b4e454c
> +#define WLFW_TIMEOUT 500
> +
>  static struct ath10k_qmi *qmi;
>  
> +static int
> +ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
> +{
> + struct wlfw_ind_register_resp_msg_v01 *resp;

struct wlfw_ind_register_resp_msg_v01 is 12 bytes,

> + struct wlfw_ind_register_req_msg_v01 *req;

and struct wlfw_ind_register_req_msg_v01 is 30 bytes.

So you can easily just store them on the stack, saving yourself the
trouble of allocating and freeing them below.

> + struct qmi_txn txn;
> + int ret;
> +
> + req = kzalloc(sizeof(*req), GFP_KERNEL);
> + if (!req)
> + return -ENOMEM;
> +
> + resp = kzalloc(sizeof(*resp), GFP_KERNEL);
> + if (!resp) {
> + kfree(req);
> + return -ENOMEM;
> + }
> +
> + req->client_id_valid = 1;
> + req->client_id = WLFW_CLIENT_ID;
> + req->fw_ready_enable_valid = 1;
> + req->fw_ready_enable = 1;
> + req->msa_ready_enable_valid = 1;
> + req->msa_ready_enable = 1;
> +
> + ret = qmi_txn_init(>qmi_hdl, ,
> +wlfw_ind_register_resp_msg_v01_ei, resp);
> + if (ret < 0) {
> + pr_err("fail to init txn for ind register resp %d\n",
> +ret);

qmi_txn_init() typically doesn't fail, but when it does it will print an
error message. So you can omit yours.

> + goto out;
> + }
> +
> + ret = qmi_send_request(>qmi_hdl, NULL, ,
> +QMI_WLFW_IND_REGISTER_REQ_V01,
> +WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN,
> +wlfw_ind_register_req_msg_v01_ei, req);
> + if (ret < 0) {
> + qmi_txn_cancel();
> + pr_err("fail to send ind register req %d\n", ret);

qmi_send_request() does print error messages when things go wrong, if
you want to add context to this use dev_err().

> + goto out;
> + }
> +
> + ret = qmi_txn_wait(, WLFW_TIMEOUT * HZ);
> + if (ret < 0)
> + goto out;
> +
> + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
> + pr_err("qmi indication register request rejected:");
> + pr_err("resut:%d error:%d\n",
> +resp->resp.result, resp->resp.error);

If resp->resp.result is not success it is going to be 1, so no need to
include that in the printout. Use dev_err() and print your error on a
single line.

> + ret = resp->resp.result;

ret is positive and some QMI_ERR_*, return a negative errno instead to
better match future readers assumptions.

> + }
> +
> + pr_debug("indication register request completed\n");
> + kfree(resp);
> + kfree(req);
> + return 0;
> +
> +out:
> + kfree(resp);
> + kfree(req);
> + return ret;
> +}
> +
>  static int ath10k_qmi_event_fw_ready_ind(struct ath10k_qmi *qmi)
>  {
>   pr_debug("fw ready event received\n");
> @@ -100,11 +168,12 @@ static void ath10k_qmi_event_server_arrive(struct 
> work_struct *work)
> work_svc_arrive);
>   int ret;
>  
> + pr_debug("wlan qmi server arrive\n");

Fold the move of this debug print into the patch that introduced it.

>   ret = ath10k_qmi_connect_to_fw_server(qmi);
>   if (ret)
>   return;
>  
> - pr_debug("qmi server arrive\n");
> + ath10k_qmi_ind_register_send_sync_msg(qmi);
>  }

Regards,
Bjorn


Re: [PATCH 04/12] ath10k: add support to start and stop qmi service

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:39 PDT 2018, Govind Singh wrote:

> Add support to start qmi service to configure the wlan
> firmware component and register event notifier to communicate
> with the WLAN firmware over qmi communication interface.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi.c | 155 
> --
>  drivers/net/wireless/ath/ath10k/qmi.h |  13 +++
>  2 files changed, 160 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> index 2235182..3a7fcc6 100644
> --- a/drivers/net/wireless/ath/ath10k/qmi.c
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -31,15 +31,115 @@
>  
>  static struct ath10k_qmi *qmi;
>  
> +static int ath10k_qmi_event_fw_ready_ind(struct ath10k_qmi *qmi)
> +{
> + pr_debug("fw ready event received\n");

Please use dev_dbg.

> + spin_lock(>event_lock);
> + qmi->fw_ready = true;
> + spin_unlock(>event_lock);

I see no reason for not just putting this code in
ath10k_qmi_fw_ready_ind().

> +

fw_ready isn't used for anything, what purpose does this code have?

> + return 0;
> +}
> +
> +static void ath10k_qmi_fw_ready_ind(struct qmi_handle *qmi_hdl,
> + struct sockaddr_qrtr *sq,
> + struct qmi_txn *txn, const void *data)
> +{
> + struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, 
> qmi_hdl);
> +
> + ath10k_qmi_event_fw_ready_ind(qmi);
> +}
> +
> +static void ath10k_qmi_msa_ready_ind(struct qmi_handle *qmi_hdl,
> +  struct sockaddr_qrtr *sq,
> +  struct qmi_txn *txn, const void *data)
> +{
> + struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, 
> qmi_hdl);
> +
> + qmi->msa_ready = true;

msa_ready is not only unused in this patch, it's unused after all 11
patches. Can you drop it?

> +}
> +
> +static struct qmi_msg_handler qmi_msg_handler[] = {
> + {
> + .type = QMI_INDICATION,
> + .msg_id = QMI_WLFW_FW_READY_IND_V01,
> + .ei = wlfw_fw_ready_ind_msg_v01_ei,
> + .decoded_size = sizeof(struct wlfw_fw_ready_ind_msg_v01),
> + .fn = ath10k_qmi_fw_ready_ind,
> + },
> + {
> + .type = QMI_INDICATION,
> + .msg_id = QMI_WLFW_MSA_READY_IND_V01,
> + .ei = wlfw_msa_ready_ind_msg_v01_ei,
> + .decoded_size = sizeof(struct wlfw_msa_ready_ind_msg_v01),
> + .fn = ath10k_qmi_msa_ready_ind,
> + },
> + {}
> +};
> +
> +static int ath10k_qmi_connect_to_fw_server(struct ath10k_qmi *qmi)
> +{
> + struct qmi_handle *qmi_hdl = >qmi_hdl;
> + int ret;
> +
> + ret = kernel_connect(qmi_hdl->sock, (struct sockaddr *)>sq,
> +  sizeof(qmi->sq), 0);
> + if (ret) {
> + pr_err("fail to connect to remote service port\n");
> + return ret;
> + }
> +
> + pr_info("wlan qmi service connected\n");
> +
> + return 0;
> +}
> +
> +static void ath10k_qmi_event_server_arrive(struct work_struct *work)
> +{
> + struct ath10k_qmi *qmi = container_of(work, struct ath10k_qmi,
> +   work_svc_arrive);
> + int ret;
> +
> + ret = ath10k_qmi_connect_to_fw_server(qmi);
> + if (ret)
> + return;
> +
> + pr_debug("qmi server arrive\n");
> +}
> +
> +static void ath10k_qmi_event_server_exit(struct work_struct *work)
> +{
> + struct ath10k_qmi *qmi = container_of(work, struct ath10k_qmi,
> +   work_svc_exit);
> +
> + spin_lock(>event_lock);
> + qmi->fw_ready = false;
> + spin_unlock(>event_lock);
> + pr_info("wlan fw service disconnected\n");
> +}
> +
>  static int ath10k_qmi_new_server(struct qmi_handle *qmi_hdl,
>struct qmi_service *service)
>  {
> + struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, 
> qmi_hdl);
> + struct sockaddr_qrtr *sq = >sq;
> +
> + sq->sq_family = AF_QIPCRTR;
> + sq->sq_node = service->node;
> + sq->sq_port = service->port;
> +
> + queue_work(qmi->event_wq, >work_svc_arrive);

This is being called in a sleepable context and kernel_connect() will
not block, so I see no reason for queue work here to invoke
ath10k_qmi_event_server_arrive() just to call
ath10k_qmi_connect_to_fw_server().

Just put the kernel_connect() call here.


This gives the added benefit that you don't need to use qmi->sq as a way
to pass parameters to ath10k_qmi_connect_to_fw_server().

> +
>   return 0;
>  }
>  
>  static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl,
> struct qmi_service *service)
>  {
> + struct ath10k_qmi *qmi =
> + container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
> +
> + queue_work(qmi->event_wq, >work_svc_exit);

I see 

Re: [PATCH 03/12] ath10k: Add ath10k QMI client driver

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:39 PDT 2018, Govind Singh wrote:

> Add QMI client driver for Q6 integrated WLAN connectivity
> subsystem. This module is responsible for communicating WLAN
> control messages to FW over QUALCOMM MSM Interface (QMI).
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/Kconfig  |   2 +-
>  drivers/net/wireless/ath/ath10k/Makefile |   4 +
>  drivers/net/wireless/ath/ath10k/qmi.c| 121 
> +++
>  drivers/net/wireless/ath/ath10k/qmi.h|  24 ++
>  4 files changed, 150 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/wireless/ath/ath10k/qmi.c
>  create mode 100644 drivers/net/wireless/ath/ath10k/qmi.h
> 
> diff --git a/drivers/net/wireless/ath/ath10k/Kconfig 
> b/drivers/net/wireless/ath/ath10k/Kconfig
> index 84f071a..9978ad5e 100644
> --- a/drivers/net/wireless/ath/ath10k/Kconfig
> +++ b/drivers/net/wireless/ath/ath10k/Kconfig
> @@ -42,7 +42,7 @@ config ATH10K_USB
>  
>  config ATH10K_SNOC
>  tristate "Qualcomm ath10k SNOC support (EXPERIMENTAL)"
> -depends on ATH10K && ARCH_QCOM
> +depends on ATH10K && ARCH_QCOM && QCOM_QMI_HELPERS

QCOM_QMI_HELPERS is expected to be selected by the clients, so this
would be:

select QCOM_QMI_HELPERS

>  ---help---
>This module adds support for integrated WCN3990 chip connected
>to system NOC(SNOC). Currently work in progress and will not
> diff --git a/drivers/net/wireless/ath/ath10k/Makefile 
> b/drivers/net/wireless/ath/ath10k/Makefile
> index 44d60a6..1730d1d 100644
> --- a/drivers/net/wireless/ath/ath10k/Makefile
> +++ b/drivers/net/wireless/ath/ath10k/Makefile
> @@ -38,5 +38,9 @@ ath10k_usb-y += usb.o
>  obj-$(CONFIG_ATH10K_SNOC) += ath10k_snoc.o
>  ath10k_snoc-y += snoc.o
>  
> +obj-$(CONFIG_ATH10K_SNOC) += ath10k_qmi.o
> +ath10k_qmi-y += qmi.o \
> + qmi_svc_v01.o
> +
>  # for tracing framework to find trace.h
>  CFLAGS_trace.o := -I$(src)
> diff --git a/drivers/net/wireless/ath/ath10k/qmi.c 
> b/drivers/net/wireless/ath/ath10k/qmi.c
> new file mode 100644
> index 000..2235182
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath10k/qmi.c
> @@ -0,0 +1,121 @@
> +/*
> + * Copyright (c) 2018 The Linux Foundation. All rights reserved.
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */

SPDX headers for new files please.

> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "qmi.h"
> +#include "qmi_svc_v01.h"
> +
> +static struct ath10k_qmi *qmi;

Please design your code so that you don't depend on a global state
pointer.

> +
> +static int ath10k_qmi_new_server(struct qmi_handle *qmi_hdl,
> +  struct qmi_service *service)
> +{
> + return 0;
> +}
> +
> +static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl,
> +   struct qmi_service *service)
> +{
> +}
> +
> +static struct qmi_ops ath10k_qmi_ops = {
> + .new_server = ath10k_qmi_new_server,
> + .del_server = ath10k_qmi_del_server,
> +};
> +
> +static int ath10k_qmi_probe(struct platform_device *pdev)
> +{
> + int ret;
> +
> + qmi = devm_kzalloc(>dev, sizeof(*qmi),
> +GFP_KERNEL);

This doesn't need to be line wrapped.

> + if (!qmi)
> + return -ENOMEM;
> +
> + qmi->pdev = pdev;

The only place you use this is to access pdev->dev, so carry the struct
device * instead.

> + platform_set_drvdata(pdev, qmi);
> + ret = qmi_handle_init(>qmi_hdl,
> +   WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
> +   _qmi_ops, NULL);
> + if (ret < 0)
> + goto err;
> +
> + ret = qmi_add_lookup(>qmi_hdl, WLFW_SERVICE_ID_V01,
> +  WLFW_SERVICE_VERS_V01, 0);
> + if (ret < 0)
> + goto err;
> +
> + pr_debug("qmi client driver probed successfully\n");

Rather than printing a line to indicate that your driver probed you can
check /sys/bus/platform/drivers/ath10k_QMI_client for for devices,
regardless of debug level.

> +
> + return 0;

qmi_add_lookup() returns 0 on success, so you can have a 

Re: [PATCH 02/12] dt: bindings: add bindings for ath10k qmi client

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:39 PDT 2018, Govind Singh wrote:

> Add device tree binding documentation details for ath10k
> qmi client for SDM845/APQ8098 SoC into "qcom,ath10k.txt".
> 
> Signed-off-by: Govind Singh 
> ---
>  Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt 
> b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> index 34e4f98..8076ae3 100644
> --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
> @@ -5,6 +5,7 @@ Required properties:
>   * "qcom,ath10k"
>   * "qcom,ipq4019-wifi"
>   * "qcom,wcn3990-wifi"
> + * "qcom,ath10k-qmi"
>  
>  PCI based devices uses compatible string "qcom,ath10k" and takes calibration
>  data along with board specific data via "qcom,ath10k-calibration-data".
> @@ -21,6 +22,8 @@ can be provided per device.
>  
>  SNOC based devices (i.e. wcn3990) uses compatible string "qcom,wcn3990-wifi".
>  
> +- qcom,wlan-msa-memory: MSA memory size
> +
>  Optional properties:
>  - reg: Address and length of the register set for the device.
>  - reg-names: Must include the list of following reg names,
> @@ -150,3 +153,8 @@ qcom,wifi@1800 {
>  <0 141 0 /* CE11 */ >;
>   vdd-0.8-cx-mx-supply = <_l5>;
>  };
> +
> +qcom,ath10k-qmi {
> + compatible = "qcom,ath10k-qmi";
> + qcom,wlan-msa-memory = <0x10>;

Is this a complete example for what's needed to get working WiFi?
> +};

Regards,
Bjorn


Re: [PATCH 01/12] ath10k: Add qmi service for wlan qmi client

2018-05-11 Thread Bjorn Andersson
On Sun 25 Mar 22:38 PDT 2018, Govind Singh wrote:

> WLAN qmi server running in Q6 dsp exposes host
> to target cold boot qmi handshake.
> Add WLAN QMI service helpers for WLAN serivice.
> 
> Signed-off-by: Govind Singh 
> ---
>  drivers/net/wireless/ath/ath10k/qmi_svc_v01.c | 2323 
> +
>  drivers/net/wireless/ath/ath10k/qmi_svc_v01.h |  685 
>  2 files changed, 3008 insertions(+)
>  create mode 100644 drivers/net/wireless/ath/ath10k/qmi_svc_v01.c
>  create mode 100644 drivers/net/wireless/ath/ath10k/qmi_svc_v01.h
> 
> diff --git a/drivers/net/wireless/ath/ath10k/qmi_svc_v01.c 
> b/drivers/net/wireless/ath/ath10k/qmi_svc_v01.c

This is not the one and only "QMI service version 1", so perhaps name
the file qmi_wlfw_v01.c or something like that?

> new file mode 100644
> index 000..5857c0c
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath10k/qmi_svc_v01.c
> @@ -0,0 +1,2323 @@
> +/*
> + * Copyright (c) 2018 The Linux Foundation. All rights reserved.
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */

Please use SPDX license header.

> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "qmi_svc_v01.h"

At least completion, mutex and idr are unused.

> +
> +static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
> + {
> + .data_type  = QMI_UNSIGNED_4_BYTE,
> + .elem_len   = 1,
> + .elem_size  = sizeof(u32),
> + .array_type = NO_ARRAY,
> + .tlv_type   = 0,
> + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01,
> +pipe_num),
> + },
[..]
> + {
> + .data_type  = QMI_EOTI,
> + .array_type = NO_ARRAY,
> + .tlv_type   = QMI_COMMON_TLV_TYPE,
> + },

I changed the value of QMI_EOTI so this last entry would better be
written as {}. But I presume this requires your code generator to
change.

> +};
[..]
> diff --git a/drivers/net/wireless/ath/ath10k/qmi_svc_v01.h 
> b/drivers/net/wireless/ath/ath10k/qmi_svc_v01.h
> new file mode 100644
> index 000..5e00bfe
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath10k/qmi_svc_v01.h
> @@ -0,0 +1,685 @@
> +/*
> + * Copyright (c) 2018 The Linux Foundation. All rights reserved.
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */

SPDX license header please.

[..]
> +struct wlfw_bdf_download_req_msg_v01 {
> + u8 valid;
> + u8 file_id_valid;
> + enum wlfw_cal_temp_id_enum_v01 file_id;

I would prefer that we replace these enums with a fixed size data type,
and remove the INT_MIN/INT_MAX hack that tricks the compiler into giving
the enum a particular size.

> + u8 total_size_valid;
> + u32 total_size;
> + u8 seg_id_valid;
> + u32 seg_id;
> + u8 data_valid;
> + u32 data_len;
> + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
> + u8 end_valid;
> + u8 end;
> + u8 bdf_type_valid;
> + u8 bdf_type;
> +};

Regards,
Bjorn


Re: [PATCH v3 00/12] *** Add support for wifi QMI client driver ***

2018-05-08 Thread Bjorn Andersson
On Sun 25 Mar 22:37 PDT 2018, Govind Singh wrote:

> Add QMI client driver for Q6 integrated WLAN connectivity subsystem.
> This module is responsible for communicating WLAN control messages to FW
> over QMI interface.
> 
> “QUALCOMM Messaging Interface”(QMI) provides the control interface between
> components running b/w remote processors with underlying transport layer
> based on integrated chipset(shared memory) or discrete 
> chipset(PCI/USB/SDIO/UART).
> 
> QMI client driver implementation is based on qmi frmework 
> https://lwn.net/Articles/729924/.
> 
> Below is the sequence of qmi handshake.
> 
>QMI CLIENT(APPS) QMI SERVER(FW 
> in Q6)
> 
>  <--wlan service discoverd
> 
>-connect to wlam qmi service->
> 
>wlan info request->
> 
> 
>msa info req>
> 
>   
>  msa ready req>
> 
>   
>   
>  capability req--->
> 
>  
> qmi bdf req->
> 
>   
>   qmi cal trigger--->
> 
>   < QMI FW ready indication---

Does the responsibility of the driver ends here? I mean is this a driver
for setting up the firmware and then there's something else doing the
actual wifi operation, or does it simply hand over execution to the
common ath10k logic at this point?

> 
> Govind Singh (12):
>   ath10k: Add qmi service for wlan qmi client
>   dt: bindings: add bindings for ath10k qmi client
>   ath10k: Add WCN3990 QMI client driver
>   ath10k: add support to start and stop qmi service
>   ath10k: Add support of QMI indication message
>   firmware: qcom: scm: Add WLAN VMID for Qualcomm SCM interface
>   ath10k: Add MSA handshake QMI mgs support
>   ath10k: Add QMI CAP request support
>   ath10k: Add QMI HOST CAP request support
>   ath10k: add bdf/cal indication support
>   ath10k: Add wlan mode on/off qmi message
>   ath10k: Add qmi wlan enable/disable support for WCN3990

I'm missing this last patch in my mailbox, and it would be nice if all
the patches where in-reply-to the cover letter, to make them easier to
find.

Regards,
Bjorn


Re: [PATCH 06/12] firmware: qcom: scm: Add WLAN VMID for Qualcomm SCM interface

2018-05-07 Thread Bjorn Andersson
On Sun 25 Mar 22:40 PDT 2018, Govind Singh wrote:

> Add WLAN related VMID's to support wlan driver to set up
> the remote's permissions call via TrustZone.
> 
> Signed-off-by: Govind Singh <govi...@codeaurora.org>

Please use ./scripts/get_maintainer.pl for each patch to get a hint
about whom to send your patches to.

While I think it's okay that Kalle picks it through his tree Andy should
give his ack first.


Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn

> ---
>  include/linux/qcom_scm.h | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
> index b401b96..da63d84 100644
> --- a/include/linux/qcom_scm.h
> +++ b/include/linux/qcom_scm.h
> @@ -1,4 +1,4 @@
> -/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
> +/* Copyright (c) 2010-2015, 2018, The Linux Foundation. All rights reserved.
>   * Copyright (C) 2015 Linaro Ltd.
>   *
>   * This program is free software; you can redistribute it and/or modify
> @@ -33,6 +33,8 @@ struct qcom_scm_vmperm {
>  
>  #define QCOM_SCM_VMID_HLOS   0x3
>  #define QCOM_SCM_VMID_MSS_MSA0xF
> +#define QCOM_SCM_VMID_WLAN   0x18
> +#define QCOM_SCM_VMID_WLAN_CE0x19
>  #define QCOM_SCM_PERM_READ   0x4
>  #define QCOM_SCM_PERM_WRITE  0x2
>  #define QCOM_SCM_PERM_EXEC   0x1
> -- 
> 1.9.1
> 


Re: [PATCH] wcn36xx: Add missing fall through comment in smd.c

2018-04-05 Thread Bjorn Andersson
On Thu 05 Apr 04:51 PDT 2018, Loic Poulain wrote:

> This prevents GCC warning.
> 

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn

> Reported-by: Dan Carpenter <dan.carpen...@oracle.com>
> Signed-off-by: Loic Poulain <loic.poul...@linaro.org>
> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 7cc2928..7b79e0b 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -2135,6 +2135,7 @@ static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, 
> void *buf, size_t len)
>   switch (rsp->type) {
>   case WCN36XX_HAL_SCAN_IND_FAILED:
>   scan_info.aborted = true;
> + /* fall through */
>   case WCN36XX_HAL_SCAN_IND_COMPLETED:
>   mutex_lock(>scan_lock);
>   wcn->scan_req = NULL;
> -- 
> 2.7.4
> 
> 
> ___
> wcn36xx mailing list
> wcn3...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/wcn36xx


Re: [PATCH] wcn36xx: dequeue all pending indicator messages

2018-03-18 Thread Bjorn Andersson
On Thu 15 Mar 15:37 PDT 2018, Daniel Mack wrote:

> In case wcn36xx_smd_rsp_process() is called more than once before
> hal_ind_work was dispatched, the messages will end up in hal_ind_queue,
> but wcn36xx_ind_smd_work() will only look at the first message in that
> list.
> 
> Fix this by dequeing the messages from the list in a loop, and only stop
> when it's empty.
> 

Reviewed-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Thanks for fixing this, I thought I already had done that.

Regards,
Bjorn

> Signed-off-by: Daniel Mack <dan...@zonque.org>
> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 95 
> +++---
>  1 file changed, 52 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 7cc29285e052..a6b5352f59e9 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -2409,54 +2409,63 @@ static void wcn36xx_ind_smd_work(struct work_struct 
> *work)
>  {
>   struct wcn36xx *wcn =
>   container_of(work, struct wcn36xx, hal_ind_work);
> - struct wcn36xx_hal_msg_header *msg_header;
> - struct wcn36xx_hal_ind_msg *hal_ind_msg;
> - unsigned long flags;
>  
> - spin_lock_irqsave(>hal_ind_lock, flags);
> + for (;;) {
> + struct wcn36xx_hal_msg_header *msg_header;
> + struct wcn36xx_hal_ind_msg *hal_ind_msg;
> + unsigned long flags;
>  
> - hal_ind_msg = list_first_entry(>hal_ind_queue,
> -struct wcn36xx_hal_ind_msg,
> -list);
> - list_del(wcn->hal_ind_queue.next);
> - spin_unlock_irqrestore(>hal_ind_lock, flags);
> + spin_lock_irqsave(>hal_ind_lock, flags);
>  
> - msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
> + if (list_empty(>hal_ind_queue)) {
> + spin_unlock_irqrestore(>hal_ind_lock, flags);
> + return;
> + }
>  
> - switch (msg_header->msg_type) {
> - case WCN36XX_HAL_COEX_IND:
> - case WCN36XX_HAL_DEL_BA_IND:
> - case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
> - break;
> - case WCN36XX_HAL_OTA_TX_COMPL_IND:
> - wcn36xx_smd_tx_compl_ind(wcn,
> -  hal_ind_msg->msg,
> -  hal_ind_msg->msg_len);
> - break;
> - case WCN36XX_HAL_MISSED_BEACON_IND:
> - wcn36xx_smd_missed_beacon_ind(wcn,
> -   hal_ind_msg->msg,
> -   hal_ind_msg->msg_len);
> - break;
> - case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
> - wcn36xx_smd_delete_sta_context_ind(wcn,
> -hal_ind_msg->msg,
> -hal_ind_msg->msg_len);
> - break;
> - case WCN36XX_HAL_PRINT_REG_INFO_IND:
> - wcn36xx_smd_print_reg_info_ind(wcn,
> -hal_ind_msg->msg,
> -hal_ind_msg->msg_len);
> - break;
> - case WCN36XX_HAL_SCAN_OFFLOAD_IND:
> - wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
> - hal_ind_msg->msg_len);
> - break;
> - default:
> - wcn36xx_err("SMD_EVENT (%d) not supported\n",
> -   msg_header->msg_type);
> + hal_ind_msg = list_first_entry(>hal_ind_queue,
> +struct wcn36xx_hal_ind_msg,
> +list);
> + list_del(_ind_msg->list);
> + spin_unlock_irqrestore(>hal_ind_lock, flags);
> +
> + msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
> +
> + switch (msg_header->msg_type) {
> + case WCN36XX_HAL_COEX_IND:
> + case WCN36XX_HAL_DEL_BA_IND:
> + case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
> + break;
> + case WCN36XX_HAL_OTA_TX_COMPL_IND:
> + wcn36xx_smd_tx_compl_ind(wcn,
> +  hal_ind_msg->msg,
> +  hal_ind_msg->msg_len);
> + break;
> + case WCN36XX_HAL_MISSED_BEACON_IND:
> + wcn36xx_smd

Re: [PATCH] wcn36xx: reduce verbosity of drivers messages

2018-02-18 Thread Bjorn Andersson
On Sat 17 Feb 12:25 PST 2018, Ramon Fried wrote:

> Whenever the WLAN interface is started the FW
> version and caps are printed, this info should appear as
> debug info.
> 
> Signed-off-by: Ramon Fried <rfr...@codeaurora.org>

Looks reasonable,

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn


Re: [PATCH] brcmfmac: Make sure CLM downloading is optional

2018-01-15 Thread Bjorn Andersson
On Mon 15 Jan 11:40 PST 2018, Arend van Spriel wrote:

> On 1/15/2018 6:10 PM, Bjorn Andersson wrote:
> > The presence of a CLM file is described as optional, but missing the clm
> > blob causes the preinit to return unsuccessfully. Fix this by ignoring
> > the return value of the brcmf_c_process_clm_blob().
> > 
> > Also remove the extra debug print, as brcmf_c_process_clm_blob() already
> > did print a useful error message before returning.
> > 
> > Fixes: fdd0bd88ceae ("brcmfmac: add CLM download support")
> > Cc: sta...@vger.kernel.org
> > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> > ---
> > 
> > This regression was introduced in v4.15-rc1, but I unfortunately didn't test
> > WiFi until now. Included a Cc to stable@ in case you choose to pick this up
> > after v4.15.
> 
> Hi Bjorn,
> 
> Thanks for looking into this. Actually there already have been a couple of
> fixes posted on the linux-wireless list. [1] was rejected, [2] is being
> discussed, and [2] was posted by me and I was awaiting response from the guy
> reporting it.
> 

Thanks for pointing me to these discussions, I did for some reason not
find them this morning. I don't see the need for the retry in [1], so I
think that's invalid.

I tested [2] and it works well for me, but I agree with Kalle that a
better description of why would be in order. Unfortunatley I can't find
it in my inbox...even though I'm subscribed to linux-wireless@.

The answer to Kalle's question should probably include a reference to
0542ad88fbdd ("firmware loader: Fix _request_firmware_load() return val
for fw load abort")

> Now the thing is that for old (Broadcom) firmware this is optional. Those
> firmwares don't even have CLM support and those that do have the CLM data
> embedded in firmware.

I don't know which applies to my device, but it at least doesn't come
with a dedicated clm blob - and the device won't receive any upgrades
and hence will never get a clm blob.

> However, Cypress wants to provide their customers with
> firmware without CLM data. For those devices it is not optional. I still
> prefer we add a mechanism to the driver to detect that, but we do not have
> that yet.
> 

That sounds reasonable, but I hope we can sort out the regression first
and then add such logic.

> Now regarding your patch some comments below ...
> 
> >   drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 8 ++--
> >   1 file changed, 2 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c 
> > b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
> > index 6a59d0609d30..0c67ba6ae135 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
> > @@ -278,12 +278,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
> > }
> > ri->result = err;
> > 
> > -   /* Do any CLM downloading */
> > -   err = brcmf_c_process_clm_blob(ifp);
> > -   if (err < 0) {
> > -   brcmf_err("download CLM blob file failed, %d\n", err);
> > -   goto done;
> > -   }
> > +   /* Do any optional CLM downloading */
> > +   brcmf_c_process_clm_blob(ifp);
> 
> The error print is indeed redundant and should be removed here. However,
> brcmf_c_process_clm_blob() also returns -ENOMEM upon allocation failure and
> I would still fail the driver probe for that.
> 

Agreed, but as we want to let a few errors, specifically from the
firmware loader, slip by I believe it's better to check the return value
there instead. So I prefer Write's [2].

Regards,
Bjorn


[PATCH] brcmfmac: Make sure CLM downloading is optional

2018-01-15 Thread Bjorn Andersson
The presence of a CLM file is described as optional, but missing the clm
blob causes the preinit to return unsuccessfully. Fix this by ignoring
the return value of the brcmf_c_process_clm_blob().

Also remove the extra debug print, as brcmf_c_process_clm_blob() already
did print a useful error message before returning.

Fixes: fdd0bd88ceae ("brcmfmac: add CLM download support")
Cc: sta...@vger.kernel.org
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

This regression was introduced in v4.15-rc1, but I unfortunately didn't test
WiFi until now. Included a Cc to stable@ in case you choose to pick this up
after v4.15.

 drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 6a59d0609d30..0c67ba6ae135 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -278,12 +278,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
}
ri->result = err;
 
-   /* Do any CLM downloading */
-   err = brcmf_c_process_clm_blob(ifp);
-   if (err < 0) {
-   brcmf_err("download CLM blob file failed, %d\n", err);
-   goto done;
-   }
+   /* Do any optional CLM downloading */
+   brcmf_c_process_clm_blob(ifp);
 
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
-- 
2.15.0



Re: [PATCH][V2] wcn36xx: fix incorrect assignment to msg_body.min_ch_time

2018-01-04 Thread Bjorn Andersson
On Fri 29 Dec 01:07 PST 2017, Colin King wrote:

> From: Colin Ian King <colin.k...@canonical.com>
> 
> The second assignment to msg_body.min_ch_time is incorrect, it
> should actually be to msg_body.max_ch_time.
> 
> Thanks to Bjorn Andersson for identifying the correct way to fix
> this as my original fix was incorrect.
> 
> Detected by CoverityScan, CID#1463042 ("Unused Value")
> 
> Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")
> Signed-off-by: Colin Ian King <colin.k...@canonical.com>

Thanks Colin,

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn

> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 2914618a0335..2a4871ca9c72 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -626,7 +626,7 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct 
> ieee80211_vif *vif,
>  
>   msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
>   msg_body.min_ch_time = 30;
> - msg_body.min_ch_time = 100;
> + msg_body.max_ch_time = 100;
>   msg_body.scan_hidden = 1;
>   memcpy(msg_body.mac, vif->addr, ETH_ALEN);
>   msg_body.p2p_search = vif->p2p;
> -- 
> 2.14.1
> 


Re: [PATCH][next] wcn36xx: remove redundant assignment to msg_body.min_ch_time

2017-12-26 Thread Bjorn Andersson
On Tue 19 Dec 09:04 PST 2017, Colin King wrote:

> From: Colin Ian King 
> 
> msg_body.min_ch_time is being assigned twice; remove the redundant
> first assignment.
> 
> Detected by CoverityScan, CID#1463042 ("Unused Value")
> 

Happy to see Coverity working for us :)


This should have had a:

Fixes: 2f3bef4b247e ("wcn36xx: Add hardware scan offload support")

> Signed-off-by: Colin Ian King 
> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 2914618a0335..bab2eca5fcac 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -625,7 +625,6 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct 
> ieee80211_vif *vif,
>   INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
>  
>   msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
> - msg_body.min_ch_time = 30;
>   msg_body.min_ch_time = 100;

But I strongly suspect the second line is supposed to be max_ch_time.

@Loic, do you agree?

Regards,
Bjorn


Re: [PATCH v2] wcn36xx: Fix dynamic power saving

2017-12-11 Thread Bjorn Andersson
On Mon 11 Dec 07:34 PST 2017, Ramon Fried wrote:

> On Mon, Dec 11, 2017 at 10:52:22AM +0200, Loic Poulain wrote:
> > Since driver does not report hardware dynamic power saving cap,
> > this is up to the mac80211 to manage power saving timeout and
> > state machine, using the ieee80211 config callback to report
> > PS changes. This patch enables/disables PS mode according to
> > the new configuration.
> > 
> > Remove old behaviour enabling PS mode in a static way, this make
> > the device unusable when power save is enabled since device is
> > forced to PS regardless RX/TX traffic.
> > 
> 
> Hi.
> I tried to see if this patch solves the ping delay once power save is
> turned on and it appears it doesn't (log below).
> I do see some change in the delay though in comparison to testing without the 
> patch.
> Bjorn, How did you test it ?
> 

Without this patch I get ping times around a second and SSH is not
usable, with this patch I see similar ping times as you, but SSH is
usable.

I have not been able to run iperf, because I keep hitting
https://bugs.96boards.org/show_bug.cgi?id=663

Regards,
Bjorn


Re: [PATCH] wcn36xx: Fix dynamic power saving

2017-12-08 Thread Bjorn Andersson
On Fri 08 Dec 08:34 PST 2017, Loic Poulain wrote:

> Since driver does not report hardware dynamic power saving cap,
> this is up to the mac80211 to manage power saving timeout and
> state machine, using the ieee80211 config callback to report
> PS changes. This patch enables/disables PS mode according to
> the new configuration.
> 
> Remove old behaviour enabling PS mode in a static way, this make
> the device unusable when power save is enabled since device is
> forced to PS regardless RX/TX traffic.
> 
> Signed-off-by: Loic Poulain <loic.poul...@linaro.org>

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

With below nit.

> ---
>  drivers/net/wireless/ath/wcn36xx/main.c | 23 ---
>  1 file changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
> b/drivers/net/wireless/ath/wcn36xx/main.c
> index f0b4d43..436b8ea 100644
> --- a/drivers/net/wireless/ath/wcn36xx/main.c
> +++ b/drivers/net/wireless/ath/wcn36xx/main.c
> @@ -384,6 +384,18 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 
> changed)
>   }
>   }
>  
> + if (changed & IEEE80211_CONF_CHANGE_PS) {
> + list_for_each_entry(tmp, >vif_list, list) {
> + vif = wcn36xx_priv_to_vif(tmp);
> + if (hw->conf.flags & IEEE80211_CONF_PS) {
> + if (vif->bss_conf.ps) /* ps allowed ? */
> + wcn36xx_pmc_enter_bmps_state(wcn, vif);
> + } else {
> + wcn36xx_pmc_exit_bmps_state(wcn, vif);

During startup I get the error print from wcn36xx_pmc_exit_bmps_state()
that we're not in BMPS state. There's no harm in this, but the error
might concern people.

How about we in addition to this, change the wcn36xx_err() to a
wcn36xx_dbg(PMC...) ?

Regards,
Bjorn


[PATCH] wcn36xx: Reduce spinlock in indication handler

2017-12-08 Thread Bjorn Andersson
The purpose of pushing indication on a list and handle these in a
separate worker is to allow the handlers to sleep. It does therefor not
make much sense to hold the queue spinlock through the entire indication
worker function.

By removing items from the queue early we don't need to hold the lock
throughout the indication worker, allowing the individual handlers to
sleep.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index fa88a2a460aa..52daae863aed 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2414,6 +2414,8 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
hal_ind_msg = list_first_entry(>hal_ind_queue,
   struct wcn36xx_hal_ind_msg,
   list);
+   list_del(wcn->hal_ind_queue.next);
+   spin_unlock_irqrestore(>hal_ind_lock, flags);
 
msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
 
@@ -2450,8 +2452,6 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
wcn36xx_err("SMD_EVENT (%d) not supported\n",
  msg_header->msg_type);
}
-   list_del(wcn->hal_ind_queue.next);
-   spin_unlock_irqrestore(>hal_ind_lock, flags);
kfree(hal_ind_msg);
 }
 int wcn36xx_smd_open(struct wcn36xx *wcn)
-- 
2.15.0



Re: [PATCH] wcn36xx: Add hardware scan offload support

2017-12-08 Thread Bjorn Andersson
On Fri 08 Dec 01:35 PST 2017, Loic Poulain wrote:

> Current hw_scan implementation does not trigger offloaded
> hardware scan and seems to only put the device in a kind of
> listening mode (beacon/probe-response) for software scan.
> Since no probe request are generated by the software, current
> scanning method is similar to a passive scan.
> 
> This patch introduces support for 'true' hardware offloaded scan.
> Hardware scan is configured and started via the start-scan-offload
> firmware message. Once scan has been completed a scan indicator
> message is received from firmware.
> 
> Moreover, this patch includes support for directed probe-request,
> allowing connection with hidden APs. It also fixes scan issues with
> band-steering AP which are not 'visible' with passive scan (due to
> hidden ssid in beacons).
> 

I'm puzzled to why I didn't see this when I dumped the control channel
that lead up to the initial hw_scan patch. But this looks good and with
a related locking issue fixed this seems to work well.

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
[..]
> +static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t 
> len)
> +{
> + struct wcn36xx_hal_scan_offload_ind *rsp = buf;
> + struct cfg80211_scan_info scan_info = {};
> +
> + if (len != sizeof(*rsp)) {
> + wcn36xx_warn("Corrupted delete scan indication\n");
> + return -EIO;
> + }
> +
> + wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)", rsp->type);
> +
> + switch (rsp->type) {
> + case WCN36XX_HAL_SCAN_IND_FAILED:
> + scan_info.aborted = true;
> + case WCN36XX_HAL_SCAN_IND_COMPLETED:
> + mutex_lock(>scan_lock);

Grabbing this mutex with DEBUG_ATOMIC_SLEEP causes issues, but that's
because the locking in ind_smd_work() is to excessive. Will reply with a
fix for this.

> + wcn->scan_req = NULL;
> + mutex_unlock(>scan_lock);
> + ieee80211_scan_completed(wcn->hw, _info);
> + break;

Regards,
Bjorn


Re: [PATCH v4] wcn36xx: Set default BTLE coexistence config

2017-11-16 Thread Bjorn Andersson
On Thu 16 Nov 00:01 PST 2017, Ramon Fried wrote:

> From: Eyal Ilsar <eil...@codeaurora.org>
> 
> If the value for the firmware configuration parameters
> BTC_STATIC_LEN_LE_BT and BTC_STATIC_LEN_LE_WLAN are not set the duty
> cycle between BT and WLAN is such that if BT (including BLE) is active
> WLAN gets 0 bandwidth. When tuning these parameters having a too high
> value for WLAN means that BLE performance degrades.
> The "sweet" point of roughly half of the maximal values was empirically
> found to achieve a balance between BLE and Wi-Fi coexistence
> performance.
> 
> Signed-off-by: Eyal Ilsar <eil...@codeaurora.org>
> Signed-off-by: Ramon Fried <rfr...@codeaurora.org>

Looks good,

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn

> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 9c6590d5348a..6f1e741acf3e 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -73,6 +73,8 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
>   WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
>   WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
>   WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
> + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12),
> + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3),
>   WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
>   WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
>  };
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 


Re: [PATCH v3] wcn36xx: Set default BTLE coexistence config

2017-11-15 Thread Bjorn Andersson
On Mon 13 Nov 23:23 PST 2017, Ramon Fried wrote:

> From: Eyal Ilsar 
> 
> If the value for the firmware configuration parameters
> BTC_STATIC_LEN_LE_BT and BTC_STATIC_LEN_LE_WLAN are not set the duty
> cycle between BT and WLAN is such that if BT (including BLE) is active
> WLAN gets 0 bandwidth. When tuning these parameters having a too high
> value for WLAN means that BLE performance degrades.
> The "sweet" point of roughly half of the maximal values was empirically
> found to achieve a balance between BLE and Wi-Fi coexistence
> performance.
> 
> Signed-off-by: Eyal Ilsar 
> Signed-off-by: Ramon Fried 
> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 9c6590d5348a..1c7598752255 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -72,8 +72,10 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
>   WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
>   WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
>   WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
> - WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),

I still don't see why you're moving this unrelated line, can you please
help me see what I'm missing?

Thanks,
Bjorn

> + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12),
> + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3),
>   WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
> + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
>   WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
>  };
>  
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 


Re: [PATCH] wcn36xx: Set BTLE coexistence related configuration values to defaults

2017-11-13 Thread Bjorn Andersson
On Sun 12 Nov 06:21 PST 2017, Ramon Fried wrote:

> From: Eyal Ilsar 
> 
> If the value for the firmware configuration parameters BTC_STATIC_LEN_LE_BT
> and BTC_STATIC_LEN_LE_WLAN are not set the duty cycle between BT and WLAN
> is such that if BT (including BLE) is active WLAN gets 0 bandwidth.
> When tuning these parameters having a too high value for WLAN means that BLE 
> performance degrades.
> The "sweet" point of roughly half of the maximal values was empirically found 
> to achieve
> a balance between BLE and Wi-Fi coexistence performance.
> 

Thanks for the patch! Just some minor comments.

Please limit subject to 50 chars and wrap body at 72 chars.

> Signed-off-by: Eyal Ilsar 
> Signed-off-by: Ramon Fried 
> ---
>  drivers/net/wireless/ath/wcn36xx/smd.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 9c6590d..1c75987 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -72,8 +72,10 @@ struct wcn36xx_cfg_val {
>   WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
>   WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
>   WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
> - WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),

I don't see a need for moving this line.

> + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 12),
> + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 3),

These looks reasonable, are we okay leaving the other coexistence
properties at their preconfigured values?

>   WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
> + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
>   WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),

Regards,
Bjorn


Re: [PATCH] wcn36xx: Remove unnecessary rcu_read_unlock in wcn36xx_bss_info_changed

2017-10-11 Thread Bjorn Andersson
On Sun 08 Oct 06:06 PDT 2017, Jia-Ju Bai wrote:

> No rcu_read_lock is called, but rcu_read_unlock is still called.
> Thus rcu_read_unlock should be removed.
> 

Thanks, not sure how I could miss that one. Kalle can you please include
this in a v4.14-rc pull request?


:

Fixes: 39efc7cc7ccf ("wcn36xx: Introduce mutual exclusion of fw configuration")

> Signed-off-by: Jia-Ju Bai <baijiaju1...@163.com>

Acked-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn

> ---
>  drivers/net/wireless/ath/wcn36xx/main.c |1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
> b/drivers/net/wireless/ath/wcn36xx/main.c
> index 35bd50b..b83f01d 100644
> --- a/drivers/net/wireless/ath/wcn36xx/main.c
> +++ b/drivers/net/wireless/ath/wcn36xx/main.c
> @@ -812,7 +812,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
> *hw,
>   if (!sta) {
>   wcn36xx_err("sta %pM is not found\n",
> bss_conf->bssid);
> - rcu_read_unlock();
>   goto out;
>   }
>   sta_priv = wcn36xx_sta_to_priv(sta);
> -- 
> 1.7.9.5
> 
> 
> 
> ___
> wcn36xx mailing list
> wcn3...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/wcn36xx


[PATCH v2] mac80211: Invoke TX LED in more code paths

2017-05-27 Thread Bjorn Andersson
ieee80211_tx_status() is only one of the possible ways a driver can
report a handled packet, some drivers call this for every packet while
others calls it rarely or never.

In order to invoke the TX LED in the non-status reporting cases this
patch pushes the call to ieee80211_led_tx() into
ieee80211_report_used_skb(), which is shared between the various code
paths.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 net/mac80211/status.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index be47ac5cd8c8..a9fa6ee57e8f 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -546,6 +546,8 @@ static void ieee80211_report_used_skb(struct 
ieee80211_local *local,
skb->wifi_acked_valid = 1;
skb->wifi_acked = acked;
}
+
+   ieee80211_led_tx(local);
 }
 
 /*
@@ -823,8 +825,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
}
}
 
-   ieee80211_led_tx(local);
-
/* SNMP counters
 * Fragments are passed to low-level drivers as separate skbs, so these
 * are actually fragments, not frames. Update frame counters only for
-- 
2.12.0



Re: [PATCH 1/2] wcn36xx: Pass used skb to ieee80211_tx_status()

2017-05-17 Thread Bjorn Andersson
On Wed 17 May 06:14 PDT 2017, Johannes Berg wrote:

> On Thu, 2017-05-04 at 13:13 +, Kalle Valo wrote:
> > 
> > > > This code intentionally checked if TX status was requested, and
> > > > if not then it doesn't go to the effort of building it.
> > > > 
> > > 
> > > What I'm finding puzzling is the fact that the only caller of
> > > ieee80211_led_tx() is ieee80211_tx_status() and it seems like
> > > drivers, such as ath10k, call this for each packet handled - but
> > > I'm likely missing something.
> 
> Yes, many drivers do call it for each packet, and as such, this
> deficiency was never noted.
> 
> > > > As it is with your patch, it'll go and report the TX status
> > > > without any
> > > > TX status information - which is handled in
> > > > wcn36xx_dxe_tx_ack_ind()
> > > > for those frames needing it.
> > > > 
> > > 
> > > Right, it doesn't sound desired. However, during normal operation
> > > I'm not seeing IEEE80211_TX_CTL_REQ_TX_STATUS being set and as such
> > > ieee80211_led_tx() is never called.
> > 
> > So what's the conclusion? How do we get leds working?
> 
> Well, frankly, I never thought the TX LED was a super good idea - but
> it had been supported by the original code IIRC, so never removed. Some
> people like frantic blinking I guess ;-)
> 

It seems very important to a lot of people...


But if ieee80211_free_txskb() is the counterpart of
ieee80211_tx_status() then we should be able to push the
ieee80211_led_tx() call down into ieee80211_report_used_skb() and handle
both cases.

The ieee80211_free_txskb() seems to be used in various cases where we
discard skbs, but perhaps this is not an issue in reality.

> But I think the problem also applies to the throughput trigger thing,
> so perhaps we need to stick some LED feedback calls into other places,
> like _noskb() or provide an extra way to do it?
> 

Looking around it seems that we either have a call to free_txskb() or
one of the tx_status(); where the _noskb() would need some special
handling. Are there others or would it be reasonable to add a call in
this one "special" case?

Regards,
Bjorn


Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

2017-05-17 Thread Bjorn Andersson
On Wed 17 May 05:53 PDT 2017, Pali Roh?r wrote:

> On Wednesday 17 May 2017 14:06:06 Johannes Berg wrote:
> > On Tue, 2017-05-16 at 01:13 +0200, Luis R. Rodriguez wrote:
> > > > > Now for N900 case there is a similar scenario
> > > > > alhtough it has additional requirement to go to user-space due to
> > > > > need to use a proprietary library to obtain the NVS calibration
> > > > > data. My thought: Why should firmware_class care?
> > > 
> > > Agreed.
> > 
> > In fact, why should the *driver* care either? IOW - why should
> > "request_firmware_prefer_user()" even exist?
> 
> There are default/example NVS data, which are stored in /lib/firmware
> and installed by linux-firmware package. Those example calibration data
> should not be used for real usage, but Pavel told us that on N900 they
> are enough for working WIFI connection. They does not contain valid MAC
> address, so kernel should generate some (random?).
> 
> So kernel driver should get NVS calibration data from userspace (which
> know how where to get or how to prepare them) and in case userspace do
> not have it, then we can try fallback to those example data (as people
> reported us they can be useful instead of non-working WIFI).
> 

We're going to see a similar case with the Qualcomm DB410c WiFi soon,
where there is default calibration for the chip (wcn3620) but specific
calibration data for the particular board or product using this chip.

As with your case we expect to have a "generic" calibration file
integrated in linux-firmware, but providing means to supporting
device-specific calibration is probably going to be requested shortly.


We have however altered the reference design of picking the MAC address
from the calibration data and have the bootloader pass it via DT - so
our calibration data doesn't need to be specific to each unit.

Regards,
Bjorn


Re: [PATCH] wcn36xx: Close SMD channel on device removal

2017-05-10 Thread Bjorn Andersson
On Wed 10 May 00:27 PDT 2017, Arend van Spriel wrote:

> On 5/10/2017 1:03 AM, Bjorn Andersson wrote:
> > On Mon 08 May 23:17 PDT 2017, Kalle Valo wrote:
> > 
> > > Bjorn Andersson <bjorn.anders...@linaro.org> writes:
> > > 
> > > > The SMD channel is not the primary WCNSS channel and must explicitly be
> > > > closed as the device is removed, or the channel will already by open on
> > > > a subsequent probe call in e.g. the case of reloading the kernel module.
> > > > 
> > > > This issue was introduced because I simplified the underlying SMD
> > > > implementation while the SMD adaptions of the driver sat on the mailing
> > > > list, but missed to update these patches. The patch does however only
> > > > apply back to the transition to rpmsg, hence the limited Fixes.
> > > > 
> > > > Fixes: 5052de8deff5 ("soc: qcom: smd: Transition client drivers from 
> > > > smd to rpmsg")
> > > > Reported-by: Eyal Ilsar <c_eil...@qti.qualcomm.com>
> > > > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> > > 
> > > As this is a regression I'll queue this to 4.12.
> > > 
> > 
> > Thanks.
> > 
> > > But if this is an older bug (didn't quite understand your description
> > > though) should there be a separate patch for stable releases?
> > > 
> > 
> > AFAICT this never worked, as it seems I did the rework in SMD while we
> > tried to figure out the dependency issues we had with moving to SMD. So
> > v4.9 through v4.11 has SMD support - with this bug.
> > 
> > How do I proceed, do you want me to write up a fix for stable@? Do I
> > send that out as an ordinary patch?
> 
> If the patch applies cleanly on branches linux-4.9.y through linux-4.11.y in
> the stable repository you can go for '--- Option 1 ---' as described in
> /Documentation/stable_kernel_rules.txt.
> 

It does not, before v4.12 it's a completely different function to call
to close the channel.

But "Option 3" describes the situation, thanks for the reference. I'll
try to find the time to verify the patch on v4.11 and send it to
stable@.

Regards,
Bjorn


Re: [PATCH] wcn36xx: Close SMD channel on device removal

2017-05-09 Thread Bjorn Andersson
On Mon 08 May 23:17 PDT 2017, Kalle Valo wrote:

> Bjorn Andersson <bjorn.anders...@linaro.org> writes:
> 
> > The SMD channel is not the primary WCNSS channel and must explicitly be
> > closed as the device is removed, or the channel will already by open on
> > a subsequent probe call in e.g. the case of reloading the kernel module.
> >
> > This issue was introduced because I simplified the underlying SMD
> > implementation while the SMD adaptions of the driver sat on the mailing
> > list, but missed to update these patches. The patch does however only
> > apply back to the transition to rpmsg, hence the limited Fixes.
> >
> > Fixes: 5052de8deff5 ("soc: qcom: smd: Transition client drivers from smd to 
> > rpmsg")
> > Reported-by: Eyal Ilsar <c_eil...@qti.qualcomm.com>
> > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> 
> As this is a regression I'll queue this to 4.12.
> 

Thanks.

> But if this is an older bug (didn't quite understand your description
> though) should there be a separate patch for stable releases?
> 

AFAICT this never worked, as it seems I did the rework in SMD while we
tried to figure out the dependency issues we had with moving to SMD. So
v4.9 through v4.11 has SMD support - with this bug.

How do I proceed, do you want me to write up a fix for stable@? Do I
send that out as an ordinary patch?

Regards,
Bjorn


[PATCH] wcn36xx: Close SMD channel on device removal

2017-05-08 Thread Bjorn Andersson
The SMD channel is not the primary WCNSS channel and must explicitly be
closed as the device is removed, or the channel will already by open on
a subsequent probe call in e.g. the case of reloading the kernel module.

This issue was introduced because I simplified the underlying SMD
implementation while the SMD adaptions of the driver sat on the mailing
list, but missed to update these patches. The patch does however only
apply back to the transition to rpmsg, hence the limited Fixes.

Fixes: 5052de8deff5 ("soc: qcom: smd: Transition client drivers from smd to 
rpmsg")
Reported-by: Eyal Ilsar <c_eil...@qti.qualcomm.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index d5e993dc9b23..517a315e259b 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1271,6 +1271,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
qcom_smem_state_put(wcn->tx_enable_state);
qcom_smem_state_put(wcn->tx_rings_empty_state);
 
+   rpmsg_destroy_ept(wcn->smd_channel);
+
iounmap(wcn->dxe_base);
iounmap(wcn->ccu_base);
 
-- 
2.12.0



Re: [PATCH 1/2] wcn36xx: Pass used skb to ieee80211_tx_status()

2017-04-28 Thread Bjorn Andersson
On Thu 27 Apr 01:22 PDT 2017, Johannes Berg wrote:

> 
> > @@ -371,7 +371,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn,
> > struct wcn36xx_dxe_ch *ch)
> >     info = IEEE80211_SKB_CB(ctl->skb);
> >     if (!(info->flags &
> > IEEE80211_TX_CTL_REQ_TX_STATUS)) {
> >     /* Keep frame until TX status comes
> > */
> > -   ieee80211_free_txskb(wcn->hw, ctl-
> > >skb);
> > +   ieee80211_tx_status(wcn->hw, ctl-
> > >skb);
> > 
> 
> I don't think this is a good idea.

Thanks for letting me know :)

> This code intentionally checked if TX status was requested, and if not
> then it doesn't go to the effort of building it.
> 

What I'm finding puzzling is the fact that the only caller of
ieee80211_led_tx() is ieee80211_tx_status() and it seems like drivers,
such as ath10k, call this for each packet handled - but I'm likely
missing something.

> As it is with your patch, it'll go and report the TX status without any
> TX status information - which is handled in wcn36xx_dxe_tx_ack_ind()
> for those frames needing it.
> 

Right, it doesn't sound desired. However, during normal operation I'm
not seeing IEEE80211_TX_CTL_REQ_TX_STATUS being set and as such
ieee80211_led_tx() is never called.

Regards,
Bjorn


[PATCH 2/2] arm64: dts: apq8016-sbc: Correct WLAN LED default-trigger

2017-04-26 Thread Bjorn Andersson
The TX status trigger of the wlan interface is named phy0tx, so this
updates the default-trigger for the WLAN LED to use that instead.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Note that without patch 1/2 this trigger does not fire - but there's also no
harm in picking the two patches through separate trees.

 arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi 
b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
index 5d83b02b7c4a..21a8f5ce8955 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
@@ -178,7 +178,7 @@
led@5 {
label = "apq8016-sbc:yellow:wlan";
gpios = <_mpps 2 GPIO_ACTIVE_HIGH>;
-   linux,default-trigger = "wlan";
+   linux,default-trigger = "phy0tx";
default-state = "off";
};
 
-- 
2.12.0



[PATCH 1/2] wcn36xx: Pass used skb to ieee80211_tx_status()

2017-04-26 Thread Bjorn Andersson
As the tx skbs are collected they should be passed to
ieee80211_tx_status() rather than ieee80211_free_txskb(), as the prior
will take care of monitoring and LED triggers while the latter will
consider the skb dropped.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/dxe.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 87dfdaf9044c..938b7bd733cf 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -371,7 +371,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct 
wcn36xx_dxe_ch *ch)
info = IEEE80211_SKB_CB(ctl->skb);
if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
/* Keep frame until TX status comes */
-   ieee80211_free_txskb(wcn->hw, ctl->skb);
+   ieee80211_tx_status(wcn->hw, ctl->skb);
}
spin_lock(>skb_lock);
if (wcn->queues_stopped) {
-- 
2.12.0



Re: [PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg

2017-03-27 Thread Bjorn Andersson
On Mon 27 Mar 16:04 PDT 2017, David Miller wrote:

> From: Bjorn Andersson <bjorn.anders...@linaro.org>
> Date: Mon, 27 Mar 2017 15:58:37 -0700
> 
> > I'm sorry, but I can't figure out how to reproduce this.
> 
> All of my builds are "make allmodconfig" so it should be easy to reproduce.

Thanks, turns out that while it was possible to select CONFIG_SMD_RPM
and CONFIG_QCOM_WCNSS_CTRL drivers/soc/Makefile does not traverse into
qcom/ unless CONFIG_ARCH_QCOM was set.

So I just sent out version 2 of the three patches, where I add an
explicit dependency on ARCH_QCOM for those two options.

Regards,
Bjorn


[PATCH v2 3/3] soc: qcom: smd-rpm: Add msm8996 compatibility

2017-03-27 Thread Bjorn Andersson
With the RPM driver transitioned to RPMSG we can reuse the SMD-RPM
driver ontop of GLINK for 8996, without any modifications.

Acked-by: Andy Gross <andy.gr...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/soc/qcom/smd-rpm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 0dcf1bf33126..c2346752b3ea 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -225,6 +225,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-apq8084" },
{ .compatible = "qcom,rpm-msm8916" },
{ .compatible = "qcom,rpm-msm8974" },
+   { .compatible = "qcom,rpm-msm8996" },
{}
 };
 MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
-- 
2.12.0



[PATCH v2 2/3] soc: qcom: smd: Remove standalone driver

2017-03-27 Thread Bjorn Andersson
Remove the standalone SMD implementation as we have transitioned the
client drivers to use the RPMSG based one.

Also remove all dependencies on QCOM_SMD from Kconfig files, in order to
keep them selectable in the absence of the removed symbol.

Acked-by: Andy Gross <andy.gr...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/remoteproc/Kconfig |6 +-
 drivers/rpmsg/Kconfig  |1 -
 drivers/soc/qcom/Kconfig   |8 -
 drivers/soc/qcom/Makefile  |1 -
 drivers/soc/qcom/smd.c | 1560 
 include/linux/rpmsg/qcom_smd.h |2 +-
 include/linux/soc/qcom/smd.h   |  139 
 7 files changed, 4 insertions(+), 1713 deletions(-)
 delete mode 100644 drivers/soc/qcom/smd.c
 delete mode 100644 include/linux/soc/qcom/smd.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 1dc43fc5f65f..faad69a1a597 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -76,7 +76,7 @@ config QCOM_ADSP_PIL
depends on OF && ARCH_QCOM
depends on REMOTEPROC
depends on QCOM_SMEM
-   depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && 
RPMSG_QCOM_SMD=n)
+   depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
select MFD_SYSCON
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
@@ -93,7 +93,7 @@ config QCOM_Q6V5_PIL
depends on OF && ARCH_QCOM
depends on QCOM_SMEM
depends on REMOTEPROC
-   depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && 
RPMSG_QCOM_SMD=n)
+   depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
select MFD_SYSCON
select QCOM_RPROC_COMMON
select QCOM_SCM
@@ -104,7 +104,7 @@ config QCOM_Q6V5_PIL
 config QCOM_WCNSS_PIL
tristate "Qualcomm WCNSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
-   depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && 
RPMSG_QCOM_SMD=n)
+   depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on QCOM_SMEM
depends on REMOTEPROC
select QCOM_MDT_LOADER
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index f12ac0b28263..edc008f55663 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -16,7 +16,6 @@ config RPMSG_CHAR
 config RPMSG_QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
depends on QCOM_SMEM
-   depends on QCOM_SMD=n
select RPMSG
help
  Say y here to enable support for the Qualcomm Shared Memory Driver
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 4e090c697eb6..9fca977ef18d 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -33,14 +33,6 @@ config QCOM_SMEM
  The driver provides an interface to items in a heap shared among all
  processors in a Qualcomm platform.
 
-config QCOM_SMD
-   tristate "Qualcomm Shared Memory Driver (SMD)"
-   depends on QCOM_SMEM
-   help
- Say y here to enable support for the Qualcomm Shared Memory Driver
- providing communication channels to remote processors in Qualcomm
- platforms.
-
 config QCOM_SMD_RPM
tristate "Qualcomm Resource Power Manager (RPM) over SMD"
depends on ARCH_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 1f30260b06b8..414f0de274fa 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,7 +1,6 @@
 obj-$(CONFIG_QCOM_GSBI)+=  qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)  += mdt_loader.o
 obj-$(CONFIG_QCOM_PM)  +=  spm.o
-obj-$(CONFIG_QCOM_SMD) +=  smd.o
 obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o
 obj-$(CONFIG_QCOM_SMEM) += smem.o
 obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
deleted file mode 100644
index 322034ab9d37..
--- a/drivers/soc/qcom/smd.c
+++ /dev/null
@@ -1,1560 +0,0 @@
-/*
- * Copyright (c) 2015, Sony Mobile Communications AB.
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-/*
- * The Qualcomm Shared Memory commu

[PATCH v2 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg

2017-03-27 Thread Bjorn Andersson
By moving these client drivers to use RPMSG instead of the direct SMD
API we can reuse them ontop of the newly added GLINK wire-protocol
support found in the 820 and 835 Qualcomm platforms.

As the new (RPMSG-based) and old SMD implementations are mutually
exclusive we have to change all client drivers in one commit, to make
sure we have a working system before and after this transition.

Acked-by: Andy Gross <andy.gr...@linaro.org>
Acked-by: Kalle Valo <kv...@codeaurora.org>
Acked-by: Marcel Holtmann <mar...@holtmann.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v1:
- Add dependency on ARCH_QCOM for soc config options, to match the fact that
  drivers/soc/Makefile only enters qcom/ iff ARCH_QCOM is set.

 drivers/bluetooth/Kconfig  |  2 +-
 drivers/bluetooth/btqcomsmd.c  | 32 +--
 drivers/net/wireless/ath/wcn36xx/Kconfig   |  2 +-
 drivers/net/wireless/ath/wcn36xx/main.c|  6 ++--
 drivers/net/wireless/ath/wcn36xx/smd.c | 10 +++---
 drivers/net/wireless/ath/wcn36xx/smd.h |  6 ++--
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  2 +-
 drivers/soc/qcom/Kconfig   |  6 ++--
 drivers/soc/qcom/smd-rpm.c | 43 +
 drivers/soc/qcom/wcnss_ctrl.c  | 50 +-
 include/linux/soc/qcom/wcnss_ctrl.h| 11 ---
 net/qrtr/Kconfig   |  2 +-
 net/qrtr/smd.c | 42 -
 13 files changed, 110 insertions(+), 104 deletions(-)

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 08e054507d0b..a6a9dd4d0eef 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -344,7 +344,7 @@ config BT_WILINK
 
 config BT_QCOMSMD
tristate "Qualcomm SMD based HCI support"
-   depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
+   depends on RPMSG || (COMPILE_TEST && RPMSG=n)
depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n)
select BT_QCA
help
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c
index 8d4868af9bbd..ef730c173d4b 100644
--- a/drivers/bluetooth/btqcomsmd.c
+++ b/drivers/bluetooth/btqcomsmd.c
@@ -14,7 +14,7 @@
 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
@@ -26,8 +26,8 @@
 struct btqcomsmd {
struct hci_dev *hdev;
 
-   struct qcom_smd_channel *acl_channel;
-   struct qcom_smd_channel *cmd_channel;
+   struct rpmsg_endpoint *acl_channel;
+   struct rpmsg_endpoint *cmd_channel;
 };
 
 static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
@@ -48,19 +48,19 @@ static int btqcomsmd_recv(struct hci_dev *hdev, unsigned 
int type,
return hci_recv_frame(hdev, skb);
 }
 
-static int btqcomsmd_acl_callback(struct qcom_smd_channel *channel,
- const void *data, size_t count)
+static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
+ int count, void *priv, u32 addr)
 {
-   struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
+   struct btqcomsmd *btq = priv;
 
btq->hdev->stat.byte_rx += count;
return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
 }
 
-static int btqcomsmd_cmd_callback(struct qcom_smd_channel *channel,
- const void *data, size_t count)
+static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
+ int count, void *priv, u32 addr)
 {
-   struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
+   struct btqcomsmd *btq = priv;
 
return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
 }
@@ -72,12 +72,12 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct 
sk_buff *skb)
 
switch (hci_skb_pkt_type(skb)) {
case HCI_ACLDATA_PKT:
-   ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len);
+   ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
hdev->stat.acl_tx++;
hdev->stat.byte_tx += skb->len;
break;
case HCI_COMMAND_PKT:
-   ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len);
+   ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
hdev->stat.cmd_tx++;
break;
default:
@@ -114,18 +114,15 @@ static int btqcomsmd_probe(struct platform_device *pdev)
wcnss = dev_get_drvdata(pdev->dev.parent);
 
btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
-  btqcomsmd_acl_callback);
+  btqcomsmd_acl_callback, btq);
if (IS_ERR(btq->acl_

Re: [PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg

2017-03-27 Thread Bjorn Andersson
On Thu 23 Mar 16:56 PDT 2017, David Miller wrote:

> From: Bjorn Andersson <bjorn.anders...@linaro.org>
> Date: Wed, 22 Mar 2017 14:57:33 -0700
> 
> > On Wed 22 Mar 11:44 PDT 2017, David Miller wrote:
> > 
> >> From: Bjorn Andersson <bjorn.anders...@linaro.org>
> >> Date: Mon, 20 Mar 2017 16:35:42 -0700
> >> 
> >> What is the status of the Kconfig dependency fix and how will I be
> >> getting it?
> >> 
> > 
> > There are two Kconfig dependencies in play here, the first is
> > c3104aae5d8c ("remoteproc: qcom: fix QCOM_SMD dependencies"), this was
> > picked up by Linus yesterday and will as such be in v4.10-rc4.
> > 
> > The other dependency, is the one Marcel wants you to pick up here is
> > https://patchwork.kernel.org/patch/9635385/. It's on LKML, but if you
> > want I can resend it with you as direct recipient, with Marcel's ack.
> > 
> > Likely Arnd would like this fix to be sent upstream for v4.11 already.
> > 
> >> Second, should I merge all three of these patches to net-next or just
> >> this one?
> >> 
> > 
> > I would like all three to be merged in this cycle and in addition I have
> > a couple of patches coming up that will cause some minor conflicts with
> > patch 2 - so I would prefer if patch 2 was available in a tag I can
> > merge into my tree.
> 
> I should have all the dependencies in net-next now, but when I apply
> this series I get undefined symbols:
> 

I'm sorry, but I can't figure out how to reproduce this. I took the
master branch of net-next and applied the three patches in this series.

> [davem@localhost net-next]$ time make -s -j8
> Kernel: arch/x86/boot/bzImage is ready  (#578)
> ERROR: "qcom_rpm_smd_write" [drivers/regulator/qcom_smd-regulator.ko] 
> undefined!

According to drivers/regulator/Kconfig REGULATOR_QCOM_SMD_RPM depends on
QCOM_SMD_RPM and there's nothing tricky here. So if the Kconfig
dependency is met you should have qcom_rpm_smd_write().

> ERROR: "qcom_wcnss_open_channel" 
> [drivers/net/wireless/ath/wcn36xx/wcn36xx.ko] undefined!

WCN36XX depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n, in other words
either qcom_wcnss_open_channel() should be defined from
drivers/soc/qcom/wcnss_ctrl.o (or .ko) or be stubbed by
include/linux/soc/qcom/wcnss_ctrl.h

> ERROR: "qcom_rpm_smd_write" [drivers/clk/qcom/clk-smd-rpm.ko] undefined!

As with REGULATOR_QCOM_SMD_RPM, this depends on QCOM_SMD_RPM - so it
should be covered.

> ERROR: "qcom_wcnss_open_channel" [drivers/bluetooth/btqcomsmd.ko] undefined!

This is the problem that was corrected by  6e9e6cc8f4e4 ("Bluetooth:
btqcomsmd: fix compile-test dependency") and with the same dependencies
as CONFIG_WCN36XX I don't see how this can happen (with that patch
applied).

> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
> 
> Please fix this up.

Can you please help me figure this out?

Perhaps you can help me figure it out by letting me know the state of
the following config options in your local .config?

CONFIG_QCOM_SMD_RPM
CONFIG_QCOM_WCNSS_CTRL
CONFIG_REGULATOR_QCOM_SMD_RPM
CONFIG_RPMSG
CONFIG_WCN36XX

I'm sorry for the inconvenience.

Regards,
Bjorn


Re: [PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg

2017-03-22 Thread Bjorn Andersson
On Wed 22 Mar 11:44 PDT 2017, David Miller wrote:

> From: Bjorn Andersson <bjorn.anders...@linaro.org>
> Date: Mon, 20 Mar 2017 16:35:42 -0700
> 
> > By moving these client drivers to use RPMSG instead of the direct SMD
> > API we can reuse them ontop of the newly added GLINK wire-protocol
> > support found in the 820 and 835 Qualcomm platforms.
> > 
> > As the new (RPMSG-based) and old SMD implementations are mutually
> > exclusive we have to change all client drivers in one commit, to make
> > sure we have a working system before and after this transition.
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> > ---
> > 
> > Based on v4.11-rc3 with Arnd's Kconfig dependency fixes for BT_QCOMSMD
> > (https://lkml.org/lkml/2017/3/20/1038).
> 
> Just some questions since I'm supposed to merge this into my net-next
> tree.
> 
> What is the status of the Kconfig dependency fix and how will I be
> getting it?
> 

There are two Kconfig dependencies in play here, the first is
c3104aae5d8c ("remoteproc: qcom: fix QCOM_SMD dependencies"), this was
picked up by Linus yesterday and will as such be in v4.10-rc4.

The other dependency, is the one Marcel wants you to pick up here is
https://patchwork.kernel.org/patch/9635385/. It's on LKML, but if you
want I can resend it with you as direct recipient, with Marcel's ack.

Likely Arnd would like this fix to be sent upstream for v4.11 already.

> Second, should I merge all three of these patches to net-next or just
> this one?
> 

I would like all three to be merged in this cycle and in addition I have
a couple of patches coming up that will cause some minor conflicts with
patch 2 - so I would prefer if patch 2 was available in a tag I can
merge into my tree.

Would it be possible for you to prepare merge all 4 (these 3 and the
bluetooth fix) and prepare a tag for Andy, Marcel and myself to include
in our trees?

Regards,
Bjorn


[PATCH 3/3] soc: qcom: smd-rpm: Add msm8996 compatibility

2017-03-20 Thread Bjorn Andersson
With the RPM driver transitioned to RPMSG we can reuse the SMD-RPM
driver ontop of GLINK for 8996, without any modifications.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/soc/qcom/smd-rpm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 0dcf1bf33126..c2346752b3ea 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -225,6 +225,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-apq8084" },
{ .compatible = "qcom,rpm-msm8916" },
{ .compatible = "qcom,rpm-msm8974" },
+   { .compatible = "qcom,rpm-msm8996" },
{}
 };
 MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
-- 
2.12.0



[PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg

2017-03-20 Thread Bjorn Andersson
By moving these client drivers to use RPMSG instead of the direct SMD
API we can reuse them ontop of the newly added GLINK wire-protocol
support found in the 820 and 835 Qualcomm platforms.

As the new (RPMSG-based) and old SMD implementations are mutually
exclusive we have to change all client drivers in one commit, to make
sure we have a working system before and after this transition.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Based on v4.11-rc3 with Arnd's Kconfig dependency fixes for BT_QCOMSMD
(https://lkml.org/lkml/2017/3/20/1038).

 drivers/bluetooth/Kconfig  |  2 +-
 drivers/bluetooth/btqcomsmd.c  | 32 +--
 drivers/net/wireless/ath/wcn36xx/Kconfig   |  2 +-
 drivers/net/wireless/ath/wcn36xx/main.c|  6 ++--
 drivers/net/wireless/ath/wcn36xx/smd.c | 10 +++---
 drivers/net/wireless/ath/wcn36xx/smd.h |  6 ++--
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  2 +-
 drivers/soc/qcom/Kconfig   |  4 +--
 drivers/soc/qcom/smd-rpm.c | 43 +
 drivers/soc/qcom/wcnss_ctrl.c  | 50 +-
 include/linux/soc/qcom/wcnss_ctrl.h| 11 ---
 net/qrtr/Kconfig   |  2 +-
 net/qrtr/smd.c | 42 -
 13 files changed, 108 insertions(+), 104 deletions(-)

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 08e054507d0b..a6a9dd4d0eef 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -344,7 +344,7 @@ config BT_WILINK
 
 config BT_QCOMSMD
tristate "Qualcomm SMD based HCI support"
-   depends on QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n)
+   depends on RPMSG || (COMPILE_TEST && RPMSG=n)
depends on QCOM_WCNSS_CTRL || (COMPILE_TEST && QCOM_WCNSS_CTRL=n)
select BT_QCA
help
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c
index 8d4868af9bbd..ef730c173d4b 100644
--- a/drivers/bluetooth/btqcomsmd.c
+++ b/drivers/bluetooth/btqcomsmd.c
@@ -14,7 +14,7 @@
 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
@@ -26,8 +26,8 @@
 struct btqcomsmd {
struct hci_dev *hdev;
 
-   struct qcom_smd_channel *acl_channel;
-   struct qcom_smd_channel *cmd_channel;
+   struct rpmsg_endpoint *acl_channel;
+   struct rpmsg_endpoint *cmd_channel;
 };
 
 static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
@@ -48,19 +48,19 @@ static int btqcomsmd_recv(struct hci_dev *hdev, unsigned 
int type,
return hci_recv_frame(hdev, skb);
 }
 
-static int btqcomsmd_acl_callback(struct qcom_smd_channel *channel,
- const void *data, size_t count)
+static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
+ int count, void *priv, u32 addr)
 {
-   struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
+   struct btqcomsmd *btq = priv;
 
btq->hdev->stat.byte_rx += count;
return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
 }
 
-static int btqcomsmd_cmd_callback(struct qcom_smd_channel *channel,
- const void *data, size_t count)
+static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
+ int count, void *priv, u32 addr)
 {
-   struct btqcomsmd *btq = qcom_smd_get_drvdata(channel);
+   struct btqcomsmd *btq = priv;
 
return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
 }
@@ -72,12 +72,12 @@ static int btqcomsmd_send(struct hci_dev *hdev, struct 
sk_buff *skb)
 
switch (hci_skb_pkt_type(skb)) {
case HCI_ACLDATA_PKT:
-   ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len);
+   ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
hdev->stat.acl_tx++;
hdev->stat.byte_tx += skb->len;
break;
case HCI_COMMAND_PKT:
-   ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len);
+   ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
hdev->stat.cmd_tx++;
break;
default:
@@ -114,18 +114,15 @@ static int btqcomsmd_probe(struct platform_device *pdev)
wcnss = dev_get_drvdata(pdev->dev.parent);
 
btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
-  btqcomsmd_acl_callback);
+  btqcomsmd_acl_callback, btq);
if (IS_ERR(btq->acl_channel))
return PTR_ERR(btq->acl_channel);
 
btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
-   

[PATCH 2/3] soc: qcom: smd: Remove standalone driver

2017-03-20 Thread Bjorn Andersson
Remove the standalone SMD implementation as we have transitioned the
client drivers to use the RPMSG based one.

Also remove all dependencies on QCOM_SMD from Kconfig files, in order to
keep them selectable in the absence of the removed symbol.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Based on v4.11-rc3 with Arnd's Kconfig dependency fixes in remoteproc
(https://lkml.org/lkml/2017/3/20/1027).

 drivers/remoteproc/Kconfig |6 +-
 drivers/rpmsg/Kconfig  |1 -
 drivers/soc/qcom/Kconfig   |8 -
 drivers/soc/qcom/Makefile  |1 -
 drivers/soc/qcom/smd.c | 1560 
 include/linux/rpmsg/qcom_smd.h |2 +-
 include/linux/soc/qcom/smd.h   |  139 
 7 files changed, 4 insertions(+), 1713 deletions(-)
 delete mode 100644 drivers/soc/qcom/smd.c
 delete mode 100644 include/linux/soc/qcom/smd.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 1dc43fc5f65f..faad69a1a597 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -76,7 +76,7 @@ config QCOM_ADSP_PIL
depends on OF && ARCH_QCOM
depends on REMOTEPROC
depends on QCOM_SMEM
-   depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && 
RPMSG_QCOM_SMD=n)
+   depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
select MFD_SYSCON
select QCOM_MDT_LOADER
select QCOM_RPROC_COMMON
@@ -93,7 +93,7 @@ config QCOM_Q6V5_PIL
depends on OF && ARCH_QCOM
depends on QCOM_SMEM
depends on REMOTEPROC
-   depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && 
RPMSG_QCOM_SMD=n)
+   depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
select MFD_SYSCON
select QCOM_RPROC_COMMON
select QCOM_SCM
@@ -104,7 +104,7 @@ config QCOM_Q6V5_PIL
 config QCOM_WCNSS_PIL
tristate "Qualcomm WCNSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
-   depends on RPMSG_QCOM_SMD || QCOM_SMD || (COMPILE_TEST && QCOM_SMD=n && 
RPMSG_QCOM_SMD=n)
+   depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
depends on QCOM_SMEM
depends on REMOTEPROC
select QCOM_MDT_LOADER
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index f12ac0b28263..edc008f55663 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -16,7 +16,6 @@ config RPMSG_CHAR
 config RPMSG_QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
depends on QCOM_SMEM
-   depends on QCOM_SMD=n
select RPMSG
help
  Say y here to enable support for the Qualcomm Shared Memory Driver
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 751dce0c19b3..4428a580a995 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -33,14 +33,6 @@ config QCOM_SMEM
  The driver provides an interface to items in a heap shared among all
  processors in a Qualcomm platform.
 
-config QCOM_SMD
-   tristate "Qualcomm Shared Memory Driver (SMD)"
-   depends on QCOM_SMEM
-   help
- Say y here to enable support for the Qualcomm Shared Memory Driver
- providing communication channels to remote processors in Qualcomm
- platforms.
-
 config QCOM_SMD_RPM
tristate "Qualcomm Resource Power Manager (RPM) over SMD"
depends on RPMSG && OF
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 1f30260b06b8..414f0de274fa 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,7 +1,6 @@
 obj-$(CONFIG_QCOM_GSBI)+=  qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)  += mdt_loader.o
 obj-$(CONFIG_QCOM_PM)  +=  spm.o
-obj-$(CONFIG_QCOM_SMD) +=  smd.o
 obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o
 obj-$(CONFIG_QCOM_SMEM) += smem.o
 obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
deleted file mode 100644
index 322034ab9d37..
--- a/drivers/soc/qcom/smd.c
+++ /dev/null
@@ -1,1560 +0,0 @@
-/*
- * Copyright (c) 2015, Sony Mobile Communications AB.
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 

[PATCH] wcn36xx: Implement cancel_hw_scan

2017-02-01 Thread Bjorn Andersson
In the even that the wcn36xx interface is brought down while a hw_scan
is active we must abort and wait for the ongoing scan to signal
completion to mac80211.

Reported-by: Mart Raudsepp <l...@gentoo.org>
Fixes: 886039036c20 ("wcn36xx: Implement firmware assisted scan")
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/main.c| 25 -
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  1 +
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index a24edf33be93..bb7110f7fc86 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -574,6 +574,7 @@ static void wcn36xx_hw_scan_worker(struct work_struct *work)
struct cfg80211_scan_request *req = wcn->scan_req;
u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
struct cfg80211_scan_info scan_info = {};
+   bool aborted = false;
int i;
 
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", 
req->n_channels);
@@ -585,6 +586,13 @@ static void wcn36xx_hw_scan_worker(struct work_struct 
*work)
 
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
for (i = 0; i < req->n_channels; i++) {
+   mutex_lock(>scan_lock);
+   aborted = wcn->scan_aborted;
+   mutex_unlock(>scan_lock);
+
+   if (aborted)
+   break;
+
wcn->scan_freq = req->channels[i]->center_freq;
wcn->scan_band = req->channels[i]->band;
 
@@ -596,7 +604,7 @@ static void wcn36xx_hw_scan_worker(struct work_struct *work)
}
wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
 
-   scan_info.aborted = false;
+   scan_info.aborted = aborted;
ieee80211_scan_completed(wcn->hw, _info);
 
mutex_lock(>scan_lock);
@@ -615,6 +623,8 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
mutex_unlock(>scan_lock);
return -EBUSY;
}
+
+   wcn->scan_aborted = false;
wcn->scan_req = _req->req;
mutex_unlock(>scan_lock);
 
@@ -623,6 +633,18 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
return 0;
 }
 
+static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif)
+{
+   struct wcn36xx *wcn = hw->priv;
+
+   mutex_lock(>scan_lock);
+   wcn->scan_aborted = true;
+   mutex_unlock(>scan_lock);
+
+   cancel_work_sync(>scan_work);
+}
+
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
 enum nl80211_band band)
 {
@@ -1034,6 +1056,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
.hw_scan= wcn36xx_hw_scan,
+   .cancel_hw_scan = wcn36xx_cancel_hw_scan,
.bss_info_changed   = wcn36xx_bss_info_changed,
.set_rts_threshold  = wcn36xx_set_rts_threshold,
.sta_add= wcn36xx_sta_add,
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 571e9f76da7e..b52b4da9a967 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -220,6 +220,7 @@ struct wcn36xx {
int scan_freq;
int scan_band;
struct mutexscan_lock;
+   boolscan_aborted;
 
/* DXE channels */
struct wcn36xx_dxe_ch   dxe_tx_l_ch;/* TX low */
-- 
2.11.0



Re: [v5,1/5] soc: qcom: smem_state: Fix include for ERR_PTR()

2016-11-18 Thread Bjorn Andersson
On Wed 16 Nov 10:49 PST 2016, Kalle Valo wrote:

> Bjorn Andersson <bjorn.anders...@linaro.org> wrote:
> > The correct include file for getting errno constants and ERR_PTR() is
> > linux/err.h, rather than linux/errno.h, so fix the include.
> > 
> > Fixes: e8b123e60084 ("soc: qcom: smem_state: Add stubs for disabled 
> > smem_state")
> > Acked-by: Andy Gross <andy.gr...@linaro.org>
> > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> 
> For some reason this fails to compile now. Can you take a look, please?
> 
> ERROR: "qcom_wcnss_open_channel" 
> [drivers/net/wireless/ath/wcn36xx/wcn36xx.ko] undefined!
> make[1]: *** [__modpost] Error 1
> make: *** [modules] Error 2
> 
> 5 patches set to Changes Requested.
> 
> 9429045 [v5,1/5] soc: qcom: smem_state: Fix include for ERR_PTR()
> 9429047 [v5,2/5] wcn36xx: Transition driver to SMD client

This patch was updated with the necessary depends in Kconfig to catch
this exact issue and when I pull in your .config (which has QCOM_SMD=n,
QCOM_WCNSS_CTRL=n and WCN36XX=y) I can build this just fine.

I've tested the various combinations and it seems to work fine. Do you
have any other patches in your tree? Any stale objects?

Would you mind retesting this, before I invest more time in trying to
reproduce the issue you're seeing?

Regards,
Bjorn


[PATCH v5 1/5] soc: qcom: smem_state: Fix include for ERR_PTR()

2016-11-14 Thread Bjorn Andersson
The correct include file for getting errno constants and ERR_PTR() is
linux/err.h, rather than linux/errno.h, so fix the include.

Fixes: e8b123e60084 ("soc: qcom: smem_state: Add stubs for disabled smem_state")
Acked-by: Andy Gross <andy.gr...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Kalle, please merge this patch through your tree.

Changes since v4:
- New patch

 include/linux/soc/qcom/smem_state.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/soc/qcom/smem_state.h 
b/include/linux/soc/qcom/smem_state.h
index 7b88697929e9..b8478ee7a71f 100644
--- a/include/linux/soc/qcom/smem_state.h
+++ b/include/linux/soc/qcom/smem_state.h
@@ -1,7 +1,7 @@
 #ifndef __QCOM_SMEM_STATE__
 #define __QCOM_SMEM_STATE__
 
-#include 
+#include 
 
 struct device_node;
 struct qcom_smem_state;
-- 
2.5.0



[PATCH v5 2/5] wcn36xx: Transition driver to SMD client

2016-11-14 Thread Bjorn Andersson
The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
channel, as such it should be a SMD client. This patch makes this
transition, now that we have the necessary frameworks available.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v4:
- Added Kconfig dependency to handle dependencies compiled as modules

 drivers/net/wireless/ath/wcn36xx/Kconfig   |  2 +
 drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
 drivers/net/wireless/ath/wcn36xx/main.c| 79 --
 drivers/net/wireless/ath/wcn36xx/smd.c | 31 +---
 drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
 6 files changed, 88 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig 
b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..4b83e87f0b94 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,8 @@
 config WCN36XX
tristate "Qualcomm Atheros WCN3660/3680 support"
depends on MAC80211 && HAS_DMA
+   depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n
+   depends on QCOM_SMD || QCOM_SMD=n
---help---
  This module adds support for wireless adapters based on
  Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 231fd022f0f5..87dfdaf9044c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -23,6 +23,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
goto out_err;
 
/* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
-   ret = wcn->ctrl_ops->smsm_change_state(
-   WCN36XX_SMSM_WLAN_TX_ENABLE,
-   WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE |
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   if (ret)
+   goto out_err;
 
return 0;
 
@@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
 * notify chip about new frame through SMSM bus.
 */
if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
-   wcn->ctrl_ops->smsm_change_state(
- 0,
- WCN36XX_SMSM_WLAN_TX_ENABLE);
+   qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+   WCN36XX_SMSM_WLAN_TX_ENABLE,
+   WCN36XX_SMSM_WLAN_TX_ENABLE);
} else {
/* indicate End Of Packet and generate interrupt on descriptor
 * done.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index e1d59da2ad20..3c2522b07c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -21,6 +21,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
int ret;
 
/* Set TX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlantx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
if (!res) {
wcn36xx_err("failed to get tx_irq\n");
return -ENOENT;
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct 
wcn36xx *wcn,
wcn->tx_irq = res->start;
 
/* Set RX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlanrx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
if (!res) {
wcn36xx_err("failed to get rx_irq\n");
return -ENOENT;
}
wcn->rx_irq = res->start;
 
+   /* Acquire SMSM tx enable handle */
+   wcn->tx_enable_state = qcom_smem_state_get(>dev,
+   "tx-enable", >tx_enable_state_bit);
+   if (IS_ERR(wcn->tx_enable_state)) {
+   wcn36xx_err("failed to get tx-enable state\n");
+   return PTR_ERR(wcn->tx_enable_state);
+   }
+
+   /* Acquire SMSM t

[PATCH v5 4/5] wcn36xx: Implement print_reg indication

2016-11-14 Thread Bjorn Andersson
Some firmware versions sends a "print register indication", handle this
by printing out the content.

Cc: Nicolas Dechesne <n...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v4:
- None

 drivers/net/wireless/ath/wcn36xx/hal.h | 16 
 drivers/net/wireless/ath/wcn36xx/smd.c | 30 ++
 2 files changed, 46 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index 4f87ef1e1eb8..b765c647319d 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -350,6 +350,8 @@ enum wcn36xx_hal_host_msg_type {
 
WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
 
+   WCN36XX_HAL_PRINT_REG_INFO_IND = 259,
+
WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE
 };
 
@@ -4703,4 +4705,18 @@ struct stats_class_b_ind {
u32 rx_time_total;
 };
 
+/* WCN36XX_HAL_PRINT_REG_INFO_IND */
+struct wcn36xx_hal_print_reg_info_ind {
+   struct wcn36xx_hal_msg_header header;
+
+   u32 count;
+   u32 scenario;
+   u32 reason;
+
+   struct {
+   u32 addr;
+   u32 value;
+   } regs[];
+} __packed;
+
 #endif /* _HAL_H_ */
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index be5e5ea1e5c3..1c2966f7db7a 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2109,6 +2109,30 @@ static int wcn36xx_smd_delete_sta_context_ind(struct 
wcn36xx *wcn,
return -ENOENT;
 }
 
+static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
+ void *buf,
+ size_t len)
+{
+   struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
+   int i;
+
+   if (len < sizeof(*rsp)) {
+   wcn36xx_warn("Corrupted print reg info indication\n");
+   return -EIO;
+   }
+
+   wcn36xx_dbg(WCN36XX_DBG_HAL,
+   "reginfo indication, scenario: 0x%x reason: 0x%x\n",
+   rsp->scenario, rsp->reason);
+
+   for (i = 0; i < rsp->count; i++) {
+   wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
+   rsp->regs[i].addr, rsp->regs[i].value);
+   }
+
+   return 0;
+}
+
 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
 {
struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
@@ -2237,6 +2261,7 @@ int wcn36xx_smd_rsp_process(struct qcom_smd_channel 
*channel,
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
+   case WCN36XX_HAL_PRINT_REG_INFO_IND:
msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
if (!msg_ind) {
wcn36xx_err("Run out of memory while handling SMD_EVENT 
(%d)\n",
@@ -2296,6 +2321,11 @@ static void wcn36xx_ind_smd_work(struct work_struct 
*work)
   hal_ind_msg->msg,
   hal_ind_msg->msg_len);
break;
+   case WCN36XX_HAL_PRINT_REG_INFO_IND:
+   wcn36xx_smd_print_reg_info_ind(wcn,
+  hal_ind_msg->msg,
+  hal_ind_msg->msg_len);
+   break;
default:
wcn36xx_err("SMD_EVENT (%d) not supported\n",
  msg_header->msg_type);
-- 
2.5.0



[PATCH v5 3/5] wcn36xx: Implement firmware assisted scan

2016-11-14 Thread Bjorn Andersson
Using the software based channel scan mechanism from mac80211 keeps us
offline for 10-15 second, we should instead issue a start_scan/end_scan
on each channel reducing this time.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v4:
- None

 drivers/net/wireless/ath/wcn36xx/main.c| 64 +-
 drivers/net/wireless/ath/wcn36xx/smd.c |  8 ++--
 drivers/net/wireless/ath/wcn36xx/smd.h |  4 +-
 drivers/net/wireless/ath/wcn36xx/txrx.c| 19 ++---
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  9 +
 5 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 3c2522b07c90..96a9584edcbb 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -568,23 +568,59 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
 {
-   struct wcn36xx *wcn = hw->priv;
+   struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+   struct cfg80211_scan_request *req = wcn->scan_req;
+   u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+   struct cfg80211_scan_info scan_info = {};
+   int i;
+
+   wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", 
req->n_channels);
+
+   for (i = 0; i < req->n_channels; i++)
+   channels[i] = req->channels[i]->hw_value;
+
+   wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
 
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
-   wcn36xx_smd_start_scan(wcn);
+   for (i = 0; i < req->n_channels; i++) {
+   wcn->scan_freq = req->channels[i]->center_freq;
+   wcn->scan_band = req->channels[i]->band;
+
+   wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+   msleep(30);
+   wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+   wcn->scan_freq = 0;
+   }
+   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+   scan_info.aborted = false;
+   ieee80211_scan_completed(wcn->hw, _info);
+
+   mutex_lock(>scan_lock);
+   wcn->scan_req = NULL;
+   mutex_unlock(>scan_lock);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif,
+  struct ieee80211_scan_request *hw_req)
 {
struct wcn36xx *wcn = hw->priv;
 
-   wcn36xx_smd_end_scan(wcn);
-   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+   mutex_lock(>scan_lock);
+   if (wcn->scan_req) {
+   mutex_unlock(>scan_lock);
+   return -EBUSY;
+   }
+   wcn->scan_req = _req->req;
+   mutex_unlock(>scan_lock);
+
+   schedule_work(>scan_work);
+
+   return 0;
 }
 
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@@ -997,8 +1033,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.configure_filter   = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
-   .sw_scan_start  = wcn36xx_sw_scan_start,
-   .sw_scan_complete   = wcn36xx_sw_scan_complete,
+   .hw_scan= wcn36xx_hw_scan,
.bss_info_changed   = wcn36xx_bss_info_changed,
.set_rts_threshold  = wcn36xx_set_rts_threshold,
.sta_add= wcn36xx_sta_add,
@@ -1023,6 +1058,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
+   ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
 
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -1032,6 +1068,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz;
wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz;
 
+   wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
+   wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
+
wcn->hw->wiphy->cipher_suites = cipher_suites;
wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
@@ -1152,6 +1191,9 @@ static int wcn36xx_probe(struct platform_devic

[PATCH v5 5/5] wcn36xx: Don't use the destroyed hal_mutex

2016-11-14 Thread Bjorn Andersson
ieee80211_unregister_hw() might invoke operations to stop the interface,
that uses the hal_mutex. So don't destroy it until after we're done
using it.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

With this patch I can successfully (although with a SMD send timeout in the
shutdown path) start and stop the WCNSS PIL/remoteproc multiple times and the
wlan0 interface will come and go accordingly.

Will submit the necessary DT patches soon as well.

Changes since v4:
- New patch

 drivers/net/wireless/ath/wcn36xx/main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 96a9584edcbb..0002190c9041 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1241,7 +1241,6 @@ static int wcn36xx_remove(struct platform_device *pdev)
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
 
release_firmware(wcn->nv);
-   mutex_destroy(>hal_mutex);
 
ieee80211_unregister_hw(hw);
 
@@ -1250,6 +1249,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
 
iounmap(wcn->dxe_base);
iounmap(wcn->ccu_base);
+
+   mutex_destroy(>hal_mutex);
ieee80211_free_hw(hw);
 
return 0;
-- 
2.5.0



Re: [PATCH 1/2] wcn36xx: Correct Kconfig dependency

2016-11-09 Thread Bjorn Andersson
On Wed 09 Nov 12:32 PST 2016, Marcel Holtmann wrote:

> Hi Bjorn,
> 
> > In the case SMD or WCNSS_CTRL are compiled as modules, wcn36xx must be
> > compiled as module as well, so we need to mention this dependency.
> > But we still want allow the driver to be compiled in case either of
> > those are =n, for compile testing reasons.
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> > ---
> > drivers/net/wireless/ath/wcn36xx/Kconfig | 2 ++
> > 1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig 
> > b/drivers/net/wireless/ath/wcn36xx/Kconfig
> > index 591ebaea8265..4b83e87f0b94 100644
> > --- a/drivers/net/wireless/ath/wcn36xx/Kconfig
> > +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
> > @@ -1,6 +1,8 @@
> > config WCN36XX
> > tristate "Qualcomm Atheros WCN3660/3680 support"
> > depends on MAC80211 && HAS_DMA
> > +   depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n
> > +   depends on QCOM_SMD || QCOM_SMD=n
> 
> I thought we wanted to move towards being able to compile the WiFi and
> Bluetooth support without requiring QCOM_SMD.
> 

That's right.

The problem I spotted was that without the dependency on QCOM_SMD we're
allowed to compile these modules as builtin, but as
IS_ENABLED(CONFIG_QCOM_SMD) is true we don't get the stubs and as such
the kernel doesn't link.

So we must enforce these modules to be compiled as modules if either
QCOM_SMD or QCOM_WCNSS_CTRL are compiled as modules, and we do that with
the first part of the depends lines.


The second part of the depends lines states that the alternative
dependency is that the modules are not enabled at all, in which case we
will fall back to using the function stubs.

So this is unfortunately how we have to describe it in Kconfig to work
with the function stubs, sorry for not getting this right in the first
place.

Regards,
Bjorn


[PATCH 2/2] soc: qcom: smem_state: Fix include for ERR_PTR()

2016-11-09 Thread Bjorn Andersson
The correct include file for getting errno constants and ERR_PTR() is
linux/err.h, rather than linux/errno.h, so fix the include.

Fixes: e8b123e60084 ("soc: qcom: smem_state: Add stubs for disabled smem_state")
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Andy, I don't see anything else going into v4.10 for smem_state.h. So if you
are okay I would like Kalle to pick this patch through his tree and be able to
merge my wcn36xx patches for v4.10.

 include/linux/soc/qcom/smem_state.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/soc/qcom/smem_state.h 
b/include/linux/soc/qcom/smem_state.h
index 7b88697929e9..b8478ee7a71f 100644
--- a/include/linux/soc/qcom/smem_state.h
+++ b/include/linux/soc/qcom/smem_state.h
@@ -1,7 +1,7 @@
 #ifndef __QCOM_SMEM_STATE__
 #define __QCOM_SMEM_STATE__
 
-#include 
+#include 
 
 struct device_node;
 struct qcom_smem_state;
-- 
2.5.0



[PATCH 1/2] wcn36xx: Correct Kconfig dependency

2016-11-09 Thread Bjorn Andersson
In the case SMD or WCNSS_CTRL are compiled as modules, wcn36xx must be
compiled as module as well, so we need to mention this dependency.
But we still want allow the driver to be compiled in case either of
those are =n, for compile testing reasons.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig 
b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..4b83e87f0b94 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,8 @@
 config WCN36XX
tristate "Qualcomm Atheros WCN3660/3680 support"
depends on MAC80211 && HAS_DMA
+   depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n
+   depends on QCOM_SMD || QCOM_SMD=n
---help---
  This module adds support for wireless adapters based on
  Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
-- 
2.5.0



Re: [PATCH v4 2/4] wcn36xx: Transition driver to SMD client

2016-09-08 Thread Bjorn Andersson
On Thu 08 Sep 10:35 PDT 2016, Kalle Valo wrote:

> Bjorn Andersson <bjorn.anders...@linaro.org> writes:
> 
> > On Thu, Sep 8, 2016 at 5:16 AM, Kalle Valo <kv...@codeaurora.org> wrote:
> >> Bjorn Andersson <bjorn.anders...@linaro.org> writes:
> >>
> >>> The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
> >>> channel, as such it should be a SMD client. This patch makes this
> >>> transition, now that we have the necessary frameworks available.
> >>>
> >>> Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> >>> ---
> >>>
> >>> Changes since v3:
> >>> - Made msg_header const in wcn36xx_smd_rsp_process()
> >>>
> >>> Changes since v2:
> >>> - Correct the call to the new ieee80211_scan_completed()
> >>>
> >>>  drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
> >>>  drivers/net/wireless/ath/wcn36xx/main.c| 79 
> >>> --
> >>>  drivers/net/wireless/ath/wcn36xx/smd.c | 31 +---
> >>>  drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
> >>>  drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
> >>>  5 files changed, 86 insertions(+), 66 deletions(-)
> >>
> >> This doesn't compile for me:
> >>
> >
> > I thought I mentioned this in the mail, sorry for missing that.
> 
> Maybe you did and I just forgot, I have a tendency to do that :)
> 
> > There is a patch for this issue in linux-next already [1] which is
> > part of [2], which was part of the pull request to arm-soc for
> > inclusion in v4.9.
> >
> > [1] https://patchwork.kernel.org/patch/9272457/
> > [2] 
> > https://git.kernel.org/cgit/linux/kernel/git/agross/linux.git/tag/?h=qcom-drivers-for-4.9
> 
> So the commit in question is:
> 
> soc: qcom: smd: Correct compile stub prototypes
> https://git.kernel.org/cgit/linux/kernel/git/agross/linux.git/commit/?h=qcom-drivers-for-4.9=3a1281848830fcb3202cfd7ffe62d19641471d05
> 

Correct

> But that's not obviously in my tree yet, but I should have it after
> 4.9-rc1 is released. I think it's easiest that I wait for that before
> applying these. Do you agree?
> 

Would be nice to have it land sooner rather than later, but I'm okay
with this.

Regards,
Bjorn


Re: [PATCH v4 2/4] wcn36xx: Transition driver to SMD client

2016-09-08 Thread Bjorn Andersson
On Thu, Sep 8, 2016 at 5:16 AM, Kalle Valo <kv...@codeaurora.org> wrote:
> Bjorn Andersson <bjorn.anders...@linaro.org> writes:
>
>> The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
>> channel, as such it should be a SMD client. This patch makes this
>> transition, now that we have the necessary frameworks available.
>>
>> Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
>> ---
>>
>> Changes since v3:
>> - Made msg_header const in wcn36xx_smd_rsp_process()
>>
>> Changes since v2:
>> - Correct the call to the new ieee80211_scan_completed()
>>
>>  drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
>>  drivers/net/wireless/ath/wcn36xx/main.c| 79 
>> --
>>  drivers/net/wireless/ath/wcn36xx/smd.c | 31 +---
>>  drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
>>  drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
>>  5 files changed, 86 insertions(+), 66 deletions(-)
>
> This doesn't compile for me:
>

I thought I mentioned this in the mail, sorry for missing that.

There is a patch for this issue in linux-next already [1] which is
part of [2], which was part of the pull request to arm-soc for
inclusion in v4.9.

[1] https://patchwork.kernel.org/patch/9272457/
[2] 
https://git.kernel.org/cgit/linux/kernel/git/agross/linux.git/tag/?h=qcom-drivers-for-4.9

Regards,
Bjorn


[PATCH v4 4/4] wcn36xx: Implement print_reg indication

2016-09-06 Thread Bjorn Andersson
Some firmware versions sends a "print register indication", handle this
by printing out the content.

Cc: Nicolas Dechesne <n...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v3:
- Rebased separate patch onto this series

 drivers/net/wireless/ath/wcn36xx/hal.h | 16 
 drivers/net/wireless/ath/wcn36xx/smd.c | 30 ++
 2 files changed, 46 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index 4f87ef1e1eb8..b765c647319d 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -350,6 +350,8 @@ enum wcn36xx_hal_host_msg_type {
 
WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
 
+   WCN36XX_HAL_PRINT_REG_INFO_IND = 259,
+
WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE
 };
 
@@ -4703,4 +4705,18 @@ struct stats_class_b_ind {
u32 rx_time_total;
 };
 
+/* WCN36XX_HAL_PRINT_REG_INFO_IND */
+struct wcn36xx_hal_print_reg_info_ind {
+   struct wcn36xx_hal_msg_header header;
+
+   u32 count;
+   u32 scenario;
+   u32 reason;
+
+   struct {
+   u32 addr;
+   u32 value;
+   } regs[];
+} __packed;
+
 #endif /* _HAL_H_ */
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index be5e5ea1e5c3..1c2966f7db7a 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2109,6 +2109,30 @@ static int wcn36xx_smd_delete_sta_context_ind(struct 
wcn36xx *wcn,
return -ENOENT;
 }
 
+static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
+ void *buf,
+ size_t len)
+{
+   struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
+   int i;
+
+   if (len < sizeof(*rsp)) {
+   wcn36xx_warn("Corrupted print reg info indication\n");
+   return -EIO;
+   }
+
+   wcn36xx_dbg(WCN36XX_DBG_HAL,
+   "reginfo indication, scenario: 0x%x reason: 0x%x\n",
+   rsp->scenario, rsp->reason);
+
+   for (i = 0; i < rsp->count; i++) {
+   wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
+   rsp->regs[i].addr, rsp->regs[i].value);
+   }
+
+   return 0;
+}
+
 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
 {
struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
@@ -2237,6 +2261,7 @@ int wcn36xx_smd_rsp_process(struct qcom_smd_channel 
*channel,
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
+   case WCN36XX_HAL_PRINT_REG_INFO_IND:
msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
if (!msg_ind) {
wcn36xx_err("Run out of memory while handling SMD_EVENT 
(%d)\n",
@@ -2296,6 +2321,11 @@ static void wcn36xx_ind_smd_work(struct work_struct 
*work)
   hal_ind_msg->msg,
   hal_ind_msg->msg_len);
break;
+   case WCN36XX_HAL_PRINT_REG_INFO_IND:
+   wcn36xx_smd_print_reg_info_ind(wcn,
+  hal_ind_msg->msg,
+  hal_ind_msg->msg_len);
+   break;
default:
wcn36xx_err("SMD_EVENT (%d) not supported\n",
  msg_header->msg_type);
-- 
2.5.0



[PATCH v4 2/4] wcn36xx: Transition driver to SMD client

2016-09-06 Thread Bjorn Andersson
The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
channel, as such it should be a SMD client. This patch makes this
transition, now that we have the necessary frameworks available.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v3:
- Made msg_header const in wcn36xx_smd_rsp_process()

Changes since v2:
- Correct the call to the new ieee80211_scan_completed()

 drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
 drivers/net/wireless/ath/wcn36xx/main.c| 79 --
 drivers/net/wireless/ath/wcn36xx/smd.c | 31 +---
 drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
 5 files changed, 86 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 231fd022f0f5..87dfdaf9044c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -23,6 +23,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
goto out_err;
 
/* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
-   ret = wcn->ctrl_ops->smsm_change_state(
-   WCN36XX_SMSM_WLAN_TX_ENABLE,
-   WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE |
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   if (ret)
+   goto out_err;
 
return 0;
 
@@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
 * notify chip about new frame through SMSM bus.
 */
if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
-   wcn->ctrl_ops->smsm_change_state(
- 0,
- WCN36XX_SMSM_WLAN_TX_ENABLE);
+   qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+   WCN36XX_SMSM_WLAN_TX_ENABLE,
+   WCN36XX_SMSM_WLAN_TX_ENABLE);
} else {
/* indicate End Of Packet and generate interrupt on descriptor
 * done.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index e1d59da2ad20..3c2522b07c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -21,6 +21,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
int ret;
 
/* Set TX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlantx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
if (!res) {
wcn36xx_err("failed to get tx_irq\n");
return -ENOENT;
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct 
wcn36xx *wcn,
wcn->tx_irq = res->start;
 
/* Set RX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlanrx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
if (!res) {
wcn36xx_err("failed to get rx_irq\n");
return -ENOENT;
}
wcn->rx_irq = res->start;
 
+   /* Acquire SMSM tx enable handle */
+   wcn->tx_enable_state = qcom_smem_state_get(>dev,
+   "tx-enable", >tx_enable_state_bit);
+   if (IS_ERR(wcn->tx_enable_state)) {
+   wcn36xx_err("failed to get tx-enable state\n");
+   return PTR_ERR(wcn->tx_enable_state);
+   }
+
+   /* Acquire SMSM tx rings empty handle */
+   wcn->tx_rings_empty_state = qcom_smem_state_get(>dev,
+   "tx-rings-empty", >tx_rings_empty_state_bit);
+   if (IS_ERR(wcn->tx_rings_empty_state)) {
+   wcn36xx_err("failed to get tx-rings-empty state\n");
+   return PTR_ERR(wcn->tx_rings_empty_state);
+   }
+
mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
if (!mmio_node) {
wcn36xx_err("failed to acquire qcom,mmio reference\n");
@@ -1115,11 +1133,14 @@ static int wcn36xx_pro

[PATCH v4 1/4] soc: qcom: wcnss_ctrl: Stub wcnss_ctrl API

2016-09-06 Thread Bjorn Andersson
Stub the wcnss_ctrl API to allow compile testing wcnss function drivers.

Cc: Marcel Holtmann <mar...@holtmann.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

There are no other pending changes colliding with this, so if Andy is okay with
this it could be merged through Kalle's tree - together with the other patches.

Marcel, with this applied we can drop the depends on QCOM_SMD from the
btqcomsmd driver as well.

Changes since v3:
- Added this patch to allow compile testing without SMD support after patch 2

 include/linux/soc/qcom/wcnss_ctrl.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/linux/soc/qcom/wcnss_ctrl.h 
b/include/linux/soc/qcom/wcnss_ctrl.h
index a37bc5538f19..eab64976a73b 100644
--- a/include/linux/soc/qcom/wcnss_ctrl.h
+++ b/include/linux/soc/qcom/wcnss_ctrl.h
@@ -3,6 +3,19 @@
 
 #include 
 
+#if IS_ENABLED(CONFIG_QCOM_WCNSS_CTRL)
+
 struct qcom_smd_channel *qcom_wcnss_open_channel(void *wcnss, const char 
*name, qcom_smd_cb_t cb);
 
+#else
+
+static inline struct qcom_smd_channel*
+qcom_wcnss_open_channel(void *wcnss, const char *name, qcom_smd_cb_t cb)
+{
+   WARN_ON(1);
+   return ERR_PTR(-ENXIO);
+}
+
+#endif
+
 #endif
-- 
2.5.0



[PATCH v4 3/4] wcn36xx: Implement firmware assisted scan

2016-09-06 Thread Bjorn Andersson
Using the software based channel scan mechanism from mac80211 keeps us
offline for 10-15 second, we should instead issue a start_scan/end_scan
on each channel reducing this time.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v3:
- None
Changes since v2:
- Match prototype change of ieee80211_scan_completed()

 drivers/net/wireless/ath/wcn36xx/main.c| 64 +-
 drivers/net/wireless/ath/wcn36xx/smd.c |  8 ++--
 drivers/net/wireless/ath/wcn36xx/smd.h |  4 +-
 drivers/net/wireless/ath/wcn36xx/txrx.c| 19 ++---
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  9 +
 5 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 3c2522b07c90..96a9584edcbb 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -568,23 +568,59 @@ out:
return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
 {
-   struct wcn36xx *wcn = hw->priv;
+   struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+   struct cfg80211_scan_request *req = wcn->scan_req;
+   u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+   struct cfg80211_scan_info scan_info = {};
+   int i;
+
+   wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", 
req->n_channels);
+
+   for (i = 0; i < req->n_channels; i++)
+   channels[i] = req->channels[i]->hw_value;
+
+   wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
 
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
-   wcn36xx_smd_start_scan(wcn);
+   for (i = 0; i < req->n_channels; i++) {
+   wcn->scan_freq = req->channels[i]->center_freq;
+   wcn->scan_band = req->channels[i]->band;
+
+   wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+   msleep(30);
+   wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+   wcn->scan_freq = 0;
+   }
+   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+   scan_info.aborted = false;
+   ieee80211_scan_completed(wcn->hw, _info);
+
+   mutex_lock(>scan_lock);
+   wcn->scan_req = NULL;
+   mutex_unlock(>scan_lock);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif,
+  struct ieee80211_scan_request *hw_req)
 {
struct wcn36xx *wcn = hw->priv;
 
-   wcn36xx_smd_end_scan(wcn);
-   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+   mutex_lock(>scan_lock);
+   if (wcn->scan_req) {
+   mutex_unlock(>scan_lock);
+   return -EBUSY;
+   }
+   wcn->scan_req = _req->req;
+   mutex_unlock(>scan_lock);
+
+   schedule_work(>scan_work);
+
+   return 0;
 }
 
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@@ -997,8 +1033,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.configure_filter   = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
-   .sw_scan_start  = wcn36xx_sw_scan_start,
-   .sw_scan_complete   = wcn36xx_sw_scan_complete,
+   .hw_scan= wcn36xx_hw_scan,
.bss_info_changed   = wcn36xx_bss_info_changed,
.set_rts_threshold  = wcn36xx_set_rts_threshold,
.sta_add= wcn36xx_sta_add,
@@ -1023,6 +1058,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
+   ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
 
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -1032,6 +1068,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz;
wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz;
 
+   wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
+   wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
+
wcn->hw->wiphy->cipher_suites = cipher_suites;
wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
@@ -1152,6 +1191,9 @@ static int wcn36xx_probe(struct platform_devic

Re: [PATCH v3 1/2] wcn36xx: Transition driver to SMD client

2016-09-02 Thread Bjorn Andersson
On Fri 02 Sep 09:24 PDT 2016, Kalle Valo wrote:

> Bjorn Andersson <bjorn.anders...@linaro.org> writes:
> 
> > The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
> > channel, as such it should be a SMD client. This patch makes this
> > transition, now that we have the necessary frameworks available.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> 
> [...]
> 
> > --- a/drivers/net/wireless/ath/wcn36xx/Kconfig
> > +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
> > @@ -1,6 +1,6 @@
> >  config WCN36XX
> > tristate "Qualcomm Atheros WCN3660/3680 support"
> > -   depends on MAC80211 && HAS_DMA
> > +   depends on MAC80211 && HAS_DMA && QCOM_SMD
> 
> While I had this patch on my pending branch I noticed that I can't
> compile wcn36xx on x86 anymore. This is actually quite inconvenient, for
> example then it's easy to miss mac80211 API changes etc. Is there any
> way we could continue build testing wcn36xx on x86 (or all) platforms?
> 

Sorry about that, we should at least be able to COMPILE_TEST it in
non-qcom builds. Thanks for letting me know.

And the driver should also depend on QCOM_WCNSS_CTRL, in the normal
case.

I'll respin this, unless you prefer an incremental patch for those
changes(?)

> Also what about older platforms? Earlier I used wcn36xx on my Nexus 4
> with help of backports project. I can't do that anymore, right?
> 

This has been tested on 8064, 8974 and 8916. So your Nexus 4 is covered.

Unfortunately I don't have a Nexus 4, but we currently have Nexus 7
(the 8064 version), Xperia Z, Xperia Z1 and DB410c using this chip and
all four has been tested with this code.

I've staged the PIL/remoteproc (firmware "loader") driver for v4.9, so
with this patch the only thing missing to fill in the dts files is one
clock from the RPM.


JFYI, There seems to be some race in the removal path, which I will look
into. But I would prefer if we could merge this to make the driver
usable, and more accessible to work on.

Regards,
Bjorn


[PATCH v3 2/2] wcn36xx: Implement firmware assisted scan

2016-09-01 Thread Bjorn Andersson
Using the software based channel scan mechanism from mac80211 keeps us
offline for 10-15 second, we should instead issue a start_scan/end_scan
on each channel reducing this time.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v2:
- None

 drivers/net/wireless/ath/wcn36xx/main.c| 64 +-
 drivers/net/wireless/ath/wcn36xx/smd.c |  8 ++--
 drivers/net/wireless/ath/wcn36xx/smd.h |  4 +-
 drivers/net/wireless/ath/wcn36xx/txrx.c| 19 ++---
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  9 +
 5 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 3c2522b07c90..96a9584edcbb 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -568,23 +568,59 @@ out:
return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
 {
-   struct wcn36xx *wcn = hw->priv;
+   struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+   struct cfg80211_scan_request *req = wcn->scan_req;
+   u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+   struct cfg80211_scan_info scan_info = {};
+   int i;
+
+   wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", 
req->n_channels);
+
+   for (i = 0; i < req->n_channels; i++)
+   channels[i] = req->channels[i]->hw_value;
+
+   wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
 
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
-   wcn36xx_smd_start_scan(wcn);
+   for (i = 0; i < req->n_channels; i++) {
+   wcn->scan_freq = req->channels[i]->center_freq;
+   wcn->scan_band = req->channels[i]->band;
+
+   wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+   msleep(30);
+   wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+   wcn->scan_freq = 0;
+   }
+   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+   scan_info.aborted = false;
+   ieee80211_scan_completed(wcn->hw, _info);
+
+   mutex_lock(>scan_lock);
+   wcn->scan_req = NULL;
+   mutex_unlock(>scan_lock);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif,
+  struct ieee80211_scan_request *hw_req)
 {
struct wcn36xx *wcn = hw->priv;
 
-   wcn36xx_smd_end_scan(wcn);
-   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+   mutex_lock(>scan_lock);
+   if (wcn->scan_req) {
+   mutex_unlock(>scan_lock);
+   return -EBUSY;
+   }
+   wcn->scan_req = _req->req;
+   mutex_unlock(>scan_lock);
+
+   schedule_work(>scan_work);
+
+   return 0;
 }
 
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@@ -997,8 +1033,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.configure_filter   = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
-   .sw_scan_start  = wcn36xx_sw_scan_start,
-   .sw_scan_complete   = wcn36xx_sw_scan_complete,
+   .hw_scan= wcn36xx_hw_scan,
.bss_info_changed   = wcn36xx_bss_info_changed,
.set_rts_threshold  = wcn36xx_set_rts_threshold,
.sta_add= wcn36xx_sta_add,
@@ -1023,6 +1058,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
+   ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
 
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -1032,6 +1068,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz;
wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz;
 
+   wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
+   wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
+
wcn->hw->wiphy->cipher_suites = cipher_suites;
wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
@@ -1152,6 +1191,9 @@ static int wcn36xx_probe(struct platform_device *pdev)
wcn->hw = hw;
wcn->dev = &

[PATCH v3 1/2] wcn36xx: Transition driver to SMD client

2016-09-01 Thread Bjorn Andersson
The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
channel, as such it should be a SMD client. This patch makes this
transition, now that we have the necessary frameworks available.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v2:
- Correct the call to the new ieee80211_scan_completed()

 drivers/net/wireless/ath/wcn36xx/Kconfig   |  2 +-
 drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
 drivers/net/wireless/ath/wcn36xx/main.c| 79 --
 drivers/net/wireless/ath/wcn36xx/smd.c | 29 +--
 drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
 6 files changed, 86 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig 
b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..394fe5b77c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,6 @@
 config WCN36XX
tristate "Qualcomm Atheros WCN3660/3680 support"
-   depends on MAC80211 && HAS_DMA
+   depends on MAC80211 && HAS_DMA && QCOM_SMD
---help---
  This module adds support for wireless adapters based on
  Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 231fd022f0f5..87dfdaf9044c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -23,6 +23,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
goto out_err;
 
/* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
-   ret = wcn->ctrl_ops->smsm_change_state(
-   WCN36XX_SMSM_WLAN_TX_ENABLE,
-   WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE |
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   if (ret)
+   goto out_err;
 
return 0;
 
@@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
 * notify chip about new frame through SMSM bus.
 */
if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
-   wcn->ctrl_ops->smsm_change_state(
- 0,
- WCN36XX_SMSM_WLAN_TX_ENABLE);
+   qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+   WCN36XX_SMSM_WLAN_TX_ENABLE,
+   WCN36XX_SMSM_WLAN_TX_ENABLE);
} else {
/* indicate End Of Packet and generate interrupt on descriptor
 * done.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index e1d59da2ad20..3c2522b07c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -21,6 +21,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
int ret;
 
/* Set TX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlantx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
if (!res) {
wcn36xx_err("failed to get tx_irq\n");
return -ENOENT;
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct 
wcn36xx *wcn,
wcn->tx_irq = res->start;
 
/* Set RX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlanrx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
if (!res) {
wcn36xx_err("failed to get rx_irq\n");
return -ENOENT;
}
wcn->rx_irq = res->start;
 
+   /* Acquire SMSM tx enable handle */
+   wcn->tx_enable_state = qcom_smem_state_get(>dev,
+   "tx-enable", >tx_enable_state_bit);
+   if (IS_ERR(wcn->tx_enable_state)) {
+   wcn36xx_err("failed to get tx-enable state\n");
+   return PTR_ERR(wcn->tx_enable_state);
+   }
+
+   /* Acquire SMSM tx rings empty handle */
+   wcn->tx_rings_empty

[PATCH v2 1/2] wcn36xx: Transition driver to SMD client

2016-08-12 Thread Bjorn Andersson
The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
channel, as such it should be a SMD client. This patch makes this
transition, now that we have the necessary frameworks available.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Resending this as the dependencies and the devicetree binding was merged in
v4.8

 drivers/net/wireless/ath/wcn36xx/Kconfig   |  2 +-
 drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
 drivers/net/wireless/ath/wcn36xx/main.c| 79 --
 drivers/net/wireless/ath/wcn36xx/smd.c | 29 +--
 drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
 6 files changed, 86 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig 
b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..394fe5b77c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,6 @@
 config WCN36XX
tristate "Qualcomm Atheros WCN3660/3680 support"
-   depends on MAC80211 && HAS_DMA
+   depends on MAC80211 && HAS_DMA && QCOM_SMD
---help---
  This module adds support for wireless adapters based on
  Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 231fd022f0f5..87dfdaf9044c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -23,6 +23,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
goto out_err;
 
/* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
-   ret = wcn->ctrl_ops->smsm_change_state(
-   WCN36XX_SMSM_WLAN_TX_ENABLE,
-   WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE |
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   if (ret)
+   goto out_err;
 
return 0;
 
@@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
 * notify chip about new frame through SMSM bus.
 */
if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
-   wcn->ctrl_ops->smsm_change_state(
- 0,
- WCN36XX_SMSM_WLAN_TX_ENABLE);
+   qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+   WCN36XX_SMSM_WLAN_TX_ENABLE,
+   WCN36XX_SMSM_WLAN_TX_ENABLE);
} else {
/* indicate End Of Packet and generate interrupt on descriptor
 * done.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index e1d59da2ad20..3c2522b07c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -21,6 +21,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
int ret;
 
/* Set TX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlantx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
if (!res) {
wcn36xx_err("failed to get tx_irq\n");
return -ENOENT;
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct 
wcn36xx *wcn,
wcn->tx_irq = res->start;
 
/* Set RX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlanrx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
if (!res) {
wcn36xx_err("failed to get rx_irq\n");
return -ENOENT;
}
wcn->rx_irq = res->start;
 
+   /* Acquire SMSM tx enable handle */
+   wcn->tx_enable_state = qcom_smem_state_get(>dev,
+   "tx-enable", >tx_enable_state_bit);
+   if (IS_ERR(wcn->tx_enable_state)) {
+   wcn36xx_err("failed to get tx-enable state\n");
+   return PTR_ERR(wcn->tx_enable_state);
+   }
+
+   /* Acquire SMSM tx rings empty handle */
+   wcn->tx_rings_empty

[PATCH v2 2/2] wcn36xx: Implement firmware assisted scan

2016-08-12 Thread Bjorn Andersson
Using the software based channel scan mechanism from mac80211 keeps us
offline for 10-15 second, we should instead issue a start_scan/end_scan
on each channel reducing this time.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

It's been a while since I posted this as an RFC, I have not received any
comments on the code but we've been running it in the Linaro kernel with good
results and possitive user feedback for quite some time.

So I'm hoping we can merge it, as it solves the #1 complaint we had with users;
where NetworkManager (or something similar) would stall and time out their
connections by scanning for networks every now and then.

 drivers/net/wireless/ath/wcn36xx/main.c| 62 --
 drivers/net/wireless/ath/wcn36xx/smd.c |  8 ++--
 drivers/net/wireless/ath/wcn36xx/smd.h |  4 +-
 drivers/net/wireless/ath/wcn36xx/txrx.c| 19 ++---
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  9 +
 5 files changed, 79 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 3c2522b07c90..23650b24c5bf 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -568,23 +568,57 @@ out:
return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
 {
-   struct wcn36xx *wcn = hw->priv;
+   struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+   struct cfg80211_scan_request *req = wcn->scan_req;
+   u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+   int i;
+
+   wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", 
req->n_channels);
+
+   for (i = 0; i < req->n_channels; i++)
+   channels[i] = req->channels[i]->hw_value;
+
+   wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
 
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
-   wcn36xx_smd_start_scan(wcn);
+   for (i = 0; i < req->n_channels; i++) {
+   wcn->scan_freq = req->channels[i]->center_freq;
+   wcn->scan_band = req->channels[i]->band;
+
+   wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+   msleep(30);
+   wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+   wcn->scan_freq = 0;
+   }
+   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+   ieee80211_scan_completed(wcn->hw, false);
+
+   mutex_lock(>scan_lock);
+   wcn->scan_req = NULL;
+   mutex_unlock(>scan_lock);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif,
+  struct ieee80211_scan_request *hw_req)
 {
struct wcn36xx *wcn = hw->priv;
 
-   wcn36xx_smd_end_scan(wcn);
-   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+   mutex_lock(>scan_lock);
+   if (wcn->scan_req) {
+   mutex_unlock(>scan_lock);
+   return -EBUSY;
+   }
+   wcn->scan_req = _req->req;
+   mutex_unlock(>scan_lock);
+
+   schedule_work(>scan_work);
+
+   return 0;
 }
 
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@@ -997,8 +1031,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.configure_filter   = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
-   .sw_scan_start  = wcn36xx_sw_scan_start,
-   .sw_scan_complete   = wcn36xx_sw_scan_complete,
+   .hw_scan= wcn36xx_hw_scan,
.bss_info_changed   = wcn36xx_bss_info_changed,
.set_rts_threshold  = wcn36xx_set_rts_threshold,
.sta_add= wcn36xx_sta_add,
@@ -1023,6 +1056,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
+   ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
 
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -1032,6 +1066,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = _band_2ghz;
wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = _band_5ghz;
 
+   wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
+   wcn->hw->wiphy->max_scan_ie_len =

Re: [RFC v0 7/8] Input: ims-pcu: use firmware_stat instead of completion

2016-08-03 Thread Bjorn Andersson
On Wed 03 Aug 08:55 PDT 2016, Luis R. Rodriguez wrote:

> On Wed, Aug 03, 2016 at 08:57:09AM +0200, Daniel Wagner wrote:
> > On 08/02/2016 09:41 AM, Luis R. Rodriguez wrote:
[..]
> > Not sure if I get you here correctly. Is the 'system configurable
> > deterministic file' is a knob which controlled by user space? Or it
> > this something you define at compile time?
> 
> I meant at compile time on the kernel. So CONFIG_READ_READY_SENTINEL
> or something like this, and it be a string, which if set then when
> the kernel read APIs are used, then a new API could be introduced
> that would *only* enable reading through once that sentinel has
> been detected by the kernel to allowed through reads. Doing this
> per mount / target filesystem is rather cumbersome given possible
> overlaps in mounts and also pivot_root() being possible, so instead
> targeting simply the fs/exec.c enum kernel_read_file_id would seem
> more efficient and clean but we would need a decided upon set of
> paths per enum kernel_read_file_id as base (or just one path per
> enum kernel_read_file_id). For number of paths I mean the number
> of target directories to look for the sentinel per enum kernel_read_file_id,
> so for instance for READING_FIRMWARE perhaps just deciding on /lib/firmware/
> would suffice, but if this supported multiple paths another option may be
> for the sentinel to also be looked for in /lib/firmware/updates/,
> /lib/firmware/" UTS_RELEASE -- etc. It would *stop* after finding one
> sentinel on any of these paths.
> 
> If a system has has CONFIG_READ_READY_SENTINEL it would mean an agreed upon
> system configuration has been decided so that at any point in time reads
> against READING_FIRMWARE using a new kernel_read_file_from_path_sentinel()
> (or something like it) would only allow the read to go through once
> the sentinel has been found for READING_FIRMWARE on the agreed upon
> paths.
> 
> The benefit of the sentintel approach is it avoids complexities with
> pivot_root(), and makes the deterministic aspect of the target left
> only to a system-configuration enabled target path / file.
> 

This sounds reasonable, it could be configured to wait for a certain
static file or userspace could generate this file once it reaches some
checkpoint.


Just to provide some additional input to "will rootfs mounted be enough
of a sentinel".

In an Android device you have a initramfs that will read an fstab file
and mount /system that holds most firmware, for some platforms
additional firmware will come from a third partition (in the Qualcomm
case mounted in /persist by the same mechanism).

With the sentinel approach one could configure the system either point
it at a file in the last file system to be mounted or have init generate
a file once its done with this; or in the generic configuration just
wait for /lib/firmware to show up.

I like this approach.

> This is just an idea. I'd like some FS folks to review.
> 

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC v0 7/8] Input: ims-pcu: use firmware_stat instead of completion

2016-08-03 Thread Bjorn Andersson
On Tue 02 Aug 00:41 PDT 2016, Luis R. Rodriguez wrote:

> On Tue, Aug 02, 2016 at 08:53:55AM +0200, Daniel Wagner wrote:
> > On 08/02/2016 08:34 AM, Luis R. Rodriguez wrote:
> > >On Tue, Aug 02, 2016 at 07:49:19AM +0200, Daniel Wagner wrote:
> > >>>The sysdata API's main goal rather is to provide a flexible API first,
> > >>>compartamentalizing the usermode helper was secondary. But now it seems
> > >>>I may just also add devm support too to help simplify code further.
> > >>
> > >>I missed the point that you plan to add usermode helper support to
> > >>the sysdata API.
> > >
> > >I had no such plans, when I have asked folks so far about "hey are you
> > >really in need for it, OK what for? " and "what extended uses do you
> > >envision?" so I far I have not gotten any replies at all. So -- instead
> > >sysdata currently ignores it.
> > 
> > So you argue for the remoteproc use case with 100+ MB firmware that
> > if there is a way to load after pivot_root() (or other additional
> > firmware partition shows up) then there is no need at all for
> > usermode helper?
> 
> No, I'm saying I'd like to hear valid uses cases for the usermode helper and 
> so
> far I have only found using coccinelle grammar 2 explicit users, that's it. My
> patch series (not yet merge) then annotates these as valid as I've verified
> through their documentation they have some quirky requirement.
> 

I think we're on the same page, but just to make sure; I do not want the
usermode helper, I only want a way to wait for the firmware files to
become available.

> Other than these two drivers I'd like hear to valid requirements for it.
> 
> The existential issue is a real issue but it does not look impossible to
> resolve. It may be a solution to bloat up the kernel with 100+ MB size just to
> stuff built-in firmware to avoid this issue, but it does not mean a solution
> is not possible.
> 
> Remind me -- why can remoteproc not stuff the firmware in initramfs ?
> 

RAM usage:
Storing the files in initramfs would consume 100MB RAM, we would then
allocate 100MB RAM for buffers during firmware loading and then we have
the reserved 100MB for the peripherals. The buffers could be easily be
removed with a mechanism for providing a buffer to the load operation,
but we would still double the RAM consumption.

Boot time:
Enlarging the kernel by 100MB will give noticeable addition to boot
times.

Development issues:
I have numerous concerns related to this, e.g. not being able to side
load the firmware files without rebuilding the initramfs. But most of
these are not technical issues, but rather a matter of convenience.

One large issue would be how to figure out how large to make the boot
partition in your Android phone, to cope with potential future growth in
firmware size - which has already proven to be a mess.

Legal matters:
Some of these firmware files are not redistributable, making it
impossible for end users to rebuild their kernel without loosing
functionality. There are even cases where these files are not allowed to
share partition with GPL binaries.


Most of these are just a major inconveniences to the developer but some
are show stoppers; especially the legal matters. So if we wave this off
as something people can live without then every downstream will sit on
their own solution to reimplement it.

> Anyway, here's a simple suggestion: fs/exec.c gets a sentinel file monitor
> support per enum kernel_read_file_id. For instance we'd have one for
> READING_FIRMWARE, one for READING_KEXEC_IMAGE, perhaps READING_POLICY, and 
> this
> would in turn be used as the system configurable deterministic file for
> which to wait for to be present before enabling each enum kernel_read_file_id
> type read.
> 
> Thoughts ?

That does sound like a good generic solution for our problem and for the
other types of files as well. Do you have any ideas (patches?) on how
each sentinel would be triggered?

The only concern I can think of right now is that the
firmware_class.path might point to a separate partition; but based on
how the signaling of the sentinels are implemented this might not be an
issue.

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC v0 7/8] Input: ims-pcu: use firmware_stat instead of completion

2016-08-01 Thread Bjorn Andersson
On Sat 30 Jul 09:58 PDT 2016, Luis R. Rodriguez wrote:

> On Sat, Jul 30, 2016 at 02:42:41PM +0200, Arend van Spriel wrote:
> > + Luis (again) ;-)
> > 
> > On 29-07-16 08:13, Daniel Wagner wrote:
> > > On 07/28/2016 09:01 PM, Bjorn Andersson wrote:
> > >> On Thu 28 Jul 11:33 PDT 2016, Dmitry Torokhov wrote:
> > >>
> > >>> On Thu, Jul 28, 2016 at 09:55:11AM +0200, Daniel Wagner wrote:
> > >>>> From: Daniel Wagner <daniel.wag...@bmw-carit.de>
> > >>>>
> > >> [..]
> > >>>
> > >>> Do not quite like it... I'd rather asynchronous request give out a
> > >>> firmware status pointer that could be used later on.
> > 
> > Excellent. Why not get rid of the callback function as well and have
> > fw_loading_wait() return result (0 = firmware available, < 0 = fail).
> > Just to confirm, you are proposing a new API function next to
> > request_firmware_nowait(), right?
> 
> If proposing new firmware_class patches please bounce / Cc me, I've
> recently asked for me to be added to MAINTAINERS so I get these
> e-mails as I'm working on a new flexible API which would allow us
> to extend the firmware API without having to care about the old
> stupid usermode helper at all.
> 

In the remoteproc world there are several systems where we see 100+MB of
firmware being loaded. It's unfeasible to have these files in an
initramfs, so we need a way to indicate to the kernel that the
second/primary (or a dedicated firmware partition) is mounted.

We're currently loading these files with request_firmware_nowait(), so
either one can either use kernel modules or the user-helper fallback to
delay the loading until the files are available. (I don't like to
enforce the usage of kernel modules)

I'm open to alternative ways of having firmware loading wait on
secondary filesystems to be mounted, but have not yet tried to tackle
this problem. I do believe something that waits and retries the firmware
load as additional file systems gets mounted would be prettier than
forcing user space to tell us it's time to move on.



Due to the size of these firmware files we release the firmware as soon
as we have copied the content into the appropriate memory segments, so
we're not utilizing the caching mechanisms of the current fw loader.

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC v0 7/8] Input: ims-pcu: use firmware_stat instead of completion

2016-07-28 Thread Bjorn Andersson
On Thu 28 Jul 11:33 PDT 2016, Dmitry Torokhov wrote:

> On Thu, Jul 28, 2016 at 09:55:11AM +0200, Daniel Wagner wrote:
> > From: Daniel Wagner 
> > 
[..]
> 
> Do not quite like it... I'd rather asynchronous request give out a
> firmware status pointer that could be used later on.
> 
>   pcu->fw_st = request_firmware_async(IMS_PCU_FIRMWARE_NAME,
>   pcu,
>   ims_pcu_process_async_firmware);
>   if (IS_ERR(pcu->fw_st))
>   return PTR_ERR(pcu->fw_st);
> 
>   
> 
>   fw_loading_wait(pcu->fw_st);
> 

In the remoteproc case (patch 6) this would clean up the code, rather
than replacing the completion API 1 to 1. I like it!

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] wcn36xx: Silence error about unsupported smd event 188

2016-07-07 Thread Bjorn Andersson
Sometimes the firmware sends a HAL_DEL_BA_IND, the prima driver silently
ignore this message so let's do the same to silence the error message.

Cc: Nicolas Dechesne <nicolas.deche...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index e8b630c4f11e..3d56a3f236f9 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2226,6 +2226,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, 
void *buf, size_t len)
 
case WCN36XX_HAL_COEX_IND:
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
+   case WCN36XX_HAL_DEL_BA_IND:
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
@@ -2273,6 +2274,7 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
 
switch (msg_header->msg_type) {
case WCN36XX_HAL_COEX_IND:
+   case WCN36XX_HAL_DEL_BA_IND:
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
break;
case WCN36XX_HAL_OTA_TX_COMPL_IND:
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] wcn36xx: Implement print_reg indication

2016-06-30 Thread Bjorn Andersson
Some firmware versions sends a "print register indication", handle this
by printing out the content.

Cc: Nicolas Dechesne <n...@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/hal.h | 16 
 drivers/net/wireless/ath/wcn36xx/smd.c | 30 ++
 2 files changed, 46 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index 4f87ef1e1eb8..b765c647319d 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -350,6 +350,8 @@ enum wcn36xx_hal_host_msg_type {
 
WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
 
+   WCN36XX_HAL_PRINT_REG_INFO_IND = 259,
+
WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE
 };
 
@@ -4703,4 +4705,18 @@ struct stats_class_b_ind {
u32 rx_time_total;
 };
 
+/* WCN36XX_HAL_PRINT_REG_INFO_IND */
+struct wcn36xx_hal_print_reg_info_ind {
+   struct wcn36xx_hal_msg_header header;
+
+   u32 count;
+   u32 scenario;
+   u32 reason;
+
+   struct {
+   u32 addr;
+   u32 value;
+   } regs[];
+} __packed;
+
 #endif /* _HAL_H_ */
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 87a62eb6228c..28d6ca0ca819 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2109,6 +2109,30 @@ static int wcn36xx_smd_delete_sta_context_ind(struct 
wcn36xx *wcn,
return -ENOENT;
 }
 
+static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
+ void *buf,
+ size_t len)
+{
+   struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
+   int i;
+
+   if (len < sizeof(*rsp)) {
+   wcn36xx_warn("Corrupted print reg info indication\n");
+   return -EIO;
+   }
+
+   wcn36xx_dbg(WCN36XX_DBG_HAL,
+   "reginfo indication, scenario: 0x%x reason: 0x%x\n",
+   rsp->scenario, rsp->reason);
+
+   for (i = 0; i < rsp->count; i++) {
+   wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
+   rsp->regs[i].addr, rsp->regs[i].value);
+   }
+
+   return 0;
+}
+
 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
 {
struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
@@ -2238,6 +2262,7 @@ int wcn36xx_smd_rsp_process(struct qcom_smd_channel 
*channel,
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
+   case WCN36XX_HAL_PRINT_REG_INFO_IND:
msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
if (!msg_ind) {
/*
@@ -2300,6 +2325,11 @@ static void wcn36xx_ind_smd_work(struct work_struct 
*work)
   hal_ind_msg->msg,
   hal_ind_msg->msg_len);
break;
+   case WCN36XX_HAL_PRINT_REG_INFO_IND:
+   wcn36xx_smd_print_reg_info_ind(wcn,
+  hal_ind_msg->msg,
+  hal_ind_msg->msg_len);
+   break;
default:
wcn36xx_err("SMD_EVENT (%d) not supported\n",
  msg_header->msg_type);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/6] wcn36xx: Fold indication payload into message header

2016-06-20 Thread Bjorn Andersson
From: Bjorn Andersson <bjorn.anders...@sonymobile.com>

Merge the two allocation instead of separately allocating room for the
indication payload.

Signed-off-by: Bjorn Andersson <bjorn.anders...@sonymobile.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 15 ++-
 drivers/net/wireless/ath/wcn36xx/smd.h |  2 +-
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index e8b630c4f11e..1a9580d72077 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2229,14 +2229,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, 
void *buf, size_t len)
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
-   msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-   if (!msg_ind)
-   goto nomem;
-   msg_ind->msg_len = len;
-   msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
-   if (!msg_ind->msg) {
-   kfree(msg_ind);
-nomem:
+   msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_KERNEL);
+   if (!msg_ind) {
/*
 * FIXME: Do something smarter then just
 * printing an error.
@@ -2245,6 +2239,10 @@ nomem:
msg_header->msg_type);
break;
}
+
+   msg_ind->msg_len = len;
+   memcpy(msg_ind->msg, buf, len);
+
mutex_lock(>hal_ind_mutex);
list_add_tail(_ind->list, >hal_ind_queue);
queue_work(wcn->hal_ind_wq, >hal_ind_work);
@@ -2295,7 +2293,6 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
  msg_header->msg_type);
}
list_del(wcn->hal_ind_queue.next);
-   kfree(hal_ind_msg->msg);
kfree(hal_ind_msg);
mutex_unlock(>hal_ind_mutex);
 }
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h 
b/drivers/net/wireless/ath/wcn36xx/smd.h
index d93e3fd73831..c4375ce1019a 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -46,8 +46,8 @@ struct wcn36xx_fw_msg_status_rsp {
 
 struct wcn36xx_hal_ind_msg {
struct list_head list;
-   u8 *msg;
size_t msg_len;
+   u8 msg[];
 };
 
 struct wcn36xx;
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/6] wcn36xx: Transition driver to SMD client

2016-06-20 Thread Bjorn Andersson
The wcn36xx wifi driver follows the life cycle of the WLAN_CTRL SMD
channel, as such it should be a SMD client. This patch makes this
transition, now that we have the necessary frameworks available.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

This patch depends on the devicetree binding approved by Rob Herring [1] and
the addition of support in the wcnss_ctrl driver for probing sub-drivers in a
timely manner [2] - i.e. when the WCNSS core OS signals that it's booted.

These are both scheduled to be merged in v4.8

[1] https://patchwork.kernel.org/patch/9159621/
[2] 
https://git.kernel.org/cgit/linux/kernel/git/agross/linux.git/log/?h=for-next

 drivers/net/wireless/ath/wcn36xx/Kconfig   |  2 +-
 drivers/net/wireless/ath/wcn36xx/dxe.c | 16 +++---
 drivers/net/wireless/ath/wcn36xx/main.c| 79 --
 drivers/net/wireless/ath/wcn36xx/smd.c | 29 +--
 drivers/net/wireless/ath/wcn36xx/smd.h |  5 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 21 +++-
 6 files changed, 86 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig 
b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..394fe5b77c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,6 @@
 config WCN36XX
tristate "Qualcomm Atheros WCN3660/3680 support"
-   depends on MAC80211 && HAS_DMA
+   depends on MAC80211 && HAS_DMA && QCOM_SMD
---help---
  This module adds support for wireless adapters based on
  Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 231fd022f0f5..87dfdaf9044c 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -23,6 +23,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
goto out_err;
 
/* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
-   ret = wcn->ctrl_ops->smsm_change_state(
-   WCN36XX_SMSM_WLAN_TX_ENABLE,
-   WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   ret = qcom_smem_state_update_bits(wcn->tx_enable_state,
+ WCN36XX_SMSM_WLAN_TX_ENABLE |
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY,
+ WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
+   if (ret)
+   goto out_err;
 
return 0;
 
@@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
 * notify chip about new frame through SMSM bus.
 */
if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
-   wcn->ctrl_ops->smsm_change_state(
- 0,
- WCN36XX_SMSM_WLAN_TX_ENABLE);
+   qcom_smem_state_update_bits(wcn->tx_rings_empty_state,
+   WCN36XX_SMSM_WLAN_TX_ENABLE,
+   WCN36XX_SMSM_WLAN_TX_ENABLE);
} else {
/* indicate End Of Packet and generate interrupt on descriptor
 * done.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index e1d59da2ad20..3c2522b07c90 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -21,6 +21,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -1058,8 +1062,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
int ret;
 
/* Set TX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlantx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
if (!res) {
wcn36xx_err("failed to get tx_irq\n");
return -ENOENT;
@@ -1067,14 +1070,29 @@ static int wcn36xx_platform_get_resources(struct 
wcn36xx *wcn,
wcn->tx_irq = res->start;
 
/* Set RX IRQ */
-   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-  "wcnss_wlanrx_irq");
+   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
if (!res) {
wcn36xx_err("failed to get rx_irq\n");
return -ENOENT;
}
wcn->rx_irq = res->start;
 
+   /* Acquire SMSM tx enable handle */
+   wcn->tx_enable_state = qcom_smem_state_get(>dev,
+  

[PATCH 4/6] wcn36xx: Correct DXE chip version differentiation

2016-06-20 Thread Bjorn Andersson
The CCU block in WCNSS is configured for appropriate routing of
interrupts from the DXE to the application cpu, this is not dependant on
the iris version (wcn3660 vs wcn3680), but rather if the SoC has a riva
or pronto built in.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/dxe.c | 11 ++-
 drivers/net/wireless/ath/wcn36xx/dxe.h |  5 ++---
 drivers/net/wireless/ath/wcn36xx/main.c| 16 ++--
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  5 +
 4 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index a8ff45400982..231fd022f0f5 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -702,12 +702,13 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
reg_data = WCN36XX_DXE_REG_RESET;
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
 
-   /* Setting interrupt path */
-   reg_data = WCN36XX_DXE_CCU_INT;
-   if (wcn->chip_version == WCN36XX_CHIP_3680)
-   wcn36xx_ccu_write_register(wcn, WCN36XX_DXE_REG_CCU_INT_3680, 
reg_data);
+   /* Select channels for rx avail and xfer done interrupts... */
+   reg_data = (WCN36XX_DXE_INT_CH3_MASK | WCN36XX_DXE_INT_CH1_MASK) << 16 |
+   WCN36XX_DXE_INT_CH0_MASK | WCN36XX_DXE_INT_CH4_MASK;
+   if (wcn->is_pronto)
+   wcn36xx_ccu_write_register(wcn, 
WCN36XX_CCU_DXE_INT_SELECT_PRONTO, reg_data);
else
-   wcn36xx_ccu_write_register(wcn, WCN36XX_DXE_REG_CCU_INT_3660, 
reg_data);
+   wcn36xx_ccu_write_register(wcn, 
WCN36XX_CCU_DXE_INT_SELECT_RIVA, reg_data);
 
/***/
/* Init descriptors for TX LOW channel */
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h 
b/drivers/net/wireless/ath/wcn36xx/dxe.h
index 012b59f4f91b..c012e807753b 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -30,9 +30,8 @@ H2H_TEST_RX_TX = DMA2
 /* DXE registers */
 #define WCN36XX_DXE_MEM_REG0
 
-#define WCN36XX_DXE_CCU_INT0xA0011
-#define WCN36XX_DXE_REG_CCU_INT_3660   0x310
-#define WCN36XX_DXE_REG_CCU_INT_3680   0x10dc
+#define WCN36XX_CCU_DXE_INT_SELECT_RIVA0x310
+#define WCN36XX_CCU_DXE_INT_SELECT_PRONTO  0x10dc
 
 /* TODO This must calculated properly but not hardcoded */
 #define WCN36XX_DXE_CTRL_TX_L  0x328a44
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 8146eeba4458..e1d59da2ad20 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -261,17 +261,6 @@ static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
}
 }
 
-static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
-{
-   if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
-   wcn36xx_info("Chip is 3680\n");
-   wcn->chip_version = WCN36XX_CHIP_3680;
-   } else {
-   wcn36xx_info("Chip is 3660\n");
-   wcn->chip_version = WCN36XX_CHIP_3660;
-   }
-}
-
 static int wcn36xx_start(struct ieee80211_hw *hw)
 {
struct wcn36xx *wcn = hw->priv;
@@ -326,9 +315,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
wcn36xx_feat_caps_info(wcn);
}
 
-   wcn36xx_detect_chip_version(wcn);
-   wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
-
/* DMA channel initialization */
ret = wcn36xx_dxe_init(wcn);
if (ret) {
@@ -1095,6 +1081,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx 
*wcn,
return -EINVAL;
}
 
+   wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
+
/* Map the CCU memory */
index = of_property_match_string(mmio_node, "reg-names", "ccu");
wcn->ccu_base = of_iomap(mmio_node, index);
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 845f2446a1b5..22242d18e1fe 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -193,7 +193,7 @@ struct wcn36xx {
u8  fw_minor;
u8  fw_major;
u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
-   u32 chip_version;
+   boolis_pronto;
 
/* extra byte for the NULL termination */
u8  crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
@@ -242,9 +242,6 @@ struct wcn36xx {
 
 };
 
-#define WCN36XX_CHIP_3660  0
-#define WCN36XX_CHIP_3680  1
-
 static inline bool wcn36x

[PATCH 3/6] wcn36xx: Split mmio space into explicit regions

2016-06-20 Thread Bjorn Andersson
Split the wcnss mmio space into explicit regions for ccu and dxe and
acquire these from the node referenced by the qcom,mmio phandle.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/dxe.c | 26 ---
 drivers/net/wireless/ath/wcn36xx/dxe.h |  6 ++--
 drivers/net/wireless/ath/wcn36xx/main.c| 51 +++---
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  3 +-
 4 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c 
b/drivers/net/wireless/ath/wcn36xx/dxe.c
index 8643801f31b6..a8ff45400982 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -35,26 +35,27 @@ void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool 
is_low)
return ch->head_blk_ctl->bd_cpu_addr;
 }
 
+static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data)
+{
+   wcn36xx_dbg(WCN36XX_DBG_DXE,
+   "wcn36xx_ccu_write_register: addr=%x, data=%x\n",
+   addr, data);
+
+   writel(data, wcn->ccu_base + addr);
+}
+
 static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
 {
wcn36xx_dbg(WCN36XX_DBG_DXE,
"wcn36xx_dxe_write_register: addr=%x, data=%x\n",
addr, data);
 
-   writel(data, wcn->mmio + addr);
+   writel(data, wcn->dxe_base + addr);
 }
 
-#define wcn36xx_dxe_write_register_x(wcn, reg, reg_data)\
-do {\
-   if (wcn->chip_version == WCN36XX_CHIP_3680)  \
-   wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
-   else \
-   wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
-} while (0) \
-
 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
 {
-   *data = readl(wcn->mmio + addr);
+   *data = readl(wcn->dxe_base + addr);
 
wcn36xx_dbg(WCN36XX_DBG_DXE,
"wcn36xx_dxe_read_register: addr=%x, data=%x\n",
@@ -703,7 +704,10 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
 
/* Setting interrupt path */
reg_data = WCN36XX_DXE_CCU_INT;
-   wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
+   if (wcn->chip_version == WCN36XX_CHIP_3680)
+   wcn36xx_ccu_write_register(wcn, WCN36XX_DXE_REG_CCU_INT_3680, 
reg_data);
+   else
+   wcn36xx_ccu_write_register(wcn, WCN36XX_DXE_REG_CCU_INT_3660, 
reg_data);
 
/***/
/* Init descriptors for TX LOW channel */
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h 
b/drivers/net/wireless/ath/wcn36xx/dxe.h
index 3eca4f9594f2..012b59f4f91b 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.h
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.h
@@ -28,11 +28,11 @@ H2H_TEST_RX_TX = DMA2
 */
 
 /* DXE registers */
-#define WCN36XX_DXE_MEM_REG0x202000
+#define WCN36XX_DXE_MEM_REG0
 
 #define WCN36XX_DXE_CCU_INT0xA0011
-#define WCN36XX_DXE_REG_CCU_INT_3660   0x200b10
-#define WCN36XX_DXE_REG_CCU_INT_3680   0x2050dc
+#define WCN36XX_DXE_REG_CCU_INT_3660   0x310
+#define WCN36XX_DXE_REG_CCU_INT_3680   0x10dc
 
 /* TODO This must calculated properly but not hardcoded */
 #define WCN36XX_DXE_CTRL_TX_L  0x328a44
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index a920d7020148..8146eeba4458 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -19,6 +19,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -1064,7 +1066,11 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
  struct platform_device *pdev)
 {
+   struct device_node *mmio_node;
struct resource *res;
+   int index;
+   int ret;
+
/* Set TX IRQ */
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
   "wcnss_wlantx_irq");
@@ -1083,19 +1089,38 @@ static int wcn36xx_platform_get_resources(struct 
wcn36xx *wcn,
}
wcn->rx_irq = res->start;
 
-   /* Map the memory */
-   res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-"wcnss_mmio");
-   if (!res) {
-   wcn36xx_err("failed to get mmio\n");
-   return -ENOENT;
+   mmio_node = of_pa

[PATCH 6/6] wcn36xx: Fix up wcn36xx_smd_update_scan_params()

2016-06-20 Thread Bjorn Andersson
Fix up the wcn36xx_smd_update_scan_params() to work with non-ancient
versions of the firmware and support actually specifying the list of
channels.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/hal.h |  4 ++--
 drivers/net/wireless/ath/wcn36xx/smd.c | 15 +--
 drivers/net/wireless/ath/wcn36xx/smd.h |  2 +-
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index 658bfb8baabe..4f87ef1e1eb8 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -4123,7 +4123,7 @@ struct wcn36xx_hal_update_scan_params_req {
 
 /* Update scan params - sent from host to PNO to be used during PNO
  * scanningx */
-struct update_scan_params_req_ex {
+struct wcn36xx_hal_update_scan_params_req_ex {
 
struct wcn36xx_hal_msg_header header;
 
@@ -4151,7 +4151,7 @@ struct update_scan_params_req_ex {
 
/* Cb State */
enum phy_chan_bond_state state;
-};
+} __packed;
 
 /* Update scan params - sent from host to PNO to be used during PNO
  * scanningx */
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index f9b2785cc277..994eba6cbaa8 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -675,22 +675,25 @@ static int wcn36xx_smd_update_scan_params_rsp(void *buf, 
size_t len)
return 0;
 }
 
-int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
+int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
+  u8 *channels, size_t channel_count)
 {
-   struct wcn36xx_hal_update_scan_params_req msg_body;
+   struct wcn36xx_hal_update_scan_params_req_ex msg_body;
int ret = 0;
 
mutex_lock(>hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
 
-   msg_body.dot11d_enabled = 0;
-   msg_body.dot11d_resolved = 0;
-   msg_body.channel_count = 26;
+   msg_body.dot11d_enabled = false;
+   msg_body.dot11d_resolved = true;
+
+   msg_body.channel_count = channel_count;
+   memcpy(msg_body.channels, channels, channel_count);
msg_body.active_min_ch_time = 60;
msg_body.active_max_ch_time = 120;
msg_body.passive_min_ch_time = 60;
msg_body.passive_max_ch_time = 110;
-   msg_body.state = 0;
+   msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
 
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h 
b/drivers/net/wireless/ath/wcn36xx/smd.h
index 493f6191a173..40d829563c2b 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -64,7 +64,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn);
 int wcn36xx_smd_end_scan(struct wcn36xx *wcn);
 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
enum wcn36xx_hal_sys_mode mode);
-int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn);
+int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t 
channel_count);
 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif);
 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr);
 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/6] wcn36xx: Change indication list lock to spinlock

2016-06-20 Thread Bjorn Andersson
From: Bjorn Andersson <bjorn.anders...@sonymobile.com>

In preparation for handling incoming messages from IRQ context, change
the indication list lock to a spinlock

Signed-off-by: Bjorn Andersson <bjorn.anders...@sonymobile.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 12 ++--
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 1a9580d72077..b2108076f5c0 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2243,10 +2243,10 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx 
*wcn, void *buf, size_t len)
msg_ind->msg_len = len;
memcpy(msg_ind->msg, buf, len);
 
-   mutex_lock(>hal_ind_mutex);
+   spin_lock(>hal_ind_lock);
list_add_tail(_ind->list, >hal_ind_queue);
queue_work(wcn->hal_ind_wq, >hal_ind_work);
-   mutex_unlock(>hal_ind_mutex);
+   spin_unlock(>hal_ind_lock);
wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
break;
default:
@@ -2260,8 +2260,9 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
container_of(work, struct wcn36xx, hal_ind_work);
struct wcn36xx_hal_msg_header *msg_header;
struct wcn36xx_hal_ind_msg *hal_ind_msg;
+   unsigned long flags;
 
-   mutex_lock(>hal_ind_mutex);
+   spin_lock_irqsave(>hal_ind_lock, flags);
 
hal_ind_msg = list_first_entry(>hal_ind_queue,
   struct wcn36xx_hal_ind_msg,
@@ -2293,8 +2294,8 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
  msg_header->msg_type);
}
list_del(wcn->hal_ind_queue.next);
+   spin_unlock_irqrestore(>hal_ind_lock, flags);
kfree(hal_ind_msg);
-   mutex_unlock(>hal_ind_mutex);
 }
 int wcn36xx_smd_open(struct wcn36xx *wcn)
 {
@@ -2307,7 +2308,7 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
}
INIT_WORK(>hal_ind_work, wcn36xx_ind_smd_work);
INIT_LIST_HEAD(>hal_ind_queue);
-   mutex_init(>hal_ind_mutex);
+   spin_lock_init(>hal_ind_lock);
 
ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
if (ret) {
@@ -2327,5 +2328,4 @@ void wcn36xx_smd_close(struct wcn36xx *wcn)
 {
wcn->ctrl_ops->close();
destroy_workqueue(wcn->hal_ind_wq);
-   mutex_destroy(>hal_ind_mutex);
 }
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 7433d67a5929..f6d8d14f13d1 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -215,7 +215,7 @@ struct wcn36xx {
struct completion   hal_rsp_compl;
struct workqueue_struct *hal_ind_wq;
struct work_struct  hal_ind_work;
-   struct mutexhal_ind_mutex;
+   spinlock_t  hal_ind_lock;
struct list_headhal_ind_queue;
 
/* DXE channels */
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC] wcn36xx: Implement firmware assisted scan

2016-05-12 Thread Bjorn Andersson
Using the software based channel scan mechanism from mac80211 keeps us
offline for 10-15 second, we should instead issue a start_scan/end_scan
on each channel reducing this time.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

With this implementation I see a reduction of throughput for about 1-2 seconds
with iperf while scanning, so the improvement is clear.

The problem with the implementation is that ieee80211_rx_status must specify
the correct band for the core to not drop the beacons. I have searched for
indications in the incoming data, but am not able to find anything useful, so
this currently rely on shared state (scan_freq/scan_band) that gets updated
during scan.

If anyone familiar with this hardware have any suggestions on how to better
deal with this I would appreciate the feedback.

 drivers/net/wireless/ath/wcn36xx/main.c| 62 --
 drivers/net/wireless/ath/wcn36xx/smd.c |  8 ++--
 drivers/net/wireless/ath/wcn36xx/smd.h |  4 +-
 drivers/net/wireless/ath/wcn36xx/txrx.c| 19 ++---
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  9 +
 5 files changed, 79 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 25a492d7504b..20ff661694ed 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -489,23 +489,57 @@ out:
return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_hw_scan_worker(struct work_struct *work)
 {
-   struct wcn36xx *wcn = hw->priv;
+   struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
+   struct cfg80211_scan_request *req = wcn->scan_req;
+   u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
+   int i;
+
+   wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", 
req->n_channels);
+
+   for (i = 0; i < req->n_channels; i++)
+   channels[i] = req->channels[i]->hw_value;
+
+   wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
 
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
-   wcn36xx_smd_start_scan(wcn);
+   for (i = 0; i < req->n_channels; i++) {
+   wcn->scan_freq = req->channels[i]->center_freq;
+   wcn->scan_band = req->channels[i]->band;
+
+   wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
+   msleep(30);
+   wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
+
+   wcn->scan_freq = 0;
+   }
+   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+
+   ieee80211_scan_completed(wcn->hw, false);
+
+   mutex_lock(>scan_lock);
+   wcn->scan_req = NULL;
+   mutex_unlock(>scan_lock);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
-struct ieee80211_vif *vif)
+static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif,
+  struct ieee80211_scan_request *hw_req)
 {
struct wcn36xx *wcn = hw->priv;
 
-   wcn36xx_smd_end_scan(wcn);
-   wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
+   mutex_lock(>scan_lock);
+   if (wcn->scan_req) {
+   mutex_unlock(>scan_lock);
+   return -EBUSY;
+   }
+   wcn->scan_req = _req->req;
+   mutex_unlock(>scan_lock);
+
+   schedule_work(>scan_work);
+
+   return 0;
 }
 
 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@@ -919,8 +953,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.configure_filter   = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
-   .sw_scan_start  = wcn36xx_sw_scan_start,
-   .sw_scan_complete   = wcn36xx_sw_scan_complete,
+   .hw_scan= wcn36xx_hw_scan,
.bss_info_changed   = wcn36xx_bss_info_changed,
.set_rts_threshold  = wcn36xx_set_rts_threshold,
.sta_add= wcn36xx_sta_add,
@@ -945,6 +978,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
+   ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
 
wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
@@ -954,6 +988,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = _band_2ghz;
wcn->hw->wip

[PATCH] wcn36xx: Set SMD timeout to 10 seconds

2016-04-21 Thread Bjorn Andersson
After booting the wireless subsystem and uploading the NV blob to the
WCNSS_CTRL service the remote continues to do things and will not start
servicing wlan-requests for another 2-5 seconds (measured).

The downstream code does not have any special handling for this case,
but has a timeout of 10 seconds for the communication layer. By
extending the wcn36xx timeout to match this we follows the same flow for
the boot procedure and can successfully configure WiFi as wlan0 is
registered.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h 
b/drivers/net/wireless/ath/wcn36xx/smd.h
index e6aadd273c46..6310560901f0 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -24,7 +24,7 @@
 
 #define WCN36XX_HAL_BUF_SIZE   4096
 
-#define HAL_MSG_TIMEOUT 500
+#define HAL_MSG_TIMEOUT 1
 #define WCN36XX_SMSM_WLAN_TX_ENABLE0x0400
 #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY   0x0200
 /* The PNO version info be contained in the rsp msg */
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 04/18] wcn36xx: Use consistent name for private vif

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Some code used priv_vif and some used vif_priv. Convert all to vif_priv
for consistency.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index cc1b3b7a4ff9..170440ed5d85 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -191,7 +191,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params *sta_params)
 {
-   struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif);
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
struct wcn36xx_sta *priv_sta = NULL;
if (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_AP ||
@@ -215,7 +215,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
else
memcpy(_params->bssid, vif->addr, ETH_ALEN);
 
-   sta_params->encrypt_type = priv_vif->encrypt_type;
+   sta_params->encrypt_type = vif_priv->encrypt_type;
sta_params->short_preamble_supported = true;
 
sta_params->rifs_mode = 0;
@@ -224,7 +224,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
sta_params->uapsd = 0;
sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
sta_params->max_ampdu_duration = 0;
-   sta_params->bssid_index = priv_vif->bss_index;
+   sta_params->bssid_index = vif_priv->bss_index;
sta_params->p2p = 0;
 
if (sta) {
@@ -726,7 +726,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
size_t len)
 {
struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
-   struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif);
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 
if (len < sizeof(*rsp))
return -EINVAL;
@@ -743,8 +743,8 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
"hal add sta self status %d self_sta_index %d dpu_index 
%d\n",
rsp->status, rsp->self_sta_index, rsp->dpu_index);
 
-   priv_vif->self_sta_index = rsp->self_sta_index;
-   priv_vif->self_dpu_desc_index = rsp->dpu_index;
+   vif_priv->self_sta_index = rsp->self_sta_index;
+   vif_priv->self_dpu_desc_index = rsp->dpu_index;
 
return 0;
 }
@@ -1175,7 +1175,7 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
 {
struct wcn36xx_hal_config_bss_rsp_msg *rsp;
struct wcn36xx_hal_config_bss_rsp_params *params;
-   struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif);
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 
if (len < sizeof(*rsp))
return -EINVAL;
@@ -1198,14 +1198,14 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx 
*wcn,
params->bss_bcast_sta_idx, params->mac,
params->tx_mgmt_power, params->ucast_dpu_signature);
 
-   priv_vif->bss_index = params->bss_index;
+   vif_priv->bss_index = params->bss_index;
 
-   if (priv_vif->sta) {
-   priv_vif->sta->bss_sta_index =  params->bss_sta_index;
-   priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
+   if (vif_priv->sta) {
+   vif_priv->sta->bss_sta_index =  params->bss_sta_index;
+   vif_priv->sta->bss_dpu_desc_index = params->dpu_desc_index;
}
 
-   priv_vif->self_ucast_dpu_sign = params->ucast_dpu_signature;
+   vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
 
return 0;
 }
@@ -1343,13 +1343,13 @@ out:
 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
 {
struct wcn36xx_hal_delete_bss_req_msg msg_body;
-   struct wcn36xx_vif *priv_vif = wcn36xx_vif_to_priv(vif);
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
int ret = 0;
 
mutex_lock(>hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
 
-   msg_body.bss_index = priv_vif->bss_index;
+   msg_body.bss_index = vif_priv->bss_index;
 
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 06/18] wcn36xx: Add helper macros to cast sta to priv

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

While poking at this I also change two related things. I rename one
variable to make the names consistent. I also move one assignment of
priv_sta to the declaration to save a few lines.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/main.c| 14 ++
 drivers/net/wireless/ath/wcn36xx/smd.c | 12 ++--
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  6 ++
 3 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 4781b5e8deb3..30f015d3a9e6 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -373,7 +373,7 @@ static void wcn36xx_tx(struct ieee80211_hw *hw,
struct wcn36xx_sta *sta_priv = NULL;
 
if (control->sta)
-   sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv;
+   sta_priv = wcn36xx_sta_to_priv(control->sta);
 
if (wcn36xx_start_tx(wcn, sta_priv, skb))
ieee80211_free_txskb(wcn->hw, skb);
@@ -518,7 +518,7 @@ static void wcn36xx_update_allowed_rates(struct 
ieee80211_sta *sta,
 {
int i, size;
u16 *rates_table;
-   struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
+   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
u32 rates = sta->supp_rates[band];
 
memset(_priv->supported_rates, 0,
@@ -661,7 +661,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
rcu_read_unlock();
goto out;
}
-   sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
+   sta_priv = wcn36xx_sta_to_priv(sta);
 
wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
 
@@ -791,7 +791,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 {
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-   struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
+   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
vif, sta->addr);
 
@@ -816,7 +816,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
 {
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-   struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
+   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
 
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
vif, sta->addr, sta_priv->sta_index);
@@ -858,7 +858,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_ampdu_params *params)
 {
struct wcn36xx *wcn = hw->priv;
-   struct wcn36xx_sta *sta_priv = NULL;
+   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
struct ieee80211_sta *sta = params->sta;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
@@ -867,8 +867,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
action, tid);
 
-   sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
-
switch (action) {
case IEEE80211_AMPDU_RX_START:
sta_priv->tid = tid;
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 6d4aa9250ca8..ff56138528b6 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -192,7 +192,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
struct wcn36xx_hal_config_sta_params *sta_params)
 {
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-   struct wcn36xx_sta *priv_sta = NULL;
+   struct wcn36xx_sta *sta_priv = NULL;
if (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT) {
@@ -228,17 +228,17 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx 
*wcn,
sta_params->p2p = 0;
 
if (sta) {
-   priv_sta = (struct wcn36xx_sta *)sta->drv_priv;
+   sta_priv = wcn36xx_sta_to_priv(sta);
if (NL80211_IFTYPE_STATION == vif->type)
memcpy(_params->bssid, sta->addr, ETH_ALEN);
else
memcpy(_params->mac, sta->addr, ETH_ALEN);
  

[PATCH v3 01/18] wcn36xx: Clean up wcn36xx_smd_send_beacon

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Needed for coming improvements. No functional changes.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
[bjorn: restored BEACON_TEMPLATE_SIZE define to 0x180]
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v2:
- Subtract sizeof(beacon_length) instead of modifying BEACON_TEMPLATE_SIZE,
  which is used in other places as well.

 drivers/net/wireless/ath/wcn36xx/hal.h |  5 -
 drivers/net/wireless/ath/wcn36xx/smd.c | 12 +---
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index b947de0fb2e5..d713204f755d 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -2884,11 +2884,14 @@ struct update_beacon_rsp_msg {
 struct wcn36xx_hal_send_beacon_req_msg {
struct wcn36xx_hal_msg_header header;
 
+   /* length of the template + 6. Only qcom knows why */
+   u32 beacon_length6;
+
/* length of the template. */
u32 beacon_length;
 
/* Beacon data. */
-   u8 beacon[BEACON_TEMPLATE_SIZE];
+   u8 beacon[BEACON_TEMPLATE_SIZE - sizeof(u32)];
 
u8 bssid[ETH_ALEN];
 
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 74f56a81ad9a..ff3ed2461a69 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1380,19 +1380,17 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct 
ieee80211_vif *vif,
mutex_lock(>hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
 
-   /* TODO need to find out why this is needed? */
-   msg_body.beacon_length = skb_beacon->len + 6;
+   msg_body.beacon_length = skb_beacon->len;
+   /* TODO need to find out why + 6 is needed */
+   msg_body.beacon_length6 = msg_body.beacon_length + 6;
 
-   if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
-   memcpy(_body.beacon, _beacon->len, sizeof(u32));
-   memcpy(&(msg_body.beacon[4]), skb_beacon->data,
-  skb_beacon->len);
-   } else {
+   if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
wcn36xx_err("Beacon is to big: beacon size=%d\n",
  msg_body.beacon_length);
ret = -ENOMEM;
goto out;
}
+   memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
 
/* TODO need to find out why this is needed? */
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 07/18] wcn36xx: Fetch private sta data from sta entry instead of from vif

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

For consistency with other code.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v1:
- Reordered after the now previous patch, to make wcn36xx_sta_to_priv()
  available before we use it

 drivers/net/wireless/ath/wcn36xx/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 30f015d3a9e6..a23738deb5b3 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -386,7 +386,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
 {
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-   struct wcn36xx_sta *sta_priv = vif_priv->sta;
+   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
int ret = 0;
u8 key[WLAN_MAX_KEY_LEN];
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 08/18] wcn36xx: Remove sta pointer in private vif struct

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

This does not work with multiple sta's in a vif.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/main.c|  3 ---
 drivers/net/wireless/ath/wcn36xx/smd.c | 28 +++-
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  1 -
 3 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index a23738deb5b3..7c06ca9fdd2c 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -796,7 +796,6 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
vif, sta->addr);
 
spin_lock_init(_priv->ampdu_lock);
-   vif_priv->sta = sta_priv;
sta_priv->vif = vif_priv;
/*
 * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
@@ -815,14 +814,12 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
  struct ieee80211_sta *sta)
 {
struct wcn36xx *wcn = hw->priv;
-   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
 
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
vif, sta->addr, sta_priv->sta_index);
 
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
-   vif_priv->sta = NULL;
sta_priv->vif = NULL;
return 0;
 }
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index ff56138528b6..76c6856ed932 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1170,6 +1170,7 @@ static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
 
 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
  struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
  void *buf,
  size_t len)
 {
@@ -1200,9 +1201,10 @@ static int wcn36xx_smd_config_bss_rsp(struct wcn36xx 
*wcn,
 
vif_priv->bss_index = params->bss_index;
 
-   if (vif_priv->sta) {
-   vif_priv->sta->bss_sta_index =  params->bss_sta_index;
-   vif_priv->sta->bss_dpu_desc_index = params->dpu_desc_index;
+   if (sta) {
+   struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
+   sta_priv->bss_sta_index = params->bss_sta_index;
+   sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
}
 
vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
@@ -1329,6 +1331,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct 
ieee80211_vif *vif,
}
ret = wcn36xx_smd_config_bss_rsp(wcn,
 vif,
+sta,
 wcn->hal_buf,
 wcn->hal_rsp_len);
if (ret) {
@@ -2058,25 +2061,24 @@ static int wcn36xx_smd_delete_sta_context_ind(struct 
wcn36xx *wcn,
 {
struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
struct wcn36xx_vif *tmp;
-   struct ieee80211_sta *sta = NULL;
+   struct ieee80211_sta *sta;
 
if (len != sizeof(*rsp)) {
wcn36xx_warn("Corrupted delete sta indication\n");
return -EIO;
}
 
+   wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
+   rsp->addr2, rsp->sta_id);
+
list_for_each_entry(tmp, >vif_list, list) {
-   if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
-   sta = container_of((void *)tmp->sta,
-struct ieee80211_sta,
-drv_priv);
-   wcn36xx_dbg(WCN36XX_DBG_HAL,
-   "delete station indication %pM index %d\n",
-   rsp->addr2,
-   rsp->sta_id);
+   rcu_read_lock();
+   sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
+   if (sta)
ieee80211_report_low_ack(sta, 0);
+   rcu_read_unlock();
+   if (sta)
return 0;
-   }
}
 
wcn36xx_warn("STA with addr %pM and index %d not found\n",
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index c368a34c8de7..54000db0af

[PATCH v3 03/18] wcn36xx: Add helper macros to cast vif to private vif and vice versa

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Makes the code a little easier to read.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/debug.c   | 12 +++-
 drivers/net/wireless/ath/wcn36xx/main.c| 16 +++-
 drivers/net/wireless/ath/wcn36xx/pmc.c |  4 ++--
 drivers/net/wireless/ath/wcn36xx/smd.c | 24 ++--
 drivers/net/wireless/ath/wcn36xx/txrx.c|  8 ++--
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 12 
 6 files changed, 36 insertions(+), 40 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c 
b/drivers/net/wireless/ath/wcn36xx/debug.c
index ef44a2da644d..2a6bb62e785c 100644
--- a/drivers/net/wireless/ath/wcn36xx/debug.c
+++ b/drivers/net/wireless/ath/wcn36xx/debug.c
@@ -33,9 +33,7 @@ static ssize_t read_file_bool_bmps(struct file *file, char 
__user *user_buf,
char buf[3];
 
list_for_each_entry(vif_priv, >vif_list, list) {
-   vif = container_of((void *)vif_priv,
-  struct ieee80211_vif,
-  drv_priv);
+   vif = wcn36xx_priv_to_vif(vif_priv);
if (NL80211_IFTYPE_STATION == vif->type) {
if (vif_priv->pw_state == WCN36XX_BMPS)
buf[0] = '1';
@@ -70,9 +68,7 @@ static ssize_t write_file_bool_bmps(struct file *file,
case 'Y':
case '1':
list_for_each_entry(vif_priv, >vif_list, list) {
-   vif = container_of((void *)vif_priv,
-  struct ieee80211_vif,
-  drv_priv);
+   vif = wcn36xx_priv_to_vif(vif_priv);
if (NL80211_IFTYPE_STATION == vif->type) {
wcn36xx_enable_keep_alive_null_packet(wcn, vif);
wcn36xx_pmc_enter_bmps_state(wcn, vif);
@@ -83,9 +79,7 @@ static ssize_t write_file_bool_bmps(struct file *file,
case 'N':
case '0':
list_for_each_entry(vif_priv, >vif_list, list) {
-   vif = container_of((void *)vif_priv,
-  struct ieee80211_vif,
-  drv_priv);
+   vif = wcn36xx_priv_to_vif(vif_priv);
if (NL80211_IFTYPE_STATION == vif->type)
wcn36xx_pmc_exit_bmps_state(wcn, vif);
}
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index a27279c2c695..62cb9ffd854c 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -346,9 +346,7 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 
changed)
wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel 
switch=%d\n",
ch);
list_for_each_entry(tmp, >vif_list, list) {
-   vif = container_of((void *)tmp,
-  struct ieee80211_vif,
-  drv_priv);
+   vif = wcn36xx_priv_to_vif(tmp);
wcn36xx_smd_switch_channel(wcn, vif, ch);
}
}
@@ -387,7 +385,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
   struct ieee80211_key_conf *key_conf)
 {
struct wcn36xx *wcn = hw->priv;
-   struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
struct wcn36xx_sta *sta_priv = vif_priv->sta;
int ret = 0;
u8 key[WLAN_MAX_KEY_LEN];
@@ -590,7 +588,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
struct sk_buff *skb = NULL;
u16 tim_off, tim_len;
enum wcn36xx_hal_link_state link_state;
-   struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 
0x%08x\n",
vif, changed);
@@ -757,7 +755,7 @@ static void wcn36xx_remove_interface(struct ieee80211_hw 
*hw,
 struct ieee80211_vif *vif)
 {
struct wcn36xx *wcn = hw->priv;
-   struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
+   struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
 
list_del(_priv->list);
@@ -768,7 +766,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,

[PATCH v3 00/18] wcn36xx fixes

2016-04-18 Thread Bjorn Andersson
The bulk of the following patches have been sitting in Eugene's Github tree for
quite some time. They fix various issues existing in the mainline drivers, so
they should be merged there too.

Also included are two new fixes, of my own; the important one being the
reordering of deletion of the bss, as this crashes the firmware on the
Dragonbaord 410c (apq8016 with pronto & wcn3620).

Lastly is a patch that adds a bunch of new capabilities found in the downstream
driver.

Changes since v2:
- Restore BEACON_TEMPLATE_SIZE to not break UPDATE_PROBE_RSP_TEMPLATE_REQ
- Added patch to correct WCN36XX_HAL_RMV_BSSKEY_RSP decoder
- Added patch with missing capabilities from downstream

Changes since v1:
- Reorder patch 6 and 7 to not break the build temporarily
- Inline fix from Jason Mobarak in the TIM PVM padding

Bjorn Andersson (3):
  wcn36xx: Delete BSS before idling link
  wcn36xx: Correct remove bss key response encoding
  wcn36xx: Fill in capability list

Pontus Fuchs (15):
  wcn36xx: Clean up wcn36xx_smd_send_beacon
  wcn36xx: Pad TIM PVM if needed
  wcn36xx: Add helper macros to cast vif to private vif and vice versa
  wcn36xx: Use consistent name for private vif
  wcn36xx: Use define for invalid index and fix typo
  wcn36xx: Add helper macros to cast sta to priv
  wcn36xx: Fetch private sta data from sta entry instead of from vif
  wcn36xx: Remove sta pointer in private vif struct
  wcn36xx: Parse trigger_ba response properly
  wcn36xx: Copy all members in config_sta v1 conversion
  wcn36xx: Use allocated self sta index instead of hard coded
  wcn36xx: Clear encrypt_type when deleting bss key
  wcn36xx: Track association state
  wcn36xx: Implement multicast filtering
  wcn36xx: Use correct command struct for EXIT_BMPS_REQ

 drivers/net/wireless/ath/wcn36xx/debug.c   |  12 +-
 drivers/net/wireless/ath/wcn36xx/hal.h |  55 ++-
 drivers/net/wireless/ath/wcn36xx/main.c| 133 +
 drivers/net/wireless/ath/wcn36xx/pmc.c |   4 +-
 drivers/net/wireless/ath/wcn36xx/smd.c | 224 +++--
 drivers/net/wireless/ath/wcn36xx/smd.h |  12 +-
 drivers/net/wireless/ath/wcn36xx/txrx.c|   8 +-
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  20 ++-
 8 files changed, 336 insertions(+), 132 deletions(-)

-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 12/18] wcn36xx: Clear encrypt_type when deleting bss key

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

This fixes a problem connecting to an open network after being
connected to an encrypted network.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 7c06ca9fdd2c..f9c77de94583 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -471,6 +471,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
break;
case DISABLE_KEY:
if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
+   vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
wcn36xx_smd_remove_bsskey(wcn,
vif_priv->encrypt_type,
key_conf->keyidx);
@@ -626,6 +627,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
} else {
vif_priv->is_joining = false;
wcn36xx_smd_delete_bss(wcn, vif);
+   vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
}
}
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 09/18] wcn36xx: Parse trigger_ba response properly

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

This message does not follow the canonical format and needs it's own
parser.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 76c6856ed932..7f315d098f52 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1968,6 +1968,17 @@ out:
return ret;
 }
 
+static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len)
+{
+   struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
+
+   if (len < sizeof(*rsp))
+   return -EINVAL;
+
+   rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
+   return rsp->status;
+}
+
 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
 {
struct wcn36xx_hal_trigger_ba_req_msg msg_body;
@@ -1992,8 +2003,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 
sta_index)
wcn36xx_err("Sending hal_trigger_ba failed\n");
goto out;
}
-   ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
-   wcn->hal_rsp_len);
+   ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
goto out;
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 05/18] wcn36xx: Use define for invalid index and fix typo

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/hal.h  | 2 +-
 drivers/net/wireless/ath/wcn36xx/main.c | 4 ++--
 drivers/net/wireless/ath/wcn36xx/smd.c  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index 3af16cba3d12..433d9801a0ae 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -48,7 +48,7 @@
 
 #define WCN36XX_HAL_IPV4_ADDR_LEN   4
 
-#define WALN_HAL_STA_INVALID_IDX 0xFF
+#define WCN36XX_HAL_STA_INVALID_IDX 0xFF
 #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF
 
 /* Default Beacon template size */
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 62cb9ffd854c..4781b5e8deb3 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -618,7 +618,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
 
if (!is_zero_ether_addr(bss_conf->bssid)) {
vif_priv->is_joining = true;
-   vif_priv->bss_index = 0xff;
+   vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
wcn36xx_smd_join(wcn, bss_conf->bssid,
 vif->addr, WCN36XX_HW_CHANNEL(wcn));
wcn36xx_smd_config_bss(wcn, vif, NULL,
@@ -711,7 +711,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
 
if (bss_conf->enable_beacon) {
vif_priv->dtim_period = bss_conf->dtim_period;
-   vif_priv->bss_index = 0xff;
+   vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
wcn36xx_smd_config_bss(wcn, vif, NULL,
   vif->addr, false);
skb = ieee80211_beacon_get_tim(hw, vif, _off,
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 170440ed5d85..6d4aa9250ca8 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -197,7 +197,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT) {
sta_params->type = 1;
-   sta_params->sta_index = 0xFF;
+   sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
} else {
sta_params->type = 0;
sta_params->sta_index = 1;
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 11/18] wcn36xx: Use allocated self sta index instead of hard coded

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index ebb446272d21..e0d5631657c1 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -200,7 +200,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
} else {
sta_params->type = 0;
-   sta_params->sta_index = 1;
+   sta_params->sta_index = vif_priv->self_sta_index;
}
 
sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 10/18] wcn36xx: Copy all members in config_sta v1 conversion

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

When converting to version 1 of the config_sta struct not all
members where copied. This fixes the problem of multicast frames
not being delivered on an encrypted network.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 19 +--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index 7f315d098f52..ebb446272d21 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -949,17 +949,32 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx 
*wcn,
memcpy(>mac, orig->mac, ETH_ALEN);
v1->aid = orig->aid;
v1->type = orig->type;
+   v1->short_preamble_supported = orig->short_preamble_supported;
v1->listen_interval = orig->listen_interval;
+   v1->wmm_enabled = orig->wmm_enabled;
v1->ht_capable = orig->ht_capable;
-
+   v1->tx_channel_width_set = orig->tx_channel_width_set;
+   v1->rifs_mode = orig->rifs_mode;
+   v1->lsig_txop_protection = orig->lsig_txop_protection;
v1->max_ampdu_size = orig->max_ampdu_size;
v1->max_ampdu_density = orig->max_ampdu_density;
v1->sgi_40mhz = orig->sgi_40mhz;
v1->sgi_20Mhz = orig->sgi_20Mhz;
-
+   v1->rmf = orig->rmf;
+   v1->encrypt_type = orig->encrypt_type;
+   v1->action = orig->action;
+   v1->uapsd = orig->uapsd;
+   v1->max_sp_len = orig->max_sp_len;
+   v1->green_field_capable = orig->green_field_capable;
+   v1->mimo_ps = orig->mimo_ps;
+   v1->delayed_ba_support = orig->delayed_ba_support;
+   v1->max_ampdu_duration = orig->max_ampdu_duration;
+   v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
memcpy(>supported_rates, >supported_rates,
   sizeof(orig->supported_rates));
v1->sta_index = orig->sta_index;
+   v1->bssid_index = orig->bssid_index;
+   v1->p2p = orig->p2p;
 }
 
 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 17/18] wcn36xx: Correct remove bss key response encoding

2016-04-18 Thread Bjorn Andersson
The WCN36XX_HAL_RMV_BSSKEY_RSP carries a single u32 with "status", so we
can use the standard status check function for decoding the result.

This is the last user of the v2 status checker, so remove the struct and
helper function.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v2:
- Added this patch to the series

 drivers/net/wireless/ath/wcn36xx/smd.c | 19 +--
 drivers/net/wireless/ath/wcn36xx/smd.h |  9 -
 2 files changed, 1 insertion(+), 27 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index c15501c06eb2..5f6ca3124bd8 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -312,22 +312,6 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t 
len)
return 0;
 }
 
-static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf,
-size_t len)
-{
-   struct wcn36xx_fw_msg_status_rsp_v2 *rsp;
-
-   if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
-   return wcn36xx_smd_rsp_status_check(buf, len);
-
-   rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
-
-   if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
-   return rsp->status;
-
-   return 0;
-}
-
 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 {
struct nv_data *nv_d;
@@ -1647,8 +1631,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
wcn36xx_err("Sending hal_remove_bsskey failed\n");
goto out;
}
-   ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
- wcn->hal_rsp_len);
+   ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
if (ret) {
wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
goto out;
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h 
b/drivers/net/wireless/ath/wcn36xx/smd.h
index c1b76d75cf85..d74d781f4c8d 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -44,15 +44,6 @@ struct wcn36xx_fw_msg_status_rsp {
u32 status;
 } __packed;
 
-/* wcn3620 returns this for tigger_ba */
-
-struct wcn36xx_fw_msg_status_rsp_v2 {
-   u8  bss_id[6];
-   u32 status __packed;
-   u16 count_following_candidates __packed;
-   /* candidate list follows */
-};
-
 struct wcn36xx_hal_ind_msg {
struct list_head list;
u8 *msg;
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 14/18] wcn36xx: Implement multicast filtering

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Pass the multicast list to FW.

This patch also adds a way to build the smd command in place. This is
needed because the MC list command is too big for the stack.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
[bjorn: dropped FIF_PROMISC_IN_BSS usage]
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/hal.h  |  6 ++--
 drivers/net/wireless/ath/wcn36xx/main.c | 50 ++--
 drivers/net/wireless/ath/wcn36xx/smd.c  | 51 +
 drivers/net/wireless/ath/wcn36xx/smd.h  |  3 ++
 4 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index 433d9801a0ae..ec64c47f918b 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -4267,9 +4267,9 @@ struct wcn36xx_hal_rcv_flt_mc_addr_list_type {
u8 data_offset;
 
u32 mc_addr_count;
-   u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS];
+   u8 mc_addr[WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS][ETH_ALEN];
u8 bss_index;
-};
+} __packed;
 
 struct wcn36xx_hal_set_pkt_filter_rsp_msg {
struct wcn36xx_hal_msg_header header;
@@ -4323,7 +4323,7 @@ struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg {
 struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg {
struct wcn36xx_hal_msg_header header;
struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list;
-};
+} __packed;
 
 struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg {
struct wcn36xx_hal_msg_header header;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 253cece1b660..c0ba7b0775b3 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -287,6 +287,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
}
 
wcn36xx_detect_chip_version(wcn);
+   wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
 
/* DMA channel initialization */
ret = wcn36xx_dxe_init(wcn);
@@ -354,15 +355,57 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 
changed)
return 0;
 }
 
-#define WCN36XX_SUPPORTED_FILTERS (0)
-
 static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
 unsigned int changed,
 unsigned int *total, u64 multicast)
 {
+   struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
+   struct wcn36xx *wcn = hw->priv;
+   struct wcn36xx_vif *tmp;
+   struct ieee80211_vif *vif = NULL;
+
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
 
-   *total &= WCN36XX_SUPPORTED_FILTERS;
+   *total &= FIF_ALLMULTI;
+
+   fp = (void *)(unsigned long)multicast;
+   list_for_each_entry(tmp, >vif_list, list) {
+   vif = wcn36xx_priv_to_vif(tmp);
+
+   /* FW handles MC filtering only when connected as STA */
+   if (*total & FIF_ALLMULTI)
+   wcn36xx_smd_set_mc_list(wcn, vif, NULL);
+   else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
+   wcn36xx_smd_set_mc_list(wcn, vif, fp);
+   }
+   kfree(fp);
+}
+
+static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw,
+struct netdev_hw_addr_list *mc_list)
+{
+   struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
+   struct netdev_hw_addr *ha;
+
+   wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n");
+   fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
+   if (!fp) {
+   wcn36xx_err("Out of memory setting filters.\n");
+   return 0;
+   }
+
+   fp->mc_addr_count = 0;
+   /* update multicast filtering parameters */
+   if (netdev_hw_addr_list_count(mc_list) <=
+   WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) {
+   netdev_hw_addr_list_for_each(ha, mc_list) {
+   memcpy(fp->mc_addr[fp->mc_addr_count],
+   ha->addr, ETH_ALEN);
+   fp->mc_addr_count++;
+   }
+   }
+
+   return (u64)(unsigned long)fp;
 }
 
 static void wcn36xx_tx(struct ieee80211_hw *hw,
@@ -920,6 +963,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.resume = wcn36xx_resume,
 #endif
.config = wcn36xx_config,
+   .prepare_multicast  = wcn36xx_prepare_multicast,
.configure_filter   = wcn36xx_configure_filter,
.tx = wcn36xx_tx,
.set_key= wcn36xx_set_key,
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index e0d5631657c1..b1bdc229e560 100644
--- a/drivers/ne

[PATCH v3 18/18] wcn36xx: Fill in capability list

2016-04-18 Thread Bjorn Andersson
Fill in the capability list with more values from the downstream driver.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v2:
- Added this patch to the series

 drivers/net/wireless/ath/wcn36xx/hal.h  | 39 
 drivers/net/wireless/ath/wcn36xx/main.c | 40 -
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index ec64c47f918b..658bfb8baabe 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -4389,6 +4389,45 @@ enum place_holder_in_cap_bitmap {
RTT = 20,
RATECTRL = 21,
WOW = 22,
+   WLAN_ROAM_SCAN_OFFLOAD = 23,
+   SPECULATIVE_PS_POLL = 24,
+   SCAN_SCH = 25,
+   IBSS_HEARTBEAT_OFFLOAD = 26,
+   WLAN_SCAN_OFFLOAD = 27,
+   WLAN_PERIODIC_TX_PTRN = 28,
+   ADVANCE_TDLS = 29,
+   BATCH_SCAN = 30,
+   FW_IN_TX_PATH = 31,
+   EXTENDED_NSOFFLOAD_SLOT = 32,
+   CH_SWITCH_V1 = 33,
+   HT40_OBSS_SCAN = 34,
+   UPDATE_CHANNEL_LIST = 35,
+   WLAN_MCADDR_FLT = 36,
+   WLAN_CH144 = 37,
+   NAN = 38,
+   TDLS_SCAN_COEXISTENCE = 39,
+   LINK_LAYER_STATS_MEAS = 40,
+   MU_MIMO = 41,
+   EXTENDED_SCAN = 42,
+   DYNAMIC_WMM_PS = 43,
+   MAC_SPOOFED_SCAN = 44,
+   BMU_ERROR_GENERIC_RECOVERY = 45,
+   DISA = 46,
+   FW_STATS = 47,
+   WPS_PRBRSP_TMPL = 48,
+   BCN_IE_FLT_DELTA = 49,
+   TDLS_OFF_CHANNEL = 51,
+   RTT3 = 52,
+   MGMT_FRAME_LOGGING = 53,
+   ENHANCED_TXBD_COMPLETION = 54,
+   LOGGING_ENHANCEMENT = 55,
+   EXT_SCAN_ENHANCED = 56,
+   MEMORY_DUMP_SUPPORTED = 57,
+   PER_PKT_STATS_SUPPORTED = 58,
+   EXT_LL_STAT = 60,
+   WIFI_CONFIG = 61,
+   ANTENNA_DIVERSITY_SELECTION = 62,
+
MAX_FEATURE_SUPPORTED = 128,
 };
 
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index 680217506b3d..fe81b2a7c8d9 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -201,7 +201,45 @@ static const char * const wcn36xx_caps_names[] = {
"BCN_FILTER",   /* 19 */
"RTT",  /* 20 */
"RATECTRL", /* 21 */
-   "WOW"   /* 22 */
+   "WOW",  /* 22 */
+   "WLAN_ROAM_SCAN_OFFLOAD",   /* 23 */
+   "SPECULATIVE_PS_POLL",  /* 24 */
+   "SCAN_SCH", /* 25 */
+   "IBSS_HEARTBEAT_OFFLOAD",   /* 26 */
+   "WLAN_SCAN_OFFLOAD",/* 27 */
+   "WLAN_PERIODIC_TX_PTRN",/* 28 */
+   "ADVANCE_TDLS", /* 29 */
+   "BATCH_SCAN",   /* 30 */
+   "FW_IN_TX_PATH",/* 31 */
+   "EXTENDED_NSOFFLOAD_SLOT",  /* 32 */
+   "CH_SWITCH_V1", /* 33 */
+   "HT40_OBSS_SCAN",   /* 34 */
+   "UPDATE_CHANNEL_LIST",  /* 35 */
+   "WLAN_MCADDR_FLT",  /* 36 */
+   "WLAN_CH144",   /* 37 */
+   "NAN",  /* 38 */
+   "TDLS_SCAN_COEXISTENCE",/* 39 */
+   "LINK_LAYER_STATS_MEAS",/* 40 */
+   "MU_MIMO",  /* 41 */
+   "EXTENDED_SCAN",/* 42 */
+   "DYNAMIC_WMM_PS",   /* 43 */
+   "MAC_SPOOFED_SCAN", /* 44 */
+   "BMU_ERROR_GENERIC_RECOVERY",   /* 45 */
+   "DISA", /* 46 */
+   "FW_STATS", /* 47 */
+   "WPS_PRBRSP_TMPL",  /* 48 */
+   "BCN_IE_FLT_DELTA", /* 49 */
+   "TDLS_OFF_CHANNEL", /* 51 */
+   "RTT3", /* 52 */
+   "MGMT_FRAME_LOGGING",   /* 53 */
+   "ENHANCED_TXBD_COMPLETION", /* 54 */
+   "LOGGING_ENHANCEMENT",  /* 55 */
+   "EXT_SCAN_ENHANCED",/* 56 */
+   "MEMORY_DUMP_SUPPORTED",/* 57 */
+   "PER_PKT_STATS_SUPPORTED",  /* 58 */
+   "EXT_LL_STAT",  /* 60 */
+   "WIFI_CONFIG",  /* 61 */
+   "ANTENNA_DIVERSITY_SELECTION",  /* 62 */
 };
 
 static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 13/18] wcn36xx: Track association state

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

Knowing the association state is needed for mc filtering.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/main.c| 2 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index f9c77de94583..253cece1b660 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -655,6 +655,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
 vif->addr,
 bss_conf->aid);
 
+   vif_priv->sta_assoc = true;
rcu_read_lock();
sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (!sta) {
@@ -686,6 +687,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
bss_conf->bssid,
vif->addr,
bss_conf->aid);
+   vif_priv->sta_assoc = false;
wcn36xx_smd_set_link_st(wcn,
bss_conf->bssid,
vif->addr,
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h 
b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 54000db0af1a..7433d67a5929 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -128,6 +128,7 @@ struct wcn36xx_vif {
u8 dtim_period;
enum ani_ed_type encrypt_type;
bool is_joining;
+   bool sta_assoc;
struct wcn36xx_hal_mac_ssid ssid;
 
/* Power management */
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 16/18] wcn36xx: Delete BSS before idling link

2016-04-18 Thread Bjorn Andersson
When disabling the beacon we must delete the bss before idling the link.

Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v2:
- Added this patch to the series

 drivers/net/wireless/ath/wcn36xx/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c 
b/drivers/net/wireless/ath/wcn36xx/main.c
index c0ba7b0775b3..680217506b3d 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -779,9 +779,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw 
*hw,
wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
link_state);
} else {
+   wcn36xx_smd_delete_bss(wcn, vif);
wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
WCN36XX_HAL_LINK_IDLE_STATE);
-   wcn36xx_smd_delete_bss(wcn, vif);
}
}
 out:
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 15/18] wcn36xx: Use correct command struct for EXIT_BMPS_REQ

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

EXIT_BMPS_REQ was using the command struct for ENTER_BMPS_REQ. I
spotted this when looking at command dumps.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index b1bdc229e560..c15501c06eb2 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1690,7 +1690,7 @@ out:
 
 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
 {
-   struct wcn36xx_hal_enter_bmps_req_msg msg_body;
+   struct wcn36xx_hal_exit_bmps_req_msg msg_body;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
int ret = 0;
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 02/18] wcn36xx: Pad TIM PVM if needed

2016-04-18 Thread Bjorn Andersson
From: Pontus Fuchs <pontus.fu...@gmail.com>

The wcn36xx FW expects a fixed size TIM PVM in the beacon template. If
supplied with a shorter than expected PVM it will overwrite the IE
following the TIM.

Squashed with fix from Jason Mobarak <j...@cozybit.com>:
Patch "wcn36xx: Pad TIM PVM if needed" has caused a regression in mesh
beaconing.  The field tim_off is always 0 for mesh mode, and thus
pvm_len (referring to the TIM length field) and pad are both incorrectly
calculated.  Thus, msg_body.beacon_length is incorrectly calculated for
mesh mode. Fix this.

Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
Signed-off-by: Jason Mobarak <j...@cozybit.com>
[bjorn: squashed in Jason's fixup]
Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
---

Changes since v1:
- Merged in Jason's patch for skipping the padding in mesh mode.

 drivers/net/wireless/ath/wcn36xx/hal.h |  3 +++
 drivers/net/wireless/ath/wcn36xx/smd.c | 27 +--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
b/drivers/net/wireless/ath/wcn36xx/hal.h
index d713204f755d..3af16cba3d12 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -54,6 +54,9 @@
 /* Default Beacon template size */
 #define BEACON_TEMPLATE_SIZE 0x180
 
+/* Minimum PVM size that the FW expects. See comment in smd.c for details. */
+#define TIM_MIN_PVM_SIZE 6
+
 /* Param Change Bitmap sent to HAL */
 #define PARAM_BCN_INTERVAL_CHANGED  (1 << 0)
 #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1)
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
b/drivers/net/wireless/ath/wcn36xx/smd.c
index ff3ed2461a69..089a7e445cd6 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -1375,12 +1375,19 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct 
ieee80211_vif *vif,
u16 p2p_off)
 {
struct wcn36xx_hal_send_beacon_req_msg msg_body;
-   int ret = 0;
+   int ret = 0, pad, pvm_len;
 
mutex_lock(>hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
 
-   msg_body.beacon_length = skb_beacon->len;
+   pvm_len = skb_beacon->data[tim_off + 1] - 3;
+   pad = TIM_MIN_PVM_SIZE - pvm_len;
+
+   /* Padding is irrelevant to mesh mode since tim_off is always 0. */
+   if (vif->type == NL80211_IFTYPE_MESH_POINT)
+   pad = 0;
+
+   msg_body.beacon_length = skb_beacon->len + pad;
/* TODO need to find out why + 6 is needed */
msg_body.beacon_length6 = msg_body.beacon_length + 6;
 
@@ -1393,6 +1400,22 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct 
ieee80211_vif *vif,
memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
 
+   if (pad > 0) {
+   /*
+* The wcn36xx FW has a fixed size for the PVM in the TIM. If
+* given the beacon template from mac80211 with a PVM shorter
+* than the FW expectes it will overwrite the data after the
+* TIM.
+*/
+   wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
+   pad, pvm_len);
+   memmove(_body.beacon[tim_off + 5 + pvm_len + pad],
+   _body.beacon[tim_off + 5 + pvm_len],
+   skb_beacon->len - (tim_off + 5 + pvm_len));
+   memset(_body.beacon[tim_off + 5 + pvm_len], 0, pad);
+   msg_body.beacon[tim_off + 1] += pad;
+   }
+
/* TODO need to find out why this is needed? */
if (vif->type == NL80211_IFTYPE_MESH_POINT)
/* mesh beacon don't need this, so push further down */
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 01/15] wcn36xx: Clean up wcn36xx_smd_send_beacon

2016-04-13 Thread Bjorn Andersson
On Sun 03 Apr 15:16 PDT 2016, Bjorn Andersson wrote:

> From: Pontus Fuchs <pontus.fu...@gmail.com>
> 
> Needed for coming improvements. No functional changes.
> 

Kalle, Eugene,

Have you picked up these patches yet?

As I was debugging a firmware crash when trying to start hostap on the
DragonBoard410c I found an issue with this patch, would like to know if
I should send an incremental patch or resend this one.

> Signed-off-by: Pontus Fuchs <pontus.fu...@gmail.com>
> Signed-off-by: Bjorn Andersson <bjorn.anders...@linaro.org>
> ---
>  drivers/net/wireless/ath/wcn36xx/hal.h |  7 +--
>  drivers/net/wireless/ath/wcn36xx/smd.c | 12 +---
>  2 files changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h 
> b/drivers/net/wireless/ath/wcn36xx/hal.h
> index b947de0fb2e5..4fd77ccc2287 100644
> --- a/drivers/net/wireless/ath/wcn36xx/hal.h
> +++ b/drivers/net/wireless/ath/wcn36xx/hal.h
> @@ -51,8 +51,8 @@
>  #define WALN_HAL_STA_INVALID_IDX 0xFF
>  #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF
>  
> -/* Default Beacon template size */
> -#define BEACON_TEMPLATE_SIZE 0x180
> +/* Default Beacon template size. */
> +#define BEACON_TEMPLATE_SIZE 0x17C

This affects the wcn36xx_hal_send_probe_resp_req_msg as well, making the
firmware on DB410c crash upon receiving the UPDATE_PROBE_RSP_TEMPLATE_REQ.

I think we should keep it at 0x180 and subtract sizeof(u32) from the
template size in send_beacon_req_msg, because the second length is
really part of the buffer.

>  
>  /* Param Change Bitmap sent to HAL */
>  #define PARAM_BCN_INTERVAL_CHANGED  (1 << 0)
> @@ -2884,6 +2884,9 @@ struct update_beacon_rsp_msg {
>  struct wcn36xx_hal_send_beacon_req_msg {
>   struct wcn36xx_hal_msg_header header;
>  
> + /* length of the template + 6. Only qcom knows why */
> + u32 beacon_length6;
> +
>   /* length of the template. */
>   u32 beacon_length;
>  
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c 
> b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 74f56a81ad9a..ff3ed2461a69 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -1380,19 +1380,17 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, 
> struct ieee80211_vif *vif,
>   mutex_lock(>hal_mutex);
>   INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
>  
> - /* TODO need to find out why this is needed? */
> - msg_body.beacon_length = skb_beacon->len + 6;
> + msg_body.beacon_length = skb_beacon->len;
> + /* TODO need to find out why + 6 is needed */
> + msg_body.beacon_length6 = msg_body.beacon_length + 6;

As far as I can tell from the prima code and SMD dumps this should be 4,
as in sizeof(u32). This looks like a mishap in the layering of prima.

>  
> - if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
> - memcpy(_body.beacon, _beacon->len, sizeof(u32));
> - memcpy(&(msg_body.beacon[4]), skb_beacon->data,
> -skb_beacon->len);
> - } else {
> + if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
>   wcn36xx_err("Beacon is to big: beacon size=%d\n",
> msg_body.beacon_length);
>   ret = -ENOMEM;
>   goto out;
>   }
> + memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
>   memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
>  
>   /* TODO need to find out why this is needed? */

PS. I confirmed that the update_beacon_rsp_msg does not come with the
prepended length...for some reason.

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >