diff options
author | Sebastian Reichel <sre@kernel.org> | 2016-04-30 11:11:54 -0400 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2016-06-27 18:38:47 -0400 |
commit | 2083057aacecbd79ed73670763f07e6e7c1acd66 (patch) | |
tree | 92608f1337e83e95c3ae3c60145e24b253d2b57f /drivers/hsi | |
parent | cb70e4c1bc96604953f5792f71ba9ba104705154 (diff) |
HSI: omap_ssi_port: replace wkin_cken with atomic bitmap operations
This simplifies the code and avoids holding a spin_lock when
runtime pm calls are made. Once the irq_safe flag is removed
for omap_ssi's runtime pm, pm_runtime_get/put_sync can sleep,
which is a no-go while holding a spin_lock.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
Diffstat (limited to 'drivers/hsi')
-rw-r--r-- | drivers/hsi/controllers/omap_ssi.h | 6 | ||||
-rw-r--r-- | drivers/hsi/controllers/omap_ssi_port.c | 16 |
2 files changed, 7 insertions, 15 deletions
diff --git a/drivers/hsi/controllers/omap_ssi.h b/drivers/hsi/controllers/omap_ssi.h index 88a523902a8f..6cdaad8805f7 100644 --- a/drivers/hsi/controllers/omap_ssi.h +++ b/drivers/hsi/controllers/omap_ssi.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #define SSI_MAX_GDD_LCH 8 | 35 | #define SSI_MAX_GDD_LCH 8 |
36 | #define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1) | 36 | #define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1) |
37 | 37 | ||
38 | #define SSI_WAKE_EN 0 | ||
39 | |||
38 | /** | 40 | /** |
39 | * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context | 41 | * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context |
40 | * @mode: Bit transmission mode | 42 | * @mode: Bit transmission mode |
@@ -75,7 +77,7 @@ struct omap_ssm_ctx { | |||
75 | * @wake_irq: IRQ number for incoming wake line (-1 if none) | 77 | * @wake_irq: IRQ number for incoming wake line (-1 if none) |
76 | * @wake_gpio: GPIO number for incoming wake line (-1 if none) | 78 | * @wake_gpio: GPIO number for incoming wake line (-1 if none) |
77 | * @pio_tasklet: Bottom half for PIO transfers and events | 79 | * @pio_tasklet: Bottom half for PIO transfers and events |
78 | * @wkin_cken: Keep track of clock references due to the incoming wake line | 80 | * @flags: flags to keep track of states |
79 | * @wk_refcount: Reference count for output wake line | 81 | * @wk_refcount: Reference count for output wake line |
80 | * @sys_mpu_enable: Context for the interrupt enable register for irq 0 | 82 | * @sys_mpu_enable: Context for the interrupt enable register for irq 0 |
81 | * @sst: Context for the synchronous serial transmitter | 83 | * @sst: Context for the synchronous serial transmitter |
@@ -99,7 +101,7 @@ struct omap_ssi_port { | |||
99 | struct gpio_desc *wake_gpio; | 101 | struct gpio_desc *wake_gpio; |
100 | struct tasklet_struct pio_tasklet; | 102 | struct tasklet_struct pio_tasklet; |
101 | bool wktest:1; /* FIXME: HACK to be removed */ | 103 | bool wktest:1; /* FIXME: HACK to be removed */ |
102 | bool wkin_cken:1; /* Workaround */ | 104 | unsigned long flags; |
103 | unsigned int wk_refcount; | 105 | unsigned int wk_refcount; |
104 | /* OMAP SSI port context */ | 106 | /* OMAP SSI port context */ |
105 | u32 sys_mpu_enable; /* We use only one irq */ | 107 | u32 sys_mpu_enable; /* We use only one irq */ |
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c index 9001b06312c3..0d3452393670 100644 --- a/drivers/hsi/controllers/omap_ssi_port.c +++ b/drivers/hsi/controllers/omap_ssi_port.c | |||
@@ -751,10 +751,8 @@ static int ssi_release(struct hsi_client *cl) | |||
751 | * Drop the clock reference for the incoming wake line | 751 | * Drop the clock reference for the incoming wake line |
752 | * if it is still kept high by the other side. | 752 | * if it is still kept high by the other side. |
753 | */ | 753 | */ |
754 | if (omap_port->wkin_cken) { | 754 | if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags)) |
755 | pm_runtime_put_sync(omap_port->pdev); | 755 | pm_runtime_put_sync(omap_port->pdev); |
756 | omap_port->wkin_cken = 0; | ||
757 | } | ||
758 | pm_runtime_get_sync(omap_port->pdev); | 756 | pm_runtime_get_sync(omap_port->pdev); |
759 | /* Stop any SSI TX/RX without a client */ | 757 | /* Stop any SSI TX/RX without a client */ |
760 | ssi_set_port_mode(omap_port, SSI_MODE_SLEEP); | 758 | ssi_set_port_mode(omap_port, SSI_MODE_SLEEP); |
@@ -981,12 +979,8 @@ static irqreturn_t ssi_wake_thread(int irq __maybe_unused, void *ssi_port) | |||
981 | * This workaround will avoid breaking the clock reference | 979 | * This workaround will avoid breaking the clock reference |
982 | * count when such a situation ocurrs. | 980 | * count when such a situation ocurrs. |
983 | */ | 981 | */ |
984 | spin_lock(&omap_port->lock); | 982 | if (!test_and_set_bit(SSI_WAKE_EN, &omap_port->flags)) |
985 | if (!omap_port->wkin_cken) { | ||
986 | omap_port->wkin_cken = 1; | ||
987 | pm_runtime_get_sync(omap_port->pdev); | 983 | pm_runtime_get_sync(omap_port->pdev); |
988 | } | ||
989 | spin_unlock(&omap_port->lock); | ||
990 | dev_dbg(&ssi->device, "Wake in high\n"); | 984 | dev_dbg(&ssi->device, "Wake in high\n"); |
991 | if (omap_port->wktest) { /* FIXME: HACK ! To be removed */ | 985 | if (omap_port->wktest) { /* FIXME: HACK ! To be removed */ |
992 | writel(SSI_WAKE(0), | 986 | writel(SSI_WAKE(0), |
@@ -1000,12 +994,8 @@ static irqreturn_t ssi_wake_thread(int irq __maybe_unused, void *ssi_port) | |||
1000 | omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); | 994 | omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); |
1001 | } | 995 | } |
1002 | hsi_event(port, HSI_EVENT_STOP_RX); | 996 | hsi_event(port, HSI_EVENT_STOP_RX); |
1003 | spin_lock(&omap_port->lock); | 997 | if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags)) |
1004 | if (omap_port->wkin_cken) { | ||
1005 | pm_runtime_put_sync(omap_port->pdev); | 998 | pm_runtime_put_sync(omap_port->pdev); |
1006 | omap_port->wkin_cken = 0; | ||
1007 | } | ||
1008 | spin_unlock(&omap_port->lock); | ||
1009 | } | 999 | } |
1010 | 1000 | ||
1011 | return IRQ_HANDLED; | 1001 | return IRQ_HANDLED; |