aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-09-10 08:58:59 -0400
committerTakashi Iwai <tiwai@suse.de>2014-09-15 09:52:38 -0400
commit3b73cfe5598eda7f5540608acd63b86688242731 (patch)
tree2f405e7c5eefdf3c17e069905548237ceca2155b
parent6336c20cdaee1dd13d01dfa8c07ce3b18bbc846f (diff)
ALSA: pdaudiocf: Use nonatomic PCM ops
Like other fixes, convert the tasklet to a threaded irq and replace spinlock with mutex appropriately. ak4117_lock remains as spinlock since it's called in another spinlock context from ak4117 driver. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c13
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h5
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c8
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_irq.c23
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c5
5 files changed, 29 insertions, 25 deletions
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 56bda124cd4a..07f4b33db3af 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -61,6 +61,7 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev);
61 61
62static void pdacf_release(struct pcmcia_device *link) 62static void pdacf_release(struct pcmcia_device *link)
63{ 63{
64 free_irq(link->irq, link->priv);
64 pcmcia_disable_device(link); 65 pcmcia_disable_device(link);
65} 66}
66 67
@@ -220,11 +221,13 @@ static int pdacf_config(struct pcmcia_device *link)
220 221
221 ret = pcmcia_request_io(link); 222 ret = pcmcia_request_io(link);
222 if (ret) 223 if (ret)
223 goto failed; 224 goto failed_preirq;
224 225
225 ret = pcmcia_request_irq(link, pdacf_interrupt); 226 ret = request_threaded_irq(link->irq, pdacf_interrupt,
227 pdacf_threaded_irq,
228 IRQF_SHARED, link->devname, link->priv);
226 if (ret) 229 if (ret)
227 goto failed; 230 goto failed_preirq;
228 231
229 ret = pcmcia_enable_device(link); 232 ret = pcmcia_enable_device(link);
230 if (ret) 233 if (ret)
@@ -236,7 +239,9 @@ static int pdacf_config(struct pcmcia_device *link)
236 239
237 return 0; 240 return 0;
238 241
239failed: 242 failed:
243 free_irq(link->irq, link->priv);
244failed_preirq:
240 pcmcia_disable_device(link); 245 pcmcia_disable_device(link);
241 return -ENODEV; 246 return -ENODEV;
242} 247}
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index ea41e57d7179..e9a7d3a784f7 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -88,10 +88,9 @@ struct snd_pdacf {
88 unsigned long port; 88 unsigned long port;
89 int irq; 89 int irq;
90 90
91 spinlock_t reg_lock; 91 struct mutex reg_lock;
92 unsigned short regmap[8]; 92 unsigned short regmap[8];
93 unsigned short suspend_reg_scr; 93 unsigned short suspend_reg_scr;
94 struct tasklet_struct tq;
95 94
96 spinlock_t ak4117_lock; 95 spinlock_t ak4117_lock;
97 struct ak4117 *ak4117; 96 struct ak4117 *ak4117;
@@ -136,7 +135,7 @@ int snd_pdacf_resume(struct snd_pdacf *chip);
136#endif 135#endif
137int snd_pdacf_pcm_new(struct snd_pdacf *chip); 136int snd_pdacf_pcm_new(struct snd_pdacf *chip);
138irqreturn_t pdacf_interrupt(int irq, void *dev); 137irqreturn_t pdacf_interrupt(int irq, void *dev);
139void pdacf_tasklet(unsigned long private_data); 138irqreturn_t pdacf_threaded_irq(int irq, void *dev);
140void pdacf_reinit(struct snd_pdacf *chip, int resume); 139void pdacf_reinit(struct snd_pdacf *chip, int resume);
141 140
142#endif /* __PDAUDIOCF_H */ 141#endif /* __PDAUDIOCF_H */
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index ea0adfb984ad..d724ab0653cf 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -162,9 +162,8 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
162 if (chip == NULL) 162 if (chip == NULL)
163 return NULL; 163 return NULL;
164 chip->card = card; 164 chip->card = card;
165 spin_lock_init(&chip->reg_lock); 165 mutex_init(&chip->reg_lock);
166 spin_lock_init(&chip->ak4117_lock); 166 spin_lock_init(&chip->ak4117_lock);
167 tasklet_init(&chip->tq, pdacf_tasklet, (unsigned long)chip);
168 card->private_data = chip; 167 card->private_data = chip;
169 168
170 pdacf_proc_init(chip); 169 pdacf_proc_init(chip);
@@ -174,19 +173,18 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
174static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1) 173static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1)
175{ 174{
176 struct snd_pdacf *chip = ak4117->change_callback_private; 175 struct snd_pdacf *chip = ak4117->change_callback_private;
177 unsigned long flags;
178 u16 val; 176 u16 val;
179 177
180 if (!(c0 & AK4117_UNLCK)) 178 if (!(c0 & AK4117_UNLCK))
181 return; 179 return;
182 spin_lock_irqsave(&chip->reg_lock, flags); 180 mutex_lock(&chip->reg_lock);
183 val = chip->regmap[PDAUDIOCF_REG_SCR>>1]; 181 val = chip->regmap[PDAUDIOCF_REG_SCR>>1];
184 if (ak4117->rcs0 & AK4117_UNLCK) 182 if (ak4117->rcs0 & AK4117_UNLCK)
185 val |= PDAUDIOCF_BLUE_LED_OFF; 183 val |= PDAUDIOCF_BLUE_LED_OFF;
186 else 184 else
187 val &= ~PDAUDIOCF_BLUE_LED_OFF; 185 val &= ~PDAUDIOCF_BLUE_LED_OFF;
188 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); 186 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
189 spin_unlock_irqrestore(&chip->reg_lock, flags); 187 mutex_unlock(&chip->reg_lock);
190} 188}
191 189
192int snd_pdacf_ak4117_create(struct snd_pdacf *chip) 190int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index dcd32201bc8c..ecf0fbd91794 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -30,6 +30,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
30{ 30{
31 struct snd_pdacf *chip = dev; 31 struct snd_pdacf *chip = dev;
32 unsigned short stat; 32 unsigned short stat;
33 bool wake_thread = false;
33 34
34 if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE| 35 if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
35 PDAUDIOCF_STAT_IS_CONFIGURED| 36 PDAUDIOCF_STAT_IS_CONFIGURED|
@@ -41,13 +42,13 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
41 if (stat & PDAUDIOCF_IRQOVR) /* should never happen */ 42 if (stat & PDAUDIOCF_IRQOVR) /* should never happen */
42 snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n"); 43 snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
43 if (chip->pcm_substream) 44 if (chip->pcm_substream)
44 tasklet_schedule(&chip->tq); 45 wake_thread = true;
45 if (!(stat & PDAUDIOCF_IRQAKM)) 46 if (!(stat & PDAUDIOCF_IRQAKM))
46 stat |= PDAUDIOCF_IRQAKM; /* check rate */ 47 stat |= PDAUDIOCF_IRQAKM; /* check rate */
47 } 48 }
48 if (get_irq_regs() != NULL) 49 if (get_irq_regs() != NULL)
49 snd_ak4117_check_rate_and_errors(chip->ak4117, 0); 50 snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
50 return IRQ_HANDLED; 51 return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
51} 52}
52 53
53static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) 54static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
@@ -256,16 +257,16 @@ static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned i
256 } 257 }
257} 258}
258 259
259void pdacf_tasklet(unsigned long private_data) 260irqreturn_t pdacf_threaded_irq(int irq, void *dev)
260{ 261{
261 struct snd_pdacf *chip = (struct snd_pdacf *) private_data; 262 struct snd_pdacf *chip = dev;
262 int size, off, cont, rdp, wdp; 263 int size, off, cont, rdp, wdp;
263 264
264 if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED) 265 if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
265 return; 266 return IRQ_HANDLED;
266 267
267 if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream)) 268 if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
268 return; 269 return IRQ_HANDLED;
269 270
270 rdp = inw(chip->port + PDAUDIOCF_REG_RDP); 271 rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
271 wdp = inw(chip->port + PDAUDIOCF_REG_WDP); 272 wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
@@ -311,15 +312,15 @@ void pdacf_tasklet(unsigned long private_data)
311 size -= cont; 312 size -= cont;
312 } 313 }
313#endif 314#endif
314 spin_lock(&chip->reg_lock); 315 mutex_lock(&chip->reg_lock);
315 while (chip->pcm_tdone >= chip->pcm_period) { 316 while (chip->pcm_tdone >= chip->pcm_period) {
316 chip->pcm_hwptr += chip->pcm_period; 317 chip->pcm_hwptr += chip->pcm_period;
317 chip->pcm_hwptr %= chip->pcm_size; 318 chip->pcm_hwptr %= chip->pcm_size;
318 chip->pcm_tdone -= chip->pcm_period; 319 chip->pcm_tdone -= chip->pcm_period;
319 spin_unlock(&chip->reg_lock); 320 mutex_unlock(&chip->reg_lock);
320 snd_pcm_period_elapsed(chip->pcm_substream); 321 snd_pcm_period_elapsed(chip->pcm_substream);
321 spin_lock(&chip->reg_lock); 322 mutex_lock(&chip->reg_lock);
322 } 323 }
323 spin_unlock(&chip->reg_lock); 324 mutex_unlock(&chip->reg_lock);
324 /* printk(KERN_DEBUG "TASKLET: end\n"); */ 325 return IRQ_HANDLED;
325} 326}
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
index 43f995a3f960..b48aa0a78c19 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -77,7 +77,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
77 default: 77 default:
78 return -EINVAL; 78 return -EINVAL;
79 } 79 }
80 spin_lock(&chip->reg_lock); 80 mutex_lock(&chip->reg_lock);
81 chip->pcm_running += inc; 81 chip->pcm_running += inc;
82 tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); 82 tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
83 if (chip->pcm_running) { 83 if (chip->pcm_running) {
@@ -91,7 +91,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
91 tmp |= val; 91 tmp |= val;
92 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); 92 pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp);
93 __end: 93 __end:
94 spin_unlock(&chip->reg_lock); 94 mutex_unlock(&chip->reg_lock);
95 snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); 95 snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE);
96 return ret; 96 return ret;
97} 97}
@@ -296,6 +296,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip)
296 296
297 pcm->private_data = chip; 297 pcm->private_data = chip;
298 pcm->info_flags = 0; 298 pcm->info_flags = 0;
299 pcm->nonatomic = true;
299 strcpy(pcm->name, chip->card->shortname); 300 strcpy(pcm->name, chip->card->shortname);
300 chip->pcm = pcm; 301 chip->pcm = pcm;
301 302