Skip to content

Commit 9fd00df

Browse files
Zbigniew Lukwinskialexandrebelloni
Zbigniew Lukwinski
authored andcommitted
i3c: master: handle IBIs in order they came
IBI shall be handled in order they appear on the bus. Otherwise could hit case when order of handling them in device driver will be different. It may lead to invalid assembling fragmented packets or events order broken. Added separate workqueue with option WQ_MEM_RECLAIM for each device driver. This ensures IBI handling order and improves IBI handling performance: IBI handlers for device B are not blocked by IBI handlers for device A. Original solution (single workqueue in main driver) was able to handle also general IBI (not related to specific device) like HJ or MR. So leaving this for such purposes. Signed-off-by: Zbigniew Lukwinski <zbigniew.lukwinski@linux.intel.com> Link: https://lore.kernel.org/r/20231015222334.1652401-2-zbigniew.lukwinski@linux.intel.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent b53e975 commit 9fd00df

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

drivers/i3c/master.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -2374,7 +2374,7 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
23742374
void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
23752375
{
23762376
atomic_inc(&dev->ibi->pending_ibis);
2377-
queue_work(dev->common.master->wq, &slot->work);
2377+
queue_work(dev->ibi->wq, &slot->work);
23782378
}
23792379
EXPORT_SYMBOL_GPL(i3c_master_queue_ibi);
23802380

@@ -2819,6 +2819,12 @@ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
28192819
if (!ibi)
28202820
return -ENOMEM;
28212821

2822+
ibi->wq = alloc_ordered_workqueue(dev_name(i3cdev_to_dev(dev->dev)), WQ_MEM_RECLAIM);
2823+
if (!ibi->wq) {
2824+
kfree(ibi);
2825+
return -ENOMEM;
2826+
}
2827+
28222828
atomic_set(&ibi->pending_ibis, 0);
28232829
init_completion(&ibi->all_ibis_handled);
28242830
ibi->handler = req->handler;
@@ -2846,6 +2852,12 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
28462852
WARN_ON(i3c_dev_disable_ibi_locked(dev));
28472853

28482854
master->ops->free_ibi(dev);
2855+
2856+
if (dev->ibi->wq) {
2857+
destroy_workqueue(dev->ibi->wq);
2858+
dev->ibi->wq = NULL;
2859+
}
2860+
28492861
kfree(dev->ibi);
28502862
dev->ibi = NULL;
28512863
}

include/linux/i3c/master.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct i3c_ibi_slot {
129129
* rejected by the master
130130
* @num_slots: number of IBI slots reserved for this device
131131
* @enabled: reflect the IBI status
132+
* @wq: workqueue used to execute IBI handlers.
132133
* @handler: IBI handler specified at i3c_device_request_ibi() call time. This
133134
* handler will be called from the controller workqueue, and as such
134135
* is allowed to sleep (though it is recommended to process the IBI
@@ -151,6 +152,7 @@ struct i3c_device_ibi_info {
151152
unsigned int max_payload_len;
152153
unsigned int num_slots;
153154
unsigned int enabled;
155+
struct workqueue_struct *wq;
154156
void (*handler)(struct i3c_device *dev,
155157
const struct i3c_ibi_payload *payload);
156158
};
@@ -469,7 +471,7 @@ struct i3c_master_controller_ops {
469471
* @boardinfo.i2c: list of I2C boardinfo objects
470472
* @boardinfo: board-level information attached to devices connected on the bus
471473
* @bus: I3C bus exposed by this master
472-
* @wq: workqueue used to execute IBI handlers. Can also be used by master
474+
* @wq: workqueue which can be used by master
473475
* drivers if they need to postpone operations that need to take place
474476
* in a thread context. Typical examples are Hot Join processing which
475477
* requires taking the bus lock in maintenance, which in turn, can only

0 commit comments

Comments
 (0)