in most_usb.c [457:533]
static int hdm_enqueue(struct most_interface *iface, int channel,
struct mbo *mbo)
{
struct most_dev *mdev = to_mdev(iface);
struct most_channel_config *conf;
int retval = 0;
struct urb *urb;
unsigned long length;
void *virt_address;
if (!mbo)
return -EINVAL;
if (iface->num_channels <= channel || channel < 0)
return -ECHRNG;
urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_KERNEL);
if (!urb)
return -ENOMEM;
conf = &mdev->conf[channel];
mutex_lock(&mdev->io_mutex);
if (!mdev->usb_device) {
retval = -ENODEV;
goto err_free_urb;
}
if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] &&
hdm_add_padding(mdev, channel, mbo)) {
retval = -EINVAL;
goto err_free_urb;
}
urb->transfer_dma = mbo->bus_address;
virt_address = mbo->virt_address;
length = mbo->buffer_length;
if (conf->direction & MOST_CH_TX) {
usb_fill_bulk_urb(urb, mdev->usb_device,
usb_sndbulkpipe(mdev->usb_device,
mdev->ep_address[channel]),
virt_address,
length,
hdm_write_completion,
mbo);
if (conf->data_type != MOST_CH_ISOC &&
conf->data_type != MOST_CH_SYNC)
urb->transfer_flags |= URB_ZERO_PACKET;
} else {
usb_fill_bulk_urb(urb, mdev->usb_device,
usb_rcvbulkpipe(mdev->usb_device,
mdev->ep_address[channel]),
virt_address,
length + conf->extra_len,
hdm_read_completion,
mbo);
}
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_anchor_urb(urb, &mdev->busy_urbs[channel]);
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
dev_err(&mdev->usb_device->dev,
"URB submit failed with error %d.\n", retval);
goto err_unanchor_urb;
}
mutex_unlock(&mdev->io_mutex);
return 0;
err_unanchor_urb:
usb_unanchor_urb(urb);
err_free_urb:
usb_free_urb(urb);
mutex_unlock(&mdev->io_mutex);
return retval;
}