We were setting the DMA masks in dwc2_driver_probe(), but that is before the driver parameters have been set to their default values. That meant the DMA masks could be set wrong. Fix it by moving the DMA mask setting into dwc2_hcd_init(), after the driver parameters have been set. This required a bit of refactoring of the dwc2_hcd_init() code as well. While there, also remove the unneeded struct device *dev parameter to dwc2_hcd_init() and dwc2_hcd_remove(), and pass in the value through the hsotg->dev member. Reported-by: Matthijs Kooijman <matthijs@xxxxxxxx> Signed-off-by: Paul Zimmerman <paulz@xxxxxxxxxxxx> --- drivers/staging/dwc2/hcd.c | 63 +++++++++++++++++++++++++++------------------- drivers/staging/dwc2/hcd.h | 6 ++--- drivers/staging/dwc2/pci.c | 19 +++----------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 01dbdd8..1a78924 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2682,7 +2682,7 @@ static void dwc2_set_uninitialized(int *p, int size) * USB bus with the core and calls the hc_driver->start() function. It returns * a negative error on failure. */ -int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, int irq, +int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, struct dwc2_core_params *params) { struct usb_hcd *hcd; @@ -2691,7 +2691,7 @@ int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, int irq, int i, num_channels; int retval = -ENOMEM; - dev_dbg(dev, "DWC OTG HCD INIT\n"); + dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n"); /* * Attempt to ensure this device is really a DWC_otg Controller. @@ -2702,22 +2702,11 @@ int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, int irq, snpsid = readl(hsotg->regs + GSNPSID); if ((snpsid & 0xfffff000) != 0x4f542000 && (snpsid & 0xfffff000) != 0x4f543000) { - dev_err(dev, "Bad value for GSNPSID: 0x%08x\n", snpsid); + dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", snpsid); retval = -ENODEV; goto error1; } - hcd = usb_create_hcd(&dwc2_hc_driver, dev, dev_name(dev)); - if (!hcd) - goto error1; - - hcd->has_tt = 1; - - spin_lock_init(&hsotg->lock); - ((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg; - hsotg->priv = hcd; - hsotg->dev = dev; - /* * Store the contents of the hardware configuration registers here for * easy access later @@ -2776,18 +2765,18 @@ int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, int irq, hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) * FRAME_NUM_ARRAY_SIZE, GFP_KERNEL); if (!hsotg->frame_num_array) - goto error2; + goto error1; hsotg->last_frame_num_array = kzalloc( sizeof(*hsotg->last_frame_num_array) * FRAME_NUM_ARRAY_SIZE, GFP_KERNEL); if (!hsotg->last_frame_num_array) - goto error2; + goto error1; hsotg->last_frame_num = HFNUM_MAX_FRNUM; #endif hsotg->core_params = kzalloc(sizeof(*hsotg->core_params), GFP_KERNEL); if (!hsotg->core_params) - goto error2; + goto error1; dwc2_set_uninitialized((int *)hsotg->core_params, sizeof(*hsotg->core_params) / sizeof(int)); @@ -2795,6 +2784,29 @@ int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, int irq, /* Validate parameter values */ dwc2_set_parameters(hsotg, params); + /* Set device flags indicating whether the HCD supports DMA */ + if (hsotg->core_params->dma_enable > 0) { + if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) + dev_warn(hsotg->dev, + "can't enable workaround for >4GB RAM\n"); + if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0) + dev_warn(hsotg->dev, + "can't enable workaround for >2GB RAM\n"); + } else { + dma_set_mask(hsotg->dev, 0); + dma_set_coherent_mask(hsotg->dev, 0); + } + + hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); + if (!hcd) + goto error1; + + hcd->has_tt = 1; + + spin_lock_init(&hsotg->lock); + ((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg; + hsotg->priv = hcd; + /* Initialize the DWC_otg core, and select the Phy type */ retval = dwc2_core_init(hsotg, true); if (retval) @@ -2904,6 +2916,8 @@ int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, int irq, error3: dwc2_hcd_release(hsotg); error2: + usb_put_hcd(hcd); +error1: kfree(hsotg->core_params); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS @@ -2911,9 +2925,7 @@ error2: kfree(hsotg->frame_num_array); #endif - usb_put_hcd(hcd); -error1: - dev_err(dev, "%s() FAILED, returning %d\n", __func__, retval); + dev_err(hsotg->dev, "%s() FAILED, returning %d\n", __func__, retval); return retval; } EXPORT_SYMBOL_GPL(dwc2_hcd_init); @@ -2922,17 +2934,17 @@ EXPORT_SYMBOL_GPL(dwc2_hcd_init); * Removes the HCD. * Frees memory and resources associated with the HCD and deregisters the bus. */ -void dwc2_hcd_remove(struct device *dev, struct dwc2_hsotg *hsotg) +void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) { struct usb_hcd *hcd; - dev_dbg(dev, "DWC OTG HCD REMOVE\n"); + dev_dbg(hsotg->dev, "DWC OTG HCD REMOVE\n"); hcd = dwc2_hsotg_to_hcd(hsotg); - dev_dbg(dev, "hsotg->hcd = %p\n", hcd); + dev_dbg(hsotg->dev, "hsotg->hcd = %p\n", hcd); if (!hcd) { - dev_dbg(dev, "%s: dwc2_hsotg_to_hcd(hsotg) NULL!\n", + dev_dbg(hsotg->dev, "%s: dwc2_hsotg_to_hcd(hsotg) NULL!\n", __func__); return; } @@ -2940,12 +2952,11 @@ void dwc2_hcd_remove(struct device *dev, struct dwc2_hsotg *hsotg) usb_remove_hcd(hcd); hsotg->priv = NULL; dwc2_hcd_release(hsotg); + usb_put_hcd(hcd); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS kfree(hsotg->last_frame_num_array); kfree(hsotg->frame_num_array); #endif - - usb_put_hcd(hcd); } EXPORT_SYMBOL_GPL(dwc2_hcd_remove); diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h index 775337e..8a60dcf 100644 --- a/drivers/staging/dwc2/hcd.h +++ b/drivers/staging/dwc2/hcd.h @@ -447,9 +447,9 @@ static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe) return !dwc2_hcd_is_pipe_in(pipe); } -extern int dwc2_hcd_init(struct device *dev, struct dwc2_hsotg *hsotg, - int irq, struct dwc2_core_params *params); -extern void dwc2_hcd_remove(struct device *dev, struct dwc2_hsotg *hsotg); +extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, + struct dwc2_core_params *params); +extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); extern int dwc2_set_parameters(struct dwc2_hsotg *hsotg, struct dwc2_core_params *params); diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c index 117d3ce..0825eef 100644 --- a/drivers/staging/dwc2/pci.c +++ b/drivers/staging/dwc2/pci.c @@ -103,7 +103,7 @@ static void dwc2_driver_remove(struct pci_dev *dev) dev_dbg(&dev->dev, "%s(%p)\n", __func__, dev); - dwc2_hcd_remove(&dev->dev, hsotg); + dwc2_hcd_remove(hsotg); pci_disable_device(dev); } @@ -133,6 +133,7 @@ static int dwc2_driver_probe(struct pci_dev *dev, pci_set_power_state(dev, PCI_D0); + hsotg->dev = &dev->dev; hsotg->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]); if (!hsotg->regs) return -ENOMEM; @@ -145,19 +146,7 @@ static int dwc2_driver_probe(struct pci_dev *dev, pci_set_master(dev); - if (dwc2_module_params.dma_enable > 0) { - if (pci_set_dma_mask(dev, DMA_BIT_MASK(31)) < 0) - dev_warn(&dev->dev, - "can't enable workaround for >2GB RAM\n"); - if (pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(31)) < 0) - dev_warn(&dev->dev, - "can't enable workaround for >2GB RAM\n"); - } else { - pci_set_dma_mask(dev, 0); - pci_set_consistent_dma_mask(dev, 0); - } - - retval = dwc2_hcd_init(&dev->dev, hsotg, dev->irq, &dwc2_module_params); + retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params); if (retval) { pci_disable_device(dev); return retval; @@ -171,7 +160,7 @@ static int dwc2_driver_probe(struct pci_dev *dev, IRQF_SHARED | IRQ_LEVEL, dev_name(&dev->dev), hsotg); if (retval) - dwc2_hcd_remove(&dev->dev, hsotg); + dwc2_hcd_remove(hsotg); return retval; } -- 1.8.2.rc0.16.g20a599e -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html