diff options
author | Yin, Fengwei <fengwei.yin@linaro.org> | 2015-08-07 09:33:12 +0800 |
---|---|---|
committer | Yin, Fengwei <fengwei.yin@linaro.org> | 2015-08-07 09:33:12 +0800 |
commit | dfc59529e72fcd2d3539e17183b68c47380c462c (patch) | |
tree | 8517f8f704c763153444ae2138c5ad1e5b23b6d4 /drivers | |
parent | 5fb83cbdff50fb081341548d12887592916fdb19 (diff) |
Partially work for migrating the wifi driver to new SMD.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c | 325 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 29 | ||||
-rw-r--r-- | drivers/soc/qcom/smd.c | 61 |
5 files changed, 156 insertions, 273 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 3da80a3a4f9d..bbd4eca5e9f1 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1047,17 +1047,19 @@ static int wcn36xx_probe(struct platform_device *pdev) goto dma_mask_err; } dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32)); - wcn->ctrl_ops = pdev->dev.platform_data; + wcn->wcn36xx_data = pdev->dev.platform_data; + wcn->ctrl_ops = &wcn->wcn36xx_data->ctrl_ops; + wcn->wcn36xx_data->wcn = wcn; if (!wcn->ctrl_ops->get_chip_type) { dev_err(&pdev->dev, "Missing ops->get_chip_type\n"); ret = -EINVAL; goto out_wq; } - wcn->chip_version = wcn->ctrl_ops->get_chip_type(); + wcn->chip_version = wcn->ctrl_ops->get_chip_type(wcn); mutex_init(&wcn->hal_mutex); - if (!wcn->ctrl_ops->get_hw_mac(addr)) { + if (!wcn->ctrl_ops->get_hw_mac(wcn, addr)) { wcn36xx_info("mac address: %pM\n", addr); SET_IEEE80211_PERM_ADDR(wcn->hw, addr); } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 0e22bae2ddf6..e67779a77d92 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -253,7 +253,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 = wcn->ctrl_ops->tx(wcn, wcn->hal_buf, len); if (ret) { wcn36xx_err("HAL TX failed\n"); goto out; @@ -2107,6 +2107,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) struct wcn36xx_hal_ind_msg *msg_ind; wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); + pr_info("%s: enter\n", __func__); + switch (msg_header->msg_type) { case WCN36XX_HAL_START_RSP: case WCN36XX_HAL_CONFIG_STA_RSP: @@ -2251,7 +2253,7 @@ out: void wcn36xx_smd_close(struct wcn36xx *wcn) { - wcn->ctrl_ops->close(); + wcn->ctrl_ops->close(wcn); destroy_workqueue(wcn->hal_ind_wq); mutex_destroy(&wcn->hal_ind_mutex); } diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c index 37f7a78352ed..0a3494ad812d 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c @@ -38,42 +38,26 @@ struct qproc { struct rproc *rproc; }; -#if 0 -struct wcn36xx_msm { - struct wcn36xx_platform_ctrl_ops ctrl_ops; - struct platform_device *core; - void *drv_priv; - void (*rsp_cb)(void *drv_priv, void *buf, size_t len); - /* SMD related */ - struct workqueue_struct *wq; - struct work_struct smd_work; - struct completion smd_compl; - smd_channel_t *smd_ch; - struct pinctrl *pinctrl; - enum wcn36xx_chip_type chip_type; -}; - -static struct wcn36xx_msm wmsm; - static int wcn36xx_msm_smsm_change_state(u32 clear_mask, u32 set_mask) -{ - return smsm_change_state(SMSM_APPS_STATE, clear_mask, set_mask); +{ + return 0; } -static int wcn36xx_msm_get_hw_mac(u8 *addr) +static int wcn36xx_msm_get_hw_mac(struct wcn36xx *wcn, u8 *addr) { const struct firmware *addr_file = NULL; int status; u8 tmp[18]; static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5}; static const char *files = {MAC_ADDR_0}; + struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data; - status = request_firmware(&addr_file, files, &wmsm.core->dev); + status = request_firmware(&addr_file, files, &pdata->core->dev); if (status < 0) { /* Assign a random mac with Qualcomm oui */ - dev_err(&wmsm.core->dev, "Failed (%d) to read macaddress file %s, using a random address instead", status, - files); + dev_err(&pdata->core->dev, "Failed (%d) to read macaddress" + "file %s, using a random address instead", status, files); memcpy(addr, qcom_oui, 3); get_random_bytes(addr + 3, 3); } else { @@ -93,147 +77,46 @@ static int wcn36xx_msm_get_hw_mac(u8 *addr) return 0; } -static int wcn36xx_msm_smd_send_and_wait(char *buf, size_t len) +static int wcn36xx_msm_smd_send_and_wait(struct wcn36xx *wcn, char *buf, size_t len) { - int avail; int ret = 0; + struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data; - avail = smd_write_avail(wmsm.smd_ch); + pr_info("%s: enter with channel: %s, buffer len: %d\n", + __func__, pdata->wlan_ctrl_channel->name, len); - if (avail >= len) { - avail = smd_write(wmsm.smd_ch, buf, len); - if (avail != len) { - dev_err(&wmsm.core->dev, - "Cannot write to SMD channel\n"); - ret = -EAGAIN; - goto out; - } - } else { - dev_err(&wmsm.core->dev, - "SMD channel can accept only %d bytes\n", avail); - ret = -ENOMEM; - goto out; + mutex_lock(&pdata->wlan_ctrl_lock); + ret = qcom_smd_send(pdata->wlan_ctrl_channel, buf, len); + if (ret) { + dev_err(wcn->dev, "wlan ctrl channel tx failed\n"); } + mutex_unlock(&pdata->wlan_ctrl_lock); -out: return ret; } -static void wcn36xx_msm_smd_notify(void *data, unsigned event) -{ - struct wcn36xx_msm *wmsm_priv = (struct wcn36xx_msm *)data; - - switch (event) { - case SMD_EVENT_OPEN: - complete(&wmsm_priv->smd_compl); - break; - case SMD_EVENT_DATA: - queue_work(wmsm_priv->wq, &wmsm_priv->smd_work); - break; - case SMD_EVENT_CLOSE: - break; - case SMD_EVENT_STATUS: - break; - case SMD_EVENT_REOPEN_READY: - break; - default: - dev_err(&wmsm_priv->core->dev, - "%s: SMD_EVENT (%d) not supported\n", __func__, event); - break; - } -} - -static void wcn36xx_msm_smd_work(struct work_struct *work) +static int wcn36xx_msm_smd_open(struct wcn36xx *wcn, void *rsp_cb) { - int avail; - int msg_len; - void *msg; - int ret; - struct wcn36xx_msm *wmsm_priv = - container_of(work, struct wcn36xx_msm, smd_work); - - while (1) { - msg_len = smd_cur_packet_size(wmsm_priv->smd_ch); - if (0 == msg_len) { - return; - } - avail = smd_read_avail(wmsm_priv->smd_ch); - if (avail < msg_len) { - return; - } - msg = kmalloc(msg_len, GFP_KERNEL); - if (NULL == msg) { - return; - } - - ret = smd_read(wmsm_priv->smd_ch, msg, msg_len); - if (ret != msg_len) { - return; - } - wmsm_priv->rsp_cb(wmsm_priv->drv_priv, msg, msg_len); - kfree(msg); - } -} - -int wcn36xx_msm_smd_open(void *drv_priv, void *rsp_cb) -{ - int ret, left; - wmsm.drv_priv = drv_priv; - wmsm.rsp_cb = rsp_cb; - INIT_WORK(&wmsm.smd_work, wcn36xx_msm_smd_work); - init_completion(&wmsm.smd_compl); - - wmsm.wq = create_workqueue("wcn36xx_msm_smd_wq"); - if (!wmsm.wq) { - dev_err(&wmsm.core->dev, "failed to allocate wq"); - ret = -ENOMEM; - return ret; - } - - ret = smd_named_open_on_edge("WLAN_CTRL", SMD_APPS_WCNSS, - &wmsm.smd_ch, &wmsm, wcn36xx_msm_smd_notify); - if (ret) { - dev_err(&wmsm.core->dev, - "smd_named_open_on_edge failed: %d\n", ret); - return ret; - } - - left = wait_for_completion_interruptible_timeout(&wmsm.smd_compl, - msecs_to_jiffies(HAL_MSG_TIMEOUT)); - if (left <= 0) { - dev_err(&wmsm.core->dev, - "timeout waiting for smd open: %d\n", ret); - return left; - } - - /* Not to receive INT until the whole buf from SMD is read */ - smd_disable_read_intr(wmsm.smd_ch); + struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data; + pr_info("%s: enter with channel: %s\n", __func__, + pdata->wlan_ctrl_channel->name); + pdata->cb = rsp_cb; return 0; } -void wcn36xx_msm_smd_close(void) -{ - smd_close(wmsm.smd_ch); - flush_workqueue(wmsm.wq); - destroy_workqueue(wmsm.wq); -} - -int wcn36xx_msm_shutdown(const struct subsys_desc *desc, bool force_stop) -{ - return 0; -} -int wcn36xx_msm_powerup(const struct subsys_desc *desc) +static void wcn36xx_msm_smd_close(struct wcn36xx *wcn) { - return 0; + return; } -static int wcn36xx_msm_get_chip_type(void) +static int wcn36xx_msm_get_chip_type(struct wcn36xx *wcn) { - return wmsm.chip_type; + struct wcn36xx_platform_data *pdata = wcn->wcn36xx_data; + return pdata->chip_type; } -static struct wcn36xx_msm wmsm = { +static struct wcn36xx_platform_data wcn36xx_data = { .ctrl_ops = { .open = wcn36xx_msm_smd_open, .close = wcn36xx_msm_smd_close, @@ -244,52 +127,64 @@ static struct wcn36xx_msm wmsm = { }, }; -static int wcn36xx_wlan_ctrl_probe(struct platform_device *pdev) +static int qcom_smd_wlan_ctrl_probe(struct qcom_smd_device *sdev) { - wmsm.core = platform_device_alloc("wcn36xx", -1); + pr_info("%s: enter\n", __func__); + mutex_init(&wcn36xx_data.wlan_ctrl_lock); + init_completion(&wcn36xx_data.wlan_ctrl_ack); - for (n = 0; n < ARRAY_SIZE(rnames); n++) { - r = platform_get_resource_byname(pdev, rtype[n], rnames[n]); - if (!r) { - dev_err(&wmsm.core->dev, - "Missing resource %s'\n", rnames[n]); - ret = -ENOMEM; - return ret; - } - res[n] = *r; - } + wcn36xx_data.sdev = sdev; - platform_device_add_resources(wmsm.core, res, n); + dev_set_drvdata(&sdev->dev, &wcn36xx_data); + wcn36xx_data.wlan_ctrl_channel = sdev->channel; - ret = platform_device_add_data(wmsm.core, &wmsm.ctrl_ops, - sizeof(wmsm.ctrl_ops)); - if (ret) { - dev_err(&wmsm.core->dev, "Can't add platform data\n"); - ret = -ENOMEM; - return ret; - } + of_platform_populate(sdev->dev.of_node, NULL, NULL, &sdev->dev); - platform_device_add(wmsm.core); + return 0; } -static int wcn36xx_wlan_ctrl_remove(struct platform_device *pdev) +static void qcom_smd_wlan_ctrl_remove(struct qcom_smd_device *sdev) { - platform_device_del(wmsm.core); - platform_device_put(wmsm.core); + of_platform_depopulate(&sdev->dev); } -#endif -struct wcn36xx_platform_data { - enum wcn36xx_chip_type chip_type; +static int qcom_smd_wlan_ctrl_callback(struct qcom_smd_device *qsdev, + const void *data, + size_t count) +{ + struct wcn36xx_platform_data *pdata = dev_get_drvdata(&qsdev->dev); - struct qcom_smd_channel *wlan_ctrl_channel; - struct completion wlan_ctrl_ack; - struct mutex wlan_ctrl_lock; + pr_info("%s: enter\n", __func__); - struct pinctrl *pinctrl; -}; + void *buf = kzalloc(count, GFP_KERNEL); + if (!buf) { + dev_err(&pdata->core->dev, "can't allocate buffer\n"); + return -ENOMEM; + } -static struct wcn36xx_platform_data wcn36xx_data; + memcpy_fromio(buf, data, count); + pdata->cb(pdata->wcn, buf, count); + kfree(buf); + + return 0; +} + +static const struct of_device_id qcom_smd_wlan_ctrl_of_match[] = { + { .compatible = "qcom,wlan-ctrl" }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_smd_wlan_ctrl_of_match); + +static struct qcom_smd_driver qcom_smd_wlan_ctrl_driver = { + .probe = qcom_smd_wlan_ctrl_probe, + .remove = qcom_smd_wlan_ctrl_remove, + .callback = qcom_smd_wlan_ctrl_callback, + .driver = { + .name = "qcom_smd_wlan_ctrl", + .owner = THIS_MODULE, + .of_match_table = qcom_smd_wlan_ctrl_of_match, + }, +}; static const struct of_device_id wcn36xx_msm_match_table[] = { { .compatible = "qcom,wcn3660", .data = (void *)WCN36XX_CHIP_3660 }, @@ -305,7 +200,6 @@ static int wcn36xx_msm_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct resource *r; struct resource res[3]; - struct pinctrl_state *ps; static const char const *rnames[] = { "wcnss_mmio", "wcnss_wlantx_irq", "wcnss_wlanrx_irq" }; static const int rtype[] = { @@ -313,35 +207,8 @@ static int wcn36xx_msm_probe(struct platform_device *pdev) struct device_node *dn; int n; - of_id = of_match_node(wcn36xx_msm_match_table, pdev->dev.of_node); - if (!of_id) - return -EINVAL; - - wcn36xx_data.chip_type = (enum wcn36xx_chip_type)of_id->data; - -#if 0 - wcn36xx_data.pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR_OR_NULL(wcn36xx_data.pinctrl)) - return PTR_ERR(wcn36xx_data.pinctrl); - - ps = pinctrl_lookup_state(wcn36xx_data.pinctrl, "wcnss_default"); - if (IS_ERR_OR_NULL(ps)) - return PTR_ERR(ps); - - ret = pinctrl_select_state(wcn36xx_data.pinctrl, ps); - if (ret) - return ret; -#endif - wcnss_core_prepare(pdev); -#if 0 - if (IS_ERR_OR_NULL(pil)) - pil = subsystem_get("wcnss"); - if (IS_ERR_OR_NULL(pil)) - return PTR_ERR(pil); -#endif - dn = of_parse_phandle(pdev->dev.of_node, "rproc", 0); if (!dn) { dev_err(&pdev->dev, "No rproc specified\n"); @@ -357,27 +224,49 @@ static int wcn36xx_msm_probe(struct platform_device *pdev) } } + qcom_smd_driver_register(&qcom_smd_wlan_ctrl_driver); wcnss_core_init(); - dev_info(&pdev->dev, "%s initialized\n", __func__); - return 0; -} + of_id = of_match_node(wcn36xx_msm_match_table, pdev->dev.of_node); + if (!of_id) + return -EINVAL; + wcn36xx_data.chip_type = (enum wcn36xx_chip_type)of_id->data; -static int wcn36xx_msm_remove(struct platform_device *pdev) -{ - struct pinctrl_state *ps; + wcn36xx_data.core = platform_device_alloc("wcn36xx", -1); + + for (n = 0; n < ARRAY_SIZE(rnames); n++) { + r = platform_get_resource_byname(pdev, rtype[n], rnames[n]); + if (!r) { + dev_err(&wcn36xx_data.core->dev, + "Missing resource %s'\n", rnames[n]); + ret = -ENOMEM; + return ret; + } + res[n] = *r; + } -#if 0 - if (wcn36xx_data.pinctrl) { - ps = pinctrl_lookup_state(wcn36xx_data.pinctrl, "wcnss_sleep"); - if (IS_ERR_OR_NULL(ps)) - return PTR_ERR(ps); + platform_device_add_resources(wcn36xx_data.core, res, n); - pinctrl_select_state(wcn36xx_data.pinctrl, ps); + ret = platform_device_add_data(wcn36xx_data.core, &wcn36xx_data, + sizeof(wcn36xx_data)); + if (ret) { + dev_err(&wcn36xx_data.core->dev, "Can't add platform data\n"); + ret = -ENOMEM; + return ret; } -#endif + platform_device_add(wcn36xx_data.core); + + dev_info(&pdev->dev, "%s initialized\n", __func__); + + return 0; +} + +static int wcn36xx_msm_remove(struct platform_device *pdev) +{ + platform_device_del(wcn36xx_data.core); + platform_device_put(wcn36xx_data.core); return 0; } diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 9ca730c1df54..d9f8b6450487 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -116,14 +116,32 @@ enum wcn36xx_chip_type { * @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 (*get_chip_type)(void); + int (*open)(struct wcn36xx *wcn, void *rsp_cb); + void (*close)(struct wcn36xx *wcn); + int (*tx)(struct wcn36xx *wcn, char *buf, size_t len); + int (*get_hw_mac)(struct wcn36xx *wcn, u8 *addr); + int (*get_chip_type)(struct wcn36xx *wcn); int (*smsm_change_state)(u32 clear_mask, u32 set_mask); }; +struct wcn36xx_platform_data { + enum wcn36xx_chip_type chip_type; + + struct platform_device *core; + + struct qcom_smd_device *sdev; + struct qcom_smd_channel *wlan_ctrl_channel; + struct completion wlan_ctrl_ack; + struct mutex wlan_ctrl_lock; + + struct pinctrl *pinctrl; + + struct wcn36xx *wcn; + + void (*cb)(struct wcn36xx *wcn, void *buf, size_t len); + struct wcn36xx_platform_ctrl_ops ctrl_ops; +}; + /** * struct wcn36xx_vif - holds VIF related fields * @@ -212,6 +230,7 @@ struct wcn36xx { int rx_irq; void __iomem *mmio; + struct wcn36xx_platform_data *wcn36xx_data; struct wcn36xx_platform_ctrl_ops *ctrl_ops; /* * smd_buf must be protected with smd_mutex to garantee diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index 50b46437e938..9451bd326223 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -131,18 +131,6 @@ struct qcom_smd_edge { struct work_struct work; }; -/* - * SMD channel states. - */ -enum smd_channel_state { - SMD_CHANNEL_CLOSED, - SMD_CHANNEL_OPENING, - SMD_CHANNEL_OPENED, - SMD_CHANNEL_FLUSHING, - SMD_CHANNEL_CLOSING, - SMD_CHANNEL_RESET, - SMD_CHANNEL_RESET_OPENING -}; /** * struct qcom_smd_channel - smd channel struct @@ -166,38 +154,6 @@ enum smd_channel_state { * @pkt_size: size of the currently handled packet * @list: lite entry for @channels in qcom_smd_edge */ -struct qcom_smd_channel { - struct qcom_smd_edge *edge; - - struct qcom_smd_device *qsdev; - - char *name; - enum smd_channel_state state; - enum smd_channel_state remote_state; - - struct smd_channel_info *tx_info; - struct smd_channel_info *rx_info; - - struct smd_channel_info_word *tx_info_word; - struct smd_channel_info_word *rx_info_word; - - struct mutex tx_lock; - wait_queue_head_t fblockread_event; - - void *tx_fifo; - void *rx_fifo; - int fifo_size; - - void *bounce_buffer; - int (*cb)(struct qcom_smd_device *, const void *, size_t); - - spinlock_t recv_lock; - - int pkt_size; - - struct list_head list; -}; - /** * struct qcom_smd - smd struct * @dev: device struct @@ -675,16 +631,24 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) { u32 hdr[5] = {len,}; int tlen = sizeof(hdr) + len; - int ret; + int ret, length; /* Word aligned channels only accept word size aligned data */ if (channel->rx_info_word != NULL && len % 4) return -EINVAL; + length = qcom_smd_get_tx_avail(channel); + pr_info("%s: channel_%s: avail tx: %d\n", __func__, + channel->name, length); + ret = mutex_lock_interruptible(&channel->tx_lock); if (ret) return ret; + length = qcom_smd_get_tx_avail(channel); + pr_info("%s: channel_%s: avail tx: %d\n", __func__, + channel->name, length); + while (qcom_smd_get_tx_avail(channel) < tlen) { if (channel->state != SMD_CHANNEL_OPENED) { ret = -EPIPE; @@ -704,9 +668,16 @@ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) SET_TX_CHANNEL_INFO(channel, fTAIL, 0); + length = qcom_smd_get_tx_avail(channel); + pr_info("%s: channel_%s: avail tx: %d\n", __func__, + channel->name, length); qcom_smd_write_fifo(channel, hdr, sizeof(hdr)); qcom_smd_write_fifo(channel, data, len); + length = qcom_smd_get_tx_avail(channel); + pr_info("%s: channel_%s: avail tx: %d\n", __func__, + channel->name, length); + SET_TX_CHANNEL_INFO(channel, fHEAD, 1); /* Ensure ordering of channel info updates */ |