Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+7 -15
+4 -2
drivers/hsi/controllers/omap_ssi.h
··· 35 35 #define SSI_MAX_GDD_LCH 8 36 36 #define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1) 37 37 38 + #define SSI_WAKE_EN 0 39 + 38 40 /** 39 41 * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context 40 42 * @mode: Bit transmission mode ··· 77 75 * @wake_irq: IRQ number for incoming wake line (-1 if none) 78 76 * @wake_gpio: GPIO number for incoming wake line (-1 if none) 79 77 * @pio_tasklet: Bottom half for PIO transfers and events 80 - * @wkin_cken: Keep track of clock references due to the incoming wake line 78 + * @flags: flags to keep track of states 81 79 * @wk_refcount: Reference count for output wake line 82 80 * @sys_mpu_enable: Context for the interrupt enable register for irq 0 83 81 * @sst: Context for the synchronous serial transmitter ··· 101 99 struct gpio_desc *wake_gpio; 102 100 struct tasklet_struct pio_tasklet; 103 101 bool wktest:1; /* FIXME: HACK to be removed */ 104 - bool wkin_cken:1; /* Workaround */ 102 + unsigned long flags; 105 103 unsigned int wk_refcount; 106 104 /* OMAP SSI port context */ 107 105 u32 sys_mpu_enable; /* We use only one irq */
+3 -13
drivers/hsi/controllers/omap_ssi_port.c
··· 751 751 * Drop the clock reference for the incoming wake line 752 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 755 pm_runtime_put_sync(omap_port->pdev); 756 - omap_port->wkin_cken = 0; 757 - } 758 756 pm_runtime_get_sync(omap_port->pdev); 759 757 /* Stop any SSI TX/RX without a client */ 760 758 ssi_set_port_mode(omap_port, SSI_MODE_SLEEP); ··· 979 981 * This workaround will avoid breaking the clock reference 980 982 * count when such a situation ocurrs. 981 983 */ 982 - spin_lock(&omap_port->lock); 983 - if (!omap_port->wkin_cken) { 984 - omap_port->wkin_cken = 1; 984 + if (!test_and_set_bit(SSI_WAKE_EN, &omap_port->flags)) 985 985 pm_runtime_get_sync(omap_port->pdev); 986 - } 987 - spin_unlock(&omap_port->lock); 988 986 dev_dbg(&ssi->device, "Wake in high\n"); 989 987 if (omap_port->wktest) { /* FIXME: HACK ! To be removed */ 990 988 writel(SSI_WAKE(0), ··· 994 1000 omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num)); 995 1001 } 996 1002 hsi_event(port, HSI_EVENT_STOP_RX); 997 - spin_lock(&omap_port->lock); 998 - if (omap_port->wkin_cken) { 1003 + if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags)) 999 1004 pm_runtime_put_sync(omap_port->pdev); 1000 - omap_port->wkin_cken = 0; 1001 - } 1002 - spin_unlock(&omap_port->lock); 1003 1005 } 1004 1006 1005 1007 return IRQ_HANDLED;