Skip to content

Commit 7afe818

Browse files
committed
virtio-snd: implement queue function lookup table
Introduce a function lookup table to handle virtio-snd queues. This prepares the device for upcoming PCM I/O receive and event features by allowing queue ID indexing for callbacks. - Set unimplemented PCM I/O receive and event entries to trigger a failed null check. - Set control and event queue flush entries to trigger a failed null check as flushing is not required for these queues.
1 parent bcc3c7b commit 7afe818

File tree

1 file changed

+42
-23
lines changed

1 file changed

+42
-23
lines changed

virtio-snd.c

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,7 @@ static int virtio_snd_stream_cb(const void *input,
331331
const PaStreamCallbackTimeInfo *time_info,
332332
PaStreamCallbackFlags status_flags,
333333
void *user_data);
334-
static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd,
335-
int index, /* virtq index */
336-
vsnd_virtq_cb cb);
334+
static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd, int index);
337335
static void __virtio_snd_frame_enqueue(void *payload,
338336
uint32_t n,
339337
uint32_t stream_id);
@@ -347,11 +345,8 @@ typedef struct {
347345
*/
348346
static uint32_t flush_stream_id = 0;
349347

350-
#define VSND_GEN_TX_QUEUE_HANDLER(NAME_SUFFIX, WRITE) \
351-
static int virtio_snd_tx_desc_##NAME_SUFFIX##_handler( \
352-
virtio_snd_state_t *vsnd, const virtio_snd_queue_t *queue, \
353-
uint32_t desc_idx, uint32_t *plen) \
354-
{ \
348+
#define VSND_TX_QUEUE_BODY(WRITE) \
349+
do { \
355350
/* A PCM I/O message uses at least 3 virtqueue descriptors to \
356351
* represent a PCM data of a period size. \
357352
* The first part contains one descriptor as follows: \
@@ -455,10 +450,23 @@ static uint32_t flush_stream_id = 0;
455450
\
456451
finally: \
457452
return 0; \
458-
}
453+
} while (0)
459454

460-
VSND_GEN_TX_QUEUE_HANDLER(normal, 1);
461-
VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
455+
static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd,
456+
const virtio_snd_queue_t *queue,
457+
uint32_t desc_idx,
458+
uint32_t *plen)
459+
{
460+
VSND_TX_QUEUE_BODY(1);
461+
}
462+
463+
static int virtio_snd_io_desc_flush_handler(virtio_snd_state_t *vsnd,
464+
const virtio_snd_queue_t *queue,
465+
uint32_t desc_idx,
466+
uint32_t *plen)
467+
{
468+
VSND_TX_QUEUE_BODY(0);
469+
}
462470

463471
static void virtio_snd_set_fail(virtio_snd_state_t *vsnd)
464472
{
@@ -723,6 +731,7 @@ static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query,
723731
*plen = 0;
724732
}
725733

734+
#define VSND_FLUSH_QUEUE 0x4
726735
static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
727736
uint32_t *plen,
728737
virtio_snd_state_t *vsnd)
@@ -770,7 +779,7 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
770779
* - The device MUST NOT complete the control request while there
771780
* are pending I/O messages for the specified stream ID.
772781
*/
773-
virtio_queue_notify_handler(vsnd, 2, virtio_snd_tx_desc_flush_handler);
782+
virtio_queue_notify_handler(vsnd, VSND_FLUSH_QUEUE | 0x2);
774783

775784
*plen = 0;
776785
}
@@ -912,6 +921,20 @@ static int virtio_snd_ctrl_desc_handler(virtio_snd_state_t *vsnd,
912921
return 0;
913922
}
914923

924+
/* virtq device operation lookup table */
925+
/* The entry of flush queue operation (whether it is needed or not
926+
* for each type of queue) starts from 0x04.
927+
* So we can set bit with 0x04 when we need to flush queue. */
928+
static vsnd_virtq_cb __virtio_snd_queue_op_tbl[8] = {
929+
virtio_snd_ctrl_desc_handler, /* control queue */
930+
NULL, /* event queue */
931+
virtio_snd_tx_desc_handler, /* TX queue */
932+
NULL, /* RX queue */
933+
NULL, /* no need to flush control queue, so trigger a failed null check */
934+
NULL, /* no need to flush event queue, so trigger a failed null check */
935+
virtio_snd_io_desc_flush_handler, /* flush TX queue */
936+
NULL, /* flush RX queue */
937+
};
915938

916939
static void __virtio_snd_frame_enqueue(void *payload,
917940
uint32_t n,
@@ -949,16 +972,10 @@ static void __virtio_snd_frame_enqueue(void *payload,
949972
pthread_mutex_unlock(&props->lock.lock);
950973
}
951974

952-
static void virtio_queue_notify_handler(
953-
virtio_snd_state_t *vsnd,
954-
int index,
955-
int (*handler)(virtio_snd_state_t *,
956-
const virtio_snd_queue_t *,
957-
uint32_t,
958-
uint32_t *))
975+
static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd, int index)
959976
{
960977
uint32_t *ram = vsnd->ram;
961-
virtio_snd_queue_t *queue = &vsnd->queues[index];
978+
virtio_snd_queue_t *queue = &vsnd->queues[index & 0x03];
962979
if (vsnd->Status & VIRTIO_STATUS__DEVICE_NEEDS_RESET)
963980
return;
964981

@@ -992,6 +1009,9 @@ static void virtio_queue_notify_handler(
9921009
* descriptor list.
9931010
*/
9941011
uint32_t len = 0;
1012+
vsnd_virtq_cb handler = __virtio_snd_queue_op_tbl[index & 0x07];
1013+
if (!handler)
1014+
return virtio_snd_set_fail(vsnd);
9951015
int result = handler(vsnd, queue, buffer_idx, &len);
9961016
if (result != 0)
9971017
return virtio_snd_set_fail(vsnd);
@@ -1026,7 +1046,7 @@ static void *func(void *args)
10261046
pthread_cond_wait(&virtio_snd_tx_cond, &virtio_snd_mutex);
10271047

10281048
tx_ev_notify--;
1029-
virtio_queue_notify_handler(vsnd, 2, virtio_snd_tx_desc_normal_handler);
1049+
virtio_queue_notify_handler(vsnd, 2);
10301050

10311051
pthread_mutex_unlock(&virtio_snd_mutex);
10321052
}
@@ -1140,8 +1160,7 @@ static bool virtio_snd_reg_write(virtio_snd_state_t *vsnd,
11401160
if (value < ARRAY_SIZE(vsnd->queues)) {
11411161
switch (value) {
11421162
case VSND_QUEUE_CTRL:
1143-
virtio_queue_notify_handler(vsnd, value,
1144-
virtio_snd_ctrl_desc_handler);
1163+
virtio_queue_notify_handler(vsnd, value);
11451164
break;
11461165
case VSND_QUEUE_TX:
11471166
tx_ev_notify++;

0 commit comments

Comments
 (0)