summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-01-16 23:06:08 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-01-16 23:06:08 -0800
commitb3a739e9c7815a310b0ec96f3a21ba75551665e3 (patch)
treeb01b5d6d0f2a52da846017e7540fd1f19a15b13a /sound
parent79383e7ce6996fd8d0f40f219d2754d5d3197883 (diff)
parentc179cf38896f3d171ed7321b7b077d834676fb73 (diff)
Merge "sound: usb: Map interface context information to interface number"
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/usb_audio_qmi_svc.c94
1 files changed, 62 insertions, 32 deletions
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 039519c1d822..a495a7f6cb22 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -69,6 +69,7 @@ struct intf_info {
size_t xfer_buf_size;
phys_addr_t xfer_buf_pa;
u8 *xfer_buf;
+ u8 intf_num;
u8 pcm_card_num;
u8 pcm_dev_num;
u8 direction;
@@ -391,10 +392,9 @@ static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
}
static int prepare_qmi_response(struct snd_usb_substream *subs,
- struct qmi_uaudio_stream_resp_msg_v01 *resp, u32 xfer_buf_len,
- int card_num, int pcm_dev_num)
+ struct qmi_uaudio_stream_req_msg_v01 *req_msg,
+ struct qmi_uaudio_stream_resp_msg_v01 *resp, int info_idx)
{
- int ret = -ENODEV;
struct usb_interface *iface;
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
@@ -403,10 +403,11 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
struct uac_format_type_i_discrete_descriptor *fmt_v1;
struct uac_format_type_i_ext_descriptor *fmt_v2;
struct uac1_as_header_descriptor *as;
- int protocol;
+ int ret = -ENODEV;
+ int protocol, card_num, pcm_dev_num;
void *hdr_ptr;
u8 *xfer_buf;
- u32 len, mult, remainder;
+ u32 len, mult, remainder, xfer_buf_len;
unsigned long va, tr_data_va = 0, tr_sync_va = 0, dcba_va = 0,
xfer_buf_va = 0;
phys_addr_t xhci_pa, xfer_buf_pa;
@@ -418,13 +419,9 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
goto err;
}
- if (uadev[card_num].info &&
- uadev[card_num].info[subs->interface].in_use) {
- pr_err("%s interface# %d already in use card# %d\n", __func__,
- subs->interface, card_num);
- ret = -EBUSY;
- goto err;
- }
+ pcm_dev_num = (req_msg->usb_token & SND_PCM_DEV_NUM_MASK) >> 8;
+ card_num = (req_msg->usb_token & SND_PCM_CARD_NUM_MASK) >> 16;
+ xfer_buf_len = req_msg->xfer_buff_size;
alts = &iface->altsetting[subs->altset_idx];
altsd = get_iface_desc(alts);
@@ -655,18 +652,19 @@ skip_sync:
uadev[card_num].card_num = card_num;
/* cache intf specific info to use it for unmap and free xfer buf */
- uadev[card_num].info[subs->interface].data_xfer_ring_va = tr_data_va;
- uadev[card_num].info[subs->interface].data_xfer_ring_size = PAGE_SIZE;
- uadev[card_num].info[subs->interface].sync_xfer_ring_va = tr_sync_va;
- uadev[card_num].info[subs->interface].sync_xfer_ring_size = PAGE_SIZE;
- uadev[card_num].info[subs->interface].xfer_buf_va = xfer_buf_va;
- uadev[card_num].info[subs->interface].xfer_buf_pa = xfer_buf_pa;
- uadev[card_num].info[subs->interface].xfer_buf_size = len;
- uadev[card_num].info[subs->interface].xfer_buf = xfer_buf;
- uadev[card_num].info[subs->interface].pcm_card_num = card_num;
- uadev[card_num].info[subs->interface].pcm_dev_num = pcm_dev_num;
- uadev[card_num].info[subs->interface].direction = subs->direction;
- uadev[card_num].info[subs->interface].in_use = true;
+ uadev[card_num].info[info_idx].data_xfer_ring_va = tr_data_va;
+ uadev[card_num].info[info_idx].data_xfer_ring_size = PAGE_SIZE;
+ uadev[card_num].info[info_idx].sync_xfer_ring_va = tr_sync_va;
+ uadev[card_num].info[info_idx].sync_xfer_ring_size = PAGE_SIZE;
+ uadev[card_num].info[info_idx].xfer_buf_va = xfer_buf_va;
+ uadev[card_num].info[info_idx].xfer_buf_pa = xfer_buf_pa;
+ uadev[card_num].info[info_idx].xfer_buf_size = len;
+ uadev[card_num].info[info_idx].xfer_buf = xfer_buf;
+ uadev[card_num].info[info_idx].pcm_card_num = card_num;
+ uadev[card_num].info[info_idx].pcm_dev_num = pcm_dev_num;
+ uadev[card_num].info[info_idx].direction = subs->direction;
+ uadev[card_num].info[info_idx].intf_num = subs->interface;
+ uadev[card_num].info[info_idx].in_use = true;
set_bit(card_num, &uaudio_qdev->card_slot);
@@ -723,7 +721,7 @@ static void uaudio_dev_cleanup(struct uaudio_dev *dev)
continue;
uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
- if_idx, dev->card_num);
+ dev->info[if_idx].intf_num, dev->card_num);
}
/* iommu_unmap dcba iova for a usb device */
@@ -867,6 +865,28 @@ static int map_pcm_format(unsigned int fmt_received)
}
}
+static int info_idx_from_ifnum(int card_num, int intf_num, bool enable)
+{
+ int i;
+
+ /*
+ * default index 0 is used when info is allocated upon
+ * first enable audio stream req for a pcm device
+ */
+ if (enable && !uadev[card_num].info)
+ return 0;
+
+ for (i = 0; i < uadev[card_num].num_intf; i++) {
+ if (enable && !uadev[card_num].info[i].in_use)
+ return i;
+ else if (!enable &&
+ uadev[card_num].info[i].intf_num == intf_num)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
static int handle_uaudio_stream_req(void *req_h, void *req)
{
struct qmi_uaudio_stream_req_msg_v01 *req_msg;
@@ -877,7 +897,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
struct intf_info *info;
int pcm_format;
u8 pcm_card_num, pcm_dev_num, direction;
- int intf_num = -1, ret = 0;
+ int info_idx = -EINVAL, ret = 0;
req_msg = (struct qmi_uaudio_stream_req_msg_v01 *)req;
@@ -921,7 +941,8 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
}
mutex_lock(&chip->dev_lock);
- intf_num = subs->interface;
+ info_idx = info_idx_from_ifnum(pcm_card_num, subs->interface,
+ req_msg->enable);
if (atomic_read(&chip->shutdown) || !subs->stream || !subs->stream->pcm
|| !subs->stream->chip) {
ret = -ENODEV;
@@ -929,6 +950,16 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
goto response;
}
+ if (req_msg->enable) {
+ if (info_idx < 0) {
+ pr_err("%s interface# %d already in use card# %d\n",
+ __func__, subs->interface, pcm_card_num);
+ ret = -EBUSY;
+ mutex_unlock(&chip->dev_lock);
+ goto response;
+ }
+ }
+
subs->pcm_format = pcm_format;
subs->channels = req_msg->number_of_ch;
subs->cur_rate = req_msg->bit_rate;
@@ -937,19 +968,18 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
ret = snd_usb_enable_audio_stream(subs, req_msg->enable);
if (!ret && req_msg->enable)
- ret = prepare_qmi_response(subs, &resp, req_msg->xfer_buff_size,
- pcm_card_num, pcm_dev_num);
+ ret = prepare_qmi_response(subs, req_msg, &resp, info_idx);
mutex_unlock(&chip->dev_lock);
response:
if (!req_msg->enable && ret != -EINVAL) {
- if (intf_num >= 0) {
+ if (info_idx >= 0) {
mutex_lock(&chip->dev_lock);
- info = &uadev[pcm_card_num].info[intf_num];
+ info = &uadev[pcm_card_num].info[info_idx];
uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
pr_debug("%s:release resources: intf# %d card# %d\n",
- __func__, intf_num, pcm_card_num);
+ __func__, subs->interface, pcm_card_num);
mutex_unlock(&chip->dev_lock);
}
if (atomic_read(&uadev[pcm_card_num].in_use))