aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2016-11-16 15:51:28 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-11-17 10:37:49 -0500
commitc110cdb171488c60295d49fda16634cfec58ae28 (patch)
treef3edd6897111ed220fcd73358b3aa293d721f788 /drivers/misc
parentbd47b5269dbb316211fee18c706d015adbf1d696 (diff)
mei: bus: make a client pointer always available
Change life time of the client pointer, allocate it upon client device creation and free it upon device destruction, instead of upon connection and disconnection. This helps to eliminate racy NULL checks in the bus code. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/bus.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 7c075e9b25e5..483587f60249 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -187,9 +187,6 @@ ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
187{ 187{
188 struct mei_cl *cl = cldev->cl; 188 struct mei_cl *cl = cldev->cl;
189 189
190 if (cl == NULL)
191 return -ENODEV;
192
193 return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING); 190 return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
194} 191}
195EXPORT_SYMBOL_GPL(mei_cldev_send); 192EXPORT_SYMBOL_GPL(mei_cldev_send);
@@ -207,9 +204,6 @@ ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
207{ 204{
208 struct mei_cl *cl = cldev->cl; 205 struct mei_cl *cl = cldev->cl;
209 206
210 if (cl == NULL)
211 return -ENODEV;
212
213 return __mei_cl_recv(cl, buf, length); 207 return __mei_cl_recv(cl, buf, length);
214} 208}
215EXPORT_SYMBOL_GPL(mei_cldev_recv); 209EXPORT_SYMBOL_GPL(mei_cldev_recv);
@@ -403,7 +397,7 @@ EXPORT_SYMBOL_GPL(mei_cldev_ver);
403 */ 397 */
404bool mei_cldev_enabled(struct mei_cl_device *cldev) 398bool mei_cldev_enabled(struct mei_cl_device *cldev)
405{ 399{
406 return cldev->cl && mei_cl_is_connected(cldev->cl); 400 return mei_cl_is_connected(cldev->cl);
407} 401}
408EXPORT_SYMBOL_GPL(mei_cldev_enabled); 402EXPORT_SYMBOL_GPL(mei_cldev_enabled);
409 403
@@ -423,14 +417,13 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
423 417
424 cl = cldev->cl; 418 cl = cldev->cl;
425 419
426 if (!cl) { 420 if (cl->state == MEI_FILE_UNINITIALIZED) {
427 mutex_lock(&bus->device_lock); 421 mutex_lock(&bus->device_lock);
428 cl = mei_cl_alloc_linked(bus); 422 ret = mei_cl_link(cl);
429 mutex_unlock(&bus->device_lock); 423 mutex_unlock(&bus->device_lock);
430 if (IS_ERR(cl)) 424 if (ret)
431 return PTR_ERR(cl); 425 return ret;
432 /* update pointers */ 426 /* update pointers */
433 cldev->cl = cl;
434 cl->cldev = cldev; 427 cl->cldev = cldev;
435 } 428 }
436 429
@@ -471,7 +464,7 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
471 struct mei_cl *cl; 464 struct mei_cl *cl;
472 int err; 465 int err;
473 466
474 if (!cldev || !cldev->cl) 467 if (!cldev)
475 return -ENODEV; 468 return -ENODEV;
476 469
477 cl = cldev->cl; 470 cl = cldev->cl;
@@ -497,9 +490,6 @@ out:
497 mei_cl_flush_queues(cl, NULL); 490 mei_cl_flush_queues(cl, NULL);
498 mei_cl_unlink(cl); 491 mei_cl_unlink(cl);
499 492
500 kfree(cl);
501 cldev->cl = NULL;
502
503 mutex_unlock(&bus->device_lock); 493 mutex_unlock(&bus->device_lock);
504 return err; 494 return err;
505} 495}
@@ -754,6 +744,7 @@ static void mei_cl_bus_dev_release(struct device *dev)
754 744
755 mei_me_cl_put(cldev->me_cl); 745 mei_me_cl_put(cldev->me_cl);
756 mei_dev_bus_put(cldev->bus); 746 mei_dev_bus_put(cldev->bus);
747 kfree(cldev->cl);
757 kfree(cldev); 748 kfree(cldev);
758} 749}
759 750
@@ -786,17 +777,25 @@ static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
786 struct mei_me_client *me_cl) 777 struct mei_me_client *me_cl)
787{ 778{
788 struct mei_cl_device *cldev; 779 struct mei_cl_device *cldev;
780 struct mei_cl *cl;
789 781
790 cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL); 782 cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
791 if (!cldev) 783 if (!cldev)
792 return NULL; 784 return NULL;
793 785
786 cl = mei_cl_allocate(bus);
787 if (!cl) {
788 kfree(cldev);
789 return NULL;
790 }
791
794 device_initialize(&cldev->dev); 792 device_initialize(&cldev->dev);
795 cldev->dev.parent = bus->dev; 793 cldev->dev.parent = bus->dev;
796 cldev->dev.bus = &mei_cl_bus_type; 794 cldev->dev.bus = &mei_cl_bus_type;
797 cldev->dev.type = &mei_cl_device_type; 795 cldev->dev.type = &mei_cl_device_type;
798 cldev->bus = mei_dev_bus_get(bus); 796 cldev->bus = mei_dev_bus_get(bus);
799 cldev->me_cl = mei_me_cl_get(me_cl); 797 cldev->me_cl = mei_me_cl_get(me_cl);
798 cldev->cl = cl;
800 mei_cl_bus_set_name(cldev); 799 mei_cl_bus_set_name(cldev);
801 cldev->is_added = 0; 800 cldev->is_added = 0;
802 INIT_LIST_HEAD(&cldev->bus_list); 801 INIT_LIST_HEAD(&cldev->bus_list);