diff options
| author | Sebastian Reichel <sre@kernel.org> | 2016-05-20 00:25:06 -0400 |
|---|---|---|
| committer | Sebastian Reichel <sre@kernel.org> | 2016-06-27 18:40:00 -0400 |
| commit | 4e552310cdf0c81210b5fc9173f7cf497eeb9feb (patch) | |
| tree | f9f4e8bdcbb87627e9a4431a55ef39f6d973adba | |
| parent | 604fdfa45886f04ad6070c1b8266c7f4154bc497 (diff) | |
HSI: omap_ssi: call msg->complete() from process context
msg->complete() should always be called from process context once
irq_safe runtime pm flag is no longer set for omap-ssi.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
| -rw-r--r-- | drivers/hsi/controllers/omap_ssi.h | 4 | ||||
| -rw-r--r-- | drivers/hsi/controllers/omap_ssi_core.c | 4 | ||||
| -rw-r--r-- | drivers/hsi/controllers/omap_ssi_port.c | 18 |
3 files changed, 25 insertions, 1 deletions
diff --git a/drivers/hsi/controllers/omap_ssi.h b/drivers/hsi/controllers/omap_ssi.h index 99143f4f8837..32ced0c8f789 100644 --- a/drivers/hsi/controllers/omap_ssi.h +++ b/drivers/hsi/controllers/omap_ssi.h | |||
| @@ -73,6 +73,8 @@ struct omap_ssm_ctx { | |||
| 73 | * @txqueue: TX message queues | 73 | * @txqueue: TX message queues |
| 74 | * @rxqueue: RX message queues | 74 | * @rxqueue: RX message queues |
| 75 | * @brkqueue: Queue of incoming HWBREAK requests (FRAME mode) | 75 | * @brkqueue: Queue of incoming HWBREAK requests (FRAME mode) |
| 76 | * @errqueue: Queue for failed messages | ||
| 77 | * @errqueue_work: Delayed Work for failed messages | ||
| 76 | * @irq: IRQ number | 78 | * @irq: IRQ number |
| 77 | * @wake_irq: IRQ number for incoming wake line (-1 if none) | 79 | * @wake_irq: IRQ number for incoming wake line (-1 if none) |
| 78 | * @wake_gpio: GPIO number for incoming wake line (-1 if none) | 80 | * @wake_gpio: GPIO number for incoming wake line (-1 if none) |
| @@ -96,6 +98,8 @@ struct omap_ssi_port { | |||
| 96 | struct list_head txqueue[SSI_MAX_CHANNELS]; | 98 | struct list_head txqueue[SSI_MAX_CHANNELS]; |
| 97 | struct list_head rxqueue[SSI_MAX_CHANNELS]; | 99 | struct list_head rxqueue[SSI_MAX_CHANNELS]; |
| 98 | struct list_head brkqueue; | 100 | struct list_head brkqueue; |
| 101 | struct list_head errqueue; | ||
| 102 | struct delayed_work errqueue_work; | ||
| 99 | unsigned int irq; | 103 | unsigned int irq; |
| 100 | int wake_irq; | 104 | int wake_irq; |
| 101 | struct gpio_desc *wake_gpio; | 105 | struct gpio_desc *wake_gpio; |
diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c index 79562ce65579..506a9f1ef7ad 100644 --- a/drivers/hsi/controllers/omap_ssi_core.c +++ b/drivers/hsi/controllers/omap_ssi_core.c | |||
| @@ -235,7 +235,9 @@ static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch) | |||
| 235 | spin_lock(&omap_port->lock); | 235 | spin_lock(&omap_port->lock); |
| 236 | list_del(&msg->link); /* Dequeue msg */ | 236 | list_del(&msg->link); /* Dequeue msg */ |
| 237 | spin_unlock(&omap_port->lock); | 237 | spin_unlock(&omap_port->lock); |
| 238 | msg->complete(msg); | 238 | |
| 239 | list_add_tail(&msg->link, &omap_port->errqueue); | ||
| 240 | schedule_delayed_work(&omap_port->errqueue_work, 0); | ||
| 239 | return; | 241 | return; |
| 240 | } | 242 | } |
| 241 | spin_lock(&omap_port->lock); | 243 | spin_lock(&omap_port->lock); |
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c index f91c6a4bb1a5..7717c769c4dd 100644 --- a/drivers/hsi/controllers/omap_ssi_port.c +++ b/drivers/hsi/controllers/omap_ssi_port.c | |||
| @@ -193,6 +193,21 @@ static int ssi_debug_add_port(struct omap_ssi_port *omap_port, | |||
| 193 | } | 193 | } |
| 194 | #endif | 194 | #endif |
| 195 | 195 | ||
| 196 | static void ssi_process_errqueue(struct work_struct *work) | ||
| 197 | { | ||
| 198 | struct omap_ssi_port *omap_port; | ||
| 199 | struct list_head *head, *tmp; | ||
| 200 | struct hsi_msg *msg; | ||
| 201 | |||
| 202 | omap_port = container_of(work, struct omap_ssi_port, errqueue_work.work); | ||
| 203 | |||
| 204 | list_for_each_safe(head, tmp, &omap_port->errqueue) { | ||
| 205 | msg = list_entry(head, struct hsi_msg, link); | ||
| 206 | msg->complete(msg); | ||
| 207 | list_del(head); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 196 | static int ssi_claim_lch(struct hsi_msg *msg) | 211 | static int ssi_claim_lch(struct hsi_msg *msg) |
| 197 | { | 212 | { |
| 198 | 213 | ||
| @@ -1170,6 +1185,7 @@ static int ssi_port_probe(struct platform_device *pd) | |||
| 1170 | omap_port->pdev = &pd->dev; | 1185 | omap_port->pdev = &pd->dev; |
| 1171 | omap_port->port_id = port_id; | 1186 | omap_port->port_id = port_id; |
| 1172 | 1187 | ||
| 1188 | INIT_DEFERRABLE_WORK(&omap_port->errqueue_work, ssi_process_errqueue); | ||
| 1173 | INIT_WORK(&omap_port->work, start_tx_work); | 1189 | INIT_WORK(&omap_port->work, start_tx_work); |
| 1174 | 1190 | ||
| 1175 | /* initialize HSI port */ | 1191 | /* initialize HSI port */ |
| @@ -1237,6 +1253,8 @@ static int ssi_port_remove(struct platform_device *pd) | |||
| 1237 | ssi_debug_remove_port(port); | 1253 | ssi_debug_remove_port(port); |
| 1238 | #endif | 1254 | #endif |
| 1239 | 1255 | ||
| 1256 | cancel_delayed_work_sync(&omap_port->errqueue_work); | ||
| 1257 | |||
| 1240 | hsi_port_unregister_clients(port); | 1258 | hsi_port_unregister_clients(port); |
| 1241 | 1259 | ||
| 1242 | port->async = hsi_dummy_msg; | 1260 | port->async = hsi_dummy_msg; |
