linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] WCN36xx convert to mainline SMD interface
@ 2015-12-28  1:34 Bjorn Andersson
  2015-12-28  1:34 ` [PATCH 1/4] wcn36xx: Fold indication payload into message header Bjorn Andersson
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-28  1:34 UTC (permalink / raw)
  To: Eugene Krasnikov, Kalle Valo
  Cc: Ian Campbell, Mark Rutland, Pawel Moll, Rob Herring, devicetree,
	fengwei.yin, linux-arm-msm, linux-kernel, linux-wireless, netdev,
	wcn36xx

The mainline kernel now has the necessary implementations for SMD, SMSM and
WCNSS_CTRL. This series provides the changes necessary for the wcn36xx driver
to utilize this infrastructure and make this driver work in mainline.


A driver for loading the WCNSS firmware, through remoteproc, has been posted
here [1]. Upon starting this the necessary SMD channels will be registered,
which triggers the probe of the wcn36xx driver.

With this, the only missing piece for having fully working Qualcomm WiFi in
mainline is the RPM clock-controller, needed by the remoteproc driver for doing
XO calibration during boot of the WCNSS core. This is being worked on
separately.

[1] https://lkml.org/lkml/2015/12/27/185

Bjorn Andersson (4):
  wcn36xx: Fold indication payload into message header
  wcn36xx: Change indication list lock to spinlock
  wcn36xx: Transition driver to SMD client
  dt: binding: Add Qualcomm wcn36xx WiFi binding

 .../bindings/net/wireless/qcom,wcn36xx-wifi.txt    |  76 ++++++++++++++
 drivers/net/wireless/ath/wcn36xx/Kconfig           |   2 +-
 drivers/net/wireless/ath/wcn36xx/dxe.c             |  16 +--
 drivers/net/wireless/ath/wcn36xx/main.c            | 111 ++++++++++++---------
 drivers/net/wireless/ath/wcn36xx/smd.c             |  51 +++++-----
 drivers/net/wireless/ath/wcn36xx/smd.h             |   6 +-
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h         |  23 ++---
 7 files changed, 188 insertions(+), 97 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt

-- 
2.5.0

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/4] wcn36xx: Fold indication payload into message header
  2015-12-28  1:34 [PATCH 0/4] WCN36xx convert to mainline SMD interface Bjorn Andersson
@ 2015-12-28  1:34 ` Bjorn Andersson
  2015-12-28  1:34 ` [PATCH 2/4] wcn36xx: Change indication list lock to spinlock Bjorn Andersson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-28  1:34 UTC (permalink / raw)
  To: Eugene Krasnikov, Kalle Valo
  Cc: fengwei.yin, linux-arm-msm, linux-kernel, linux-wireless, netdev,
	wcn36xx

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

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 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 74f56a81ad9a..6b5dbe6f0d0a 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2151,14 +2151,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.
@@ -2167,6 +2161,10 @@ nomem:
 				    msg_header->msg_type);
 			break;
 		}
+
+		msg_ind->msg_len = len;
+		memcpy(msg_ind->msg, buf, len);
+
 		mutex_lock(&wcn->hal_ind_mutex);
 		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
 		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
@@ -2217,7 +2215,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(&wcn->hal_ind_mutex);
 }
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 8361f9e3995b..21cc4ac7b5ca 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -55,8 +55,8 @@ struct wcn36xx_fw_msg_status_rsp_v2 {
 
 struct wcn36xx_hal_ind_msg {
 	struct list_head list;
-	u8 *msg;
 	size_t msg_len;
+	u8 msg[];
 };
 
 struct wcn36xx;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/4] wcn36xx: Change indication list lock to spinlock
  2015-12-28  1:34 [PATCH 0/4] WCN36xx convert to mainline SMD interface Bjorn Andersson
  2015-12-28  1:34 ` [PATCH 1/4] wcn36xx: Fold indication payload into message header Bjorn Andersson
@ 2015-12-28  1:34 ` Bjorn Andersson
  2015-12-28 23:06   ` Stephen Hemminger
       [not found] ` <1451266467-15377-1-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
  2015-12-28  1:34 ` [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding Bjorn Andersson
  3 siblings, 1 reply; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-28  1:34 UTC (permalink / raw)
  To: Eugene Krasnikov, Kalle Valo
  Cc: fengwei.yin, linux-arm-msm, linux-kernel, linux-wireless, netdev,
	wcn36xx

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

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 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 6b5dbe6f0d0a..4307429740a9 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2165,10 +2165,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(&wcn->hal_ind_mutex);
+		spin_lock(&wcn->hal_ind_lock);
 		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
 		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-		mutex_unlock(&wcn->hal_ind_mutex);
+		spin_unlock(&wcn->hal_ind_lock);
 		wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
 		break;
 	default:
@@ -2182,8 +2182,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(&wcn->hal_ind_mutex);
+	spin_lock_irqsave(&wcn->hal_ind_lock, flags);
 
 	hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
 				       struct wcn36xx_hal_ind_msg,
@@ -2215,8 +2216,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(&wcn->hal_ind_lock, flags);
 	kfree(hal_ind_msg);
-	mutex_unlock(&wcn->hal_ind_mutex);
 }
 int wcn36xx_smd_open(struct wcn36xx *wcn)
 {
@@ -2229,7 +2230,7 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
 	}
 	INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
 	INIT_LIST_HEAD(&wcn->hal_ind_queue);
-	mutex_init(&wcn->hal_ind_mutex);
+	spin_lock_init(&wcn->hal_ind_lock);
 
 	ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
 	if (ret) {
@@ -2249,5 +2250,4 @@ void wcn36xx_smd_close(struct wcn36xx *wcn)
 {
 	wcn->ctrl_ops->close();
 	destroy_workqueue(wcn->hal_ind_wq);
-	mutex_destroy(&wcn->hal_ind_mutex);
 }
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 7b41e833e18c..7997cc1312ee 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 mutex		hal_ind_mutex;
+	spinlock_t		hal_ind_lock;
 	struct list_head	hal_ind_queue;
 
 	/* DXE channels */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/4] wcn36xx: Transition driver to SMD client
       [not found] ` <1451266467-15377-1-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
@ 2015-12-28  1:34   ` Bjorn Andersson
  2016-01-11  9:02     ` Eugene Krasnikov
  0 siblings, 1 reply; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-28  1:34 UTC (permalink / raw)
  To: Eugene Krasnikov, Kalle Valo
  Cc: Ian Campbell, Mark Rutland, Pawel Moll, Rob Herring,
	fengwei.yin-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	wcn36xx-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

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.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
---
 drivers/net/wireless/ath/wcn36xx/Kconfig   |   2 +-
 drivers/net/wireless/ath/wcn36xx/dxe.c     |  16 +++--
 drivers/net/wireless/ath/wcn36xx/main.c    | 111 +++++++++++++++++------------
 drivers/net/wireless/ath/wcn36xx/smd.c     |  26 ++++---
 drivers/net/wireless/ath/wcn36xx/smd.h     |   4 ++
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  21 ++----
 6 files changed, 99 insertions(+), 81 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 f8dfa05b290a..47f3937a7ab9 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 <linux/interrupt.h>
+#include <linux/soc/qcom/smem_state.h>
 #include "wcn36xx.h"
 #include "txrx.h"
 
@@ -150,9 +151,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;
 
@@ -676,9 +680,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 7c169abdbafe..8659e3f997d2 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -19,6 +19,9 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/soc/qcom/smd.h>
+#include <linux/soc/qcom/smem_state.h>
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -981,48 +984,63 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
 }
 
 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
-					  struct platform_device *pdev)
+					  struct device *dev)
 {
-	struct resource *res;
+	u32 mmio[2];
+	int ret;
+
 	/* Set TX IRQ */
-	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-					   "wcnss_wlantx_irq");
-	if (!res) {
+	wcn->tx_irq = irq_of_parse_and_map(dev->of_node, 0);
+	if (!wcn->tx_irq) {
 		wcn36xx_err("failed to get tx_irq\n");
 		return -ENOENT;
 	}
-	wcn->tx_irq = res->start;
 
 	/* Set RX IRQ */
-	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-					   "wcnss_wlanrx_irq");
-	if (!res) {
+	wcn->rx_irq = irq_of_parse_and_map(dev->of_node, 1);
+	if (!wcn->rx_irq) {
 		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",
+			&wcn->tx_enable_state_bit);
+	if (IS_ERR(wcn->tx_enable_state)) {
+		wcn36xx_err("failed to get tx-enable state\n");
+		return -ENOENT;
+	}
+
+	/* Acquire SMSM tx rings empty handle */
+	wcn->tx_rings_empty_state = qcom_smem_state_get(dev, "tx-rings-empty",
+			&wcn->tx_rings_empty_state_bit);
+	if (IS_ERR(wcn->tx_rings_empty_state)) {
+		wcn36xx_err("failed to get tx-rings-empty state\n");
+		return -ENOENT;
+	}
 
 	/* Map the memory */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						 "wcnss_mmio");
-	if (!res) {
-		wcn36xx_err("failed to get mmio\n");
+	ret = of_property_read_u32_array(dev->of_node, "qcom,wcnss-mmio", mmio, 2);
+	if (ret) {
+		wcn36xx_err("failed to get qcom,wcnss-mmio\n");
 		return -ENOENT;
 	}
-	wcn->mmio = ioremap(res->start, resource_size(res));
+
+	wcn->mmio = ioremap(mmio[0], mmio[1]);
 	if (!wcn->mmio) {
 		wcn36xx_err("failed to map io memory\n");
 		return -ENOMEM;
 	}
+
 	return 0;
 }
 
-static int wcn36xx_probe(struct platform_device *pdev)
+static int wcn36xx_probe(struct qcom_smd_device *sdev)
 {
 	struct ieee80211_hw *hw;
 	struct wcn36xx *wcn;
 	int ret;
-	u8 addr[ETH_ALEN];
+	const u8 *addr;
 
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
 
@@ -1032,20 +1050,27 @@ static int wcn36xx_probe(struct platform_device *pdev)
 		ret = -ENOMEM;
 		goto out_err;
 	}
-	platform_set_drvdata(pdev, hw);
+	dev_set_drvdata(&sdev->dev, hw);
 	wcn = hw->priv;
 	wcn->hw = hw;
-	wcn->dev = &pdev->dev;
-	wcn->ctrl_ops = pdev->dev.platform_data;
+	wcn->dev = &sdev->dev;
+	wcn->smd_channel = sdev->channel;
 
 	mutex_init(&wcn->hal_mutex);
 
-	if (!wcn->ctrl_ops->get_hw_mac(addr)) {
+	sdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	addr = of_get_property(sdev->dev.of_node, "local-mac-address", &ret);
+	if (addr && ret != ETH_ALEN) {
+		wcn36xx_err("invalid local-mac-address\n");
+		ret = -EINVAL;
+		goto out_err;
+	} else if (addr) {
 		wcn36xx_info("mac address: %pM\n", addr);
 		SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
 	}
 
-	ret = wcn36xx_platform_get_resources(wcn, pdev);
+	ret = wcn36xx_platform_get_resources(wcn, &sdev->dev);
 	if (ret)
 		goto out_wq;
 
@@ -1063,9 +1088,10 @@ out_wq:
 out_err:
 	return ret;
 }
-static int wcn36xx_remove(struct platform_device *pdev)
+
+static void wcn36xx_remove(struct qcom_smd_device *sdev)
 {
-	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+	struct ieee80211_hw *hw = dev_get_drvdata(&sdev->dev);
 	struct wcn36xx *wcn = hw->priv;
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
 
@@ -1073,41 +1099,34 @@ static int wcn36xx_remove(struct platform_device *pdev)
 	mutex_destroy(&wcn->hal_mutex);
 
 	ieee80211_unregister_hw(hw);
+
+	qcom_smem_state_put(wcn->tx_enable_state);
+	qcom_smem_state_put(wcn->tx_rings_empty_state);
+
 	iounmap(wcn->mmio);
 	ieee80211_free_hw(hw);
-
-	return 0;
 }
-static const struct platform_device_id wcn36xx_platform_id_table[] = {
-	{
-		.name = "wcn36xx",
-		.driver_data = 0
-	},
+
+static const struct of_device_id wcn36xx_of_match[] = {
+	{ .compatible = "qcom,wcn3620-wlan" },
+	{ .compatible = "qcom,wcn3660-wlan" },
+	{ .compatible = "qcom,wcn3680-wlan" },
 	{}
 };
-MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
+MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
 
-static struct platform_driver wcn36xx_driver = {
+static struct qcom_smd_driver wcn36xx_driver = {
 	.probe      = wcn36xx_probe,
 	.remove     = wcn36xx_remove,
+	.callback = wcn36xx_smd_rsp_process,
 	.driver         = {
 		.name   = "wcn36xx",
+		.of_match_table = wcn36xx_of_match,
+		.owner  = THIS_MODULE,
 	},
-	.id_table    = wcn36xx_platform_id_table,
 };
 
-static int __init wcn36xx_init(void)
-{
-	platform_driver_register(&wcn36xx_driver);
-	return 0;
-}
-module_init(wcn36xx_init);
-
-static void __exit wcn36xx_exit(void)
-{
-	platform_driver_unregister(&wcn36xx_driver);
-}
-module_exit(wcn36xx_exit);
+module_qcom_smd_driver(wcn36xx_driver);
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org");
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 4307429740a9..2bf42787a4af 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -19,6 +19,7 @@
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
 #include <linux/bitops.h>
+#include <linux/soc/qcom/smd.h>
 #include "smd.h"
 
 struct wcn36xx_cfg_val {
@@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
 
 	init_completion(&wcn->hal_rsp_compl);
 	start = jiffies;
-	ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
+	ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len);
 	if (ret) {
 		wcn36xx_err("HAL TX failed\n");
 		goto out;
@@ -2100,9 +2101,13 @@ out:
 	mutex_unlock(&wcn->hal_mutex);
 	return ret;
 }
-static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
+
+int wcn36xx_smd_rsp_process(struct qcom_smd_device *sdev,
+			    const void *buf, size_t len)
 {
-	struct wcn36xx_hal_msg_header *msg_header = buf;
+	const struct wcn36xx_hal_msg_header *msg_header = buf;
+	struct ieee80211_hw *hw = dev_get_drvdata(&sdev->dev);
+	struct wcn36xx *wcn = hw->priv;
 	struct wcn36xx_hal_ind_msg *msg_ind;
 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
 
@@ -2151,7 +2156,7 @@ 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) + len, GFP_KERNEL);
+		msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
 		if (!msg_ind) {
 			/*
 			 * FIXME: Do something smarter then just
@@ -2175,6 +2180,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
 		wcn36xx_err("SMD_EVENT (%d) not supported\n",
 			      msg_header->msg_type);
 	}
+
+	return 0;
 }
 static void wcn36xx_ind_smd_work(struct work_struct *work)
 {
@@ -2232,22 +2239,13 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
 	INIT_LIST_HEAD(&wcn->hal_ind_queue);
 	spin_lock_init(&wcn->hal_ind_lock);
 
-	ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
-	if (ret) {
-		wcn36xx_err("failed to open control channel\n");
-		goto free_wq;
-	}
-
-	return ret;
+	return 0;
 
-free_wq:
-	destroy_workqueue(wcn->hal_ind_wq);
 out:
 	return ret;
 }
 
 void wcn36xx_smd_close(struct wcn36xx *wcn)
 {
-	wcn->ctrl_ops->close();
 	destroy_workqueue(wcn->hal_ind_wq);
 }
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 21cc4ac7b5ca..4d96d56d266f 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -60,6 +60,7 @@ struct wcn36xx_hal_ind_msg {
 };
 
 struct wcn36xx;
+struct qcom_smd_device;
 
 int wcn36xx_smd_open(struct wcn36xx *wcn);
 void wcn36xx_smd_close(struct wcn36xx *wcn);
@@ -136,4 +137,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
 
 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
+
+int wcn36xx_smd_rsp_process(struct qcom_smd_device *sdev,
+			    const void *buf, size_t len);
 #endif	/* _SMD_H_ */
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 7997cc1312ee..4be81f66e167 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -103,19 +103,6 @@ struct nv_data {
 	u8	table;
 };
 
-/* Interface for platform control path
- *
- * @open: hook must be called when wcn36xx wants to open control channel.
- * @tx: sends a buffer.
- */
-struct wcn36xx_platform_ctrl_ops {
-	int (*open)(void *drv_priv, void *rsp_cb);
-	void (*close)(void);
-	int (*tx)(char *buf, size_t len);
-	int (*get_hw_mac)(u8 *addr);
-	int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
-};

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding
  2015-12-28  1:34 [PATCH 0/4] WCN36xx convert to mainline SMD interface Bjorn Andersson
                   ` (2 preceding siblings ...)
       [not found] ` <1451266467-15377-1-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
@ 2015-12-28  1:34 ` Bjorn Andersson
  2015-12-29 18:34   ` Rob Herring
       [not found]   ` <1451266467-15377-5-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
  3 siblings, 2 replies; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-28  1:34 UTC (permalink / raw)
  To: Eugene Krasnikov, Ian Campbell, Kalle Valo, Mark Rutland,
	Pawel Moll, Rob Herring
  Cc: devicetree, fengwei.yin, linux-arm-msm, linux-kernel,
	linux-wireless, netdev, wcn36xx

Add binding representing the Qualcomm wcn3620/60/80 WiFi block.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 .../bindings/net/wireless/qcom,wcn36xx-wifi.txt    | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt

diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
new file mode 100644
index 000000000000..7b314b9f30af
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
@@ -0,0 +1,76 @@
+Qualcomm WCN36xx WiFi Binding
+
+This binding describes the Qualcomm WCN36xx WiFi hardware. The hardware block
+is part of the Qualcomm WCNSS core, a WiFi/BT/FM combo chip, found in a variety
+of Qualcomm platforms.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be one of:
+		    "qcom,wcn3620-wlan",
+		    "qcom,wcn3660-wlan",
+		    "qcom,wcn3680-wlan"
+
+- qcom,smd-channel:
+	Usage: required
+	Value type: <string>
+	Definition: standard SMD property specifying the SMD channel used for
+		    communication with the WiFi firmware
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the two IRQs for tx and rx respectively
+
+- qcom,wcnss-mmio:
+	Usage: required
+	Value type: <prop-encoed-array>
+	Definition: should specify base address and size of the WiFi related
+		    registers of WCNSS
+
+- qcom,state:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the tx-enable and tx-ring-empty state
+		    references
+
+- qcom,state-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: name of the states, must be "tx-enable", "tx-rings-empty";
+
+- local-mac-address:
+	Usage: optional
+	Value type: <prop-encoded-array> encoded as array of hex numbers
+	Definition: specifies MAC address that was assigned to the network
+		    device described by the node containing this property.
+
+= EXAMPLE
+The following example represents a SMD node, with one edge representing the
+"pronto" subsystem, with the wcn3680 WiFi device described; as found on the
+8974 platform.
+
+smd {
+	compatible = "qcom,smd";
+
+	pronto {
+		interrupts = <0 142 1>;
+
+		qcom,ipc = <&apcs 8 17>;
+		qcom,smd-edge = <6>;
+
+		wifi {
+			compatible = "qcom,wcn3680-wlan";
+			qcom,smd-channels = "WLAN_CTRL";
+
+			interrupts = <0 145 0>, <0 146 0>;
+			interrupt-names = "tx", "rx";
+
+			qcom,wcnss-mmio = <0xfb000000 0x21b000>;
+
+			qcom,state = <&apps_smsm 10>, <&apps_smsm 9>;
+			qcom,state-names = "tx-enable", "tx-rings-empty";
+		};
+	};
+};
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/4] wcn36xx: Change indication list lock to spinlock
  2015-12-28  1:34 ` [PATCH 2/4] wcn36xx: Change indication list lock to spinlock Bjorn Andersson
@ 2015-12-28 23:06   ` Stephen Hemminger
  2015-12-29  4:25     ` Bjorn Andersson
  0 siblings, 1 reply; 14+ messages in thread
From: Stephen Hemminger @ 2015-12-28 23:06 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Eugene Krasnikov, Kalle Valo, fengwei.yin, linux-arm-msm,
	linux-kernel, linux-wireless, netdev, wcn36xx

On Sun, 27 Dec 2015 17:34:25 -0800
Bjorn Andersson <bjorn@kryo.se> wrote:

> In preparation for handling incoming messages from IRQ context, change
> the indication list lock to a spinlock
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
>  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 6b5dbe6f0d0a..4307429740a9 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -2165,10 +2165,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(&wcn->hal_ind_mutex);
> +		spin_lock(&wcn->hal_ind_lock);

If you are going to handle messages in IRQ context, that better be a spin_lock_irq() or spin_lock_bh().

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/4] wcn36xx: Change indication list lock to spinlock
  2015-12-28 23:06   ` Stephen Hemminger
@ 2015-12-29  4:25     ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-29  4:25 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Eugene Krasnikov, Kalle Valo, fengwei.yin, linux-arm-msm,
	linux-kernel, linux-wireless, netdev, wcn36xx

On Mon 28 Dec 15:06 PST 2015, Stephen Hemminger wrote:

> On Sun, 27 Dec 2015 17:34:25 -0800
> Bjorn Andersson <bjorn@kryo.se> wrote:
> 
> > In preparation for handling incoming messages from IRQ context, change
> > the indication list lock to a spinlock
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> > ---
> >  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 6b5dbe6f0d0a..4307429740a9 100644
> > --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> > +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> > @@ -2165,10 +2165,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(&wcn->hal_ind_mutex);
> > +		spin_lock(&wcn->hal_ind_lock);
> 
> If you are going to handle messages in IRQ context, that better be a
> spin_lock_irq() or spin_lock_bh().

This function is executed in IRQ context after the next patch, as such I
use spin_lock() here and spin_lock_irqsave() in the worker thread
(wcn36xx_ind_smd_work()).

Is this not how the spin_lock API should be used?

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding
  2015-12-28  1:34 ` [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding Bjorn Andersson
@ 2015-12-29 18:34   ` Rob Herring
  2015-12-29 19:03     ` Bjorn Andersson
       [not found]   ` <1451266467-15377-5-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
  1 sibling, 1 reply; 14+ messages in thread
From: Rob Herring @ 2015-12-29 18:34 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Eugene Krasnikov, Ian Campbell, Kalle Valo, Mark Rutland,
	Pawel Moll, devicetree, fengwei.yin, linux-arm-msm, linux-kernel,
	linux-wireless, netdev, wcn36xx

On Sun, Dec 27, 2015 at 05:34:27PM -0800, Bjorn Andersson wrote:
> Add binding representing the Qualcomm wcn3620/60/80 WiFi block.
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
>  .../bindings/net/wireless/qcom,wcn36xx-wifi.txt    | 76 ++++++++++++++++++++++
>  1 file changed, 76 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> new file mode 100644
> index 000000000000..7b314b9f30af
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> @@ -0,0 +1,76 @@
> +Qualcomm WCN36xx WiFi Binding
> +
> +This binding describes the Qualcomm WCN36xx WiFi hardware. The hardware block
> +is part of the Qualcomm WCNSS core, a WiFi/BT/FM combo chip, found in a variety
> +of Qualcomm platforms.

Are BT/FM functions completely separate? If so, separate bindings are 
okay. If not, then we need to describe the full chip.

Rob

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding
  2015-12-29 18:34   ` Rob Herring
@ 2015-12-29 19:03     ` Bjorn Andersson
  2015-12-29 23:27       ` Rob Herring
  2016-01-25 17:50       ` Bjorn Andersson
  0 siblings, 2 replies; 14+ messages in thread
From: Bjorn Andersson @ 2015-12-29 19:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: Eugene Krasnikov, Ian Campbell, Kalle Valo, Mark Rutland,
	Pawel Moll, devicetree, fengwei.yin, linux-arm-msm, linux-kernel,
	linux-wireless, netdev, wcn36xx

On Tue 29 Dec 10:34 PST 2015, Rob Herring wrote:

> On Sun, Dec 27, 2015 at 05:34:27PM -0800, Bjorn Andersson wrote:
> > Add binding representing the Qualcomm wcn3620/60/80 WiFi block.
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> > ---
> >  .../bindings/net/wireless/qcom,wcn36xx-wifi.txt    | 76 ++++++++++++++++++++++
> >  1 file changed, 76 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> > new file mode 100644
> > index 000000000000..7b314b9f30af
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> > @@ -0,0 +1,76 @@
> > +Qualcomm WCN36xx WiFi Binding
> > +
> > +This binding describes the Qualcomm WCN36xx WiFi hardware. The hardware block
> > +is part of the Qualcomm WCNSS core, a WiFi/BT/FM combo chip, found in a variety
> > +of Qualcomm platforms.
> 
> Are BT/FM functions completely separate? If so, separate bindings are 
> okay. If not, then we need to describe the full chip.
> 

It's three different hardware blocks (WiFi, BT and FM-radio) with shared
RF-hardware and an ARM core for control logic.

There seems to be some control commands going towards the BT part that
controls coexistence properties of the RF-hardware, but other than that
I see it as logically separate blocks.


So I think it's fine to model this as separate pieces in DT.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding
       [not found]   ` <1451266467-15377-5-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
@ 2015-12-29 19:11     ` Andy Gross
  0 siblings, 0 replies; 14+ messages in thread
From: Andy Gross @ 2015-12-29 19:11 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Eugene Krasnikov, Ian Campbell, Kalle Valo, Mark Rutland,
	Pawel Moll, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
	fengwei.yin-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	wcn36xx-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Sun, Dec 27, 2015 at 05:34:27PM -0800, Bjorn Andersson wrote:
> Add binding representing the Qualcomm wcn3620/60/80 WiFi block.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
> ---

<snip>

> +
> +- qcom,wcnss-mmio:
> +	Usage: required
> +	Value type: <prop-encoed-array>

nit:  encoded

> +	Definition: should specify base address and size of the WiFi related
> +		    registers of WCNSS
> +
> +- qcom,state:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: should specify the tx-enable and tx-ring-empty state
> +		    references
> +

<snip>

Otherwise looks good.

Reviewed-by: Andy Gross <andy.gross-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding
  2015-12-29 19:03     ` Bjorn Andersson
@ 2015-12-29 23:27       ` Rob Herring
  2016-01-25 17:50       ` Bjorn Andersson
  1 sibling, 0 replies; 14+ messages in thread
From: Rob Herring @ 2015-12-29 23:27 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Eugene Krasnikov, Ian Campbell, Kalle Valo, Mark Rutland,
	Pawel Moll, devicetree, fengwei.yin, linux-arm-msm, linux-kernel,
	linux-wireless, netdev, wcn36xx

On Tue, Dec 29, 2015 at 11:03:57AM -0800, Bjorn Andersson wrote:
> On Tue 29 Dec 10:34 PST 2015, Rob Herring wrote:
> 
> > On Sun, Dec 27, 2015 at 05:34:27PM -0800, Bjorn Andersson wrote:
> > > Add binding representing the Qualcomm wcn3620/60/80 WiFi block.
> > > Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> > > ---
> > >  .../bindings/net/wireless/qcom,wcn36xx-wifi.txt    | 76 ++++++++++++++++++++++
> > >  1 file changed, 76 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> > > 
> > > diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> > > new file mode 100644
> > > index 000000000000..7b314b9f30af
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
> > > @@ -0,0 +1,76 @@
> > > +Qualcomm WCN36xx WiFi Binding
> > > +
> > > +This binding describes the Qualcomm WCN36xx WiFi hardware. The hardware block
> > > +is part of the Qualcomm WCNSS core, a WiFi/BT/FM combo chip, found in a variety
> > > +of Qualcomm platforms.
> > 
> > Are BT/FM functions completely separate? If so, separate bindings are 
> > okay. If not, then we need to describe the full chip.
> > 
> 
> It's three different hardware blocks (WiFi, BT and FM-radio) with shared
> RF-hardware and an ARM core for control logic.
> 
> There seems to be some control commands going towards the BT part that
> controls coexistence properties of the RF-hardware, but other than that
> I see it as logically separate blocks.
> 
> 
> So I think it's fine to model this as separate pieces in DT.

Okay.

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/4] wcn36xx: Transition driver to SMD client
  2015-12-28  1:34   ` [PATCH 3/4] wcn36xx: Transition driver to SMD client Bjorn Andersson
@ 2016-01-11  9:02     ` Eugene Krasnikov
       [not found]       ` <CAFSJ42a2mD1gSaarKEny4xp9g_PbcLuv3PLsRnHp+qviv6f6mg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Eugene Krasnikov @ 2016-01-11  9:02 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Kalle Valo, Ian Campbell, Mark Rutland, Pawel Moll, Rob Herring,
	yfw, linux-arm-msm, linux-kernel, linux-wireless, netdev,
	wcn36xx

Better late than never! Looks good to me.

2015-12-28 1:34 GMT+00:00 Bjorn Andersson <bjorn@kryo.se>:
> 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.andersson@sonymobile.com>
> ---
>  drivers/net/wireless/ath/wcn36xx/Kconfig   |   2 +-
>  drivers/net/wireless/ath/wcn36xx/dxe.c     |  16 +++--
>  drivers/net/wireless/ath/wcn36xx/main.c    | 111 +++++++++++++++++------------
>  drivers/net/wireless/ath/wcn36xx/smd.c     |  26 ++++---
>  drivers/net/wireless/ath/wcn36xx/smd.h     |   4 ++
>  drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  21 ++----
>  6 files changed, 99 insertions(+), 81 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 f8dfa05b290a..47f3937a7ab9 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 <linux/interrupt.h>
> +#include <linux/soc/qcom/smem_state.h>
>  #include "wcn36xx.h"
>  #include "txrx.h"
>
> @@ -150,9 +151,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;
>
> @@ -676,9 +680,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 7c169abdbafe..8659e3f997d2 100644
> --- a/drivers/net/wireless/ath/wcn36xx/main.c
> +++ b/drivers/net/wireless/ath/wcn36xx/main.c
> @@ -19,6 +19,9 @@
>  #include <linux/module.h>
>  #include <linux/firmware.h>
>  #include <linux/platform_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/soc/qcom/smd.h>
> +#include <linux/soc/qcom/smem_state.h>
>  #include "wcn36xx.h"
>
>  unsigned int wcn36xx_dbg_mask;
> @@ -981,48 +984,63 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
>  }
>
>  static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
> -                                         struct platform_device *pdev)
> +                                         struct device *dev)
>  {
> -       struct resource *res;
> +       u32 mmio[2];
> +       int ret;
> +
>         /* Set TX IRQ */
> -       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
> -                                          "wcnss_wlantx_irq");
> -       if (!res) {
> +       wcn->tx_irq = irq_of_parse_and_map(dev->of_node, 0);
> +       if (!wcn->tx_irq) {
>                 wcn36xx_err("failed to get tx_irq\n");
>                 return -ENOENT;
>         }
> -       wcn->tx_irq = res->start;
>
>         /* Set RX IRQ */
> -       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
> -                                          "wcnss_wlanrx_irq");
> -       if (!res) {
> +       wcn->rx_irq = irq_of_parse_and_map(dev->of_node, 1);
> +       if (!wcn->rx_irq) {
>                 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",
> +                       &wcn->tx_enable_state_bit);
> +       if (IS_ERR(wcn->tx_enable_state)) {
> +               wcn36xx_err("failed to get tx-enable state\n");
> +               return -ENOENT;
> +       }
> +
> +       /* Acquire SMSM tx rings empty handle */
> +       wcn->tx_rings_empty_state = qcom_smem_state_get(dev, "tx-rings-empty",
> +                       &wcn->tx_rings_empty_state_bit);
> +       if (IS_ERR(wcn->tx_rings_empty_state)) {
> +               wcn36xx_err("failed to get tx-rings-empty state\n");
> +               return -ENOENT;
> +       }
>
>         /* Map the memory */
> -       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> -                                                "wcnss_mmio");
> -       if (!res) {
> -               wcn36xx_err("failed to get mmio\n");
> +       ret = of_property_read_u32_array(dev->of_node, "qcom,wcnss-mmio", mmio, 2);
> +       if (ret) {
> +               wcn36xx_err("failed to get qcom,wcnss-mmio\n");
>                 return -ENOENT;
>         }
> -       wcn->mmio = ioremap(res->start, resource_size(res));
> +
> +       wcn->mmio = ioremap(mmio[0], mmio[1]);
>         if (!wcn->mmio) {
>                 wcn36xx_err("failed to map io memory\n");
>                 return -ENOMEM;
>         }
> +
>         return 0;
>  }
>
> -static int wcn36xx_probe(struct platform_device *pdev)
> +static int wcn36xx_probe(struct qcom_smd_device *sdev)
>  {
>         struct ieee80211_hw *hw;
>         struct wcn36xx *wcn;
>         int ret;
> -       u8 addr[ETH_ALEN];
> +       const u8 *addr;
>
>         wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
>
> @@ -1032,20 +1050,27 @@ static int wcn36xx_probe(struct platform_device *pdev)
>                 ret = -ENOMEM;
>                 goto out_err;
>         }
> -       platform_set_drvdata(pdev, hw);
> +       dev_set_drvdata(&sdev->dev, hw);
>         wcn = hw->priv;
>         wcn->hw = hw;
> -       wcn->dev = &pdev->dev;
> -       wcn->ctrl_ops = pdev->dev.platform_data;
> +       wcn->dev = &sdev->dev;
> +       wcn->smd_channel = sdev->channel;
>
>         mutex_init(&wcn->hal_mutex);
>
> -       if (!wcn->ctrl_ops->get_hw_mac(addr)) {
> +       sdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> +
> +       addr = of_get_property(sdev->dev.of_node, "local-mac-address", &ret);
> +       if (addr && ret != ETH_ALEN) {
> +               wcn36xx_err("invalid local-mac-address\n");
> +               ret = -EINVAL;
> +               goto out_err;
> +       } else if (addr) {
>                 wcn36xx_info("mac address: %pM\n", addr);
>                 SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
>         }
>
> -       ret = wcn36xx_platform_get_resources(wcn, pdev);
> +       ret = wcn36xx_platform_get_resources(wcn, &sdev->dev);
>         if (ret)
>                 goto out_wq;
>
> @@ -1063,9 +1088,10 @@ out_wq:
>  out_err:
>         return ret;
>  }
> -static int wcn36xx_remove(struct platform_device *pdev)
> +
> +static void wcn36xx_remove(struct qcom_smd_device *sdev)
>  {
> -       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
> +       struct ieee80211_hw *hw = dev_get_drvdata(&sdev->dev);
>         struct wcn36xx *wcn = hw->priv;
>         wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
>
> @@ -1073,41 +1099,34 @@ static int wcn36xx_remove(struct platform_device *pdev)
>         mutex_destroy(&wcn->hal_mutex);
>
>         ieee80211_unregister_hw(hw);
> +
> +       qcom_smem_state_put(wcn->tx_enable_state);
> +       qcom_smem_state_put(wcn->tx_rings_empty_state);
> +
>         iounmap(wcn->mmio);
>         ieee80211_free_hw(hw);
> -
> -       return 0;
>  }
> -static const struct platform_device_id wcn36xx_platform_id_table[] = {
> -       {
> -               .name = "wcn36xx",
> -               .driver_data = 0
> -       },
> +
> +static const struct of_device_id wcn36xx_of_match[] = {
> +       { .compatible = "qcom,wcn3620-wlan" },
> +       { .compatible = "qcom,wcn3660-wlan" },
> +       { .compatible = "qcom,wcn3680-wlan" },
>         {}
>  };
> -MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
> +MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
>
> -static struct platform_driver wcn36xx_driver = {
> +static struct qcom_smd_driver wcn36xx_driver = {
>         .probe      = wcn36xx_probe,
>         .remove     = wcn36xx_remove,
> +       .callback = wcn36xx_smd_rsp_process,
>         .driver         = {
>                 .name   = "wcn36xx",
> +               .of_match_table = wcn36xx_of_match,
> +               .owner  = THIS_MODULE,
>         },
> -       .id_table    = wcn36xx_platform_id_table,
>  };
>
> -static int __init wcn36xx_init(void)
> -{
> -       platform_driver_register(&wcn36xx_driver);
> -       return 0;
> -}
> -module_init(wcn36xx_init);
> -
> -static void __exit wcn36xx_exit(void)
> -{
> -       platform_driver_unregister(&wcn36xx_driver);
> -}
> -module_exit(wcn36xx_exit);
> +module_qcom_smd_driver(wcn36xx_driver);
>
>  MODULE_LICENSE("Dual BSD/GPL");
>  MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
> index 4307429740a9..2bf42787a4af 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> @@ -19,6 +19,7 @@
>  #include <linux/etherdevice.h>
>  #include <linux/firmware.h>
>  #include <linux/bitops.h>
> +#include <linux/soc/qcom/smd.h>
>  #include "smd.h"
>
>  struct wcn36xx_cfg_val {
> @@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
>
>         init_completion(&wcn->hal_rsp_compl);
>         start = jiffies;
> -       ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
> +       ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len);
>         if (ret) {
>                 wcn36xx_err("HAL TX failed\n");
>                 goto out;
> @@ -2100,9 +2101,13 @@ out:
>         mutex_unlock(&wcn->hal_mutex);
>         return ret;
>  }
> -static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
> +
> +int wcn36xx_smd_rsp_process(struct qcom_smd_device *sdev,
> +                           const void *buf, size_t len)
>  {
> -       struct wcn36xx_hal_msg_header *msg_header = buf;
> +       const struct wcn36xx_hal_msg_header *msg_header = buf;
> +       struct ieee80211_hw *hw = dev_get_drvdata(&sdev->dev);
> +       struct wcn36xx *wcn = hw->priv;
>         struct wcn36xx_hal_ind_msg *msg_ind;
>         wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
>
> @@ -2151,7 +2156,7 @@ 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) + len, GFP_KERNEL);
> +               msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
>                 if (!msg_ind) {
>                         /*
>                          * FIXME: Do something smarter then just
> @@ -2175,6 +2180,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
>                 wcn36xx_err("SMD_EVENT (%d) not supported\n",
>                               msg_header->msg_type);
>         }
> +
> +       return 0;
>  }
>  static void wcn36xx_ind_smd_work(struct work_struct *work)
>  {
> @@ -2232,22 +2239,13 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
>         INIT_LIST_HEAD(&wcn->hal_ind_queue);
>         spin_lock_init(&wcn->hal_ind_lock);
>
> -       ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
> -       if (ret) {
> -               wcn36xx_err("failed to open control channel\n");
> -               goto free_wq;
> -       }
> -
> -       return ret;
> +       return 0;
>
> -free_wq:
> -       destroy_workqueue(wcn->hal_ind_wq);
>  out:
>         return ret;
>  }
>
>  void wcn36xx_smd_close(struct wcn36xx *wcn)
>  {
> -       wcn->ctrl_ops->close();
>         destroy_workqueue(wcn->hal_ind_wq);
>  }
> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
> index 21cc4ac7b5ca..4d96d56d266f 100644
> --- a/drivers/net/wireless/ath/wcn36xx/smd.h
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.h
> @@ -60,6 +60,7 @@ struct wcn36xx_hal_ind_msg {
>  };
>
>  struct wcn36xx;
> +struct qcom_smd_device;
>
>  int wcn36xx_smd_open(struct wcn36xx *wcn);
>  void wcn36xx_smd_close(struct wcn36xx *wcn);
> @@ -136,4 +137,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
>  int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
>
>  int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
> +
> +int wcn36xx_smd_rsp_process(struct qcom_smd_device *sdev,
> +                           const void *buf, size_t len);
>  #endif /* _SMD_H_ */
> diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> index 7997cc1312ee..4be81f66e167 100644
> --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> @@ -103,19 +103,6 @@ struct nv_data {
>         u8      table;
>  };
>
> -/* Interface for platform control path
> - *
> - * @open: hook must be called when wcn36xx wants to open control channel.
> - * @tx: sends a buffer.
> - */
> -struct wcn36xx_platform_ctrl_ops {
> -       int (*open)(void *drv_priv, void *rsp_cb);
> -       void (*close)(void);
> -       int (*tx)(char *buf, size_t len);
> -       int (*get_hw_mac)(u8 *addr);
> -       int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
> -};
> -
>  /**
>   * struct wcn36xx_vif - holds VIF related fields
>   *
> @@ -204,7 +191,13 @@ struct wcn36xx {
>         int                     rx_irq;
>         void __iomem            *mmio;
>
> -       struct wcn36xx_platform_ctrl_ops *ctrl_ops;
> +       struct qcom_smd_channel *smd_channel;
> +
> +       struct qcom_smem_state  *tx_enable_state;
> +       unsigned                tx_enable_state_bit;
> +       struct qcom_smem_state  *tx_rings_empty_state;
> +       unsigned                tx_rings_empty_state_bit;
> +
>         /*
>          * smd_buf must be protected with smd_mutex to garantee
>          * that all messages are sent one after another
> --
> 2.5.0
>



-- 
Best regards,
Eugene

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding
  2015-12-29 19:03     ` Bjorn Andersson
  2015-12-29 23:27       ` Rob Herring
@ 2016-01-25 17:50       ` Bjorn Andersson
  1 sibling, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2016-01-25 17:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Eugene Krasnikov, Ian Campbell, Kalle Valo, Mark Rutland,
	Pawel Moll, devicetree-u79uwXL29TY76Z2rM5mHXA, yfw,
	linux-arm-msm, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless, netdev, wcn36xx

On Tue, Dec 29, 2015 at 11:03 AM, Bjorn Andersson <bjorn-UYDU3/A3LUY@public.gmane.org> wrote:
> On Tue 29 Dec 10:34 PST 2015, Rob Herring wrote:
>
>> On Sun, Dec 27, 2015 at 05:34:27PM -0800, Bjorn Andersson wrote:
>> > Add binding representing the Qualcomm wcn3620/60/80 WiFi block.
>> > Signed-off-by: Bjorn Andersson <bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
>> > ---
>> >  .../bindings/net/wireless/qcom,wcn36xx-wifi.txt    | 76 ++++++++++++++++++++++
>> >  1 file changed, 76 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
>> >
>> > diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
>> > new file mode 100644
>> > index 000000000000..7b314b9f30af
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/net/wireless/qcom,wcn36xx-wifi.txt
>> > @@ -0,0 +1,76 @@
>> > +Qualcomm WCN36xx WiFi Binding
>> > +
>> > +This binding describes the Qualcomm WCN36xx WiFi hardware. The hardware block
>> > +is part of the Qualcomm WCNSS core, a WiFi/BT/FM combo chip, found in a variety
>> > +of Qualcomm platforms.
>>
>> Are BT/FM functions completely separate? If so, separate bindings are
>> okay. If not, then we need to describe the full chip.
>>
>
> It's three different hardware blocks (WiFi, BT and FM-radio) with shared
> RF-hardware and an ARM core for control logic.
>
> There seems to be some control commands going towards the BT part that
> controls coexistence properties of the RF-hardware, but other than that
> I see it as logically separate blocks.
>
>
> So I think it's fine to model this as separate pieces in DT.
>

After more testing I've concluded that there is a timing dependency
between the WiFi driver and the wcnss_ctrl driver. If the WiFi driver
starts communicating with the WLAN subsystem in the WCNSS block before
we have finished uploading the NV data to the WCNSS core further
communication will fail.

So looks like I need to remodel this slightly to take this into account :/

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/4] wcn36xx: Transition driver to SMD client
       [not found]       ` <CAFSJ42a2mD1gSaarKEny4xp9g_PbcLuv3PLsRnHp+qviv6f6mg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-03-29  4:39         ` Bjorn Andersson
  0 siblings, 0 replies; 14+ messages in thread
From: Bjorn Andersson @ 2016-03-29  4:39 UTC (permalink / raw)
  To: Eugene Krasnikov
  Cc: Kalle Valo, Ian Campbell, Mark Rutland, Pawel Moll, Rob Herring,
	yfw, linux-arm-msm, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless, netdev, wcn36xx

On Mon, Jan 11, 2016 at 1:02 AM, Eugene Krasnikov <k.eugene.e-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Better late than never! Looks good to me.
>

Unfortunately I ran into an issue with ordering of operations between
the WiFi driver and the wcnss_ctrl driver. So an updated series is on
the way, but this depends on changes to the wcnss_ctrl driver, which
are being reviewed right now.

Regards,
Bjorn

> 2015-12-28 1:34 GMT+00:00 Bjorn Andersson <bjorn-UYDU3/A3LUY@public.gmane.org>:
>> 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.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
>> ---
>>  drivers/net/wireless/ath/wcn36xx/Kconfig   |   2 +-
>>  drivers/net/wireless/ath/wcn36xx/dxe.c     |  16 +++--
>>  drivers/net/wireless/ath/wcn36xx/main.c    | 111 +++++++++++++++++------------
>>  drivers/net/wireless/ath/wcn36xx/smd.c     |  26 ++++---
>>  drivers/net/wireless/ath/wcn36xx/smd.h     |   4 ++
>>  drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  21 ++----
>>  6 files changed, 99 insertions(+), 81 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 f8dfa05b290a..47f3937a7ab9 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 <linux/interrupt.h>
>> +#include <linux/soc/qcom/smem_state.h>
>>  #include "wcn36xx.h"
>>  #include "txrx.h"
>>
>> @@ -150,9 +151,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;
>>
>> @@ -676,9 +680,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 7c169abdbafe..8659e3f997d2 100644
>> --- a/drivers/net/wireless/ath/wcn36xx/main.c
>> +++ b/drivers/net/wireless/ath/wcn36xx/main.c
>> @@ -19,6 +19,9 @@
>>  #include <linux/module.h>
>>  #include <linux/firmware.h>
>>  #include <linux/platform_device.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/soc/qcom/smd.h>
>> +#include <linux/soc/qcom/smem_state.h>
>>  #include "wcn36xx.h"
>>
>>  unsigned int wcn36xx_dbg_mask;
>> @@ -981,48 +984,63 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
>>  }
>>
>>  static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
>> -                                         struct platform_device *pdev)
>> +                                         struct device *dev)
>>  {
>> -       struct resource *res;
>> +       u32 mmio[2];
>> +       int ret;
>> +
>>         /* Set TX IRQ */
>> -       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
>> -                                          "wcnss_wlantx_irq");
>> -       if (!res) {
>> +       wcn->tx_irq = irq_of_parse_and_map(dev->of_node, 0);
>> +       if (!wcn->tx_irq) {
>>                 wcn36xx_err("failed to get tx_irq\n");
>>                 return -ENOENT;
>>         }
>> -       wcn->tx_irq = res->start;
>>
>>         /* Set RX IRQ */
>> -       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
>> -                                          "wcnss_wlanrx_irq");
>> -       if (!res) {
>> +       wcn->rx_irq = irq_of_parse_and_map(dev->of_node, 1);
>> +       if (!wcn->rx_irq) {
>>                 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",
>> +                       &wcn->tx_enable_state_bit);
>> +       if (IS_ERR(wcn->tx_enable_state)) {
>> +               wcn36xx_err("failed to get tx-enable state\n");
>> +               return -ENOENT;
>> +       }
>> +
>> +       /* Acquire SMSM tx rings empty handle */
>> +       wcn->tx_rings_empty_state = qcom_smem_state_get(dev, "tx-rings-empty",
>> +                       &wcn->tx_rings_empty_state_bit);
>> +       if (IS_ERR(wcn->tx_rings_empty_state)) {
>> +               wcn36xx_err("failed to get tx-rings-empty state\n");
>> +               return -ENOENT;
>> +       }
>>
>>         /* Map the memory */
>> -       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
>> -                                                "wcnss_mmio");
>> -       if (!res) {
>> -               wcn36xx_err("failed to get mmio\n");
>> +       ret = of_property_read_u32_array(dev->of_node, "qcom,wcnss-mmio", mmio, 2);
>> +       if (ret) {
>> +               wcn36xx_err("failed to get qcom,wcnss-mmio\n");
>>                 return -ENOENT;
>>         }
>> -       wcn->mmio = ioremap(res->start, resource_size(res));
>> +
>> +       wcn->mmio = ioremap(mmio[0], mmio[1]);
>>         if (!wcn->mmio) {
>>                 wcn36xx_err("failed to map io memory\n");
>>                 return -ENOMEM;
>>         }
>> +
>>         return 0;
>>  }
>>
>> -static int wcn36xx_probe(struct platform_device *pdev)
>> +static int wcn36xx_probe(struct qcom_smd_device *sdev)
>>  {
>>         struct ieee80211_hw *hw;
>>         struct wcn36xx *wcn;
>>         int ret;
>> -       u8 addr[ETH_ALEN];
>> +       const u8 *addr;
>>
>>         wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
>>
>> @@ -1032,20 +1050,27 @@ static int wcn36xx_probe(struct platform_device *pdev)
>>                 ret = -ENOMEM;
>>                 goto out_err;
>>         }
>> -       platform_set_drvdata(pdev, hw);
>> +       dev_set_drvdata(&sdev->dev, hw);
>>         wcn = hw->priv;
>>         wcn->hw = hw;
>> -       wcn->dev = &pdev->dev;
>> -       wcn->ctrl_ops = pdev->dev.platform_data;
>> +       wcn->dev = &sdev->dev;
>> +       wcn->smd_channel = sdev->channel;
>>
>>         mutex_init(&wcn->hal_mutex);
>>
>> -       if (!wcn->ctrl_ops->get_hw_mac(addr)) {
>> +       sdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
>> +
>> +       addr = of_get_property(sdev->dev.of_node, "local-mac-address", &ret);
>> +       if (addr && ret != ETH_ALEN) {
>> +               wcn36xx_err("invalid local-mac-address\n");
>> +               ret = -EINVAL;
>> +               goto out_err;
>> +       } else if (addr) {
>>                 wcn36xx_info("mac address: %pM\n", addr);
>>                 SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
>>         }
>>
>> -       ret = wcn36xx_platform_get_resources(wcn, pdev);
>> +       ret = wcn36xx_platform_get_resources(wcn, &sdev->dev);
>>         if (ret)
>>                 goto out_wq;
>>
>> @@ -1063,9 +1088,10 @@ out_wq:
>>  out_err:
>>         return ret;
>>  }
>> -static int wcn36xx_remove(struct platform_device *pdev)
>> +
>> +static void wcn36xx_remove(struct qcom_smd_device *sdev)
>>  {
>> -       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
>> +       struct ieee80211_hw *hw = dev_get_drvdata(&sdev->dev);
>>         struct wcn36xx *wcn = hw->priv;
>>         wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
>>
>> @@ -1073,41 +1099,34 @@ static int wcn36xx_remove(struct platform_device *pdev)
>>         mutex_destroy(&wcn->hal_mutex);
>>
>>         ieee80211_unregister_hw(hw);
>> +
>> +       qcom_smem_state_put(wcn->tx_enable_state);
>> +       qcom_smem_state_put(wcn->tx_rings_empty_state);
>> +
>>         iounmap(wcn->mmio);
>>         ieee80211_free_hw(hw);
>> -
>> -       return 0;
>>  }
>> -static const struct platform_device_id wcn36xx_platform_id_table[] = {
>> -       {
>> -               .name = "wcn36xx",
>> -               .driver_data = 0
>> -       },
>> +
>> +static const struct of_device_id wcn36xx_of_match[] = {
>> +       { .compatible = "qcom,wcn3620-wlan" },
>> +       { .compatible = "qcom,wcn3660-wlan" },
>> +       { .compatible = "qcom,wcn3680-wlan" },
>>         {}
>>  };
>> -MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
>> +MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
>>
>> -static struct platform_driver wcn36xx_driver = {
>> +static struct qcom_smd_driver wcn36xx_driver = {
>>         .probe      = wcn36xx_probe,
>>         .remove     = wcn36xx_remove,
>> +       .callback = wcn36xx_smd_rsp_process,
>>         .driver         = {
>>                 .name   = "wcn36xx",
>> +               .of_match_table = wcn36xx_of_match,
>> +               .owner  = THIS_MODULE,
>>         },
>> -       .id_table    = wcn36xx_platform_id_table,
>>  };
>>
>> -static int __init wcn36xx_init(void)
>> -{
>> -       platform_driver_register(&wcn36xx_driver);
>> -       return 0;
>> -}
>> -module_init(wcn36xx_init);
>> -
>> -static void __exit wcn36xx_exit(void)
>> -{
>> -       platform_driver_unregister(&wcn36xx_driver);
>> -}
>> -module_exit(wcn36xx_exit);
>> +module_qcom_smd_driver(wcn36xx_driver);
>>
>>  MODULE_LICENSE("Dual BSD/GPL");
>>  MODULE_AUTHOR("Eugene Krasnikov k.eugene.e-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org");
>> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
>> index 4307429740a9..2bf42787a4af 100644
>> --- a/drivers/net/wireless/ath/wcn36xx/smd.c
>> +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
>> @@ -19,6 +19,7 @@
>>  #include <linux/etherdevice.h>
>>  #include <linux/firmware.h>
>>  #include <linux/bitops.h>
>> +#include <linux/soc/qcom/smd.h>
>>  #include "smd.h"
>>
>>  struct wcn36xx_cfg_val {
>> @@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
>>
>>         init_completion(&wcn->hal_rsp_compl);
>>         start = jiffies;
>> -       ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
>> +       ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len);
>>         if (ret) {
>>                 wcn36xx_err("HAL TX failed\n");
>>                 goto out;
>> @@ -2100,9 +2101,13 @@ out:
>>         mutex_unlock(&wcn->hal_mutex);
>>         return ret;
>>  }
>> -static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
>> +
>> +int wcn36xx_smd_rsp_process(struct qcom_smd_device *sdev,
>> +                           const void *buf, size_t len)
>>  {
>> -       struct wcn36xx_hal_msg_header *msg_header = buf;
>> +       const struct wcn36xx_hal_msg_header *msg_header = buf;
>> +       struct ieee80211_hw *hw = dev_get_drvdata(&sdev->dev);
>> +       struct wcn36xx *wcn = hw->priv;
>>         struct wcn36xx_hal_ind_msg *msg_ind;
>>         wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
>>
>> @@ -2151,7 +2156,7 @@ 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) + len, GFP_KERNEL);
>> +               msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
>>                 if (!msg_ind) {
>>                         /*
>>                          * FIXME: Do something smarter then just
>> @@ -2175,6 +2180,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
>>                 wcn36xx_err("SMD_EVENT (%d) not supported\n",
>>                               msg_header->msg_type);
>>         }
>> +
>> +       return 0;
>>  }
>>  static void wcn36xx_ind_smd_work(struct work_struct *work)
>>  {
>> @@ -2232,22 +2239,13 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
>>         INIT_LIST_HEAD(&wcn->hal_ind_queue);
>>         spin_lock_init(&wcn->hal_ind_lock);
>>
>> -       ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
>> -       if (ret) {
>> -               wcn36xx_err("failed to open control channel\n");
>> -               goto free_wq;
>> -       }
>> -
>> -       return ret;
>> +       return 0;
>>
>> -free_wq:
>> -       destroy_workqueue(wcn->hal_ind_wq);
>>  out:
>>         return ret;
>>  }
>>
>>  void wcn36xx_smd_close(struct wcn36xx *wcn)
>>  {
>> -       wcn->ctrl_ops->close();
>>         destroy_workqueue(wcn->hal_ind_wq);
>>  }
>> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
>> index 21cc4ac7b5ca..4d96d56d266f 100644
>> --- a/drivers/net/wireless/ath/wcn36xx/smd.h
>> +++ b/drivers/net/wireless/ath/wcn36xx/smd.h
>> @@ -60,6 +60,7 @@ struct wcn36xx_hal_ind_msg {
>>  };
>>
>>  struct wcn36xx;
>> +struct qcom_smd_device;
>>
>>  int wcn36xx_smd_open(struct wcn36xx *wcn);
>>  void wcn36xx_smd_close(struct wcn36xx *wcn);
>> @@ -136,4 +137,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index);
>>  int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index);
>>
>>  int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
>> +
>> +int wcn36xx_smd_rsp_process(struct qcom_smd_device *sdev,
>> +                           const void *buf, size_t len);
>>  #endif /* _SMD_H_ */
>> diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
>> index 7997cc1312ee..4be81f66e167 100644
>> --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
>> +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
>> @@ -103,19 +103,6 @@ struct nv_data {
>>         u8      table;
>>  };
>>
>> -/* Interface for platform control path
>> - *
>> - * @open: hook must be called when wcn36xx wants to open control channel.
>> - * @tx: sends a buffer.
>> - */
>> -struct wcn36xx_platform_ctrl_ops {
>> -       int (*open)(void *drv_priv, void *rsp_cb);
>> -       void (*close)(void);
>> -       int (*tx)(char *buf, size_t len);
>> -       int (*get_hw_mac)(u8 *addr);
>> -       int (*smsm_change_state)(u32 clear_mask, u32 set_mask);
>> -};
>> -
>>  /**
>>   * struct wcn36xx_vif - holds VIF related fields
>>   *
>> @@ -204,7 +191,13 @@ struct wcn36xx {
>>         int                     rx_irq;
>>         void __iomem            *mmio;
>>
>> -       struct wcn36xx_platform_ctrl_ops *ctrl_ops;
>> +       struct qcom_smd_channel *smd_channel;
>> +
>> +       struct qcom_smem_state  *tx_enable_state;
>> +       unsigned                tx_enable_state_bit;
>> +       struct qcom_smem_state  *tx_rings_empty_state;
>> +       unsigned                tx_rings_empty_state_bit;
>> +
>>         /*
>>          * smd_buf must be protected with smd_mutex to garantee
>>          * that all messages are sent one after another
>> --
>> 2.5.0
>>
>
>
>
> --
> Best regards,
> Eugene
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2016-03-29  4:39 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-28  1:34 [PATCH 0/4] WCN36xx convert to mainline SMD interface Bjorn Andersson
2015-12-28  1:34 ` [PATCH 1/4] wcn36xx: Fold indication payload into message header Bjorn Andersson
2015-12-28  1:34 ` [PATCH 2/4] wcn36xx: Change indication list lock to spinlock Bjorn Andersson
2015-12-28 23:06   ` Stephen Hemminger
2015-12-29  4:25     ` Bjorn Andersson
     [not found] ` <1451266467-15377-1-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
2015-12-28  1:34   ` [PATCH 3/4] wcn36xx: Transition driver to SMD client Bjorn Andersson
2016-01-11  9:02     ` Eugene Krasnikov
     [not found]       ` <CAFSJ42a2mD1gSaarKEny4xp9g_PbcLuv3PLsRnHp+qviv6f6mg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-03-29  4:39         ` Bjorn Andersson
2015-12-28  1:34 ` [PATCH 4/4] dt: binding: Add Qualcomm wcn36xx WiFi binding Bjorn Andersson
2015-12-29 18:34   ` Rob Herring
2015-12-29 19:03     ` Bjorn Andersson
2015-12-29 23:27       ` Rob Herring
2016-01-25 17:50       ` Bjorn Andersson
     [not found]   ` <1451266467-15377-5-git-send-email-bjorn.andersson-/MT0OVThwyLZJqsBc5GL+g@public.gmane.org>
2015-12-29 19:11     ` Andy Gross

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).