forked from Minki/linux
firmware: arm_scmi: Fix deferred_tx_wq release on error paths
Use devres to allocate the dedicated deferred_tx_wq polling workqueue so
as to automatically trigger the proper resource release on error path.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: 5a3b7185c4
("firmware: arm_scmi: Add atomic mode support to virtio transport")
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Link: https://lore.kernel.org/r/20221028140833.280091-6-cristian.marussi@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
This commit is contained in:
parent
5ffc1c4cb8
commit
1eff6929af
@ -148,7 +148,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
|
||||
{
|
||||
unsigned long flags;
|
||||
DECLARE_COMPLETION_ONSTACK(vioch_shutdown_done);
|
||||
void *deferred_wq = NULL;
|
||||
|
||||
/*
|
||||
* Prepare to wait for the last release if not already released
|
||||
@ -162,16 +161,11 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
|
||||
|
||||
vioch->shutdown_done = &vioch_shutdown_done;
|
||||
virtio_break_device(vioch->vqueue->vdev);
|
||||
if (!vioch->is_rx && vioch->deferred_tx_wq) {
|
||||
deferred_wq = vioch->deferred_tx_wq;
|
||||
if (!vioch->is_rx && vioch->deferred_tx_wq)
|
||||
/* Cannot be kicked anymore after this...*/
|
||||
vioch->deferred_tx_wq = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&vioch->lock, flags);
|
||||
|
||||
if (deferred_wq)
|
||||
destroy_workqueue(deferred_wq);
|
||||
|
||||
scmi_vio_channel_release(vioch);
|
||||
|
||||
/* Let any possibly concurrent RX path release the channel */
|
||||
@ -416,6 +410,11 @@ static bool virtio_chan_available(struct device *dev, int idx)
|
||||
return vioch && !vioch->cinfo;
|
||||
}
|
||||
|
||||
static void scmi_destroy_tx_workqueue(void *deferred_tx_wq)
|
||||
{
|
||||
destroy_workqueue(deferred_tx_wq);
|
||||
}
|
||||
|
||||
static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
bool tx)
|
||||
{
|
||||
@ -430,6 +429,8 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
|
||||
/* Setup a deferred worker for polling. */
|
||||
if (tx && !vioch->deferred_tx_wq) {
|
||||
int ret;
|
||||
|
||||
vioch->deferred_tx_wq =
|
||||
alloc_workqueue(dev_name(&scmi_vdev->dev),
|
||||
WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS,
|
||||
@ -437,6 +438,11 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
|
||||
if (!vioch->deferred_tx_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, scmi_destroy_tx_workqueue,
|
||||
vioch->deferred_tx_wq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
INIT_WORK(&vioch->deferred_tx_work,
|
||||
scmi_vio_deferred_tx_worker);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user