1 // SPDX-License-Identifier: GPL-2.0 OR MIT
4 * Xen para-virtual sound device
6 * Copyright (C) 2016-2018 EPAM Systems Inc.
8 * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
11 #include <linux/delay.h>
12 #include <linux/module.h>
15 #include <xen/platform_pci.h>
17 #include <xen/xenbus.h>
19 #include <xen/interface/io/sndif.h>
21 #include "xen_snd_front.h"
22 #include "xen_snd_front_alsa.h"
23 #include "xen_snd_front_evtchnl.h"
24 #include "xen_snd_front_shbuf.h"
26 static struct xensnd_req
*
27 be_stream_prepare_req(struct xen_snd_front_evtchnl
*evtchnl
, u8 operation
)
29 struct xensnd_req
*req
;
31 req
= RING_GET_REQUEST(&evtchnl
->u
.req
.ring
,
32 evtchnl
->u
.req
.ring
.req_prod_pvt
);
33 req
->operation
= operation
;
34 req
->id
= evtchnl
->evt_next_id
++;
35 evtchnl
->evt_id
= req
->id
;
39 static int be_stream_do_io(struct xen_snd_front_evtchnl
*evtchnl
)
41 if (unlikely(evtchnl
->state
!= EVTCHNL_STATE_CONNECTED
))
44 reinit_completion(&evtchnl
->u
.req
.completion
);
45 xen_snd_front_evtchnl_flush(evtchnl
);
49 static int be_stream_wait_io(struct xen_snd_front_evtchnl
*evtchnl
)
51 if (wait_for_completion_timeout(&evtchnl
->u
.req
.completion
,
52 msecs_to_jiffies(VSND_WAIT_BACK_MS
)) <= 0)
55 return evtchnl
->u
.req
.resp_status
;
58 int xen_snd_front_stream_query_hw_param(struct xen_snd_front_evtchnl
*evtchnl
,
59 struct xensnd_query_hw_param
*hw_param_req
,
60 struct xensnd_query_hw_param
*hw_param_resp
)
62 struct xensnd_req
*req
;
65 mutex_lock(&evtchnl
->u
.req
.req_io_lock
);
67 mutex_lock(&evtchnl
->ring_io_lock
);
68 req
= be_stream_prepare_req(evtchnl
, XENSND_OP_HW_PARAM_QUERY
);
69 req
->op
.hw_param
= *hw_param_req
;
70 mutex_unlock(&evtchnl
->ring_io_lock
);
72 ret
= be_stream_do_io(evtchnl
);
75 ret
= be_stream_wait_io(evtchnl
);
78 *hw_param_resp
= evtchnl
->u
.req
.resp
.hw_param
;
80 mutex_unlock(&evtchnl
->u
.req
.req_io_lock
);
84 int xen_snd_front_stream_prepare(struct xen_snd_front_evtchnl
*evtchnl
,
85 struct xen_snd_front_shbuf
*sh_buf
,
86 u8 format
, unsigned int channels
,
87 unsigned int rate
, u32 buffer_sz
,
90 struct xensnd_req
*req
;
93 mutex_lock(&evtchnl
->u
.req
.req_io_lock
);
95 mutex_lock(&evtchnl
->ring_io_lock
);
96 req
= be_stream_prepare_req(evtchnl
, XENSND_OP_OPEN
);
97 req
->op
.open
.pcm_format
= format
;
98 req
->op
.open
.pcm_channels
= channels
;
99 req
->op
.open
.pcm_rate
= rate
;
100 req
->op
.open
.buffer_sz
= buffer_sz
;
101 req
->op
.open
.period_sz
= period_sz
;
102 req
->op
.open
.gref_directory
= xen_snd_front_shbuf_get_dir_start(sh_buf
);
103 mutex_unlock(&evtchnl
->ring_io_lock
);
105 ret
= be_stream_do_io(evtchnl
);
108 ret
= be_stream_wait_io(evtchnl
);
110 mutex_unlock(&evtchnl
->u
.req
.req_io_lock
);
114 int xen_snd_front_stream_close(struct xen_snd_front_evtchnl
*evtchnl
)
116 struct xensnd_req
*req
;
119 mutex_lock(&evtchnl
->u
.req
.req_io_lock
);
121 mutex_lock(&evtchnl
->ring_io_lock
);
122 req
= be_stream_prepare_req(evtchnl
, XENSND_OP_CLOSE
);
123 mutex_unlock(&evtchnl
->ring_io_lock
);
125 ret
= be_stream_do_io(evtchnl
);
128 ret
= be_stream_wait_io(evtchnl
);
130 mutex_unlock(&evtchnl
->u
.req
.req_io_lock
);
134 int xen_snd_front_stream_write(struct xen_snd_front_evtchnl
*evtchnl
,
135 unsigned long pos
, unsigned long count
)
137 struct xensnd_req
*req
;
140 mutex_lock(&evtchnl
->u
.req
.req_io_lock
);
142 mutex_lock(&evtchnl
->ring_io_lock
);
143 req
= be_stream_prepare_req(evtchnl
, XENSND_OP_WRITE
);
144 req
->op
.rw
.length
= count
;
145 req
->op
.rw
.offset
= pos
;
146 mutex_unlock(&evtchnl
->ring_io_lock
);
148 ret
= be_stream_do_io(evtchnl
);
151 ret
= be_stream_wait_io(evtchnl
);
153 mutex_unlock(&evtchnl
->u
.req
.req_io_lock
);
157 int xen_snd_front_stream_read(struct xen_snd_front_evtchnl
*evtchnl
,
158 unsigned long pos
, unsigned long count
)
160 struct xensnd_req
*req
;
163 mutex_lock(&evtchnl
->u
.req
.req_io_lock
);
165 mutex_lock(&evtchnl
->ring_io_lock
);
166 req
= be_stream_prepare_req(evtchnl
, XENSND_OP_READ
);
167 req
->op
.rw
.length
= count
;
168 req
->op
.rw
.offset
= pos
;
169 mutex_unlock(&evtchnl
->ring_io_lock
);
171 ret
= be_stream_do_io(evtchnl
);
174 ret
= be_stream_wait_io(evtchnl
);
176 mutex_unlock(&evtchnl
->u
.req
.req_io_lock
);
180 int xen_snd_front_stream_trigger(struct xen_snd_front_evtchnl
*evtchnl
,
183 struct xensnd_req
*req
;
186 mutex_lock(&evtchnl
->u
.req
.req_io_lock
);
188 mutex_lock(&evtchnl
->ring_io_lock
);
189 req
= be_stream_prepare_req(evtchnl
, XENSND_OP_TRIGGER
);
190 req
->op
.trigger
.type
= type
;
191 mutex_unlock(&evtchnl
->ring_io_lock
);
193 ret
= be_stream_do_io(evtchnl
);
196 ret
= be_stream_wait_io(evtchnl
);
198 mutex_unlock(&evtchnl
->u
.req
.req_io_lock
);
202 static void xen_snd_drv_fini(struct xen_snd_front_info
*front_info
)
204 xen_snd_front_alsa_fini(front_info
);
205 xen_snd_front_evtchnl_free_all(front_info
);
208 static int sndback_initwait(struct xen_snd_front_info
*front_info
)
213 ret
= xen_snd_front_cfg_card(front_info
, &num_streams
);
217 /* create event channels for all streams and publish */
218 ret
= xen_snd_front_evtchnl_create_all(front_info
, num_streams
);
222 return xen_snd_front_evtchnl_publish_all(front_info
);
225 static int sndback_connect(struct xen_snd_front_info
*front_info
)
227 return xen_snd_front_alsa_init(front_info
);
230 static void sndback_disconnect(struct xen_snd_front_info
*front_info
)
232 xen_snd_drv_fini(front_info
);
233 xenbus_switch_state(front_info
->xb_dev
, XenbusStateInitialising
);
236 static void sndback_changed(struct xenbus_device
*xb_dev
,
237 enum xenbus_state backend_state
)
239 struct xen_snd_front_info
*front_info
= dev_get_drvdata(&xb_dev
->dev
);
242 dev_dbg(&xb_dev
->dev
, "Backend state is %s, front is %s\n",
243 xenbus_strstate(backend_state
),
244 xenbus_strstate(xb_dev
->state
));
246 switch (backend_state
) {
247 case XenbusStateReconfiguring
:
249 case XenbusStateReconfigured
:
251 case XenbusStateInitialised
:
255 case XenbusStateInitialising
:
256 /* Recovering after backend unexpected closure. */
257 sndback_disconnect(front_info
);
260 case XenbusStateInitWait
:
261 /* Recovering after backend unexpected closure. */
262 sndback_disconnect(front_info
);
264 ret
= sndback_initwait(front_info
);
266 xenbus_dev_fatal(xb_dev
, ret
, "initializing frontend");
268 xenbus_switch_state(xb_dev
, XenbusStateInitialised
);
271 case XenbusStateConnected
:
272 if (xb_dev
->state
!= XenbusStateInitialised
)
275 ret
= sndback_connect(front_info
);
277 xenbus_dev_fatal(xb_dev
, ret
, "initializing frontend");
279 xenbus_switch_state(xb_dev
, XenbusStateConnected
);
282 case XenbusStateClosing
:
284 * In this state backend starts freeing resources,
285 * so let it go into closed state first, so we can also
290 case XenbusStateUnknown
:
292 case XenbusStateClosed
:
293 if (xb_dev
->state
== XenbusStateClosed
)
296 sndback_disconnect(front_info
);
301 static int xen_drv_probe(struct xenbus_device
*xb_dev
,
302 const struct xenbus_device_id
*id
)
304 struct xen_snd_front_info
*front_info
;
306 front_info
= devm_kzalloc(&xb_dev
->dev
,
307 sizeof(*front_info
), GFP_KERNEL
);
311 front_info
->xb_dev
= xb_dev
;
312 dev_set_drvdata(&xb_dev
->dev
, front_info
);
314 return xenbus_switch_state(xb_dev
, XenbusStateInitialising
);
317 static int xen_drv_remove(struct xenbus_device
*dev
)
319 struct xen_snd_front_info
*front_info
= dev_get_drvdata(&dev
->dev
);
322 xenbus_switch_state(dev
, XenbusStateClosing
);
325 * On driver removal it is disconnected from XenBus,
326 * so no backend state change events come via .otherend_changed
327 * callback. This prevents us from exiting gracefully, e.g.
328 * signaling the backend to free event channels, waiting for its
329 * state to change to XenbusStateClosed and cleaning at our end.
330 * Normally when front driver removed backend will finally go into
331 * XenbusStateInitWait state.
333 * Workaround: read backend's state manually and wait with time-out.
335 while ((xenbus_read_unsigned(front_info
->xb_dev
->otherend
, "state",
336 XenbusStateUnknown
) != XenbusStateInitWait
) &&
343 state
= xenbus_read_unsigned(front_info
->xb_dev
->otherend
,
344 "state", XenbusStateUnknown
);
345 pr_err("Backend state is %s while removing driver\n",
346 xenbus_strstate(state
));
349 xen_snd_drv_fini(front_info
);
350 xenbus_frontend_closed(dev
);
354 static const struct xenbus_device_id xen_drv_ids
[] = {
355 { XENSND_DRIVER_NAME
},
359 static struct xenbus_driver xen_driver
= {
361 .probe
= xen_drv_probe
,
362 .remove
= xen_drv_remove
,
363 .otherend_changed
= sndback_changed
,
366 static int __init
xen_drv_init(void)
371 if (!xen_has_pv_devices())
374 /* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */
375 if (XEN_PAGE_SIZE
!= PAGE_SIZE
) {
376 pr_err(XENSND_DRIVER_NAME
": different kernel and Xen page sizes are not supported: XEN_PAGE_SIZE (%lu) != PAGE_SIZE (%lu)\n",
377 XEN_PAGE_SIZE
, PAGE_SIZE
);
381 pr_info("Initialising Xen " XENSND_DRIVER_NAME
" frontend driver\n");
382 return xenbus_register_frontend(&xen_driver
);
385 static void __exit
xen_drv_fini(void)
387 pr_info("Unregistering Xen " XENSND_DRIVER_NAME
" frontend driver\n");
388 xenbus_unregister_driver(&xen_driver
);
391 module_init(xen_drv_init
);
392 module_exit(xen_drv_fini
);
394 MODULE_DESCRIPTION("Xen virtual sound device frontend");
395 MODULE_LICENSE("GPL");
396 MODULE_ALIAS("xen:" XENSND_DRIVER_NAME
);
397 MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual soundcard}}");