summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/pci/mixart/mixart.c17
-rw-r--r--sound/pci/mixart/mixart.h10
-rw-r--r--sound/pci/mixart/mixart_core.c79
-rw-r--r--sound/pci/mixart/mixart_core.h2
4 files changed, 44 insertions, 64 deletions
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 75fc342cff2a..1faf47e81570 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -986,6 +986,7 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, name);
preallocate_buffers(chip, pcm);
@@ -1018,6 +1019,7 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, name);
preallocate_buffers(chip, pcm);
@@ -1303,8 +1305,9 @@ static int snd_mixart_probe(struct pci_dev *pci,
}
}
- if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, mgr)) {
+ if (request_threaded_irq(pci->irq, snd_mixart_interrupt,
+ snd_mixart_threaded_irq, IRQF_SHARED,
+ KBUILD_MODNAME, mgr)) {
dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
snd_mixart_free(mgr);
return -EBUSY;
@@ -1314,24 +1317,18 @@ static int snd_mixart_probe(struct pci_dev *pci,
sprintf(mgr->shortname, "Digigram miXart");
sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
- /* ISR spinlock */
- spin_lock_init(&mgr->lock);
-
/* init mailbox */
mgr->msg_fifo_readptr = 0;
mgr->msg_fifo_writeptr = 0;
- spin_lock_init(&mgr->msg_lock);
- mutex_init(&mgr->msg_mutex);
+ mutex_init(&mgr->lock);
+ mutex_init(&mgr->msg_lock);
init_waitqueue_head(&mgr->msg_sleep);
atomic_set(&mgr->msg_processed, 0);
/* init setup mutex*/
mutex_init(&mgr->setup_mutex);
- /* init message taslket */
- tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
-
/* card assignment */
mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */
for (i = 0; i < mgr->num_cards; i++) {
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 561634d5c007..0cc17e0ea34a 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -78,22 +78,18 @@ struct mixart_mgr {
char shortname[32]; /* short name of this soundcard */
char longname[80]; /* name of this soundcard */
- /* message tasklet */
- struct tasklet_struct msg_taskq;
-
/* one and only blocking message or notification may be pending */
u32 pending_event;
wait_queue_head_t msg_sleep;
- /* messages stored for tasklet */
+ /* messages fifo */
u32 msg_fifo[MSG_FIFO_SIZE];
int msg_fifo_readptr;
int msg_fifo_writeptr;
atomic_t msg_processed; /* number of messages to be processed in takslet */
- spinlock_t lock; /* interrupt spinlock */
- spinlock_t msg_lock; /* mailbox spinlock */
- struct mutex msg_mutex; /* mutex for blocking_requests */
+ struct mutex lock; /* interrupt lock */
+ struct mutex msg_lock; /* mailbox lock */
struct mutex setup_mutex; /* mutex used in hw_params, open and close */
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index 84f67450924e..fe80313674d9 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -76,7 +76,6 @@ static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
u32 msg_frame_address )
{
- unsigned long flags;
u32 headptr;
u32 size;
int err;
@@ -84,7 +83,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
unsigned int i;
#endif
- spin_lock_irqsave(&mgr->msg_lock, flags);
+ mutex_lock(&mgr->msg_lock);
err = 0;
/* copy message descriptor from miXart to driver */
@@ -133,7 +132,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
_clean_exit:
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
@@ -243,28 +242,24 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
wait_queue_t wait;
long timeout;
- mutex_lock(&mgr->msg_mutex);
-
init_waitqueue_entry(&wait, current);
- spin_lock_irq(&mgr->msg_lock);
+ mutex_lock(&mgr->msg_lock);
/* send the message */
err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */
if (err) {
- spin_unlock_irq(&mgr->msg_lock);
- mutex_unlock(&mgr->msg_mutex);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&mgr->msg_sleep, &wait);
- spin_unlock_irq(&mgr->msg_lock);
+ mutex_unlock(&mgr->msg_lock);
timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
remove_wait_queue(&mgr->msg_sleep, &wait);
if (! timeout) {
/* error - no ack */
- mutex_unlock(&mgr->msg_mutex);
dev_err(&mgr->pci->dev,
"error: no response on msg %x\n", msg_frame);
return -EIO;
@@ -281,7 +276,6 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
if( request->message_id != resp.message_id )
dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
- mutex_unlock(&mgr->msg_mutex);
return err;
}
@@ -300,34 +294,29 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK))
return -EINVAL;
- mutex_lock(&mgr->msg_mutex);
-
init_waitqueue_entry(&wait, current);
- spin_lock_irq(&mgr->msg_lock);
+ mutex_lock(&mgr->msg_lock);
/* send the message */
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event); /* send and mark the notification event pending */
if(err) {
- spin_unlock_irq(&mgr->msg_lock);
- mutex_unlock(&mgr->msg_mutex);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&mgr->msg_sleep, &wait);
- spin_unlock_irq(&mgr->msg_lock);
+ mutex_unlock(&mgr->msg_lock);
timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
remove_wait_queue(&mgr->msg_sleep, &wait);
if (! timeout) {
/* error - no ack */
- mutex_unlock(&mgr->msg_mutex);
dev_err(&mgr->pci->dev,
"error: notification %x not received\n", notif_event);
return -EIO;
}
- mutex_unlock(&mgr->msg_mutex);
return 0;
}
@@ -335,13 +324,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
{
u32 message_frame;
- unsigned long flags;
int err;
/* just send the message (do not mark it as a pending one) */
- spin_lock_irqsave(&mgr->msg_lock, flags);
+ mutex_lock(&mgr->msg_lock);
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
/* the answer will be handled by snd_struct mixart_msgasklet() */
atomic_inc(&mgr->msg_processed);
@@ -350,19 +338,16 @@ int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *requ
}
-/* common buffer of tasklet and interrupt to send/receive messages */
+/* common buffer of interrupt to send/receive messages */
static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
-void snd_mixart_msg_tasklet(unsigned long arg)
+static void snd_mixart_process_msg(struct mixart_mgr *mgr)
{
- struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg);
struct mixart_msg resp;
u32 msg, addr, type;
int err;
- spin_lock(&mgr->lock);
-
while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
mgr->msg_fifo_readptr++;
@@ -381,7 +366,7 @@ void snd_mixart_msg_tasklet(unsigned long arg)
err = get_msg(mgr, &resp, addr);
if( err < 0 ) {
dev_err(&mgr->pci->dev,
- "tasklet: error(%d) reading mf %x\n",
+ "error(%d) reading mf %x\n",
err, msg);
break;
}
@@ -393,12 +378,12 @@ void snd_mixart_msg_tasklet(unsigned long arg)
case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
if(mixart_msg_data[0])
dev_err(&mgr->pci->dev,
- "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
+ "error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
mixart_msg_data[0]);
break;
default:
dev_dbg(&mgr->pci->dev,
- "tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
+ "received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
break;
}
@@ -409,7 +394,7 @@ void snd_mixart_msg_tasklet(unsigned long arg)
/* get_msg() necessary */
default:
dev_err(&mgr->pci->dev,
- "tasklet doesn't know what to do with message %x\n",
+ "doesn't know what to do with message %x\n",
msg);
} /* switch type */
@@ -417,26 +402,17 @@ void snd_mixart_msg_tasklet(unsigned long arg)
atomic_dec(&mgr->msg_processed);
} /* while there is a msg in fifo */
-
- spin_unlock(&mgr->lock);
}
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
{
struct mixart_mgr *mgr = dev_id;
- int err;
- struct mixart_msg resp;
-
- u32 msg;
u32 it_reg;
- spin_lock(&mgr->lock);
-
it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
if( !(it_reg & MIXART_OIDI) ) {
/* this device did not cause the interrupt */
- spin_unlock(&mgr->lock);
return IRQ_NONE;
}
@@ -450,6 +426,17 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
/* clear interrupt */
writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
+ return IRQ_WAKE_THREAD;
+}
+
+irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id)
+{
+ struct mixart_mgr *mgr = dev_id;
+ int err;
+ struct mixart_msg resp;
+ u32 msg;
+
+ mutex_lock(&mgr->lock);
/* process interrupt */
while (retrieve_msg_frame(mgr, &msg)) {
@@ -518,9 +505,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
if(elapsed) {
- spin_unlock(&mgr->lock);
+ mutex_unlock(&mgr->lock);
snd_pcm_period_elapsed(stream->substream);
- spin_lock(&mgr->lock);
+ mutex_lock(&mgr->lock);
}
}
}
@@ -556,7 +543,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
/* no break, continue ! */
case MSG_TYPE_ANSWER:
/* answer or notification to a message we are waiting for*/
- spin_lock(&mgr->msg_lock);
+ mutex_lock(&mgr->msg_lock);
if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
wake_up(&mgr->msg_sleep);
mgr->pending_event = 0;
@@ -566,9 +553,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
mgr->msg_fifo_writeptr++;
mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
- tasklet_schedule(&mgr->msg_taskq);
+ snd_mixart_process_msg(mgr);
}
- spin_unlock(&mgr->msg_lock);
+ mutex_unlock(&mgr->msg_lock);
break;
case MSG_TYPE_REQUEST:
default:
@@ -582,7 +569,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
/* allow interrupt again */
writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
- spin_unlock(&mgr->lock);
+ mutex_unlock(&mgr->lock);
return IRQ_HANDLED;
}
diff --git a/sound/pci/mixart/mixart_core.h b/sound/pci/mixart/mixart_core.h
index c919b734756f..d1722e575409 100644
--- a/sound/pci/mixart/mixart_core.h
+++ b/sound/pci/mixart/mixart_core.h
@@ -564,7 +564,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *r
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request);
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id);
-void snd_mixart_msg_tasklet(unsigned long arg);
+irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id);
void snd_mixart_reset_board(struct mixart_mgr *mgr);