mirror of https://gitee.com/openkylin/linux.git
Merge branch 'topic/usb-ep-check-v2' into for-next
Pulling the EP validity checks in USB audio drivers. It also adds a new helper in USB core, which was acked by Greg. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
8ed5d192c0
|
@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
static const int pipetypes[4] = {
|
||||
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
|
||||
};
|
||||
|
||||
/**
|
||||
* usb_urb_ep_type_check - sanity check of endpoint in the given urb
|
||||
* @urb: urb to be checked
|
||||
*
|
||||
* This performs a light-weight sanity check for the endpoint in the
|
||||
* given urb. It returns 0 if the urb contains a valid endpoint, otherwise
|
||||
* a negative error code.
|
||||
*/
|
||||
int usb_urb_ep_type_check(const struct urb *urb)
|
||||
{
|
||||
const struct usb_host_endpoint *ep;
|
||||
|
||||
ep = usb_pipe_endpoint(urb->dev, urb->pipe);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_urb_ep_type_check);
|
||||
|
||||
/**
|
||||
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
|
||||
* @urb: pointer to the urb describing the request
|
||||
|
@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||
*/
|
||||
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||
{
|
||||
static int pipetypes[4] = {
|
||||
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
|
||||
};
|
||||
int xfertype, max;
|
||||
struct usb_device *dev;
|
||||
struct usb_host_endpoint *ep;
|
||||
|
@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||
*/
|
||||
|
||||
/* Check that the pipe's type matches the endpoint's type */
|
||||
if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
|
||||
if (usb_urb_ep_type_check(urb))
|
||||
dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
|
||||
usb_pipetype(urb->pipe), pipetypes[xfertype]);
|
||||
|
||||
|
|
|
@ -1728,6 +1728,8 @@ static inline int usb_urb_dir_out(struct urb *urb)
|
|||
return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
|
||||
}
|
||||
|
||||
int usb_urb_ep_type_check(const struct urb *urb);
|
||||
|
||||
void *usb_alloc_coherent(struct usb_device *dev, size_t size,
|
||||
gfp_t mem_flags, dma_addr_t *dma);
|
||||
void usb_free_coherent(struct usb_device *dev, size_t size,
|
||||
|
|
|
@ -342,6 +342,13 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)
|
|||
bcd2k->midi_out_buf, BUFSIZE,
|
||||
bcd2000_output_complete, bcd2k, 1);
|
||||
|
||||
/* sanity checks of EPs before actually submitting */
|
||||
if (usb_urb_ep_type_check(bcd2k->midi_in_urb) ||
|
||||
usb_urb_ep_type_check(bcd2k->midi_out_urb)) {
|
||||
dev_err(&bcd2k->dev->dev, "invalid MIDI EP\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcd2000_init_device(bcd2k);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -461,6 +461,13 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
|
|||
cdev->midi_out_buf, EP1_BUFSIZE,
|
||||
snd_usb_caiaq_midi_output_done, cdev);
|
||||
|
||||
/* sanity checks of EPs before actually submitting */
|
||||
if (usb_urb_ep_type_check(&cdev->ep1_in_urb) ||
|
||||
usb_urb_ep_type_check(&cdev->midi_out_urb)) {
|
||||
dev_err(dev, "invalid EPs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&cdev->ep1_wait_queue);
|
||||
init_waitqueue_head(&cdev->prepare_wait_queue);
|
||||
|
||||
|
|
|
@ -718,6 +718,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
|
|||
usb_rcvbulkpipe(usb_dev, 0x4),
|
||||
cdev->ep4_in_buf, EP4_BUFSIZE,
|
||||
snd_usb_caiaq_ep4_reply_dispatch, cdev);
|
||||
ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
|
||||
if (ret < 0)
|
||||
goto exit_free_idev;
|
||||
|
||||
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
|
||||
|
||||
|
@ -757,6 +760,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
|
|||
usb_rcvbulkpipe(usb_dev, 0x4),
|
||||
cdev->ep4_in_buf, EP4_BUFSIZE,
|
||||
snd_usb_caiaq_ep4_reply_dispatch, cdev);
|
||||
ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
|
||||
if (ret < 0)
|
||||
goto exit_free_idev;
|
||||
|
||||
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
|
||||
|
||||
|
@ -802,6 +808,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
|
|||
usb_rcvbulkpipe(usb_dev, 0x4),
|
||||
cdev->ep4_in_buf, EP4_BUFSIZE,
|
||||
snd_usb_caiaq_ep4_reply_dispatch, cdev);
|
||||
ret = usb_urb_ep_type_check(cdev->ep4_in_urb);
|
||||
if (ret < 0)
|
||||
goto exit_free_idev;
|
||||
|
||||
snd_usb_caiaq_set_auto_msg(cdev, 1, 10, 5);
|
||||
break;
|
||||
|
|
|
@ -541,6 +541,8 @@ static int hiface_pcm_init_urb(struct pcm_urb *urb,
|
|||
usb_fill_bulk_urb(&urb->instance, chip->dev,
|
||||
usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
|
||||
PCM_PACKET_SIZE, handler, urb);
|
||||
if (usb_urb_ep_type_check(&urb->instance))
|
||||
return -EINVAL;
|
||||
init_usb_anchor(&urb->submitted);
|
||||
|
||||
return 0;
|
||||
|
@ -599,9 +601,12 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
|
|||
mutex_init(&rt->stream_mutex);
|
||||
spin_lock_init(&rt->playback.lock);
|
||||
|
||||
for (i = 0; i < PCM_N_URBS; i++)
|
||||
hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
|
||||
for (i = 0; i < PCM_N_URBS; i++) {
|
||||
ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
|
||||
hiface_pcm_out_urb_handler);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -78,6 +78,13 @@ static int line6_start_listen(struct usb_line6 *line6)
|
|||
line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
|
||||
line6_data_received, line6);
|
||||
}
|
||||
|
||||
/* sanity checks of EP before actually submitting */
|
||||
if (usb_urb_ep_type_check(line6->urb_listen)) {
|
||||
dev_err(line6->ifcdev, "invalid control EP\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
line6->urb_listen->actual_length = 0;
|
||||
err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
|
||||
return err;
|
||||
|
@ -168,17 +175,24 @@ static int line6_send_raw_message_async_part(struct message *msg,
|
|||
}
|
||||
|
||||
msg->done += bytes;
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
||||
if (retval < 0) {
|
||||
dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
|
||||
__func__, retval);
|
||||
usb_free_urb(urb);
|
||||
kfree(msg);
|
||||
return retval;
|
||||
}
|
||||
/* sanity checks of EP before actually submitting */
|
||||
retval = usb_urb_ep_type_check(urb);
|
||||
if (retval < 0)
|
||||
goto error;
|
||||
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (retval < 0)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
|
||||
__func__, retval);
|
||||
usb_free_urb(urb);
|
||||
kfree(msg);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -130,16 +130,21 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
|
|||
transfer_buffer, length, midi_sent, line6,
|
||||
line6->interval);
|
||||
urb->actual_length = 0;
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
retval = usb_urb_ep_type_check(urb);
|
||||
if (retval < 0)
|
||||
goto error;
|
||||
|
||||
if (retval < 0) {
|
||||
dev_err(line6->ifcdev, "usb_submit_urb failed\n");
|
||||
usb_free_urb(urb);
|
||||
return retval;
|
||||
}
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (retval < 0)
|
||||
goto error;
|
||||
|
||||
++line6->line6midi->num_active_send_urbs;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dev_err(line6->ifcdev, "usb_submit_urb failed\n");
|
||||
usb_free_urb(urb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
|
||||
|
|
|
@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
|
|||
unsigned int pipe;
|
||||
int length;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
rep->in = NULL;
|
||||
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
|
||||
|
@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
|
|||
for (i = 0; i < INPUT_URBS; ++i) {
|
||||
ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!ep->urbs[i]) {
|
||||
snd_usbmidi_in_endpoint_delete(ep);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (ep_info->in_interval)
|
||||
|
@ -1305,8 +1306,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
|
|||
buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
|
||||
&ep->urbs[i]->transfer_dma);
|
||||
if (!buffer) {
|
||||
snd_usbmidi_in_endpoint_delete(ep);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (ep_info->in_interval)
|
||||
usb_fill_int_urb(ep->urbs[i], umidi->dev,
|
||||
|
@ -1318,10 +1319,20 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
|
|||
pipe, buffer, length,
|
||||
snd_usbmidi_in_urb_complete, ep);
|
||||
ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
|
||||
err = usb_urb_ep_type_check(ep->urbs[i]);
|
||||
if (err < 0) {
|
||||
dev_err(&umidi->dev->dev, "invalid MIDI in EP %x\n",
|
||||
ep_info->in_ep);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rep->in = ep;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
snd_usbmidi_in_endpoint_delete(ep);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1357,6 +1368,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
|
|||
unsigned int i;
|
||||
unsigned int pipe;
|
||||
void *buffer;
|
||||
int err;
|
||||
|
||||
rep->out = NULL;
|
||||
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
|
||||
|
@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
|
|||
for (i = 0; i < OUTPUT_URBS; ++i) {
|
||||
ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!ep->urbs[i].urb) {
|
||||
snd_usbmidi_out_endpoint_delete(ep);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
ep->urbs[i].ep = ep;
|
||||
}
|
||||
|
@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
|
|||
ep->max_transfer, GFP_KERNEL,
|
||||
&ep->urbs[i].urb->transfer_dma);
|
||||
if (!buffer) {
|
||||
snd_usbmidi_out_endpoint_delete(ep);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (ep_info->out_interval)
|
||||
usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
|
||||
|
@ -1419,6 +1431,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
|
|||
pipe, buffer, ep->max_transfer,
|
||||
snd_usbmidi_out_urb_complete,
|
||||
&ep->urbs[i]);
|
||||
err = usb_urb_ep_type_check(ep->urbs[i].urb);
|
||||
if (err < 0) {
|
||||
dev_err(&umidi->dev->dev, "invalid MIDI out EP %x\n",
|
||||
ep_info->out_ep);
|
||||
goto error;
|
||||
}
|
||||
ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
|
||||
}
|
||||
|
||||
|
@ -1437,6 +1455,10 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
|
|||
|
||||
rep->out = ep;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
snd_usbmidi_out_endpoint_delete(ep);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -279,6 +279,9 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
|
|||
usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
|
||||
i_usX2Y_Out04Int, usX2Y
|
||||
);
|
||||
err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -298,6 +301,8 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y)
|
|||
usX2Y->In04Buf, 21,
|
||||
i_usX2Y_In04Int, usX2Y,
|
||||
10);
|
||||
if (usb_urb_ep_type_check(usX2Y->In04urb))
|
||||
return -EINVAL;
|
||||
return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
|
||||
}
|
||||
|
||||
|
|
|
@ -677,6 +677,9 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
|
|||
usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4),
|
||||
usbdata + i, 2, i_usX2Y_04Int, usX2Y);
|
||||
}
|
||||
err = usb_urb_ep_type_check(us->urb[0]);
|
||||
if (err < 0)
|
||||
goto cleanup;
|
||||
us->submitted = 0;
|
||||
us->len = NOOF_SETRATE_URBS;
|
||||
usX2Y->US04 = us;
|
||||
|
|
Loading…
Reference in New Issue