Merge "sound: usb: Map interface context information to interface number"

This commit is contained in:
Linux Build Service Account 2017-01-16 23:06:08 -08:00 committed by Gerrit - the friendly Code Review server
commit b3a739e9c7

View file

@ -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))