Re: [PATCH 2/6] usb: core: TPL should apply for both OTG and EH
On Mon, Aug 11, 2014 at 11:25:44AM +0530, Pratyush Anand wrote: Hi Peter, On Thu, Aug 07, 2014 at 02:45:15PM +0800, Peter Chen wrote: According to On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification, the targeted hosts (non-PC hosts) include both embedded hosts and otg, and each targeted host product defines the set of supported peripherals on a TPL (Targeted Peripheral List). So, TPL should apply for both OTG and embedded host, and the otg support is not a must for embedded host. The TPL support feature will only be effect when CONFIG_USB_OTG_WHITELIST has been chosen and hcd-tpl_support flag is set, it can avoid the enumeration fails problem for the user who chooses CONFIG_USB_OTG_WHITELIST wrongly. Signed-off-by: Peter Chen peter.c...@freescale.com --- drivers/usb/core/hub.c | 20 +++- drivers/usb/core/otg_whitelist.h | 22 ++ 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8a4dcbc..5e0b8eb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2199,9 +2199,7 @@ static void announce_device(struct usb_device *udev) static inline void announce_device(struct usb_device *udev) { } #endif -#ifdef CONFIG_USB_OTG #include otg_whitelist.h -#endif /** * usb_enumerate_device_otg - FIXME (usbcore-internal) @@ -2261,21 +2259,6 @@ static int usb_enumerate_device_otg(struct usb_device *udev) } } } - - if (!is_targeted(udev)) { - - /* Maybe it can talk to us, though we can't talk to it. -* (Includes HNP test device.) -*/ - if (udev-bus-b_hnp_enable || udev-bus-is_b_host) { - err = usb_port_suspend(udev, PMSG_SUSPEND); - if (err 0) - dev_dbg(udev-dev, HNP fail, %d\n, err); - } - err = -ENOTSUPP; If I did not miss anything then I see an issue if above hunk is removed. Suppose, there is an OTG B device which is not supported by host, then the above hunk was suspending the bus so that B device can get a chance to become host. By removing above hunk, how do we cater this scenario? ~Pratyush PS: All other changes of the series seems fine to me. Pratyush, if it is no problem for my v3 patchset, would you add your ack or reviewed-by for it? Thanks. -- Best Regards, Peter Chen -- 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 1/1] HID: usbhid: add usb_clear_halt determination for next hid_start_in
HID IR device will not response to any command send from host when it is finishing paring and tring to reset itself. During this period of time, usb_cleaer_halt will be fail and if hid_start_in soon again, we has the possibility trap in infinite loop. Signed-off-by: CheChun Kuo vichy@gmail.com --- drivers/hid/usbhid/hid-core.c |3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 79cf503..256b102 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -122,7 +122,8 @@ static void hid_reset(struct work_struct *work) dev_dbg(usbhid-intf-dev, clear halt\n); rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid-urbin-pipe); clear_bit(HID_CLEAR_HALT, usbhid-iofl); - hid_start_in(hid); + if (rc == 0) + hid_start_in(hid); } else if (test_bit(HID_RESET_PENDING, usbhid-iofl)) { -- 1.7.9.5 -- 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
Re: [PATCH 1/1] HID: usbhid: add usb_clear_halt determination for next hid_start_in
On Fri, 22 Aug 2014, CheChun Kuo wrote: HID IR device will not response to any command send from host when it is finishing paring and tring to reset itself. During this period of time, usb_cleaer_halt will be fail and if hid_start_in soon again, we has the possibility trap in infinite loop. Signed-off-by: CheChun Kuo vichy@gmail.com --- drivers/hid/usbhid/hid-core.c |3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 79cf503..256b102 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -122,7 +122,8 @@ static void hid_reset(struct work_struct *work) dev_dbg(usbhid-intf-dev, clear halt\n); rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid-urbin-pipe); clear_bit(HID_CLEAR_HALT, usbhid-iofl); - hid_start_in(hid); + if (rc == 0) + hid_start_in(hid); } I'd need a more detailed explanation for this patch, as I don't understand neither the text in the changelog nor the patch itself. Namely: - which IR devices are showing this behavior? - where does the infinite loop come from? hid_reset() should error out properly if usb_clear_halt() fails and HID_IN_RUNNING flag is not set Thanks, -- Jiri Kosina SUSE Labs -- 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
Re: [PATCH RESEND v2 7/7] ARM: dts: vf610-twr: Add USB support
On Tue, Aug 19, 2014 at 12:24:37AM +0400, Sergei Shtylyov wrote: Hello. On 08/19/2014 12:07 AM, Stefan Agner wrote: Add USB support for Freescale Vybrid tower. The USB hosts over-current protection signal is not connected is not connected to the PHY's over- Yes, we all understood that it's not connected, no need to repeat. ;-) I will fix it up when applying. Shawn -- 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
Re: [PATCH RESEND v2 0/7] vf610: Add USB support
On Mon, Aug 18, 2014 at 10:07:10PM +0200, Stefan Agner wrote: Stefan Agner (7): ARM: dts: vf610: Add USB PHY and controller ARM: imx: clk-vf610: Add USBPHY clocks ... ARM: dts: vf610: Add usbmisc for non-core registers ... ARM: dts: vf610-colibri: Add USB support ARM: dts: vf610-twr: Add USB support Applied these 5 patches, thanks. -- 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
Re: [linux-usb] USB Gadget drivers Windows 7/8 support and .bAlternateSetting in interface descriptor
Hi Community, I finally fix the UAC1 on Windows 7 host issue. Thanks for your help. I will submit patches after more testing. On 08/22/2014 10:43 AM, Xuebing Wang wrote: On 08/21/2014 04:24 PM, Sebastian Andrzej Siewior wrote: On 08/20/2014 02:13 AM, Peter Chen wrote: Thanks, so Xunbing, the imx6 hardware (chipidea core) have 8 endpoints, and support all four transfer type, it should be no problem to support RNDIS. But you shouldn't use RNDIS on Windows 7 or 8. As far as I recall they do not bring the RNDIS driver which is deprecated and only supported by Windows XP which is EOL by now. Windows 7 and 8 support CDC [0] and this is what you should look for. [0] http://msdn.microsoft.com/en-us/library/windows/hardware/ff538820%28v=vs.85%29.aspx Sebastian Sebastian, Peter, Andrzej, Thank you for your help. 1) Are you aware of any devices (based on Freescale i.MX or ChipIdea USB IP) with a gadget driver which uses .bAlternateSetting that support Windows 7/8? 2) The reason I am asking this is that USB 1.1 Spec (section 9.2.6.4 Standard Device Requests) says: For standard device requests that require no Data stage, a device *must* be able to complete the request and be able to successfully complete the Status stage of the request *within 50 ms* of receipt of the request. This limitation applies to requests to the device, interface, or endpoint. I am debugging this Windows support for UAC1, thus I am referring to USB 1.1 spec. 3) For any gadget which uses .bAlternateSetting, Host will send USB_REQ_SET_INTERFACE Standard Device Request which requires no Data State. I am not sure if Windows drivers strictly adhere to USB spec, thus strictly require device to respond to USB_REQ_SET_INTERFACE within 50ms??? 4) In gadget driver set_alt functions (to handle USB_REQ_SET_INTERFACE), ep_enable/ep_disable will be called, and timing of this differs from hardware platform to platform (and UDC drivers), does this explain why below function exists??? 4.1) /** * gadget_supports_altsettings - return true if altsettings work * @gadget: the gadget in question */ static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) { /* PXA 21x/25x/26x has no altsettings at all */ if (gadget_is_pxa(gadget)) return false; /* PXA 27x and 3xx have *broken* altsetting support */ if (gadget_is_pxa27x(gadget)) return false; /* Everything else is *presumably* fine ... */ return true; } 4.2) /* Some controllers can't support CDC Ethernet (ECM) ... */ static inline bool can_support_ecm(struct usb_gadget *gadget) { if (!gadget_supports_altsettings(gadget)) return false; /* Everything else is *presumably* fine ... but this is a bit * chancy, so be **CERTAIN** there are no hardware issues with * your controller. Add it above if it can't handle CDC. */ return true; } Thanks again. -- Thanks, Xuebing Wang -- 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 V5 0/2] usb: gadget: zero: Add support for interrupt EP
This patchset adds support for interrupt EP and the corresponding test cases to gadget zero. The code has been rebased and tested on Kernel v3.15-rc5 V4 - V5 - Rebased on Felipe Balbi's testing/next - Build tested - No other change V3 - V4 - Edited the commit message to provide more information regarding the new test cases added - Rebased the code in Kernel v3.16-rc5 - No change in the code V2 - V3 - Rectified wMaxPacketSize for FS from 1023 to 64 - Modified default value of interrupt interval for FS to 1 ms V1 - V2 - Modified the alternate interface from having 6 EPs (2 - Interrupt, 2 Bulk, 2 Isoc) to 2 EPs (Interrupt only) RFC - V1 - Added support for configuring interrupt EP attributes from configfs interface Amit Virdi (2): usb: gadget: zero: Add support for interrupt EP usbtest: Add interrupt EP testcases drivers/usb/gadget/function/f_loopback.c | 3 +- drivers/usb/gadget/function/f_sourcesink.c | 511 +++-- drivers/usb/gadget/function/g_zero.h | 13 +- drivers/usb/gadget/legacy/zero.c | 21 ++ drivers/usb/misc/usbtest.c | 113 ++- 5 files changed, 624 insertions(+), 37 deletions(-) -- 1.8.0 -- 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
Re: [PATCH v3 0/6] usb: host: change TPL support behaviour
On Tue, Aug 19, 2014 at 09:51:51AM +0800, Peter Chen wrote: Changes for v3: - Add possible role switch for unsupported HNP capable OTG B-peripheral, see USB OTG EH 2.0 spec page 38, this feature was deleted wrongly at previous revision patches. Changes for v2: - Move TPL support judgement out of is_target, the user can be easy to know if it needs to do TPL judgement. [patch 1/6] - Keep the unsupport device message unchange [patch 1/6] According to On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification, a Targeted Host (non-PC host, OTG or Embedded host) is not required to support operation with all types of USB peripherals. It is up to the manufacturer of each Targeted Host to declare which peripherals the host will support and provide a list of those peripherals. This is called the Targeted Host's Targeted Peripheral List (TPL). The TPL shall accurately represent the device classes supported by the Targeted Host. And the TPL support is a must for USB OTG EH certification test, and TPL support needs to apply for both OTG and EH, it should be decided by platform setting. This patchset changes TPL support behaviour like below: - Apply possible TPL support for all kinds of host - Effect TPL in code is decided by both configuration (CONFIG_USB_OTG_WHITELIST) and platform flag, it can avoid the enumeration failure by choosing TPL configuration wrongly. Besides, TPL can be have a good supplement for authorized feature supplied by sys, Eg, TPL can be modified to match by class using interface descriptor, etc. It may help give some suggestions for recently badUSB report. http://venturebeat.com/2014/07/31/why-you-can-no-longer-trust-any-usb-device-plugged-into-your-pc/ https://srlabs.de/badusb/ Peter Chen (6): usb: hcd: add TPL support flag usb: core: TPL should apply for both OTG and EH usb: core: Kconfig: TPL should apply for both OTG and EH usb: common: add API to get if the platform supports TPL usb: chipidea: add TPL support for targeted hosts doc: dt-binding: ci-hdrc-imx: add TPL support .../devicetree/bindings/usb/ci-hdrc-imx.txt|2 ++ drivers/usb/chipidea/core.c|4 +++ drivers/usb/chipidea/host.c|1 + drivers/usb/common/usb-common.c| 15 + drivers/usb/core/Kconfig | 12 ++- drivers/usb/core/hub.c | 33 +--- drivers/usb/core/otg_whitelist.h | 13 ++-- include/linux/usb/chipidea.h |1 + include/linux/usb/hcd.h|1 + include/linux/usb/of.h |5 +++ 10 files changed, 50 insertions(+), 37 deletions(-) Reviewed-by: Pratyush Anand pratyush.an...@st.com -- 1.7.9.5 -- 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
[RFC 1/2] USB: OTG: Hold wakeupsource when VBUS present
From: Todd Poynor toddpoy...@google.com USB: OTG: Hold wakeupsource when VBUS present Enabled by default, can disable with: echo N /sys/module/otg_wakeupsource/parameters/enabled This is one of the number of patches from the Android AOSP common.git tree, which is used on almost all Android devices. so I wanted to submit it for review to see if it should go upstream. Cc: Felipe Balbi ba...@ti.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: linux-ker...@vger.kernel.org Cc: linux-usb@vger.kernel.org Cc: Android Kernel Team kernel-t...@android.com Cc: John Stultz john.stu...@linaro.org Cc: Arve Hj�nnev�g a...@android.com Cc: Benoit Goby ben...@android.com Signed-off-by: Todd Poynor toddpoy...@google.com Signed-off-by: Kiran Raparthy kiran.ku...@linaro.org [kiran: Added context to commit message Included build fix from Benoit Goby and Arve Arve Hj�nnev�g Removed lock-held field in driver as this mechanism is provided in wakeup.c wakelock(wl) terminology replaced with wakeup_source(ws) sys entry(module param) field modified to otg_wakeupsource __pm_stay_awake and __pm_relax called directly from the main code instead of calling them via otgws_grab,otgws_drop] --- drivers/usb/phy/Kconfig| 8 ++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/otg-wakeupsource.c | 171 + 3 files changed, 180 insertions(+) create mode 100644 drivers/usb/phy/otg-wakeupsource.c diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e253fa0..9c747b2 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -6,6 +6,14 @@ menu USB Physical Layer drivers config USB_PHY def_bool n +config USB_OTG_WAKEUPSOURCE + bool Hold a wakeupsource when USB connected + depends on PM_SLEEP + select USB_PHY + help + Select this to automatically hold a wakeupsource when USB is + connected, preventing suspend. + # # USB Transceiver Drivers # diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 24a9133..ca2fbaf 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_USB_PHY) += phy.o obj-$(CONFIG_OF) += of.o +obj-$(CONFIG_USB_OTG_WAKEUPSOURCE) += otg-wakeupsource.o # transceiver drivers, keep the list sorted diff --git a/drivers/usb/phy/otg-wakeupsource.c b/drivers/usb/phy/otg-wakeupsource.c new file mode 100644 index 000..fa44e11 --- /dev/null +++ b/drivers/usb/phy/otg-wakeupsource.c @@ -0,0 +1,171 @@ +/* + * otg-wakeupsource.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include linux/kernel.h +#include linux/device.h +#include linux/module.h +#include linux/notifier.h +#include linux/pm_wakeup.h +#include linux/spinlock.h +#include linux/usb/otg.h + +static bool enabled = true; +static struct usb_phy *otgws_xceiv; +static struct notifier_block otgws_nb; + + +static DEFINE_SPINLOCK(otgws_spinlock); + +/* + * Only one lock, but since these 2 fields are associated with each other... + */ + +struct otgws_lock { + char name[40]; + struct wakeup_source wsource; +}; + +/* + * VBUS present lock. + */ + +static struct otgws_lock vbus_lock; + +static int otgws_otg_notifications(struct notifier_block *nb, + unsigned long event, void *unused) +{ + unsigned long irqflags; + + if (!enabled) + return NOTIFY_OK; + + spin_lock_irqsave(otgws_spinlock, irqflags); + + switch (event) { + case USB_EVENT_VBUS: + case USB_EVENT_ENUMERATED: + __pm_stay_awake(vbus_lock.wsource); + break; + + case USB_EVENT_NONE: + case USB_EVENT_ID: + case USB_EVENT_CHARGER: + __pm_relax(vbus_lock.wsource); + break; + + default: + break; + } + + spin_unlock_irqrestore(otgws_spinlock, irqflags); + return NOTIFY_OK; +} + +static void sync_with_xceiv_state(void) +{ + if ((otgws_xceiv-last_event == USB_EVENT_VBUS) || + (otgws_xceiv-last_event == USB_EVENT_ENUMERATED)) + __pm_stay_awake(vbus_lock.wsource); + else + __pm_relax(vbus_lock.wsource); +} + +static int init_for_xceiv(void) +{ + int rv; + struct usb_phy *phy; + + if (!otgws_xceiv) { + phy = usb_get_phy(USB_PHY_TYPE_USB2); + + if (IS_ERR(phy)) { +
[RFC 2/2] usb: otg: Temporarily hold wakeupsource on charger and disconnect events
From: Todd Poynor toddpoy...@google.com usb: otg: Temporarily hold wakeupsource on charger and disconnect events Allow other parts of the system to react to the charger connect/disconnect event without allowing the system to suspend before the other parts can process the event. This wakeup_source times out after 2 seconds; if nobody else holds a wakeup_source by that time then the device can sleep. This patch also refactoras the logic of wakeupsource_init,otg_notifications and handle event funtions This is one of the number of patches from the Android AOSP tegra.git tree, which is used on Android devices. so I wanted to submit it for review to see if it should go upstream. Cc: Felipe Balbi ba...@ti.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: linux-ker...@vger.kernel.org Cc: linux-usb@vger.kernel.org Cc: Android Kernel Team kernel-t...@android.com Cc: John Stultz john.stu...@linaro.org Signed-off-by: Todd Poynor toddpoy...@google.com Signed-off-by: Kiran Raparthy kiran.ku...@linaro.org [kiran: Added context to commit message] --- drivers/usb/phy/otg-wakeupsource.c | 108 ++--- include/linux/usb/otg.h| 2 + 2 files changed, 41 insertions(+), 69 deletions(-) diff --git a/drivers/usb/phy/otg-wakeupsource.c b/drivers/usb/phy/otg-wakeupsource.c index fa44e11..d2c16b8 100644 --- a/drivers/usb/phy/otg-wakeupsource.c +++ b/drivers/usb/phy/otg-wakeupsource.c @@ -39,21 +39,25 @@ struct otgws_lock { }; /* - * VBUS present lock. ++ * VBUS present lock. Also used as a timed lock on charger ++ * connect/disconnect and USB host disconnect, to allow the system ++ * to react to the change in power. */ static struct otgws_lock vbus_lock; -static int otgws_otg_notifications(struct notifier_block *nb, - unsigned long event, void *unused) +static void otgws_handle_event(unsigned long event) { unsigned long irqflags; - if (!enabled) - return NOTIFY_OK; - spin_lock_irqsave(otgws_spinlock, irqflags); + if (!enabled) { + __pm_relax(vbus_lock.wsource); + spin_unlock_irqrestore(otgws_spinlock, irqflags); + return; + } + switch (event) { case USB_EVENT_VBUS: case USB_EVENT_ENUMERATED: @@ -63,7 +67,8 @@ static int otgws_otg_notifications(struct notifier_block *nb, case USB_EVENT_NONE: case USB_EVENT_ID: case USB_EVENT_CHARGER: - __pm_relax(vbus_lock.wsource); + __pm_wakeup_event(vbus_lock.wsource, + msecs_to_jiffies(TEMPORARY_HOLD_TIME)); break; default: @@ -71,72 +76,25 @@ static int otgws_otg_notifications(struct notifier_block *nb, } spin_unlock_irqrestore(otgws_spinlock, irqflags); - return NOTIFY_OK; -} - -static void sync_with_xceiv_state(void) -{ - if ((otgws_xceiv-last_event == USB_EVENT_VBUS) || - (otgws_xceiv-last_event == USB_EVENT_ENUMERATED)) - __pm_stay_awake(vbus_lock.wsource); - else - __pm_relax(vbus_lock.wsource); } -static int init_for_xceiv(void) +static int otgws_otg_notifications(struct notifier_block *nb, + unsigned long event, void *unused) { - int rv; - struct usb_phy *phy; - - if (!otgws_xceiv) { - phy = usb_get_phy(USB_PHY_TYPE_USB2); - - if (IS_ERR(phy)) { - pr_err(%s: No USB transceiver found\n, __func__); - return PTR_ERR(phy); - } - otgws_xceiv = phy; - - snprintf(vbus_lock.name, sizeof(vbus_lock.name), vbus-%s, -dev_name(otgws_xceiv-dev)); - wakeup_source_init(vbus_lock.wsource, vbus_lock.name); - - rv = usb_register_notifier(otgws_xceiv, otgws_nb); - - if (rv) { - pr_err(%s: usb_register_notifier on transceiver %s - failed\n, __func__, - dev_name(otgws_xceiv-dev)); - otgws_xceiv = NULL; - wakeup_source_trash(vbus_lock.wsource); - return rv; - } - } - - return 0; + otgws_handle_event(event); + return NOTIFY_OK; } static int set_enabled(const char *val, const struct kernel_param *kp) { - unsigned long irqflags; int rv = param_set_bool(val, kp); if (rv) return rv; - rv = init_for_xceiv(); - - if (rv) - return rv; - - spin_lock_irqsave(otgws_spinlock, irqflags); - - if (enabled) - sync_with_xceiv_state(); - else - __pm_relax(vbus_lock.wsource); + if (otgws_xceiv) + otgws_handle_event(otgws_xceiv-last_event); - spin_unlock_irqrestore(otgws_spinlock, irqflags);
Re: [PATCH 1/1] HID: usbhid: add usb_clear_halt determination for next hid_start_in
hi Jiri: 2014-08-22 15:45 GMT+08:00 Jiri Kosina jkos...@suse.cz: On Fri, 22 Aug 2014, CheChun Kuo wrote: HID IR device will not response to any command send from host when it is finishing paring and tring to reset itself. During this period of time, usb_cleaer_halt will be fail and if hid_start_in soon again, we has the possibility trap in infinite loop. Signed-off-by: CheChun Kuo vichy@gmail.com --- drivers/hid/usbhid/hid-core.c |3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 79cf503..256b102 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -122,7 +122,8 @@ static void hid_reset(struct work_struct *work) dev_dbg(usbhid-intf-dev, clear halt\n); rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid-urbin-pipe); clear_bit(HID_CLEAR_HALT, usbhid-iofl); - hid_start_in(hid); + if (rc == 0) + hid_start_in(hid); } I'd need a more detailed explanation for this patch, as I don't understand neither the text in the changelog nor the patch itself. Namely: - which IR devices are showing this behavior? The USB hid device that will transform IR signal to usb command when user press volume up/down, voice recording, etc. - where does the infinite loop come from? hid_reset() should error out properly if usb_clear_halt() fails and HID_IN_RUNNING flag is not set Below I briefly draw the timing when this issue happen i) hid_irq_in get URB status as -EPIPE ii) set HID_CLEAR_HALT flag and schedule hid_reset work iii) hid_reset call usb_clear_halt and hid_start_in again iv) if device still doesn't response host command, it will go to i) above and keep looping thanks for your help, -- 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
Re: [PATCH v5 3/4] usb: hcd: Caibrate PHY post hcd reset
Hi, s/Caibrate/Calibrate/ Cheers, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg -- 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 4/4] usb: renesas_usbhs: fix the usb_pkt_pop()
This patch fixes the usb_pkt_pop(). If a gadget driver calls usb_ep_dequeue(), this driver will call the usb_pkt_pop(). So, the usb_pkt_pop() should cancel the transaction. Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda...@renesas.com --- drivers/usb/renesas_usbhs/fifo.c | 30 +++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 1564829..b0c97a3 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -108,19 +108,45 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) return list_first_entry(pipe-list, struct usbhs_pkt, node); } +static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, + struct usbhs_fifo *fifo); +static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, +struct usbhs_fifo *fifo); +static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo, + struct usbhs_pkt *pkt); +#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) +#define usbhsf_dma_unmap(p)__usbhsf_dma_map_ctrl(p, 0) +static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map); struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); unsigned long flags; / spin lock / usbhs_lock(priv, flags); + usbhs_pipe_disable(pipe); + if (!pkt) pkt = __usbhsf_pkt_get(pipe); - if (pkt) + if (pkt) { + struct dma_chan *chan = NULL; + + if (fifo) + chan = usbhsf_dma_chan_get(fifo, pkt); + if (chan) { + dmaengine_terminate_all(chan); + usbhsf_fifo_clear(pipe, fifo); + usbhsf_dma_unmap(pkt); + } + __usbhsf_pkt_del(pkt); + } + + if (fifo) + usbhsf_fifo_unselect(pipe, fifo); usbhs_unlock(priv, flags); / spin unlock **/ @@ -778,8 +804,6 @@ static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, usbhs_bset(priv, fifo-sel, DREQE, dreqe); } -#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) -#define usbhsf_dma_unmap(p)__usbhsf_dma_map_ctrl(p, 0) static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) { struct usbhs_pipe *pipe = pkt-pipe; -- 1.7.9.5 -- 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 v2 1/3] libusbg: Don't try to set read only attribute
Some of function attributes are read only on configfs, so library should not try to set them and accept only empty values in functions which set multiple attributes at single call. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- src/usbg.c | 26 +++--- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/usbg.c b/src/usbg.c index 3dc4356..45c5b65 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -2311,6 +2311,12 @@ int usbg_set_function_net_attrs(usbg_function *f, usbg_f_net_attrs *attrs) int ret = USBG_SUCCESS; char *addr; + /* ifname is read only so we accept only empty string for this param */ + if (attrs-ifname[0]) { + ret = USBG_ERROR_INVALID_PARAM; + goto out; + } + addr = ether_ntoa(attrs-dev_addr); ret = usbg_write_string(f-path, f-name, dev_addr, addr); if (ret != USBG_SUCCESS) @@ -2321,10 +2327,6 @@ int usbg_set_function_net_attrs(usbg_function *f, usbg_f_net_attrs *attrs) if (ret != USBG_SUCCESS) goto out; - ret = usbg_write_string(f-path, f-name, ifname, attrs-ifname); - if (ret != USBG_SUCCESS) - goto out; - ret = usbg_write_dec(f-path, f-name, qmult, attrs-qmult); out: @@ -2342,7 +2344,10 @@ int usbg_set_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) case F_SERIAL: case F_ACM: case F_OBEX: - ret = usbg_write_dec(f-path, f-name, port_num, f_attrs-serial.port_num); + /* port_num attribute is read only so we accept only 0 +* and do nothing with it */ + ret = f_attrs-serial.port_num ? USBG_ERROR_INVALID_PARAM + : USBG_SUCCESS; break; case F_ECM: case F_SUBSET: @@ -2352,10 +2357,17 @@ int usbg_set_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) ret = usbg_set_function_net_attrs(f, f_attrs-net); break; case F_PHONET: - ret = usbg_write_string(f-path, f-name, ifname, f_attrs-phonet.ifname); + /* ifname attribute is read only +* so we accept only empty string */ + ret = f_attrs-phonet.ifname[0] ? USBG_ERROR_INVALID_PARAM + : USBG_SUCCESS; break; case F_FFS: - ret = USBG_ERROR_NOT_SUPPORTED; + /* dev_name is a virtual atribute so allow only to use empty +* empty string which means nop */ + ret = f_attrs-ffs.dev_name[0] ? USBG_ERROR_INVALID_PARAM + : USBG_SUCCESS; + break; default: ERROR(Unsupported function type\n); ret = USBG_ERROR_NOT_SUPPORTED; -- 1.7.9.5 -- 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 v2 2/3] libusbg: Add missing const qualifiers
Const qualifers should be placed in all functions which don't need to modify provided buffers to allow caller to pass literals or pointers to non-modifable space. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h | 28 +++--- src/usbg.c | 79 +++ 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 5509cdb..a44203a 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -240,7 +240,7 @@ extern const char *usbg_strerror(usbg_error e); * @param Pointer to be filled with pointer to usbg_state * @return 0 on success, usbg_error on error */ -extern int usbg_init(char *configfs_path, usbg_state **state); +extern int usbg_init(const char *configfs_path, usbg_state **state); /** * @brief Clean up the libusbg library state @@ -360,7 +360,7 @@ extern int usbg_rm_gadget_strs(usbg_gadget *g, int lang); * @param g Pointer to be filled with pointer to gadget * @return 0 on success usbg_error if error occurred */ -extern int usbg_create_gadget_vid_pid(usbg_state *s, char *name, +extern int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, uint16_t idVendor, uint16_t idProduct, usbg_gadget **g); /** @@ -374,8 +374,9 @@ extern int usbg_create_gadget_vid_pid(usbg_state *s, char *name, * @note Given strings are assumed to be in US English * @return 0 on success usbg_error if error occurred */ -extern int usbg_create_gadget(usbg_state *s, char *name, - usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, usbg_gadget **g); +extern int usbg_create_gadget(usbg_state *s, const char *name, + usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, + usbg_gadget **g); /** * @brief Set the USB gadget attributes @@ -506,7 +507,8 @@ extern int usbg_set_gadget_strs(usbg_gadget *g, int lang, * @param ser Serial number * @return 0 on success usbg_error if error occurred */ -extern int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *ser); +extern int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, +const char *ser); /** * @brief Set the manufacturer name for a gadget @@ -515,7 +517,8 @@ extern int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *ser); * @param mnf Manufacturer * @return 0 on success usbg_error if error occurred */ -extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, char *mnf); +extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, + const char *mnf); /** * @brief Set the product name for a gadget @@ -524,7 +527,8 @@ extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, char *mnf); * @param prd Product * @return 0 on success usbg_error if error occurred */ -extern int usbg_set_gadget_product(usbg_gadget *g, int lang, char *prd); +extern int usbg_set_gadget_product(usbg_gadget *g, int lang, + const char *prd); /* USB function allocation and configuration */ @@ -539,7 +543,8 @@ extern int usbg_set_gadget_product(usbg_gadget *g, int lang, char *prd); * @return 0 on success usbg_error if error occurred */ extern int usbg_create_function(usbg_gadget *g, usbg_function_type type, - char *instance, usbg_function_attrs *f_attrs, usbg_function **f); +const char *instance, usbg_function_attrs *f_attrs, + usbg_function **f); /** * @brief Get function instance name length @@ -663,7 +668,7 @@ extern int usbg_set_config_strs(usbg_config *c, int lang, * @param string Configuration description * @return 0 on success, usbg_error on failure. */ -extern int usbg_set_config_string(usbg_config *c, int lang, char *string); +extern int usbg_set_config_string(usbg_config *c, int lang, const char *string); /** * @brief Add a function to a configuration @@ -672,7 +677,8 @@ extern int usbg_set_config_string(usbg_config *c, int lang, char *string); * @param f Pointer to function * @return 0 on success, usbg_error on failure. */ -extern int usbg_add_config_function(usbg_config *c, char *name, usbg_function *f); +extern int usbg_add_config_function(usbg_config *c, const char *name, + usbg_function *f); /** * @brief Get target function of given binding @@ -712,7 +718,7 @@ extern int usbg_get_udcs(struct dirent ***udc_list); * @param udc Name of UDC to enable gadget * @return 0 on success or usbg_error if error occurred. */ -extern int usbg_enable_gadget(usbg_gadget *g, char *udc); +extern int usbg_enable_gadget(usbg_gadget *g, const char *udc); /** * @brief Disable a USB gadget device diff --git a/src/usbg.c b/src/usbg.c index 45c5b65..251946b 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -269,7 +269,7 @@ const char
[PATCH v2 3/3] libusbg: Use reentrant functions to avoid static buffers usage
ether_aton() and ether_ntoa() use static buffers which are overwritten by next call of this function so those functions should not be used in multithread environment. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h |1 + src/usbg.c | 16 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index a44203a..e123365 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -38,6 +38,7 @@ #define LANG_US_ENG0x0409 #define DEFAULT_CONFIG_LABEL config +/* This one has to be at least 18 bytes to hold network addres */ #define USBG_MAX_STR_LENGTH 256 #define USBG_MAX_PATH_LENGTH PATH_MAX #define USBG_MAX_NAME_LENGTH 40 diff --git a/src/usbg.c b/src/usbg.c index 251946b..b1b5f44 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -744,6 +744,7 @@ static int usbg_parse_function_net_attrs(usbg_function *f, usbg_function_attrs *f_attrs) { struct ether_addr *addr; + struct ether_addr addr_buf; char str_addr[USBG_MAX_STR_LENGTH]; int ret; @@ -751,7 +752,7 @@ static int usbg_parse_function_net_attrs(usbg_function *f, if (ret != USBG_SUCCESS) goto out; - addr = ether_aton(str_addr); + addr = ether_aton_r(str_addr, addr_buf); if (addr) { f_attrs-net.dev_addr = *addr; } else { @@ -763,7 +764,7 @@ static int usbg_parse_function_net_attrs(usbg_function *f, if (ret != USBG_SUCCESS) goto out; - addr = ether_aton(str_addr); + addr = ether_aton_r(str_addr, addr_buf); if (addr) { f_attrs-net.host_addr = *addr; } else { @@ -2314,6 +2315,7 @@ int usbg_get_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) int usbg_set_function_net_attrs(usbg_function *f, usbg_f_net_attrs *attrs) { int ret = USBG_SUCCESS; + char addr_buf[USBG_MAX_STR_LENGTH]; char *addr; /* ifname is read only so we accept only empty string for this param */ @@ -2322,12 +2324,12 @@ int usbg_set_function_net_attrs(usbg_function *f, usbg_f_net_attrs *attrs) goto out; } - addr = ether_ntoa(attrs-dev_addr); + addr = ether_ntoa_r(attrs-dev_addr, addr_buf); ret = usbg_write_string(f-path, f-name, dev_addr, addr); if (ret != USBG_SUCCESS) goto out; - addr = ether_ntoa(attrs-host_addr); + addr = ether_ntoa_r(attrs-host_addr, addr_buf); ret = usbg_write_string(f-path, f-name, host_addr, addr); if (ret != USBG_SUCCESS) goto out; @@ -2386,7 +2388,8 @@ int usbg_set_net_dev_addr(usbg_function *f, struct ether_addr *dev_addr) int ret = USBG_SUCCESS; if (f dev_addr) { - char *str_addr = ether_ntoa(dev_addr); + char str_buf[USBG_MAX_STR_LENGTH]; + char *str_addr = ether_ntoa_r(dev_addr, str_buf); ret = usbg_write_string(f-path, f-name, dev_addr, str_addr); } else { ret = USBG_ERROR_INVALID_PARAM; @@ -2400,7 +2403,8 @@ int usbg_set_net_host_addr(usbg_function *f, struct ether_addr *host_addr) int ret = USBG_SUCCESS; if (f host_addr) { - char *str_addr = ether_ntoa(host_addr); + char str_buf[USBG_MAX_STR_LENGTH]; + char *str_addr = ether_ntoa_r(host_addr, str_buf); ret = usbg_write_string(f-path, f-name, host_addr, str_addr); } else { ret = USBG_ERROR_INVALID_PARAM; -- 1.7.9.5 -- 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 v2 02/16] libusbg: Add guards for libconfig version
Changes sent to libcofngi has not been merged yet, so add compatibility defines to make all compile and work. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- src/usbg.c |9 + 1 file changed, 9 insertions(+) diff --git a/src/usbg.c b/src/usbg.c index b1b5f44..dfaf66c 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -31,6 +31,15 @@ #define CONFIGS_DIR configs #define FUNCTIONS_DIR functions +/* Guards for older versions of libconfig */ +#ifndef CONFIG_FORMAT_ASSIGN +#define CONFIG_FORMAT_ASSIGN CONFIG_FORMAT_DEFAULT +#endif + +#ifndef CONFIG_FORMAT_NO_SEMICOLON +#define CONFIG_FORMAT_NO_SEMICOLON CONFIG_FORMAT_DEFAULT +#endif + /** * @file usbg.c * @todo Handle buffer overflows -- 1.7.9.5 -- 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 v2 05/16] libusbg: Add export config functionality
Configuration may have several functions if we add strings and some attributes it gives a few shell commands to set it up. To avoid this add export cofiguration which allows to store usb configuration in a file. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h |8 ++ src/usbg.c | 283 +++ 2 files changed, 291 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 99c201c..02eb1dd 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -907,6 +907,14 @@ extern usbg_binding *usbg_get_next_binding(usbg_binding *b); extern int usbg_export_function(usbg_function *f, FILE *stream); /** + * @brief Exports configuration to file + * @param c Pointer to configuration to be exported + * @param stream where configuration should be saved + * @return 0 on success, usbg_error otherwise + */ +extern int usbg_export_config(usbg_config *c, FILE *stream); + +/** * @} */ #endif /* __USBG_H__ */ diff --git a/src/usbg.c b/src/usbg.c index 2af63ea..0c16113 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -2472,11 +2472,266 @@ usbg_binding *usbg_get_next_binding(usbg_binding *b) return b ? TAILQ_NEXT(b, bnode) : NULL; } +#define USBG_NAME_TAG name #define USBG_ATTRS_TAG attrs +#define USBG_STRINGS_TAG strings +#define USBG_FUNCTIONS_TAG functions +#define USBG_LANG_TAG lang #define USBG_TYPE_TAG type #define USBG_INSTANCE_TAG instance +#define USBG_ID_TAG id +#define USBG_FUNCTION_TAG function #define USBG_TAB_WIDTH 4 +static inline int generate_function_label(usbg_function *f, char *buf, int size) +{ + return snprintf(buf, size, %s_%s, +usbg_get_function_type_str(f-type), f-instance); + +} + +static int usbg_export_binding(usbg_binding *b, config_setting_t *root) +{ + config_setting_t *node; + int ret = USBG_ERROR_NO_MEM; + int cfg_ret; + char label[USBG_MAX_NAME_LENGTH]; + int nmb; + +#define CRETAE_ATTR_STRING(SOURCE, NAME) \ + do {\ + node = config_setting_add(root, NAME, CONFIG_TYPE_STRING); \ + if (!node) \ + goto out; \ + cfg_ret = config_setting_set_string(node, SOURCE); \ + if (cfg_ret != CONFIG_TRUE) { \ + ret = USBG_ERROR_OTHER_ERROR; \ + goto out; \ + } \ + } while (0) + + CRETAE_ATTR_STRING(b-name, USBG_NAME_TAG); + + nmb = generate_function_label(b-target, label, sizeof(label)); + if (nmb = sizeof(label)) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + CRETAE_ATTR_STRING(label, USBG_FUNCTION_TAG); + +#undef CRETAE_ATTR_STRING + + ret = USBG_SUCCESS; + +out: + return ret; +} + +static int usbg_export_config_bindings(usbg_config *c, config_setting_t *root) +{ + usbg_binding *b; + config_setting_t *node; + int ret = USBG_SUCCESS; + + TAILQ_FOREACH(b, c-bindings, bnode) { + node = config_setting_add(root, NULL, CONFIG_TYPE_GROUP); + if (!node) { + ret = USBG_ERROR_NO_MEM; + break; + } + + ret = usbg_export_binding(b, node); + if (ret != USBG_SUCCESS) + break; + } + + return ret; +} + +static int usbg_export_config_strs_lang(usbg_config *c, char *lang_str, + config_setting_t *root) +{ + config_setting_t *node; + usbg_config_strs strs; + int lang; + int usbg_ret, cfg_ret, ret2; + int ret = USBG_ERROR_NO_MEM; + + ret2 = sscanf(lang_str, %x, lang); + if (ret2 != 1) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + usbg_ret = usbg_get_config_strs(c, lang, strs); + if (usbg_ret != USBG_SUCCESS) { + ret = usbg_ret; + goto out; + } + + node = config_setting_add(root, USBG_LANG_TAG, CONFIG_TYPE_INT); + if (!node) + goto out; + + cfg_ret = config_setting_set_format(node, CONFIG_FORMAT_HEX); + if (cfg_ret != CONFIG_TRUE) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + cfg_ret = config_setting_set_int(node, lang); + if (cfg_ret != CONFIG_TRUE) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + node = config_setting_add(root, configuration , CONFIG_TYPE_STRING); + if (!node) + goto out; + + cfg_ret =
[PATCH v2 08/16] libusbg: Add errors which may happen during parsing
Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h |4 src/usbg.c | 24 2 files changed, 28 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 3a66ae3..3d3cba0 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -217,6 +217,10 @@ typedef enum { USBG_ERROR_BUSY = -8, USBG_ERROR_NOT_SUPPORTED = -9, USBG_ERROR_PATH_TOO_LONG = -10, + USBG_ERROR_INVALID_FORMAT = -11, + USBG_ERROR_MISSING_TAG = -12, + USBG_ERROR_INVALID_TYPE = -13, + USBG_ERROR_INVALID_VALUE = -14, USBG_ERROR_OTHER_ERROR = -99 } usbg_error; diff --git a/src/usbg.c b/src/usbg.c index ea4f85f..74f6bfd 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -226,6 +226,18 @@ const char *usbg_error_name(usbg_error e) case USBG_ERROR_PATH_TOO_LONG: ret = USBG_ERROR_PATH_TOO_LONG; break; + case USBG_ERROR_INVALID_FORMAT: + ret = USBG_ERROR_INVALID_FORMAT; + break; + case USBG_ERROR_MISSING_TAG: + ret = USBG_ERROR_MISSING_TAG; + break; + case USBG_ERROR_INVALID_TYPE: + ret = USBG_ERROR_INVALUD_TYPE; + break; + case USBG_ERROR_INVALID_VALUE: + ret = USBG_ERROR_INVALID_VALUE; + break; case USBG_ERROR_OTHER_ERROR: ret = USBG_ERROR_OTHER_ERROR; break; @@ -272,6 +284,18 @@ const char *usbg_strerror(usbg_error e) case USBG_ERROR_PATH_TOO_LONG: ret = Created path was too long to process it.; break; + case USBG_ERROR_INVALID_FORMAT: + ret = Given file has incompatible format.; + break; + case USBG_ERROR_MISSING_TAG: + ret = One of mandatory tags is missing.; + break; + case USBG_ERROR_INVALID_TYPE: + ret = One of attributes has incompatible type.; + break; + case USBG_ERROR_INVALID_VALUE: + ret = Incorrect value provided as attribute.; + break; case USBG_ERROR_OTHER_ERROR: ret = Other error; break; -- 1.7.9.5 -- 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 v2 06/16] libusbg: Add export gadget functionality
Whole gadget setting process take a lot of simple commands (or lines of code). Those shell commands may take a while or require dedicated script and hard-coding gadget configuration. To avoid such situation add to library ability to export a whole gadget into file. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h |8 ++ src/usbg.c | 314 +++ 2 files changed, 322 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 02eb1dd..3a66ae3 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -915,6 +915,14 @@ extern int usbg_export_function(usbg_function *f, FILE *stream); extern int usbg_export_config(usbg_config *c, FILE *stream); /** + * @brief Exports whole gadget to file + * @param g Pointer to gadget to be exported + * @param stream where gadget should be saved + * @return 0 on success, usbg_error otherwise + */ +extern int usbg_export_gadget(usbg_gadget *g, FILE *stream); + +/** * @} */ #endif /* __USBG_H__ */ diff --git a/src/usbg.c b/src/usbg.c index 0c16113..ea4f85f 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -2476,6 +2476,7 @@ usbg_binding *usbg_get_next_binding(usbg_binding *b) #define USBG_ATTRS_TAG attrs #define USBG_STRINGS_TAG strings #define USBG_FUNCTIONS_TAG functions +#define USBG_CONFIGS_TAG configs #define USBG_LANG_TAG lang #define USBG_TYPE_TAG type #define USBG_INSTANCE_TAG instance @@ -2732,6 +2733,41 @@ out: } +static int usbg_export_gadget_configs(usbg_gadget *g, config_setting_t *root) +{ + usbg_config *c; + config_setting_t *node, *id_node; + int ret = USBG_SUCCESS; + int cfg_ret; + + TAILQ_FOREACH(c, g-configs, cnode) { + node = config_setting_add(root, NULL, CONFIG_TYPE_GROUP); + if (!node) { + ret = USBG_ERROR_NO_MEM; + break; + } + + id_node = config_setting_add(node, USBG_ID_TAG, +CONFIG_TYPE_INT); + if (!id_node) { + ret = USBG_ERROR_NO_MEM; + break; + } + + cfg_ret = config_setting_set_int(id_node, c-id); + if (cfg_ret != CONFIG_TRUE) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + + ret = usbg_export_config_prep(c, node); + if (ret != USBG_SUCCESS) + break; + } + + return ret; +} + static int usbg_export_f_net_attrs(usbg_f_net_attrs *attrs, config_setting_t *root) { @@ -2853,6 +2889,258 @@ out: } +static int usbg_export_gadget_functions(usbg_gadget *g, config_setting_t *root) +{ + usbg_function *f; + config_setting_t *node, *inst_node; + int ret = USBG_SUCCESS; + int cfg_ret; + char label[USBG_MAX_NAME_LENGTH]; + char *func_label; + int nmb; + + TAILQ_FOREACH(f, g-functions, fnode) { + if (f-label) { + func_label = f-label; + } else { + nmb = generate_function_label(f, label, sizeof(label)); + if (nmb = sizeof(label)) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + func_label = label; + } + + node = config_setting_add(root, func_label, CONFIG_TYPE_GROUP); + if (!node) { + ret = USBG_ERROR_NO_MEM; + break; + } + + /* Add instance name to identify in this gadget */ + inst_node = config_setting_add(node, USBG_INSTANCE_TAG, + CONFIG_TYPE_STRING); + if (!inst_node) { + ret = USBG_ERROR_NO_MEM; + break; + } + + cfg_ret = config_setting_set_string(inst_node, f-instance); + if (cfg_ret != CONFIG_TRUE) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + + ret = usbg_export_function_prep(f, node); + if (ret != USBG_SUCCESS) + break; + } + + return ret; +} + +static int usbg_export_gadget_strs_lang(usbg_gadget *g, const char *lang_str, + config_setting_t *root) +{ + config_setting_t *node; + usbg_gadget_strs strs; + int lang; + int usbg_ret, cfg_ret; + int ret = USBG_ERROR_NO_MEM; + + ret = sscanf(lang_str, %x, lang); + if (ret != 1) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + usbg_ret = usbg_get_gadget_strs(g, lang, strs); + if (usbg_ret != USBG_SUCCESS) { +
[PATCH v2 03/16] libusbg: Add label field to usbg_function structure
Add some field where additional label for function can be stored. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- src/usbg.c |5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/usbg.c b/src/usbg.c index dfaf66c..e5ed240 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -84,7 +84,8 @@ struct usbg_function char *name; char *path; char *instance; - + /* Only for internal library usage */ + char *label; usbg_function_type type; }; @@ -520,6 +521,7 @@ static inline void usbg_free_function(usbg_function *f) { free(f-path); free(f-name); + free(f-label); free(f); } @@ -640,6 +642,7 @@ static usbg_function *usbg_allocate_function(const char *path, if (!f) goto out; + f-label = NULL; type_name = usbg_get_function_type_str(type); if (!type_name) { free(f); -- 1.7.9.5 -- 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 v2 04/16] libusbg: Add export function functionality
Function settings may be complicated and their configuration may take a long while. To save time it would be convenient to allow for storing function settings in a file. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h | 11 src/usbg.c | 156 +++ 2 files changed, 167 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index e123365..99c201c 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -22,6 +22,7 @@ #include netinet/ether.h #include stdint.h #include limits.h +#include stdio.h /* For FILE * */ /** * @file include/usbg/usbg.h @@ -895,6 +896,16 @@ extern usbg_config *usbg_get_next_config(usbg_config *c); */ extern usbg_binding *usbg_get_next_binding(usbg_binding *b); +/* Import / Export API */ + +/** + * @brief Exports usb function to file + * @param f Pointer to function to be exported + * @param stream where function should be saved + * @return 0 on success, usbg_error otherwise + */ +extern int usbg_export_function(usbg_function *f, FILE *stream); + /** * @} */ diff --git a/src/usbg.c b/src/usbg.c index e5ed240..2af63ea 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -26,6 +26,7 @@ #include sys/stat.h #include unistd.h #include ctype.h +#include libconfig.h #define STRINGS_DIR strings #define CONFIGS_DIR configs @@ -2470,3 +2471,158 @@ usbg_binding *usbg_get_next_binding(usbg_binding *b) { return b ? TAILQ_NEXT(b, bnode) : NULL; } + +#define USBG_ATTRS_TAG attrs +#define USBG_TYPE_TAG type +#define USBG_INSTANCE_TAG instance +#define USBG_TAB_WIDTH 4 + +static int usbg_export_f_net_attrs(usbg_f_net_attrs *attrs, + config_setting_t *root) +{ + config_setting_t *node; + char *addr; + char addr_buf[USBG_MAX_STR_LENGTH]; + int cfg_ret; + int ret = USBG_ERROR_NO_MEM; + + node = config_setting_add(root, dev_addr, CONFIG_TYPE_STRING); + if (!node) + goto out; + + addr = ether_ntoa_r(attrs-dev_addr, addr_buf); + cfg_ret = config_setting_set_string(node, addr); + if (cfg_ret != CONFIG_TRUE) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + node = config_setting_add(root, host_addr, CONFIG_TYPE_STRING); + if (!node) + goto out; + + addr = ether_ntoa_r(attrs-host_addr, addr_buf); + cfg_ret = config_setting_set_string(node, addr); + if (cfg_ret != CONFIG_TRUE) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + node = config_setting_add(root, qmult, CONFIG_TYPE_INT); + if (!node) + goto out; + + cfg_ret = config_setting_set_int(node, attrs-qmult); + ret = cfg_ret == CONFIG_TRUE ? 0 : USBG_ERROR_OTHER_ERROR; + + /* if name is read only so we don't export it */ +out: + return ret; + +} + +static int usbg_export_function_attrs(usbg_function *f, config_setting_t *root) +{ + config_setting_t *node; + usbg_function_attrs f_attrs; + int usbg_ret, cfg_ret; + int ret = USBG_ERROR_NO_MEM; + + usbg_ret = usbg_get_function_attrs(f, f_attrs); + if (usbg_ret) { + ret = usbg_ret; + goto out; + } + + switch (f-type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: + node = config_setting_add(root, port_num, CONFIG_TYPE_INT); + if (!node) + goto out; + + cfg_ret = config_setting_set_int(node, f_attrs.serial.port_num); + ret = cfg_ret == CONFIG_TRUE ? 0 : USBG_ERROR_OTHER_ERROR; + break; + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: + ret = usbg_export_f_net_attrs(f_attrs.net, root); + break; + case F_PHONET: + /* Don't export ifname because it is read only */ + break; + case F_FFS: + /* We don't need to export ffs attributes +* due to instance name export */ + ret = USBG_SUCCESS; + break; + default: + ERROR(Unsupported function type\n); + ret = USBG_ERROR_NOT_SUPPORTED; + } + +out: + return ret; +} + +/* This function does not import instance name becuase this is more property + * of a gadget than a function itselt */ +static int usbg_export_function_prep(usbg_function *f, config_setting_t *root) +{ + config_setting_t *node; + int ret = USBG_ERROR_NO_MEM; + int cfg_ret; + + node = config_setting_add(root, USBG_TYPE_TAG, CONFIG_TYPE_STRING); + if (!node) + goto out; + + cfg_ret = config_setting_set_string(node, usbg_get_function_type_str( + f-type)); + if (cfg_ret != CONFIG_TRUE) { +
[PATCH v2 07/16] libusbg: examples: Add sample application to export gadget
Add sample C code which shows how to use new functionality of libusbg - gadget export. This program allows to export chosen gadget from configfs to a file. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- examples/Makefile.am |3 +- examples/gadget-export.c | 81 ++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 examples/gadget-export.c diff --git a/examples/Makefile.am b/examples/Makefile.am index abafe3c..aeb0273 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,7 +1,8 @@ -bin_PROGRAMS = show-gadgets gadget-acm-ecm gadget-vid-pid-remove gadget-ffs +bin_PROGRAMS = show-gadgets gadget-acm-ecm gadget-vid-pid-remove gadget-ffs gadget-export gadget_acm_ecm_SOURCES = gadget-acm-ecm.c show_gadgets_SOURCES = show-gadgets.c gadget_vid_pid_remove_SOURCES = gadget-vid-pid-remove.c gadget_ffs_SOURCES = gadget-ffs.c +gadget_export_SOURCE = gadget-export.c AM_CPPFLAGS=-I../include/ AM_LDFLAGS=-L../src/ -lusbg diff --git a/examples/gadget-export.c b/examples/gadget-export.c new file mode 100644 index 000..9d51e9e --- /dev/null +++ b/examples/gadget-export.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2014 Samsung Electronics + * + * Krzysztof Opasiak k.opas...@samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/** + * @file gadget-export.c + * @example gadget-export.c + * This is an example of how to export a gadget to file. + * Common reason of doing this is to share schema of gadget + * between different devices or preserve gadget between reboots. + */ + +#include errno.h +#include string.h +#include stdio.h +#include usbg/usbg.h + +int main(int argc, char **argv) +{ + usbg_state *s; + usbg_gadget *g; + int ret = -EINVAL; + int usbg_ret; + FILE *output; + + if (argc != 3) { + fprintf(stderr, Usage: gadget-export gadget_name file_name\n); + return ret; + } + + /* Prepare output file */ + output = fopen(argv[2], w); + if (!output) { + fprintf(stderr, Error on fopen. Error: %s\n, strerror(errno)); + goto out1; + } + + /* Do gadget exporting */ + usbg_ret = usbg_init(/sys/kernel/config, s); + if (usbg_ret != USBG_SUCCESS) { + fprintf(stderr, Error on USB gadget init\n); + fprintf(stderr, Error: %s : %s\n, usbg_error_name(usbg_ret), + usbg_strerror(usbg_ret)); + goto out2; + } + + g = usbg_get_gadget(s, argv[1]); + if (!g) { + fprintf(stderr, Error on get gadget\n); + goto out3; + } + + usbg_ret = usbg_export_gadget(g, output); + if (usbg_ret != USBG_SUCCESS) { + fprintf(stderr, Error on export gadget\n); + fprintf(stderr, Error: %s : %s\n, usbg_error_name(usbg_ret), + usbg_strerror(usbg_ret)); + goto out3; + } + + ret = 0; + +out3: + usbg_cleanup(s); +out2: + fclose(output); +out1: + return ret; +} -- 1.7.9.5 -- 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 v2 01/16] libusbg: Add dependency to libconfig
This library is used to import and export gadget/function/config to and from file. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- configure.ac|1 + libusbg.pc.in |2 +- src/Makefile.am |4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 878c2ab..bff1257 100644 --- a/configure.ac +++ b/configure.ac @@ -4,6 +4,7 @@ AC_PROG_CC AM_PROG_AR AC_CONFIG_MACRO_DIR([m4]) AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) +PKG_CHECK_MODULES(LIBCONFIG, libconfig) LT_INIT AC_CONFIG_FILES([Makefile src/Makefile examples/Makefile libusbg.pc]) DX_INIT_DOXYGEN([$PACKAGE_NAME],[doxygen.cfg]) diff --git a/libusbg.pc.in b/libusbg.pc.in index 46eb245..e24d8d6 100644 --- a/libusbg.pc.in +++ b/libusbg.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: libusbg Description: USB gadget-configfs library -Requires: +Requires: libconfig Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lusbg Cflags: -I${includedir} diff --git a/src/Makefile.am b/src/Makefile.am index d955a4c..8fcaf76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,6 @@ lib_LTLIBRARIES = libusbg.la libusbg_la_SOURCES = usbg.c -libusbg_la_LDFLAGS = -version-info 0:1:0 +libusbg_la_LDFLAGS = $(LIBCONFIG_LIBS) +libusbg_la_LDFLAGS += -version-info 0:1:0 +libusbg_la_CFLAGS = $(LIBCONFIG_CFLAGS) AM_CPPFLAGS=-I../include/ -- 1.7.9.5 -- 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 v2 09/16] libusbg: Allow to store error information in usbg_gadget
If error occurred during parsing user should have an oportunity to get details about place and type of error. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- src/usbg.c |8 1 file changed, 8 insertions(+) diff --git a/src/usbg.c b/src/usbg.c index 74f6bfd..929f1c7 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -63,6 +63,7 @@ struct usbg_gadget TAILQ_HEAD(chead, usbg_config) configs; TAILQ_HEAD(fhead, usbg_function) functions; usbg_state *parent; + config_t *last_failed_import; }; struct usbg_config @@ -568,6 +569,12 @@ static void usbg_free_gadget(usbg_gadget *g) { usbg_config *c; usbg_function *f; + + if (g-last_failed_import) { + config_destroy(g-last_failed_import); + free(g-last_failed_import); + } + while (!TAILQ_EMPTY(g-configs)) { c = TAILQ_FIRST(g-configs); TAILQ_REMOVE(g-configs, c, cnode); @@ -605,6 +612,7 @@ static usbg_gadget *usbg_allocate_gadget(const char *path, const char *name, if (g) { TAILQ_INIT(g-functions); TAILQ_INIT(g-configs); + g-last_failed_import = NULL; g-name = strdup(name); g-path = strdup(path); g-parent = parent; -- 1.7.9.5 -- 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 v2 13/16] libusbg: Add import gadget functionality
Whole gadget can be exported to file using usbg_export_gadget(). This commit adds complementary API function usbg_import_gadget() which allows to import whole gadget (including attrs, strings, configs, functions and bindings) from file to configfs. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h | 12 ++ src/usbg.c | 348 +++ 2 files changed, 360 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 70b9910..23783eb 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -951,6 +951,18 @@ extern int usbg_import_function(usbg_gadget *g, FILE *stream, */ extern int usbg_import_config(usbg_gadget *g, FILE *stream, int id, usbg_config **c); +/** + * @brief Imports usb gadget from file + * @param s current state of library + * @param stream from which gadget should be imported + * @param name which shuld be used for new gadget + * @param g place for pointer to imported gadget + * if NULL this param will be ignored. + * @return 0 on success, usbg_error otherwise + */ +extern int usbg_import_gadget(usbg_state *s, FILE *stream, + const char *name, usbg_gadget **g); +/** * @} */ #endif /* __USBG_H__ */ diff --git a/src/usbg.c b/src/usbg.c index 3527c1b..32cefe4 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -3777,6 +3777,311 @@ error2: return ret; } +static int usbg_import_gadget_configs(config_setting_t *root, usbg_gadget *g) +{ + config_setting_t *node, *id_node; + int usbg_ret, cfg_ret; + int id; + usbg_config *c; + int ret = USBG_SUCCESS; + int count, i; + + count = config_setting_length(root); + + for (i = 0; i count; ++i) { + node = config_setting_get_elem(root, i); + if (!node) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + + if (!config_setting_is_group(node)) { + ret = USBG_ERROR_INVALID_TYPE; + break; + } + + /* Look for id */ + id_node = config_setting_get_member(node, USBG_ID_TAG); + if (!id_node) { + ret = USBG_ERROR_MISSING_TAG; + break; + } + + if (!usbg_config_is_int(id_node)) { + ret = USBG_ERROR_INVALID_TYPE; + break; + } + + id = config_setting_get_int(id_node); + + ret = usbg_import_config_run(g, node, id, c); + if (ret != USBG_SUCCESS) + break; + } + + return ret; +} + +static int usbg_import_gadget_functions(config_setting_t *root, usbg_gadget *g) +{ + config_setting_t *node, *inst_node; + int usbg_ret, cfg_ret; + const char *instance; + const char *label; + usbg_function *f; + int ret = USBG_SUCCESS; + int count, i; + + count = config_setting_length(root); + + for (i = 0; i count; ++i) { + node = config_setting_get_elem(root, i); + if (!node) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + + if (!config_setting_is_group(node)) { + ret = USBG_ERROR_INVALID_TYPE; + break; + } + + /* Look for instance name */ + inst_node = config_setting_get_member(node, USBG_INSTANCE_TAG); + if (!inst_node) { + ret = USBG_ERROR_MISSING_TAG; + break; + } + + if (!usbg_config_is_string(inst_node)) { + ret = USBG_ERROR_INVALID_TYPE; + break; + } + + instance = config_setting_get_string(inst_node); + if (!instance) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + + ret = usbg_import_function_run(g, node, instance, f); + if (ret != USBG_SUCCESS) + break; + + /* Set the label given by user */ + label = config_setting_name(node); + if (!label) { + ret = USBG_ERROR_OTHER_ERROR; + break; + } + + f-label = strdup(label); + if (!f-label) { + ret = USBG_ERROR_NO_MEM; + break; + } + } + + return ret; +} + +static int usbg_import_gadget_strs_lang(config_setting_t *root, usbg_gadget *g) +{ + config_setting_t *node; + int lang; + const char *str; + usbg_gadget_strs g_strs = {0}; + int usbg_ret, cfg_ret; + int ret = USBG_ERROR_INVALID_TYPE; +
[PATCH v2 10/16] libusbg: Add import function functionality
Functions can be exported to file using usbg_export_function(). This commit adds complementary API function usbg_import_function() which allows to import function from file to configfs. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h | 13 src/usbg.c | 188 +++ 2 files changed, 201 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 3d3cba0..5e75208 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -927,6 +927,19 @@ extern int usbg_export_config(usbg_config *c, FILE *stream); extern int usbg_export_gadget(usbg_gadget *g, FILE *stream); /** + +/** + * @brief Imports usb function from file and adds it to given gadget + * @param g Gadget where function should be placed + * @param stream from which function should be imported + * @param instance name which shuld be used for new function + * @param f place for pointer to imported function + * if NULL this param will be ignored. + * @return 0 on success, usbg_error otherwise + */ +extern int usbg_import_function(usbg_gadget *g, FILE *stream, + const char *instance, usbg_function **f); + * @} */ #endif /* __USBG_H__ */ diff --git a/src/usbg.c b/src/usbg.c index 929f1c7..a6c9fdf 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -3255,3 +3255,191 @@ out: config_destroy(cfg); return ret; } + +#define usbg_config_is_int(node) (config_setting_type(node) == CONFIG_TYPE_INT) +#define usbg_config_is_string(node) \ + (config_setting_type(node) == CONFIG_TYPE_STRING) + +static void usbg_set_failed_import(config_t **to_set, config_t *failed) +{ + if (*to_set != NULL) { + config_destroy(*to_set); + free(*to_set); + } + + *to_set = failed; +} + +static int usbg_import_f_net_attrs(config_setting_t *root, usbg_function *f) +{ + config_setting_t *node; + int ret = USBG_SUCCESS; + int qmult; + struct ether_addr *addr; + struct ether_addr addr_buf; + const char *str; + +#define GET_OPTIONAL_ADDR(NAME)\ + do {\ + node = config_setting_get_member(root, #NAME); \ + if (node) { \ + str = config_setting_get_string(node); \ + if (!str) { \ + ret = USBG_ERROR_INVALID_TYPE; \ + goto out; \ + } \ + \ + addr = ether_aton_r(str, addr_buf);\ + if (!addr) {\ + ret = USBG_ERROR_INVALID_VALUE; \ + goto out; \ + } \ + ret = usbg_set_net_##NAME(f, addr); \ + if (ret != USBG_SUCCESS)\ + goto out; \ + } \ + } while (0) + + GET_OPTIONAL_ADDR(host_addr); + GET_OPTIONAL_ADDR(dev_addr); + +#undef GET_OPTIONAL_ADDR + + node = config_setting_get_member(root, qmult); + if (node) { + if (!usbg_config_is_int(node)) { + ret = USBG_ERROR_INVALID_TYPE; + goto out; + } + qmult = config_setting_get_int(node); + ret = usbg_set_net_qmult(f, qmult); + } + +out: + return ret; +} + +static int usbg_import_function_attrs(config_setting_t *root, usbg_function *f) +{ + int ret = USBG_SUCCESS; + + switch (f-type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: + /* Don't import port_num because it is read only */ + break; + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: + ret = usbg_import_f_net_attrs(root, f); + break; + case F_PHONET: + /* Don't import ifname because it is read only */ + break; + case F_FFS: + /* We don't need to export ffs attributes +* due to instance name export */ + break; + default: + ERROR(Unsupported function type\n); + ret = USBG_ERROR_NOT_SUPPORTED; + } + + return ret; +} + +static int usbg_import_function_run(usbg_gadget *g, config_setting_t *root, + const char *instance, usbg_function **f) +{ + config_setting_t *node; + const char *type_str; + int
[PATCH v2 11/16] libusbg: Add import config functionality
Configurations can be exported to file using usbg_export_config(). This commit adds complementary API function usbg_import_config() which allows to import configuration (with attrs, strings and bindings) from file to chosen gadget. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- include/usbg/usbg.h | 11 ++ src/usbg.c | 416 +++ 2 files changed, 427 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 5e75208..70b9910 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -940,6 +940,17 @@ extern int usbg_export_gadget(usbg_gadget *g, FILE *stream); extern int usbg_import_function(usbg_gadget *g, FILE *stream, const char *instance, usbg_function **f); +/** + * @brief Imports usb configuration from file and adds it to given gadget + * @param g Gadget where configuration should be placed + * @param stream from which configuration should be imported + * @param id which shuld be used for new configuration + * @param c place for pointer to imported configuration + * if NULL this param will be ignored. + * @return 0 on success, usbg_error otherwise + */ +extern int usbg_import_config(usbg_gadget *g, FILE *stream, int id, + usbg_config **c); * @} */ #endif /* __USBG_H__ */ diff --git a/src/usbg.c b/src/usbg.c index a6c9fdf..3e4725d 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -3260,6 +3260,38 @@ out: #define usbg_config_is_string(node) \ (config_setting_type(node) == CONFIG_TYPE_STRING) +static int split_function_label(const char *label, usbg_function_type *type, + const char **instance) +{ + const char *floor; + char buf[USBG_MAX_NAME_LENGTH]; + int len; + int function_type; + int ret = USBG_ERROR_NOT_FOUND; + + /* We assume that function type string doesn't contain '_' */ + floor = strchr(label, '_'); + /* if phrase before _ is longer than max name length we may +* stop looking */ + len = floor - label; + if (len = USBG_MAX_NAME_LENGTH || floor == label) + goto out; + + strncpy(buf, label, len); + buf[len] = '\0'; + + function_type = usbg_lookup_function_type(buf); + if (function_type 0) + goto out; + + *type = (usbg_function_type)function_type; + *instance = floor + 1; + + ret = USBG_SUCCESS; +out: + return ret; +} + static void usbg_set_failed_import(config_t **to_set, config_t *failed) { if (*to_set != NULL) { @@ -3398,6 +3430,346 @@ out: return ret; } +static usbg_function *usbg_lookup_function(usbg_gadget *g, const char *label) +{ + usbg_function *f; + int usbg_ret; + + /* check if such function has also been imported */ + TAILQ_FOREACH(f, g-functions, fnode) { + if (f-label !strcmp(f-label, label)) + break; + } + + /* if not let's check if label follows the naming convention */ + if (!f) { + usbg_function_type type; + const char *instance; + + usbg_ret = split_function_label(label, type, instance); + if (usbg_ret != USBG_SUCCESS) + goto out; + + /* check if such function exist */ + f = usbg_get_function(g, type, instance); + } + +out: + return f; +} + +/* We have a string which should match with one of function names */ +static int usbg_import_binding_string(config_setting_t *root, usbg_config *c) +{ + const char *func_label; + usbg_function *target; + int ret; + + func_label = config_setting_get_string(root); + if (!func_label) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + target = usbg_lookup_function(c-parent, func_label); + if (!target) { + ret = USBG_ERROR_NOT_FOUND; + goto out; + } + + ret = usbg_add_config_function(c, target-name, target); +out: + return ret; +} + +static int usbg_import_binding_group(config_setting_t *root, usbg_config *c) +{ + config_setting_t *node; + const char *func_label, *name; + usbg_function *target; + int ret; + + node = config_setting_get_member(root, USBG_FUNCTION_TAG); + if (!node) { + ret = USBG_ERROR_MISSING_TAG; + goto out; + } + + /* It is allowed to provide link to existing function +* or define unlabeled instance of function in this place */ + if (usbg_config_is_string(node)) { + func_label = config_setting_get_string(node); + if (!func_label) { + ret = USBG_ERROR_OTHER_ERROR; + goto out; + } + + target = usbg_lookup_function(c-parent, func_label); + if (!target) { +
[PATCH v2 12/16] libusbg: Allow to store error information in usbg_state
If error occurred during parsing user should have an opportunity to get details about place and type of error. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- src/usbg.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/src/usbg.c b/src/usbg.c index 3e4725d..3527c1b 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -51,6 +51,7 @@ struct usbg_state char *path; TAILQ_HEAD(ghead, usbg_gadget) gadgets; + config_t *last_failed_import; }; struct usbg_gadget @@ -599,6 +600,11 @@ static void usbg_free_state(usbg_state *s) usbg_free_gadget(g); } + if (s-last_failed_import) { + config_destroy(s-last_failed_import); + free(s-last_failed_import); + } + free(s-path); free(s); } @@ -1255,6 +1261,7 @@ static int usbg_init_state(char *path, usbg_state *s) /* State takes the ownership of path and should free it */ s-path = path; + s-last_failed_import = NULL; TAILQ_INIT(s-gadgets); ret = usbg_parse_gadgets(path, s); -- 1.7.9.5 -- 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 v2 16/16] libusbg: doc: Add document about gadget schemes
Add document which clarify reasons of implementing gadget schemes and also describes syntax of such files. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com --- doc/gadget_schemes.txt | 301 1 file changed, 301 insertions(+) create mode 100644 doc/gadget_schemes.txt diff --git a/doc/gadget_schemes.txt b/doc/gadget_schemes.txt new file mode 100644 index 000..d1d44a5 --- /dev/null +++ b/doc/gadget_schemes.txt @@ -0,0 +1,301 @@ + + Gadget schemes + + +Index: +1. What are gadget schemes? +2. Why gadget schemes? +3. Gadget scheme syntax + 3.1 Function scheme + 3.2 Configuration scheme + 3.3 Gadget scheme +4. Conclusion + + +1. What are gadget schemes? + +Gadget schemes are files which contains configuration data of +gadget/function/configuration. Those files can be generated using +usbg_export_*() functions for whole gadget, configuration or single +function. Library provides also set of usbg_import_*() functions which +allows to load configuration data back to configfs. + + + 2. Why gadget schemes? + +New kernel interface - ConfigFS which along with libcomposite allows +to set up custom gadget. This can be achieved using simple, command +line file system operation like mkdir, rmdir, ln -s, read and +write. Yes, it is possible to configure usb gadget using only command +line but each time after reboot user needs to recreate all gadgets +once again. This means that after each reboot user needs to use about +15 commands (depends on number and types of function). This is +definitely not acceptable for those who used legacy gadgets and write +only modprobe g_ether. + +One of first idea to solve this is to create a script and run it +after each reboot. This approach is feasible but has many +disadvantages. First of them is security. ConfigFS is modifiable by +default only by root, so scripts has to be executed with root +rights. Secondly it's really hard to modify such a script because many +calls has hard-coded path where for example echo should be +done. There is a lot of simple, but low level operations which can +cause a lot of confusion for beginner. + +Second approach is to create executable which will create our gadget +using base libusbg API. It is also possible but let's think for a +moment why configfs has been introduced. It has been announced to +separate code from configuration. Code is a piece of C code in kernel +module which realizes usb function and configuration is understood as +composition of those functions into a gadget as a whole. If we would +like to create binary file for each gadget we would waste a lot of +work which kernel contributors put to remove hard-coded gadgets from +linux kernel. This all leads us to solution described in this document +- gadget schemes. Light weight configuration files which describes +composition of functions into gadget. They can be simply loaded using +usbg_import_*() and exported using usbg_export_*(). This makes them +easy to use equivalent of modprobe gadget_module. + + + 3. Gadget scheme syntax + +Gadget schemes implementation uses libconfig for reading and writing +scheme files. This means that all limitations of libconfig are also +present in gadget schemes. More over there are additional constrains +for scheme files. Gadget scheme is only a password and import and +export is not limited to whole gadgets. It is possible to export all 3 +types of gadget entity: function, configuration and gadget. Please +refer to libconfig documentation for details about syntax and rules. + +3.1 Function scheme + +Function scheme is a file or part of file which represents single +function. + +Example: + +instance = my_func_instance +type = ecm + +attrs = { + dev_addr = ef:33:be:9a:90:36 + dev_addr = ab:63:6e:8b:10:16 + qmult = 5 +} + +For functions, type is the only attribute which is always +mandatory. Instance is mandatory only if function is part of bigger +scheme (gadget for example). By default usbg_export_function() does +not export instance name, because usbg_import_function() takes +instance as one of parameters. This convention allows for simple +function movement between gadgets without names conflict. + +Attrs section is optional. It may not be included, present but empty +or present and filled with function attributes. Attribute names are +similar as those from configfs. Each type of function has own set of +possible attributes. It is worth to mention that some attributes are +read only and they cannot be imported from file. To make it more +user-friendly read-only parameters are just ignored. This allows for +direct use of previously exported function in import. If some +attribute has not been provided default value provided by kernel will +be used. + + 3.2 Configuration scheme + +Configuration scheme is a file or part of file which represents
Re: [PATCH v2 02/16] libusbg: Add guards for libconfig version
Hello. On 8/22/2014 3:59 PM, Krzysztof Opasiak wrote: Changes sent to libcofngi has not been merged yet, Perhaps libconfig? so add compatibility defines to make all compile and work. Signed-off-by: Krzysztof Opasiak k.opas...@samsung.com [...] WBR, Sergei -- 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 1/2] leds: usb: Add LED trigger for USB gadget activity
With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Signed-off-by: Michal Sojka so...@merica.cz --- drivers/leds/trigger/Kconfig | 8 ++ drivers/leds/trigger/Makefile| 1 + drivers/leds/trigger/ledtrig-usbgadget.c | 45 drivers/usb/musb/musb_gadget.c | 6 +++-- include/linux/leds.h | 6 + 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 drivers/leds/trigger/ledtrig-usbgadget.c diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 49794b4..9562963 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_USBGADGET + bool LED USB Gadget Trigger + depends on (USB_MUSB_GADGET || USB_MUSB_DUAL_ROLE) + depends on LEDS_TRIGGERS + help + This allows LEDs to be controlled by USB gadget activity. + If unsure, say Y. + config LEDS_TRIGGER_HEARTBEAT tristate LED Heartbeat Trigger depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48d..45917c0 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_USBGADGET) += ledtrig-usbgadget.o diff --git a/drivers/leds/trigger/ledtrig-usbgadget.c b/drivers/leds/trigger/ledtrig-usbgadget.c new file mode 100644 index 000..1eb90da --- /dev/null +++ b/drivers/leds/trigger/ledtrig-usbgadget.c @@ -0,0 +1,45 @@ +/* + * LED Trigger for USB Gadget Activity + * + * Copyright 2014 Michal Sojka so...@merica.cz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include linux/module.h +#include linux/kernel.h +#include linux/init.h +#include linux/leds.h + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_usbgadget); +static unsigned long usbgadget_blink_delay = BLINK_DELAY; + +void ledtrig_usbgadget_activity(void) +{ + led_trigger_blink_oneshot(ledtrig_usbgadget, + usbgadget_blink_delay, usbgadget_blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_usbgadget_activity); + +static int __init ledtrig_usbgadget_init(void) +{ + led_trigger_register_simple(usb-gadget, ledtrig_usbgadget); + return 0; +} + +static void __exit ledtrig_usbgadget_exit(void) +{ + led_trigger_unregister_simple(ledtrig_usbgadget); +} + +module_init(ledtrig_usbgadget_init); +module_exit(ledtrig_usbgadget_exit); + +MODULE_AUTHOR(Michal Sojka so...@merica.cz); +MODULE_DESCRIPTION(LED Trigger for USB Gadget Activity); +MODULE_LICENSE(GPL); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d4aa779..98f8b24 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -42,6 +42,7 @@ #include linux/delay.h #include linux/dma-mapping.h #include linux/slab.h +#include linux/leds.h #include musb_core.h @@ -167,11 +168,12 @@ __acquires(ep-musb-lock) if (!dma_mapping_error(musb-g.dev, request-dma)) unmap_dma_buffer(req, musb); - if (request-status == 0) + if (request-status == 0) { dev_dbg(musb-controller, %s done request %p, %d/%d\n, ep-end_point.name, request, req-request.actual, req-request.length); - else + ledtrig_usbgadget_activity(); + } else dev_dbg(musb-controller, %s request %p, %d/%d fault %d\n, ep-end_point.name, request, req-request.actual, req-request.length, diff --git a/include/linux/leds.h b/include/linux/leds.h index 0287ab2..5d9668e 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -218,6 +218,12 @@ extern void ledtrig_ide_activity(void); static inline void ledtrig_ide_activity(void) {} #endif +#ifdef CONFIG_LEDS_TRIGGER_USBGADGET +extern void ledtrig_usbgadget_activity(void); +#else +static inline void ledtrig_usbgadget_activity(void) {} +#endif + #if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE) extern void ledtrig_flash_ctrl(bool on); extern void ledtrig_torch_ctrl(bool on); -- 2.1.0
[PATCH] drivers: usb: gadget: fusb300_udc.h: Fix typo in include guard
Signed-off-by: Rasmus Villemoes li...@rasmusvillemoes.dk --- drivers/usb/gadget/udc/fusb300_udc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h index ae811d8..ad39f89 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.h +++ b/drivers/usb/gadget/udc/fusb300_udc.h @@ -12,7 +12,7 @@ #ifndef __FUSB300_UDC_H__ -#define __FUSB300_UDC_H_ +#define __FUSB300_UDC_H__ #include linux/kernel.h -- 1.9.2 -- 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
Re: [PATCH] usb: phy: twl4030-usb: Fix lost interrupts after ID pin goes down
Hi, On Thu, Aug 21, 2014 at 7:48 PM, Tony Lindgren t...@atomide.com wrote: Commit 249751f22380 (usb: phy: twl4030-usb: poll for ID disconnect) added twl4030_id_workaround_work() to deal with lost interrupts after ID pin goes down. However, this currently only works for the insertion. The PHY interrupts are not working after disconnecting an USB-A device from the board, and the deeper idle states for omap are blocked as the USB controller stays busy. The issue can be solved by calling delayed work from twl4030_usb_irq() when ID pin is down and the PHY is not asleep like we already do in twl4030_id_workaround_work(). The way it is supposed to work is that after plugging in the cable twl4030_phy_power_on() sees ID_GROUND and kicks off id_workaround_work every second. When cable is unplugged, twl4030_id_workaround_work() sees changes in STS_HW_CONDITIONS register and triggers events. Doesn't that work for you, why do you need to trigger it from twl4030_usb_irq() too? But as both twl4030_usb_irq() and twl4030_id_workaround_work() already do pretty much the same thing, let's call twl4030_usb_irq() from twl4030_id_workaround_work() instead of adding some more duplicate code. The difference is the sysfs_notify() call, so now every time id_workaround_work triggers (around once per second while the cable is plugged) userspace will now get useless uevent. Haven't actually checked if it really happens though, so I might be wrong. -- Gražvydas -- 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
Re: [RFC 1/2] USB: OTG: Hold wakeupsource when VBUS present
On Fri, 22 Aug 2014, Kiran Kumar Raparthy wrote: From: Todd Poynor toddpoy...@google.com USB: OTG: Hold wakeupsource when VBUS present Enabled by default, can disable with: echo N /sys/module/otg_wakeupsource/parameters/enabled This is one of the number of patches from the Android AOSP common.git tree, which is used on almost all Android devices. so I wanted to submit it for review to see if it should go upstream. --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -6,6 +6,14 @@ menu USB Physical Layer drivers config USB_PHY def_bool n +config USB_OTG_WAKEUPSOURCE + bool Hold a wakeupsource when USB connected + depends on PM_SLEEP + select USB_PHY + help + Select this to automatically hold a wakeupsource when USB is + connected, preventing suspend. Without commenting on the appropriateness of this change, I'd like to point out that users will not understand either the Kconfig symbol name or the help text. The help text, especially, ought to be clear even to people not very familiar with USB. Something more like this would be a lot better: Prevent the system from going into automatic suspend while it is attached as a USB peripheral. Alan Stern -- 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 v2] drivers: usb: gadget: fusb300_udc.h: Fix typo in include guard
Clearly this was meant to be an include guard, but a trailing underscore was missing. It has been this way since the file was introduced in 0fe6f1d1 (usb: udc: add Faraday fusb300 driver). Signed-off-by: Rasmus Villemoes li...@rasmusvillemoes.dk --- drivers/usb/gadget/udc/fusb300_udc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h index ae811d8..ad39f89 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.h +++ b/drivers/usb/gadget/udc/fusb300_udc.h @@ -12,7 +12,7 @@ #ifndef __FUSB300_UDC_H__ -#define __FUSB300_UDC_H_ +#define __FUSB300_UDC_H__ #include linux/kernel.h -- 2.0.4 -- 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
Re: [Bug 80711] [PATCH]SG_FLAG_LUN_INHIBIT is no longer implemented and there's not way to prevent the kernel from using the 2nd cdb byte for the LUN
On Thu, 21 Aug 2014, Christoph Hellwig wrote: On Thu, Aug 21, 2014 at 05:43:41PM -0400, Martin K. Petersen wrote: Alan Okay, here's a patch that implements the suggestion, except that I Alan put the flag in the Scsi_Host structure instead of the template. Alan This was to minimize the impact of the change. Among the various Alan SCSI-over-USB transports, only the Bulk-Only transport gives the Alan LUN separately from the CDB. I don't know if there are any Alan multi-LUN USB devices that don't use the Bulk-Only transport, but Alan if there are then they won't work if the LUN isn't stored in Alan CDB[1]. I'm in agreement with this approach. I like it too. One idea to unclutter the fastpath would be to have a single flag that controls if the LUN is set which is based on the host(-template) flag and the scsi level, which would allow us to remove all the clutter around that area. Good idea. An enhanced patch is below. If I can get a Tested-By: from Tiziano and one or two Acked-By: responses, I'll submit this for the current and stable kernels. Sending the initial INQUIRY command to LUNs larger than 0 involves a chicken-and-egg problem -- we don't know whether to fill in the LUN bits in the command until we know the SCSI level, and we don't know the SCSI level until the INQUIRY response is received. The solution we have been using is to store the most recently discovered level in the target structure, and use it as a default. If probing starts with LUN 0, and if all the LUNs have similar levels, this ought to work. Except for one thing: The code does store the default level in the scsi_target, but forgets to copy it back into each newly allocated scsi_device! I added a line to do that into the patch. Alan Stern Index: usb-3.16/include/scsi/scsi_host.h === --- usb-3.16.orig/include/scsi/scsi_host.h +++ usb-3.16/include/scsi/scsi_host.h @@ -695,6 +695,9 @@ struct Scsi_Host { /* The controller does not support WRITE SAME */ unsigned no_write_same:1; + /* The transport requires the LUN bits NOT to be stored in CDB[1] */ + unsigned no_scsi2_lun_in_cdb:1; + /* * Optional work queue to be utilized by the transport */ Index: usb-3.16/include/scsi/scsi_device.h === --- usb-3.16.orig/include/scsi/scsi_device.h +++ usb-3.16/include/scsi/scsi_device.h @@ -174,6 +174,7 @@ struct scsi_device { unsigned wce_default_on:1; /* Cache is ON by default */ unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ unsigned broken_fua:1; /* Don't set FUA bit */ + unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ atomic_t disk_events_disable_depth; /* disable depth for disk events */ Index: usb-3.16/drivers/scsi/scsi.c === --- usb-3.16.orig/drivers/scsi/scsi.c +++ usb-3.16/drivers/scsi/scsi.c @@ -674,14 +674,10 @@ int scsi_dispatch_cmd(struct scsi_cmnd * goto out; } - /* -* If SCSI-2 or lower, store the LUN value in cmnd. -*/ - if (cmd-device-scsi_level = SCSI_2 - cmd-device-scsi_level != SCSI_UNKNOWN) { + /* Store the LUN value in cmnd, if needed. */ + if (cmd-device-lun_in_cdb) cmd-cmnd[1] = (cmd-cmnd[1] 0x1f) | (cmd-device-lun 5 0xe0); - } scsi_log_send(cmd); Index: usb-3.16/drivers/scsi/scsi_scan.c === --- usb-3.16.orig/drivers/scsi/scsi_scan.c +++ usb-3.16/drivers/scsi/scsi_scan.c @@ -257,6 +257,7 @@ static struct scsi_device *scsi_alloc_sd sdev-sdev_gendev.parent = get_device(starget-dev); sdev-sdev_target = starget; + sdev-scsi_level = starget-scsi_level; /* usually NULL and set by -slave_alloc instead */ sdev-hostdata = hostdata; @@ -735,6 +736,15 @@ static int scsi_probe_lun(struct scsi_de sdev-scsi_level++; sdev-sdev_target-scsi_level = sdev-scsi_level; + /* +* If SCSI-2 or lower, and if the transport requires it, +* store the LUN value in CDB[1]. +*/ + if (sdev-scsi_level = SCSI_2 + sdev-scsi_level != SCSI_UNKNOWN + !sdev-host-no_scsi2_lun_in_cdb) + sdev-lun_in_cdb = 1; + return 0; } Index: usb-3.16/drivers/usb/storage/usb.c === --- usb-3.16.orig/drivers/usb/storage/usb.c +++ usb-3.16/drivers/usb/storage/usb.c @@ -981,6 +981,14 @@ int usb_stor_probe2(struct us_data *us) if (!(us-fflags US_FL_SCM_MULT_TARG)) us_to_host(us)-max_id = 1; + /* +* Like Windows, we won't store the LUN bits in CDB[1] for SCSI-2 +
Re: [PATCH v2] drivers: usb: gadget: fusb300_udc.h: Fix typo in include guard
On Fri, Aug 22, 2014 at 04:44:33PM +0200, Rasmus Villemoes wrote: Clearly this was meant to be an include guard, but a trailing underscore was missing. It has been this way since the file was introduced in 0fe6f1d1 (usb: udc: add Faraday fusb300 driver). right here you need to have: Fixes: 0fe6f1d1 (usb: udc: add Faraday fusb300 driver) Cc: sta...@vger.kernel.org Signed-off-by: Rasmus Villemoes li...@rasmusvillemoes.dk --- drivers/usb/gadget/udc/fusb300_udc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/fusb300_udc.h b/drivers/usb/gadget/udc/fusb300_udc.h index ae811d8..ad39f89 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.h +++ b/drivers/usb/gadget/udc/fusb300_udc.h @@ -12,7 +12,7 @@ #ifndef __FUSB300_UDC_H__ -#define __FUSB300_UDC_H_ +#define __FUSB300_UDC_H__ #include linux/kernel.h -- 2.0.4 -- balbi signature.asc Description: Digital signature
Re: [Bug 80711] [PATCH]SG_FLAG_LUN_INHIBIT is no longer implemented and there's not way to prevent the kernel from using the 2nd cdb byte for the LUN
On Fri, Aug 22, 2014 at 10:53:42AM -0400, Alan Stern wrote: Good idea. An enhanced patch is below. If I can get a Tested-By: from Tiziano and one or two Acked-By: responses, I'll submit this for the current and stable kernels. Sending the initial INQUIRY command to LUNs larger than 0 involves a chicken-and-egg problem -- we don't know whether to fill in the LUN bits in the command until we know the SCSI level, and we don't know the SCSI level until the INQUIRY response is received. The solution we have been using is to store the most recently discovered level in the target structure, and use it as a default. If probing starts with LUN 0, and if all the LUNs have similar levels, this ought to work. Except for one thing: The code does store the default level in the scsi_target, but forgets to copy it back into each newly allocated scsi_device! I added a line to do that into the patch. Looks good to me, Acked-by: Christoph Hellwig h...@lst.de Do you want to queue this up in the USB tree? From the looks of what I have on my plate so far it seems like we could avoid conflicts with it in the SCSI tree. -- 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
Re: [Bug 80711] [PATCH]SG_FLAG_LUN_INHIBIT is no longer implemented and there's not way to prevent the kernel from using the 2nd cdb byte for the LUN
Alan == Alan Stern st...@rowland.harvard.edu writes: Alan Sending the initial INQUIRY command to LUNs larger than 0 involves Alan a chicken-and-egg problem -- we don't know whether to fill in the Alan LUN bits in the command until we know the SCSI level, and we don't Alan know the SCSI level until the INQUIRY response is received. The Alan solution we have been using is to store the most recently Alan discovered level in the target structure, and use it as a default. Alan If probing starts with LUN 0, and if all the LUNs have similar Alan levels, this ought to work. Looks good, Alan. Acked-by: Martin K. Petersen martin.peter...@oracle.com -- Martin K. Petersen Oracle Linux Engineering -- 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
Re: [PATCH v2] drivers: usb: gadget: fusb300_udc.h: Fix typo in include guard
Felipe Balbi ba...@ti.com writes: On Fri, Aug 22, 2014 at 04:44:33PM +0200, Rasmus Villemoes wrote: Clearly this was meant to be an include guard, but a trailing underscore was missing. It has been this way since the file was introduced in 0fe6f1d1 (usb: udc: add Faraday fusb300 driver). right here you need to have: Fixes: 0fe6f1d1 (usb: udc: add Faraday fusb300 driver) Cc: sta...@vger.kernel.org Really? I can't see that it satisfies the Documentation/stable_kernel_rules.txt. There's no chance of build error, since the file is only included directly from a single .c file. As you can see on LKML I've sent a few handfuls of similar patches all over the tree; IMHO none of them qualify for stable. If you insist, I'll add the Fixes and Cc tags. Thanks, Rasmus -- 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
Re: [Bug 80711] [PATCH]SG_FLAG_LUN_INHIBIT is no longer implemented and there's not way to prevent the kernel from using the 2nd cdb byte for the LUN
On Fri, 22 Aug 2014, Christoph Hellwig wrote: On Fri, Aug 22, 2014 at 10:53:42AM -0400, Alan Stern wrote: Good idea. An enhanced patch is below. If I can get a Tested-By: from Tiziano and one or two Acked-By: responses, I'll submit this for the current and stable kernels. Sending the initial INQUIRY command to LUNs larger than 0 involves a chicken-and-egg problem -- we don't know whether to fill in the LUN bits in the command until we know the SCSI level, and we don't know the SCSI level until the INQUIRY response is received. The solution we have been using is to store the most recently discovered level in the target structure, and use it as a default. If probing starts with LUN 0, and if all the LUNs have similar levels, this ought to work. Except for one thing: The code does store the default level in the scsi_target, but forgets to copy it back into each newly allocated scsi_device! I added a line to do that into the patch. Looks good to me, Acked-by: Christoph Hellwig h...@lst.de Do you want to queue this up in the USB tree? From the looks of what I have on my plate so far it seems like we could avoid conflicts with it in the SCSI tree. After hearing from Tiziano, I'll submit the patch to the SCSI tree. Alan Stern -- 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] Including XHCI_TRUST_TX_LENGTH for Renesas uPD720202 USB 3.0 chip.
Renesas uPD720202 USB 3.0 chip needs XHCI_TRUST_TX_LENGTH quirk workaround as per below logs produced when using a Diammond video capture dongle: Aug 21 18:07:33 [kernel] handle_tx_event: 67 callbacks suppressed Aug 21 18:07:33 [kernel] xhci_hcd :01:00.0: WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk? - Last output repeated 9 times - While at it I took the opportunity to define Renesas uPD720202 device ID. Signed-off-by: Rodrigo Severo rodr...@fabricadeideias.com --- drivers/usb/host/xhci-pci.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 47390e3..52df456 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -38,6 +38,8 @@ #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 +#define PCI_DEVICE_ID_RENESAS_UPD720202 0x0015 + static const char hcd_name[] = xhci_hcd; /* called after powerup, by probe or system-pm wakeup */ @@ -143,10 +145,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci-quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev-vendor == PCI_VENDOR_ID_RENESAS - pdev-device == 0x0015 - pdev-subsystem_vendor == PCI_VENDOR_ID_SAMSUNG - pdev-subsystem_device == 0xc0cd) - xhci-quirks |= XHCI_RESET_ON_RESUME; + pdev-device == PCI_DEVICE_ID_RENESAS_UPD720202) { + xhci-quirks |= XHCI_TRUST_TX_LENGTH; + if (pdev-subsystem_vendor == PCI_VENDOR_ID_SAMSUNG + pdev-subsystem_device == 0xc0cd) + xhci-quirks |= XHCI_RESET_ON_RESUME; + } if (pdev-vendor == PCI_VENDOR_ID_VIA) xhci-quirks |= XHCI_RESET_ON_RESUME; } -- 1.8.5.5 -- 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
Re: [Bug 80711] [PATCH]SG_FLAG_LUN_INHIBIT is no longer implemented and there's not way to prevent the kernel from using the 2nd cdb byte for the LUN
On Fri, 2014-08-22 at 10:53 -0400, Alan Stern wrote: On Thu, 21 Aug 2014, Christoph Hellwig wrote: On Thu, Aug 21, 2014 at 05:43:41PM -0400, Martin K. Petersen wrote: Alan Okay, here's a patch that implements the suggestion, except that I Alan put the flag in the Scsi_Host structure instead of the template. Alan This was to minimize the impact of the change. Among the various Alan SCSI-over-USB transports, only the Bulk-Only transport gives the Alan LUN separately from the CDB. I don't know if there are any Alan multi-LUN USB devices that don't use the Bulk-Only transport, but Alan if there are then they won't work if the LUN isn't stored in Alan CDB[1]. I'm in agreement with this approach. I like it too. One idea to unclutter the fastpath would be to have a single flag that controls if the LUN is set which is based on the host(-template) flag and the scsi level, which would allow us to remove all the clutter around that area. Good idea. An enhanced patch is below. If I can get a Tested-By: from Tiziano and one or two Acked-By: responses, I'll submit this for the current and stable kernels. Sending the initial INQUIRY command to LUNs larger than 0 involves a chicken-and-egg problem -- we don't know whether to fill in the LUN bits in the command until we know the SCSI level, and we don't know the SCSI level until the INQUIRY response is received. The solution we have been using is to store the most recently discovered level in the target structure, and use it as a default. If probing starts with LUN 0, and if all the LUNs have similar levels, this ought to work. Except for one thing: The code does store the default level in the scsi_target, but forgets to copy it back into each newly allocated scsi_device! I added a line to do that into the patch. Alan Stern Index: usb-3.16/include/scsi/scsi_host.h === --- usb-3.16.orig/include/scsi/scsi_host.h +++ usb-3.16/include/scsi/scsi_host.h @@ -695,6 +695,9 @@ struct Scsi_Host { /* The controller does not support WRITE SAME */ unsigned no_write_same:1; + /* The transport requires the LUN bits NOT to be stored in CDB[1] */ + unsigned no_scsi2_lun_in_cdb:1; I think Christoph mentioned shortening this flag length, but personally I'm not that bothered. /* * Optional work queue to be utilized by the transport */ Index: usb-3.16/include/scsi/scsi_device.h === --- usb-3.16.orig/include/scsi/scsi_device.h +++ usb-3.16/include/scsi/scsi_device.h @@ -174,6 +174,7 @@ struct scsi_device { unsigned wce_default_on:1; /* Cache is ON by default */ unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ unsigned broken_fua:1; /* Don't set FUA bit */ + unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ atomic_t disk_events_disable_depth; /* disable depth for disk events */ Index: usb-3.16/drivers/scsi/scsi.c === --- usb-3.16.orig/drivers/scsi/scsi.c +++ usb-3.16/drivers/scsi/scsi.c @@ -674,14 +674,10 @@ int scsi_dispatch_cmd(struct scsi_cmnd * goto out; } - /* - * If SCSI-2 or lower, store the LUN value in cmnd. - */ - if (cmd-device-scsi_level = SCSI_2 - cmd-device-scsi_level != SCSI_UNKNOWN) { + /* Store the LUN value in cmnd, if needed. */ + if (cmd-device-lun_in_cdb) cmd-cmnd[1] = (cmd-cmnd[1] 0x1f) | (cmd-device-lun 5 0xe0); - } scsi_log_send(cmd); Index: usb-3.16/drivers/scsi/scsi_scan.c === --- usb-3.16.orig/drivers/scsi/scsi_scan.c +++ usb-3.16/drivers/scsi/scsi_scan.c @@ -257,6 +257,7 @@ static struct scsi_device *scsi_alloc_sd sdev-sdev_gendev.parent = get_device(starget-dev); sdev-sdev_target = starget; + sdev-scsi_level = starget-scsi_level; Why is this necessary? Isn't this set correctly in scsi_probe_lun? The target level is actually set from the device level. Other than this, I'm fine with the code ... you can add the acked by from me when we resolve the above question. James /* usually NULL and set by -slave_alloc instead */ sdev-hostdata = hostdata; @@ -735,6 +736,15 @@ static int scsi_probe_lun(struct scsi_de sdev-scsi_level++; sdev-sdev_target-scsi_level = sdev-scsi_level; + /* + * If SCSI-2 or lower, and if the transport requires it, + * store the LUN value in CDB[1]. + */ + if (sdev-scsi_level = SCSI_2 + sdev-scsi_level != SCSI_UNKNOWN + !sdev-host-no_scsi2_lun_in_cdb) + sdev-lun_in_cdb = 1; + return 0; } Index:
[PATCH v3 9/9] usb: chipidea: add support to the generic PHY framework in ChipIdea
This patch adds support of the PHY framework for ChipIdea drivers. Changes are done in both the ChipIdea common code and in the drivers accessing the PHY. This is done by adding a new PHY member in ChipIdea's structures and by taking care of it in the code. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com --- drivers/usb/chipidea/ci.h | 5 ++- drivers/usb/chipidea/core.c| 71 ++ drivers/usb/chipidea/debug.c | 4 ++- drivers/usb/chipidea/host.c| 5 ++- drivers/usb/chipidea/otg_fsm.c | 6 +++- include/linux/usb/chipidea.h | 2 ++ 6 files changed, 76 insertions(+), 17 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index dac5ab6adfa2..7e9e8223672a 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -161,7 +161,8 @@ struct hw_bank { * @test_mode: the selected test mode * @platdata: platform specific information supplied by parent device * @vbus_active: is VBUS active - * @usb_phy: pointer to USB PHY, if any + * @phy: pointer to PHY, if any + * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework * @hcd: pointer to usb_hcd for ehci host driver * @debugfs: root dentry for this controller in debugfs * @id_event: indicates there is an id event, and handled at ci_otg_work @@ -202,6 +203,8 @@ struct ci_hdrc { struct ci_hdrc_platform_data*platdata; int vbus_active; + struct phy *phy; + /* old usb_phy interface */ struct usb_phy *usb_phy; struct usb_hcd *hcd; struct dentry *debugfs; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index a8cd35fd8175..0041f5b5eafc 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -47,6 +47,7 @@ #include linux/delay.h #include linux/device.h #include linux/dma-mapping.h +#include linux/phy/phy.h #include linux/platform_device.h #include linux/module.h #include linux/idr.h @@ -293,6 +294,46 @@ static void hw_phymode_configure(struct ci_hdrc *ci) } /** + * _ci_usb_phy_init: initialize phy taking in account both phy and usb_phy + * interfaces + * @ci: the controller + * + * This function returns an error code if the phy failed to init + */ +static int _ci_usb_phy_init(struct ci_hdrc *ci) +{ + int ret; + + if (ci-phy) { + ret = phy_init(ci-phy); + if (ret) { + phy_exit(ci-phy); + return ret; + } + ret = phy_power_on(ci-phy); + } else { + ret = usb_phy_init(ci-usb_phy); + } + + return ret; +} + +/** + * _ci_usb_phy_exit: deinitialize phy taking in account both phy and usb_phy + * interfaces + * @ci: the controller + */ +static void ci_usb_phy_exit(struct ci_hdrc *ci) +{ + if (ci-phy) { + phy_power_off(ci-phy); + phy_exit(ci-phy); + } else { + usb_phy_shutdown(ci-usb_phy); + } +} + +/** * ci_usb_phy_init: initialize phy according to different phy type * @ci: the controller * @@ -306,7 +347,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci) case USBPHY_INTERFACE_MODE_UTMI: case USBPHY_INTERFACE_MODE_UTMIW: case USBPHY_INTERFACE_MODE_HSIC: - ret = usb_phy_init(ci-usb_phy); + ret = _ci_usb_phy_init(ci); if (ret) return ret; hw_phymode_configure(ci); @@ -314,12 +355,12 @@ static int ci_usb_phy_init(struct ci_hdrc *ci) case USBPHY_INTERFACE_MODE_ULPI: case USBPHY_INTERFACE_MODE_SERIAL: hw_phymode_configure(ci); - ret = usb_phy_init(ci-usb_phy); + ret = _ci_usb_phy_init(ci); if (ret) return ret; break; default: - ret = usb_phy_init(ci-usb_phy); + ret = _ci_usb_phy_init(ci); } return ret; @@ -595,23 +636,27 @@ static int ci_hdrc_probe(struct platform_device *pdev) return -ENODEV; } - if (ci-platdata-usb_phy) + if (ci-platdata-phy) + ci-phy = ci-platdata-phy; + else if (ci-platdata-usb_phy) ci-usb_phy = ci-platdata-usb_phy; else - ci-usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); + ci-phy = devm_phy_get(dev, usb-phy); - if (IS_ERR(ci-usb_phy)) { - ret = PTR_ERR(ci-usb_phy); + if (IS_ERR(ci-phy)) { /* * if -ENXIO is returned, it means PHY layer wasn't * enabled, so it makes no sense to return -EPROBE_DEFER * in that case, since no PHY driver will ever probe. */ - if (ret == -ENXIO) -
[PATCH v3 8/9] usb: chipidea: move usb_otg into struct ci_hdrc
Move the usb_otg member from struct usb_phy to struct ci_hdrc. Rework its initialization taking in account this modification. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com --- drivers/usb/chipidea/ci.h | 1 + drivers/usb/chipidea/host.c| 8 +++- drivers/usb/chipidea/otg_fsm.c | 15 ++- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index b2caa1772712..dac5ab6adfa2 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -177,6 +177,7 @@ struct ci_hdrc { struct ci_role_driver *roles[CI_ROLE_END]; enum ci_rolerole; boolis_otg; + struct usb_otg otg; struct otg_fsm fsm; struct ci_otg_fsm_timer_list*fsm_timer; struct work_struct work; diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 0b67d78dd953..0952d4adfa4c 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -85,13 +85,11 @@ static int host_start(struct ci_hdrc *ci) if (ret) { goto disable_reg; } else { - struct usb_otg *otg = ci-usb_phy-otg; + struct usb_otg *otg = ci-otg; ci-hcd = hcd; - if (otg) { - otg-host = hcd-self; - hcd-self.otg_port = 1; - } + otg-host = hcd-self; + hcd-self.otg_port = 1; } if (ci-platdata-flags CI_HDRC_DISABLE_STREAMING) diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 8a64ce87364e..7eb86863fb3c 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -778,20 +778,9 @@ void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci) int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) { int retval = 0; - struct usb_otg *otg; - otg = devm_kzalloc(ci-dev, - sizeof(struct usb_otg), GFP_KERNEL); - if (!otg) { - dev_err(ci-dev, - Failed to allocate usb_otg structure for ci hdrc otg!\n); - return -ENOMEM; - } - - otg-usb_phy = ci-usb_phy; - otg-gadget = ci-gadget; - ci-fsm.otg = otg; - ci-usb_phy-otg = ci-fsm.otg; + ci-otg.usb_phy = ci-usb_phy; + ci-fsm.otg = ci-otg; ci-fsm.power_up = 1; ci-fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0; ci-fsm.otg-state = OTG_STATE_UNDEFINED; -- 1.9.1 -- 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 v3 2/9] usb: rename phy to usb_phy in OTG
This patch prepares the introduction of the generic PHY support in the USB OTG common functions. The USB PHY member of the OTG structure is renamed to 'usb_phy' and modifications are done in all drivers accessing it. Renaming this pointer will allow to keep the compatibility for USB PHY drivers. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com --- drivers/phy/phy-omap-usb2.c | 6 ++-- drivers/usb/chipidea/otg_fsm.c | 2 +- drivers/usb/phy/phy-ab8500-usb.c| 6 ++-- drivers/usb/phy/phy-fsl-usb.c | 13 drivers/usb/phy/phy-generic.c | 2 +- drivers/usb/phy/phy-gpio-vbus-usb.c | 4 +-- drivers/usb/phy/phy-isp1301-omap.c | 10 +++--- drivers/usb/phy/phy-msm-usb.c | 61 +++-- drivers/usb/phy/phy-mv-usb.c| 4 +-- drivers/usb/phy/phy-samsung-usb2.c | 2 +- drivers/usb/phy/phy-tahvo.c | 8 +++-- drivers/usb/phy/phy-ulpi.c | 6 ++-- include/linux/usb/otg.h | 2 +- 13 files changed, 66 insertions(+), 60 deletions(-) diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 3bb54e55c762..a454042ddb06 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -60,7 +60,7 @@ EXPORT_SYMBOL_GPL(omap_usb2_set_comparator); static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) { - struct omap_usb *phy = phy_to_omapusb(otg-phy); + struct omap_usb *phy = phy_to_omapusb(otg-usb_phy); if (!phy-comparator) return -ENODEV; @@ -70,7 +70,7 @@ static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) static int omap_usb_start_srp(struct usb_otg *otg) { - struct omap_usb *phy = phy_to_omapusb(otg-phy); + struct omap_usb *phy = phy_to_omapusb(otg-usb_phy); if (!phy-comparator) return -ENODEV; @@ -255,7 +255,7 @@ static int omap_usb2_probe(struct platform_device *pdev) otg-set_vbus = omap_usb_set_vbus; if (phy_data-flags OMAP_USB2_HAS_START_SRP) otg-start_srp = omap_usb_start_srp; - otg-phy= phy-phy; + otg-usb_phy= phy-phy; platform_set_drvdata(pdev, phy); diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 8cb2508a6b71..d8490e758a74 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -788,7 +788,7 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) return -ENOMEM; } - otg-phy = ci-transceiver; + otg-usb_phy = ci-transceiver; otg-gadget = ci-gadget; ci-fsm.otg = otg; ci-transceiver-otg = ci-fsm.otg; diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 2d5250143ce1..3a802fa7dae2 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -1056,7 +1056,7 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg, if (!otg) return -ENODEV; - ab = phy_to_ab(otg-phy); + ab = phy_to_ab(otg-usb_phy); ab-phy.otg-gadget = gadget; @@ -1080,7 +1080,7 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) if (!otg) return -ENODEV; - ab = phy_to_ab(otg-phy); + ab = phy_to_ab(otg-usb_phy); ab-phy.otg-host = host; @@ -1382,7 +1382,7 @@ static int ab8500_usb_probe(struct platform_device *pdev) ab-phy.set_power = ab8500_usb_set_power; ab-phy.otg-state = OTG_STATE_UNDEFINED; - otg-phy= ab-phy; + otg-usb_phy= ab-phy; otg-set_host = ab8500_usb_set_host; otg-set_peripheral = ab8500_usb_set_peripheral; diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index a22f88fb8176..b4cc341094ac 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -499,7 +499,8 @@ int fsl_otg_start_host(struct otg_fsm *fsm, int on) { struct usb_otg *otg = fsm-otg; struct device *dev; - struct fsl_otg *otg_dev = container_of(otg-phy, struct fsl_otg, phy); + struct fsl_otg *otg_dev = + container_of(otg-usb_phy, struct fsl_otg, phy); u32 retval = 0; if (!otg-host) @@ -594,7 +595,7 @@ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host) if (!otg) return -ENODEV; - otg_dev = container_of(otg-phy, struct fsl_otg, phy); + otg_dev = container_of(otg-usb_phy, struct fsl_otg, phy); if (otg_dev != fsl_otg_dev) return -ENODEV; @@ -644,7 +645,7 @@ static int fsl_otg_set_peripheral(struct usb_otg *otg, if (!otg) return -ENODEV; - otg_dev = container_of(otg-phy, struct fsl_otg, phy); + otg_dev = container_of(otg-usb_phy, struct fsl_otg, phy); VDBG(otg_dev 0x%x\n,
[PATCH v3 3/9] usb: add support to the generic PHY framework in OTG
This patch adds support of the PHY framework in OTG and keeps the USB PHY compatibility. Here the only modification is to add PHY member in the OTG structure, along with the USB PHY one. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com --- include/linux/usb/otg.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 978fbbb0e266..52661c5da690 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -9,11 +9,14 @@ #ifndef __LINUX_USB_OTG_H #define __LINUX_USB_OTG_H +#include linux/phy/phy.h #include linux/usb/phy.h struct usb_otg { u8 default_a; + struct phy *phy; + /* old usb_phy interface */ struct usb_phy *usb_phy; struct usb_bus *host; struct usb_gadget *gadget; -- 1.9.1 -- 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 v3 7/9] usb: rename transceiver and phy to usb_phy in ChipIdea
This patch prepares the introduction of the generic PHY support in the USB ChipIdea common functions. The USB PHY member of the ChipIdea structure ('transceiver') is renamed to 'usb_phy', the 'phy' member of the ChipIdea pdata structure is renamed to 'usb_phy' and modifications are done in all drivers accessing it. Renaming this pointer will allow to keep the compatibility for USB PHY drivers. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com --- drivers/usb/chipidea/ci.h | 4 ++-- drivers/usb/chipidea/ci_hdrc_imx.c | 2 +- drivers/usb/chipidea/ci_hdrc_msm.c | 8 drivers/usb/chipidea/core.c| 20 ++-- drivers/usb/chipidea/debug.c | 2 +- drivers/usb/chipidea/host.c| 4 ++-- drivers/usb/chipidea/otg_fsm.c | 4 ++-- drivers/usb/chipidea/udc.c | 4 ++-- include/linux/usb/chipidea.h | 2 +- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 9563cb56d564..b2caa1772712 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -161,7 +161,7 @@ struct hw_bank { * @test_mode: the selected test mode * @platdata: platform specific information supplied by parent device * @vbus_active: is VBUS active - * @transceiver: pointer to USB PHY, if any + * @usb_phy: pointer to USB PHY, if any * @hcd: pointer to usb_hcd for ehci host driver * @debugfs: root dentry for this controller in debugfs * @id_event: indicates there is an id event, and handled at ci_otg_work @@ -201,7 +201,7 @@ struct ci_hdrc { struct ci_hdrc_platform_data*platdata; int vbus_active; - struct usb_phy *transceiver; + struct usb_phy *usb_phy; struct usb_hcd *hcd; struct dentry *debugfs; boolid_event; diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 65444b02bd68..3aa3f62e079c 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -139,7 +139,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) goto err_clk; } - pdata.phy = data-phy; + pdata.usb_phy = data-phy; if (imx_platform_flag-flags CI_HDRC_IMX_IMX28_WRITE_FIX) pdata.flags |= CI_HDRC_IMX28_WRITE_FIX; diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index d72b9d2de2c5..94cd7c3e12a3 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -31,13 +31,13 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) case CI_HDRC_CONTROLLER_STOPPED_EVENT: dev_dbg(dev, CI_HDRC_CONTROLLER_STOPPED_EVENT received\n); /* -* Put the transceiver in non-driving mode. Otherwise host +* Put the phy in non-driving mode. Otherwise host * may not detect soft-disconnection. */ - val = usb_phy_io_read(ci-transceiver, ULPI_FUNC_CTRL); + val = usb_phy_io_read(ci-usb_phy, ULPI_FUNC_CTRL); val = ~ULPI_FUNC_CTRL_OPMODE_MASK; val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - usb_phy_io_write(ci-transceiver, val, ULPI_FUNC_CTRL); + usb_phy_io_write(ci-usb_phy, val, ULPI_FUNC_CTRL); break; default: dev_dbg(dev, unknown ci_hdrc event\n); @@ -71,7 +71,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev) if (IS_ERR(phy)) return PTR_ERR(phy); - ci_hdrc_msm_platdata.phy = phy; + ci_hdrc_msm_platdata.usb_phy = phy; plat_ci = ci_hdrc_add_device(pdev-dev, pdev-resource, pdev-num_resources, diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 619d13e29995..a8cd35fd8175 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -306,7 +306,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci) case USBPHY_INTERFACE_MODE_UTMI: case USBPHY_INTERFACE_MODE_UTMIW: case USBPHY_INTERFACE_MODE_HSIC: - ret = usb_phy_init(ci-transceiver); + ret = usb_phy_init(ci-usb_phy); if (ret) return ret; hw_phymode_configure(ci); @@ -314,12 +314,12 @@ static int ci_usb_phy_init(struct ci_hdrc *ci) case USBPHY_INTERFACE_MODE_ULPI: case USBPHY_INTERFACE_MODE_SERIAL: hw_phymode_configure(ci); - ret = usb_phy_init(ci-transceiver); + ret = usb_phy_init(ci-usb_phy); if (ret) return ret; break; default: - ret = usb_phy_init(ci-transceiver); + ret =
[PATCH v3 0/9] usb: add support for the generic PHY framework
Hi all, This is an attempt to add more common USB code aware of the generic PHY framework, while keeping the compatibility for the USB PHY one. It does not add the full support, some USB PHY specific functions not being available currently in the generic PHY subsystem (e.g. usb_phy_set_power()). But it allows to use the generic PHY framework in other cases, and might help others to convert their USB PHY drivers. A little background: I submitted a series to support USB on Berlin SoCs[1]. One patch added a new PHY driver in drivers/usb/phy and Felipe asked it to be in the generic PHY framework instead[2]. This PHY being used by a ChipIdea driver, changes were needed in ChipIdea, OTG and HCD. This is done in 3 steps: 1. moving the OTG state from the USB PHY structure to the OTG one 2. renaming the field 'phy' to 'usb_phy' 3. adding a field for the generic framework PHY and dissociating its use from the USB PHY one Step 1 is in the first patch. Steps 2 and 3 are done for OTG, and ChipIdea subsystems in patches 2-3, 7 and 9. HCD generic PHY support was made by Sergei and Yoshihiro[1]. I added some modifications to make this support consistent with this series in patches 4-6. The usb_otg has been moved into the ci_hdrc structure in ChipIdea, in patch 8. I tested it by using the ChipIdea driver I introduced, both with an USB PHY and a PHY driver successfully. I also compiled a multi_v7 kernel (ARM), with every driver I could enable in the USB section. Patches can also be found at: git://git.free-electrons.com:users/antoine-tenart/linux.git usb-phy The series applies on top of Sergei and Yoshihiro generic PHY support in HCD[1]. Thanks a lot! Antoine Changes since v2: - rebased the series on top of v3.17-rc1 (and [1]) - moved phy_exit() after phy_power_on() - switched to devm_phy_get() to handle non DT cases - moved usb_otg into the ci_hdrc structure Changes since v1: - rebased the series on top of [1] (generic PHY support for HCD) - split s/phy/usb_phy/ renaming and generic PHY support in separate patches [1] https://www.mail-archive.com/linux-usb@vger.kernel.org/msg43471.html Antoine Ténart (9): usb: move the OTG state from the USB PHY to the OTG structure usb: rename phy to usb_phy in OTG usb: add support to the generic PHY framework in OTG usb: rename phy to usb_phy in HCD usb: rename gen_phy to phy in HCD usb: allow to supply the PHY in the drivers when using HCD usb: rename transceiver and phy to usb_phy in ChipIdea usb: chipidea: move usb_otg into struct ci_hdrc usb: chipidea: add support to the generic PHY framework in ChipIdea drivers/phy/phy-omap-usb2.c | 14 ++ drivers/usb/chipidea/ci.h | 8 +++- drivers/usb/chipidea/ci_hdrc_imx.c | 2 +- drivers/usb/chipidea/ci_hdrc_msm.c | 8 ++-- drivers/usb/chipidea/core.c | 71 ++- drivers/usb/chipidea/debug.c| 5 +- drivers/usb/chipidea/host.c | 13 ++--- drivers/usb/chipidea/otg_fsm.c | 29 +-- drivers/usb/chipidea/udc.c | 4 +- drivers/usb/common/usb-otg-fsm.c| 8 ++-- drivers/usb/core/hcd.c | 45 +- drivers/usb/core/hub.c | 8 ++-- drivers/usb/host/ehci-fsl.c | 16 +++ drivers/usb/host/ehci-hub.c | 2 +- drivers/usb/host/ehci-msm.c | 4 +- drivers/usb/host/ehci-tegra.c | 16 +++ drivers/usb/host/ohci-omap.c| 20 drivers/usb/musb/am35x.c| 28 +-- drivers/usb/musb/blackfin.c | 18 +++ drivers/usb/musb/da8xx.c| 28 +-- drivers/usb/musb/davinci.c | 18 +++ drivers/usb/musb/musb_core.c| 94 ++-- drivers/usb/musb/musb_dsps.c| 26 +- drivers/usb/musb/musb_gadget.c | 36 +++--- drivers/usb/musb/musb_host.c| 8 ++-- drivers/usb/musb/musb_virthub.c | 22 - drivers/usb/musb/omap2430.c | 30 ++-- drivers/usb/musb/tusb6010.c | 40 drivers/usb/musb/ux500.c| 10 ++-- drivers/usb/phy/phy-ab8500-usb.c| 16 +++ drivers/usb/phy/phy-fsl-usb.c | 23 - drivers/usb/phy/phy-generic.c | 6 +-- drivers/usb/phy/phy-gpio-vbus-usb.c | 14 +++--- drivers/usb/phy/phy-isp1301-omap.c | 10 ++-- drivers/usb/phy/phy-msm-usb.c | 95 +++-- drivers/usb/phy/phy-mv-usb.c| 50 +-- drivers/usb/phy/phy-samsung-usb2.c | 2 +- drivers/usb/phy/phy-tahvo.c | 8 ++-- drivers/usb/phy/phy-ulpi.c | 6 +-- include/linux/usb/chipidea.h| 4 +- include/linux/usb/hcd.h | 6 ++- include/linux/usb/otg.h | 7 ++- include/linux/usb/phy.h | 1 - 43 files changed, 467 insertions(+), 412 deletions(-) -- 1.9.1 -- To unsubscribe from
[PATCH v3 6/9] usb: allow to supply the PHY in the drivers when using HCD
This patch modify the generic code handling PHYs to allow them to be supplied from the drivers. This adds checks to ensure no PHY was already there when looking for one in the generic code. This also makes sure we do not modify its state in the generic HCD functions, it was provided by the driver. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu --- drivers/usb/core/hcd.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6619239baf6d..dc0e46e5e618 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2646,7 +2646,7 @@ int usb_add_hcd(struct usb_hcd *hcd, } } - if (IS_ENABLED(CONFIG_GENERIC_PHY)) { + if (IS_ENABLED(CONFIG_GENERIC_PHY) !hcd-phy) { struct phy *phy = phy_get(hcd-self.controller, usb); if (IS_ERR(phy)) { @@ -2666,6 +2666,7 @@ int usb_add_hcd(struct usb_hcd *hcd, goto err_phy; } hcd-phy = phy; + hcd-remove_phy = 1; } } @@ -2812,7 +2813,7 @@ err_allocate_root_hub: err_register_bus: hcd_buffer_destroy(hcd); err_create_buf: - if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-phy) { + if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-remove_phy hcd-phy) { phy_power_off(hcd-phy); phy_exit(hcd-phy); phy_put(hcd-phy); @@ -2896,7 +2897,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_deregister_bus(hcd-self); hcd_buffer_destroy(hcd); - if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-phy) { + if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-remove_phy hcd-phy) { phy_power_off(hcd-phy); phy_exit(hcd-phy); phy_put(hcd-phy); -- 1.9.1 -- 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 v3 1/9] usb: move the OTG state from the USB PHY to the OTG structure
Before using the PHY framework instead of the USB PHY one, we need to move the OTG state into another place, since it won't be available when USB PHY isn't used. This patch moves the OTG state into the OTG structure, and makes all the needed modifications in the drivers using the OTG state. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com Acked-by: Peter Chen peter.c...@freescale.com --- drivers/phy/phy-omap-usb2.c | 8 +--- drivers/usb/chipidea/debug.c| 3 +- drivers/usb/chipidea/otg_fsm.c | 12 ++--- drivers/usb/common/usb-otg-fsm.c| 8 ++-- drivers/usb/host/ohci-omap.c| 2 +- drivers/usb/musb/am35x.c| 28 +-- drivers/usb/musb/blackfin.c | 18 +++ drivers/usb/musb/da8xx.c| 28 +-- drivers/usb/musb/davinci.c | 18 +++ drivers/usb/musb/musb_core.c| 94 ++--- drivers/usb/musb/musb_dsps.c| 26 +- drivers/usb/musb/musb_gadget.c | 36 +++--- drivers/usb/musb/musb_host.c| 8 ++-- drivers/usb/musb/musb_virthub.c | 22 - drivers/usb/musb/omap2430.c | 30 ++-- drivers/usb/musb/tusb6010.c | 40 drivers/usb/musb/ux500.c| 10 ++-- drivers/usb/phy/phy-ab8500-usb.c| 10 ++-- drivers/usb/phy/phy-fsl-usb.c | 10 ++-- drivers/usb/phy/phy-generic.c | 4 +- drivers/usb/phy/phy-gpio-vbus-usb.c | 10 ++-- drivers/usb/phy/phy-msm-usb.c | 34 +++--- drivers/usb/phy/phy-mv-usb.c| 46 +- include/linux/usb/otg.h | 2 + include/linux/usb/phy.h | 1 - 25 files changed, 252 insertions(+), 256 deletions(-) diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 93d78359246c..3bb54e55c762 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -80,11 +80,9 @@ static int omap_usb_start_srp(struct usb_otg *otg) static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct usb_phy *phy = otg-phy; - otg-host = host; if (!host) - phy-state = OTG_STATE_UNDEFINED; + otg-state = OTG_STATE_UNDEFINED; return 0; } @@ -92,11 +90,9 @@ static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) static int omap_usb_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct usb_phy *phy = otg-phy; - otg-gadget = gadget; if (!gadget) - phy-state = OTG_STATE_UNDEFINED; + otg-state = OTG_STATE_UNDEFINED; return 0; } diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 795d6538d630..787671d40379 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -219,8 +219,7 @@ static int ci_otg_show(struct seq_file *s, void *unused) fsm = ci-fsm; /* -- State - */ - seq_printf(s, OTG state: %s\n\n, - usb_otg_state_string(ci-transceiver-state)); + usb_otg_state_string(ci-transceiver-otg.state)); /* -- State Machine Variables - */ seq_printf(s, a_bus_drop: %d\n, fsm-a_bus_drop); diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index caaabc58021e..8cb2508a6b71 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -328,7 +328,7 @@ static void b_ssend_srp_tmout_func(void *ptr, unsigned long indicator) set_tmout(ci, indicator); /* only vbus fall below B_sess_vld in b_idle state */ - if (ci-transceiver-state == OTG_STATE_B_IDLE) + if (ci-fsm.otg-state == OTG_STATE_B_IDLE) ci_otg_queue_work(ci); } @@ -582,11 +582,11 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) * when there is no gadget class driver */ if (ci-fsm.id !(ci-driver) - ci-transceiver-state OTG_STATE_A_IDLE) + ci-fsm.otg-state OTG_STATE_A_IDLE) return 0; if (otg_statemachine(ci-fsm)) { - if (ci-transceiver-state == OTG_STATE_A_IDLE) { + if (ci-fsm.otg-state == OTG_STATE_A_IDLE) { /* * Further state change for cases: * a_idle to b_idle; or @@ -600,7 +600,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) ci_otg_queue_work(ci); if (ci-id_event) ci-id_event = false; - } else if (ci-transceiver-state == OTG_STATE_B_IDLE) { + } else if (ci-fsm.otg-state == OTG_STATE_B_IDLE) { if (ci-fsm.b_sess_vld) { ci-fsm.power_up = 0; /* @@ -627,7 +627,7 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci) otg_bsess_vld = hw_read_otgsc(ci,
Re: [PATCH v2] drivers: usb: gadget: fusb300_udc.h: Fix typo in include guard
Hi, On Fri, Aug 22, 2014 at 05:21:12PM +0200, Rasmus Villemoes wrote: Felipe Balbi ba...@ti.com writes: On Fri, Aug 22, 2014 at 04:44:33PM +0200, Rasmus Villemoes wrote: Clearly this was meant to be an include guard, but a trailing underscore was missing. It has been this way since the file was introduced in 0fe6f1d1 (usb: udc: add Faraday fusb300 driver). right here you need to have: Fixes: 0fe6f1d1 (usb: udc: add Faraday fusb300 driver) Cc: sta...@vger.kernel.org Really? I can't see that it satisfies the Documentation/stable_kernel_rules.txt. There's no chance of build error, since the file is only included directly from a single .c file. As you can see on LKML I've sent a few handfuls of similar patches all over the tree; IMHO none of them qualify for stable. If you insist, I'll add the Fixes and Cc tags. it's a bug fix nevertheless. -- balbi signature.asc Description: Digital signature
Re: [PATCH] usb: phy: twl4030-usb: Fix lost interrupts after ID pin goes down
Hi, * Grazvydas Ignotas nota...@gmail.com [140822 06:21]: Hi, On Thu, Aug 21, 2014 at 7:48 PM, Tony Lindgren t...@atomide.com wrote: Commit 249751f22380 (usb: phy: twl4030-usb: poll for ID disconnect) added twl4030_id_workaround_work() to deal with lost interrupts after ID pin goes down. However, this currently only works for the insertion. The PHY interrupts are not working after disconnecting an USB-A device from the board, and the deeper idle states for omap are blocked as the USB controller stays busy. The issue can be solved by calling delayed work from twl4030_usb_irq() when ID pin is down and the PHY is not asleep like we already do in twl4030_id_workaround_work(). The way it is supposed to work is that after plugging in the cable twl4030_phy_power_on() sees ID_GROUND and kicks off id_workaround_work every second. When cable is unplugged, twl4030_id_workaround_work() sees changes in STS_HW_CONDITIONS register and triggers events. Doesn't that work for you, why do you need to trigger it from twl4030_usb_irq() too? Not any longer because we are currently call schedule_delayed_work() only from twl4030_phy_power_on(). That function got renamed, it used to be twl4030_phy_resume() before the generic phy framework changes. So looking at the v3.12 code, you're right, it seems to behave as you describe. That however changed with the generic phy framework changes for v3.13, and looks like the correct breaking commit is f1ddc24c9e33 (usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops) instead. So it won't currently work after unplugging and replugging as all connect and disconnect interrupts go unnoticed after ID_GROUND. So we need to poll whenever ID_GROUND and PHY is not asleep. But as both twl4030_usb_irq() and twl4030_id_workaround_work() already do pretty much the same thing, let's call twl4030_usb_irq() from twl4030_id_workaround_work() instead of adding some more duplicate code. The difference is the sysfs_notify() call, so now every time id_workaround_work triggers (around once per second while the cable is plugged) userspace will now get useless uevent. Haven't actually checked if it really happens though, so I might be wrong. Good point. That can be avoided by doing calling it only if we have an irq and not from delayed work. Updated patch below, I've updated the description for the proper regression causing commit and added a check when to call the sysfs_notify. Kept Felipe's ack, hope that works. Regards, Tony 8 - From: Tony Lindgren t...@atomide.com Date: Thu, 21 Aug 2014 08:59:43 -0700 Subject: [PATCH] usb: phy: twl4030-usb: Fix lost interrupts after ID pin goes down Commit 249751f22380 (usb: phy: twl4030-usb: poll for ID disconnect) added twl4030_id_workaround_work() to deal with lost interrupts after ID pin goes down. Looks like commit f1ddc24c9e33 (usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops) changed things around for the generic phy framework, and delayed work no longer got called except initially during boot. The PHY connect and disconnect interrupts for twl4030-usb are not working after disconnecting a USB-A cable from the board, and the deeper idle states for omap are blocked as the USB controller stays busy. The issue can be solved by calling delayed work from twl4030_usb_irq() when ID pin is down and the PHY is not asleep like we already do in twl4030_id_workaround_work(). But as both twl4030_usb_irq() and twl4030_id_workaround_work() already do pretty much the same thing, let's call twl4030_usb_irq() from twl4030_id_workaround_work() instead of adding some more duplicate code. We also must call sysfs_notify() only when we have an interrupt and not from the delayed work as notified by Grazvydas Ignotas nota...@gmail.com. Fixes: f1ddc24c9e33 (usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops) Cc: sta...@vger.kernel.org # v3.13+ Acked-by: Felipe Balbi ba...@ti.com Signed-off-by: Tony Lindgren t...@atomide.com --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -560,7 +560,15 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) */ omap_musb_mailbox(status); } - sysfs_notify(twl-dev-kobj, NULL, vbus); + + /* don't schedule during sleep - irq works right then */ + if (status == OMAP_MUSB_ID_GROUND !twl-asleep) { + cancel_delayed_work(twl-id_workaround_work); + schedule_delayed_work(twl-id_workaround_work, HZ); + } + + if (irq) + sysfs_notify(twl-dev-kobj, NULL, vbus); return IRQ_HANDLED; } @@ -569,29 +577,8 @@ static void twl4030_id_workaround_work(struct work_struct *work) { struct twl4030_usb *twl = container_of(work, struct twl4030_usb, id_workaround_work.work); - enum omap_musb_vbus_id_status status; - bool status_changed = false; - - status =
Re: [PATCH v3 6/9] usb: allow to supply the PHY in the drivers when using HCD
Hello. On 08/22/2014 07:50 PM, Antoine Ténart wrote: This patch modify the generic code handling PHYs to allow them to be supplied from the drivers. This adds checks to ensure no PHY was already there when looking for one in the generic code. This also makes sure we do not modify its state in the generic HCD functions, it was provided by the driver. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu --- drivers/usb/core/hcd.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6619239baf6d..dc0e46e5e618 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2646,7 +2646,7 @@ int usb_add_hcd(struct usb_hcd *hcd, } } - if (IS_ENABLED(CONFIG_GENERIC_PHY)) { + if (IS_ENABLED(CONFIG_GENERIC_PHY) !hcd-phy) { struct phy *phy = phy_get(hcd-self.controller, usb); if (IS_ERR(phy)) { @@ -2666,6 +2666,7 @@ int usb_add_hcd(struct usb_hcd *hcd, goto err_phy; } hcd-phy = phy; + hcd-remove_phy = 1; } } @@ -2812,7 +2813,7 @@ err_allocate_root_hub: err_register_bus: hcd_buffer_destroy(hcd); err_create_buf: - if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-phy) { + if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-remove_phy hcd-phy) { The 'hcd-phy' check seems redundant now. phy_power_off(hcd-phy); phy_exit(hcd-phy); phy_put(hcd-phy); @@ -2896,7 +2897,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_deregister_bus(hcd-self); hcd_buffer_destroy(hcd); - if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-phy) { + if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-remove_phy hcd-phy) { Here as well. [...] WBR, Sergei -- 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 v2 5/5] usb: phy: samsung: remove old common USB PHY code
drivers/usb/phy/phy-samsung-usb[2,3] drivers got replaced by drivers/phy/phy-samsung-usb[2,3] ones and the old common Samsung USB PHY code is no longer used. Signed-off-by: Bartlomiej Zolnierkiewicz b.zolnier...@samsung.com Acked-by: Kyungmin Park kyungmin.p...@samsung.com Reviewed-by: Vivek Gautam gautam.vi...@samsung.com Reviewed-by: Jingoo Han jg1@samsung.com Acked-by: Kishon Vijay Abraham I kis...@ti.com Cc: Kamil Debski k.deb...@samsung.com --- drivers/usb/phy/Kconfig | 7 - drivers/usb/phy/Makefile | 1 - drivers/usb/phy/phy-samsung-usb.c| 241 -- drivers/usb/phy/phy-samsung-usb.h| 349 --- include/linux/platform_data/samsung-usbphy.h | 27 --- 5 files changed, 625 deletions(-) delete mode 100644 drivers/usb/phy/phy-samsung-usb.c delete mode 100644 drivers/usb/phy/phy-samsung-usb.h delete mode 100644 include/linux/platform_data/samsung-usbphy.h diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 0cd1f44..7012a82 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -71,13 +71,6 @@ config AM335X_PHY_USB This driver provides PHY support for that phy which part for the AM335x SoC. -config SAMSUNG_USBPHY - tristate - help - Enable this to support Samsung USB phy helper driver for Samsung SoCs. - This driver provides common interface to interact, for Samsung USB 2.0 PHY - driver and later for Samsung USB 3.0 PHY driver. - config TWL6030_USB tristate TWL6030 USB Transceiver Driver depends on TWL4030_CORE OMAP_USB2 USB_MUSB_OMAP2PLUS diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 75f2bba..1e38a6f 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o -obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o obj-$(CONFIG_USB_GPIO_VBUS)+= phy-gpio-vbus-usb.o diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c deleted file mode 100644 index ac025ca..000 --- a/drivers/usb/phy/phy-samsung-usb.c +++ /dev/null @@ -1,241 +0,0 @@ -/* linux/drivers/usb/phy/phy-samsung-usb.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Author: Praveen Paneri p.pan...@samsung.com - * - * Samsung USB-PHY helper driver with common function calls; - * interacts with Samsung USB 2.0 PHY controller driver and later - * with Samsung USB 3.0 PHY driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include linux/module.h -#include linux/platform_device.h -#include linux/clk.h -#include linux/device.h -#include linux/err.h -#include linux/io.h -#include linux/of.h -#include linux/of_address.h -#include linux/usb/samsung_usb_phy.h - -#include phy-samsung-usb.h - -int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy) -{ - struct device_node *usbphy_sys; - - /* Getting node for system controller interface for usb-phy */ - usbphy_sys = of_get_child_by_name(sphy-dev-of_node, usbphy-sys); - if (!usbphy_sys) { - dev_err(sphy-dev, No sys-controller interface for usb-phy\n); - return -ENODEV; - } - - sphy-pmuregs = of_iomap(usbphy_sys, 0); - - if (sphy-pmuregs == NULL) { - dev_err(sphy-dev, Can't get usb-phy pmu control register\n); - goto err0; - } - - sphy-sysreg = of_iomap(usbphy_sys, 1); - - /* -* Not returning error code here, since this situation is not fatal. -* Few SoCs may not have this switch available -*/ - if (sphy-sysreg == NULL) - dev_warn(sphy-dev, Can't get usb-phy sysreg cfg register\n); - - of_node_put(usbphy_sys); - - return 0; - -err0: - of_node_put(usbphy_sys); - return -ENXIO; -} -EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt); - -/* - * Set isolation here for phy. - * Here 'on = true' would mean USB PHY block is isolated, hence - * de-activated and vice-versa. - */ -void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, bool on) -{ - void __iomem *reg = NULL; - u32 reg_val; -
[PATCH v2 3/5] usb: phy: samsung: remove old USB 2.0 PHY driver
drivers/usb/phy/phy-samsung-usb2 driver got replaced by drivers/phy/phy-samsung-usb2 one and is no longer used. Signed-off-by: Bartlomiej Zolnierkiewicz b.zolnier...@samsung.com Acked-by: Kyungmin Park kyungmin.p...@samsung.com Reviewed-by: Vivek Gautam gautam.vi...@samsung.com Reviewed-by: Jingoo Han jg1@samsung.com Acked-by: Kishon Vijay Abraham I kis...@ti.com Cc: Kamil Debski k.deb...@samsung.com --- drivers/usb/phy/Kconfig| 8 - drivers/usb/phy/Makefile | 1 - drivers/usb/phy/phy-samsung-usb2.c | 541 - 3 files changed, 550 deletions(-) delete mode 100644 drivers/usb/phy/phy-samsung-usb2.c diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e253fa0..452e252 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -78,14 +78,6 @@ config SAMSUNG_USBPHY This driver provides common interface to interact, for Samsung USB 2.0 PHY driver and later for Samsung USB 3.0 PHY driver. -config SAMSUNG_USB2PHY - tristate Samsung USB 2.0 PHY controller Driver - select SAMSUNG_USBPHY - select USB_PHY - help - Enable this to support Samsung USB 2.0 (High Speed) PHY controller - driver for Samsung SoCs. - config SAMSUNG_USB3PHY tristate Samsung USB 3.0 PHY controller Driver select SAMSUNG_USBPHY diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 24a9133..c651005 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o -obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c deleted file mode 100644 index b3ba866..000 --- a/drivers/usb/phy/phy-samsung-usb2.c +++ /dev/null @@ -1,541 +0,0 @@ -/* linux/drivers/usb/phy/phy-samsung-usb2.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Author: Praveen Paneri p.pan...@samsung.com - * - * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and - * OHCI-EXYNOS controllers. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include linux/module.h -#include linux/platform_device.h -#include linux/clk.h -#include linux/delay.h -#include linux/device.h -#include linux/err.h -#include linux/io.h -#include linux/of.h -#include linux/usb/otg.h -#include linux/usb/samsung_usb_phy.h -#include linux/platform_data/samsung-usbphy.h - -#include phy-samsung-usb.h - -static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) -{ - if (!otg) - return -ENODEV; - - if (!otg-host) - otg-host = host; - - return 0; -} - -static bool exynos5_phyhost_is_on(void __iomem *regs) -{ - u32 reg; - - reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - - return !(reg HOST_CTRL0_SIDDQ); -} - -static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy) -{ - void __iomem *regs = sphy-regs; - u32 phyclk = sphy-ref_clk_freq; - u32 phyhost; - u32 phyotg; - u32 phyhsic; - u32 ehcictrl; - u32 ohcictrl; - - /* -* phy_usage helps in keeping usage count for phy -* so that the first consumer enabling the phy is also -* the last consumer to disable it. -*/ - - atomic_inc(sphy-phy_usage); - - if (exynos5_phyhost_is_on(regs)) { - dev_info(sphy-dev, Already power on PHY\n); - return; - } - - /* Host configuration */ - phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - - /* phy reference clock configuration */ - phyhost = ~HOST_CTRL0_FSEL_MASK; - phyhost |= HOST_CTRL0_FSEL(phyclk); - - /* host phy reset */ - phyhost = ~(HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL | - HOST_CTRL0_SIDDQ | - /* Enable normal mode of operation */ - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP); - - /* Link reset */ - phyhost |= (HOST_CTRL0_LINKSWRST | -
[PATCH v2 0/5] usb: phy: samsung: remove old USB PHY code
Hi, This patch series removes the old Samsung USB PHY drivers that got replaced by the new ones using the generic PHY layer. Depends on: - v3.17-rc1 branch of Linus' kernel Changes since v1 (https://lkml.org/lkml/2014/8/14/241): - rebased on v3.17-rc1 kernel - added Acked-by-s from Kishon Vijay Abraham I - added Reviewed-by-s from Vivek Gautam and Jingoo Han Best regards, -- Bartlomiej Zolnierkiewicz Samsung RD Institute Poland Samsung Electronics Bartlomiej Zolnierkiewicz (5): ARM: dts: remove old USB2 PHY node hook for Arndale ARM: dts: remove old USB2 PHY node for Exynos5250 usb: phy: samsung: remove old USB 2.0 PHY driver usb: phy: samsung: remove old USB 3.0 PHY driver usb: phy: samsung: remove old common USB PHY code arch/arm/boot/dts/exynos5250-arndale.dts | 4 - arch/arm/boot/dts/exynos5250.dtsi| 15 - drivers/usb/phy/Kconfig | 23 -- drivers/usb/phy/Makefile | 3 - drivers/usb/phy/phy-samsung-usb.c| 241 drivers/usb/phy/phy-samsung-usb.h| 349 - drivers/usb/phy/phy-samsung-usb2.c | 541 --- drivers/usb/phy/phy-samsung-usb3.c | 350 - include/linux/platform_data/samsung-usbphy.h | 27 -- 9 files changed, 1553 deletions(-) delete mode 100644 drivers/usb/phy/phy-samsung-usb.c delete mode 100644 drivers/usb/phy/phy-samsung-usb.h delete mode 100644 drivers/usb/phy/phy-samsung-usb2.c delete mode 100644 drivers/usb/phy/phy-samsung-usb3.c delete mode 100644 include/linux/platform_data/samsung-usbphy.h -- 1.8.2.3 -- 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
Re: [PATCH v3 6/9] usb: allow to supply the PHY in the drivers when using HCD
On 08/22/2014 08:53 PM, Sergei Shtylyov wrote: This patch modify the generic code handling PHYs to allow them to be supplied from the drivers. This adds checks to ensure no PHY was already there when looking for one in the generic code. This also makes sure we do not modify its state in the generic HCD functions, it was provided by the driver. Signed-off-by: Antoine Ténart antoine.ten...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu --- drivers/usb/core/hcd.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6619239baf6d..dc0e46e5e618 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c [...] @@ -2666,6 +2666,7 @@ int usb_add_hcd(struct usb_hcd *hcd, goto err_phy; } hcd-phy = phy; +hcd-remove_phy = 1; } } @@ -2812,7 +2813,7 @@ err_allocate_root_hub: err_register_bus: hcd_buffer_destroy(hcd); err_create_buf: -if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-phy) { +if (IS_ENABLED(CONFIG_GENERIC_PHY) hcd-remove_phy hcd-phy) { The 'hcd-phy' check seems redundant now. Oh, sorry, I forgot about USB PHY which also sets this flag. WBR, Segei -- 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
Re: [RFC 1/2] USB: OTG: Hold wakeupsource when VBUS present
Hi, On Fri, Aug 22, 2014 at 03:19:32PM +0530, Kiran Kumar Raparthy wrote: From: Todd Poynor toddpoy...@google.com USB: OTG: Hold wakeupsource when VBUS present Enabled by default, can disable with: I would turn this around and make it disabled by default so that it doesn't change behavior for distro kernels. echo N /sys/module/otg_wakeupsource/parameters/enabled This is one of the number of patches from the Android AOSP common.git tree, which is used on almost all Android devices. so I wanted to submit it for review to see if it should go upstream. you never explain why this is needed and you have also added some information to commit log which shouldn't be here. Cc: Felipe Balbi ba...@ti.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: linux-ker...@vger.kernel.org Cc: linux-usb@vger.kernel.org Cc: Android Kernel Team kernel-t...@android.com Cc: John Stultz john.stu...@linaro.org Cc: Arve Hj�nnev�g a...@android.com Cc: Benoit Goby ben...@android.com Signed-off-by: Todd Poynor toddpoy...@google.com Signed-off-by: Kiran Raparthy kiran.ku...@linaro.org [kiran: Added context to commit message Included build fix from Benoit Goby and Arve Arve Hj�nnev�g Removed lock-held field in driver as this mechanism is provided in wakeup.c wakelock(wl) terminology replaced with wakeup_source(ws) sys entry(module param) field modified to otg_wakeupsource __pm_stay_awake and __pm_relax called directly from the main code instead of calling them via otgws_grab,otgws_drop] --- drivers/usb/phy/Kconfig| 8 ++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/otg-wakeupsource.c | 171 + 3 files changed, 180 insertions(+) create mode 100644 drivers/usb/phy/otg-wakeupsource.c diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e253fa0..9c747b2 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -6,6 +6,14 @@ menu USB Physical Layer drivers config USB_PHY def_bool n +config USB_OTG_WAKEUPSOURCE + bool Hold a wakeupsource when USB connected + depends on PM_SLEEP + select USB_PHY + help + Select this to automatically hold a wakeupsource when USB is + connected, preventing suspend. + # # USB Transceiver Drivers # diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 24a9133..ca2fbaf 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_USB_PHY)+= phy.o obj-$(CONFIG_OF) += of.o +obj-$(CONFIG_USB_OTG_WAKEUPSOURCE) += otg-wakeupsource.o # transceiver drivers, keep the list sorted diff --git a/drivers/usb/phy/otg-wakeupsource.c b/drivers/usb/phy/otg-wakeupsource.c new file mode 100644 index 000..fa44e11 --- /dev/null +++ b/drivers/usb/phy/otg-wakeupsource.c @@ -0,0 +1,171 @@ +/* + * otg-wakeupsource.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include linux/kernel.h +#include linux/device.h +#include linux/module.h +#include linux/notifier.h +#include linux/pm_wakeup.h +#include linux/spinlock.h +#include linux/usb/otg.h + +static bool enabled = true; +static struct usb_phy *otgws_xceiv; +static struct notifier_block otgws_nb; this aches to be a per-PHY thing rather forcing it to be a one-for-all. We have systems with more than one port and the PHY framework is also starting to be used by the host side stack. +static DEFINE_SPINLOCK(otgws_spinlock); + +/* + * Only one lock, but since these 2 fields are associated with each other... + */ one line comment + +struct otgws_lock { + char name[40]; + struct wakeup_source wsource; +}; + +/* + * VBUS present lock. + */ one line comment +static struct otgws_lock vbus_lock; should be per-PHY -- balbi signature.asc Description: Digital signature
[RFC PATCH 01/20] xhci: cleanup remaining cycle bit toggles via ternary conditional
These can simply be toggled via xor. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c | 12 ++-- 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 749fc68eb5c1..0efbbf0b6233 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -237,9 +237,9 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, next-link.control ^= cpu_to_le32(TRB_CYCLE); /* Toggle the cycle bit after the last ring segment. */ - if (last_trb_on_last_seg(xhci, ring, ring-enq_seg, next)) { - ring-cycle_state = (ring-cycle_state ? 0 : 1); - } + if (last_trb_on_last_seg(xhci, ring, ring-enq_seg, + next)) + ring-cycle_state ^= 1; } ring-enq_seg = ring-enq_seg-next; ring-enqueue = ring-enq_seg-trbs; @@ -2875,9 +2875,9 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, next-link.control ^= cpu_to_le32(TRB_CYCLE); /* Toggle the cycle bit after the last ring segment. */ - if (last_trb_on_last_seg(xhci, ring, ring-enq_seg, next)) { - ring-cycle_state = (ring-cycle_state ? 0 : 1); - } + if (last_trb_on_last_seg(xhci, ring, ring-enq_seg, + next)) + ring-cycle_state ^= 1; ring-enq_seg = ring-enq_seg-next; ring-enqueue = ring-enq_seg-trbs; next = ring-enqueue; -- 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
[RFC PATCH 02/20] xhci: remove invalid cast of xhci to a usb_device in xhci_log_ctx trace
An xhci controller device is a pci or a platform device, never a usb_device. Cc: Xenia Ragiadakou burzalod...@gmail.com Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-trace.h |5 - 1 files changed, 0 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index dde3959b7a33..fe7ee98d2a2b 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -77,20 +77,15 @@ DECLARE_EVENT_CLASS(xhci_log_ctx, __field(dma_addr_t, ctx_dma) __field(u8 *, ctx_va) __field(unsigned, ctx_ep_num) - __field(int, slot_id) __dynamic_array(u32, ctx_data, ((HCC_64BYTE_CONTEXT(xhci-hcc_params) + 1) * 8) * ((ctx-type == XHCI_CTX_TYPE_INPUT) + ep_num + 1)) ), TP_fast_assign( - struct usb_device *udev; - - udev = to_usb_device(xhci_to_hcd(xhci)-self.controller); __entry-ctx_64 = HCC_64BYTE_CONTEXT(xhci-hcc_params); __entry-ctx_type = ctx-type; __entry-ctx_dma = ctx-dma; __entry-ctx_va = ctx-bytes; - __entry-slot_id = udev-slot_id; __entry-ctx_ep_num = ep_num; memcpy(__get_dynamic_array(ctx_data), ctx-bytes, ((HCC_64BYTE_CONTEXT(xhci-hcc_params) + 1) * 32) * -- 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
Re: [PATCH 0/5] usb: phy: samsung: remove old USB PHY code
Hi, On Wednesday, August 20, 2014 01:12:44 PM Felipe Balbi wrote: Hi, On Thu, Aug 14, 2014 at 04:25:22PM +0200, Bartlomiej Zolnierkiewicz wrote: Hi, This patch series removes the old Samsung USB PHY drivers that got replaced by the new ones using the generic PHY layer. Depends on: - next-20140813 branch of linux-next kernel this thread seems to have died, what do I need to do with these patches? Please apply them (patches #3, #4 and #5). Patches #1 and #2 should be applied (or Acked-by) by Kukjin Kim. Are we deleting the phy drivers or not ? Yes, we are deleting them. It has been agreed on by Kishon and Vivek. Please rebase on v3.17-rc1 and resend with all Acks in place. Done: https://lkml.org/lkml/2014/8/22/446 Please note that if you want to apply it to current -next kernel (next-20140822) then you need to resolve conflict between patch #5/5 (usb: phy: samsung: remove old common USB PHY code) and commit bbc66e140bab (usb: phy: samsung: Fix wrong bit mask for PHYPARAM1_PCS_TXDEEMPH) by simply removing the new version of drivers/usb/phy/phy-samsung-usb.h file. Best regards, -- Bartlomiej Zolnierkiewicz Samsung RD Institute Poland Samsung Electronics -- 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
[RFC PATCH 04/20] xhci: increase trb segment size, kill -segment_pool
TRB segments are allocated relatively infrequently and would benefit from being larger (to reduce probability of overrunning a segment in a TD fragment). We already burn a page satisfying a single segment allocation, so there's little reason to not allocate in page-sized chunks in the first instance. In support of freeing segments from irq context struct xhci_segment grows a -dev and -ew field (exectue_work). As a result there is no longer a need to pass a 'xhci' parameter down to xhci_free_segment(). Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-mem.c | 70 --- drivers/usb/host/xhci.c |2 + drivers/usb/host/xhci.h | 19 +++- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fcae0ce47daa..1d05dc9e1928 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -40,14 +40,15 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, unsigned int cycle_state, gfp_t flags) { struct xhci_segment *seg; - dma_addr_t dma; int i; seg = kzalloc(sizeof *seg, flags); if (!seg) return NULL; - seg-trbs = dma_pool_alloc(xhci-segment_pool, flags, dma); + seg-dev = xhci_to_dev(xhci); + seg-trbs = dma_alloc_coherent(seg-dev, TRB_SEGMENT_SIZE, + seg-dma, flags); if (!seg-trbs) { kfree(seg); return NULL; @@ -59,33 +60,43 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, for (i = 0; i TRBS_PER_SEGMENT; i++) seg-trbs[i].link.control |= cpu_to_le32(TRB_CYCLE); } - seg-dma = dma; seg-next = NULL; return seg; } -static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) +static void xhci_segment_free_work(struct work_struct *w) { + struct xhci_segment *seg = container_of(w, typeof(*seg), work); + if (seg-trbs) { - dma_pool_free(xhci-segment_pool, seg-trbs, seg-dma); + dma_free_coherent(seg-dev, TRB_SEGMENT_SIZE, seg-trbs, + seg-dma); seg-trbs = NULL; } + put_device(seg-dev); kfree(seg); } -static void xhci_free_segments_for_ring(struct xhci_hcd *xhci, - struct xhci_segment *first) +static void xhci_segment_free(struct xhci_segment *seg) +{ + INIT_WORK(seg-work, xhci_segment_free_work); + get_device(seg-dev); + schedule_work(seg-work); +} + +static void xhci_free_segments_for_ring(struct xhci_segment *first) { struct xhci_segment *seg; seg = first-next; while (seg != first) { struct xhci_segment *next = seg-next; - xhci_segment_free(xhci, seg); + + xhci_segment_free(seg); seg = next; } - xhci_segment_free(xhci, first); + xhci_segment_free(first); } /* @@ -273,7 +284,7 @@ static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags) } /* XXX: Do we need the hcd structure in all these functions? */ -void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) +void xhci_ring_free(struct xhci_ring *ring) { if (!ring) return; @@ -281,7 +292,7 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) if (ring-first_seg) { if (ring-type == TYPE_STREAM) xhci_remove_stream_mapping(ring); - xhci_free_segments_for_ring(xhci, ring-first_seg); + xhci_free_segments_for_ring(ring-first_seg); } kfree(ring); @@ -336,7 +347,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, prev = *first; while (prev) { next = prev-next; - xhci_segment_free(xhci, prev); + xhci_segment_free(prev); prev = next; } return -ENOMEM; @@ -411,7 +422,7 @@ void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci, virt_dev-num_rings_cached, (virt_dev-num_rings_cached 1) ? s : ); } else { - xhci_ring_free(xhci, virt_dev-eps[ep_index].ring); + xhci_ring_free(virt_dev-eps[ep_index].ring); xhci_dbg(xhci, Ring cache full (%d rings), freeing ring\n, virt_dev-num_rings_cached); @@ -482,7 +493,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, struct xhci_segment *next;
[RFC PATCH 05/20] xhci: prepare for mid-segment link-trbs
Break the assumption that link-trbs are always located at the end of a segment. Introduce -link to struct xhci_segment and use that every place that looks up the link-trb for a segment. This is meant to be functionally equivalent to the existing driver and is just a search and replace for hard coded link at the end assumption. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-mem.c | 17 +++-- drivers/usb/host/xhci-ring.c |7 ++- drivers/usb/host/xhci.c | 12 drivers/usb/host/xhci.h |1 + 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 1d05dc9e1928..1eda6166b30f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -115,11 +115,11 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, return; prev-next = next; if (type != TYPE_EVENT) { - prev-trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = - cpu_to_le64(next-dma); + prev-link = prev-trbs[TRBS_PER_SEGMENT-1]; + prev-link-link.segment_ptr = cpu_to_le64(next-dma); /* Set the last TRB in the segment to have a TRB type ID of Link TRB */ - val = le32_to_cpu(prev-trbs[TRBS_PER_SEGMENT-1].link.control); + val = le32_to_cpu(prev-link-link.control); val = ~TRB_TYPE_BITMASK; val |= TRB_TYPE(TRB_LINK); /* Always set the chain bit with 0.95 hardware */ @@ -128,7 +128,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, (type == TYPE_ISOC (xhci-quirks XHCI_AMD_0x96_HOST))) val |= TRB_CHAIN; - prev-trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); + prev-link-link.control = cpu_to_le32(val); } } @@ -152,10 +152,8 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, ring-num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs; if (ring-type != TYPE_EVENT ring-enq_seg == ring-last_seg) { - ring-last_seg-trbs[TRBS_PER_SEGMENT-1].link.control - = ~cpu_to_le32(LINK_TOGGLE); - last-trbs[TRBS_PER_SEGMENT-1].link.control - |= cpu_to_le32(LINK_TOGGLE); + ring-last_seg-link-link.control = ~cpu_to_le32(LINK_TOGGLE); + last-link-link.control |= cpu_to_le32(LINK_TOGGLE); ring-last_seg = last; } } @@ -395,8 +393,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, /* Only event ring does not use link TRB */ if (type != TYPE_EVENT) { /* See section 4.9.2.1 and 6.4.4.1 */ - ring-last_seg-trbs[TRBS_PER_SEGMENT - 1].link.control |= - cpu_to_le32(LINK_TOGGLE); + ring-last_seg-link-link.control |= cpu_to_le32(LINK_TOGGLE); } xhci_initialize_ring_info(ring, cycle_state); return ring; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0efbbf0b6233..ae436cb7e06d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -374,12 +374,10 @@ static struct xhci_segment *find_trb_seg( union xhci_trb *trb, int *cycle_state) { struct xhci_segment *cur_seg = start_seg; - struct xhci_generic_trb *generic_trb; while (cur_seg-trbs trb || cur_seg-trbs[TRBS_PER_SEGMENT - 1] trb) { - generic_trb = cur_seg-trbs[TRBS_PER_SEGMENT - 1].generic; - if (generic_trb-field[3] cpu_to_le32(LINK_TOGGLE)) + if (cur_seg-link-link.control cpu_to_le32(LINK_TOGGLE)) *cycle_state ^= 0x1; cur_seg = cur_seg-next; if (cur_seg == start_seg) @@ -1735,8 +1733,7 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, if (start_dma == 0) return NULL; /* We may get an event for a Link TRB in the middle of a TD */ - end_seg_dma = xhci_trb_virt_to_dma(cur_seg, - cur_seg-trbs[TRBS_PER_SEGMENT - 1]); + end_seg_dma = xhci_trb_virt_to_dma(cur_seg, cur_seg-link); /* If the end TRB isn't in this segment, this is set to 0 */ end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1d3dc014b477..0b05f67fde5b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -820,10 +820,14 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) ring = xhci-cmd_ring; seg = ring-deq_seg; do { - memset(seg-trbs, 0,
[RFC PATCH 03/20] xhci: introduce xhci_to_dev
Replace many occurrences of xhci_to_hcd(xhci)-self.controller with a helper. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-mem.c | 29 - drivers/usb/host/xhci.c |6 +++--- drivers/usb/host/xhci.h | 13 + 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8056d90690ee..fcae0ce47daa 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -574,11 +574,10 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, struct xhci_stream_ctx *stream_ctx, dma_addr_t dma) { - struct device *dev = xhci_to_hcd(xhci)-self.controller; size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; if (size MEDIUM_STREAM_ARRAY_SIZE) - dma_free_coherent(dev, size, + dma_free_coherent(xhci_to_dev(xhci), size, stream_ctx, dma); else if (size = SMALL_STREAM_ARRAY_SIZE) return dma_pool_free(xhci-small_streams_pool, @@ -602,11 +601,10 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, unsigned int num_stream_ctxs, dma_addr_t *dma, gfp_t mem_flags) { - struct device *dev = xhci_to_hcd(xhci)-self.controller; size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; if (size MEDIUM_STREAM_ARRAY_SIZE) - return dma_alloc_coherent(dev, size, + return dma_alloc_coherent(xhci_to_dev(xhci), size, dma, mem_flags); else if (size = SMALL_STREAM_ARRAY_SIZE) return dma_pool_alloc(xhci-small_streams_pool, @@ -1644,7 +1642,6 @@ void xhci_slot_copy(struct xhci_hcd *xhci, static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) { int i; - struct device *dev = xhci_to_hcd(xhci)-self.controller; int num_sp = HCS_MAX_SCRATCHPAD(xhci-hcs_params2); xhci_dbg_trace(xhci, trace_xhci_dbg_init, @@ -1657,7 +1654,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) if (!xhci-scratchpad) goto fail_sp; - xhci-scratchpad-sp_array = dma_alloc_coherent(dev, + xhci-scratchpad-sp_array = dma_alloc_coherent(xhci_to_dev(xhci), num_sp * sizeof(u64), xhci-scratchpad-sp_dma, flags); if (!xhci-scratchpad-sp_array) @@ -1676,8 +1673,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) xhci-dcbaa-dev_context_ptrs[0] = cpu_to_le64(xhci-scratchpad-sp_dma); for (i = 0; i num_sp; i++) { dma_addr_t dma; - void *buf = dma_alloc_coherent(dev, xhci-page_size, dma, - flags); + void *buf = dma_alloc_coherent(xhci_to_dev(xhci), + xhci-page_size, dma, flags); if (!buf) goto fail_sp5; @@ -1690,7 +1687,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) fail_sp5: for (i = i - 1; i = 0; i--) { - dma_free_coherent(dev, xhci-page_size, + dma_free_coherent(xhci_to_dev(xhci), xhci-page_size, xhci-scratchpad-sp_buffers[i], xhci-scratchpad-sp_dma_buffers[i]); } @@ -1700,7 +1697,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) kfree(xhci-scratchpad-sp_buffers); fail_sp3: - dma_free_coherent(dev, num_sp * sizeof(u64), + dma_free_coherent(xhci_to_dev(xhci), num_sp * sizeof(u64), xhci-scratchpad-sp_array, xhci-scratchpad-sp_dma); @@ -1716,7 +1713,6 @@ static void scratchpad_free(struct xhci_hcd *xhci) { int num_sp; int i; - struct device *dev = xhci_to_hcd(xhci)-self.controller; if (!xhci-scratchpad) return; @@ -1724,13 +1720,13 @@ static void scratchpad_free(struct xhci_hcd *xhci) num_sp = HCS_MAX_SCRATCHPAD(xhci-hcs_params2); for (i = 0; i num_sp; i++) { - dma_free_coherent(dev, xhci-page_size, + dma_free_coherent(xhci_to_dev(xhci), xhci-page_size, xhci-scratchpad-sp_buffers[i], xhci-scratchpad-sp_dma_buffers[i]); } kfree(xhci-scratchpad-sp_dma_buffers); kfree(xhci-scratchpad-sp_buffers); - dma_free_coherent(dev, num_sp * sizeof(u64), + dma_free_coherent(xhci_to_dev(xhci), num_sp * sizeof(u64), xhci-scratchpad-sp_array, xhci-scratchpad-sp_dma); kfree(xhci-scratchpad); @@ -1792,7 +1788,6 @@ void
[RFC PATCH 11/20] xhci: provide helpers for retrieving 'enqueue' and 'dequeue' pointers
In prepartion for converting ring management from pointers to power-of-2 indexes, introduce xhci_ring_dequeue(), xhci_ring_enqueue(), xhci_ring_set_dequeue(), and xhci_ring_set_enqueue(). Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-dbg.c | 16 ++-- drivers/usb/host/xhci-mem.c | 14 ++-- drivers/usb/host/xhci-ring.c | 166 ++ drivers/usb/host/xhci.c |6 +- drivers/usb/host/xhci.h | 27 ++- 5 files changed, 130 insertions(+), 99 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index ad22409ddecb..19a6037257c3 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -328,16 +328,16 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg) void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring) { - xhci_dbg(xhci, Ring deq = %p (virt), 0x%llx (dma)\n, - ring-dequeue, - (unsigned long long)xhci_trb_virt_to_dma(ring-deq_seg, - ring-dequeue)); + dma_addr_t dma; + + dma = xhci_trb_virt_to_dma(ring-deq_seg, xhci_ring_dequeue(ring)); + xhci_dbg(xhci, Ring deq = %p (virt), %pad (dma)\n, + xhci_ring_dequeue(ring), dma); xhci_dbg(xhci, Ring deq updated %u times\n, ring-deq_updates); - xhci_dbg(xhci, Ring enq = %p (virt), 0x%llx (dma)\n, - ring-enqueue, - (unsigned long long)xhci_trb_virt_to_dma(ring-enq_seg, - ring-enqueue)); + dma = xhci_trb_virt_to_dma(ring-enq_seg, xhci_ring_enqueue(ring)); + xhci_dbg(xhci, Ring enq = %p (virt), %pad (dma)\n, + xhci_ring_enqueue(ring), dma); xhci_dbg(xhci, Ring enq updated %u times\n, ring-enq_updates); } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index cfc7acc6482d..e0b459441807 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -261,9 +261,9 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring, struct xhci_segment *first_seg = xhci_ring_first_seg(ring); /* The ring is empty, so the enqueue pointer == dequeue pointer */ - ring-enqueue = first_seg-trbs; + xhci_ring_set_enqueue(ring, first_seg-trbs); ring-enq_seg = first_seg; - ring-dequeue = ring-enqueue; + xhci_ring_set_dequeue(ring, xhci_ring_enqueue(ring)); ring-deq_seg = first_seg; /* The ring is initialized to 0. The producer must write 1 to the cycle * bit to handover ownership of the TRB, so PCS = 1. The consumer must @@ -749,9 +749,11 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep_ctx, struct xhci_virt_ep *ep) { + struct xhci_ring *ring = ep-ring; dma_addr_t addr; + ep_ctx-ep_info = cpu_to_le32(~(EP_MAXPSTREAMS_MASK | EP_HAS_LSA)); - addr = xhci_trb_virt_to_dma(ep-ring-deq_seg, ep-ring-dequeue); + addr = xhci_trb_virt_to_dma(ring-deq_seg, xhci_ring_dequeue(ring)); ep_ctx-deq = cpu_to_le64(addr | ep-ring-cycle_state); } @@ -1014,8 +1016,8 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * been completed or cancelled before the reset. */ ep0_ctx-deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring-enq_seg, - ep_ring-enqueue) - | ep_ring-cycle_state); + xhci_ring_enqueue(ep_ring)) + | ep_ring-cycle_state); } /* @@ -2020,7 +2022,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) dma_addr_t deq; deq = xhci_trb_virt_to_dma(xhci-event_ring-deq_seg, - xhci-event_ring-dequeue); + xhci_ring_dequeue(xhci-event_ring)); if (deq == 0 !in_interrupt()) xhci_warn(xhci, WARN something wrong with SW event ring dequeue ptr.\n); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 61c48ed4db9b..01e6685738ff 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -122,7 +122,7 @@ static bool ep_last_trb(struct xhci_ring *ring, struct xhci_segment *seg, static int enqueue_is_link_trb(struct xhci_ring *ring) { - struct xhci_link_trb *link = ring-enqueue-link; + struct xhci_link_trb *link = xhci_ring_enqueue(ring)-link; return TRB_TYPE_LINK_LE32(link-control); } @@ -148,11 +148,11 @@ static void next_trb(struct xhci_ring *ring, struct xhci_segment **seg, static void event_inc_deq(struct xhci_ring *ring) { ring-deq_updates++; - ring-dequeue++; +
[RFC PATCH 06/20] xhci: drop 'xhci' argument to last_trb
last_trb() can simply distinguish event rings by the ring -type. With this in place the 'xhci' parameter can be removed from last_trb_on_last_seg(), next_trb(), and inc_deq(). Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c | 75 -- 1 files changed, 35 insertions(+), 40 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ae436cb7e06d..8f4e900128b5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -90,12 +90,12 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, /* Does this link TRB point to the first segment in a ring, * or was the previous TRB the last TRB on the last segment in the ERST? */ -static bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring *ring, +static bool last_trb_on_last_seg(struct xhci_ring *ring, struct xhci_segment *seg, union xhci_trb *trb) { - if (ring == xhci-event_ring) + if (ring-type == TYPE_EVENT) return (trb == seg-trbs[TRBS_PER_SEGMENT]) - (seg-next == xhci-event_ring-first_seg); + (seg-next == ring-first_seg); else return le32_to_cpu(trb-link.control) LINK_TOGGLE; } @@ -104,10 +104,10 @@ static bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring *ring, * segment? I.e. would the updated event TRB pointer step off the end of the * event seg? */ -static int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, - struct xhci_segment *seg, union xhci_trb *trb) +static int last_trb(struct xhci_ring *ring, struct xhci_segment *seg, + union xhci_trb *trb) { - if (ring == xhci-event_ring) + if (ring-type == TYPE_EVENT) return trb == seg-trbs[TRBS_PER_SEGMENT]; else return TRB_TYPE_LINK_LE32(trb-link.control); @@ -123,12 +123,10 @@ static int enqueue_is_link_trb(struct xhci_ring *ring) * TRB is in a new segment. This does not skip over link TRBs, and it does not * effect the ring dequeue or enqueue pointers. */ -static void next_trb(struct xhci_hcd *xhci, - struct xhci_ring *ring, - struct xhci_segment **seg, +static void next_trb(struct xhci_ring *ring, struct xhci_segment **seg, union xhci_trb **trb) { - if (last_trb(xhci, ring, *seg, *trb)) { + if (last_trb(ring, *seg, *trb)) { *seg = (*seg)-next; *trb = ((*seg)-trbs); } else { @@ -140,7 +138,7 @@ static void next_trb(struct xhci_hcd *xhci, * See Cycle bit rules. SW is the consumer for the event ring only. * Don't make a ring full of link TRBs. That would be dumb and this would loop. */ -static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) +static void inc_deq(struct xhci_ring *ring) { ring-deq_updates++; @@ -149,7 +147,7 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) * is not on a link TRB, there is one more usable TRB */ if (ring-type != TYPE_EVENT - !last_trb(xhci, ring, ring-deq_seg, ring-dequeue)) + !last_trb(ring, ring-deq_seg, ring-dequeue)) ring-num_trbs_free++; do { @@ -158,9 +156,9 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) * we're at the end of an event ring segment (which doesn't have * link TRBS) */ - if (last_trb(xhci, ring, ring-deq_seg, ring-dequeue)) { + if (last_trb(ring, ring-deq_seg, ring-dequeue)) { if (ring-type == TYPE_EVENT - last_trb_on_last_seg(xhci, ring, + last_trb_on_last_seg(ring, ring-deq_seg, ring-dequeue)) { ring-cycle_state ^= 1; } @@ -169,7 +167,7 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) } else { ring-dequeue++; } - } while (last_trb(xhci, ring, ring-deq_seg, ring-dequeue)); + } while (last_trb(ring, ring-deq_seg, ring-dequeue)); } /* @@ -198,7 +196,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, chain = le32_to_cpu(ring-enqueue-generic.field[3]) TRB_CHAIN; /* If this is not event ring, there is one less usable TRB */ if (ring-type != TYPE_EVENT - !last_trb(xhci, ring, ring-enq_seg, ring-enqueue)) + !last_trb(ring, ring-enq_seg, ring-enqueue)) ring-num_trbs_free--; next = ++(ring-enqueue); @@ -206,7 +204,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Update the dequeue pointer further if
[RFC PATCH 08/20] xhci: refactor inc_enq(), share a common advance_enq() with prepare_ring()
There are two locations where we advance the enqueue pointer through a chain of link trbs, in inc_enq() and prepare_ring(). Factor that into a common advance_enq(). Also, in preparation for per-ring operations factor out the differences between the event-rings, chain-quirk-rings and normal endpoint rings into event_ring_inc_enq() and common_inc_enq(). Unfortunately this isn't a net win in the diffstat, but it does eliminate the liability of failing to update one of the instances especially in preparation for overhauling TD-fragment handling for xhci1.0+ hosts. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c | 164 ++ 1 files changed, 86 insertions(+), 78 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bee5c18b0509..d8c9a8211ace 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -171,9 +171,39 @@ static void inc_deq(struct xhci_ring *ring) } /* - * See Cycle bit rules. SW is the consumer for the event ring only. - * Don't make a ring full of link TRBs. That would be dumb and this would loop. - * + * Don't make a ring full of link TRBs. That would be dumb and this + * would loop. + */ +static void advance_enq(struct xhci_ring *ring, u32 chain, bool do_carry_chain) +{ + union xhci_trb *next = ring-enqueue; + + /* +* Update the enqueue pointer further if we're now pointing to a +* link TRB +*/ + while (last_trb(ring, ring-enq_seg, next)) { + if (do_carry_chain) { + next-link.control = cpu_to_le32(~TRB_CHAIN); + next-link.control |= cpu_to_le32(chain); + } else { + next-link.control |= cpu_to_le32(TRB_CHAIN); + } + + /* Give this link TRB to the hardware */ + wmb(); + next-link.control ^= cpu_to_le32(TRB_CYCLE); + + /* Toggle the cycle bit after the last ring segment. */ + if (last_trb_on_last_seg(ring, ring-enq_seg, next)) + ring-cycle_state ^= 1; + ring-enq_seg = xhci_segment_next(ring, ring-enq_seg); + ring-enqueue = ring-enq_seg-trbs; + next = ring-enqueue; + } +} + +/* * If we've just enqueued a TRB that is in the middle of a TD (meaning the * chain bit is set), then set the chain bit in all the following link TRBs. * If we've enqueued the last TRB in a TD, make sure the following link TRBs @@ -187,63 +217,68 @@ static void inc_deq(struct xhci_ring *ring) * @more_trbs_coming: Will you enqueue more TRBs before calling * prepare_transfer()? */ -static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, - bool more_trbs_coming) +static void common_inc_enq(struct xhci_ring *ring, bool more_trbs_coming, + bool do_carry_chain) { - u32 chain; - union xhci_trb *next; - - chain = le32_to_cpu(ring-enqueue-generic.field[3]) TRB_CHAIN; - /* If this is not event ring, there is one less usable TRB */ - if (ring-type != TYPE_EVENT - !last_trb(ring, ring-enq_seg, ring-enqueue)) - ring-num_trbs_free--; - next = ++(ring-enqueue); + u32 chain = le32_to_cpu(ring-enqueue-generic.field[3]) TRB_CHAIN; + ring-num_trbs_free--; + (ring-enqueue)++; ring-enq_updates++; - /* Update the dequeue pointer further if that was a link TRB or we're at -* the end of an event ring segment (which doesn't have link TRBS) + + /* +* If the caller doesn't plan on enqueueing more TDs before +* ringing the doorbell, then we don't want to give the link TRB +* to the hardware just yet. We'll give the link TRB back in +* prepare_ring() just before we enqueue the TD at the top of +* the ring. */ - while (last_trb(ring, ring-enq_seg, next)) { - if (ring-type != TYPE_EVENT) { - /* -* If the caller doesn't plan on enqueueing more -* TDs before ringing the doorbell, then we -* don't want to give the link TRB to the -* hardware just yet. We'll give the link TRB -* back in prepare_ring() just before we enqueue -* the TD at the top of the ring. -*/ - if (!chain !more_trbs_coming) - break; + if (!chain !more_trbs_coming) + return; + advance_enq(ring, chain, do_carry_chain); +} - /* If we're not dealing with 0.95 hardware or -* isoc rings on AMD 0.96 host, -* carry over the chain bit of the previous TRB -
[RFC PATCH 12/20] xhci: introduce struct xhci_ring_pointer
Consolidate ring pointer tracking variables into their own type. This simplifies the calling convention of some routines and allows for the later introduction of integer ring index variables. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-dbg.c |8 + drivers/usb/host/xhci-mem.c | 26 ++-- drivers/usb/host/xhci-ring.c | 306 +++--- drivers/usb/host/xhci.c | 32 ++-- drivers/usb/host/xhci.h | 55 +--- 5 files changed, 201 insertions(+), 226 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 19a6037257c3..f1230629978c 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -330,12 +330,12 @@ void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring) { dma_addr_t dma; - dma = xhci_trb_virt_to_dma(ring-deq_seg, xhci_ring_dequeue(ring)); + dma = xhci_trb_virt_to_dma(ring-deq); xhci_dbg(xhci, Ring deq = %p (virt), %pad (dma)\n, xhci_ring_dequeue(ring), dma); xhci_dbg(xhci, Ring deq updated %u times\n, ring-deq_updates); - dma = xhci_trb_virt_to_dma(ring-enq_seg, xhci_ring_enqueue(ring)); + dma = xhci_trb_virt_to_dma(ring-enq); xhci_dbg(xhci, Ring enq = %p (virt), %pad (dma)\n, xhci_ring_enqueue(ring), dma); xhci_dbg(xhci, Ring enq updated %u times\n, @@ -379,7 +379,7 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci, ring = ep-stream_info-stream_rings[i]; xhci_dbg(xhci, Dev %d endpoint %d stream ID %d:\n, slot_id, ep_index, i); - xhci_debug_segment(xhci, ring-deq_seg); + xhci_debug_segment(xhci, ring-deq.seg); } } else { ring = ep-ring; @@ -387,7 +387,7 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci, return; xhci_dbg(xhci, Dev %d endpoint ring %d:\n, slot_id, ep_index); - xhci_debug_segment(xhci, ring-deq_seg); + xhci_debug_segment(xhci, ring-deq.seg); } } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index e0b459441807..452aa75a096c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -107,7 +107,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, new_tail = list_last_entry(segments, typeof(*new_tail), list); new_head = list_first_entry(segments, typeof(*new_head), list); - insert_head = ring-enq_seg; + insert_head = ring-enq.seg; insert_next = xhci_segment_next(ring, insert_head); /* link them physically */ @@ -259,12 +259,12 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring, unsigned int cycle_state) { struct xhci_segment *first_seg = xhci_ring_first_seg(ring); + struct xhci_ring_pointer enq = { first_seg, first_seg-trbs }; /* The ring is empty, so the enqueue pointer == dequeue pointer */ - xhci_ring_set_enqueue(ring, first_seg-trbs); - ring-enq_seg = first_seg; - xhci_ring_set_dequeue(ring, xhci_ring_enqueue(ring)); - ring-deq_seg = first_seg; + xhci_ring_set_enqueue(ring, enq); + xhci_ring_set_dequeue(ring, enq); + /* The ring is initialized to 0. The producer must write 1 to the cycle * bit to handover ownership of the TRB, so PCS = 1. The consumer must * compare CCS to the cycle bit to check ownership, so CCS = 1. @@ -753,7 +753,7 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci, dma_addr_t addr; ep_ctx-ep_info = cpu_to_le32(~(EP_MAXPSTREAMS_MASK | EP_HAS_LSA)); - addr = xhci_trb_virt_to_dma(ring-deq_seg, xhci_ring_dequeue(ring)); + addr = xhci_trb_virt_to_dma(ring-deq); ep_ctx-deq = cpu_to_le64(addr | ep-ring-cycle_state); } @@ -1015,8 +1015,7 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * configured device has reset, so all control transfers should have * been completed or cancelled before the reset. */ - ep0_ctx-deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring-enq_seg, - xhci_ring_enqueue(ep_ring)) + ep0_ctx-deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring-enq) | ep_ring-cycle_state); } @@ -1859,11 +1858,13 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci, unsigned long long start_dma; unsigned long long end_dma; struct xhci_segment *seg; + struct xhci_ring_pointer start_rp = { input_seg, start_trb }; + struct xhci_ring_pointer end_rp = { input_seg, end_trb }; - start_dma = xhci_trb_virt_to_dma(input_seg, start_trb); - end_dma =
[RFC PATCH 13/20] xhci: use %pad for printing dma_addr_t
Clean up verbose (unsigned long long) casts. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-dbg.c | 70 - drivers/usb/host/xhci-mem.c | 46 --- drivers/usb/host/xhci-ring.c | 41 +++- drivers/usb/host/xhci-trace.h |8 ++--- drivers/usb/host/xhci.c | 19 +-- 5 files changed, 79 insertions(+), 105 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index f1230629978c..8789d930f517 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -425,10 +425,8 @@ static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma) { int i; for (i = 0; i 4; ++i) { - xhci_dbg(xhci, @%p (virt) @%08llx -(dma) %#08llx - rsvd64[%d]\n, -ctx[4 + i], (unsigned long long)dma, -ctx[4 + i], i); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08llx - rsvd64[%d]\n, + ctx[4 + i], dma, ctx[4 + i], i); dma += 8; } } @@ -464,25 +462,21 @@ static void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx * int csz = HCC_64BYTE_CONTEXT(xhci-hcc_params); xhci_dbg(xhci, Slot Context:\n); - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - dev_info\n, - slot_ctx-dev_info, - (unsigned long long)dma, slot_ctx-dev_info); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - dev_info\n, + slot_ctx-dev_info, dma, slot_ctx-dev_info); dma += field_size; - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - dev_info2\n, - slot_ctx-dev_info2, - (unsigned long long)dma, slot_ctx-dev_info2); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - dev_info2\n, + slot_ctx-dev_info2, dma, slot_ctx-dev_info2); dma += field_size; - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - tt_info\n, - slot_ctx-tt_info, - (unsigned long long)dma, slot_ctx-tt_info); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - tt_info\n, + slot_ctx-tt_info, dma, slot_ctx-tt_info); dma += field_size; - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - dev_state\n, - slot_ctx-dev_state, - (unsigned long long)dma, slot_ctx-dev_state); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - dev_state\n, + slot_ctx-dev_state, dma, slot_ctx-dev_state); dma += field_size; for (i = 0; i 4; ++i) { - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n, - slot_ctx-reserved[i], (unsigned long long)dma, + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - rsvd[%d]\n, + slot_ctx-reserved[i], dma, slot_ctx-reserved[i], i); dma += field_size; } @@ -512,26 +506,21 @@ static void xhci_dbg_ep_ctx(struct xhci_hcd *xhci, xhci_dbg(xhci, %s Endpoint %02d Context (ep_index %02d):\n, usb_endpoint_out(epaddr) ? OUT : IN, epaddr USB_ENDPOINT_NUMBER_MASK, i); - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - ep_info\n, - ep_ctx-ep_info, - (unsigned long long)dma, ep_ctx-ep_info); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - ep_info\n, + ep_ctx-ep_info, dma, ep_ctx-ep_info); dma += field_size; - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - ep_info2\n, - ep_ctx-ep_info2, - (unsigned long long)dma, ep_ctx-ep_info2); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - ep_info2\n, + ep_ctx-ep_info2, dma, ep_ctx-ep_info2); dma += field_size; - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08llx - deq\n, - ep_ctx-deq, - (unsigned long long)dma, ep_ctx-deq); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08llx - deq\n, + ep_ctx-deq, dma, ep_ctx-deq); dma += 2*field_size; - xhci_dbg(xhci, @%p (virt) @%08llx (dma) %#08x - tx_info\n, - ep_ctx-tx_info, - (unsigned long long)dma, ep_ctx-tx_info); + xhci_dbg(xhci, @%p (virt) @%pad (dma) %#08x - tx_info\n, + ep_ctx-tx_info, dma, ep_ctx-tx_info); dma += field_size; for (j = 0; j 3; ++j) { -
[RFC PATCH 09/20] xhci: introduce ring ops to handle event vs non-event rings
It's confusing (to me at least) to keep on remembering the differences between event rings (managed by the hardware) and non-event rings managed by the host. Replace if (ring-type == FOO) branches with ring ops that are specific to the type of ring. This is a tradeoff of direct code readability vs isolation and better readability of diffs (i.e. diff-context will now explicitly identify the ring type). It promotes quirky rings to their own type in that they have their own distinct ring ops, as a result we no longer need to pass 'xhci' to queue_trb(). Finally, this is a preparation for xhci1.0+ ring handling which will have it's own ring ops. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-mem.c | 63 ++--- drivers/usb/host/xhci-ring.c | 306 +- drivers/usb/host/xhci.h | 28 +++- 3 files changed, 252 insertions(+), 145 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index ad682731153f..cfc7acc6482d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -96,36 +96,6 @@ static void xhci_free_segments(struct list_head *segments) } /* - * Change the last TRB in the prev segment to be a Link TRB which points to the - * DMA address of the next segment. The caller needs to set any Link TRB - * related flags, such as End TRB, Toggle Cycle, and no snoop. - */ -static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, - struct xhci_segment *next, enum xhci_ring_type type) -{ - u32 val; - - if (!prev || !next) - return; - if (type != TYPE_EVENT) { - prev-link = prev-trbs[TRBS_PER_SEGMENT-1]; - prev-link-link.segment_ptr = cpu_to_le64(next-dma); - - /* Set the last TRB in the segment to have a TRB type ID of Link TRB */ - val = le32_to_cpu(prev-link-link.control); - val = ~TRB_TYPE_BITMASK; - val |= TRB_TYPE(TRB_LINK); - /* Always set the chain bit with 0.95 hardware */ - /* Set chain bit for isoc rings on AMD 0.96 host */ - if (xhci_link_trb_quirk(xhci) || - (type == TYPE_ISOC -(xhci-quirks XHCI_AMD_0x96_HOST))) - val |= TRB_CHAIN; - prev-link-link.control = cpu_to_le32(val); - } -} - -/* * Link the ring to the new segments. * Set Toggle Cycle for the new ring if needed. */ @@ -141,8 +111,8 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, insert_next = xhci_segment_next(ring, insert_head); /* link them physically */ - xhci_link_segments(xhci, insert_head, new_head, ring-type); - xhci_link_segments(xhci, new_tail, insert_next, ring-type); + ring-ops-link_segments(insert_head, new_head); + ring-ops-link_segments(new_tail, insert_next); /* link them logically */ list_splice_init(segments, insert_head-list); @@ -150,7 +120,8 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, ring-num_segs += num_segs; ring-num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs; - if (ring-type != TYPE_EVENT insert_head == last_seg) { + BUG_ON(xhci_is_event_ring(ring)); + if (insert_head == last_seg) { last_seg-link-link.control = ~cpu_to_le32(LINK_TOGGLE); new_tail-link-link.control |= cpu_to_le32(LINK_TOGGLE); } @@ -276,7 +247,7 @@ void xhci_ring_free(struct xhci_ring *ring) return; if (!list_empty(ring-segments)) { - if (ring-type == TYPE_STREAM) + if (ring-is_stream) xhci_remove_stream_mapping(ring); xhci_free_segments(ring-segments); } @@ -316,7 +287,8 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring, /* Allocate segments and link them for a ring */ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, struct list_head *segments, unsigned int num_segs, - unsigned int cycle_state, enum xhci_ring_type type, gfp_t flags) + unsigned int cycle_state, const struct xhci_ring_ops *ops, + gfp_t flags) { struct xhci_segment *seg; int i; @@ -338,7 +310,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, if (next-list == segments) next = list_first_entry(segments, typeof(*next), list); - xhci_link_segments(xhci, seg, next, type); + ops-link_segments(seg, next); } return 0; @@ -362,20 +334,20 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, if (!ring) return NULL; + xhci_ring_init_type(xhci, ring, type); ring-num_segs = num_segs;
[RFC PATCH 00/20] xhci: implement xhci-v1+ td-fragment rules, test
Sending as an RFC primarily to get feedback on the unit testing approach while there's still time to yell at me in person at LinuxCon. Including Rusty in pursuit of comments on how to do mocked interfaces for testing purposes in-tree. === This series updates the xhci driver to honor all the rules specified in section 4.11.7.1 of the xhci specification (v1.1). See the changelog for patch 19 for more background. Patches 1-18 are cleanups, fixes, and smaller ring geometry changes to support patches 19 and 20. If you only review one of these patches please review patch 20 (xhci: unit test ring enqueue/dequeue routines) to see the current passing test cases and please do propose additional ones. As it stands Sarah would like, and I agree, that we need a cancellation unit test before proposing this for inclusion. The current unit test is passing as well as basic verification with a SuperSpeed USB Mass Storage device. Testing with known problematic devices is requested / required before this is ready for upstream. Note the comment in v1_inc_deq() in patch 19. /* * ep_inc_deq() lets the dequeue-pointer (deq/tail) wrap the * enqueue-pointer (enq/head)! However, since room_on_ring() looks at * -num_trbs_free instead of the position of the ring pointers, it * never causes a problem as enq gets back in line with deq at the next * submission. * * In the case of v1+ rings, conditional_expand() is sensitive to this * wrap and prematurely expands the ring. Prevent that condition by * stopping once deq == enq. Eventually, -num_trbs_free should be * deprecated entirely in favor of just comparing the ring pointers. * For now, for legacy compatibility, we leave well enough alone and * limit this to xhci-v1+ implementations. */ I'm wondering if this is the root cause behind the set ring dequeue pointer problem reported by Julius [1]? I'll be taking a closer look at that as I revise this series. [1]: http://marc.info/?l=linux-usbm=140484618509288w=2 Finally, note that this conversion should be a nop for xhci hosts prior to v1.0 as the old enqueue scheme is preserved. I'm taking this approach to limit bug hunting diversions on older hosts. If anyone has a pre-1.0 host, test reports are appreciated to verify that it indeed does not break those hosts. --- For testing convenience these patches are available via git at: git://git.kernel.org/pub/scm/linux/kernel/git/djbw/usb td-fragments-v1 Note that this branch may be rebased and/or abandoned (in favor of a td-fragments-v2+) as the set is revised. Dan Williams (20): xhci: cleanup remaining cycle bit toggles via ternary conditional xhci: remove invalid cast of xhci to a usb_device in xhci_log_ctx trace xhci: introduce xhci_to_dev xhci: increase trb segment size, kill -segment_pool xhci: prepare for mid-segment link-trbs xhci: drop 'xhci' argument to last_trb xhci: make xhci_segments doubly linked xhci: refactor inc_enq(), share a common advance_enq() with prepare_ring() xhci: introduce ring ops to handle event vs non-event rings xhci: clarify ring valid checks xhci: provide helpers for retrieving 'enqueue' and 'dequeue' pointers xhci: introduce struct xhci_ring_pointer xhci: use %pad for printing dma_addr_t xhci: power-of-2 ring sizes xhci: kill -num_trbs_free_temp in struct xhci_ring xhci: refactor prepare_transfer() xhci: combine xhci_queue_bulk_tx() and queue_bulk_sg_tx() xhci: add xhci_ring_reap_td() helper xhci: v1.0 scatterlist enqueue support (td-fragment rework) xhci: unit test ring enqueue/dequeue routines drivers/usb/host/Kconfig| 13 drivers/usb/host/Makefile |1 drivers/usb/host/xhci-dbg.c | 97 +- drivers/usb/host/xhci-hub.c |5 drivers/usb/host/xhci-mem.c | 580 +- drivers/usb/host/xhci-ring.c| 1638 ++- drivers/usb/host/xhci-trace.h | 13 drivers/usb/host/xhci.c | 82 + drivers/usb/host/xhci.h | 230 +++- drivers/usb/host/xhcitest/Makefile | 35 + drivers/usb/host/xhcitest/xhci-trace.h | 96 ++ drivers/usb/host/xhcitest/xhci-unit-dbg.c |1 drivers/usb/host/xhcitest/xhci-unit-trace.c |2 drivers/usb/host/xhcitest/xhci-unit.c | 641 +++ 14 files changed, 2457 insertions(+), 977 deletions(-) create mode 100644 drivers/usb/host/xhcitest/Makefile create mode 100644 drivers/usb/host/xhcitest/xhci-trace.h create mode 100644 drivers/usb/host/xhcitest/xhci-unit-dbg.c create mode 100644 drivers/usb/host/xhcitest/xhci-unit-trace.c create mode 100644 drivers/usb/host/xhcitest/xhci-unit.c -- To unsubscribe from this list: send the line unsubscribe
[RFC PATCH 10/20] xhci: clarify ring valid checks
All rings have -dequeue = -enqueue = first trb in first segment, so it is redundant to check if -dequeue is NULL when -ring is set. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-hub.c |5 ++--- drivers/usb/host/xhci-ring.c |2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa79e8749040..b01778002be2 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -285,7 +285,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) spin_lock_irqsave(xhci-lock, flags); for (i = LAST_EP_INDEX; i 0; i--) { - if (virt_dev-eps[i].ring virt_dev-eps[i].ring-dequeue) { + if (virt_dev-eps[i].ring) { struct xhci_command *command; command = xhci_alloc_command(xhci, false, false, GFP_NOWAIT); @@ -322,8 +322,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) int i; for (i = 0; i LAST_EP_INDEX + 1; i++) - if (xhci-devs[slot_id]-eps[i].ring - xhci-devs[slot_id]-eps[i].ring-dequeue) + if (xhci-devs[slot_id]-eps[i].ring) xhci_ring_ep_doorbell(xhci, slot_id, i, 0); return; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 8a46c99c6ba5..61c48ed4db9b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2767,7 +2767,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci) int update_ptrs = 1; int ret; - if (!xhci-event_ring || !xhci-event_ring-dequeue) { + if (!xhci-event_ring) { xhci-error_bitmask |= 1 1; return 0; } -- 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
[RFC PATCH 17/20] xhci: combine xhci_queue_bulk_tx() and queue_bulk_sg_tx()
The only difference between these two routines is that the latter handles a scatterlist of more than one entry. Fake a single entry scatterlist for the non-sg case, and delete the duplicate code. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c | 158 +- 1 files changed, 19 insertions(+), 139 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3a9ed6543dfe..ed42704f68ad 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3044,17 +3044,15 @@ static int prepare_transfer(struct xhci_hcd *xhci, return prepare_td(ep_ring, urb, td_index); } -static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) +static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, + struct urb *urb, struct scatterlist *sgl, int num_sgs) { - int num_sgs, num_trbs, running_total, temp, i; + int num_trbs, running_total, temp, i; struct scatterlist *sg; - sg = NULL; - num_sgs = urb-num_mapped_sgs; temp = urb-transfer_buffer_length; - num_trbs = 0; - for_each_sg(urb-sg, sg, num_sgs, i) { + for_each_sg(sgl, sg, num_sgs, i) { unsigned int len = sg_dma_len(sg); /* Scatter gather list entries may cross 64KB boundaries */ @@ -3198,15 +3196,15 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, } static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) + struct urb *urb, struct scatterlist *sgl, int num_sgs, + int slot_id, unsigned int ep_index) { struct xhci_ring *ep_ring; unsigned int num_trbs; struct urb_priv *urb_priv; struct xhci_td *td; - struct scatterlist *sg; - int num_sgs; int trb_buff_len, this_sg_len, running_total; + struct scatterlist *sg = sgl; unsigned int total_packet_count; bool first_trb; u64 addr; @@ -3218,8 +3216,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (!ep_ring) return -EINVAL; - num_trbs = count_sg_trbs_needed(xhci, urb); - num_sgs = urb-num_mapped_sgs; + num_trbs = count_sg_trbs_needed(xhci, urb, sgl, num_sgs); total_packet_count = DIV_ROUND_UP(urb-transfer_buffer_length, usb_endpoint_maxp(urb-ep-desc)); @@ -3250,7 +3247,6 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, *the amount of memory allocated for this scatter-gather list. * 3. TRBs buffers can't cross 64KB boundaries. */ - sg = urb-sg; addr = (u64) sg_dma_address(sg); this_sg_len = sg_dma_len(sg); trb_buff_len = TRB_MAX_BUFF_SIZE - (addr (TRB_MAX_BUFF_SIZE - 1)); @@ -3349,140 +3345,24 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return 0; } -/* This is very similar to what ehci-q.c qtd_fill() does */ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) { - struct xhci_ring *ep_ring; - struct urb_priv *urb_priv; - struct xhci_td *td; - int num_trbs; - bool first_trb; - bool more_trbs_coming; - int start_cycle; - u32 field, length_field; - union xhci_trb *start_trb; - int running_total, trb_buff_len, ret; - unsigned int total_packet_count; - u64 addr; - if (urb-num_sgs) - return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index); + return queue_bulk_sg_tx(xhci, mem_flags, urb, urb-sg, + urb-num_mapped_sgs, slot_id, ep_index); + else { + struct scatterlist scatter, *sg = scatter; - ep_ring = xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) - return -EINVAL; - - num_trbs = 0; - /* How much data is (potentially) left before the 64KB boundary? */ - running_total = TRB_MAX_BUFF_SIZE - - (urb-transfer_dma (TRB_MAX_BUFF_SIZE - 1)); - running_total = TRB_MAX_BUFF_SIZE - 1; + sg_init_table(sg, 1); + sg_set_buf(sg, urb-transfer_buffer, + urb-transfer_buffer_length); + sg-dma_address = urb-transfer_dma; + sg_dma_len(sg) = sg-length; - /* If there's some data on this 64KB chunk, or we have to send a -* zero-length transfer, we need at least one TRB -*/ - if (running_total != 0 || urb-transfer_buffer_length == 0) - num_trbs++; - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total urb-transfer_buffer_length) { - num_trbs++; -
[RFC PATCH 16/20] xhci: refactor prepare_transfer()
In preparation for honoring xhci-v1.0+ td-fragment handling rules break out the subroutines of prepare_transfer(). Rather than calculating the number of trbs required and expanding the ring, v1.0+ hosts will dynamically resize the ring as it discovers td-fragments that end up straddling a segment boundary. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c | 122 -- 1 files changed, 70 insertions(+), 52 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 27d271e26445..3a9ed6543dfe 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2920,10 +2920,69 @@ static void queue_trb(struct xhci_ring *ring, bool more_trbs_coming, * FIXME allocate segments if the ring is full. */ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, - u32 ep_state, unsigned int num_trbs, gfp_t mem_flags) + unsigned int num_trbs, gfp_t mem_flags) { unsigned int num_trbs_needed; + while (1) { + if (room_on_ring(xhci, ep_ring, num_trbs)) + break; + + if (ep_ring == xhci-cmd_ring) { + xhci_err(xhci, Do not support expand command ring\n); + return -ENOMEM; + } + + xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, + ERROR no room on ep ring, try ring expansion); + num_trbs_needed = num_trbs - ep_ring-num_trbs_free; + if (xhci_ring_expansion(xhci, ep_ring, num_trbs_needed, + mem_flags)) { + xhci_err(xhci, Ring expansion failed\n); + return -ENOMEM; + } + } + + if (enqueue_is_link_trb(ep_ring)) + advance_enq(ep_ring, 0, do_carry_chain(xhci, ep_ring)); + return 0; +} + +static int prepare_td(struct xhci_ring *ring, struct urb *urb, + unsigned int td_index) +{ + struct urb_priv *urb_priv; + struct xhci_td *td; + + urb_priv = urb-hcpriv; + td = urb_priv-td[td_index]; + + INIT_LIST_HEAD(td-td_list); + INIT_LIST_HEAD(td-cancelled_td_list); + + if (td_index == 0) { + struct usb_hcd *hcd = bus_to_hcd(urb-dev-bus); + int ret = usb_hcd_link_urb_to_ep(hcd, urb); + + if (ret) + return ret; + } + + td-urb = urb; + /* Add this TD to the tail of the endpoint ring's TD list */ + list_add_tail(td-td_list, ring-td_list); + td-start_seg = ring-enq.seg; + td-first_trb = xhci_ring_enqueue(ring); + urb_priv-td[td_index] = td; + + return 0; +} + +static int check_ep_submit_state(struct xhci_hcd *xhci, + struct xhci_ep_ctx *ep_ctx) +{ + u32 ep_state = le32_to_cpu(ep_ctx-ep_info) EP_STATE_MASK; + /* Make sure the endpoint has been added to xHC schedule */ switch (ep_state) { case EP_STATE_DISABLED: @@ -2951,28 +3010,6 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, */ return -EINVAL; } - - while (1) { - if (room_on_ring(xhci, ep_ring, num_trbs)) - break; - - if (ep_ring == xhci-cmd_ring) { - xhci_err(xhci, Do not support expand command ring\n); - return -ENOMEM; - } - - xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, - ERROR no room on ep ring, try ring expansion); - num_trbs_needed = num_trbs - ep_ring-num_trbs_free; - if (xhci_ring_expansion(xhci, ep_ring, num_trbs_needed, - mem_flags)) { - xhci_err(xhci, Ring expansion failed\n); - return -ENOMEM; - } - } - - if (enqueue_is_link_trb(ep_ring)) - advance_enq(ep_ring, 0, do_carry_chain(xhci, ep_ring)); return 0; } @@ -2986,8 +3023,6 @@ static int prepare_transfer(struct xhci_hcd *xhci, gfp_t mem_flags) { int ret; - struct urb_priv *urb_priv; - struct xhci_td *td; struct xhci_ring *ep_ring; struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev-out_ctx, ep_index); @@ -2998,33 +3033,15 @@ static int prepare_transfer(struct xhci_hcd *xhci, return -EINVAL; } - ret = prepare_ring(xhci, ep_ring, - le32_to_cpu(ep_ctx-ep_info) EP_STATE_MASK, - num_trbs, mem_flags); + ret = check_ep_submit_state(xhci, ep_ctx); if (ret) return ret; - urb_priv = urb-hcpriv; - td = urb_priv-td[td_index]; - - INIT_LIST_HEAD(td-td_list); -
[RFC PATCH 18/20] xhci: add xhci_ring_reap_td() helper
TDs from endpoint rings are open-coded cleaned up in a duplicate fashion in two places. Provide common helper. This is later used to as a place to inject ring-type-specific post-reap operations. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c | 17 + 1 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ed42704f68ad..ef9d58039666 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1962,6 +1962,13 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code) return 0; } +static void xhci_ring_reap_td(struct xhci_ring *ep_ring, struct xhci_td *td) +{ + while (xhci_ring_dequeue(ep_ring) != td-last_trb) + xhci_ring_inc_deq(ep_ring); + xhci_ring_inc_deq(ep_ring); +} + /* * Finish the td processing, remove the td from td list; * Return 1 if the urb can be given back. @@ -2020,10 +2027,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, slot_id, ep_index, ep_ring-stream_id, td, event_trb); } else { - /* Update ring dequeue pointer */ - while (xhci_ring_dequeue(ep_ring) != td-last_trb) - xhci_ring_inc_deq(ep_ring); - xhci_ring_inc_deq(ep_ring); + xhci_ring_reap_td(ep_ring, td); } td_cleanup: @@ -2272,10 +2276,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, /* calc actual length */ frame-actual_length = 0; - /* Update ring dequeue pointer */ - while (xhci_ring_dequeue(ep_ring) != td-last_trb) - xhci_ring_inc_deq(ep_ring); - xhci_ring_inc_deq(ep_ring); + xhci_ring_reap_td(ep_ring, td); return finish_td(xhci, td, NULL, event, ep, status, true); } -- 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
[RFC PATCH 14/20] xhci: power-of-2 ring sizes
In preparation for dynamic ring expansion while walking scatterlists for v1.0+ xhci hosts force the ring sizes to be a power-of-2. This property combined with the conversion of segments to a doubly linked list allows for translating ring pointers to integers enabling simple math to interrogate the state of the ring. Beyond determining the amount of free space in the ring this enables easy to calculate answers to questions like: * whether a trb is free or allocated? * which segment precedes the current segment? * how many trbs before the enqueue pointer wraps into the same segment as the dequeue pointer? The open coded num_trbs alignment statement in xhci_ring_expansion() is replaced with the standard ALIGN macro. Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-mem.c | 45 ++- drivers/usb/host/xhci.c |2 +- drivers/usb/host/xhci.h |8 +++- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b1ba9ec79c88..edaa49798172 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -117,7 +117,6 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, /* link them logically */ list_splice_init(segments, insert_head-list); - ring-num_segs += num_segs; ring-num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs; BUG_ON(xhci_is_event_ring(ring)); @@ -281,7 +280,7 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring, * Each segment has a link TRB, and leave an extra TRB for SW * accounting purpose */ - ring-num_trbs_free = ring-num_segs * (TRBS_PER_SEGMENT - 1) - 1; + ring-num_trbs_free = (1 ring-order) * (TRBS_PER_SEGMENT - 1) - 1; } /* Allocate segments and link them for a ring */ @@ -324,7 +323,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, * See section 4.9.1 and figures 15 and 16. */ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, - unsigned int num_segs, unsigned int cycle_state, + unsigned int order, unsigned int cycle_state, enum xhci_ring_type type, gfp_t flags) { struct xhci_ring *ring; @@ -335,13 +334,10 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, return NULL; xhci_ring_init_type(xhci, ring, type); - ring-num_segs = num_segs; + ring-order = order; INIT_LIST_HEAD(ring-segments); INIT_LIST_HEAD(ring-td_list); - if (num_segs == 0) - return ring; - - ret = xhci_alloc_segments_for_ring(xhci, ring-segments, num_segs, + ret = xhci_alloc_segments_for_ring(xhci, ring-segments, (1 order), cycle_state, ring-ops, flags); if (ret) goto fail; @@ -425,17 +421,21 @@ static void xhci_reinit_cached_ring(struct xhci_hcd *xhci, int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, unsigned int num_trbs, gfp_t flags) { - unsigned intnum_segs; - unsigned intnum_segs_needed; - int ret; + int ret; LIST_HEAD(segments); + unsigned int num_segs, inc, base; - num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) / - (TRBS_PER_SEGMENT - 1); + num_segs = ALIGN(num_trbs, TRBS_PER_SEGMENT) / TRBS_PER_SEGMENT; - /* Allocate number of segments we needed, or double the ring size */ - num_segs = ring-num_segs num_segs_needed ? - ring-num_segs : num_segs_needed; + /* +* Increase the order to accommodate the number of new segments +* needed +*/ + inc = 1; + base = xhci_ring_num_segs(ring); + while (((1 (ring-order + inc)) - base) num_segs) + inc++; + num_segs = (1 (ring-order + inc)) - base; ret = xhci_alloc_segments_for_ring(xhci, segments, num_segs, ring-cycle_state, ring-ops, flags); @@ -451,9 +451,10 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, } xhci_link_rings(xhci, ring, segments, num_segs); + ring-order = ilog2((1 ring-order) + num_segs); xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, ring expansion succeed, now has %d segments, - ring-num_segs); + xhci_ring_num_segs(ring)); return 0; } @@ -668,7 +669,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, struct xhci_segment *first_seg; stream_info-stream_rings[cur_stream] = - xhci_ring_alloc(xhci, 2, 1, TYPE_STREAM, mem_flags); + xhci_ring_alloc(xhci, 1, 1,
[RFC PATCH 15/20] xhci: kill -num_trbs_free_temp in struct xhci_ring
This can simply be done inline in xhci_queue_isoc_tx(). Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-ring.c |6 +++--- drivers/usb/host/xhci.h |1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ed167f17b2d2..27d271e26445 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3672,6 +3672,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_ring_pointer rp; u64 start_addr, addr; int i, j; + unsigned int num_trbs_free_save; bool more_trbs_coming; ep_ring = xhci-devs[slot_id]-eps[ep_index].ring; @@ -3687,6 +3688,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, start_cycle = ep_ring-cycle_state; urb_priv = urb-hcpriv; + num_trbs_free_save = ep_ring-num_trbs_free; /* Queue the first TRB, even if it's zero-length */ for (i = 0; i num_tds; i++) { unsigned int total_packet_count; @@ -3834,7 +3836,7 @@ cleanup: rp.ptr = urb_priv-td[0]-first_trb; xhci_ring_set_enqueue(ep_ring, rp); ep_ring-cycle_state = start_cycle; - ep_ring-num_trbs_free = ep_ring-num_trbs_free_temp; + ep_ring-num_trbs_free = num_trbs_free_save; usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb-dev-bus), urb); return ret; } @@ -3903,8 +3905,6 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, urb-dev-speed == USB_SPEED_FULL) urb-interval /= 8; } - ep_ring-num_trbs_free_temp = ep_ring-num_trbs_free; - return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index); } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c38b10b96898..94c5d74e35b8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1350,7 +1350,6 @@ struct xhci_ring { unsigned intstream_id; unsigned intorder; unsigned intnum_trbs_free; - unsigned intnum_trbs_free_temp; boollast_td_was_short; boolis_command; boolis_stream; -- 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
[RFC PATCH 19/20] xhci: v1.0 scatterlist enqueue support (td-fragment rework)
v1.0 hosts require that TD-fragments (portions of a TD that do not end on a MPB boundary) not cross a TRB segment boundary. This constraint is in addition to the constraint that a TRB may not specify a transfer that crosses a 64K boundary. This enabling permits the driver to accept scatterlists of nearly any geometry. Nearly because there is one unlikely remaining degenerate case of a driver submitting a transfer that consumes all the TRBs in a segment before hitting an MBP boundary. That case is trapped and the transfer is rejected. Given the multi-dimensional constraints of queuing TRBs from a scattelist, this implementation does not attempt to pre-calculate the number TRBs in a TD. Instead it attempts a dry-run of enqueuing the TRBs to the ring. If it discovers a TD-fragment straddling a segment boundary it backs up to the last MBP boundary, inserts a link-trb at that boundary, and restarts enqueuing in the next segment. A side effect of not pre-calculating the number of required TRBs is that the ring is now expanded as the scatterlist is walked, rather than in prepare_ring(). To simplify the math and forgo the need to track (union xhci_trb *) and (struct xhci_segment *) pointers, modulo-power-of-2 ring indexes are used. A small portion of the patch is adding infrastructure to convert from a (struct xhci_ring_pointer *) to an integer index. Glossary of acronyms: TRB: Transfer Request Buffer, 16-byte xhci-hardware scatterlist entry TD: Transfer Descriptor, the set of trbs that comprise a transfer TRB segment: A contiguous allocation of TRBs. They are of size PAGE_SIZE in the xhci driver. Each segment ends with a link TRB pointing to the next segment, but the link trb may appear at any TRB boundary in the segment. Ring: A linked list of segments. MBP: Max Burst Packet, is the minimum amount of data hardware expects to transfer before the end of a segment (assuming the TD spans a segment boundary). Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/xhci-mem.c | 17 + drivers/usb/host/xhci-ring.c | 620 +- drivers/usb/host/xhci.h | 75 + 3 files changed, 695 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index edaa49798172..1fc38ec60c25 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -103,7 +103,8 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, struct list_head *segments, unsigned int num_segs) { struct xhci_segment *insert_head, *insert_next, *new_head, *new_tail; - struct xhci_segment *last_seg = xhci_ring_last_seg(ring); + struct xhci_segment *last_seg = xhci_ring_last_seg(ring), *seg; + int i; new_tail = list_last_entry(segments, typeof(*new_tail), list); new_head = list_first_entry(segments, typeof(*new_head), list); @@ -124,6 +125,11 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring, last_seg-link-link.control = ~cpu_to_le32(LINK_TOGGLE); new_tail-link-link.control |= cpu_to_le32(LINK_TOGGLE); } + + i = insert_head-segid + 1; + seg = insert_head; + list_for_each_entry_continue(seg, ring-segments, list) + seg-segid = i++; } /* @@ -257,8 +263,9 @@ void xhci_ring_free(struct xhci_ring *ring) static void xhci_initialize_ring_info(struct xhci_ring *ring, unsigned int cycle_state) { - struct xhci_segment *first_seg = xhci_ring_first_seg(ring); + struct xhci_segment *first_seg = xhci_ring_first_seg(ring), *seg; struct xhci_ring_pointer enq = { first_seg, first_seg-trbs }; + int i; /* The ring is empty, so the enqueue pointer == dequeue pointer */ xhci_ring_set_enqueue(ring, enq); @@ -280,7 +287,11 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring, * Each segment has a link TRB, and leave an extra TRB for SW * accounting purpose */ - ring-num_trbs_free = (1 ring-order) * (TRBS_PER_SEGMENT - 1) - 1; + ring-num_trbs_free = xhci_ring_size(ring) - xhci_ring_num_segs(ring) - 1; + + i = 0; + list_for_each_entry(seg, ring-segments, list) + seg-segid = i++; } /* Allocate segments and link them for a ring */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ef9d58039666..82a24ce58c3e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -168,6 +168,40 @@ static void ep_inc_deq(struct xhci_ring *ring) } while (ring-ops-last_trb(ring, ring-deq)); } +static void v1_inc_deq(struct xhci_ring *ring) +{ + ring-deq_updates++; + + if (!ring-ops-last_trb(ring, ring-deq)) + ring-num_trbs_free++; + + /* +* ep_inc_deq() lets the dequeue-pointer (deq/tail) wrap the +*
[RFC PATCH 20/20] xhci: unit test ring enqueue/dequeue routines
Given the complexity of satisfying xhci 1.0+ host trb boundary constraints, provide a test case that exercises inserting mid-segment links into a ring. The linker --wrap= option is used to not pollute the global identifier space and to make it clear which standard xhci driver routines are being mocked-up. The --wrap= option does not come into play when both xhci-hcd and xhci-test are built-in to the kernel, so namespace collisions are prevented by excluding xhci-test from the build when xhci-hcd is built-in. It's unfortunate that this is an in-kernel test rather than userspace and that the infrastructure is custom rather than generic. That said, it serves its purpose of exercising the corner cases of the scatterlist parsing implementation in xhci. Cc: Rusty Russell ru...@rustcorp.com.au Signed-off-by: Dan Williams dan.j.willi...@intel.com --- drivers/usb/host/Kconfig| 13 + drivers/usb/host/Makefile |1 drivers/usb/host/xhci-mem.c |2 drivers/usb/host/xhci-ring.c|2 drivers/usb/host/xhcitest/Makefile | 35 + drivers/usb/host/xhcitest/xhci-trace.h | 96 drivers/usb/host/xhcitest/xhci-unit-dbg.c |1 drivers/usb/host/xhcitest/xhci-unit-trace.c |2 drivers/usb/host/xhcitest/xhci-unit.c | 641 +++ 9 files changed, 793 insertions(+), 0 deletions(-) create mode 100644 drivers/usb/host/xhcitest/Makefile create mode 100644 drivers/usb/host/xhcitest/xhci-trace.h create mode 100644 drivers/usb/host/xhcitest/xhci-unit-dbg.c create mode 100644 drivers/usb/host/xhcitest/xhci-unit-trace.c create mode 100644 drivers/usb/host/xhcitest/xhci-unit.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 82800a775501..9ac2b817c7e6 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -24,6 +24,19 @@ config USB_XHCI_HCD To compile this driver as a module, choose M here: the module will be called xhci-hcd. +config USB_XHCI_TEST + tristate xHCI Unit Tests + depends on USB_XHCI_HCD!=y + depends on !DEBUG_SG + ---help--- + This module runs sanity checks against the xhci ring + enqueue/dequeue code. + + It really only makes sense to compile this driver as a module, + and only load it when doing xhci driver development. + + Choose M to compile this driver as a module named xhci_test. + if USB_XHCI_HCD config USB_XHCI_PLATFORM diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 144c038ef70f..715c0011a792 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o +obj-$(CONFIG_USB_XHCI_TEST)+= xhcitest/ obj-$(CONFIG_USB_SL811_HCD)+= sl811-hcd.o obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 1fc38ec60c25..febcbbac980e 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -526,6 +526,7 @@ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, (ctx-bytes + CTX_SIZE(xhci-hcc_params)); } +#ifndef XHCI_UNIT struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index) @@ -538,6 +539,7 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, return (struct xhci_ep_ctx *) (ctx-bytes + (ep_index * CTX_SIZE(xhci-hcc_params))); } +#endif /* Streams structures manipulation */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 82a24ce58c3e..13f42ff9f55a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -536,6 +536,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) return 0; } +#ifndef XHCI_UNIT void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, @@ -560,6 +561,7 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, * write-posting flush. It'll get there soon enough. */ } +#endif /* Ring the doorbell for any rings with pending URBs */ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci, diff --git a/drivers/usb/host/xhcitest/Makefile b/drivers/usb/host/xhcitest/Makefile new file mode 100644 index ..b60009b220e8 --- /dev/null +++ b/drivers/usb/host/xhcitest/Makefile @@ -0,0 +1,35 @@ +CFLAGS_xhci-unit-trace.o := -I$(src) + +# Boilplate wrappers for functions defined in xhci.c (not included) +ldflags-y := --wrap=xhci_find_slot_id_by_port +ldflags-y +=
Re: [Bug 80711] [PATCH]SG_FLAG_LUN_INHIBIT is no longer implemented and there's not way to prevent the kernel from using the 2nd cdb byte for the LUN
On Fri, 22 Aug 2014, James Bottomley wrote: On Fri, 2014-08-22 at 10:53 -0400, Alan Stern wrote: Sending the initial INQUIRY command to LUNs larger than 0 involves a chicken-and-egg problem -- we don't know whether to fill in the LUN bits in the command until we know the SCSI level, and we don't know the SCSI level until the INQUIRY response is received. The solution we have been using is to store the most recently discovered level in the target structure, and use it as a default. If probing starts with LUN 0, and if all the LUNs have similar levels, this ought to work. Except for one thing: The code does store the default level in the scsi_target, but forgets to copy it back into each newly allocated scsi_device! I added a line to do that into the patch. --- usb-3.16.orig/include/scsi/scsi_host.h +++ usb-3.16/include/scsi/scsi_host.h @@ -695,6 +695,9 @@ struct Scsi_Host { /* The controller does not support WRITE SAME */ unsigned no_write_same:1; + /* The transport requires the LUN bits NOT to be stored in CDB[1] */ + unsigned no_scsi2_lun_in_cdb:1; I think Christoph mentioned shortening this flag length, but personally I'm not that bothered. It was shorter in the original version of the patch, but I decided to make it a little longer to match the name of the new scsi_device flag added in this version. --- usb-3.16.orig/drivers/scsi/scsi_scan.c +++ usb-3.16/drivers/scsi/scsi_scan.c @@ -257,6 +257,7 @@ static struct scsi_device *scsi_alloc_sd sdev-sdev_gendev.parent = get_device(starget-dev); sdev-sdev_target = starget; + sdev-scsi_level = starget-scsi_level; Why is this necessary? Isn't this set correctly in scsi_probe_lun? The target level is actually set from the device level. The reason was mentioned in the quoted text at the start of this email. In greater detail: Yes, sdev-scsi_level is set correctly in scsi_probe_lun, but only _after_ the INQUIRY data has been received (because the level is part of the INQUIRY data). So how can the INQUIRY CDB be set up correctly before we know the device's level? (When the current code sends an INQUIRY for LUN 1, it will _not_ put the LUN bits in CDB[1] -- even if LUN 0 reported SCSI-2. That doesn't seem right.) My answer is to use a default level copied from the target. The target's level in turn was set from the previously probed device... which means that the first device to be probed gets a default level of SCSI-2. That's okay as long as the first device probed is LUN 0. Hmmm, but now I see the patch doesn't set a default value for the new sdev-lun_in_cdb flag. That needs to be fixed... Other than this, I'm fine with the code ... you can add the acked by from me when we resolve the above question. Okay. It's true that this issue is only tangentially related to the main point of the patch. It could be removed and addressed later. Alan Stern -- 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
Re: [PATCH v2 1/5] ARM: dts: remove old USB2 PHY node hook for Arndale
Am 22.08.2014 18:59, schrieb Bartlomiej Zolnierkiewicz: drivers/usb/phy/phy-samsung-usb2 driver got replaced by drivers/phy/phy-samsung-usb2 one. Remove the leftover hook from Arndale dts file. Signed-off-by: Bartlomiej Zolnierkiewicz b.zolnier...@samsung.com Acked-by: Kyungmin Park kyungmin.p...@samsung.com Reviewed-by: Vivek Gautam gautam.vi...@samsung.com Reviewed-by: Jingoo Han jg1@samsung.com Acked-by: Kishon Vijay Abraham I kis...@ti.com Cc: Mark Brown broo...@linaro.org Cc: Kamil Debski k.deb...@samsung.com --- arch/arm/boot/dts/exynos5250-arndale.dts | 4 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index d0de1f5..dad8f9b 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -570,8 +570,4 @@ connect-gpios = gpd1 7 1; }; }; - - usb@1211 { - usb-phy = usb2_phy; - }; }; This will trivially conflict with my exynos5250 cleanups in the Spring series: ehci {...} there. https://patchwork.kernel.org/patch/4664751/ Regards, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg -- 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
Re: [PATCH 1/1] HID: usbhid: add usb_clear_halt determination for next hid_start_in
hi alan and all: I recently posted (but did not submit) a more comprehensive solution to this and other related problems. For example, HID devices typically run at low speed or full speed. When attached through a hub to an EHCI controller (very common on modern systems), unplugging the device causes -EPIPE errors, so the driver calls usb_clear_halt and restarts the interrupt pipe. Of course, the same failure occurs again, so there's a lengthy flurry of useless error messages. This patch changes the driver so that after usb_clear_halt fails, it will try to do a port reset. And if that fails, the driver will be unbound from the device. This avoids infinite loops. What do you think? Alan Stern Index: usb-3.16/drivers/hid/usbhid/hid-core.c === --- usb-3.16.orig/drivers/hid/usbhid/hid-core.c +++ usb-3.16/drivers/hid/usbhid/hid-core.c @@ -116,40 +116,24 @@ static void hid_reset(struct work_struct struct usbhid_device *usbhid = container_of(work, struct usbhid_device, reset_work); struct hid_device *hid = usbhid-hid; - int rc = 0; + int rc; if (test_bit(HID_CLEAR_HALT, usbhid-iofl)) { dev_dbg(usbhid-intf-dev, clear halt\n); rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid-urbin-pipe); clear_bit(HID_CLEAR_HALT, usbhid-iofl); - hid_start_in(hid); - } - - else if (test_bit(HID_RESET_PENDING, usbhid-iofl)) { - dev_dbg(usbhid-intf-dev, resetting device\n); - rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid-intf); if (rc == 0) { - rc = usb_reset_device(hid_to_usb_dev(hid)); - usb_unlock_device(hid_to_usb_dev(hid)); + hid_start_in(hid); + } else { + dev_dbg(usbhid-intf-dev, + clear-halt failed: %d\n, rc); + set_bit(HID_RESET_PENDING, usbhid-iofl); } - clear_bit(HID_RESET_PENDING, usbhid-iofl); } - switch (rc) { - case 0: - if (!test_bit(HID_IN_RUNNING, usbhid-iofl)) - hid_io_error(hid); - break; - default: - hid_err(hid, can't reset device, %s-%s/input%d, status %d\n, - hid_to_usb_dev(hid)-bus-bus_name, - hid_to_usb_dev(hid)-devpath, - usbhid-ifnum, rc); - /* FALLTHROUGH */ - case -EHOSTUNREACH: - case -ENODEV: - case -EINTR: - break; + if (test_bit(HID_RESET_PENDING, usbhid-iofl)) { + dev_dbg(usbhid-intf-dev, resetting device\n); + usb_queue_reset_device(usbhid-intf); } } from your patch, I have some questions: a. in Alan's version, if both HID_CLEAR_HALT and HID_RESET_PENDING are set, hid_reset will both clear ep halt and reset devcie. But in original one, even HID_CLEAR_HALT and HID_RESET_PENDING are both set, hid_reset only do one of them. is there any special reason in original hid_reset to use below flow? if (test_bit(HID_CLEAR_HALT, usbhid-iofl)) { x } else if (test_bit(HID_RESET_PENDING, usbhid-iofl)) { xx } b. in original hid_reset, if Clear halt ep or Rest device success or none of those flags raise up, it will call hid_io_error for later resending the urb. Shall we need to call hid_io_error(hid); in the end if clear halt or reset device success? c. why we chose to use usb_queue_reset_device instead of usb_reset_device()? d. shall we useusb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid-intf) or spin_lock_irq(usbhid-lock) before calling usb_queue_reset_device? I append patch for explaining my questions. Appreciate your kind help, diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 256b102..aa321f9 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -116,18 +116,22 @@ static void hid_reset(struct work_struct *work) struct usbhid_device *usbhid = container_of(work, struct usbhid_device, reset_work); struct hid_device *hid = usbhid-hid; - int rc = 0; + int rc; if (test_bit(HID_CLEAR_HALT, usbhid-iofl)) { dev_dbg(usbhid-intf-dev, clear halt\n); rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid-urbin-pipe); clear_bit(HID_CLEAR_HALT, usbhid-iofl); - if (rc == 0) + if (rc == 0) { hid_start_in(hid); + } else { + dev_dbg(usbhid-intf-dev, + clear-halt failed: %d\n, rc); + set_bit(HID_RESET_PENDING, usbhid-iofl); +
Re: [PATCH 1/2] leds: usb: Add LED trigger for USB gadget activity
On Fri, Aug 22, 2014 at 4:53 AM, Michal Sojka so...@merica.cz wrote: With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Generally I think one led trigger for both USB host and USB gadget activity is good enough. We don't need 2 same led trigger here. And probably you can just put this code in drivers/usb subsystem, since this driver is quite simple to add to USB subsystem. Thanks, -Bryan Signed-off-by: Michal Sojka so...@merica.cz --- drivers/leds/trigger/Kconfig | 8 ++ drivers/leds/trigger/Makefile| 1 + drivers/leds/trigger/ledtrig-usbgadget.c | 45 drivers/usb/musb/musb_gadget.c | 6 +++-- include/linux/leds.h | 6 + 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 drivers/leds/trigger/ledtrig-usbgadget.c diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 49794b4..9562963 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_USBGADGET + bool LED USB Gadget Trigger + depends on (USB_MUSB_GADGET || USB_MUSB_DUAL_ROLE) + depends on LEDS_TRIGGERS + help + This allows LEDs to be controlled by USB gadget activity. + If unsure, say Y. + config LEDS_TRIGGER_HEARTBEAT tristate LED Heartbeat Trigger depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48d..45917c0 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_USBGADGET) += ledtrig-usbgadget.o diff --git a/drivers/leds/trigger/ledtrig-usbgadget.c b/drivers/leds/trigger/ledtrig-usbgadget.c new file mode 100644 index 000..1eb90da --- /dev/null +++ b/drivers/leds/trigger/ledtrig-usbgadget.c @@ -0,0 +1,45 @@ +/* + * LED Trigger for USB Gadget Activity + * + * Copyright 2014 Michal Sojka so...@merica.cz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include linux/module.h +#include linux/kernel.h +#include linux/init.h +#include linux/leds.h + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_usbgadget); +static unsigned long usbgadget_blink_delay = BLINK_DELAY; + +void ledtrig_usbgadget_activity(void) +{ + led_trigger_blink_oneshot(ledtrig_usbgadget, + usbgadget_blink_delay, usbgadget_blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_usbgadget_activity); + +static int __init ledtrig_usbgadget_init(void) +{ + led_trigger_register_simple(usb-gadget, ledtrig_usbgadget); + return 0; +} + +static void __exit ledtrig_usbgadget_exit(void) +{ + led_trigger_unregister_simple(ledtrig_usbgadget); +} + +module_init(ledtrig_usbgadget_init); +module_exit(ledtrig_usbgadget_exit); + +MODULE_AUTHOR(Michal Sojka so...@merica.cz); +MODULE_DESCRIPTION(LED Trigger for USB Gadget Activity); +MODULE_LICENSE(GPL); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d4aa779..98f8b24 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -42,6 +42,7 @@ #include linux/delay.h #include linux/dma-mapping.h #include linux/slab.h +#include linux/leds.h #include musb_core.h @@ -167,11 +168,12 @@ __acquires(ep-musb-lock) if (!dma_mapping_error(musb-g.dev, request-dma)) unmap_dma_buffer(req, musb); - if (request-status == 0) + if (request-status == 0) { dev_dbg(musb-controller, %s done request %p, %d/%d\n, ep-end_point.name, request, req-request.actual, req-request.length); - else + ledtrig_usbgadget_activity(); + } else dev_dbg(musb-controller, %s request %p, %d/%d fault %d\n, ep-end_point.name, request, req-request.actual, req-request.length, diff --git a/include/linux/leds.h b/include/linux/leds.h index 0287ab2..5d9668e 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h
Re: Trace with v3.17-rc1 while trying to enable power saving for pci device
Hi, I just tried out the current git master (commit 5317821c08) and got the following trace: [ 25.637181] [ cut here ] [ 25.637191] WARNING: CPU: 0 PID: 756 at fs/proc/generic.c:521 remove_proc_entry+0x170/0x180() [ 25.637194] remove_proc_entry: removing non-empty directory 'irq/23', leaking at least 'ehci_hcd:usb4' [ 25.637196] Modules linked in: ecb btusb bluetooth crc16 arc4 iwldvm x86_pkg_temp_thermal mac80211 intel_powerclamp snd_hda_codec_hdmi snd_hda_codec_realtek i915 snd_hda_codec_generic snd_hda_intel intel_rapl coretemp kvm_intel snd_hda_controller snd_hda_codec kvm snd_hwdep iwlwifi psmouse snd_pcm thinkpad_acpi uvcvideo cfg80211 evdev serio_raw nvram snd_timer i2c_algo_bit videobuf2_vmalloc videobuf2_memops drm_kms_helper videobuf2_core snd v4l2_common drm soundcore wmi pcspkr tpm_tis tpm rfkill videodev battery ac video i2c_i801 i2ccore button processor sch_fq fuse autofs4 dm_crypt dm_mod sd_mod crc_t10dif crct10dif_generic crct10dif_pclmul crct10dif_common crc32_pclmul crc32c_intel ghash_clmulni_intel ahci libahci libata scsi_mod ehci_pci ehci_hcd xhci_hcd sdhci_pci e1000e sdhci ptp pps_core mmc_core usbcore thermal usb_common thermal_sys [ 25.637257] CPU: 0 PID: 756 Comm: rc.local Not tainted 3.17.0-rc1+ #1 [ 25.637259] Hardware name: LENOVO 23250BM/23250BM, BIOS G2ETA1WW (2.61 ) 04/22/2014 [ 25.637261] 0009 814b56ef 8800c9b7fc30 8106eb42 [ 25.637265] 880037648c40 8800c9b7fc80 0002 8800c9b7fce6 [ 25.637268] 8800c9b7fce6 8106eba7 81719f08 8830 [ 25.637271] Call Trace: [ 25.637277] [814b56ef] ? dump_stack+0x41/0x51 [ 25.637283] [8106eb42] ? warn_slowpath_common+0x72/0x90 [ 25.637286] [8106eba7] ? warn_slowpath_fmt+0x47/0x50 [ 25.637291] [811da561] ? proc_entry_rundown+0x41/0x80 [ 25.637294] [811de740] ? remove_proc_entry+0x170/0x180 [ 25.637300] [810b7db7] ? unregister_irq_proc+0xb7/0xc0 [ 25.637303] [810b2ab2] ? free_desc+0x22/0x60 [ 25.637307] [810b2b22] ? irq_free_descs+0x32/0x80 [ 25.637312] [810335f4] ? mp_unmap_irq+0x74/0xb0 [ 25.637316] [812d733c] ? do_pci_disable_device+0x4c/0x60 [ 25.637319] [812d7390] ? pci_disable_device+0x40/0xb0 [ 25.637330] [a0038fc2] ? suspend_common+0x52/0x150 [usbcore] [ 25.637335] [812d8ff7] ? pci_pm_runtime_suspend+0x57/0x150 [ 25.637340] [8137e636] ? __rpm_callback+0x26/0x60 [ 25.637343] [8137e688] ? rpm_callback+0x18/0x80 [ 25.637346] [8137f137] ? rpm_suspend+0x107/0x600 [ 25.637350] [810a1c6f] ? __wake_up+0x2f/0x50 [ 25.637353] [8137fcad] ? pm_runtime_allow+0x4d/0x50 [ 25.637357] [8137c75d] ? control_store+0xbd/0xc0 [ 25.637361] [811e91bb] ? kernfs_fop_write+0xdb/0x160 [ 25.637365] [811835ed] ? vfs_write+0xad/0x1e0 [ 25.637368] [811840fd] ? SyS_write+0x3d/0xa0 [ 25.637373] [814bb052] ? system_call_fastpath+0x16/0x1b [ 25.637375] ---[ end trace 40fa9ae9acda7087 ]--- I get the trace due to enabling power saving via 'echo 'auto' /sys/bus/pci/devices/:00:1d.0/power/control' with 00:1d.0 being the USB controller (according to lspci): 00:1d.0 USB controller [0c03]: Intel Corporation 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 [8086:1e26] (rev 04) If you need more information, please do not hesitate to ask. Inspired by commit c5946f9d286, which mentions a similar problem, I tried the following: diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index efc953119ce2..c5160bcaa790 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -361,6 +361,7 @@ void usb_hcd_pci_remove(struct pci_dev *dev) } usb_put_hcd(hcd); + free_irq(hcd-irq, hcd); pci_disable_device(dev); } EXPORT_SYMBOL_GPL(usb_hcd_pci_remove); But this did not work, so maybe somebody, who actually knows this code should have a look at this. With best regards, Julian Wollrath -- 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
Re: [RFC PATCH 19/20] xhci: v1.0 scatterlist enqueue support (td-fragment rework)
On Fri, 22 Aug 2014, Dan Williams wrote: v1.0 hosts require that TD-fragments (portions of a TD that do not end on a MPB boundary) not cross a TRB segment boundary. This constraint is in addition to the constraint that a TRB may not specify a transfer that crosses a 64K boundary. This enabling permits the driver to accept scatterlists of nearly any geometry. Nearly because there is one unlikely remaining degenerate case of a driver submitting a transfer that consumes all the TRBs in a segment before hitting an MBP boundary. That case is trapped and the transfer is rejected. That last part sounds problematic. The issue will arise at unpredictable times, depending on the lengths of the scatterlists that have been submitted in the past, so it's not easily reproducible. What is the caller supposed to do when this happens? As for the likelihood of this occurring... A ring segment is one page, so 4096 bytes. Each TRB is 16 bytes, so a segment can hold 256 TRBs. With a bulk maxpacket size of 1024 and a (typical?) maxburst size of 8, MPB boundaries occur every 8192 bytes. Therefore if a scatterlist contains more than 256 entries, with an average length 32 bytes, it is likely trigger this condition (depending on the exact alignment with respect to the MPB boundary). I don't know exactly how unlikely such a situation is, but it's not hard to imagine a network packet composed of lots of little pieces. Instead of failing the submission, we ought to set up some sort of bounce buffers. I have no good suggestions on how to implement that, however. Alan Stern -- 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
Re: [PATCH 1/1] HID: usbhid: add usb_clear_halt determination for next hid_start_in
On Sat, 23 Aug 2014, vichy wrote: from your patch, I have some questions: a. in Alan's version, if both HID_CLEAR_HALT and HID_RESET_PENDING are set, hid_reset will both clear ep halt and reset devcie. But in original one, even HID_CLEAR_HALT and HID_RESET_PENDING are both set, hid_reset only do one of them. Yes. In my patch, the clear-halt handler will turn on the HID_RESET_PENDING bit if something goes wrong. In that case we want to do both things. is there any special reason in original hid_reset to use below flow? if (test_bit(HID_CLEAR_HALT, usbhid-iofl)) { x } else if (test_bit(HID_RESET_PENDING, usbhid-iofl)) { xx } No special reason. We probably never thought that both flags would be set. b. in original hid_reset, if Clear halt ep or Rest device success or none of those flags raise up, it will call hid_io_error for later resending the urb. No, the clear-halt part calls hid_start_in when everything works. It doesn't call hid_io_error, because hid_start_in turns on the HID_IN_RUNNING flag. Shall we need to call hid_io_error(hid); in the end if clear halt or reset device success? In the clear-halt case, we don't have to because we call hid_start_in. In the reset device case, we don't have to because hid_post_reset calls hid_start_in if there are no errors. c. why we chose to use usb_queue_reset_device instead of usb_reset_device()? I originally tried using usb_reset_device, and it caused a deadlock: Unplug the HID device. I/O error occurs. hid_io_error schedules reset_work. The reset_work callback routine is hid_reset. It calls usb_reset_device. The reset fails because the device is gone. At the end of the reset, hid_post_reset is called. hid_post_reset returns 1 because hid_get_class_descriptor fails. Because the post_reset routine failed, usb_reset_device calls usb_unbind_and_rebind_marked_interfaces. That routine indirectly calls usbhid_disconnect. usbhid_disconnect calls usbhid_close by way of hid_destroy_device. usbhid_close calls hid_cancel_delayed_stuff. hid_cancel_delayed_stuff calls cancel_work_sync for reset_work. So the reset_work routine tries to cancel itself synchronously while it is running. usb_queue_reset_device was carefully written to avoid such deadlocks. d. shall we useusb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid-intf) or spin_lock_irq(usbhid-lock) before calling usb_queue_reset_device? No. usb_queue_reset_device takes care of the locking. Alan Stern -- 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
Re: Kernel 3.16.0 USB crash
Hi, On 08/15/2014 09:44 AM, Claudio Bizzarri wrote: On Thu, Aug 14, 2014 at 11:46:33AM +0200, Hans de Goede wrote: Hi, ... Can you collect lsusb -v output for the drive in question when connected through an usb-3 port (the uas module does not need to be loaded). Here lsusb output, full text as attachment Thanks. Bus 003 Device 003: ID 152d:0567 JMicron Technology Corp. / JMicron USA Technology Corp. Device Descriptor: bLength18 bDescriptorType 1 bcdUSB 3.00 bDeviceClass0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 9 idVendor 0x152d JMicron Technology Corp. / JMicron USA Technology Corp. idProduct 0x0567 bcdDevice0.00 iManufacturer 10 JMicron iProduct 11 USB to ATA/ATAPI Bridge iSerial 5 152D00539000 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 121 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xc0 Self Powered MaxPower2mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk-Only iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 15 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 15 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber0 bAlternateSetting 1 bNumEndpoints 4 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 98 iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x01 EP 1 OUT bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 0 Command pipe (0x01) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 0 MaxStreams 32 32, ok that is the amount which we know jmicron chips can handle over usb-2, so one would expect that having 32 outstanding commands will work when connected over usb-3 too. Status pipe (0x02) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x83 EP 3 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 15 MaxStreams 32 Data-in pipe (0x03) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x04 EP 4 OUT bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 15 MaxStreams 32 Data-out pipe (0x04) Binary Object Store Descriptor: bLength 5 bDescriptorType15 wTotalLength
Re: [PATCH v2] usb: dwc3: add tracepoints to aid debugging
Hi, On Tue, Aug 19, 2014 at 11:36:05PM +, Paul Zimmerman wrote: From: Felipe Balbi [mailto:ba...@ti.com] Sent: Tuesday, August 19, 2014 3:02 PM I didn't have time to test this yet (other than build testing), but how does this one look ? Now we will print cute little strings for all events and we still have proper link state tracking. 8- From 513ba489d66ff81eca056b41fda0cc965e6fe3ed Mon Sep 17 00:00:00 2001 From: Felipe Balbi ba...@ti.com Date: Wed, 30 Apr 2014 17:45:10 -0500 Subject: [PATCH] usb: dwc3: add tracepoints to aid debugging When we're debugging hard-to-reproduce and time-sensitive use cases, printk() poses too much overhead. That's when the kernel's tracing infrastructure comes into play. This patch implements a few initial tracepoints for the dwc3 driver. More traces can be added as necessary in order to ease the task of debugging dwc3. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/dwc3/Makefile | 5 +- drivers/usb/dwc3/core.h | 2 + drivers/usb/dwc3/debug.c | 73 ++ drivers/usb/dwc3/debug.h | 5 ++ drivers/usb/dwc3/ep0.c| 2 + drivers/usb/dwc3/gadget.c | 27 +- drivers/usb/dwc3/io.h | 30 +-- drivers/usb/dwc3/trace.c | 19 +++ drivers/usb/dwc3/trace.h | 128 ++ 9 files changed, 272 insertions(+), 19 deletions(-) create mode 100644 drivers/usb/dwc3/debug.c create mode 100644 drivers/usb/dwc3/trace.c create mode 100644 drivers/usb/dwc3/trace.h diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 10ac3e7..7793e6c 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,9 +1,12 @@ +# define_trace.h needs to know how to find our header +CFLAGS_trace.o := -I$(src) + ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG obj-$(CONFIG_USB_DWC3) += dwc3.o -dwc3-y := core.o +dwc3-y := core.o debug.o trace.o ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += host.o diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 48fb264..dbdad87 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -33,6 +33,8 @@ #include linux/phy/phy.h +#define DWC3_MSG_MAX 500 + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 diff --git a/drivers/usb/dwc3/debug.c b/drivers/usb/dwc3/debug.c new file mode 100644 index 000..6e109ce --- /dev/null +++ b/drivers/usb/dwc3/debug.c @@ -0,0 +1,73 @@ +/** + * debug.c - DesignWare USB3 DRD Controller Debug/Trace Support + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Felipe Balbi ba...@ti.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include core.h +#include debug.h + +static char event_str[DWC3_MSG_MAX]; + +static void dwc3_endpoint_event_str(struct dwc3 *dwc, + const struct dwc3_event_depevt *event) +{ + struct dwc3_ep *dep = dwc-eps[event-endpoint_number]; + + snprintf(event_str, DWC3_MSG_MAX, %s %s, dep-name, + dwc3_ep_event_string(event-endpoint_event)); Maybe you should also include the raw event data in the trace? Some of the other bits in the event besides the event number can tell you useful things while debugging. I changed this to print only the raw event code. It's not that difficult to decode by hand anyways and makes the code a lot simpler. We can add decoding later if it really becomes annoying. In any case here's another version, I also changed a few things in ep0, there are no more dev_{v,}dbg inside ep0.c, this is so that we avoid high overhead while debugging ep0 (which can be finicky at times). Anyway, please give it another round of review. And as always, if there's anything we might wanna add, please speak up :-) 8 From b38435444c882a94b011e28da0f094ce98aeee59 Mon Sep 17 00:00:00 2001 From: Felipe Balbi ba...@ti.com Date: Wed, 30 Apr 2014 17:45:10 -0500 Subject: [PATCH] usb: dwc3: add tracepoints to aid debugging When
RE: [PATCHv2 10/13] usb: dwc2: initialize the spin_lock for both host and gadget
From: dingu...@altera.com [mailto:dingu...@altera.com] Sent: Wednesday, July 30, 2014 8:21 AM Move spin_lock_init to common location for both host and gadget. Signed-off-by: Dinh Nguyen dingu...@altera.com --- drivers/usb/dwc2/hcd.c |1 - drivers/usb/dwc2/platform.c |1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 07a7bcd..c6778d9 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2824,7 +2824,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, hcd-has_tt = 1; - spin_lock_init(hsotg-lock); ((struct wrapper_priv_data *) hcd-hcd_priv)-hsotg = hsotg; hsotg-priv = hcd; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index eb2a131..4898268 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -197,6 +197,7 @@ static int dwc2_driver_probe(struct platform_device *dev) } platform_set_drvdata(dev, hsotg); + spin_lock_init(hsotg-lock); return retval; } Hi Dinh, I don't have a copy of your v3 patches in my mailbox anymore, so I am replying to the v2 one instead. Are you absolutely sure that no code that takes the spinlock can be called before this point? This is the last line in the probe() function, so I have a hard time believing it is safe to initialize the spinlock this late. In particular, the IRQ has already been attached, and usb_add_gadget_udc() has already been called. So it seems entirely possible that some other entity could try to access the driver before this point. The same comment applies to your Update pci portion of the dwc2 driver patch. -- Paul -- 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
Re: [RFC PATCH 19/20] xhci: v1.0 scatterlist enqueue support (td-fragment rework)
On Fri, Aug 22, 2014 at 10:57 AM, Alan Stern st...@rowland.harvard.edu wrote: On Fri, 22 Aug 2014, Dan Williams wrote: v1.0 hosts require that TD-fragments (portions of a TD that do not end on a MPB boundary) not cross a TRB segment boundary. This constraint is in addition to the constraint that a TRB may not specify a transfer that crosses a 64K boundary. This enabling permits the driver to accept scatterlists of nearly any geometry. Nearly because there is one unlikely remaining degenerate case of a driver submitting a transfer that consumes all the TRBs in a segment before hitting an MBP boundary. That case is trapped and the transfer is rejected. That last part sounds problematic. The issue will arise at unpredictable times, depending on the lengths of the scatterlists that have been submitted in the past, so it's not easily reproducible. What is the caller supposed to do when this happens? As for the likelihood of this occurring... A ring segment is one page, so 4096 bytes. Each TRB is 16 bytes, so a segment can hold 256 TRBs. With a bulk maxpacket size of 1024 and a (typical?) maxburst size of 8, MPB boundaries occur every 8192 bytes. Therefore if a scatterlist contains more than 256 entries, with an average length 32 bytes, it is likely trigger this condition (depending on the exact alignment with respect to the MPB boundary). I don't know exactly how unlikely such a situation is, but it's not hard to imagine a network packet composed of lots of little pieces. Instead of failing the submission, we ought to set up some sort of bounce buffers. I have no good suggestions on how to implement that, however. Yes. I was hoping to cross that bridge when we come to it. Currently, we silently send something down that the hardware can't handle, so at least it's caught and reported. Bounce buffers... or urb splitting... but yes I have no idea how frequent something pathological like this gets sent down all in one urb. -- 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
Re: [PATCHv2 10/13] usb: dwc2: initialize the spin_lock for both host and gadget
Hi, On Fri, Aug 22, 2014 at 08:52:23PM +, Paul Zimmerman wrote: From: dingu...@altera.com [mailto:dingu...@altera.com] Sent: Wednesday, July 30, 2014 8:21 AM Move spin_lock_init to common location for both host and gadget. Signed-off-by: Dinh Nguyen dingu...@altera.com --- drivers/usb/dwc2/hcd.c |1 - drivers/usb/dwc2/platform.c |1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 07a7bcd..c6778d9 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2824,7 +2824,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, hcd-has_tt = 1; - spin_lock_init(hsotg-lock); ((struct wrapper_priv_data *) hcd-hcd_priv)-hsotg = hsotg; hsotg-priv = hcd; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index eb2a131..4898268 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -197,6 +197,7 @@ static int dwc2_driver_probe(struct platform_device *dev) } platform_set_drvdata(dev, hsotg); + spin_lock_init(hsotg-lock); return retval; } Hi Dinh, I don't have a copy of your v3 patches in my mailbox anymore, so I am replying to the v2 one instead. Are you absolutely sure that no code that takes the spinlock can be called before this point? This is the last line in the probe() function, so I have a hard time believing it is safe to initialize the spinlock this late. In particular, the IRQ has already been attached, and usb_add_gadget_udc() has already been called. So it seems entirely possible that some other entity could try to access the driver before this point. you're right with this comment. request_irq() enables the IRQ line and it could be that we already have a pending event to handle which fires as soon as we enable that IRQ line. -- balbi signature.asc Description: Digital signature
RE: [PATCH v2] usb: dwc3: add tracepoints to aid debugging
From: Felipe Balbi [mailto:ba...@ti.com] Sent: Friday, August 22, 2014 1:47 PM On Tue, Aug 19, 2014 at 11:36:05PM +, Paul Zimmerman wrote: From: Felipe Balbi ba...@ti.com Date: Wed, 30 Apr 2014 17:45:10 -0500 diff --git a/drivers/usb/dwc3/debug.c b/drivers/usb/dwc3/debug.c new file mode 100644 index 000..6e109ce --- /dev/null +++ b/drivers/usb/dwc3/debug.c @@ -0,0 +1,73 @@ +/** + * debug.c - DesignWare USB3 DRD Controller Debug/Trace Support + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Felipe Balbi ba...@ti.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include core.h +#include debug.h + +static char event_str[DWC3_MSG_MAX]; + +static void dwc3_endpoint_event_str(struct dwc3 *dwc, + const struct dwc3_event_depevt *event) +{ + struct dwc3_ep *dep = dwc-eps[event-endpoint_number]; + + snprintf(event_str, DWC3_MSG_MAX, %s %s, dep-name, + dwc3_ep_event_string(event-endpoint_event)); Maybe you should also include the raw event data in the trace? Some of the other bits in the event besides the event number can tell you useful things while debugging. I changed this to print only the raw event code. It's not that difficult to decode by hand anyways and makes the code a lot simpler. We can add decoding later if it really becomes annoying. In any case here's another version, I also changed a few things in ep0, there are no more dev_{v,}dbg inside ep0.c, this is so that we avoid high overhead while debugging ep0 (which can be finicky at times). Anyway, please give it another round of review. And as always, if there's anything we might wanna add, please speak up :-) 8 From b38435444c882a94b011e28da0f094ce98aeee59 Mon Sep 17 00:00:00 2001 From: Felipe Balbi ba...@ti.com Date: Wed, 30 Apr 2014 17:45:10 -0500 Subject: [PATCH] usb: dwc3: add tracepoints to aid debugging When we're debugging hard-to-reproduce and time-sensitive use cases, printk() poses too much overhead. That's when the kernel's tracing infrastructure comes into play. This patch implements a few initial tracepoints for the dwc3 driver. More traces can be added as necessary in order to ease the task of debugging dwc3. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/dwc3/Makefile | 5 +- drivers/usb/dwc3/core.h | 2 + drivers/usb/dwc3/debug.c | 33 +++ drivers/usb/dwc3/debug.h | 3 + drivers/usb/dwc3/ep0.c| 65 - drivers/usb/dwc3/gadget.c | 24 +++- drivers/usb/dwc3/io.h | 30 +- drivers/usb/dwc3/trace.c | 19 ++ drivers/usb/dwc3/trace.h | 143 ++ 9 files changed, 277 insertions(+), 47 deletions(-) create mode 100644 drivers/usb/dwc3/debug.c create mode 100644 drivers/usb/dwc3/trace.c create mode 100644 drivers/usb/dwc3/trace.h diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 10ac3e7..7793e6c 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,9 +1,12 @@ +# define_trace.h needs to know how to find our header +CFLAGS_trace.o := -I$(src) + ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG obj-$(CONFIG_USB_DWC3) += dwc3.o -dwc3-y := core.o +dwc3-y := core.o debug.o trace.o ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += host.o diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 48fb264..dbdad87 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -33,6 +33,8 @@ #include linux/phy/phy.h +#define DWC3_MSG_MAX 500 + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 diff --git a/drivers/usb/dwc3/debug.c b/drivers/usb/dwc3/debug.c new file mode 100644 index 000..6d01e0c --- /dev/null +++ b/drivers/usb/dwc3/debug.c @@ -0,0 +1,33 @@ +/** + * debug.c - DesignWare USB3 DRD Controller Debug/Trace Support + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Felipe Balbi ba...@ti.com + * + * This program is free software: you can
Re: [PATCH 1/2] leds: usb: Add LED trigger for USB gadget activity
On Fri, Aug 22, 2014 at 10:39:03AM -0700, Bryan Wu wrote: On Fri, Aug 22, 2014 at 4:53 AM, Michal Sojka so...@merica.cz wrote: With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Generally I think one led trigger for both USB host and USB gadget activity is good enough. We don't need 2 same led trigger here. What about systems that have both running at the same time? Don't you want individual control? And probably you can just put this code in drivers/usb subsystem, since this driver is quite simple to add to USB subsystem. I have no objection to that, if the LED people don't mind it. thanks, greg k-h -- 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
Re: [PATCH v2] usb: dwc3: add tracepoints to aid debugging
Hi, On Fri, Aug 22, 2014 at 09:26:55PM +, Paul Zimmerman wrote: diff --git a/drivers/usb/dwc3/debug.c b/drivers/usb/dwc3/debug.c new file mode 100644 index 000..6d01e0c --- /dev/null +++ b/drivers/usb/dwc3/debug.c @@ -0,0 +1,33 @@ +/** + * debug.c - DesignWare USB3 DRD Controller Debug/Trace Support + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Felipe Balbi ba...@ti.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include debug.h + +void dwc3_trace(void (*trace)(struct va_format *), + const char *fmt, ...) Unnecessary line wrap? It looks like this would fit on one line. fixed all three instances @@ -726,6 +732,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, if (!dwc-gadget_driver) goto out; + trace_dwc3_ctrl_req(ctrl); I don't see this function defined anywhere in this patch. Same for some of the other trace functions. I guess these are automatically defined by some tracing macro magic? Is there any way to see what the event yup, you got it. If you look at trace.h, it defines all the trace points and on trace.c where we have: #define CREATE_TRACE_POINTS #include trace.h that'll cause the creation of all these functions. will look like short of running the code? These are probably dumb questions, but I haven't done anything yet with the tracing API, so I'm pretty clueless about it. Next week I'll send you a sample output with all events enabled :-) Other than that, I can't think of anything else to be added at this point. As you say, other trace points can be added later if desired. Right, I wanted to have a way of using those debug registers (GDBG*) for tracing the internal HW blocks but there's no documentation about what those registers mean i.e. how to decode the data returned by them. Other than that... we might want to, at some point, have a more granular tracing of the TRB/usb_request lifetime - right now we're only tracing alloc, queue, dequeue, free - but I guess tracing request accesses alone is already a pretty good deal, as it can help communicating with IP folks and giving them a sequence of events for writing RTL simulation :-) cheers -- balbi signature.asc Description: Digital signature
Re: [PATCH 1/2] leds: usb: Add LED trigger for USB gadget activity
Hi, On Fri, Aug 22, 2014 at 01:53:12PM +0200, Michal Sojka wrote: With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Signed-off-by: Michal Sojka so...@merica.cz --- drivers/leds/trigger/Kconfig | 8 ++ drivers/leds/trigger/Makefile| 1 + drivers/leds/trigger/ledtrig-usbgadget.c | 45 drivers/usb/musb/musb_gadget.c | 6 +++-- include/linux/leds.h | 6 + 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 drivers/leds/trigger/ledtrig-usbgadget.c diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 49794b4..9562963 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_USBGADGET + bool LED USB Gadget Trigger + depends on (USB_MUSB_GADGET || USB_MUSB_DUAL_ROLE) + depends on LEDS_TRIGGERS + help + This allows LEDs to be controlled by USB gadget activity. + If unsure, say Y. + config LEDS_TRIGGER_HEARTBEAT tristate LED Heartbeat Trigger depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48d..45917c0 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU)+= ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)+= ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA)+= ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_USBGADGET) += ledtrig-usbgadget.o diff --git a/drivers/leds/trigger/ledtrig-usbgadget.c b/drivers/leds/trigger/ledtrig-usbgadget.c new file mode 100644 index 000..1eb90da --- /dev/null +++ b/drivers/leds/trigger/ledtrig-usbgadget.c @@ -0,0 +1,45 @@ +/* + * LED Trigger for USB Gadget Activity + * + * Copyright 2014 Michal Sojka so...@merica.cz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include linux/module.h +#include linux/kernel.h +#include linux/init.h +#include linux/leds.h + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_usbgadget); +static unsigned long usbgadget_blink_delay = BLINK_DELAY; + +void ledtrig_usbgadget_activity(void) +{ + led_trigger_blink_oneshot(ledtrig_usbgadget, + usbgadget_blink_delay, usbgadget_blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_usbgadget_activity); + +static int __init ledtrig_usbgadget_init(void) +{ + led_trigger_register_simple(usb-gadget, ledtrig_usbgadget); + return 0; +} + +static void __exit ledtrig_usbgadget_exit(void) +{ + led_trigger_unregister_simple(ledtrig_usbgadget); +} + +module_init(ledtrig_usbgadget_init); +module_exit(ledtrig_usbgadget_exit); + +MODULE_AUTHOR(Michal Sojka so...@merica.cz); +MODULE_DESCRIPTION(LED Trigger for USB Gadget Activity); +MODULE_LICENSE(GPL); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d4aa779..98f8b24 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -42,6 +42,7 @@ #include linux/delay.h #include linux/dma-mapping.h #include linux/slab.h +#include linux/leds.h #include musb_core.h @@ -167,11 +168,12 @@ __acquires(ep-musb-lock) if (!dma_mapping_error(musb-g.dev, request-dma)) unmap_dma_buffer(req, musb); - if (request-status == 0) + if (request-status == 0) { dev_dbg(musb-controller, %s done request %p, %d/%d\n, ep-end_point.name, request, req-request.actual, req-request.length); - else + ledtrig_usbgadget_activity(); looks like this should, somehow, be done at udc-core.c although you'd need some refactoring to make that happen. It shouldn't be too difficult to have a generic usb_gadget_giveback_request() cheers -- balbi signature.asc Description: Digital signature
Re: [PATCH 1/2] leds: usb: Add LED trigger for USB gadget activity
On Fri, Aug 22, 2014 at 2:42 PM, Greg Kroah-Hartman gre...@linuxfoundation.org wrote: On Fri, Aug 22, 2014 at 10:39:03AM -0700, Bryan Wu wrote: On Fri, Aug 22, 2014 at 4:53 AM, Michal Sojka so...@merica.cz wrote: With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Generally I think one led trigger for both USB host and USB gadget activity is good enough. We don't need 2 same led trigger here. What about systems that have both running at the same time? Don't you want individual control? Actually I wanted to say we don't need 2 same driver for USB host and USB gadget but one driver which has 2 led triggers like usb_host_ledtrig and usb_gadget_ledtrig. I think drivers/net/can/led.c is a good example to start. And probably you can just put this code in drivers/usb subsystem, since this driver is quite simple to add to USB subsystem. I have no objection to that, if the LED people don't mind it. Because logically it's only used by USB subsystem and it can be a core component of USB, also drivers/net/can/led.c is a good example. Thanks, -Bryan -- 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
Re: [PATCH 1/2] leds: usb: Add LED trigger for USB gadget activity
On Fri, Aug 22 2014, Greg Kroah-Hartman wrote: On Fri, Aug 22, 2014 at 10:39:03AM -0700, Bryan Wu wrote: On Fri, Aug 22, 2014 at 4:53 AM, Michal Sojka so...@merica.cz wrote: With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Generally I think one led trigger for both USB host and USB gadget activity is good enough. We don't need 2 same led trigger here. What about systems that have both running at the same time? Don't you want individual control? Yes, I have a device with two USB connectors (host, device) and a LED next to each. From the LEDs it should be clear, which connector is being used. Thanks, -Michal -- 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
Re: [PATCH 1/2] leds: usb: Add LED trigger for USB gadget activity
Hi Felipe, On Fri, Aug 22 2014, Felipe Balbi wrote: Hi, On Fri, Aug 22, 2014 at 01:53:12PM +0200, Michal Sojka wrote: With this patch, USB gadget activity can be signaled by blinking a LED. Since there is no generic code where to put the trigger for all USB controllers, each USB controller needs to call the trigger individually. This patch adds the call only for the musb controller where I can test it. Signed-off-by: Michal Sojka so...@merica.cz --- drivers/leds/trigger/Kconfig | 8 ++ drivers/leds/trigger/Makefile| 1 + drivers/leds/trigger/ledtrig-usbgadget.c | 45 drivers/usb/musb/musb_gadget.c | 6 +++-- include/linux/leds.h | 6 + 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 drivers/leds/trigger/ledtrig-usbgadget.c diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 49794b4..9562963 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_USBGADGET +bool LED USB Gadget Trigger +depends on (USB_MUSB_GADGET || USB_MUSB_DUAL_ROLE) +depends on LEDS_TRIGGERS +help + This allows LEDs to be controlled by USB gadget activity. + If unsure, say Y. + config LEDS_TRIGGER_HEARTBEAT tristate LED Heartbeat Trigger depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48d..45917c0 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)+= ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_USBGADGET)+= ledtrig-usbgadget.o diff --git a/drivers/leds/trigger/ledtrig-usbgadget.c b/drivers/leds/trigger/ledtrig-usbgadget.c new file mode 100644 index 000..1eb90da --- /dev/null +++ b/drivers/leds/trigger/ledtrig-usbgadget.c @@ -0,0 +1,45 @@ +/* + * LED Trigger for USB Gadget Activity + * + * Copyright 2014 Michal Sojka so...@merica.cz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include linux/module.h +#include linux/kernel.h +#include linux/init.h +#include linux/leds.h + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_usbgadget); +static unsigned long usbgadget_blink_delay = BLINK_DELAY; + +void ledtrig_usbgadget_activity(void) +{ +led_trigger_blink_oneshot(ledtrig_usbgadget, + usbgadget_blink_delay, usbgadget_blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_usbgadget_activity); + +static int __init ledtrig_usbgadget_init(void) +{ +led_trigger_register_simple(usb-gadget, ledtrig_usbgadget); +return 0; +} + +static void __exit ledtrig_usbgadget_exit(void) +{ +led_trigger_unregister_simple(ledtrig_usbgadget); +} + +module_init(ledtrig_usbgadget_init); +module_exit(ledtrig_usbgadget_exit); + +MODULE_AUTHOR(Michal Sojka so...@merica.cz); +MODULE_DESCRIPTION(LED Trigger for USB Gadget Activity); +MODULE_LICENSE(GPL); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d4aa779..98f8b24 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -42,6 +42,7 @@ #include linux/delay.h #include linux/dma-mapping.h #include linux/slab.h +#include linux/leds.h #include musb_core.h @@ -167,11 +168,12 @@ __acquires(ep-musb-lock) if (!dma_mapping_error(musb-g.dev, request-dma)) unmap_dma_buffer(req, musb); -if (request-status == 0) +if (request-status == 0) { dev_dbg(musb-controller, %s done request %p, %d/%d\n, ep-end_point.name, request, req-request.actual, req-request.length); -else +ledtrig_usbgadget_activity(); looks like this should, somehow, be done at udc-core.c although you'd need some refactoring to make that happen. It shouldn't be too difficult to have a generic usb_gadget_giveback_request() I'm sending a second version, where it is moved to udc directory. I'll look at refactoring next week. Thanks, -Michal -- 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