aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/ti-st
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/ti-st')
-rw-r--r--drivers/misc/ti-st/Kconfig2
-rw-r--r--drivers/misc/ti-st/st_core.c26
-rw-r--r--drivers/misc/ti-st/st_kim.c146
-rw-r--r--drivers/misc/ti-st/st_ll.c2
4 files changed, 99 insertions, 77 deletions
diff --git a/drivers/misc/ti-st/Kconfig b/drivers/misc/ti-st/Kconfig
index abb5de1afce..f34dcc51473 100644
--- a/drivers/misc/ti-st/Kconfig
+++ b/drivers/misc/ti-st/Kconfig
@@ -5,7 +5,7 @@
menu "Texas Instruments shared transport line discipline"
config TI_ST
tristate "Shared transport core driver"
- depends on NET && GPIOLIB
+ depends on NET && GPIOLIB && TTY
select FW_LOADER
help
This enables the shared transport core driver for TI
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 2b62232c2c6..1972d57aadb 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -22,7 +22,6 @@
#define pr_fmt(fmt) "(stc): " fmt
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/tty.h>
#include <linux/seq_file.h>
@@ -30,11 +29,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 +101,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 +141,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__);
@@ -238,7 +239,8 @@ void st_int_recv(void *disc_data,
char *ptr;
struct st_proto_s *proto;
unsigned short payload_len = 0;
- int len = 0, type = 0;
+ int len = 0;
+ unsigned char type = 0;
unsigned char *plen;
struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
unsigned long flags;
@@ -349,6 +351,11 @@ void st_int_recv(void *disc_data,
st_gdata->rx_skb = alloc_skb(
st_gdata->list[type]->max_frame_size,
GFP_ATOMIC);
+ if (st_gdata->rx_skb == NULL) {
+ pr_err("out of memory: dropping\n");
+ goto done;
+ }
+
skb_reserve(st_gdata->rx_skb,
st_gdata->list[type]->reserve);
/* next 2 required for BT only */
@@ -374,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;
@@ -396,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;
@@ -504,7 +511,6 @@ long st_register(struct st_proto_s *new_proto)
unsigned long flags = 0;
st_kim_ref(&st_gdata, 0);
- pr_info("%s(%d) ", __func__, new_proto->chnl_id);
if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
|| new_proto->reg_complete_cb == NULL) {
pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
@@ -555,7 +561,9 @@ long st_register(struct st_proto_s *new_proto)
if ((st_gdata->protos_registered != ST_EMPTY) &&
(test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
pr_err(" KIM failure complete callback ");
+ spin_lock_irqsave(&st_gdata->lock, flags);
st_reg_complete(st_gdata, err);
+ spin_unlock_irqrestore(&st_gdata->lock, flags);
clear_bit(ST_REG_PENDING, &st_gdata->st_state);
}
return -EINVAL;
@@ -803,7 +811,7 @@ static void st_tty_flush_buffer(struct tty_struct *tty)
kfree_skb(st_gdata->tx_skb);
st_gdata->tx_skb = NULL;
- tty->ops->flush_buffer(tty);
+ tty_driver_flush_buffer(tty);
return;
}
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index a7a861ceee2..9d3dbb28734 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -63,10 +63,27 @@ 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)) {
+ 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);
@@ -119,7 +136,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;
@@ -201,22 +218,25 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
pr_debug("%s", __func__);
- INIT_COMPLETION(kim_gdata->kim_rcvd);
+ reinit_completion(&kim_gdata->kim_rcvd);
if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) {
pr_err("kim: couldn't write 4 bytes");
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;
}
- INIT_COMPLETION(kim_gdata->kim_rcvd);
+ reinit_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;
@@ -236,7 +256,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;
@@ -342,7 +362,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
/* reinit completion before sending for the
* relevant wait
*/
- INIT_COMPLETION(kim_gdata->kim_rcvd);
+ reinit_completion(&kim_gdata->kim_rcvd);
/*
* Free space found in uart buffer, call st_int_write
@@ -370,15 +390,15 @@ 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);
return -ETIMEDOUT;
}
- INIT_COMPLETION(kim_gdata->kim_rcvd);
+ reinit_completion(&kim_gdata->kim_rcvd);
break;
case ACTION_DELAY: /* sleep */
pr_info("sleep command in scr");
@@ -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;
}
@@ -460,15 +474,15 @@ long st_kim_start(void *kim_data)
gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
mdelay(100);
/* re-initialize the completion */
- INIT_COMPLETION(kim_gdata->ldisc_installed);
+ reinit_completion(&kim_gdata->ldisc_installed);
/* send notification to UIM */
kim_gdata->ldisc_install = 1;
pr_info("ldisc_install = 1");
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 */
@@ -511,13 +525,12 @@ long st_kim_stop(void *kim_data)
kim_gdata->kim_pdev->dev.platform_data;
struct tty_struct *tty = kim_gdata->core_data->tty;
- INIT_COMPLETION(kim_gdata->ldisc_installed);
+ reinit_completion(&kim_gdata->ldisc_installed);
if (tty) { /* can be called before ldisc is installed */
/* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty);
tty_driver_flush_buffer(tty);
- tty->ops->flush_buffer(tty);
}
/* send uninstall notification to UIM */
@@ -526,11 +539,11 @@ 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");
- return -ETIMEDOUT;
+ err = -ETIMEDOUT;
}
/* By default configure BT nShutdown to LOW state */
@@ -666,7 +679,7 @@ void st_kim_ref(struct st_data_s **core_data, int id)
*core_data = NULL;
return;
}
- kim_gdata = dev_get_drvdata(&pdev->dev);
+ kim_gdata = platform_get_drvdata(pdev);
*core_data = kim_gdata->core_data;
}
@@ -701,12 +714,12 @@ 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;
struct kim_data_s *kim_gdata;
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
+ int err;
if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
/* multiple devices could exist */
@@ -721,29 +734,30 @@ static int kim_probe(struct platform_device *pdev)
pr_err("no mem to allocate");
return -ENOMEM;
}
- dev_set_drvdata(&pdev->dev, kim_gdata);
+ platform_set_drvdata(pdev, kim_gdata);
- status = st_core_init(&kim_gdata->core_data);
- if (status != 0) {
+ err = st_core_init(&kim_gdata->core_data);
+ if (err != 0) {
pr_err(" ST core init failed");
- return -EIO;
+ err = -EIO;
+ goto err_core_init;
}
/* 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)) {
+ err = gpio_request(kim_gdata->nshutdown, "kim");
+ if (unlikely(err)) {
pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
- return status;
+ return err;
}
/* Configure nShutdown GPIO as output=0 */
- status = gpio_direction_output(kim_gdata->nshutdown, 0);
- if (unlikely(status)) {
+ err = gpio_direction_output(kim_gdata->nshutdown, 0);
+ if (unlikely(err)) {
pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
- return status;
+ return err;
}
/* get reference of pdev for request_firmware
*/
@@ -751,10 +765,10 @@ static int kim_probe(struct platform_device *pdev)
init_completion(&kim_gdata->kim_rcvd);
init_completion(&kim_gdata->ldisc_installed);
- status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
- if (status) {
+ err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
+ if (err) {
pr_err("failed to create sysfs entries");
- return status;
+ goto err_sysfs_group;
}
/* copying platform data */
@@ -766,8 +780,8 @@ static int kim_probe(struct platform_device *pdev)
kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
if (IS_ERR(kim_debugfs_dir)) {
pr_err(" debugfs entries creation failed ");
- kim_debugfs_dir = NULL;
- return -EIO;
+ err = -EIO;
+ goto err_debugfs_dir;
}
debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
@@ -776,6 +790,17 @@ static int kim_probe(struct platform_device *pdev)
kim_gdata, &list_debugfs_fops);
pr_info(" debugfs entries created ");
return 0;
+
+err_debugfs_dir:
+ sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
+
+err_sysfs_group:
+ st_core_exit(kim_gdata->core_data);
+
+err_core_init:
+ kfree(kim_gdata);
+
+ return err;
}
static int kim_remove(struct platform_device *pdev)
@@ -784,7 +809,7 @@ static int kim_remove(struct platform_device *pdev)
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
struct kim_data_s *kim_gdata;
- kim_gdata = dev_get_drvdata(&pdev->dev);
+ kim_gdata = platform_get_drvdata(pdev);
/* Free the Bluetooth/FM/GPIO
* nShutdown gpio from the system
@@ -804,7 +829,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;
@@ -814,7 +839,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;
@@ -837,19 +862,8 @@ static struct platform_driver kim_platform_driver = {
},
};
-static int __init st_kim_init(void)
-{
- return platform_driver_register(&kim_platform_driver);
-}
-
-static void __exit st_kim_deinit(void)
-{
- platform_driver_unregister(&kim_platform_driver);
-}
-
+module_platform_driver(kim_platform_driver);
-module_init(st_kim_init);
-module_exit(st_kim_deinit);
MODULE_AUTHOR("Pavan Savoy <pavan_savoy@ti.com>");
MODULE_DESCRIPTION("Shared Transport Driver for TI BT/FM/GPS combo chips ");
MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
index 1ff460a8e9c..93b4d67cc4a 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);
}