15
15
#include <sound/pcm_params.h>
16
16
17
17
#include <xen/xenbus.h>
18
+ #include <xen/xen-front-pgdir-shbuf.h>
18
19
19
20
#include "xen_snd_front.h"
20
21
#include "xen_snd_front_alsa.h"
21
22
#include "xen_snd_front_cfg.h"
22
23
#include "xen_snd_front_evtchnl.h"
23
- #include "xen_snd_front_shbuf.h"
24
24
25
25
struct xen_snd_front_pcm_stream_info {
26
26
struct xen_snd_front_info * front_info ;
27
27
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
+
29
36
int index ;
30
37
31
38
bool is_open ;
@@ -214,12 +221,20 @@ static void stream_clear(struct xen_snd_front_pcm_stream_info *stream)
214
221
stream -> out_frames = 0 ;
215
222
atomic_set (& stream -> hw_ptr , 0 );
216
223
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 ;
218
229
}
219
230
220
231
static void stream_free (struct xen_snd_front_pcm_stream_info * stream )
221
232
{
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 );
223
238
stream_clear (stream );
224
239
}
225
240
@@ -421,30 +436,67 @@ static int alsa_close(struct snd_pcm_substream *substream)
421
436
return 0 ;
422
437
}
423
438
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 (stream -> 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
+
424
461
static int alsa_hw_params (struct snd_pcm_substream * substream ,
425
462
struct snd_pcm_hw_params * params )
426
463
{
427
464
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 ;
428
467
int ret ;
429
468
430
469
/*
431
470
* This callback may be called multiple times,
432
471
* so free the previously allocated shared buffer if any.
433
472
*/
434
473
stream_free (stream );
474
+ ret = shbuf_setup_backstore (stream , params_buffer_bytes (params ));
475
+ if (ret < 0 )
476
+ goto fail ;
435
477
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 ;
446
491
447
492
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 ;
448
500
}
449
501
450
502
static int alsa_hw_free (struct snd_pcm_substream * substream )
@@ -476,7 +528,7 @@ static int alsa_prepare(struct snd_pcm_substream *substream)
476
528
sndif_format = ret ;
477
529
478
530
ret = xen_snd_front_stream_prepare (& stream -> evt_pair -> req ,
479
- & stream -> sh_buf ,
531
+ & stream -> shbuf ,
480
532
sndif_format ,
481
533
runtime -> channels ,
482
534
runtime -> rate ,
@@ -556,10 +608,10 @@ static int alsa_pb_copy_user(struct snd_pcm_substream *substream,
556
608
{
557
609
struct xen_snd_front_pcm_stream_info * stream = stream_get (substream );
558
610
559
- if (unlikely (pos + count > stream -> sh_buf . buffer_sz ))
611
+ if (unlikely (pos + count > stream -> buffer_sz ))
560
612
return - EINVAL ;
561
613
562
- if (copy_from_user (stream -> sh_buf . buffer + pos , src , count ))
614
+ if (copy_from_user (stream -> buffer + pos , src , count ))
563
615
return - EFAULT ;
564
616
565
617
return xen_snd_front_stream_write (& stream -> evt_pair -> req , pos , count );
@@ -571,10 +623,10 @@ static int alsa_pb_copy_kernel(struct snd_pcm_substream *substream,
571
623
{
572
624
struct xen_snd_front_pcm_stream_info * stream = stream_get (substream );
573
625
574
- if (unlikely (pos + count > stream -> sh_buf . buffer_sz ))
626
+ if (unlikely (pos + count > stream -> buffer_sz ))
575
627
return - EINVAL ;
576
628
577
- memcpy (stream -> sh_buf . buffer + pos , src , count );
629
+ memcpy (stream -> buffer + pos , src , count );
578
630
579
631
return xen_snd_front_stream_write (& stream -> evt_pair -> req , pos , count );
580
632
}
@@ -586,14 +638,14 @@ static int alsa_cap_copy_user(struct snd_pcm_substream *substream,
586
638
struct xen_snd_front_pcm_stream_info * stream = stream_get (substream );
587
639
int ret ;
588
640
589
- if (unlikely (pos + count > stream -> sh_buf . buffer_sz ))
641
+ if (unlikely (pos + count > stream -> buffer_sz ))
590
642
return - EINVAL ;
591
643
592
644
ret = xen_snd_front_stream_read (& stream -> evt_pair -> req , pos , count );
593
645
if (ret < 0 )
594
646
return ret ;
595
647
596
- return copy_to_user (dst , stream -> sh_buf . buffer + pos , count ) ?
648
+ return copy_to_user (dst , stream -> buffer + pos , count ) ?
597
649
- EFAULT : 0 ;
598
650
}
599
651
@@ -604,14 +656,14 @@ static int alsa_cap_copy_kernel(struct snd_pcm_substream *substream,
604
656
struct xen_snd_front_pcm_stream_info * stream = stream_get (substream );
605
657
int ret ;
606
658
607
- if (unlikely (pos + count > stream -> sh_buf . buffer_sz ))
659
+ if (unlikely (pos + count > stream -> buffer_sz ))
608
660
return - EINVAL ;
609
661
610
662
ret = xen_snd_front_stream_read (& stream -> evt_pair -> req , pos , count );
611
663
if (ret < 0 )
612
664
return ret ;
613
665
614
- memcpy (dst , stream -> sh_buf . buffer + pos , count );
666
+ memcpy (dst , stream -> buffer + pos , count );
615
667
616
668
return 0 ;
617
669
}
@@ -622,10 +674,10 @@ static int alsa_pb_fill_silence(struct snd_pcm_substream *substream,
622
674
{
623
675
struct xen_snd_front_pcm_stream_info * stream = stream_get (substream );
624
676
625
- if (unlikely (pos + count > stream -> sh_buf . buffer_sz ))
677
+ if (unlikely (pos + count > stream -> buffer_sz ))
626
678
return - EINVAL ;
627
679
628
- memset (stream -> sh_buf . buffer + pos , 0 , count );
680
+ memset (stream -> buffer + pos , 0 , count );
629
681
630
682
return xen_snd_front_stream_write (& stream -> evt_pair -> req , pos , count );
631
683
}
0 commit comments