Skip to content

Commit 329037e

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 compilation error. - Set control and event queue flush entries to trigger a compilation error as flushing is not required for these queues.
1 parent bcc3c7b commit 329037e

File tree

1 file changed

+43
-24
lines changed

1 file changed

+43
-24
lines changed

virtio-snd.c

Lines changed: 43 additions & 24 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)
454+
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+
}
459462

460-
VSND_GEN_TX_QUEUE_HANDLER(normal, 1);
461-
VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
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,22 @@ 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 just trigger a compilation error
934+
*/
935+
NULL, /* no need to flush event queue, so just trigger a compilation
936+
error */
937+
virtio_snd_io_desc_flush_handler, /* flush TX queue */
938+
NULL, /* flush RX queue */
939+
};
915940

916941
static void __virtio_snd_frame_enqueue(void *payload,
917942
uint32_t n,
@@ -949,16 +974,10 @@ static void __virtio_snd_frame_enqueue(void *payload,
949974
pthread_mutex_unlock(&props->lock.lock);
950975
}
951976

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 *))
977+
static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd, int index)
959978
{
960979
uint32_t *ram = vsnd->ram;
961-
virtio_snd_queue_t *queue = &vsnd->queues[index];
980+
virtio_snd_queue_t *queue = &vsnd->queues[index & 0x03];
962981
if (vsnd->Status & VIRTIO_STATUS__DEVICE_NEEDS_RESET)
963982
return;
964983

@@ -992,7 +1011,8 @@ static void virtio_queue_notify_handler(
9921011
* descriptor list.
9931012
*/
9941013
uint32_t len = 0;
995-
int result = handler(vsnd, queue, buffer_idx, &len);
1014+
int result = __virtio_snd_queue_op_tbl[index & 0x07](vsnd, queue,
1015+
buffer_idx, &len);
9961016
if (result != 0)
9971017
return virtio_snd_set_fail(vsnd);
9981018

@@ -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)