usb: fixes for-v4.2-rc2
The first set of fixes for this -rc cycle. Most importantly we have a NULL pointer dereference fix on DWC3, a fix to a really old bug on musb_start() and another NULL pointer dereference fix on MXS phy driver. Signed-off-by: Felipe Balbi <balbi@ti.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIbBAABAgAGBQJVnAuoAAoJEIaOsuA1yqREjDAP+Mh3RWLDjqOywy0oI11FOJdO 6F5kDAPlb1uOiD9aNzR/w1lMAGABvMkIN7a9KSWmP/IiL0kqvnF3yHg7HF1vPeab 4U/qGD/ote6fx2EQywI9Gd1vX133m5EQa+GuTsqHoRlh/K5MLo+VnNd6Blwv4oc/ iCGaiJh/n14nNOEj7B4+UXem59VfPQeSBZs+UdFXWXTMsaNlkdWHGeXRkovIiiSn E0soCZ2qsWjDBKbp7JqRg86+suSJPVQEqnT3KBEL9e/GOgzY3nA/I2oEbXyL7S3n liTHeL1PzbGp3+8GQ5Sd5zRziUUCnipAonn/3rNXniCJPqeKI8frzkVgjrSgRilD 2yio3cKp74RgNLjk0XpiLebHF4d0YVrh2LlxPBbdknuuVOt99WG9BIr2PMP9pMMb cDtMFfgKWlGAU9fecAzQNqD/1NKp4ohKbNOUhd6nZXhX7Q0fqTWBcgatuOXqbtbS UVsflelQmV8Moz4+cXy6QiulejP4p93Eid35Z77OGlxflnCsSSyuWZaO7bsP53u5 bs02XE/sfMHl+yZLlexuQ8DVFm5cHydSmQ1wzuRJ7rdyDqdQWZEAYuFwEgeeB8Zv PR5xJYTKsBY+w3Y0PI1BLvVFp8wREvy/Y5tH26HrXCtMe7kgSBHXqFXZiIang2bx K6VQJSvLKzjNG0HnO0M= =Dnp/ -----END PGP SIGNATURE----- Merge tag 'fixes-for-v4.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: usb: fixes for-v4.2-rc2 The first set of fixes for this -rc cycle. Most importantly we have a NULL pointer dereference fix on DWC3, a fix to a really old bug on musb_start() and another NULL pointer dereference fix on MXS phy driver. Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
commit
d4669bb142
|
@ -72,17 +72,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
|
||||||
dev_dbg(hsotg->dev, "%s\n", __func__);
|
dev_dbg(hsotg->dev, "%s\n", __func__);
|
||||||
|
|
||||||
/* Backup Host regs */
|
/* Backup Host regs */
|
||||||
hr = hsotg->hr_backup;
|
hr = &hsotg->hr_backup;
|
||||||
if (!hr) {
|
|
||||||
hr = devm_kzalloc(hsotg->dev, sizeof(*hr), GFP_KERNEL);
|
|
||||||
if (!hr) {
|
|
||||||
dev_err(hsotg->dev, "%s: can't allocate host regs\n",
|
|
||||||
__func__);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
hsotg->hr_backup = hr;
|
|
||||||
}
|
|
||||||
hr->hcfg = readl(hsotg->regs + HCFG);
|
hr->hcfg = readl(hsotg->regs + HCFG);
|
||||||
hr->haintmsk = readl(hsotg->regs + HAINTMSK);
|
hr->haintmsk = readl(hsotg->regs + HAINTMSK);
|
||||||
for (i = 0; i < hsotg->core_params->host_channels; ++i)
|
for (i = 0; i < hsotg->core_params->host_channels; ++i)
|
||||||
|
@ -90,6 +80,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
|
||||||
|
|
||||||
hr->hprt0 = readl(hsotg->regs + HPRT0);
|
hr->hprt0 = readl(hsotg->regs + HPRT0);
|
||||||
hr->hfir = readl(hsotg->regs + HFIR);
|
hr->hfir = readl(hsotg->regs + HFIR);
|
||||||
|
hr->valid = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -109,12 +100,13 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
|
||||||
dev_dbg(hsotg->dev, "%s\n", __func__);
|
dev_dbg(hsotg->dev, "%s\n", __func__);
|
||||||
|
|
||||||
/* Restore host regs */
|
/* Restore host regs */
|
||||||
hr = hsotg->hr_backup;
|
hr = &hsotg->hr_backup;
|
||||||
if (!hr) {
|
if (!hr->valid) {
|
||||||
dev_err(hsotg->dev, "%s: no host registers to restore\n",
|
dev_err(hsotg->dev, "%s: no host registers to restore\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hr->valid = false;
|
||||||
|
|
||||||
writel(hr->hcfg, hsotg->regs + HCFG);
|
writel(hr->hcfg, hsotg->regs + HCFG);
|
||||||
writel(hr->haintmsk, hsotg->regs + HAINTMSK);
|
writel(hr->haintmsk, hsotg->regs + HAINTMSK);
|
||||||
|
@ -152,17 +144,7 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
|
||||||
dev_dbg(hsotg->dev, "%s\n", __func__);
|
dev_dbg(hsotg->dev, "%s\n", __func__);
|
||||||
|
|
||||||
/* Backup dev regs */
|
/* Backup dev regs */
|
||||||
dr = hsotg->dr_backup;
|
dr = &hsotg->dr_backup;
|
||||||
if (!dr) {
|
|
||||||
dr = devm_kzalloc(hsotg->dev, sizeof(*dr), GFP_KERNEL);
|
|
||||||
if (!dr) {
|
|
||||||
dev_err(hsotg->dev, "%s: can't allocate device regs\n",
|
|
||||||
__func__);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
hsotg->dr_backup = dr;
|
|
||||||
}
|
|
||||||
|
|
||||||
dr->dcfg = readl(hsotg->regs + DCFG);
|
dr->dcfg = readl(hsotg->regs + DCFG);
|
||||||
dr->dctl = readl(hsotg->regs + DCTL);
|
dr->dctl = readl(hsotg->regs + DCTL);
|
||||||
|
@ -195,7 +177,7 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
|
||||||
dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i));
|
dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i));
|
||||||
dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i));
|
dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i));
|
||||||
}
|
}
|
||||||
|
dr->valid = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,12 +197,13 @@ static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
|
||||||
dev_dbg(hsotg->dev, "%s\n", __func__);
|
dev_dbg(hsotg->dev, "%s\n", __func__);
|
||||||
|
|
||||||
/* Restore dev regs */
|
/* Restore dev regs */
|
||||||
dr = hsotg->dr_backup;
|
dr = &hsotg->dr_backup;
|
||||||
if (!dr) {
|
if (!dr->valid) {
|
||||||
dev_err(hsotg->dev, "%s: no device registers to restore\n",
|
dev_err(hsotg->dev, "%s: no device registers to restore\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
dr->valid = false;
|
||||||
|
|
||||||
writel(dr->dcfg, hsotg->regs + DCFG);
|
writel(dr->dcfg, hsotg->regs + DCFG);
|
||||||
writel(dr->dctl, hsotg->regs + DCTL);
|
writel(dr->dctl, hsotg->regs + DCTL);
|
||||||
|
@ -268,17 +251,7 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Backup global regs */
|
/* Backup global regs */
|
||||||
gr = hsotg->gr_backup;
|
gr = &hsotg->gr_backup;
|
||||||
if (!gr) {
|
|
||||||
gr = devm_kzalloc(hsotg->dev, sizeof(*gr), GFP_KERNEL);
|
|
||||||
if (!gr) {
|
|
||||||
dev_err(hsotg->dev, "%s: can't allocate global regs\n",
|
|
||||||
__func__);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
hsotg->gr_backup = gr;
|
|
||||||
}
|
|
||||||
|
|
||||||
gr->gotgctl = readl(hsotg->regs + GOTGCTL);
|
gr->gotgctl = readl(hsotg->regs + GOTGCTL);
|
||||||
gr->gintmsk = readl(hsotg->regs + GINTMSK);
|
gr->gintmsk = readl(hsotg->regs + GINTMSK);
|
||||||
|
@ -291,6 +264,7 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
|
||||||
for (i = 0; i < MAX_EPS_CHANNELS; i++)
|
for (i = 0; i < MAX_EPS_CHANNELS; i++)
|
||||||
gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i));
|
gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i));
|
||||||
|
|
||||||
|
gr->valid = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,12 +283,13 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
|
||||||
dev_dbg(hsotg->dev, "%s\n", __func__);
|
dev_dbg(hsotg->dev, "%s\n", __func__);
|
||||||
|
|
||||||
/* Restore global regs */
|
/* Restore global regs */
|
||||||
gr = hsotg->gr_backup;
|
gr = &hsotg->gr_backup;
|
||||||
if (!gr) {
|
if (!gr->valid) {
|
||||||
dev_err(hsotg->dev, "%s: no global registers to restore\n",
|
dev_err(hsotg->dev, "%s: no global registers to restore\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
gr->valid = false;
|
||||||
|
|
||||||
writel(0xffffffff, hsotg->regs + GINTSTS);
|
writel(0xffffffff, hsotg->regs + GINTSTS);
|
||||||
writel(gr->gotgctl, hsotg->regs + GOTGCTL);
|
writel(gr->gotgctl, hsotg->regs + GOTGCTL);
|
||||||
|
|
|
@ -492,6 +492,7 @@ struct dwc2_gregs_backup {
|
||||||
u32 gdfifocfg;
|
u32 gdfifocfg;
|
||||||
u32 dtxfsiz[MAX_EPS_CHANNELS];
|
u32 dtxfsiz[MAX_EPS_CHANNELS];
|
||||||
u32 gpwrdn;
|
u32 gpwrdn;
|
||||||
|
bool valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -521,6 +522,7 @@ struct dwc2_dregs_backup {
|
||||||
u32 doepctl[MAX_EPS_CHANNELS];
|
u32 doepctl[MAX_EPS_CHANNELS];
|
||||||
u32 doeptsiz[MAX_EPS_CHANNELS];
|
u32 doeptsiz[MAX_EPS_CHANNELS];
|
||||||
u32 doepdma[MAX_EPS_CHANNELS];
|
u32 doepdma[MAX_EPS_CHANNELS];
|
||||||
|
bool valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -538,6 +540,7 @@ struct dwc2_hregs_backup {
|
||||||
u32 hcintmsk[MAX_EPS_CHANNELS];
|
u32 hcintmsk[MAX_EPS_CHANNELS];
|
||||||
u32 hprt0;
|
u32 hprt0;
|
||||||
u32 hfir;
|
u32 hfir;
|
||||||
|
bool valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -705,9 +708,9 @@ struct dwc2_hsotg {
|
||||||
struct work_struct wf_otg;
|
struct work_struct wf_otg;
|
||||||
struct timer_list wkp_timer;
|
struct timer_list wkp_timer;
|
||||||
enum dwc2_lx_state lx_state;
|
enum dwc2_lx_state lx_state;
|
||||||
struct dwc2_gregs_backup *gr_backup;
|
struct dwc2_gregs_backup gr_backup;
|
||||||
struct dwc2_dregs_backup *dr_backup;
|
struct dwc2_dregs_backup dr_backup;
|
||||||
struct dwc2_hregs_backup *hr_backup;
|
struct dwc2_hregs_backup hr_backup;
|
||||||
|
|
||||||
struct dentry *debug_root;
|
struct dentry *debug_root;
|
||||||
struct debugfs_regset32 *regset;
|
struct debugfs_regset32 *regset;
|
||||||
|
|
|
@ -359,10 +359,9 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg)
|
||||||
|
|
||||||
/* Caller must hold driver lock */
|
/* Caller must hold driver lock */
|
||||||
static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
|
static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
|
||||||
struct dwc2_hcd_urb *urb, void **ep_handle,
|
struct dwc2_hcd_urb *urb, struct dwc2_qh *qh,
|
||||||
gfp_t mem_flags)
|
struct dwc2_qtd *qtd)
|
||||||
{
|
{
|
||||||
struct dwc2_qtd *qtd;
|
|
||||||
u32 intr_mask;
|
u32 intr_mask;
|
||||||
int retval;
|
int retval;
|
||||||
int dev_speed;
|
int dev_speed;
|
||||||
|
@ -386,18 +385,15 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
qtd = kzalloc(sizeof(*qtd), mem_flags);
|
|
||||||
if (!qtd)
|
if (!qtd)
|
||||||
return -ENOMEM;
|
return -EINVAL;
|
||||||
|
|
||||||
dwc2_hcd_qtd_init(qtd, urb);
|
dwc2_hcd_qtd_init(qtd, urb);
|
||||||
retval = dwc2_hcd_qtd_add(hsotg, qtd, (struct dwc2_qh **)ep_handle,
|
retval = dwc2_hcd_qtd_add(hsotg, qtd, qh);
|
||||||
mem_flags);
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(hsotg->dev,
|
dev_err(hsotg->dev,
|
||||||
"DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n",
|
"DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n",
|
||||||
retval);
|
retval);
|
||||||
kfree(qtd);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2445,6 +2441,9 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
||||||
u32 tflags = 0;
|
u32 tflags = 0;
|
||||||
void *buf;
|
void *buf;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct dwc2_qh *qh;
|
||||||
|
bool qh_allocated = false;
|
||||||
|
struct dwc2_qtd *qtd;
|
||||||
|
|
||||||
if (dbg_urb(urb)) {
|
if (dbg_urb(urb)) {
|
||||||
dev_vdbg(hsotg->dev, "DWC OTG HCD URB Enqueue\n");
|
dev_vdbg(hsotg->dev, "DWC OTG HCD URB Enqueue\n");
|
||||||
|
@ -2523,16 +2522,33 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
||||||
urb->iso_frame_desc[i].length);
|
urb->iso_frame_desc[i].length);
|
||||||
|
|
||||||
urb->hcpriv = dwc2_urb;
|
urb->hcpriv = dwc2_urb;
|
||||||
|
qh = (struct dwc2_qh *) ep->hcpriv;
|
||||||
|
/* Create QH for the endpoint if it doesn't exist */
|
||||||
|
if (!qh) {
|
||||||
|
qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, mem_flags);
|
||||||
|
if (!qh) {
|
||||||
|
retval = -ENOMEM;
|
||||||
|
goto fail0;
|
||||||
|
}
|
||||||
|
ep->hcpriv = qh;
|
||||||
|
qh_allocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qtd = kzalloc(sizeof(*qtd), mem_flags);
|
||||||
|
if (!qtd) {
|
||||||
|
retval = -ENOMEM;
|
||||||
|
goto fail1;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&hsotg->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
retval = usb_hcd_link_urb_to_ep(hcd, urb);
|
retval = usb_hcd_link_urb_to_ep(hcd, urb);
|
||||||
if (retval)
|
|
||||||
goto fail1;
|
|
||||||
|
|
||||||
retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, mem_flags);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
|
retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, qtd);
|
||||||
|
if (retval)
|
||||||
|
goto fail3;
|
||||||
|
|
||||||
if (alloc_bandwidth) {
|
if (alloc_bandwidth) {
|
||||||
dwc2_allocate_bus_bandwidth(hcd,
|
dwc2_allocate_bus_bandwidth(hcd,
|
||||||
dwc2_hcd_get_ep_bandwidth(hsotg, ep),
|
dwc2_hcd_get_ep_bandwidth(hsotg, ep),
|
||||||
|
@ -2543,12 +2559,25 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail2:
|
fail3:
|
||||||
dwc2_urb->priv = NULL;
|
dwc2_urb->priv = NULL;
|
||||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||||
fail1:
|
fail2:
|
||||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
urb->hcpriv = NULL;
|
urb->hcpriv = NULL;
|
||||||
|
kfree(qtd);
|
||||||
|
fail1:
|
||||||
|
if (qh_allocated) {
|
||||||
|
struct dwc2_qtd *qtd2, *qtd2_tmp;
|
||||||
|
|
||||||
|
ep->hcpriv = NULL;
|
||||||
|
dwc2_hcd_qh_unlink(hsotg, qh);
|
||||||
|
/* Free each QTD in the QH's QTD list */
|
||||||
|
list_for_each_entry_safe(qtd2, qtd2_tmp, &qh->qtd_list,
|
||||||
|
qtd_list_entry)
|
||||||
|
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh);
|
||||||
|
dwc2_hcd_qh_free(hsotg, qh);
|
||||||
|
}
|
||||||
fail0:
|
fail0:
|
||||||
kfree(dwc2_urb);
|
kfree(dwc2_urb);
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,9 @@ extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
|
||||||
/* Schedule Queue Functions */
|
/* Schedule Queue Functions */
|
||||||
/* Implemented in hcd_queue.c */
|
/* Implemented in hcd_queue.c */
|
||||||
extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg);
|
extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg);
|
||||||
|
extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
|
||||||
|
struct dwc2_hcd_urb *urb,
|
||||||
|
gfp_t mem_flags);
|
||||||
extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||||
extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||||
extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
|
||||||
|
@ -471,7 +474,7 @@ extern void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||||
|
|
||||||
extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
|
extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
|
||||||
extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
||||||
struct dwc2_qh **qh, gfp_t mem_flags);
|
struct dwc2_qh *qh);
|
||||||
|
|
||||||
/* Unlinks and frees a QTD */
|
/* Unlinks and frees a QTD */
|
||||||
static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
|
static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
|
||||||
|
|
|
@ -191,7 +191,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
|
||||||
*
|
*
|
||||||
* Return: Pointer to the newly allocated QH, or NULL on error
|
* Return: Pointer to the newly allocated QH, or NULL on error
|
||||||
*/
|
*/
|
||||||
static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
|
struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
|
||||||
struct dwc2_hcd_urb *urb,
|
struct dwc2_hcd_urb *urb,
|
||||||
gfp_t mem_flags)
|
gfp_t mem_flags)
|
||||||
{
|
{
|
||||||
|
@ -767,57 +767,32 @@ void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
|
||||||
*
|
*
|
||||||
* @hsotg: The DWC HCD structure
|
* @hsotg: The DWC HCD structure
|
||||||
* @qtd: The QTD to add
|
* @qtd: The QTD to add
|
||||||
* @qh: Out parameter to return queue head
|
* @qh: Queue head to add qtd to
|
||||||
* @atomic_alloc: Flag to do atomic alloc if needed
|
|
||||||
*
|
*
|
||||||
* Return: 0 if successful, negative error code otherwise
|
* Return: 0 if successful, negative error code otherwise
|
||||||
*
|
*
|
||||||
* Finds the correct QH to place the QTD into. If it does not find a QH, it
|
* If the QH to which the QTD is added is not currently scheduled, it is placed
|
||||||
* will create a new QH. If the QH to which the QTD is added is not currently
|
* into the proper schedule based on its EP type.
|
||||||
* scheduled, it is placed into the proper schedule based on its EP type.
|
|
||||||
*/
|
*/
|
||||||
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
|
||||||
struct dwc2_qh **qh, gfp_t mem_flags)
|
struct dwc2_qh *qh)
|
||||||
{
|
{
|
||||||
struct dwc2_hcd_urb *urb = qtd->urb;
|
|
||||||
int allocated = 0;
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/*
|
if (unlikely(!qh)) {
|
||||||
* Get the QH which holds the QTD-list to insert to. Create QH if it
|
dev_err(hsotg->dev, "%s: Invalid QH\n", __func__);
|
||||||
* doesn't exist.
|
retval = -EINVAL;
|
||||||
*/
|
goto fail;
|
||||||
if (*qh == NULL) {
|
|
||||||
*qh = dwc2_hcd_qh_create(hsotg, urb, mem_flags);
|
|
||||||
if (*qh == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
allocated = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = dwc2_hcd_qh_add(hsotg, *qh);
|
retval = dwc2_hcd_qh_add(hsotg, qh);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
qtd->qh = *qh;
|
qtd->qh = qh;
|
||||||
list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
|
list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (allocated) {
|
|
||||||
struct dwc2_qtd *qtd2, *qtd2_tmp;
|
|
||||||
struct dwc2_qh *qh_tmp = *qh;
|
|
||||||
|
|
||||||
*qh = NULL;
|
|
||||||
dwc2_hcd_qh_unlink(hsotg, qh_tmp);
|
|
||||||
|
|
||||||
/* Free each QTD in the QH's QTD list */
|
|
||||||
list_for_each_entry_safe(qtd2, qtd2_tmp, &qh_tmp->qtd_list,
|
|
||||||
qtd_list_entry)
|
|
||||||
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp);
|
|
||||||
|
|
||||||
dwc2_hcd_qh_free(hsotg, qh_tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,10 +446,12 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
|
||||||
/* Select the HS PHY interface */
|
/* Select the HS PHY interface */
|
||||||
switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
|
switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
|
||||||
case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI:
|
case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI:
|
||||||
if (!strncmp(dwc->hsphy_interface, "utmi", 4)) {
|
if (dwc->hsphy_interface &&
|
||||||
|
!strncmp(dwc->hsphy_interface, "utmi", 4)) {
|
||||||
reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI;
|
reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI;
|
||||||
break;
|
break;
|
||||||
} else if (!strncmp(dwc->hsphy_interface, "ulpi", 4)) {
|
} else if (dwc->hsphy_interface &&
|
||||||
|
!strncmp(dwc->hsphy_interface, "ulpi", 4)) {
|
||||||
reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
|
reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
|
||||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1758,10 +1758,13 @@ unknown:
|
||||||
* take such requests too, if that's ever needed: to work
|
* take such requests too, if that's ever needed: to work
|
||||||
* in config 0, etc.
|
* in config 0, etc.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(f, &cdev->config->functions, list)
|
if (cdev->config) {
|
||||||
if (f->req_match && f->req_match(f, ctrl))
|
list_for_each_entry(f, &cdev->config->functions, list)
|
||||||
goto try_fun_setup;
|
if (f->req_match && f->req_match(f, ctrl))
|
||||||
f = NULL;
|
goto try_fun_setup;
|
||||||
|
f = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||||
case USB_RECIP_INTERFACE:
|
case USB_RECIP_INTERFACE:
|
||||||
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
|
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
|
||||||
|
|
|
@ -924,7 +924,8 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
|
||||||
|
|
||||||
kiocb->private = p;
|
kiocb->private = p;
|
||||||
|
|
||||||
kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
|
if (p->aio)
|
||||||
|
kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
|
||||||
|
|
||||||
res = ffs_epfile_io(kiocb->ki_filp, p);
|
res = ffs_epfile_io(kiocb->ki_filp, p);
|
||||||
if (res == -EIOCBQUEUED)
|
if (res == -EIOCBQUEUED)
|
||||||
|
@ -968,7 +969,8 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
|
||||||
|
|
||||||
kiocb->private = p;
|
kiocb->private = p;
|
||||||
|
|
||||||
kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
|
if (p->aio)
|
||||||
|
kiocb_set_cancel_fn(kiocb, ffs_aio_cancel);
|
||||||
|
|
||||||
res = ffs_epfile_io(kiocb->ki_filp, p);
|
res = ffs_epfile_io(kiocb->ki_filp, p);
|
||||||
if (res == -EIOCBQUEUED)
|
if (res == -EIOCBQUEUED)
|
||||||
|
|
|
@ -2786,7 +2786,7 @@ int fsg_common_set_nluns(struct fsg_common *common, int nluns)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
|
curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL);
|
||||||
if (unlikely(!curlun))
|
if (unlikely(!curlun))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -2796,8 +2796,6 @@ int fsg_common_set_nluns(struct fsg_common *common, int nluns)
|
||||||
common->luns = curlun;
|
common->luns = curlun;
|
||||||
common->nluns = nluns;
|
common->nluns = nluns;
|
||||||
|
|
||||||
pr_info("Number of LUNs=%d\n", common->nluns);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
|
EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
|
||||||
|
@ -3563,14 +3561,26 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
|
||||||
struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
|
struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
|
||||||
struct fsg_common *common = opts->common;
|
struct fsg_common *common = opts->common;
|
||||||
struct fsg_dev *fsg;
|
struct fsg_dev *fsg;
|
||||||
|
unsigned nluns, i;
|
||||||
|
|
||||||
fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
|
fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
|
||||||
if (unlikely(!fsg))
|
if (unlikely(!fsg))
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
mutex_lock(&opts->lock);
|
mutex_lock(&opts->lock);
|
||||||
|
if (!opts->refcnt) {
|
||||||
|
for (nluns = i = 0; i < FSG_MAX_LUNS; ++i)
|
||||||
|
if (common->luns[i])
|
||||||
|
nluns = i + 1;
|
||||||
|
if (!nluns)
|
||||||
|
pr_warn("No LUNS defined, continuing anyway\n");
|
||||||
|
else
|
||||||
|
common->nluns = nluns;
|
||||||
|
pr_info("Number of LUNs=%u\n", common->nluns);
|
||||||
|
}
|
||||||
opts->refcnt++;
|
opts->refcnt++;
|
||||||
mutex_unlock(&opts->lock);
|
mutex_unlock(&opts->lock);
|
||||||
|
|
||||||
fsg->function.name = FSG_DRIVER_DESC;
|
fsg->function.name = FSG_DRIVER_DESC;
|
||||||
fsg->function.bind = fsg_bind;
|
fsg->function.bind = fsg_bind;
|
||||||
fsg->function.unbind = fsg_unbind;
|
fsg->function.unbind = fsg_unbind;
|
||||||
|
|
|
@ -1145,7 +1145,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
|
||||||
if (opts->id && !midi->id) {
|
if (opts->id && !midi->id) {
|
||||||
status = -ENOMEM;
|
status = -ENOMEM;
|
||||||
mutex_unlock(&opts->lock);
|
mutex_unlock(&opts->lock);
|
||||||
goto kstrdup_fail;
|
goto setup_fail;
|
||||||
}
|
}
|
||||||
midi->in_ports = opts->in_ports;
|
midi->in_ports = opts->in_ports;
|
||||||
midi->out_ports = opts->out_ports;
|
midi->out_ports = opts->out_ports;
|
||||||
|
@ -1164,8 +1164,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
|
||||||
|
|
||||||
return &midi->func;
|
return &midi->func;
|
||||||
|
|
||||||
kstrdup_fail:
|
|
||||||
f_midi_unregister_card(midi);
|
|
||||||
setup_fail:
|
setup_fail:
|
||||||
for (--i; i >= 0; i--)
|
for (--i; i >= 0; i--)
|
||||||
kfree(midi->in_port[i]);
|
kfree(midi->in_port[i]);
|
||||||
|
|
|
@ -1171,7 +1171,7 @@ static int fotg210_udc_probe(struct platform_device *pdev)
|
||||||
udc_name, fotg210);
|
udc_name, fotg210);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("request_irq error (%d)\n", ret);
|
pr_err("request_irq error (%d)\n", ret);
|
||||||
goto err_irq;
|
goto err_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget);
|
ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget);
|
||||||
|
@ -1183,7 +1183,6 @@ static int fotg210_udc_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_add_udc:
|
err_add_udc:
|
||||||
err_irq:
|
|
||||||
free_irq(ires->start, fotg210);
|
free_irq(ires->start, fotg210);
|
||||||
|
|
||||||
err_req:
|
err_req:
|
||||||
|
|
|
@ -275,9 +275,7 @@ static int musb_has_gadget(struct musb *musb)
|
||||||
#ifdef CONFIG_USB_MUSB_HOST
|
#ifdef CONFIG_USB_MUSB_HOST
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
if (musb->port_mode == MUSB_PORT_MODE_HOST)
|
return musb->port_mode == MUSB_PORT_MODE_HOST;
|
||||||
return 1;
|
|
||||||
return musb->g.dev.driver != NULL;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,9 @@ static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
|
||||||
{
|
{
|
||||||
unsigned int vbus_value;
|
unsigned int vbus_value;
|
||||||
|
|
||||||
|
if (!mxs_phy->regmap_anatop)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (mxs_phy->port_id == 0)
|
if (mxs_phy->port_id == 0)
|
||||||
regmap_read(mxs_phy->regmap_anatop,
|
regmap_read(mxs_phy->regmap_anatop,
|
||||||
ANADIG_USB1_VBUS_DET_STAT,
|
ANADIG_USB1_VBUS_DET_STAT,
|
||||||
|
|
Loading…
Reference in New Issue