From: Pavan Savoy <[email protected]>
Resending - Since I'm not sure the first mail was went through.
This time adding a patch from Matthias Kaehlcke.
Greg,
Please find attached the patch-set which fixes/updates the WiLink shared
transport driver hosted at drivers/misc/ti-st/
Among the following set of patches:-
The gpio handling patch, disabling chip upon firmware download timeout &
fixing the read fw version command comes from testing the driver on various
platforms with a variety of serial driver working underneath.
The other 2 patches comes in form of removing sparse warnings and a nicer
update from existing wait for completion usage.
Matthias Kaehlcke (1):
drivers/misc/ti-st: check chip_awake NULL check
Pavan Savoy (5):
drivers/misc/ti-st: remove gpio handling
drivers/misc/ti-st: remove sparse warnings
drivers/misc/ti-st: chip_disable on timeout
drivers/misc/ti-st: use cpu friendly completions
drivers/misc/ti-st: fix read fw version cmd
drivers/misc/ti-st/st_core.c | 12 +++--
drivers/misc/ti-st/st_kim.c | 109 +++++++++++++++++-------------------------
drivers/misc/ti-st/st_ll.c | 2 +-
include/linux/ti_wilink_st.h | 3 +-
4 files changed, 54 insertions(+), 72 deletions(-)
--
1.7.4.1
From: Pavan Savoy <[email protected]>
If the read firmware version response from the chip is split into multiple
frames of UART buffer being received by the host, the TI-ST driver as of today
is unable to put the pieces of response together unlike other responses.
Signed-off-by: Pavan Savoy <[email protected]>
---
drivers/misc/ti-st/st_kim.c | 40 +++++++++++++++++++++++++++-------------
1 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 0f36db3..04a8199 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -66,7 +66,24 @@ static struct platform_device *st_get_plat_device(int id)
static void validate_firmware_response(struct kim_data_s *kim_gdata)
{
struct sk_buff *skb = kim_gdata->rx_skb;
- if (unlikely(skb->data[5] != 0)) {
+ if (!skb)
+ return;
+
+ /* these magic numbers are the position in the response buffer which
+ * allows us to distinguish whether the response is for the read
+ * version info. command
+ */
+ if (skb->data[2] == 0x01 && skb->data[3] == 0x01 &&
+ skb->data[4] == 0x10 && skb->data[5] == 0x00) {
+ /* fw version response */
+ memcpy(kim_gdata->resp_buffer,
+ kim_gdata->rx_skb->data,
+ kim_gdata->rx_skb->len);
+ complete_all(&kim_gdata->kim_rcvd);
+ kim_gdata->rx_state = ST_W4_PACKET_TYPE;
+ kim_gdata->rx_skb = NULL;
+ kim_gdata->rx_count = 0;
+ } else if (unlikely(skb->data[5] != 0)) {
pr_err("no proper response during fw download");
pr_err("data6 %x", skb->data[5]);
kfree_skb(skb);
@@ -213,10 +230,13 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
return -ETIMEDOUT;
}
INIT_COMPLETION(kim_gdata->kim_rcvd);
+ /* the positions 12 & 13 in the response buffer provide with the
+ * chip, major & minor numbers
+ */
version =
- MAKEWORD(kim_gdata->resp_buffer[13],
- kim_gdata->resp_buffer[14]);
+ MAKEWORD(kim_gdata->resp_buffer[12],
+ kim_gdata->resp_buffer[13]);
chip = (version & 0x7C00) >> 10;
min_ver = (version & 0x007F);
maj_ver = (version & 0x0380) >> 7;
@@ -410,16 +430,10 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count)
struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
struct kim_data_s *kim_gdata = st_gdata->kim_data;
- /* copy to local buffer */
- if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) {
- /* must be the read_ver_cmd */
- memcpy(kim_gdata->resp_buffer, data, count);
- complete_all(&kim_gdata->kim_rcvd);
- return;
- } else {
- kim_int_recv(kim_gdata, data, count);
- /* either completes or times out */
- }
+ /* proceed to gather all data and distinguish read fw version response
+ * from other fw responses when data gathering is complete
+ */
+ kim_int_recv(kim_gdata, data, count);
return;
}
--
1.7.4.1
From: Pavan Savoy <[email protected]>
If the communication with the WiLink breaks down for whatever reasons & the
ti-st driver is unable to un-install the line-discipline during clean-up in
st_kim_stop, the GPIO should be held low (BT_EN=0) & the platform's chip
disable hook shall also be called.
Signed-off-by: Pavan Savoy <[email protected]>
---
drivers/misc/ti-st/st_kim.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 847406a..54ff644 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -524,7 +524,7 @@ long st_kim_stop(void *kim_data)
msecs_to_jiffies(LDISC_TIME));
if (!err) { /* timeout */
pr_err(" timed out waiting for ldisc to be un-installed");
- return -ETIMEDOUT;
+ err = -ETIMEDOUT;
}
/* platform specific disable */
--
1.7.4.1
From: Matthias Kaehlcke <[email protected]>
Before calling on any of the platform hooks, shared transport driver checks
for the validity of the platform hooks as to whether it is provided or not.
A wrong function was being checked for, before the chip_awake hook was called
by the HCI-LL sleep logic handler. This patch corrects the check.
Signed-off-by: Pavan Savoy <[email protected]>
Signed-off-by: Matthias Kaehlcke <[email protected]>
---
drivers/misc/ti-st/st_ll.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
index 1ff460a..93b4d67 100644
--- a/drivers/misc/ti-st/st_ll.c
+++ b/drivers/misc/ti-st/st_ll.c
@@ -87,7 +87,7 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data)
/* communicate to platform about chip wakeup */
kim_data = st_data->kim_data;
pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_asleep)
+ if (pdata->chip_awake)
pdata->chip_awake(NULL);
}
--
1.7.4.1
From: Pavan Savoy <[email protected]>
A platform hook to enable/disable the chip was introduced to perform specific
activities to power-up and power-down the WL chip.
Moving the power-up/down sequence also there makes more sense, since different
platforms have begun to have their own ways to power-up/down the chip.
This patch removes all of the gpio handling done by the driver in
st_kim_start/st_kim_stop & any of the gpio request done in the probe function.
Signed-off-by: Pavan Savoy <[email protected]>
---
drivers/misc/ti-st/st_kim.c | 37 +------------------------------------
1 files changed, 1 insertions(+), 36 deletions(-)
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 7c14f8f..5c99995 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -454,11 +454,6 @@ long st_kim_start(void *kim_data)
if (pdata->chip_enable)
pdata->chip_enable(kim_gdata);
- /* Configure BT nShutdown to HIGH state */
- gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(5); /* FIXME: a proper toggle */
- gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(100);
/* re-initialize the completion */
INIT_COMPLETION(kim_gdata->ldisc_installed);
/* send notification to UIM */
@@ -500,8 +495,7 @@ long st_kim_start(void *kim_data)
* (b) upon failure to either install ldisc or download firmware.
* The function is responsible to (a) notify UIM about un-installation,
* (b) flush UART if the ldisc was installed.
- * (c) reset BT_EN - pull down nshutdown at the end.
- * (d) invoke platform's chip disabling routine.
+ * (c) invoke platform's chip disabling routine.
*/
long st_kim_stop(void *kim_data)
{
@@ -533,13 +527,6 @@ long st_kim_stop(void *kim_data)
return -ETIMEDOUT;
}
- /* By default configure BT nShutdown to LOW state */
- gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(1);
- gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(1);
- gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
-
/* platform specific disable */
if (pdata->chip_disable)
pdata->chip_disable(kim_gdata);
@@ -731,20 +718,6 @@ static int kim_probe(struct platform_device *pdev)
/* refer to itself */
kim_gdata->core_data->kim_data = kim_gdata;
- /* Claim the chip enable nShutdown gpio from the system */
- kim_gdata->nshutdown = pdata->nshutdown_gpio;
- status = gpio_request(kim_gdata->nshutdown, "kim");
- if (unlikely(status)) {
- pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
- return status;
- }
-
- /* Configure nShutdown GPIO as output=0 */
- status = gpio_direction_output(kim_gdata->nshutdown, 0);
- if (unlikely(status)) {
- pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
- return status;
- }
/* get reference of pdev for request_firmware
*/
kim_gdata->kim_pdev = pdev;
@@ -780,18 +753,10 @@ static int kim_probe(struct platform_device *pdev)
static int kim_remove(struct platform_device *pdev)
{
- /* free the GPIOs requested */
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
struct kim_data_s *kim_gdata;
kim_gdata = dev_get_drvdata(&pdev->dev);
- /* Free the Bluetooth/FM/GPIO
- * nShutdown gpio from the system
- */
- gpio_free(pdata->nshutdown_gpio);
- pr_info("nshutdown GPIO Freed");
-
debugfs_remove_recursive(kim_debugfs_dir);
sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
pr_info("sysfs entries removed");
--
1.7.4.1
From: Pavan Savoy <[email protected]>
remove sparse warnings by assigning right storage specifiers to functions and
also clean-up the declarations in the include/linux/ti_wilink_st.h
Change-Id: I459a8faf759339c63ec9497d28651d64ccfea534
Signed-off-by: Pavan Savoy <[email protected]>
---
drivers/misc/ti-st/st_core.c | 12 +++++++-----
drivers/misc/ti-st/st_kim.c | 12 ++++++------
include/linux/ti_wilink_st.h | 3 ++-
3 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index acfaeeb..46937b1 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -30,11 +30,13 @@
#include <linux/ti_wilink_st.h>
+extern void st_kim_recv(void *, const unsigned char *, long);
+void st_int_recv(void *, const unsigned char *, long);
/* function pointer pointing to either,
* st_kim_recv during registration to receive fw download responses
* st_int_recv after registration to receive proto stack responses
*/
-void (*st_recv) (void*, const unsigned char*, long);
+static void (*st_recv) (void *, const unsigned char *, long);
/********************************************************************/
static void add_channel_to_table(struct st_data_s *st_gdata,
@@ -100,7 +102,7 @@ int st_int_write(struct st_data_s *st_gdata,
* push the skb received to relevant
* protocol stacks
*/
-void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
+static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
{
pr_debug(" %s(prot:%d) ", __func__, chnl_id);
@@ -140,7 +142,7 @@ void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
* This function is being called with spin lock held, protocol drivers are
* only expected to complete their waits and do nothing more than that.
*/
-void st_reg_complete(struct st_data_s *st_gdata, char err)
+static void st_reg_complete(struct st_data_s *st_gdata, char err)
{
unsigned char i = 0;
pr_info(" %s ", __func__);
@@ -379,7 +381,7 @@ done:
* completely, return that skb which has the pending data.
* In normal cases, return top of txq.
*/
-struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
+static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
{
struct sk_buff *returning_skb;
@@ -401,7 +403,7 @@ struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
* txq and waitq needs protection since the other contexts
* may be sending data, waking up chip.
*/
-void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
+static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
{
unsigned long flags = 0;
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 5c99995..847406a 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -63,7 +63,7 @@ static struct platform_device *st_get_plat_device(int id)
* in case of error don't complete so that waiting for proper
* response times out
*/
-void validate_firmware_response(struct kim_data_s *kim_gdata)
+static void validate_firmware_response(struct kim_data_s *kim_gdata)
{
struct sk_buff *skb = kim_gdata->rx_skb;
if (unlikely(skb->data[5] != 0)) {
@@ -119,7 +119,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len)
* have been observed to come in bursts of different
* tty_receive and hence the logic
*/
-void kim_int_recv(struct kim_data_s *kim_gdata,
+static void kim_int_recv(struct kim_data_s *kim_gdata,
const unsigned char *data, long count)
{
const unsigned char *ptr;
@@ -236,7 +236,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
return 0;
}
-void skip_change_remote_baud(unsigned char **ptr, long *len)
+static void skip_change_remote_baud(unsigned char **ptr, long *len)
{
unsigned char *nxt_action, *cur_action;
cur_action = *ptr;
@@ -688,7 +688,7 @@ static const struct file_operations list_debugfs_fops = {
* board-*.c file
*/
-struct dentry *kim_debugfs_dir;
+static struct dentry *kim_debugfs_dir;
static int kim_probe(struct platform_device *pdev)
{
long status;
@@ -769,7 +769,7 @@ static int kim_remove(struct platform_device *pdev)
return 0;
}
-int kim_suspend(struct platform_device *pdev, pm_message_t state)
+static int kim_suspend(struct platform_device *pdev, pm_message_t state)
{
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
@@ -779,7 +779,7 @@ int kim_suspend(struct platform_device *pdev, pm_message_t state)
return -EOPNOTSUPP;
}
-int kim_resume(struct platform_device *pdev)
+static int kim_resume(struct platform_device *pdev)
{
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h
index 3ca0269..932b763 100644
--- a/include/linux/ti_wilink_st.h
+++ b/include/linux/ti_wilink_st.h
@@ -281,9 +281,10 @@ struct kim_data_s {
long st_kim_start(void *);
long st_kim_stop(void *);
-void st_kim_recv(void *, const unsigned char *, long count);
void st_kim_complete(void *);
void kim_st_list_protocols(struct st_data_s *, void *);
+void st_kim_recv(void *, const unsigned char *, long);
+
/*
* BTS headers
--
1.7.4.1
From: Pavan Savoy <[email protected]>
Be nice to CPU and don't hog the resources, use a nice wait_for_interruptible
timeout for completions instead of wait_for_timeout which is
non-interruptible.
Signed-off-by: Pavan Savoy <[email protected]>
---
drivers/misc/ti-st/st_kim.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 54ff644..0f36db3 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -207,8 +207,8 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
return -EIO;
}
- if (!wait_for_completion_timeout
- (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
+ if (!wait_for_completion_interruptible_timeout(
+ &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
pr_err(" waiting for ver info- timed out ");
return -ETIMEDOUT;
}
@@ -370,9 +370,9 @@ static long download_firmware(struct kim_data_s *kim_gdata)
break;
case ACTION_WAIT_EVENT: /* wait */
pr_debug("W");
- if (!wait_for_completion_timeout
- (&kim_gdata->kim_rcvd,
- msecs_to_jiffies(CMD_RESP_TIME))) {
+ if (!wait_for_completion_interruptible_timeout(
+ &kim_gdata->kim_rcvd,
+ msecs_to_jiffies(CMD_RESP_TIME))) {
pr_err("response timeout during fw download ");
/* timed out */
release_firmware(kim_gdata->fw_entry);
@@ -462,8 +462,8 @@ long st_kim_start(void *kim_data)
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
NULL, "install");
/* wait for ldisc to be installed */
- err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
- msecs_to_jiffies(LDISC_TIME));
+ err = wait_for_completion_interruptible_timeout(
+ &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
if (!err) {
/* ldisc installation timeout,
* flush uart, power cycle BT_EN */
@@ -520,8 +520,8 @@ long st_kim_stop(void *kim_data)
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
/* wait for ldisc to be un-installed */
- err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
- msecs_to_jiffies(LDISC_TIME));
+ err = wait_for_completion_interruptible_timeout(
+ &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
if (!err) { /* timeout */
pr_err(" timed out waiting for ldisc to be un-installed");
err = -ETIMEDOUT;
--
1.7.4.1