diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-01-16 23:06:08 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-01-16 23:06:08 -0800 |
commit | b3a739e9c7815a310b0ec96f3a21ba75551665e3 (patch) | |
tree | b01b5d6d0f2a52da846017e7540fd1f19a15b13a /sound | |
parent | 79383e7ce6996fd8d0f40f219d2754d5d3197883 (diff) | |
parent | c179cf38896f3d171ed7321b7b077d834676fb73 (diff) |
Merge "sound: usb: Map interface context information to interface number"
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/usb_audio_qmi_svc.c | 94 |
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)) |