diff options
author | Shobek Sam Attupurath <sattupurath@nvidia.com> | 2013-10-24 14:07:03 +0530 |
---|---|---|
committer | Harry Hong <hhong@nvidia.com> | 2013-10-31 03:48:08 -0700 |
commit | db4316cda1b5d073da4572feb76524a155d44124 (patch) | |
tree | 5362732e4a6a5d9a45e325223249efc1a976277e /drivers | |
parent | 23af567e569a6f0259b9ad848671201555042c07 (diff) |
misc: ti-st: Create rx_list before all channels are registered
rx_list should be created before the channels are registered else when the
chip sends data after registering channel 4 we may encounter a crash.
Bug 1390113
Change-Id: Ieb1e0bbeda7845a156ee6636f233c79df36ba7db
Signed-off-by: Shobek Sam Attupurath <sattupurath@nvidia.com>
Reviewed-on: http://git-master/r/303251
Reviewed-by: Rakesh Goyal <rgoyal@nvidia.com>
Tested-by: Rakesh Goyal <rgoyal@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/ti-st/tty_hci.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/drivers/misc/ti-st/tty_hci.c b/drivers/misc/ti-st/tty_hci.c index 591b0be944ca..ab98515da3a2 100644 --- a/drivers/misc/ti-st/tty_hci.c +++ b/drivers/misc/ti-st/tty_hci.c @@ -142,8 +142,14 @@ int hci_tty_open(struct inode *inod, struct file *file) pr_info("inside %s (%p, %p)\n", __func__, inod, file); hst = kzalloc(sizeof(*hst), GFP_KERNEL); + + if (!hst) + return -ENOMEM; + file->private_data = hst; - hst = file->private_data; + + skb_queue_head_init(&hst->rx_list); + init_waitqueue_head(&hst->data_q); for (i = 0; i < MAX_BT_CHNL_IDS; i++) { ti_st_proto[i].priv_data = hst; @@ -161,12 +167,23 @@ int hci_tty_open(struct inode *inod, struct file *file) hst->reg_status = -EINPROGRESS; err = st_register(&ti_st_proto[i]); - if (!err) - goto done; + + if (!err) { + hst->st_write = ti_st_proto[i].write; + if (!hst->st_write) { + pr_err("undefined ST write function"); + err = -EIO; + goto error; + } + continue; + } if (err != -EINPROGRESS) { pr_err("st_register failed %d", err); - return err; + /* this channel is not registered - don't unregister */ + --i; + /*return err;*/ + goto error; } /* ST is busy with either protocol @@ -192,26 +209,18 @@ int hci_tty_open(struct inode *inod, struct file *file) return -EAGAIN; } -done: - hst->st_write = ti_st_proto[i].write; - if (!hst->st_write) { - pr_err("undefined ST write function"); - for (i = 0; i < MAX_BT_CHNL_IDS; i++) { - /* Undo registration with ST */ - err = st_unregister(&ti_st_proto[i]); - if (err) - pr_err("st_unregister() failed with " - "error %d", err); - hst->st_write = NULL; - } - return -EIO; - } } - skb_queue_head_init(&hst->rx_list); - init_waitqueue_head(&hst->data_q); - return 0; + +error: + while (i-- >= 0) + if (st_unregister(&ti_st_proto[i])) + pr_err("st_unregister() failed with "); + + kfree(hst); + + return err; } /** hci_tty_release Function |