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/controllers | |
| 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/controllers')
| -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; |
