mirror of https://gitee.com/openkylin/linux.git
USB: fixes for v4.14-rc5
A deadlock fix in dummy-hcd; Fixing a use-after-free bug in composite; Renesas got another fix for DMA programming (this time around a fix for receiving ZLP); Tegra PHY got a suspend fix; A memory leak on our configfs ABI got plugged. Other than these, a couple other minor fixes on usbtest. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEElLzh7wn96CXwjh2IzL64meEamQYFAlnfLs4ACgkQzL64meEa mQblUQ/9HFiX4p7z908QkU6JhESyE89T3C4N7309E6JbHlr7whjlQWRvYnmaDsN1 R6EvpsrYuuiuG2peoHeOy9LwrQ2ULTo59X6TYAGxN8+t51lnDkWWZBVMlOACqKMd SQExYw/Ik4UJiFQdrD5TDa/+sAC5uZYKFST9cYp7v+Rt0PEqjT41rgdDXHHfRuQc cpSfBxDfcZwcmV/xJAn9RLfGmg+SDMHqPHZY1lph7ayrn/xZ4G2eQmkBAOGqJB9y O+GQCRVzhX2N5HiFLKvwehx1AvUUrqosE6w8wE7JkefGnfvgjy+JfUqJ71GhbSu3 tn/zVEBC3hgpr+ccQepzdFtScynQoRnMwa6yuV3W5zlgiy0f3nR6X82nFnNZmpks H1gbmTOK/jGIsFq5j5pOsd50Ch157VYG1wMz7el0Jig+derVIaxLcBaRK3ZvNfVO qx1s9WztXlJ42XJDaWfBr8ieemWcSSHO0fA+EXQ3NkdN/OR38FS+4RwhrlMKp0lG XFWaLhDUOHZ+SAak9L5FjzVLpxC1dmqYziY35oax4Jvm7yrjhdB+be+tnXFiE7yW nMXW22bM4jVJhGg9SKjBvW5kiKijYBFbkAGsH9hVswVQLrVtZXUofyfypTgGqI02 85y/1cN9o5gjQAH3Rc7eH0qmza7ouhi2a/BV+NsQY4I9ZFe2bq0= =uGcr -----END PGP SIGNATURE----- Merge tag 'fixes-for-v4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: USB: fixes for v4.14-rc5 A deadlock fix in dummy-hcd; Fixing a use-after-free bug in composite; Renesas got another fix for DMA programming (this time around a fix for receiving ZLP); Tegra PHY got a suspend fix; A memory leak on our configfs ABI got plugged. Other than these, a couple other minor fixes on usbtest.
This commit is contained in:
commit
2d30408ecf
|
@ -2026,6 +2026,8 @@ static DEVICE_ATTR_RO(suspended);
|
|||
static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
|
||||
{
|
||||
struct usb_composite_dev *cdev = get_gadget_data(gadget);
|
||||
struct usb_gadget_strings *gstr = cdev->driver->strings[0];
|
||||
struct usb_string *dev_str = gstr->strings;
|
||||
|
||||
/* composite_disconnect() must already have been called
|
||||
* by the underlying peripheral controller driver!
|
||||
|
@ -2045,6 +2047,9 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
|
|||
|
||||
composite_dev_cleanup(cdev);
|
||||
|
||||
if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer)
|
||||
dev_str[USB_GADGET_MANUFACTURER_IDX].s = "";
|
||||
|
||||
kfree(cdev->def_manufacturer);
|
||||
kfree(cdev);
|
||||
set_gadget_data(gadget, NULL);
|
||||
|
|
|
@ -1143,11 +1143,12 @@ static struct configfs_attribute *interf_grp_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
||||
int n_interf,
|
||||
struct usb_os_desc **desc,
|
||||
char **names,
|
||||
struct module *owner)
|
||||
struct config_group *usb_os_desc_prepare_interf_dir(
|
||||
struct config_group *parent,
|
||||
int n_interf,
|
||||
struct usb_os_desc **desc,
|
||||
char **names,
|
||||
struct module *owner)
|
||||
{
|
||||
struct config_group *os_desc_group;
|
||||
struct config_item_type *os_desc_type, *interface_type;
|
||||
|
@ -1159,7 +1160,7 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
|||
|
||||
char *vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL);
|
||||
if (!vlabuf)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group);
|
||||
os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type);
|
||||
|
@ -1184,7 +1185,7 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
|||
configfs_add_default_group(&d->group, os_desc_group);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return os_desc_group;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_os_desc_prepare_interf_dir);
|
||||
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
|
||||
void unregister_gadget_item(struct config_item *item);
|
||||
|
||||
int usb_os_desc_prepare_interf_dir(struct config_group *parent,
|
||||
int n_interf,
|
||||
struct usb_os_desc **desc,
|
||||
char **names,
|
||||
struct module *owner);
|
||||
struct config_group *usb_os_desc_prepare_interf_dir(
|
||||
struct config_group *parent,
|
||||
int n_interf,
|
||||
struct usb_os_desc **desc,
|
||||
char **names,
|
||||
struct module *owner);
|
||||
|
||||
static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item)
|
||||
{
|
||||
|
|
|
@ -908,6 +908,7 @@ static void rndis_free_inst(struct usb_function_instance *f)
|
|||
free_netdev(opts->net);
|
||||
}
|
||||
|
||||
kfree(opts->rndis_interf_group); /* single VLA chunk */
|
||||
kfree(opts);
|
||||
}
|
||||
|
||||
|
@ -916,6 +917,7 @@ static struct usb_function_instance *rndis_alloc_inst(void)
|
|||
struct f_rndis_opts *opts;
|
||||
struct usb_os_desc *descs[1];
|
||||
char *names[1];
|
||||
struct config_group *rndis_interf_group;
|
||||
|
||||
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
|
||||
if (!opts)
|
||||
|
@ -940,8 +942,14 @@ static struct usb_function_instance *rndis_alloc_inst(void)
|
|||
names[0] = "rndis";
|
||||
config_group_init_type_name(&opts->func_inst.group, "",
|
||||
&rndis_func_type);
|
||||
usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
|
||||
names, THIS_MODULE);
|
||||
rndis_interf_group =
|
||||
usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
|
||||
names, THIS_MODULE);
|
||||
if (IS_ERR(rndis_interf_group)) {
|
||||
rndis_free_inst(&opts->func_inst);
|
||||
return ERR_CAST(rndis_interf_group);
|
||||
}
|
||||
opts->rndis_interf_group = rndis_interf_group;
|
||||
|
||||
return &opts->func_inst;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ struct f_rndis_opts {
|
|||
bool bound;
|
||||
bool borrowed_net;
|
||||
|
||||
struct config_group *rndis_interf_group;
|
||||
struct usb_os_desc rndis_os_desc;
|
||||
char rndis_ext_compat_id[16];
|
||||
|
||||
|
|
|
@ -419,6 +419,7 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
|
|||
static void set_link_state(struct dummy_hcd *dum_hcd)
|
||||
{
|
||||
struct dummy *dum = dum_hcd->dum;
|
||||
unsigned int power_bit;
|
||||
|
||||
dum_hcd->active = 0;
|
||||
if (dum->pullup)
|
||||
|
@ -429,17 +430,19 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
|
|||
return;
|
||||
|
||||
set_link_state_by_speed(dum_hcd);
|
||||
power_bit = (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 ?
|
||||
USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER);
|
||||
|
||||
if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
|
||||
dum_hcd->active)
|
||||
dum_hcd->resuming = 0;
|
||||
|
||||
/* Currently !connected or in reset */
|
||||
if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 ||
|
||||
if ((dum_hcd->port_status & power_bit) == 0 ||
|
||||
(dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
|
||||
unsigned disconnect = USB_PORT_STAT_CONNECTION &
|
||||
unsigned int disconnect = power_bit &
|
||||
dum_hcd->old_status & (~dum_hcd->port_status);
|
||||
unsigned reset = USB_PORT_STAT_RESET &
|
||||
unsigned int reset = USB_PORT_STAT_RESET &
|
||||
(~dum_hcd->old_status) & dum_hcd->port_status;
|
||||
|
||||
/* Report reset and disconnect events to the driver */
|
||||
|
|
|
@ -202,12 +202,13 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
if (in) {
|
||||
if (in)
|
||||
dev->in_pipe = usb_rcvbulkpipe(udev,
|
||||
in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
|
||||
if (out)
|
||||
dev->out_pipe = usb_sndbulkpipe(udev,
|
||||
out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
|
||||
}
|
||||
|
||||
if (iso_in) {
|
||||
dev->iso_in = &iso_in->desc;
|
||||
dev->in_iso_pipe = usb_rcvisocpipe(udev,
|
||||
|
@ -1964,6 +1965,9 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param,
|
|||
int status = 0;
|
||||
struct urb *urbs[param->sglen];
|
||||
|
||||
if (!param->sglen || param->iterations > UINT_MAX / param->sglen)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.count = param->iterations * param->sglen;
|
||||
context.dev = dev;
|
||||
|
@ -2087,6 +2091,8 @@ usbtest_do_ioctl(struct usb_interface *intf, struct usbtest_param_32 *param)
|
|||
|
||||
if (param->iterations <= 0)
|
||||
return -EINVAL;
|
||||
if (param->sglen > MAX_SGLEN)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* Just a bunch of test cases that every HCD is expected to handle.
|
||||
*
|
||||
|
|
|
@ -329,6 +329,14 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
|
|||
unsigned long val;
|
||||
void __iomem *base = phy->regs;
|
||||
|
||||
/*
|
||||
* The USB driver may have already initiated the phy clock
|
||||
* disable so wait to see if the clock turns off and if not
|
||||
* then proceed with gating the clock.
|
||||
*/
|
||||
if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) == 0)
|
||||
return;
|
||||
|
||||
if (phy->is_legacy_phy) {
|
||||
val = readl(base + USB_SUSP_CTRL);
|
||||
val |= USB_SUSP_SET;
|
||||
|
@ -351,6 +359,15 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
|
|||
unsigned long val;
|
||||
void __iomem *base = phy->regs;
|
||||
|
||||
/*
|
||||
* The USB driver may have already initiated the phy clock
|
||||
* enable so wait to see if the clock turns on and if not
|
||||
* then proceed with ungating the clock.
|
||||
*/
|
||||
if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
|
||||
USB_PHY_CLK_VALID) == 0)
|
||||
return;
|
||||
|
||||
if (phy->is_legacy_phy) {
|
||||
val = readl(base + USB_SUSP_CTRL);
|
||||
val |= USB_SUSP_CLR;
|
||||
|
|
|
@ -857,9 +857,9 @@ static void xfer_work(struct work_struct *work)
|
|||
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
|
||||
|
||||
usbhs_pipe_running(pipe, 1);
|
||||
usbhsf_dma_start(pipe, fifo);
|
||||
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
|
||||
dma_async_issue_pending(chan);
|
||||
usbhsf_dma_start(pipe, fifo);
|
||||
usbhs_pipe_enable(pipe);
|
||||
|
||||
xfer_work_end:
|
||||
|
|
Loading…
Reference in New Issue