forked from Minki/linux
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>
This commit is contained in:
parent
604fdfa458
commit
4e552310cd
@ -73,6 +73,8 @@ struct omap_ssm_ctx {
|
|||||||
* @txqueue: TX message queues
|
* @txqueue: TX message queues
|
||||||
* @rxqueue: RX message queues
|
* @rxqueue: RX message queues
|
||||||
* @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
|
* @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
|
||||||
|
* @errqueue: Queue for failed messages
|
||||||
|
* @errqueue_work: Delayed Work for failed messages
|
||||||
* @irq: IRQ number
|
* @irq: IRQ number
|
||||||
* @wake_irq: IRQ number for incoming wake line (-1 if none)
|
* @wake_irq: IRQ number for incoming wake line (-1 if none)
|
||||||
* @wake_gpio: GPIO number for incoming wake line (-1 if none)
|
* @wake_gpio: GPIO number for incoming wake line (-1 if none)
|
||||||
@ -96,6 +98,8 @@ struct omap_ssi_port {
|
|||||||
struct list_head txqueue[SSI_MAX_CHANNELS];
|
struct list_head txqueue[SSI_MAX_CHANNELS];
|
||||||
struct list_head rxqueue[SSI_MAX_CHANNELS];
|
struct list_head rxqueue[SSI_MAX_CHANNELS];
|
||||||
struct list_head brkqueue;
|
struct list_head brkqueue;
|
||||||
|
struct list_head errqueue;
|
||||||
|
struct delayed_work errqueue_work;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
int wake_irq;
|
int wake_irq;
|
||||||
struct gpio_desc *wake_gpio;
|
struct gpio_desc *wake_gpio;
|
||||||
|
@ -235,7 +235,9 @@ static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
|
|||||||
spin_lock(&omap_port->lock);
|
spin_lock(&omap_port->lock);
|
||||||
list_del(&msg->link); /* Dequeue msg */
|
list_del(&msg->link); /* Dequeue msg */
|
||||||
spin_unlock(&omap_port->lock);
|
spin_unlock(&omap_port->lock);
|
||||||
msg->complete(msg);
|
|
||||||
|
list_add_tail(&msg->link, &omap_port->errqueue);
|
||||||
|
schedule_delayed_work(&omap_port->errqueue_work, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
spin_lock(&omap_port->lock);
|
spin_lock(&omap_port->lock);
|
||||||
|
@ -193,6 +193,21 @@ static int ssi_debug_add_port(struct omap_ssi_port *omap_port,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void ssi_process_errqueue(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct omap_ssi_port *omap_port;
|
||||||
|
struct list_head *head, *tmp;
|
||||||
|
struct hsi_msg *msg;
|
||||||
|
|
||||||
|
omap_port = container_of(work, struct omap_ssi_port, errqueue_work.work);
|
||||||
|
|
||||||
|
list_for_each_safe(head, tmp, &omap_port->errqueue) {
|
||||||
|
msg = list_entry(head, struct hsi_msg, link);
|
||||||
|
msg->complete(msg);
|
||||||
|
list_del(head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int ssi_claim_lch(struct hsi_msg *msg)
|
static int ssi_claim_lch(struct hsi_msg *msg)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1170,6 +1185,7 @@ static int ssi_port_probe(struct platform_device *pd)
|
|||||||
omap_port->pdev = &pd->dev;
|
omap_port->pdev = &pd->dev;
|
||||||
omap_port->port_id = port_id;
|
omap_port->port_id = port_id;
|
||||||
|
|
||||||
|
INIT_DEFERRABLE_WORK(&omap_port->errqueue_work, ssi_process_errqueue);
|
||||||
INIT_WORK(&omap_port->work, start_tx_work);
|
INIT_WORK(&omap_port->work, start_tx_work);
|
||||||
|
|
||||||
/* initialize HSI port */
|
/* initialize HSI port */
|
||||||
@ -1237,6 +1253,8 @@ static int ssi_port_remove(struct platform_device *pd)
|
|||||||
ssi_debug_remove_port(port);
|
ssi_debug_remove_port(port);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&omap_port->errqueue_work);
|
||||||
|
|
||||||
hsi_port_unregister_clients(port);
|
hsi_port_unregister_clients(port);
|
||||||
|
|
||||||
port->async = hsi_dummy_msg;
|
port->async = hsi_dummy_msg;
|
||||||
|
Loading…
Reference in New Issue
Block a user