Loading sound/usb/usb_audio_qmi_svc.c +62 −32 Original line number Diff line number Diff line Loading @@ -68,6 +68,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; Loading Loading @@ -390,10 +391,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; Loading @@ -402,10 +402,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; Loading @@ -417,13 +418,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); Loading Loading @@ -654,18 +651,19 @@ static int prepare_qmi_response(struct snd_usb_substream *subs, 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); Loading Loading @@ -722,7 +720,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 */ Loading Loading @@ -866,6 +864,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; Loading @@ -876,7 +896,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; Loading Loading @@ -920,7 +940,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; Loading @@ -928,6 +949,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; Loading @@ -936,19 +967,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)) Loading Loading
sound/usb/usb_audio_qmi_svc.c +62 −32 Original line number Diff line number Diff line Loading @@ -68,6 +68,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; Loading Loading @@ -390,10 +391,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; Loading @@ -402,10 +402,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; Loading @@ -417,13 +418,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); Loading Loading @@ -654,18 +651,19 @@ static int prepare_qmi_response(struct snd_usb_substream *subs, 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); Loading Loading @@ -722,7 +720,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 */ Loading Loading @@ -866,6 +864,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; Loading @@ -876,7 +896,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; Loading Loading @@ -920,7 +940,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; Loading @@ -928,6 +949,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; Loading @@ -936,19 +967,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)) Loading