forked from Minki/linux
USB fixes for 5.14-rc3
Here are some USB fixes for 5.14-rc3 to resolve a bunch of tiny problems reported. Included in here are: - dtsi revert to resolve a problem which broke android systems that relied on the dts name to find the USB controller device. People are still working out the "real" solution for this, but for now the revert is needed. - core USB fix for pipe calculation found by syzbot - typec fixes - gadget driver fixes - new usb-serial device ids - new USB quirks - xhci fixes - usb hub fixes for power management issues reported - other tiny fixes All have been in linux-next with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYPrXzA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymtAQCeLCwOQUwwi3b/GIHW9Ik92eAB2C8AoNf1GZW3 NBb8mwFi7bZgANICyG7v =65r/ -----END PGP SIGNATURE----- Merge tag 'usb-5.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are some USB fixes for 5.14-rc3 to resolve a bunch of tiny problems reported. Included in here are: - dtsi revert to resolve a problem which broke android systems that relied on the dts name to find the USB controller device. People are still working out the "real" solution for this, but for now the revert is needed. - core USB fix for pipe calculation found by syzbot - typec fixes - gadget driver fixes - new usb-serial device ids - new USB quirks - xhci fixes - usb hub fixes for power management issues reported - other tiny fixes All have been in linux-next with no reported problems" * tag 'usb-5.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (27 commits) USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick Revert "USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem" usb: cdc-wdm: fix build error when CONFIG_WWAN_CORE is not set Revert "arm64: dts: qcom: Harmonize DWC USB3 DT nodes name" usb: dwc2: gadget: Fix sending zero length packet in DDMA mode. usb: dwc2: Skip clock gating on Samsung SoCs usb: renesas_usbhs: Fix superfluous irqs happen after usb_pkt_pop() usb: dwc2: gadget: Fix GOUTNAK flow for Slave mode. usb: phy: Fix page fault from usb_phy_uevent usb: xhci: avoid renesas_usb_fw.mem when it's unusable usb: gadget: u_serial: remove WARN_ON on null port usb: dwc3: avoid NULL access of usb_gadget_driver usb: max-3421: Prevent corruption of freed memory usb: gadget: Fix Unbalanced pm_runtime_enable in tegra_xudc_probe MAINTAINERS: repair reference in USB IP DRIVER FOR HISILICON KIRIN 970 usb: typec: stusb160x: Don't block probing of consumer of "connector" nodes usb: typec: stusb160x: register role switch before interrupt registration USB: usb-storage: Add LaCie Rugged USB3-FW to IGNORE_UAS usb: ehci: Prevent missed ehci interrupts with edge-triggered MSI usb: hub: Disable USB 3 device initiated lpm if exit latency is too high ...
This commit is contained in:
commit
74738c556d
@ -19123,7 +19123,7 @@ M: Mauro Carvalho Chehab <mchehab@kernel.org>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
|
||||
F: drivers/phy/hisilicon/phy-kirin970-usb3.c
|
||||
F: drivers/phy/hisilicon/phy-hi3670-usb3.c
|
||||
|
||||
USB ISP116X DRIVER
|
||||
M: Olav Kongas <ok@artecdesign.ee>
|
||||
|
@ -1063,7 +1063,7 @@
|
||||
status = "okay";
|
||||
extcon = <&usb2_id>;
|
||||
|
||||
usb@7600000 {
|
||||
dwc3@7600000 {
|
||||
extcon = <&usb2_id>;
|
||||
dr_mode = "otg";
|
||||
maximum-speed = "high-speed";
|
||||
@ -1074,7 +1074,7 @@
|
||||
status = "okay";
|
||||
extcon = <&usb3_id>;
|
||||
|
||||
usb@6a00000 {
|
||||
dwc3@6a00000 {
|
||||
extcon = <&usb3_id>;
|
||||
dr_mode = "otg";
|
||||
};
|
||||
|
@ -443,7 +443,7 @@
|
||||
resets = <&gcc GCC_USB0_BCR>;
|
||||
status = "disabled";
|
||||
|
||||
dwc_0: usb@8a00000 {
|
||||
dwc_0: dwc3@8a00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x8a00000 0xcd00>;
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -484,7 +484,7 @@
|
||||
resets = <&gcc GCC_USB1_BCR>;
|
||||
status = "disabled";
|
||||
|
||||
dwc_1: usb@8c00000 {
|
||||
dwc_1: dwc3@8c00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x8c00000 0xcd00>;
|
||||
interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -2566,7 +2566,7 @@
|
||||
power-domains = <&gcc USB30_GDSC>;
|
||||
status = "disabled";
|
||||
|
||||
usb@6a00000 {
|
||||
dwc3@6a00000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x06a00000 0xcc00>;
|
||||
interrupts = <0 131 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -2873,7 +2873,7 @@
|
||||
qcom,select-utmi-as-pipe-clk;
|
||||
status = "disabled";
|
||||
|
||||
usb@7600000 {
|
||||
dwc3@7600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x07600000 0xcc00>;
|
||||
interrupts = <0 138 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -1964,7 +1964,7 @@
|
||||
|
||||
resets = <&gcc GCC_USB_30_BCR>;
|
||||
|
||||
usb3_dwc3: usb@a800000 {
|
||||
usb3_dwc3: dwc3@a800000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x0a800000 0xcd00>;
|
||||
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -337,7 +337,7 @@
|
||||
&usb3 {
|
||||
status = "okay";
|
||||
|
||||
usb@7580000 {
|
||||
dwc3@7580000 {
|
||||
dr_mode = "host";
|
||||
};
|
||||
};
|
||||
|
@ -544,7 +544,7 @@
|
||||
assigned-clock-rates = <19200000>, <200000000>;
|
||||
status = "disabled";
|
||||
|
||||
usb@7580000 {
|
||||
dwc3@7580000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x07580000 0xcd00>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -573,7 +573,7 @@
|
||||
assigned-clock-rates = <19200000>, <133333333>;
|
||||
status = "disabled";
|
||||
|
||||
usb@78c0000 {
|
||||
dwc3@78c0000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0x078c0000 0xcc00>;
|
||||
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -2756,7 +2756,7 @@
|
||||
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3 0>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
|
||||
usb_1_dwc3: usb@a600000 {
|
||||
usb_1_dwc3: dwc3@a600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a600000 0 0xe000>;
|
||||
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -3781,7 +3781,7 @@
|
||||
<&gladiator_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_0 0>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
|
||||
usb_1_dwc3: usb@a600000 {
|
||||
usb_1_dwc3: dwc3@a600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a600000 0 0xcd00>;
|
||||
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -3829,7 +3829,7 @@
|
||||
<&gladiator_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3_1 0>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
|
||||
usb_2_dwc3: usb@a800000 {
|
||||
usb_2_dwc3: dwc3@a800000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a800000 0 0xcd00>;
|
||||
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -2344,7 +2344,7 @@
|
||||
|
||||
resets = <&gcc GCC_USB30_PRIM_BCR>;
|
||||
|
||||
usb_1_dwc3: usb@a600000 {
|
||||
usb_1_dwc3: dwc3@a600000 {
|
||||
compatible = "snps,dwc3";
|
||||
reg = <0 0x0a600000 0 0xcd00>;
|
||||
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -824,7 +824,7 @@ static struct usb_class_driver wdm_class = {
|
||||
};
|
||||
|
||||
/* --- WWAN framework integration --- */
|
||||
#ifdef CONFIG_WWAN
|
||||
#ifdef CONFIG_WWAN_CORE
|
||||
static int wdm_wwan_port_start(struct wwan_port *port)
|
||||
{
|
||||
struct wdm_device *desc = wwan_port_get_drvdata(port);
|
||||
@ -963,11 +963,11 @@ static void wdm_wwan_rx(struct wdm_device *desc, int length)
|
||||
/* inbuf has been copied, it is safe to check for outstanding data */
|
||||
schedule_work(&desc->service_outs_intr);
|
||||
}
|
||||
#else /* CONFIG_WWAN */
|
||||
#else /* CONFIG_WWAN_CORE */
|
||||
static void wdm_wwan_init(struct wdm_device *desc) {}
|
||||
static void wdm_wwan_deinit(struct wdm_device *desc) {}
|
||||
static void wdm_wwan_rx(struct wdm_device *desc, int length) {}
|
||||
#endif /* CONFIG_WWAN */
|
||||
#endif /* CONFIG_WWAN_CORE */
|
||||
|
||||
/* --- error handling --- */
|
||||
static void wdm_rxwork(struct work_struct *work)
|
||||
|
@ -1133,7 +1133,7 @@ static int do_proc_control(struct usb_dev_state *ps,
|
||||
"wIndex=%04x wLength=%04x\n",
|
||||
ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
|
||||
ctrl->wIndex, ctrl->wLength);
|
||||
if (ctrl->bRequestType & 0x80) {
|
||||
if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
|
||||
pipe = usb_rcvctrlpipe(dev, 0);
|
||||
snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
|
||||
#define USB_TP_TRANSMISSION_DELAY 40 /* ns */
|
||||
#define USB_TP_TRANSMISSION_DELAY_MAX 65535 /* ns */
|
||||
#define USB_PING_RESPONSE_TIME 400 /* ns */
|
||||
|
||||
/* Protect struct usb_device->state and ->children members
|
||||
* Note: Both are also protected by ->dev.sem, except that ->state can
|
||||
@ -182,8 +183,9 @@ int usb_device_supports_lpm(struct usb_device *udev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Maximum Exit Latency (MEL) for the host to initiate a transition from
|
||||
* either U1 or U2.
|
||||
* Set the Maximum Exit Latency (MEL) for the host to wakup up the path from
|
||||
* U1/U2, send a PING to the device and receive a PING_RESPONSE.
|
||||
* See USB 3.1 section C.1.5.2
|
||||
*/
|
||||
static void usb_set_lpm_mel(struct usb_device *udev,
|
||||
struct usb3_lpm_parameters *udev_lpm_params,
|
||||
@ -193,35 +195,37 @@ static void usb_set_lpm_mel(struct usb_device *udev,
|
||||
unsigned int hub_exit_latency)
|
||||
{
|
||||
unsigned int total_mel;
|
||||
unsigned int device_mel;
|
||||
unsigned int hub_mel;
|
||||
|
||||
/*
|
||||
* Calculate the time it takes to transition all links from the roothub
|
||||
* to the parent hub into U0. The parent hub must then decode the
|
||||
* packet (hub header decode latency) to figure out which port it was
|
||||
* bound for.
|
||||
*
|
||||
* The Hub Header decode latency is expressed in 0.1us intervals (0x1
|
||||
* means 0.1us). Multiply that by 100 to get nanoseconds.
|
||||
* tMEL1. time to transition path from host to device into U0.
|
||||
* MEL for parent already contains the delay up to parent, so only add
|
||||
* the exit latency for the last link (pick the slower exit latency),
|
||||
* and the hub header decode latency. See USB 3.1 section C 2.2.1
|
||||
* Store MEL in nanoseconds
|
||||
*/
|
||||
total_mel = hub_lpm_params->mel +
|
||||
(hub->descriptor->u.ss.bHubHdrDecLat * 100);
|
||||
max(udev_exit_latency, hub_exit_latency) * 1000 +
|
||||
hub->descriptor->u.ss.bHubHdrDecLat * 100;
|
||||
|
||||
/*
|
||||
* How long will it take to transition the downstream hub's port into
|
||||
* U0? The greater of either the hub exit latency or the device exit
|
||||
* latency.
|
||||
*
|
||||
* The BOS U1/U2 exit latencies are expressed in 1us intervals.
|
||||
* Multiply that by 1000 to get nanoseconds.
|
||||
* tMEL2. Time to submit PING packet. Sum of tTPTransmissionDelay for
|
||||
* each link + wHubDelay for each hub. Add only for last link.
|
||||
* tMEL4, the time for PING_RESPONSE to traverse upstream is similar.
|
||||
* Multiply by 2 to include it as well.
|
||||
*/
|
||||
device_mel = udev_exit_latency * 1000;
|
||||
hub_mel = hub_exit_latency * 1000;
|
||||
if (device_mel > hub_mel)
|
||||
total_mel += device_mel;
|
||||
else
|
||||
total_mel += hub_mel;
|
||||
total_mel += (__le16_to_cpu(hub->descriptor->u.ss.wHubDelay) +
|
||||
USB_TP_TRANSMISSION_DELAY) * 2;
|
||||
|
||||
/*
|
||||
* tMEL3, tPingResponse. Time taken by device to generate PING_RESPONSE
|
||||
* after receiving PING. Also add 2100ns as stated in USB 3.1 C 1.5.2.4
|
||||
* to cover the delay if the PING_RESPONSE is queued behind a Max Packet
|
||||
* Size DP.
|
||||
* Note these delays should be added only once for the entire path, so
|
||||
* add them to the MEL of the device connected to the roothub.
|
||||
*/
|
||||
if (!hub->hdev->parent)
|
||||
total_mel += USB_PING_RESPONSE_TIME + 2100;
|
||||
|
||||
udev_lpm_params->mel = total_mel;
|
||||
}
|
||||
@ -4112,6 +4116,47 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow device intiated U1/U2 if the system exit latency + one bus
|
||||
* interval is greater than the minimum service interval of any active
|
||||
* periodic endpoint. See USB 3.2 section 9.4.9
|
||||
*/
|
||||
static bool usb_device_may_initiate_lpm(struct usb_device *udev,
|
||||
enum usb3_link_state state)
|
||||
{
|
||||
unsigned int sel; /* us */
|
||||
int i, j;
|
||||
|
||||
if (state == USB3_LPM_U1)
|
||||
sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
|
||||
else if (state == USB3_LPM_U2)
|
||||
sel = DIV_ROUND_UP(udev->u2_params.sel, 1000);
|
||||
else
|
||||
return false;
|
||||
|
||||
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *intf;
|
||||
struct usb_endpoint_descriptor *desc;
|
||||
unsigned int interval;
|
||||
|
||||
intf = udev->actconfig->interface[i];
|
||||
if (!intf)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++) {
|
||||
desc = &intf->cur_altsetting->endpoint[j].desc;
|
||||
|
||||
if (usb_endpoint_xfer_int(desc) ||
|
||||
usb_endpoint_xfer_isoc(desc)) {
|
||||
interval = (1 << (desc->bInterval - 1)) * 125;
|
||||
if (sel + 125 > interval)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the hub-initiated U1/U2 idle timeouts, and enable device-initiated
|
||||
* U1/U2 entry.
|
||||
@ -4184,20 +4229,23 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
* U1/U2_ENABLE
|
||||
*/
|
||||
if (udev->actconfig &&
|
||||
usb_set_device_initiated_lpm(udev, state, true) == 0) {
|
||||
if (state == USB3_LPM_U1)
|
||||
udev->usb3_lpm_u1_enabled = 1;
|
||||
else if (state == USB3_LPM_U2)
|
||||
udev->usb3_lpm_u2_enabled = 1;
|
||||
} else {
|
||||
/* Don't request U1/U2 entry if the device
|
||||
* cannot transition to U1/U2.
|
||||
*/
|
||||
usb_set_lpm_timeout(udev, state, 0);
|
||||
hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
|
||||
usb_device_may_initiate_lpm(udev, state)) {
|
||||
if (usb_set_device_initiated_lpm(udev, state, true)) {
|
||||
/*
|
||||
* Request to enable device initiated U1/U2 failed,
|
||||
* better to turn off lpm in this case.
|
||||
*/
|
||||
usb_set_lpm_timeout(udev, state, 0);
|
||||
hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state == USB3_LPM_U1)
|
||||
udev->usb3_lpm_u1_enabled = 1;
|
||||
else if (state == USB3_LPM_U2)
|
||||
udev->usb3_lpm_u2_enabled = 1;
|
||||
}
|
||||
/*
|
||||
* Disable the hub-initiated U1/U2 idle timeouts, and disable device-initiated
|
||||
* U1/U2 entry.
|
||||
|
@ -501,10 +501,6 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
/* DJI CineSSD */
|
||||
{ USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* Fibocom L850-GL LTE Modem */
|
||||
{ USB_DEVICE(0x2cb7, 0x0007), .driver_info =
|
||||
USB_QUIRK_IGNORE_REMOTE_WAKEUP },
|
||||
|
||||
/* INTEL VALUE SSD */
|
||||
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
|
@ -383,6 +383,9 @@ enum dwc2_ep0_state {
|
||||
* 0 - No (default)
|
||||
* 1 - Partial power down
|
||||
* 2 - Hibernation
|
||||
* @no_clock_gating: Specifies whether to avoid clock gating feature.
|
||||
* 0 - No (use clock gating)
|
||||
* 1 - Yes (avoid it)
|
||||
* @lpm: Enable LPM support.
|
||||
* 0 - No
|
||||
* 1 - Yes
|
||||
@ -480,6 +483,7 @@ struct dwc2_core_params {
|
||||
#define DWC2_POWER_DOWN_PARAM_NONE 0
|
||||
#define DWC2_POWER_DOWN_PARAM_PARTIAL 1
|
||||
#define DWC2_POWER_DOWN_PARAM_HIBERNATION 2
|
||||
bool no_clock_gating;
|
||||
|
||||
bool lpm;
|
||||
bool lpm_clock_gating;
|
||||
|
@ -556,7 +556,8 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
|
||||
* If neither hibernation nor partial power down are supported,
|
||||
* clock gating is used to save power.
|
||||
*/
|
||||
dwc2_gadget_enter_clock_gating(hsotg);
|
||||
if (!hsotg->params.no_clock_gating)
|
||||
dwc2_gadget_enter_clock_gating(hsotg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2749,12 +2749,14 @@ static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Zlp for all endpoints, for ep0 only in DATA IN stage */
|
||||
/* Zlp for all endpoints in non DDMA, for ep0 only in DATA IN stage */
|
||||
if (hs_ep->send_zlp) {
|
||||
dwc2_hsotg_program_zlp(hsotg, hs_ep);
|
||||
hs_ep->send_zlp = 0;
|
||||
/* transfer will be completed on next complete interrupt */
|
||||
return;
|
||||
if (!using_desc_dma(hsotg)) {
|
||||
dwc2_hsotg_program_zlp(hsotg, hs_ep);
|
||||
/* transfer will be completed on next complete interrupt */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_DATA_IN) {
|
||||
@ -3900,9 +3902,27 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
|
||||
__func__);
|
||||
}
|
||||
} else {
|
||||
/* Mask GINTSTS_GOUTNAKEFF interrupt */
|
||||
dwc2_hsotg_disable_gsint(hsotg, GINTSTS_GOUTNAKEFF);
|
||||
|
||||
if (!(dwc2_readl(hsotg, GINTSTS) & GINTSTS_GOUTNAKEFF))
|
||||
dwc2_set_bit(hsotg, DCTL, DCTL_SGOUTNAK);
|
||||
|
||||
if (!using_dma(hsotg)) {
|
||||
/* Wait for GINTSTS_RXFLVL interrupt */
|
||||
if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
|
||||
GINTSTS_RXFLVL, 100)) {
|
||||
dev_warn(hsotg->dev, "%s: timeout GINTSTS.RXFLVL\n",
|
||||
__func__);
|
||||
} else {
|
||||
/*
|
||||
* Pop GLOBAL OUT NAK status packet from RxFIFO
|
||||
* to assert GOUTNAKEFF interrupt
|
||||
*/
|
||||
dwc2_readl(hsotg, GRXSTSP);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for global nak to take effect */
|
||||
if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
|
||||
GINTSTS_GOUTNAKEFF, 100))
|
||||
@ -4348,6 +4368,9 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
|
||||
epctl = dwc2_readl(hs, epreg);
|
||||
|
||||
if (value) {
|
||||
/* Unmask GOUTNAKEFF interrupt */
|
||||
dwc2_hsotg_en_gsint(hs, GINTSTS_GOUTNAKEFF);
|
||||
|
||||
if (!(dwc2_readl(hs, GINTSTS) & GINTSTS_GOUTNAKEFF))
|
||||
dwc2_set_bit(hs, DCTL, DCTL_SGOUTNAK);
|
||||
// STALL bit will be set in GOUTNAKEFF interrupt handler
|
||||
|
@ -3338,7 +3338,8 @@ int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
|
||||
* If not hibernation nor partial power down are supported,
|
||||
* clock gating is used to save power.
|
||||
*/
|
||||
dwc2_host_enter_clock_gating(hsotg);
|
||||
if (!hsotg->params.no_clock_gating)
|
||||
dwc2_host_enter_clock_gating(hsotg);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4402,7 +4403,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
|
||||
* If not hibernation nor partial power down are supported,
|
||||
* clock gating is used to save power.
|
||||
*/
|
||||
dwc2_host_enter_clock_gating(hsotg);
|
||||
if (!hsotg->params.no_clock_gating)
|
||||
dwc2_host_enter_clock_gating(hsotg);
|
||||
|
||||
/* After entering suspend, hardware is not accessible */
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
@ -76,6 +76,7 @@ static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg)
|
||||
struct dwc2_core_params *p = &hsotg->params;
|
||||
|
||||
p->power_down = DWC2_POWER_DOWN_PARAM_NONE;
|
||||
p->no_clock_gating = true;
|
||||
p->phy_utmi_width = 8;
|
||||
}
|
||||
|
||||
|
@ -1279,6 +1279,7 @@ struct dwc3 {
|
||||
unsigned dis_metastability_quirk:1;
|
||||
|
||||
unsigned dis_split_quirk:1;
|
||||
unsigned async_callbacks:1;
|
||||
|
||||
u16 imod_interval;
|
||||
};
|
||||
|
@ -597,11 +597,13 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
|
||||
|
||||
static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
|
||||
{
|
||||
int ret;
|
||||
int ret = -EINVAL;
|
||||
|
||||
spin_unlock(&dwc->lock);
|
||||
ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
|
||||
spin_lock(&dwc->lock);
|
||||
if (dwc->async_callbacks) {
|
||||
spin_unlock(&dwc->lock);
|
||||
ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
|
||||
spin_lock(&dwc->lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2585,6 +2585,16 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dwc3_gadget_async_callbacks(struct usb_gadget *g, bool enable)
|
||||
{
|
||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dwc->async_callbacks = enable;
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
}
|
||||
|
||||
static const struct usb_gadget_ops dwc3_gadget_ops = {
|
||||
.get_frame = dwc3_gadget_get_frame,
|
||||
.wakeup = dwc3_gadget_wakeup,
|
||||
@ -2596,6 +2606,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
|
||||
.udc_set_ssp_rate = dwc3_gadget_set_ssp_rate,
|
||||
.get_config_params = dwc3_gadget_config_params,
|
||||
.vbus_draw = dwc3_gadget_vbus_draw,
|
||||
.udc_async_callbacks = dwc3_gadget_async_callbacks,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -3231,7 +3242,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
||||
|
||||
static void dwc3_disconnect_gadget(struct dwc3 *dwc)
|
||||
{
|
||||
if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
|
||||
if (dwc->async_callbacks && dwc->gadget_driver->disconnect) {
|
||||
spin_unlock(&dwc->lock);
|
||||
dwc->gadget_driver->disconnect(dwc->gadget);
|
||||
spin_lock(&dwc->lock);
|
||||
@ -3240,7 +3251,7 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc)
|
||||
|
||||
static void dwc3_suspend_gadget(struct dwc3 *dwc)
|
||||
{
|
||||
if (dwc->gadget_driver && dwc->gadget_driver->suspend) {
|
||||
if (dwc->async_callbacks && dwc->gadget_driver->suspend) {
|
||||
spin_unlock(&dwc->lock);
|
||||
dwc->gadget_driver->suspend(dwc->gadget);
|
||||
spin_lock(&dwc->lock);
|
||||
@ -3249,7 +3260,7 @@ static void dwc3_suspend_gadget(struct dwc3 *dwc)
|
||||
|
||||
static void dwc3_resume_gadget(struct dwc3 *dwc)
|
||||
{
|
||||
if (dwc->gadget_driver && dwc->gadget_driver->resume) {
|
||||
if (dwc->async_callbacks && dwc->gadget_driver->resume) {
|
||||
spin_unlock(&dwc->lock);
|
||||
dwc->gadget_driver->resume(dwc->gadget);
|
||||
spin_lock(&dwc->lock);
|
||||
@ -3261,7 +3272,7 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
|
||||
if (!dwc->gadget_driver)
|
||||
return;
|
||||
|
||||
if (dwc->gadget->speed != USB_SPEED_UNKNOWN) {
|
||||
if (dwc->async_callbacks && dwc->gadget->speed != USB_SPEED_UNKNOWN) {
|
||||
spin_unlock(&dwc->lock);
|
||||
usb_gadget_udc_reset(dwc->gadget, dwc->gadget_driver);
|
||||
spin_lock(&dwc->lock);
|
||||
@ -3585,7 +3596,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
|
||||
* implemented.
|
||||
*/
|
||||
|
||||
if (dwc->gadget_driver && dwc->gadget_driver->resume) {
|
||||
if (dwc->async_callbacks && dwc->gadget_driver->resume) {
|
||||
spin_unlock(&dwc->lock);
|
||||
dwc->gadget_driver->resume(dwc->gadget);
|
||||
spin_lock(&dwc->lock);
|
||||
|
@ -1198,7 +1198,7 @@ void gserial_free_line(unsigned char port_num)
|
||||
struct gs_port *port;
|
||||
|
||||
mutex_lock(&ports[port_num].lock);
|
||||
if (WARN_ON(!ports[port_num].port)) {
|
||||
if (!ports[port_num].port) {
|
||||
mutex_unlock(&ports[port_num].lock);
|
||||
return;
|
||||
}
|
||||
|
@ -3853,6 +3853,7 @@ static int tegra_xudc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
free_eps:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
tegra_xudc_free_eps(xudc);
|
||||
free_event_ring:
|
||||
tegra_xudc_free_event_ring(xudc);
|
||||
|
@ -703,24 +703,28 @@ EXPORT_SYMBOL_GPL(ehci_setup);
|
||||
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
|
||||
u32 status, masked_status, pcd_status = 0, cmd;
|
||||
u32 status, current_status, masked_status, pcd_status = 0;
|
||||
u32 cmd;
|
||||
int bh;
|
||||
|
||||
spin_lock(&ehci->lock);
|
||||
|
||||
status = ehci_readl(ehci, &ehci->regs->status);
|
||||
status = 0;
|
||||
current_status = ehci_readl(ehci, &ehci->regs->status);
|
||||
restart:
|
||||
|
||||
/* e.g. cardbus physical eject */
|
||||
if (status == ~(u32) 0) {
|
||||
if (current_status == ~(u32) 0) {
|
||||
ehci_dbg (ehci, "device removed\n");
|
||||
goto dead;
|
||||
}
|
||||
status |= current_status;
|
||||
|
||||
/*
|
||||
* We don't use STS_FLR, but some controllers don't like it to
|
||||
* remain on, so mask it out along with the other status bits.
|
||||
*/
|
||||
masked_status = status & (INTR_MASK | STS_FLR);
|
||||
masked_status = current_status & (INTR_MASK | STS_FLR);
|
||||
|
||||
/* Shared IRQ? */
|
||||
if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
|
||||
@ -730,6 +734,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
|
||||
|
||||
/* clear (just) interrupts */
|
||||
ehci_writel(ehci, masked_status, &ehci->regs->status);
|
||||
|
||||
/* For edge interrupts, don't race with an interrupt bit being raised */
|
||||
current_status = ehci_readl(ehci, &ehci->regs->status);
|
||||
if (current_status & INTR_MASK)
|
||||
goto restart;
|
||||
|
||||
cmd = ehci_readl(ehci, &ehci->regs->command);
|
||||
bh = 0;
|
||||
|
||||
|
@ -153,8 +153,6 @@ struct max3421_hcd {
|
||||
*/
|
||||
struct urb *curr_urb;
|
||||
enum scheduling_pass sched_pass;
|
||||
struct usb_device *loaded_dev; /* dev that's loaded into the chip */
|
||||
int loaded_epnum; /* epnum whose toggles are loaded */
|
||||
int urb_done; /* > 0 -> no errors, < 0: errno */
|
||||
size_t curr_len;
|
||||
u8 hien;
|
||||
@ -492,39 +490,17 @@ max3421_set_speed(struct usb_hcd *hcd, struct usb_device *dev)
|
||||
* Caller must NOT hold HCD spinlock.
|
||||
*/
|
||||
static void
|
||||
max3421_set_address(struct usb_hcd *hcd, struct usb_device *dev, int epnum,
|
||||
int force_toggles)
|
||||
max3421_set_address(struct usb_hcd *hcd, struct usb_device *dev, int epnum)
|
||||
{
|
||||
struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
|
||||
int old_epnum, same_ep, rcvtog, sndtog;
|
||||
struct usb_device *old_dev;
|
||||
int rcvtog, sndtog;
|
||||
u8 hctl;
|
||||
|
||||
old_dev = max3421_hcd->loaded_dev;
|
||||
old_epnum = max3421_hcd->loaded_epnum;
|
||||
|
||||
same_ep = (dev == old_dev && epnum == old_epnum);
|
||||
if (same_ep && !force_toggles)
|
||||
return;
|
||||
|
||||
if (old_dev && !same_ep) {
|
||||
/* save the old end-points toggles: */
|
||||
u8 hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
|
||||
|
||||
rcvtog = (hrsl >> MAX3421_HRSL_RCVTOGRD_BIT) & 1;
|
||||
sndtog = (hrsl >> MAX3421_HRSL_SNDTOGRD_BIT) & 1;
|
||||
|
||||
/* no locking: HCD (i.e., we) own toggles, don't we? */
|
||||
usb_settoggle(old_dev, old_epnum, 0, rcvtog);
|
||||
usb_settoggle(old_dev, old_epnum, 1, sndtog);
|
||||
}
|
||||
/* setup new endpoint's toggle bits: */
|
||||
rcvtog = usb_gettoggle(dev, epnum, 0);
|
||||
sndtog = usb_gettoggle(dev, epnum, 1);
|
||||
hctl = (BIT(rcvtog + MAX3421_HCTL_RCVTOG0_BIT) |
|
||||
BIT(sndtog + MAX3421_HCTL_SNDTOG0_BIT));
|
||||
|
||||
max3421_hcd->loaded_epnum = epnum;
|
||||
spi_wr8(hcd, MAX3421_REG_HCTL, hctl);
|
||||
|
||||
/*
|
||||
@ -532,7 +508,6 @@ max3421_set_address(struct usb_hcd *hcd, struct usb_device *dev, int epnum,
|
||||
* address-assignment so it's best to just always load the
|
||||
* address whenever the end-point changed/was forced.
|
||||
*/
|
||||
max3421_hcd->loaded_dev = dev;
|
||||
spi_wr8(hcd, MAX3421_REG_PERADDR, dev->devnum);
|
||||
}
|
||||
|
||||
@ -667,7 +642,7 @@ max3421_select_and_start_urb(struct usb_hcd *hcd)
|
||||
struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
|
||||
struct urb *urb, *curr_urb = NULL;
|
||||
struct max3421_ep *max3421_ep;
|
||||
int epnum, force_toggles = 0;
|
||||
int epnum;
|
||||
struct usb_host_endpoint *ep;
|
||||
struct list_head *pos;
|
||||
unsigned long flags;
|
||||
@ -777,7 +752,6 @@ done:
|
||||
usb_settoggle(urb->dev, epnum, 0, 1);
|
||||
usb_settoggle(urb->dev, epnum, 1, 1);
|
||||
max3421_ep->pkt_state = PKT_STATE_SETUP;
|
||||
force_toggles = 1;
|
||||
} else
|
||||
max3421_ep->pkt_state = PKT_STATE_TRANSFER;
|
||||
}
|
||||
@ -785,7 +759,7 @@ done:
|
||||
spin_unlock_irqrestore(&max3421_hcd->lock, flags);
|
||||
|
||||
max3421_ep->last_active = max3421_hcd->frame_number;
|
||||
max3421_set_address(hcd, urb->dev, epnum, force_toggles);
|
||||
max3421_set_address(hcd, urb->dev, epnum);
|
||||
max3421_set_speed(hcd, urb->dev);
|
||||
max3421_next_transfer(hcd, 0);
|
||||
return 1;
|
||||
@ -1379,6 +1353,16 @@ max3421_urb_done(struct usb_hcd *hcd)
|
||||
status = 0;
|
||||
urb = max3421_hcd->curr_urb;
|
||||
if (urb) {
|
||||
/* save the old end-points toggles: */
|
||||
u8 hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
|
||||
int rcvtog = (hrsl >> MAX3421_HRSL_RCVTOGRD_BIT) & 1;
|
||||
int sndtog = (hrsl >> MAX3421_HRSL_SNDTOGRD_BIT) & 1;
|
||||
int epnum = usb_endpoint_num(&urb->ep->desc);
|
||||
|
||||
/* no locking: HCD (i.e., we) own toggles, don't we? */
|
||||
usb_settoggle(urb->dev, epnum, 0, rcvtog);
|
||||
usb_settoggle(urb->dev, epnum, 1, sndtog);
|
||||
|
||||
max3421_hcd->curr_urb = NULL;
|
||||
spin_lock_irqsave(&max3421_hcd->lock, flags);
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
|
@ -1638,11 +1638,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
||||
* Inform the usbcore about resume-in-progress by returning
|
||||
* a non-zero value even if there are no status changes.
|
||||
*/
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
status = bus_state->resuming_ports;
|
||||
|
||||
mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
/* For each port, did anything change? If so, set that bit in buf. */
|
||||
for (i = 0; i < max_ports; i++) {
|
||||
temp = readl(ports[i]->addr);
|
||||
|
@ -207,8 +207,7 @@ static int renesas_check_rom_state(struct pci_dev *pdev)
|
||||
return 0;
|
||||
|
||||
case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */
|
||||
dev_dbg(&pdev->dev, "Unknown ROM status ...\n");
|
||||
break;
|
||||
return 0;
|
||||
|
||||
case RENESAS_ROM_STATUS_ERROR: /* Error State */
|
||||
default: /* All other states are marked as "Reserved states" */
|
||||
@ -225,12 +224,13 @@ static int renesas_fw_check_running(struct pci_dev *pdev)
|
||||
u8 fw_state;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Only if device has ROM and loaded FW we can skip loading and
|
||||
* return success. Otherwise (even unknown state), attempt to load FW.
|
||||
*/
|
||||
if (renesas_check_rom(pdev) && !renesas_check_rom_state(pdev))
|
||||
return 0;
|
||||
/* Check if device has ROM and loaded, if so skip everything */
|
||||
err = renesas_check_rom(pdev);
|
||||
if (err) { /* we have rom */
|
||||
err = renesas_check_rom_state(pdev);
|
||||
if (!err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the device is actually needing the firmware. As most
|
||||
|
@ -636,7 +636,14 @@ static const struct pci_device_id pci_ids[] = {
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pci_ids);
|
||||
|
||||
/*
|
||||
* Without CONFIG_USB_XHCI_PCI_RENESAS renesas_xhci_check_request_fw() won't
|
||||
* load firmware, so don't encumber the xhci-pci driver with it.
|
||||
*/
|
||||
#if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS)
|
||||
MODULE_FIRMWARE("renesas_usb_fw.mem");
|
||||
#endif
|
||||
|
||||
/* pci driver glue; this is a "new style" PCI driver module */
|
||||
static struct pci_driver xhci_pci_driver = {
|
||||
|
@ -86,10 +86,10 @@ static struct usb_phy *__device_to_usb_phy(struct device *dev)
|
||||
|
||||
list_for_each_entry(usb_phy, &phy_list, head) {
|
||||
if (usb_phy->dev == dev)
|
||||
break;
|
||||
return usb_phy;
|
||||
}
|
||||
|
||||
return usb_phy;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usb_phy_set_default_current(struct usb_phy *usb_phy)
|
||||
@ -150,8 +150,14 @@ static int usb_phy_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
struct usb_phy *usb_phy;
|
||||
char uchger_state[50] = { 0 };
|
||||
char uchger_type[50] = { 0 };
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&phy_lock, flags);
|
||||
usb_phy = __device_to_usb_phy(dev);
|
||||
spin_unlock_irqrestore(&phy_lock, flags);
|
||||
|
||||
if (!usb_phy)
|
||||
return -ENODEV;
|
||||
|
||||
snprintf(uchger_state, ARRAY_SIZE(uchger_state),
|
||||
"USB_CHARGER_STATE=%s", usb_chger_state[usb_phy->chg_state]);
|
||||
|
@ -101,6 +101,8 @@ static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo,
|
||||
#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);
|
||||
static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable);
|
||||
static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable);
|
||||
struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
|
||||
{
|
||||
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
|
||||
@ -123,6 +125,11 @@ struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
|
||||
if (chan) {
|
||||
dmaengine_terminate_all(chan);
|
||||
usbhsf_dma_unmap(pkt);
|
||||
} else {
|
||||
if (usbhs_pipe_is_dir_in(pipe))
|
||||
usbhsf_rx_irq_ctrl(pipe, 0);
|
||||
else
|
||||
usbhsf_tx_irq_ctrl(pipe, 0);
|
||||
}
|
||||
|
||||
usbhs_pipe_clear_without_sequence(pipe, 0, 0);
|
||||
|
@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x10C4, 0x89A4) }, /* CESINEL FTBC Flexible Thyristor Bridge Controller */
|
||||
{ USB_DEVICE(0x10C4, 0x89FB) }, /* Qivicon ZigBee USB Radio Stick */
|
||||
{ USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */
|
||||
{ USB_DEVICE(0x10C4, 0x8A5B) }, /* CEL EM3588 ZigBee USB Stick */
|
||||
{ USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */
|
||||
{ USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */
|
||||
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
|
||||
@ -202,8 +203,8 @@ static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
|
||||
{ USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */
|
||||
{ USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */
|
||||
{ USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 Display serial interface */
|
||||
{ USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 M.2 Key E serial interface */
|
||||
{ USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 M.2 Key E serial interface */
|
||||
{ USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 Display serial interface */
|
||||
{ USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */
|
||||
{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
|
||||
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
|
||||
|
@ -238,6 +238,7 @@ static void option_instat_callback(struct urb *urb);
|
||||
#define QUECTEL_PRODUCT_UC15 0x9090
|
||||
/* These u-blox products use Qualcomm's vendor ID */
|
||||
#define UBLOX_PRODUCT_R410M 0x90b2
|
||||
#define UBLOX_PRODUCT_R6XX 0x90fa
|
||||
/* These Yuga products use Qualcomm's vendor ID */
|
||||
#define YUGA_PRODUCT_CLM920_NC5 0x9625
|
||||
|
||||
@ -1101,6 +1102,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
/* u-blox products using Qualcomm vendor ID */
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
|
||||
.driver_info = RSVD(1) | RSVD(3) },
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R6XX),
|
||||
.driver_info = RSVD(3) },
|
||||
/* Quectel products using Quectel vendor ID */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0xff, 0xff),
|
||||
.driver_info = NUMEP2 },
|
||||
|
@ -45,6 +45,13 @@ UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999,
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME),
|
||||
|
||||
/* Reported-by: Julian Sikorski <belegdol@gmail.com> */
|
||||
UNUSUAL_DEV(0x059f, 0x1061, 0x0000, 0x9999,
|
||||
"LaCie",
|
||||
"Rugged USB3-FW",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_UAS),
|
||||
|
||||
/*
|
||||
* Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI
|
||||
* commands in UAS mode. Observed with the 1.28 firmware; are there others?
|
||||
|
@ -685,6 +685,15 @@ static int stusb160x_probe(struct i2c_client *client)
|
||||
if (!fwnode)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* This fwnode has a "compatible" property, but is never populated as a
|
||||
* struct device. Instead we simply parse it to read the properties.
|
||||
* This it breaks fw_devlink=on. To maintain backward compatibility
|
||||
* with existing DT files, we work around this by deleting any
|
||||
* fwnode_links to/from this fwnode.
|
||||
*/
|
||||
fw_devlink_purge_absent_suppliers(fwnode);
|
||||
|
||||
/*
|
||||
* When both VDD and VSYS power supplies are present, the low power
|
||||
* supply VSYS is selected when VSYS voltage is above 3.1 V.
|
||||
@ -739,10 +748,6 @@ static int stusb160x_probe(struct i2c_client *client)
|
||||
typec_set_pwr_opmode(chip->port, chip->pwr_opmode);
|
||||
|
||||
if (client->irq) {
|
||||
ret = stusb160x_irq_init(chip, client->irq);
|
||||
if (ret)
|
||||
goto port_unregister;
|
||||
|
||||
chip->role_sw = fwnode_usb_role_switch_get(fwnode);
|
||||
if (IS_ERR(chip->role_sw)) {
|
||||
ret = PTR_ERR(chip->role_sw);
|
||||
@ -752,6 +757,10 @@ static int stusb160x_probe(struct i2c_client *client)
|
||||
ret);
|
||||
goto port_unregister;
|
||||
}
|
||||
|
||||
ret = stusb160x_irq_init(chip, client->irq);
|
||||
if (ret)
|
||||
goto role_sw_put;
|
||||
} else {
|
||||
/*
|
||||
* If Source or Dual power role, need to enable VDD supply
|
||||
@ -775,6 +784,9 @@ static int stusb160x_probe(struct i2c_client *client)
|
||||
|
||||
return 0;
|
||||
|
||||
role_sw_put:
|
||||
if (chip->role_sw)
|
||||
usb_role_switch_put(chip->role_sw);
|
||||
port_unregister:
|
||||
typec_unregister_port(chip->port);
|
||||
all_reg_disable:
|
||||
|
@ -629,6 +629,15 @@ static int tps6598x_probe(struct i2c_client *client)
|
||||
if (!fwnode)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* This fwnode has a "compatible" property, but is never populated as a
|
||||
* struct device. Instead we simply parse it to read the properties.
|
||||
* This breaks fw_devlink=on. To maintain backward compatibility
|
||||
* with existing DT files, we work around this by deleting any
|
||||
* fwnode_links to/from this fwnode.
|
||||
*/
|
||||
fw_devlink_purge_absent_suppliers(fwnode);
|
||||
|
||||
tps->role_sw = fwnode_usb_role_switch_get(fwnode);
|
||||
if (IS_ERR(tps->role_sw)) {
|
||||
ret = PTR_ERR(tps->role_sw);
|
||||
|
Loading…
Reference in New Issue
Block a user