in most_usb.c [566:635]
static int hdm_configure_channel(struct most_interface *iface, int channel,
struct most_channel_config *conf)
{
unsigned int num_frames;
unsigned int frame_size;
struct most_dev *mdev = to_mdev(iface);
struct device *dev = &mdev->usb_device->dev;
if (!conf) {
dev_err(dev, "Bad config pointer.\n");
return -EINVAL;
}
if (channel < 0 || channel >= iface->num_channels) {
dev_err(dev, "Channel ID out of range.\n");
return -EINVAL;
}
mdev->is_channel_healthy[channel] = true;
mdev->clear_work[channel].channel = channel;
mdev->clear_work[channel].mdev = mdev;
INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt);
if (!conf->num_buffers || !conf->buffer_size) {
dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
return -EINVAL;
}
if (conf->data_type != MOST_CH_SYNC &&
!(conf->data_type == MOST_CH_ISOC &&
conf->packets_per_xact != 0xFF)) {
mdev->padding_active[channel] = false;
/*
* Since the NIC's padding mode is not going to be
* used, we can skip the frame size calculations and
* move directly on to exit.
*/
goto exit;
}
mdev->padding_active[channel] = true;
frame_size = get_stream_frame_size(&mdev->dev, conf);
if (frame_size == 0 || frame_size > USB_MTU) {
dev_warn(dev, "Misconfig: frame size wrong\n");
return -EINVAL;
}
num_frames = conf->buffer_size / frame_size;
if (conf->buffer_size % frame_size) {
u16 old_size = conf->buffer_size;
conf->buffer_size = num_frames * frame_size;
dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n",
mdev->suffix[channel], old_size, conf->buffer_size);
}
/* calculate extra length to comply w/ HW padding */
conf->extra_len = num_frames * (USB_MTU - frame_size);
exit:
mdev->conf[channel] = *conf;
if (conf->data_type == MOST_CH_ASYNC) {
u16 ep = mdev->ep_address[channel];
if (start_sync_ep(mdev->usb_device, ep) < 0)
dev_warn(dev, "sync for ep%02x failed", ep);
}
return 0;
}