aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Pham <jackp@codeaurora.org>2018-01-25 02:58:20 -0500
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-02-12 03:52:54 -0500
commit675272d092e4a5570bace92593776f7348daf4c5 (patch)
tree319e0dd41ec839dfe0dcc4185879060e6f9287d7
parent6cf439e0d37463e42784271179c8a308fd7493c6 (diff)
usb: gadget: f_fs: Use config_ep_by_speed()
In commit 2bfa0719ac2a ("usb: gadget: function: f_fs: pass companion descriptor along") there is a pointer arithmetic bug where the comp_desc is obtained as follows: comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + USB_DT_ENDPOINT_SIZE); Since ds is a pointer to usb_endpoint_descriptor, adding 7 to it ends up going out of bounds (7 * sizeof(struct usb_endpoint_descriptor), which is actually 7*9 bytes) past the SS descriptor. As a result the maxburst value will be read incorrectly, and the UDC driver will also get a garbage comp_desc (assuming it uses it). Since Felipe wrote, "Eventually, f_fs.c should be converted to use config_ep_by_speed() like all other functions, though", let's finally do it. This allows the other usb_ep fields to be properly populated, such as maxpacket and mult. It also eliminates the awkward speed-based descriptor lookup since config_ep_by_speed() does that already using the ones found in struct usb_function. Fixes: 2bfa0719ac2a ("usb: gadget: function: f_fs: pass companion descriptor along") Cc: stable@vger.kernel.org Signed-off-by: Jack Pham <jackp@codeaurora.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/gadget/function/f_fs.c38
1 files changed, 7 insertions, 31 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 49fc589fbf58..c2592d883f67 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1855,44 +1855,20 @@ static int ffs_func_eps_enable(struct ffs_function *func)
1855 1855
1856 spin_lock_irqsave(&func->ffs->eps_lock, flags); 1856 spin_lock_irqsave(&func->ffs->eps_lock, flags);
1857 while(count--) { 1857 while(count--) {
1858 struct usb_endpoint_descriptor *ds;
1859 struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
1860 int needs_comp_desc = false;
1861 int desc_idx;
1862
1863 if (ffs->gadget->speed == USB_SPEED_SUPER) {
1864 desc_idx = 2;
1865 needs_comp_desc = true;
1866 } else if (ffs->gadget->speed == USB_SPEED_HIGH)
1867 desc_idx = 1;
1868 else
1869 desc_idx = 0;
1870
1871 /* fall-back to lower speed if desc missing for current speed */
1872 do {
1873 ds = ep->descs[desc_idx];
1874 } while (!ds && --desc_idx >= 0);
1875
1876 if (!ds) {
1877 ret = -EINVAL;
1878 break;
1879 }
1880
1881 ep->ep->driver_data = ep; 1858 ep->ep->driver_data = ep;
1882 ep->ep->desc = ds;
1883 1859
1884 if (needs_comp_desc) { 1860 ret = config_ep_by_speed(func->gadget, &func->function, ep->ep);
1885 comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + 1861 if (ret) {
1886 USB_DT_ENDPOINT_SIZE); 1862 pr_err("%s: config_ep_by_speed(%s) returned %d\n",
1887 ep->ep->maxburst = comp_desc->bMaxBurst + 1; 1863 __func__, ep->ep->name, ret);
1888 ep->ep->comp_desc = comp_desc; 1864 break;
1889 } 1865 }
1890 1866
1891 ret = usb_ep_enable(ep->ep); 1867 ret = usb_ep_enable(ep->ep);
1892 if (likely(!ret)) { 1868 if (likely(!ret)) {
1893 epfile->ep = ep; 1869 epfile->ep = ep;
1894 epfile->in = usb_endpoint_dir_in(ds); 1870 epfile->in = usb_endpoint_dir_in(ep->ep->desc);
1895 epfile->isoc = usb_endpoint_xfer_isoc(ds); 1871 epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc);
1896 } else { 1872 } else {
1897 break; 1873 break;
1898 } 1874 }