hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/sound/xen/xen_snd_front_alsa.c
....@@ -15,17 +15,24 @@
1515 #include <sound/pcm_params.h>
1616
1717 #include <xen/xenbus.h>
18
+#include <xen/xen-front-pgdir-shbuf.h>
1819
1920 #include "xen_snd_front.h"
2021 #include "xen_snd_front_alsa.h"
2122 #include "xen_snd_front_cfg.h"
2223 #include "xen_snd_front_evtchnl.h"
23
-#include "xen_snd_front_shbuf.h"
2424
2525 struct xen_snd_front_pcm_stream_info {
2626 struct xen_snd_front_info *front_info;
2727 struct xen_snd_front_evtchnl_pair *evt_pair;
28
- struct xen_snd_front_shbuf sh_buf;
28
+
29
+ /* This is the shared buffer with its backing storage. */
30
+ struct xen_front_pgdir_shbuf shbuf;
31
+ u8 *buffer;
32
+ size_t buffer_sz;
33
+ int num_pages;
34
+ struct page **pages;
35
+
2936 int index;
3037
3138 bool is_open;
....@@ -189,7 +196,7 @@
189196 mask = 0;
190197 for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++)
191198 if (pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa) & alsa_formats)
192
- mask |= 1 << ALSA_SNDIF_FORMATS[i].sndif;
199
+ mask |= BIT_ULL(ALSA_SNDIF_FORMATS[i].sndif);
193200
194201 return mask;
195202 }
....@@ -201,7 +208,7 @@
201208
202209 mask = 0;
203210 for (i = 0; i < ARRAY_SIZE(ALSA_SNDIF_FORMATS); i++)
204
- if (1 << ALSA_SNDIF_FORMATS[i].sndif & sndif_formats)
211
+ if (BIT_ULL(ALSA_SNDIF_FORMATS[i].sndif) & sndif_formats)
205212 mask |= pcm_format_to_bits(ALSA_SNDIF_FORMATS[i].alsa);
206213
207214 return mask;
....@@ -214,12 +221,20 @@
214221 stream->out_frames = 0;
215222 atomic_set(&stream->hw_ptr, 0);
216223 xen_snd_front_evtchnl_pair_clear(stream->evt_pair);
217
- xen_snd_front_shbuf_clear(&stream->sh_buf);
224
+ memset(&stream->shbuf, 0, sizeof(stream->shbuf));
225
+ stream->buffer = NULL;
226
+ stream->buffer_sz = 0;
227
+ stream->pages = NULL;
228
+ stream->num_pages = 0;
218229 }
219230
220231 static void stream_free(struct xen_snd_front_pcm_stream_info *stream)
221232 {
222
- xen_snd_front_shbuf_free(&stream->sh_buf);
233
+ xen_front_pgdir_shbuf_unmap(&stream->shbuf);
234
+ xen_front_pgdir_shbuf_free(&stream->shbuf);
235
+ if (stream->buffer)
236
+ free_pages_exact(stream->buffer, stream->buffer_sz);
237
+ kfree(stream->pages);
223238 stream_clear(stream);
224239 }
225240
....@@ -421,10 +436,34 @@
421436 return 0;
422437 }
423438
439
+static int shbuf_setup_backstore(struct xen_snd_front_pcm_stream_info *stream,
440
+ size_t buffer_sz)
441
+{
442
+ int i;
443
+
444
+ stream->buffer = alloc_pages_exact(buffer_sz, GFP_KERNEL);
445
+ if (!stream->buffer)
446
+ return -ENOMEM;
447
+
448
+ stream->buffer_sz = buffer_sz;
449
+ stream->num_pages = DIV_ROUND_UP(stream->buffer_sz, PAGE_SIZE);
450
+ stream->pages = kcalloc(stream->num_pages, sizeof(struct page *),
451
+ GFP_KERNEL);
452
+ if (!stream->pages)
453
+ return -ENOMEM;
454
+
455
+ for (i = 0; i < stream->num_pages; i++)
456
+ stream->pages[i] = virt_to_page(stream->buffer + i * PAGE_SIZE);
457
+
458
+ return 0;
459
+}
460
+
424461 static int alsa_hw_params(struct snd_pcm_substream *substream,
425462 struct snd_pcm_hw_params *params)
426463 {
427464 struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
465
+ struct xen_snd_front_info *front_info = stream->front_info;
466
+ struct xen_front_pgdir_shbuf_cfg buf_cfg;
428467 int ret;
429468
430469 /*
....@@ -432,19 +471,32 @@
432471 * so free the previously allocated shared buffer if any.
433472 */
434473 stream_free(stream);
474
+ ret = shbuf_setup_backstore(stream, params_buffer_bytes(params));
475
+ if (ret < 0)
476
+ goto fail;
435477
436
- ret = xen_snd_front_shbuf_alloc(stream->front_info->xb_dev,
437
- &stream->sh_buf,
438
- params_buffer_bytes(params));
439
- if (ret < 0) {
440
- stream_free(stream);
441
- dev_err(&stream->front_info->xb_dev->dev,
442
- "Failed to allocate buffers for stream with index %d\n",
443
- stream->index);
444
- return ret;
445
- }
478
+ memset(&buf_cfg, 0, sizeof(buf_cfg));
479
+ buf_cfg.xb_dev = front_info->xb_dev;
480
+ buf_cfg.pgdir = &stream->shbuf;
481
+ buf_cfg.num_pages = stream->num_pages;
482
+ buf_cfg.pages = stream->pages;
483
+
484
+ ret = xen_front_pgdir_shbuf_alloc(&buf_cfg);
485
+ if (ret < 0)
486
+ goto fail;
487
+
488
+ ret = xen_front_pgdir_shbuf_map(&stream->shbuf);
489
+ if (ret < 0)
490
+ goto fail;
446491
447492 return 0;
493
+
494
+fail:
495
+ stream_free(stream);
496
+ dev_err(&front_info->xb_dev->dev,
497
+ "Failed to allocate buffers for stream with index %d\n",
498
+ stream->index);
499
+ return ret;
448500 }
449501
450502 static int alsa_hw_free(struct snd_pcm_substream *substream)
....@@ -476,7 +528,7 @@
476528 sndif_format = ret;
477529
478530 ret = xen_snd_front_stream_prepare(&stream->evt_pair->req,
479
- &stream->sh_buf,
531
+ &stream->shbuf,
480532 sndif_format,
481533 runtime->channels,
482534 runtime->rate,
....@@ -556,10 +608,10 @@
556608 {
557609 struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
558610
559
- if (unlikely(pos + count > stream->sh_buf.buffer_sz))
611
+ if (unlikely(pos + count > stream->buffer_sz))
560612 return -EINVAL;
561613
562
- if (copy_from_user(stream->sh_buf.buffer + pos, src, count))
614
+ if (copy_from_user(stream->buffer + pos, src, count))
563615 return -EFAULT;
564616
565617 return xen_snd_front_stream_write(&stream->evt_pair->req, pos, count);
....@@ -571,10 +623,10 @@
571623 {
572624 struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
573625
574
- if (unlikely(pos + count > stream->sh_buf.buffer_sz))
626
+ if (unlikely(pos + count > stream->buffer_sz))
575627 return -EINVAL;
576628
577
- memcpy(stream->sh_buf.buffer + pos, src, count);
629
+ memcpy(stream->buffer + pos, src, count);
578630
579631 return xen_snd_front_stream_write(&stream->evt_pair->req, pos, count);
580632 }
....@@ -586,14 +638,14 @@
586638 struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
587639 int ret;
588640
589
- if (unlikely(pos + count > stream->sh_buf.buffer_sz))
641
+ if (unlikely(pos + count > stream->buffer_sz))
590642 return -EINVAL;
591643
592644 ret = xen_snd_front_stream_read(&stream->evt_pair->req, pos, count);
593645 if (ret < 0)
594646 return ret;
595647
596
- return copy_to_user(dst, stream->sh_buf.buffer + pos, count) ?
648
+ return copy_to_user(dst, stream->buffer + pos, count) ?
597649 -EFAULT : 0;
598650 }
599651
....@@ -604,14 +656,14 @@
604656 struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
605657 int ret;
606658
607
- if (unlikely(pos + count > stream->sh_buf.buffer_sz))
659
+ if (unlikely(pos + count > stream->buffer_sz))
608660 return -EINVAL;
609661
610662 ret = xen_snd_front_stream_read(&stream->evt_pair->req, pos, count);
611663 if (ret < 0)
612664 return ret;
613665
614
- memcpy(dst, stream->sh_buf.buffer + pos, count);
666
+ memcpy(dst, stream->buffer + pos, count);
615667
616668 return 0;
617669 }
....@@ -622,10 +674,10 @@
622674 {
623675 struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
624676
625
- if (unlikely(pos + count > stream->sh_buf.buffer_sz))
677
+ if (unlikely(pos + count > stream->buffer_sz))
626678 return -EINVAL;
627679
628
- memset(stream->sh_buf.buffer + pos, 0, count);
680
+ memset(stream->buffer + pos, 0, count);
629681
630682 return xen_snd_front_stream_write(&stream->evt_pair->req, pos, count);
631683 }
....@@ -637,31 +689,29 @@
637689 * to know when the buffer can be transferred to the backend.
638690 */
639691
640
-static struct snd_pcm_ops snd_drv_alsa_playback_ops = {
641
- .open = alsa_open,
642
- .close = alsa_close,
643
- .ioctl = snd_pcm_lib_ioctl,
644
- .hw_params = alsa_hw_params,
645
- .hw_free = alsa_hw_free,
646
- .prepare = alsa_prepare,
647
- .trigger = alsa_trigger,
648
- .pointer = alsa_pointer,
649
- .copy_user = alsa_pb_copy_user,
650
- .copy_kernel = alsa_pb_copy_kernel,
651
- .fill_silence = alsa_pb_fill_silence,
692
+static const struct snd_pcm_ops snd_drv_alsa_playback_ops = {
693
+ .open = alsa_open,
694
+ .close = alsa_close,
695
+ .hw_params = alsa_hw_params,
696
+ .hw_free = alsa_hw_free,
697
+ .prepare = alsa_prepare,
698
+ .trigger = alsa_trigger,
699
+ .pointer = alsa_pointer,
700
+ .copy_user = alsa_pb_copy_user,
701
+ .copy_kernel = alsa_pb_copy_kernel,
702
+ .fill_silence = alsa_pb_fill_silence,
652703 };
653704
654
-static struct snd_pcm_ops snd_drv_alsa_capture_ops = {
655
- .open = alsa_open,
656
- .close = alsa_close,
657
- .ioctl = snd_pcm_lib_ioctl,
658
- .hw_params = alsa_hw_params,
659
- .hw_free = alsa_hw_free,
660
- .prepare = alsa_prepare,
661
- .trigger = alsa_trigger,
662
- .pointer = alsa_pointer,
663
- .copy_user = alsa_cap_copy_user,
664
- .copy_kernel = alsa_cap_copy_kernel,
705
+static const struct snd_pcm_ops snd_drv_alsa_capture_ops = {
706
+ .open = alsa_open,
707
+ .close = alsa_close,
708
+ .hw_params = alsa_hw_params,
709
+ .hw_free = alsa_hw_free,
710
+ .prepare = alsa_prepare,
711
+ .trigger = alsa_trigger,
712
+ .pointer = alsa_pointer,
713
+ .copy_user = alsa_cap_copy_user,
714
+ .copy_kernel = alsa_cap_copy_kernel,
665715 };
666716
667717 static int new_pcm_instance(struct xen_snd_front_card_info *card_info,