mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-13 14:14:37 +00:00
Merge branch 'topic/ctxfi' into for-linus
* topic/ctxfi: ALSA: ctxfi - Fix deadlock with xfi-timer ALSA: ctxfi - Replace atc lock to mutex
This commit is contained in:
commit
3d2aa66dda
3 changed files with 21 additions and 23 deletions
|
@ -259,7 +259,6 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
int n_amixer = apcm->substream->runtime->channels, i = 0;
|
int n_amixer = apcm->substream->runtime->channels, i = 0;
|
||||||
int device = apcm->substream->pcm->device;
|
int device = apcm->substream->pcm->device;
|
||||||
unsigned int pitch;
|
unsigned int pitch;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (NULL != apcm->src) {
|
if (NULL != apcm->src) {
|
||||||
/* Prepared pcm playback */
|
/* Prepared pcm playback */
|
||||||
|
@ -311,10 +310,10 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
src = apcm->src;
|
src = apcm->src;
|
||||||
for (i = 0; i < n_amixer; i++) {
|
for (i = 0; i < n_amixer; i++) {
|
||||||
amixer = apcm->amixers[i];
|
amixer = apcm->amixers[i];
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
amixer->ops->setup(amixer, &src->rsc,
|
amixer->ops->setup(amixer, &src->rsc,
|
||||||
INIT_VOL, atc->pcm[i+device*2]);
|
INIT_VOL, atc->pcm[i+device*2]);
|
||||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
mutex_unlock(&atc->atc_mutex);
|
||||||
src = src->ops->next_interleave(src);
|
src = src->ops->next_interleave(src);
|
||||||
if (NULL == src)
|
if (NULL == src)
|
||||||
src = apcm->src;
|
src = apcm->src;
|
||||||
|
@ -865,7 +864,6 @@ static int
|
||||||
spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
{
|
{
|
||||||
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||||
unsigned long flags;
|
|
||||||
unsigned int rate = apcm->substream->runtime->rate;
|
unsigned int rate = apcm->substream->runtime->rate;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
int err;
|
int err;
|
||||||
|
@ -885,7 +883,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
dao->ops->get_spos(dao, &status);
|
dao->ops->get_spos(dao, &status);
|
||||||
if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
|
if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
|
||||||
status &= ((~IEC958_AES3_CON_FS) << 24);
|
status &= ((~IEC958_AES3_CON_FS) << 24);
|
||||||
|
@ -895,7 +893,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
}
|
}
|
||||||
if ((rate != atc->pll_rate) && (32000 != rate))
|
if ((rate != atc->pll_rate) && (32000 != rate))
|
||||||
err = atc_pll_init(atc, rate);
|
err = atc_pll_init(atc, rate);
|
||||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
mutex_unlock(&atc->atc_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -908,7 +906,6 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
struct dao *dao;
|
struct dao *dao;
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (NULL != apcm->src)
|
if (NULL != apcm->src)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -934,13 +931,13 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
|
||||||
src = apcm->src;
|
src = apcm->src;
|
||||||
}
|
}
|
||||||
/* Connect to SPDIFOO */
|
/* Connect to SPDIFOO */
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||||
amixer = apcm->amixers[0];
|
amixer = apcm->amixers[0];
|
||||||
dao->ops->set_left_input(dao, &amixer->rsc);
|
dao->ops->set_left_input(dao, &amixer->rsc);
|
||||||
amixer = apcm->amixers[1];
|
amixer = apcm->amixers[1];
|
||||||
dao->ops->set_right_input(dao, &amixer->rsc);
|
dao->ops->set_right_input(dao, &amixer->rsc);
|
||||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
mutex_unlock(&atc->atc_mutex);
|
||||||
|
|
||||||
ct_timer_prepare(apcm->timer);
|
ct_timer_prepare(apcm->timer);
|
||||||
|
|
||||||
|
@ -1088,7 +1085,6 @@ static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status)
|
||||||
|
|
||||||
static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
struct dao_desc da_dsc = {0};
|
struct dao_desc da_dsc = {0};
|
||||||
struct dao *dao;
|
struct dao *dao;
|
||||||
int err;
|
int err;
|
||||||
|
@ -1096,7 +1092,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
||||||
struct rsc *rscs[2] = {NULL};
|
struct rsc *rscs[2] = {NULL};
|
||||||
unsigned int spos = 0;
|
unsigned int spos = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&atc->atc_lock, flags);
|
mutex_lock(&atc->atc_mutex);
|
||||||
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
dao = container_of(atc->daios[SPDIFOO], struct dao, daio);
|
||||||
da_dsc.msr = state ? 1 : atc->msr;
|
da_dsc.msr = state ? 1 : atc->msr;
|
||||||
da_dsc.passthru = state ? 1 : 0;
|
da_dsc.passthru = state ? 1 : 0;
|
||||||
|
@ -1114,7 +1110,7 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state)
|
||||||
}
|
}
|
||||||
dao->ops->set_spos(dao, spos);
|
dao->ops->set_spos(dao, spos);
|
||||||
dao->ops->commit_write(dao);
|
dao->ops->commit_write(dao);
|
||||||
spin_unlock_irqrestore(&atc->atc_lock, flags);
|
mutex_unlock(&atc->atc_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1572,7 +1568,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
|
||||||
atc->msr = msr;
|
atc->msr = msr;
|
||||||
atc->chip_type = chip_type;
|
atc->chip_type = chip_type;
|
||||||
|
|
||||||
spin_lock_init(&atc->atc_lock);
|
mutex_init(&atc->atc_mutex);
|
||||||
|
|
||||||
/* Find card model */
|
/* Find card model */
|
||||||
err = atc_identify_card(atc);
|
err = atc_identify_card(atc);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#define CTATC_H
|
#define CTATC_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/spinlock_types.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
|
@ -90,7 +90,7 @@ struct ct_atc {
|
||||||
void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
|
||||||
unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
|
unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index);
|
||||||
|
|
||||||
spinlock_t atc_lock;
|
struct mutex atc_mutex;
|
||||||
|
|
||||||
int (*pcm_playback_prepare)(struct ct_atc *atc,
|
int (*pcm_playback_prepare)(struct ct_atc *atc,
|
||||||
struct ct_atc_pcm *apcm);
|
struct ct_atc_pcm *apcm);
|
||||||
|
|
|
@ -180,7 +180,7 @@ static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer)
|
||||||
*
|
*
|
||||||
* call this inside the lock and irq disabled
|
* call this inside the lock and irq disabled
|
||||||
*/
|
*/
|
||||||
static int ct_xfitimer_reprogram(struct ct_timer *atimer)
|
static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update)
|
||||||
{
|
{
|
||||||
struct ct_timer_instance *ti;
|
struct ct_timer_instance *ti;
|
||||||
unsigned int min_intr = (unsigned int)-1;
|
unsigned int min_intr = (unsigned int)-1;
|
||||||
|
@ -216,6 +216,8 @@ static int ct_xfitimer_reprogram(struct ct_timer *atimer)
|
||||||
ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ +
|
ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ +
|
||||||
rate - 1, rate);
|
rate - 1, rate);
|
||||||
}
|
}
|
||||||
|
if (ti->need_update && !can_update)
|
||||||
|
min_intr = 0; /* pending to the next irq */
|
||||||
if (ti->frag_count < min_intr)
|
if (ti->frag_count < min_intr)
|
||||||
min_intr = ti->frag_count;
|
min_intr = ti->frag_count;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +237,7 @@ static void ct_xfitimer_check_period(struct ct_timer *atimer)
|
||||||
|
|
||||||
spin_lock_irqsave(&atimer->list_lock, flags);
|
spin_lock_irqsave(&atimer->list_lock, flags);
|
||||||
list_for_each_entry(ti, &atimer->instance_head, instance_list) {
|
list_for_each_entry(ti, &atimer->instance_head, instance_list) {
|
||||||
if (ti->need_update) {
|
if (ti->running && ti->need_update) {
|
||||||
ti->need_update = 0;
|
ti->need_update = 0;
|
||||||
ti->apcm->interrupt(ti->apcm);
|
ti->apcm->interrupt(ti->apcm);
|
||||||
}
|
}
|
||||||
|
@ -252,7 +254,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
|
||||||
spin_lock_irqsave(&atimer->lock, flags);
|
spin_lock_irqsave(&atimer->lock, flags);
|
||||||
atimer->irq_handling = 1;
|
atimer->irq_handling = 1;
|
||||||
do {
|
do {
|
||||||
update = ct_xfitimer_reprogram(atimer);
|
update = ct_xfitimer_reprogram(atimer, 1);
|
||||||
spin_unlock(&atimer->lock);
|
spin_unlock(&atimer->lock);
|
||||||
if (update)
|
if (update)
|
||||||
ct_xfitimer_check_period(atimer);
|
ct_xfitimer_check_period(atimer);
|
||||||
|
@ -265,6 +267,7 @@ static void ct_xfitimer_callback(struct ct_timer *atimer)
|
||||||
static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
|
static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
|
||||||
{
|
{
|
||||||
ti->frag_count = ti->substream->runtime->period_size;
|
ti->frag_count = ti->substream->runtime->period_size;
|
||||||
|
ti->running = 0;
|
||||||
ti->need_update = 0;
|
ti->need_update = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +276,6 @@ static void ct_xfitimer_prepare(struct ct_timer_instance *ti)
|
||||||
static void ct_xfitimer_update(struct ct_timer *atimer)
|
static void ct_xfitimer_update(struct ct_timer *atimer)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int update;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&atimer->lock, flags);
|
spin_lock_irqsave(&atimer->lock, flags);
|
||||||
if (atimer->irq_handling) {
|
if (atimer->irq_handling) {
|
||||||
|
@ -284,10 +286,8 @@ static void ct_xfitimer_update(struct ct_timer *atimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
ct_xfitimer_irq_stop(atimer);
|
ct_xfitimer_irq_stop(atimer);
|
||||||
update = ct_xfitimer_reprogram(atimer);
|
ct_xfitimer_reprogram(atimer, 0);
|
||||||
spin_unlock_irqrestore(&atimer->lock, flags);
|
spin_unlock_irqrestore(&atimer->lock, flags);
|
||||||
if (update)
|
|
||||||
ct_xfitimer_check_period(atimer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ct_xfitimer_start(struct ct_timer_instance *ti)
|
static void ct_xfitimer_start(struct ct_timer_instance *ti)
|
||||||
|
@ -298,6 +298,8 @@ static void ct_xfitimer_start(struct ct_timer_instance *ti)
|
||||||
spin_lock_irqsave(&atimer->lock, flags);
|
spin_lock_irqsave(&atimer->lock, flags);
|
||||||
if (list_empty(&ti->running_list))
|
if (list_empty(&ti->running_list))
|
||||||
atimer->wc = ct_xfitimer_get_wc(atimer);
|
atimer->wc = ct_xfitimer_get_wc(atimer);
|
||||||
|
ti->running = 1;
|
||||||
|
ti->need_update = 0;
|
||||||
list_add(&ti->running_list, &atimer->running_head);
|
list_add(&ti->running_list, &atimer->running_head);
|
||||||
spin_unlock_irqrestore(&atimer->lock, flags);
|
spin_unlock_irqrestore(&atimer->lock, flags);
|
||||||
ct_xfitimer_update(atimer);
|
ct_xfitimer_update(atimer);
|
||||||
|
@ -310,7 +312,7 @@ static void ct_xfitimer_stop(struct ct_timer_instance *ti)
|
||||||
|
|
||||||
spin_lock_irqsave(&atimer->lock, flags);
|
spin_lock_irqsave(&atimer->lock, flags);
|
||||||
list_del_init(&ti->running_list);
|
list_del_init(&ti->running_list);
|
||||||
ti->need_update = 0;
|
ti->running = 0;
|
||||||
spin_unlock_irqrestore(&atimer->lock, flags);
|
spin_unlock_irqrestore(&atimer->lock, flags);
|
||||||
ct_xfitimer_update(atimer);
|
ct_xfitimer_update(atimer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue