Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4a62573 authored by Sebastian Reichel's avatar Sebastian Reichel
Browse files

HSI: omap_ssi_port: switch to threaded pio irq



Move pio interrupt handler from tasklet into thread to
allow runtime_pm_get_sync calls without irq_safe being
set.

Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
Tested-by: default avatarPavel Machek <pavel@ucw.cz>
parent 927d3f8f
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ struct omap_ssm_ctx {
 * @irq: IRQ number
 * @wake_irq: IRQ number for incoming wake line (-1 if none)
 * @wake_gpio: GPIO number for incoming wake line (-1 if none)
 * @pio_tasklet: Bottom half for PIO transfers and events
 * @flags: flags to keep track of states
 * @wk_refcount: Reference count for output wake line
 * @work: worker for starting TX
@@ -100,7 +99,6 @@ struct omap_ssi_port {
	unsigned int		irq;
	int			wake_irq;
	struct gpio_desc	*wake_gpio;
	struct tasklet_struct	pio_tasklet;
	bool			wktest:1; /* FIXME: HACK to be removed */
	unsigned long		flags;
	unsigned int		wk_refcount;
+24 −36
Original line number Diff line number Diff line
@@ -877,7 +877,7 @@ static void ssi_pio_complete(struct hsi_port *port, struct list_head *queue)
	u32 reg;
	u32 val;

	spin_lock(&omap_port->lock);
	spin_lock_bh(&omap_port->lock);
	msg = list_first_entry(queue, struct hsi_msg, link);
	if ((!msg->sgt.nents) || (!msg->sgt.sgl->length)) {
		msg->actual_len = 0;
@@ -909,7 +909,7 @@ static void ssi_pio_complete(struct hsi_port *port, struct list_head *queue)
					(msg->ttype == HSI_MSG_WRITE))) {
			writel(val, omap_ssi->sys +
					SSI_MPU_STATUS_REG(port->num, 0));
			spin_unlock(&omap_port->lock);
			spin_unlock_bh(&omap_port->lock);

			return;
		}
@@ -925,12 +925,12 @@ static void ssi_pio_complete(struct hsi_port *port, struct list_head *queue)
	writel_relaxed(reg, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
	writel_relaxed(val, omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
	list_del(&msg->link);
	spin_unlock(&omap_port->lock);
	spin_unlock_bh(&omap_port->lock);
	msg->complete(msg);
	ssi_transfer(omap_port, queue);
}

static void ssi_pio_tasklet(unsigned long ssi_port)
static irqreturn_t ssi_pio_thread(int irq, void *ssi_port)
{
	struct hsi_port *port = (struct hsi_port *)ssi_port;
	struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
@@ -941,6 +941,8 @@ static void ssi_pio_tasklet(unsigned long ssi_port)
	u32 status_reg;

	pm_runtime_get_sync(omap_port->pdev);

	do {
		status_reg = readl(sys + SSI_MPU_STATUS_REG(port->num, 0));
		status_reg &= readl(sys + SSI_MPU_ENABLE_REG(port->num, 0));

@@ -957,21 +959,11 @@ static void ssi_pio_tasklet(unsigned long ssi_port)

		status_reg = readl(sys + SSI_MPU_STATUS_REG(port->num, 0));
		status_reg &= readl(sys + SSI_MPU_ENABLE_REG(port->num, 0));
	pm_runtime_put_sync(omap_port->pdev);

	if (status_reg)
		tasklet_hi_schedule(&omap_port->pio_tasklet);
	else
		enable_irq(omap_port->irq);
}

static irqreturn_t ssi_pio_isr(int irq, void *port)
{
	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);

	tasklet_hi_schedule(&omap_port->pio_tasklet);
	disable_irq_nosync(irq);
		/* TODO: sleep if we retry? */
	} while (status_reg);

	pm_runtime_put(omap_port->pdev);
	return IRQ_HANDLED;
}

@@ -1023,10 +1015,8 @@ static int ssi_port_irq(struct hsi_port *port, struct platform_device *pd)
		return err;
	}
	omap_port->irq = err;
	tasklet_init(&omap_port->pio_tasklet, ssi_pio_tasklet,
							(unsigned long)port);
	err = devm_request_irq(&port->device, omap_port->irq, ssi_pio_isr,
						0, "mpu_irq0", port);
	err = devm_request_threaded_irq(&port->device, omap_port->irq, NULL,
				ssi_pio_thread, IRQF_ONESHOT, "SSI PORT", port);
	if (err < 0)
		dev_err(&port->device, "Request IRQ %d failed (%d)\n",
							omap_port->irq, err);
@@ -1229,8 +1219,6 @@ static int ssi_port_remove(struct platform_device *pd)

	hsi_port_unregister_clients(port);

	tasklet_kill(&omap_port->pio_tasklet);

	port->async	= hsi_dummy_msg;
	port->setup	= hsi_dummy_cl;
	port->flush	= hsi_dummy_cl;