[GIT][PULL] Improvements to max3421-hcd driver
The following changes since commit 08332893e37af6ae779367e78e444f8f9571511d: Linux 4.12-rc2 (2017-05-21 19:30:23 -0700) are available in the git repository at: https://github.com/AlexanderAmelkin/linux-wandboard.git tags/max3421-improvements-1 for you to fetch changes up to b9a7559d24c0b2cb6e69124d861a943f79272681: usb: max3421-hcd: Remove function name from dev_dbg calls (2017-05-25 11:52:13 +0300) The separate patches for these changes will be sent as a follow up. usb: max3421-hcd: Make the driver more up-to-date and flexible This set of patches updates the max3421-hcd driver and fixes some bugs in it. Specifically, it: - Adds support for devicetree - Makes platform related parameters configurable - Adds sanity checks for platform related parameters - Fixes crash on driver removal - Tidies up use of memory allocation/deallocation functions - Removes superfluous debug text Alexander Amelkin (3): usb: max3421-hcd: Add devicetree support to the driver usb: max3421-hcd: Fix crash on the driver removal usb: max3421-hcd: Remove function name from dev_dbg calls .../devicetree/bindings/usb/maxim,max3421-hcd.txt | 19 +++ drivers/usb/host/max3421-hcd.c | 131 + 2 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/maxim,max3421-hcd.txt -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] usb: max3421-hcd: Remove function name from dev_dbg calls
NOTE: Please don't use the plain text here as a patch because it most probably is corrupted by my webmail client. Attached is a copy of the following text guaranteed to have correct tabs/spaces. - From b9a7559d24c0b2cb6e69124d861a943f79272681 Mon Sep 17 00:00:00 2001 From: Alexander Amelkin <amel...@fastwel.ru> Date: Fri, 14 Apr 2017 18:01:58 +0300 Subject: [PATCH 3/3] usb: max3421-hcd: Remove function name from dev_dbg calls The kernel dynamic debugging facility already has a means for displaying the function name if the developer wants to (the 'f' flag). There is no need to hard-code output of the function name into dev_dbg calls. Signed-off-by: Alexander Amelkin <alexan...@amelkin.msk.ru> --- drivers/usb/host/max3421-hcd.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index bd59c16..cfca8a2 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -706,8 +706,8 @@ max3421_select_and_start_urb(struct usb_hcd *hcd) urb = list_first_entry(>urb_list, struct urb, urb_list); if (urb->unlinked) { - dev_dbg(>dev, "%s: URB %p unlinked=%d", - __func__, urb, urb->unlinked); + dev_dbg(>dev, "URB %p unlinked=%d", + urb, urb->unlinked); max3421_hcd->curr_urb = urb; max3421_hcd->urb_done = 1; spin_unlock_irqrestore(_hcd->lock, @@ -815,8 +815,8 @@ max3421_check_unlink(struct usb_hcd *hcd) list_for_each_entry_safe(urb, next, >urb_list, urb_list) { if (urb->unlinked) { retval = 1; - dev_dbg(>dev, "%s: URB %p unlinked=%d", - __func__, urb, urb->unlinked); + dev_dbg(>dev, "URB %p unlinked=%d", + urb, urb->unlinked); usb_hcd_unlink_urb_from_ep(hcd, urb); spin_unlock_irqrestore(_hcd->lock, flags); @@ -912,8 +912,8 @@ max3421_handle_error(struct usb_hcd *hcd, u8 hrsl) * from; report error */ max3421_hcd->urb_done = hrsl_to_error[result_code]; - dev_dbg(>dev, "%s: unexpected error HRSL=0x%02x", - __func__, hrsl); + dev_dbg(>dev, "unexpected error HRSL=0x%02x", + hrsl); break; case MAX3421_HRSL_TOGERR: @@ -940,14 +940,12 @@ max3421_handle_error(struct usb_hcd *hcd, u8 hrsl) else { /* Based on ohci.h cc_to_err[]: */ max3421_hcd->urb_done = hrsl_to_error[result_code]; - dev_dbg(>dev, "%s: unexpected error HRSL=0x%02x", - __func__, hrsl); + dev_dbg(>dev, "unexpected error HRSL=0x%02x", hrsl); } break; case MAX3421_HRSL_STALL: - dev_dbg(>dev, "%s: unexpected error HRSL=0x%02x", - __func__, hrsl); + dev_dbg(>dev, "unexpected error HRSL=0x%02x", hrsl); max3421_hcd->urb_done = hrsl_to_error[result_code]; break; -- 2.7.4 From b9a7559d24c0b2cb6e69124d861a943f79272681 Mon Sep 17 00:00:00 2001 From: Alexander Amelkin <amel...@fastwel.ru> Date: Fri, 14 Apr 2017 18:01:58 +0300 Subject: [PATCH 3/3] usb: max3421-hcd: Remove function name from dev_dbg calls The kernel dynamic debugging facility already has a means for displaying the function name if the developer wants to (the 'f' flag). There is no need to hard-code output of the function name into dev_dbg calls. Signed-off-by: Alexander Amelkin <alexan...@amelkin.msk.ru> --- drivers/usb/host/max3421-hcd.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index bd59c16..cfca8a2 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -706,8 +706,8 @@ max3421_select_and_start_urb(struct usb_hcd *hcd) urb = list_first_entry(>urb_list, struct urb, urb_list); if (urb->unlinked) { -dev_dbg(>dev, "%s: URB %p unlinked=%d", - __func__, urb, urb->unlinked); +dev_dbg(>dev, "URB %p unlinked=%d"
[PATCH 2/3] usb: max3421-hcd: Fix crash on the driver removal
NOTE: Please don't use the plain text here as a patch because it most probably is corrupted by my webmail client. Attached is a copy of the following text guaranteed to have correct tabs/spaces. - From 8c4c65d3892df3721474023836216a02e03fb23e Mon Sep 17 00:00:00 2001 From: Alexander Amelkin <amel...@fastwel.ru> Date: Fri, 14 Apr 2017 17:58:07 +0300 Subject: [PATCH 2/3] usb: max3421-hcd: Fix crash on the driver removal The driver was calling kthread_stop inside a spin-locked region while the thread was calling schedule() on a regular basis. That resulted in panic due to 'scheduling while atomic'. There was no need to get the spin-lock before stopping the thread as thread stopping is asynchronous and the thread only stops when it detects the stop flag set by kthread_stop(), at which point it is not accessing any resources anyway. Hence, this patch removes the spin-locking around the kthread_stop() call. Additionally, the allocated resources were not free'd in the correct order. Some were not free'd at all. This patch switches all resource allocations to devm_* functions and also reorders deallocation to properly revert the allocations (although not actually needed for devm-allocated resources). Signed-off-by: Alexander Amelkin <alexan...@amelkin.msk.ru> --- drivers/usb/host/max3421-hcd.c | 29 +++-- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index f600052..bd59c16 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1925,10 +1925,10 @@ max3421_probe(struct spi_device *spi) max3421_hcd_list = max3421_hcd; INIT_LIST_HEAD(_hcd->ep_list); - max3421_hcd->tx = kmalloc(sizeof(*max3421_hcd->tx), GFP_KERNEL); + max3421_hcd->tx = devm_kzalloc(>dev, sizeof(*max3421_hcd->tx), GFP_KERNEL); if (!max3421_hcd->tx) goto error; - max3421_hcd->rx = kmalloc(sizeof(*max3421_hcd->rx), GFP_KERNEL); + max3421_hcd->rx = devm_kzalloc(>dev, sizeof(*max3421_hcd->rx), GFP_KERNEL); if (!max3421_hcd->rx) goto error; @@ -1946,8 +1946,8 @@ max3421_probe(struct spi_device *spi) goto error; } - retval = request_irq(spi->irq, max3421_irq_handler, -IRQF_TRIGGER_LOW, "max3421", hcd); + retval = devm_request_irq(>dev, spi->irq, max3421_irq_handler, + IRQF_TRIGGER_LOW, "max3421", hcd); if (retval < 0) { dev_err(>dev, "failed to request irq %d\n", spi->irq); goto error; @@ -1976,7 +1976,6 @@ max3421_remove(struct spi_device *spi) { struct max3421_hcd *max3421_hcd = NULL, **prev; struct usb_hcd *hcd = NULL; - unsigned long flags; for (prev = _hcd_list; *prev; prev = &(*prev)->next) { max3421_hcd = *prev; @@ -1990,12 +1989,20 @@ max3421_remove(struct spi_device *spi) spi); return -ENODEV; } - spin_lock_irqsave(_hcd->lock, flags); + + devm_free_irq(>dev, spi->irq, hcd); + + usb_remove_hcd(hcd); kthread_stop(max3421_hcd->spi_thread); - *prev = max3421_hcd->next; - spin_unlock_irqrestore(_hcd->lock, flags); + devm_kfree(>dev, max3421_hcd->rx); + max3421_hcd->rx = NULL; + devm_kfree(>dev, max3421_hcd->tx); + max3421_hcd->tx = NULL; + + *prev = max3421_hcd->next; + usb_put_hcd(hcd); #if defined(CONFIG_OF) if (spi->dev.platform_data) { @@ -2005,12 +2012,6 @@ max3421_remove(struct spi_device *spi) } #endif - free_irq(spi->irq, hcd); - - usb_remove_hcd(hcd); - - - usb_put_hcd(hcd); return 0; } -- 2.7.4 From 8c4c65d3892df3721474023836216a02e03fb23e Mon Sep 17 00:00:00 2001 From: Alexander Amelkin <amel...@fastwel.ru> Date: Fri, 14 Apr 2017 17:58:07 +0300 Subject: [PATCH 2/3] usb: max3421-hcd: Fix crash on the driver removal The driver was calling kthread_stop inside a spin-locked region while the thread was calling schedule() on a regular basis. That resulted in panic due to 'scheduling while atomic'. There was no need to get the spin-lock before stopping the thread as thread stopping is asynchronous and the thread only stops when it detects the stop flag set by kthread_stop(), at which point it is not accessing any resources anyway. Hence, this patch removes the spin-locking around the kthread_stop() call. Additionally, the allocated resources were not free'd in the correct order. Some were not free'd at all. This patch switches all resource allocations to devm_* functions and also reorders deallocation to properly revert the allocations (although not actually needed for devm-allocated resour
[PATCH 1/3] usb: max3421-hcd: Add devicetree support to the driver
NOTE: Please don't use the plain text here as a patch because it most probably is corrupted by my webmail client. Attached is a copy of the following text guaranteed to have correct tabs/spaces. - Before this patch the max3421-hcd driver could only use statically linked platform data to initialize its parameters. This prevented it from being used on systems using device tree. The data taken from the device tree is put into dev->platform_data when CONFIG_OF is enabled and the device is an OpenFirmware node. The driver's 'compatible' string is 'maxim,max3421' Binding documentation is also added with this patch. Signed-off-by: Alexander Amelkin <alexan...@amelkin.msk.ru> --- .../devicetree/bindings/usb/maxim,max3421-hcd.txt | 19 + drivers/usb/host/max3421-hcd.c | 96 -- 2 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/maxim,max3421-hcd.txt diff --git a/Documentation/devicetree/bindings/usb/maxim,max3421-hcd.txt b/Documentation/devicetree/bindings/usb/maxim,max3421-hcd.txt new file mode 100644 index 000..a8b9faa --- /dev/null +++ b/Documentation/devicetree/bindings/usb/maxim,max3421-hcd.txt @@ -0,0 +1,19 @@ +* SPI-based USB host controller Maxim Integrated max3421e + +Required properties: +- compatible: must be "maxim,max3421" +- reg: chip select number to which the max3421 chip is connected + (depends on master SPI controller) +- spi-max-frequency: the operational frequency, must not exceed <2600> +- interrupt-parent: phandle of the associated GPIO controller to which the INT line + of max3421e chip is connected +- interrupts: specification of the GPIO pin (in terms of the `interrupt-parent`) + to which INT line of max3421e chip is connected. + The driver configures MAX3421E for active low level triggered interrupts. + Configure your 'interrupt-parent' gpio controller accordingly. +- vbus: + GPOUTx is the number (1-8) of GPOUT pin of max3421e used to drive Vbus. + ACTIVE_LEVEL is 1 or 0. + +Don't forget to add pinctrl properties if you need some GPIO pins reconfigured +for use as INT. See binding information for the pinctrl nodes. diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 369869a..f600052 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -61,6 +61,12 @@ #include #include +#if defined(CONFIG_OF) +#include + +#define MAX3421_GPOUT_COUNT 8 +#endif + #include #define DRIVER_DESC"MAX3421 USB Host-Controller Driver" @@ -1699,6 +1705,10 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index, spin_lock_irqsave(_hcd->lock, flags); pdata = spi->dev.platform_data; + if (!pdata) { + dev_err(>dev, "Device platform data is missing\n"); + return -EFAULT; + } switch (type_req) { case ClearHubFeature: @@ -1831,20 +1841,80 @@ static struct hc_driver max3421_hcd_desc = { .bus_resume = max3421_bus_resume, }; +#if defined(CONFIG_OF) +static struct max3421_hcd_platform_data max3421_data; + +static const struct of_device_id max3421_dt_ids[] = { + { .compatible = "maxim,max3421", .data = _data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, max3421_dt_ids); +#endif + static int max3421_probe(struct spi_device *spi) { struct max3421_hcd *max3421_hcd; struct usb_hcd *hcd = NULL; int retval = -ENOMEM; +#if defined(CONFIG_OF) + struct max3421_hcd_platform_data *pdata = NULL; +#endif if (spi_setup(spi) < 0) { dev_err(>dev, "Unable to setup SPI bus"); return -EFAULT; } - hcd = usb_create_hcd(_hcd_desc, >dev, -dev_name(>dev)); + if (!spi->irq) { + dev_err(>dev, "Failed to get SPI IRQ for node '%s'\n", spi->dev.of_node->full_name); + return -EFAULT; + } + +#if defined(CONFIG_OF) + if (spi->dev.of_node) { + /* A temporary alias structure */ + union { + uint32_t value[2]; + struct { + uint32_t gpout; + uint32_t active_level; + }; + } vbus; + + if(!(pdata = devm_kzalloc(>dev, sizeof(*pdata), GFP_KERNEL))) { + dev_err(>dev, "failed to allocate memory for private data\n"); + retval = -ENOMEM; + goto error; + } + spi->dev.platform_data = pdata; + + if ((retval = of_property_read_u32_array(spi->dev.of_node, "vbus", vbus.value, 2))) { + dev_err(>dev, "device tree node property 'vbus' is missing\n"); + goto error; + } + pdata->vbus_gpout = vbus.gpout; + pdata->vbus_active_level = vbus.active_level; + } + else +#endif + pdata = spi->dev.platform_data; + if (!pdata) { + dev_err(>
max3421-hcd low performance
Hi. I'm using max3421-hcd on max3421evkit-1+ connected to SPI of Wandboard (i.MX6Quad) and running kernel 4.11-rc6 (from trunk of linux-stable). The SPI is running at 25MHz (the maximum for max3421e chip). The performance I'm observing is very low. Transfer speed to/from a USB flash stick is as low as 70KB/sec. There are no errors in dmesg. The max3421e datasheet claims that the chip is capable of Full Speed USB, and 25MHz SPI clock should be sufficient for that. Do you have any ideas why it may be performing that poorly for me or how could I debug that? Thank you. Alexander. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html