Commit e09bf86f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB / Thunderbolt updates from Greg KH:
 "Here is the big set of USB and Thunderbolt changes for 6.9-rc1. Lots
  of tiny changes and forward progress to support new hardware and
  better support for existing devices. Included in here are:

   - Thunderbolt (i.e. USB4) updates for newer hardware and uses as more
     people start to use the hardware

   - default USB authentication mode Kconfig and documentation update to
     make it more obvious what is going on

   - USB typec updates and enhancements

   - usual dwc3 driver updates

   - usual xhci driver updates

   - function USB (i.e. gadget) driver updates and additions

   - new device ids for lots of drivers

   - loads of other small updates, full details in the shortlog

  All of these, including a "last minute regression fix" have been in
  linux-next with no reported issues"

* tag 'usb-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (185 commits)
  usb: usb-acpi: Fix oops due to freeing uninitialized pld pointer
  usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
  usb: gadget: tegra-xudc: Fix USB3 PHY retrieval logic
  phy: tegra: xusb: Add API to retrieve the port number of phy
  USB: gadget: pxa27x_udc: Remove unused of_gpio.h
  usb: gadget/snps_udc_plat: Remove unused of_gpio.h
  usb: ohci-pxa27x: Remove unused of_gpio.h
  usb: sl811-hcd: only defined function checkdone if QUIRK2 is defined
  usb: Clarify expected behavior of dev_bin_attrs_are_visible()
  xhci: Allow RPM on the USB controller (1022:43f7) by default
  usb: isp1760: remove SLAB_MEM_SPREAD flag usage
  usb: misc: onboard_hub: use pointer consistently in the probe function
  usb: gadget: fsl: Increase size of name buffer for endpoints
  usb: gadget: fsl: Add of device table to enable module autoloading
  usb: typec: tcpm: add support to set tcpc connector orientatition
  usb: typec: tcpci: add generic tcpci fallback compatible
  dt-bindings: usb: typec-tcpci: add tcpci fallback binding
  usb: gadget: fsl-udc: Replace custom log wrappers by dev_{err,warn,dbg,vdbg}
  usb: core: Set connect_type of ports based on DT node
  dt-bindings: usb: Add downstream facing ports to realtek binding
  ...
parents 2ac2b166 a788e53c
......@@ -4,6 +4,14 @@ KernelVersion: 3.13
Description: The purpose of this directory is to create and remove it.
A corresponding USB function instance is created/removed.
There are no attributes here.
All parameters are set through FunctionFS.
All attributes are read only:
============= ============================================
ready 1 if the function is ready to be used, E.G.
if userspace has written descriptors and
strings to ep0, so the gadget can be
enabled - 0 otherwise.
============= ============================================
All other parameters are set through FunctionFS.
......@@ -442,6 +442,16 @@ What: /sys/bus/usb/devices/usbX/descriptors
Description:
Contains the interface descriptors, in binary.
What: /sys/bus/usb/devices/usbX/bos_descriptors
Date: March 2024
Contact: Elbert Mai <code@elbertmai.com>
Description:
Binary file containing the cached binary device object store (BOS)
of the device. This consists of the BOS descriptor followed by the
set of device capability descriptors. All descriptors read from
this file are in bus-endian format. Note that the kernel will not
request the BOS from a device if its bcdUSB is less than 0x0201.
What: /sys/bus/usb/devices/usbX/idProduct
Description:
Product ID, in hexadecimal.
......
......@@ -19,3 +19,9 @@ Description:
- none
- host
- device
What: /sys/class/usb_role/<switch>/connector
Date: Feb 2024
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Optional symlink to the USB Type-C connector.
......@@ -26,6 +26,7 @@ properties:
- enum:
- qcom,pm4125-vbus-reg
- qcom,pm6150-vbus-reg
- qcom,pmi632-vbus-reg
- const: qcom,pm8150b-vbus-reg
reg:
......
......@@ -23,6 +23,7 @@ properties:
oneOf:
- items:
- enum:
- qcom,qcm6490-pmic-glink
- qcom,sc8180x-pmic-glink
- qcom,sc8280xp-pmic-glink
- qcom,sm8350-pmic-glink
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,q6usb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm ASoC DPCM USB backend DAI
maintainers:
- Wesley Cheng <quic_wcheng@quicinc.com>
description:
The USB port is a supported AFE path on the Q6 DSP. This ASoC DPCM
backend DAI will communicate the required settings to initialize the
XHCI host controller properly for enabling the offloaded audio stream.
Parameters defined under this node will carry settings, which will be
passed along during the QMI stream enable request and configuration of
the XHCI host controller.
allOf:
- $ref: dai-common.yaml#
properties:
compatible:
enum:
- qcom,q6usb
iommus:
maxItems: 1
"#sound-dai-cells":
const: 1
qcom,usb-audio-intr-idx:
description:
Desired XHCI interrupter number to use. Depending on the audio DSP
on the platform, it will operate on a specific XHCI interrupter.
$ref: /schemas/types.yaml#/definitions/uint16
maximum: 8
required:
- compatible
- "#sound-dai-cells"
- qcom,usb-audio-intr-idx
additionalProperties: false
examples:
- |
dais {
compatible = "qcom,q6usb";
#sound-dai-cells = <1>;
iommus = <&apps_smmu 0x180f 0x0>;
qcom,usb-audio-intr-idx = /bits/ 16 <2>;
};
......@@ -23,24 +23,11 @@ properties:
connector:
type: object
$ref: ../connector/usb-connector.yaml
unevaluatedProperties: false
description:
Properties for usb c connector.
properties:
compatible:
const: usb-c-connector
power-role: true
data-role: true
try-power-role: true
required:
- compatible
required:
- compatible
- reg
......
......@@ -313,7 +313,7 @@ properties:
usb-phy:
description: phandle for the PHY device. Use "phys" instead.
$ref: /schemas/types.yaml#/definitions/phandle
maxItems: 1
deprecated: true
fsl,usbphy:
......
......@@ -27,13 +27,8 @@ properties:
vcc-supply:
description: power supply (2.7V-5.5V)
mode-switch:
description: Flag the port as possible handle of altmode switching
type: boolean
orientation-switch:
description: Flag the port as possible handler of orientation switching
type: boolean
mode-switch: true
orientation-switch: true
port:
$ref: /schemas/graph.yaml#/$defs/port-base
......@@ -79,6 +74,9 @@ required:
- reg
- port
allOf:
- $ref: usb-switch.yaml#
additionalProperties: false
examples:
......
......@@ -77,6 +77,7 @@ properties:
- const: usb-ehci
- enum:
- generic-ehci
- marvell,ac5-ehci
- marvell,armada-3700-ehci
- marvell,orion-ehci
- nuvoton,npcm750-ehci
......
......@@ -33,13 +33,8 @@ properties:
vcc-supply:
description: power supply
mode-switch:
description: Flag the port as possible handle of altmode switching
type: boolean
orientation-switch:
description: Flag the port as possible handler of orientation switching
type: boolean
mode-switch: true
orientation-switch: true
port:
$ref: /schemas/graph.yaml#/properties/port
......@@ -54,6 +49,9 @@ required:
- orientation-switch
- port
allOf:
- $ref: usb-switch.yaml#
additionalProperties: false
examples:
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/hisilicon,hi3798mv200-dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HiSilicon Hi3798MV200 DWC3 USB SoC controller
maintainers:
- Yang Xiwen <forbidden405@foxmail.com>
properties:
compatible:
const: hisilicon,hi3798mv200-dwc3
'#address-cells':
const: 1
'#size-cells':
const: 1
ranges: true
clocks:
items:
- description: Controller bus clock
- description: Controller suspend clock
- description: Controller reference clock
- description: Controller gm clock
- description: Controller gs clock
- description: Controller utmi clock
- description: Controller pipe clock
clock-names:
items:
- const: bus
- const: suspend
- const: ref
- const: gm
- const: gs
- const: utmi
- const: pipe
resets:
maxItems: 1
reset-names:
const: soft
patternProperties:
'^usb@[0-9a-f]+$':
$ref: snps,dwc3.yaml#
required:
- compatible
- ranges
- '#address-cells'
- '#size-cells'
- clocks
- clock-names
- resets
- reset-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
usb {
compatible = "hisilicon,hi3798mv200-dwc3";
ranges;
#address-cells = <1>;
#size-cells = <1>;
clocks = <&clk_bus>,
<&clk_suspend>,
<&clk_ref>,
<&clk_gm>,
<&clk_gs>,
<&clk_utmi>,
<&clk_pipe>;
clock-names = "bus", "suspend", "ref", "gm", "gs", "utmi", "pipe";
resets = <&crg 0xb0 12>;
reset-names = "soft";
usb@98a0000 {
compatible = "snps,dwc3";
reg = <0x98a0000 0x10000>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_bus>,
<&clk_suspend>,
<&clk_ref>;
clock-names = "bus_early", "suspend", "ref";
phys = <&usb2_phy1_port2>, <&combphy0 0>;
phy-names = "usb2-phy", "usb3-phy";
maximum-speed = "super-speed";
dr_mode = "host";
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/ite,it5205.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ITE IT5202 Type-C USB Alternate Mode Passive MUX
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
- Tianping Fang <tianping.fang@mediatek.com>
properties:
compatible:
const: ite,it5205
reg:
maxItems: 1
vcc-supply:
description: Power supply for VCC pin (3.3V)
mode-switch:
description: Flag the port as possible handle of altmode switching
type: boolean
orientation-switch:
description: Flag the port as possible handler of orientation switching
type: boolean
ite,ovp-enable:
description: Enable Over Voltage Protection functionality
type: boolean
port:
$ref: /schemas/graph.yaml#/properties/port
description:
A port node to link the IT5205 to a TypeC controller for the purpose of
handling altmode muxing and orientation switching.
required:
- compatible
- reg
- orientation-switch
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c2 {
#address-cells = <1>;
#size-cells = <0>;
typec-mux@48 {
compatible = "ite,it5205";
reg = <0x48>;
mode-switch;
orientation-switch;
vcc-supply = <&mt6359_vibr_ldo_reg>;
port {
it5205_usbss_sbu: endpoint {
remote-endpoint = <&typec_controller>;
};
};
};
};
...
......@@ -185,7 +185,10 @@ properties:
2 - used by mt2712 etc, revision 2 with following IPM rule;
101 - used by mt8183, specific 1.01;
102 - used by mt8192, specific 1.02;
enum: [1, 2, 101, 102]
103 - used by mt8195, IP0, specific 1.03;
105 - used by mt8195, IP2, specific 1.05;
106 - used by mt8195, IP3, specific 1.06;
enum: [1, 2, 101, 102, 103, 105, 106]
mediatek,u3p-dis-msk:
$ref: /schemas/types.yaml#/definitions/uint32
......
......@@ -72,8 +72,6 @@ allOf:
i2c-bus: false
else:
$ref: /schemas/usb/usb-device.yaml
required:
- peer-hub
additionalProperties: false
......
......@@ -20,13 +20,8 @@ properties:
vdd18-supply:
description: Power supply for VDD18 pin
retimer-switch:
description: Flag the port as possible handle of SuperSpeed signals retiming
type: boolean
orientation-switch:
description: Flag the port as possible handler of orientation switching
type: boolean
orientation-switch: true
retimer-switch: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
......@@ -49,6 +44,9 @@ required:
- compatible
- reg
allOf:
- $ref: usb-switch.yaml#
additionalProperties: false
examples:
......
......@@ -11,7 +11,9 @@ maintainers:
properties:
compatible:
const: nxp,ptn5110
items:
- const: nxp,ptn5110
- const: tcpci
reg:
maxItems: 1
......@@ -41,7 +43,7 @@ examples:
#size-cells = <0>;
tcpci@50 {
compatible = "nxp,ptn5110";
compatible = "nxp,ptn5110", "tcpci";
reg = <0x50>;
interrupt-parent = <&gpio3>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
......
......@@ -21,14 +21,8 @@ properties:
description: power supply (1.8V)
enable-gpios: true
retimer-switch:
description: Flag the port as possible handle of SuperSpeed signals retiming
type: boolean
orientation-switch:
description: Flag the port as possible handler of orientation switching
type: boolean
orientation-switch: true
retimer-switch: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
......@@ -95,6 +89,9 @@ required:
- compatible
- reg
allOf:
- $ref: usb-switch.yaml#
additionalProperties: false
examples:
......
......@@ -102,7 +102,7 @@ properties:
description: |
Different types of interrupts are used based on HS PHY used on target:
- pwr_event: Used for wakeup based on other power events.
- hs_phY_irq: Apart from DP/DM/QUSB2 PHY interrupts, there is
- hs_phy_irq: Apart from DP/DM/QUSB2 PHY interrupts, there is
hs_phy_irq which is not triggered by default and its
functionality is mutually exclusive to that of
{dp/dm}_hs_phy_irq and qusb2_phy_irq.
......
......@@ -14,8 +14,19 @@ description:
properties:
compatible:
enum:
- qcom,pm8150b-typec
oneOf:
- enum:
- qcom,pmi632-typec
- qcom,pm8150b-typec
- items:
- enum:
- qcom,pm6150-typec
- const: qcom,pm8150b-typec
- items:
- enum:
- qcom,pm4125-typec
- const: qcom,pmi632-typec
connector:
type: object
......@@ -24,9 +35,11 @@ properties:
reg:
description: Type-C port and pdphy SPMI register base offsets
minItems: 1
maxItems: 2
interrupts:
minItems: 8
items:
- description: Type-C CC attach notification, VBUS error, tCCDebounce done
- description: Type-C VCONN powered
......@@ -46,6 +59,7 @@ properties:
- description: Power Domain Fast Role Swap event
interrupt-names:
minItems: 8
items:
- const: or-rid-detect-change
- const: vpd-detect
......@@ -81,7 +95,33 @@ required:
- interrupts
- interrupt-names
- vdd-vbus-supply
- vdd-pdphy-supply
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,pmi632-typec
then:
properties:
reg:
maxItems: 1
interrupts:
maxItems: 8
interrupt-names:
maxItems: 8
vdd-pdphy-supply: false
else:
properties:
reg:
maxItems: 2
interrupts:
minItems: 16
interrupt-names:
maxItems: 16
required:
- vdd-pdphy-supply
additionalProperties: false
......
......@@ -35,13 +35,8 @@ properties:
vdd-supply:
description: USBSS VDD power supply
mode-switch:
description: Flag the port as possible handle of altmode switching
type: boolean
orientation-switch:
description: Flag the port as possible handler of orientation switching
type: boolean
mode-switch: true
orientation-switch: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
......@@ -63,6 +58,9 @@ required:
- reg
- ports
allOf:
- $ref: usb-switch.yaml#
additionalProperties: false
examples:
......
......@@ -21,6 +21,12 @@ properties:
reg: true
'#address-cells':
const: 1
'#size-cells':
const: 0
vdd-supply:
description:
phandle to the regulator that provides power to the hub.
......@@ -30,6 +36,36 @@ properties:
description:
phandle to the peer hub on the controller.
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
1st downstream facing USB port
port@2:
$ref: /schemas/graph.yaml#/properties/port
description:
2nd downstream facing USB port
port@3:
$ref: /schemas/graph.yaml#/properties/port
description:
3rd downstream facing USB port
port@4:
$ref: /schemas/graph.yaml#/properties/port
description:
4th downstream facing USB port
patternProperties:
'^.*@[1-4]$':
description: The hard wired USB devices
type: object
$ref: /schemas/usb/usb-device.yaml
required:
- peer-hub
- compatible
......@@ -50,6 +86,13 @@ examples:
reg = <1>;
vdd-supply = <&pp3300_hub>;
peer-hub = <&hub_3_0>;
#address-cells = <1>;
#size-cells = <0>;
/* USB 2.0 device on port 2 */
device@2 {
compatible = "usb123,4567";
reg = <2>;
};
};
/* 3.0 hub on port 2 */
......@@ -58,5 +101,17 @@ examples:
reg = <2>;
vdd-supply = <&pp3300_hub>;
peer-hub = <&hub_2_0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
/* Type-A connector on port 4 */
port@4 {
reg = <4>;
endpoint {
remote-endpoint = <&usb_a0_ss>;
};
};
};
};
};
......@@ -14,7 +14,10 @@ properties:
const: ti,am62-usb
reg:
maxItems: 1
minItems: 1
items:
- description: USB CFG register space
- description: USB PHY2 register space
ranges: true
......@@ -82,7 +85,8 @@ examples:
usbss1: usb@f910000 {
compatible = "ti,am62-usb";
reg = <0x00 0x0f910000 0x00 0x800>;
reg = <0x00 0x0f910000 0x00 0x800>,
<0x00 0x0f918000 0x00 0x400>;
clocks = <&k3_clks 162 3>;
clock-names = "ref";
ti,syscon-phy-pll-refclk = <&wkup_conf 0x4018>;
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/ti,usb8020b.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI USB8020B USB 3.0 hub controller
maintainers:
- Macpaul Lin <macpaul.lin@mediatek.com>
allOf:
- $ref: usb-device.yaml#
properties:
compatible:
enum:
- usb451,8025
- usb451,8027
reg: true
reset-gpios:
items:
- description: GPIO specifier for GRST# pin.
vdd-supply:
description:
VDD power supply to the hub
peer-hub:
$ref: /schemas/types.yaml#/definitions/phandle
description:
phandle to the peer hub on the controller.
required:
- compatible
- reg
- peer-hub
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
usb {
dr_mode = "host";
#address-cells = <1>;
#size-cells = <0>;
/* 2.0 hub on port 1 */
hub_2_0: hub@1 {
compatible = "usb451,8027";
reg = <1>;
peer-hub = <&hub_3_0>;
reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
vdd-supply = <&usb_hub_fixed_3v3>;
};
/* 3.0 hub on port 2 */
hub_3_0: hub@2 {
compatible = "usb451,8025";
reg = <2>;
peer-hub = <&hub_2_0>;
reset-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
vdd-supply = <&usb_hub_fixed_3v3>;
};
};
......@@ -37,10 +37,11 @@ properties:
description: Should specify the GPIO detecting a VBus insertion
maxItems: 1
vbus-regulator:
description: Should specify the regulator supplying current drawn from
the VBus line.
$ref: /schemas/types.yaml#/definitions/phandle
vbus-supply:
description: regulator supplying VBUS. It will be enabled and disabled
dynamically in OTG mode. If the regulator is controlled by a
GPIO line, this should be modeled as a regulator-fixed and
referenced by this supply.
wakeup-source:
description:
......@@ -65,7 +66,7 @@ examples:
vcc-supply = <&hsusb1_vcc_regulator>;
reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
vbus-detect-gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
vbus-regulator = <&vbus_regulator>;
vbus-supply = <&vbus_regulator>;
#phy-cells = <0>;
};
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-switch.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: USB Orientation and Mode Switches Common Properties
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
description:
Common properties for devices handling USB mode and orientation switching.
properties:
mode-switch:
description: Possible handler of altmode switching
type: boolean
orientation-switch:
description: Possible handler of orientation switching
type: boolean
retimer-switch:
description: Possible handler of SuperSpeed signals retiming
type: boolean
port:
$ref: /schemas/graph.yaml#/properties/port
description:
A port node to link the device to a TypeC controller for the purpose of
handling altmode muxing and orientation switching.
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description:
Super Speed (SS) Output endpoint to the Type-C connector
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
description:
Super Speed (SS) Input endpoint from the Super-Speed PHY
unevaluatedProperties: false
properties:
endpoint:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
unevaluatedProperties: false
properties:
data-lanes:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
uniqueItems: true
items:
maximum: 8
oneOf:
- required:
- port
- required:
- ports
additionalProperties: true
......@@ -25,6 +25,8 @@ properties:
usb-phy:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
maxItems: 1
description:
List of all the USB PHYs on this HCD to be accepted by the legacy USB
Physical Layer subsystem.
......
......@@ -99,8 +99,10 @@ The disconnect() callback
This callback is a signal to break any connection with an interface.
You are not allowed any IO to a device after returning from this
callback. You also may not do any other operation that may interfere
with another driver bound the interface, eg. a power management
operation.
with another driver bound to the interface, eg. a power management
operation. Outstanding operations on the device must be completed or
aborted before this callback may return.
If you are called due to a physical disconnection, all your URBs will be
killed by usbcore. Note that in this case disconnect will be called some
time after the physical disconnection. Thus your driver must be prepared
......
......@@ -2,6 +2,9 @@
How FunctionFS works
====================
Overview
========
From kernel point of view it is just a composite function with some
unique behaviour. It may be added to an USB configuration only after
the user space driver has registered by writing descriptors and
......@@ -66,3 +69,36 @@ have been written to their ep0's.
Conversely, the gadget is unregistered after the first USB function
closes its endpoints.
DMABUF interface
================
FunctionFS additionally supports a DMABUF based interface, where the
userspace can attach DMABUF objects (externally created) to an endpoint,
and subsequently use them for data transfers.
A userspace application can then use this interface to share DMABUF
objects between several interfaces, allowing it to transfer data in a
zero-copy fashion, for instance between IIO and the USB stack.
As part of this interface, three new IOCTLs have been added. These three
IOCTLs have to be performed on a data endpoint (ie. not ep0). They are:
``FUNCTIONFS_DMABUF_ATTACH(int)``
Attach the DMABUF object, identified by its file descriptor, to the
data endpoint. Returns zero on success, and a negative errno value
on error.
``FUNCTIONFS_DMABUF_DETACH(int)``
Detach the given DMABUF object, identified by its file descriptor,
from the data endpoint. Returns zero on success, and a negative
errno value on error. Note that closing the endpoint's file
descriptor will automatically detach all attached DMABUFs.
``FUNCTIONFS_DMABUF_TRANSFER(struct usb_ffs_dmabuf_transfer_req *)``
Enqueue the previously attached DMABUF to the transfer queue.
The argument is a structure that packs the DMABUF's file descriptor,
the size in bytes to transfer (which should generally correspond to
the size of the DMABUF), and a 'flags' field which is unused
for now. Returns zero on success, and a negative errno value on
error.
......@@ -206,6 +206,14 @@ the standard procedure for using FunctionFS (mount it, run the userspace
process which implements the function proper). The gadget should be enabled
by writing a suitable string to usb_gadget/<gadget>/UDC.
The FFS function provides just one attribute in its function directory:
ready
The attribute is read-only and signals if the function is ready (1) to be
used, E.G. if userspace has written descriptors and strings to ep0, so
the gadget can be enabled.
Testing the FFS function
------------------------
......
......@@ -63,6 +63,52 @@ pm6150_resin: resin {
};
};
pm6150_vbus: usb-vbus-regulator@1100 {
compatible = "qcom,pm6150-vbus-reg,
qcom,pm8150b-vbus-reg";
reg = <0x1100>;
status = "disabled";
};
pm6150_typec: typec@1500 {
compatible = "qcom,pm6150-typec,
qcom,pm8150b-typec";
reg = <0x1500>, <0x1700>;
interrupts = <0x0 0x15 0x00 IRQ_TYPE_EDGE_RISING>,
<0x0 0x15 0x01 IRQ_TYPE_EDGE_BOTH>,
<0x0 0x15 0x02 IRQ_TYPE_EDGE_RISING>,
<0x0 0x15 0x03 IRQ_TYPE_EDGE_BOTH>,
<0x0 0x15 0x04 IRQ_TYPE_EDGE_RISING>,
<0x0 0x15 0x05 IRQ_TYPE_EDGE_RISING>,
<0x0 0x15 0x06 IRQ_TYPE_EDGE_BOTH>,
<0x0 0x15 0x07 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x00 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x01 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x02 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x03 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x04 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x05 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x06 IRQ_TYPE_EDGE_RISING>,
<0x0 0x17 0x07 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "or-rid-detect-change",
"vpd-detect",
"cc-state-change",
"vconn-oc",
"vbus-change",
"attach-detach",
"legacy-cable-detect",
"try-snk-src-detect",
"sig-tx",
"sig-rx",
"msg-tx",
"msg-rx",
"msg-tx-failed",
"msg-tx-discarded",
"msg-rx-discarded",
"fr-swap";
status = "disabled";
};
pm6150_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
......
......@@ -126,7 +126,7 @@ SATA0: sata@30000010000 {
interrupts = <93 2>;
};
EHCI0: ehci@30010000000 {
EHCI0: usb@30010000000 {
compatible = "ibm,476gtr-ehci", "generic-ehci";
reg = <0x300 0x10000000 0x0 0x10000>;
interrupt-parent = <&MPIC>;
......@@ -140,14 +140,14 @@ SD0: sd@30000000000 {
interrupt-parent = <&MPIC>;
};
OHCI0: ohci@30010010000 {
OHCI0: usb@30010010000 {
compatible = "ibm,476gtr-ohci", "generic-ohci";
reg = <0x300 0x10010000 0x0 0x10000>;
interrupt-parent = <&MPIC>;
interrupts = <89 1>;
};
OHCI1: ohci@30010020000 {
OHCI1: usb@30010020000 {
compatible = "ibm,476gtr-ohci", "generic-ohci";
reg = <0x300 0x10020000 0x0 0x10000>;
interrupt-parent = <&MPIC>;
......
......@@ -87,6 +87,7 @@ source "drivers/phy/motorola/Kconfig"
source "drivers/phy/mscc/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
source "drivers/phy/realtek/Kconfig"
source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
......
......@@ -26,6 +26,7 @@ obj-y += allwinner/ \
mscc/ \
qualcomm/ \
ralink/ \
realtek/ \
renesas/ \
rockchip/ \
samsung/ \
......
......@@ -489,6 +489,53 @@ int phy_calibrate(struct phy *phy)
}
EXPORT_SYMBOL_GPL(phy_calibrate);
/**
* phy_notify_connect() - phy connect notification
* @phy: the phy returned by phy_get()
* @port: the port index for connect
*
* If the phy needs to get connection status, the callback can be used.
* Returns: %0 if successful, a negative error code otherwise
*/
int phy_notify_connect(struct phy *phy, int port)
{
int ret;
if (!phy || !phy->ops->connect)
return 0;
mutex_lock(&phy->mutex);
ret = phy->ops->connect(phy, port);
mutex_unlock(&phy->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(phy_notify_connect);
/**
* phy_notify_disconnect() - phy disconnect notification
* @phy: the phy returned by phy_get()
* @port: the port index for disconnect
*
* If the phy needs to get connection status, the callback can be used.
*
* Returns: %0 if successful, a negative error code otherwise
*/
int phy_notify_disconnect(struct phy *phy, int port)
{
int ret;
if (!phy || !phy->ops->disconnect)
return 0;
mutex_lock(&phy->mutex);
ret = phy->ops->disconnect(phy, port);
mutex_unlock(&phy->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(phy_notify_disconnect);
/**
* phy_configure() - Changes the phy parameters
* @phy: the phy returned by phy_get()
......
# SPDX-License-Identifier: GPL-2.0
#
# Phy drivers for Realtek platforms
#
if ARCH_REALTEK || COMPILE_TEST
config PHY_RTK_RTD_USB2PHY
tristate "Realtek RTD USB2 PHY Transceiver Driver"
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
select USB_COMMON
help
Enable this to support Realtek SoC USB2 phy transceiver.
The DHC (digital home center) RTD series SoCs used the Synopsys
DWC3 USB IP. This driver will do the PHY initialization
of the parameters.
config PHY_RTK_RTD_USB3PHY
tristate "Realtek RTD USB3 PHY Transceiver Driver"
depends on USB_SUPPORT
select GENERIC_PHY
select USB_PHY
select USB_COMMON
help
Enable this to support Realtek SoC USB3 phy transceiver.
The DHC (digital home center) RTD series SoCs used the Synopsys
DWC3 USB IP. This driver will do the PHY initialization
of the parameters.
endif # ARCH_REALTEK || COMPILE_TEST
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_RTK_RTD_USB2PHY) += phy-rtk-usb2.o
obj-$(CONFIG_PHY_RTK_RTD_USB3PHY) += phy-rtk-usb3.o
This diff is collapsed.
This diff is collapsed.
......@@ -1531,6 +1531,19 @@ int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
}
EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_usb3_companion);
int tegra_xusb_padctl_get_port_number(struct phy *phy)
{
struct tegra_xusb_lane *lane;
if (!phy)
return -ENODEV;
lane = phy_get_drvdata(phy);
return lane->index;
}
EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_port_number);
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver");
MODULE_LICENSE("GPL v2");
......@@ -24,6 +24,23 @@
#define DP_PORT_VDO (DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)) | \
DP_CAP_DFP_D | DP_CAP_RECEPTACLE)
static void cros_typec_role_switch_quirk(struct fwnode_handle *fwnode)
{
#ifdef CONFIG_ACPI
struct fwnode_handle *switch_fwnode;
/* Supply the USB role switch with the correct pld_crc if it's missing. */
switch_fwnode = fwnode_find_reference(fwnode, "usb-role-switch", 0);
if (!IS_ERR_OR_NULL(switch_fwnode)) {
struct acpi_device *adev = to_acpi_device_node(switch_fwnode);
if (adev && !adev->pld_crc)
adev->pld_crc = to_acpi_device_node(fwnode)->pld_crc;
fwnode_handle_put(switch_fwnode);
}
#endif
}
static int cros_typec_parse_port_props(struct typec_capability *cap,
struct fwnode_handle *fwnode,
struct device *dev)
......@@ -66,6 +83,8 @@ static int cros_typec_parse_port_props(struct typec_capability *cap,
cap->prefer_role = ret;
}
cros_typec_role_switch_quirk(fwnode);
cap->fwnode = fwnode;
return 0;
......
# SPDX-License-Identifier: GPL-2.0-only
ccflags-y := -I$(src)
obj-${CONFIG_USB4} := thunderbolt.o
thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o eeprom.o
thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o
......
......@@ -15,6 +15,8 @@
#include "ctl.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
#define TB_CTL_RX_PKG_COUNT 10
#define TB_CTL_RETRIES 4
......@@ -32,6 +34,7 @@
* @timeout_msec: Default timeout for non-raw control messages
* @callback: Callback called when hotplug message is received
* @callback_data: Data passed to @callback
* @index: Domain number. This will be output with the trace record.
*/
struct tb_ctl {
struct tb_nhi *nhi;
......@@ -47,6 +50,8 @@ struct tb_ctl {
int timeout_msec;
event_cb callback;
void *callback_data;
int index;
};
......@@ -369,6 +374,9 @@ static int tb_ctl_tx(struct tb_ctl *ctl, const void *data, size_t len,
pkg->frame.size = len + 4;
pkg->frame.sof = type;
pkg->frame.eof = type;
trace_tb_tx(ctl->index, type, data, len);
cpu_to_be32_array(pkg->buffer, data, len / 4);
*(__be32 *) (pkg->buffer + len) = tb_crc(pkg->buffer, len);
......@@ -384,6 +392,7 @@ static int tb_ctl_tx(struct tb_ctl *ctl, const void *data, size_t len,
static bool tb_ctl_handle_event(struct tb_ctl *ctl, enum tb_cfg_pkg_type type,
struct ctl_pkg *pkg, size_t size)
{
trace_tb_event(ctl->index, type, pkg->buffer, size);
return ctl->callback(ctl->callback_data, type, pkg->buffer, size);
}
......@@ -489,6 +498,9 @@ static void tb_ctl_rx_callback(struct tb_ring *ring, struct ring_frame *frame,
* triggered from messing with the active requests.
*/
req = tb_cfg_request_find(pkg->ctl, pkg);
trace_tb_rx(pkg->ctl->index, frame->eof, pkg->buffer, frame->size, !req);
if (req) {
if (req->copy(req, pkg))
schedule_work(&req->work);
......@@ -614,6 +626,7 @@ struct tb_cfg_result tb_cfg_request_sync(struct tb_ctl *ctl,
/**
* tb_ctl_alloc() - allocate a control channel
* @nhi: Pointer to NHI
* @index: Domain number
* @timeout_msec: Default timeout used with non-raw control messages
* @cb: Callback called for plug events
* @cb_data: Data passed to @cb
......@@ -622,14 +635,16 @@ struct tb_cfg_result tb_cfg_request_sync(struct tb_ctl *ctl,
*
* Return: Returns a pointer on success or NULL on failure.
*/
struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, int timeout_msec, event_cb cb,
void *cb_data)
struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, int index, int timeout_msec,
event_cb cb, void *cb_data)
{
int i;
struct tb_ctl *ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
if (!ctl)
return NULL;
ctl->nhi = nhi;
ctl->index = index;
ctl->timeout_msec = timeout_msec;
ctl->callback = cb;
ctl->callback_data = cb_data;
......
......@@ -21,8 +21,8 @@ struct tb_ctl;
typedef bool (*event_cb)(void *data, enum tb_cfg_pkg_type type,
const void *buf, size_t size);
struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, int timeout_msec, event_cb cb,
void *cb_data);
struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, int index, int timeout_msec,
event_cb cb, void *cb_data);
void tb_ctl_start(struct tb_ctl *ctl);
void tb_ctl_stop(struct tb_ctl *ctl);
void tb_ctl_free(struct tb_ctl *ctl);
......
......@@ -321,12 +321,12 @@ static void tb_domain_release(struct device *dev)
tb_ctl_free(tb->ctl);
destroy_workqueue(tb->wq);
ida_simple_remove(&tb_domain_ida, tb->index);
ida_free(&tb_domain_ida, tb->index);
mutex_destroy(&tb->lock);
kfree(tb);
}
struct device_type tb_domain_type = {
const struct device_type tb_domain_type = {
.name = "thunderbolt_domain",
.release = tb_domain_release,
};
......@@ -389,7 +389,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
tb->nhi = nhi;
mutex_init(&tb->lock);
tb->index = ida_simple_get(&tb_domain_ida, 0, 0, GFP_KERNEL);
tb->index = ida_alloc(&tb_domain_ida, GFP_KERNEL);
if (tb->index < 0)
goto err_free;
......@@ -397,7 +397,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
if (!tb->wq)
goto err_remove_ida;
tb->ctl = tb_ctl_alloc(nhi, timeout_msec, tb_domain_event_cb, tb);
tb->ctl = tb_ctl_alloc(nhi, tb->index, timeout_msec, tb_domain_event_cb, tb);
if (!tb->ctl)
goto err_destroy_wq;
......@@ -413,7 +413,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
err_destroy_wq:
destroy_workqueue(tb->wq);
err_remove_ida:
ida_simple_remove(&tb_domain_ida, tb->index);
ida_free(&tb_domain_ida, tb->index);
err_free:
kfree(tb);
......@@ -423,6 +423,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
/**
* tb_domain_add() - Add domain to the system
* @tb: Domain to add
* @reset: Issue reset to the host router
*
* Starts the domain and adds it to the system. Hotplugging devices will
* work after this has been returned successfully. In order to remove
......@@ -431,7 +432,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
*
* Return: %0 in case of success and negative errno in case of error
*/
int tb_domain_add(struct tb *tb)
int tb_domain_add(struct tb *tb, bool reset)
{
int ret;
......@@ -460,7 +461,7 @@ int tb_domain_add(struct tb *tb)
/* Start the domain */
if (tb->cm_ops->start) {
ret = tb->cm_ops->start(tb);
ret = tb->cm_ops->start(tb, reset);
if (ret)
goto err_domain_del;
}
......@@ -505,6 +506,10 @@ void tb_domain_remove(struct tb *tb)
mutex_unlock(&tb->lock);
flush_workqueue(tb->wq);
if (tb->cm_ops->deinit)
tb->cm_ops->deinit(tb);
device_unregister(&tb->dev);
}
......
......@@ -2144,7 +2144,7 @@ static int icm_runtime_resume(struct tb *tb)
return 0;
}
static int icm_start(struct tb *tb)
static int icm_start(struct tb *tb, bool not_used)
{
struct icm *icm = tb_priv(tb);
int ret;
......
......@@ -6,6 +6,8 @@
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*/
#include <linux/delay.h>
#include "tb.h"
/**
......@@ -45,6 +47,49 @@ static int find_port_lc_cap(struct tb_port *port)
return sw->cap_lc + start + phys * size;
}
/**
* tb_lc_reset_port() - Trigger downstream port reset through LC
* @port: Port that is reset
*
* Triggers downstream port reset through link controller registers.
* Returns %0 in case of success negative errno otherwise. Only supports
* non-USB4 routers with link controller (that's Thunderbolt 2 and
* Thunderbolt 3).
*/
int tb_lc_reset_port(struct tb_port *port)
{
struct tb_switch *sw = port->sw;
int cap, ret;
u32 mode;
if (sw->generation < 2)
return -EINVAL;
cap = find_port_lc_cap(port);
if (cap < 0)
return cap;
ret = tb_sw_read(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
if (ret)
return ret;
mode |= TB_LC_PORT_MODE_DPR;
ret = tb_sw_write(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
if (ret)
return ret;
fsleep(10000);
ret = tb_sw_read(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
if (ret)
return ret;
mode &= ~TB_LC_PORT_MODE_DPR;
return tb_sw_write(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
}
static int tb_lc_set_port_configured(struct tb_port *port, bool configured)
{
bool upstream = tb_is_upstream_port(port);
......
......@@ -48,7 +48,7 @@
static bool host_reset = true;
module_param(host_reset, bool, 0444);
MODULE_PARM_DESC(host_reset, "reset USBv2 host router (default: true)");
MODULE_PARM_DESC(host_reset, "reset USB4 host router (default: true)");
static int ring_interrupt_index(const struct tb_ring *ring)
{
......@@ -465,7 +465,7 @@ static int ring_request_msix(struct tb_ring *ring, bool no_suspend)
if (!nhi->pdev->msix_enabled)
return 0;
ret = ida_simple_get(&nhi->msix_ida, 0, MSIX_MAX_VECS, GFP_KERNEL);
ret = ida_alloc_max(&nhi->msix_ida, MSIX_MAX_VECS - 1, GFP_KERNEL);
if (ret < 0)
return ret;
......@@ -485,7 +485,7 @@ static int ring_request_msix(struct tb_ring *ring, bool no_suspend)
return 0;
err_ida_remove:
ida_simple_remove(&nhi->msix_ida, ring->vector);
ida_free(&nhi->msix_ida, ring->vector);
return ret;
}
......@@ -496,7 +496,7 @@ static void ring_release_msix(struct tb_ring *ring)
return;
free_irq(ring->irq, ring);
ida_simple_remove(&ring->nhi->msix_ida, ring->vector);
ida_free(&ring->nhi->msix_ida, ring->vector);
ring->vector = 0;
ring->irq = 0;
}
......@@ -1364,7 +1364,6 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
nhi_check_quirks(nhi);
nhi_check_iommu(nhi);
nhi_reset(nhi);
res = nhi_init_msi(nhi);
......@@ -1392,7 +1391,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_dbg(dev, "NHI initialized, starting thunderbolt\n");
res = tb_domain_add(tb);
res = tb_domain_add(tb, host_reset);
if (res) {
/*
* At this point the RX/TX rings might already have been
......
......@@ -330,7 +330,7 @@ struct tb_nvm *tb_nvm_alloc(struct device *dev)
if (!nvm)
return ERR_PTR(-ENOMEM);
ret = ida_simple_get(&nvm_ida, 0, 0, GFP_KERNEL);
ret = ida_alloc(&nvm_ida, GFP_KERNEL);
if (ret < 0) {
kfree(nvm);
return ERR_PTR(ret);
......@@ -528,7 +528,7 @@ void tb_nvm_free(struct tb_nvm *nvm)
nvmem_unregister(nvm->non_active);
nvmem_unregister(nvm->active);
vfree(nvm->buf);
ida_simple_remove(&nvm_ida, nvm->id);
ida_free(&nvm_ida, nvm->id);
}
kfree(nvm);
}
......
......@@ -446,6 +446,19 @@ static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index,
return -ETIMEDOUT;
}
/**
* tb_path_deactivate_hop() - Deactivate one path in path config space
* @port: Lane or protocol adapter
* @hop_index: HopID of the path to be cleared
*
* This deactivates or clears a single path config space entry at
* @hop_index. Returns %0 in success and negative errno otherwise.
*/
int tb_path_deactivate_hop(struct tb_port *port, int hop_index)
{
return __tb_path_deactivate_hop(port, hop_index, true);
}
static void __tb_path_deactivate_hops(struct tb_path *path, int first_hop)
{
int i, res;
......
......@@ -43,6 +43,12 @@ static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
}
}
static void quirk_block_rpm_in_redrive(struct tb_switch *sw)
{
sw->quirks |= QUIRK_KEEP_POWER_IN_DP_REDRIVE;
tb_sw_dbg(sw, "preventing runtime PM in DP redrive mode\n");
}
struct tb_quirk {
u16 hw_vendor_id;
u16 hw_device_id;
......@@ -86,6 +92,14 @@ static const struct tb_quirk tb_quirks[] = {
quirk_usb3_maximum_bandwidth },
{ 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_40G_BRIDGE, 0x0000, 0x0000,
quirk_usb3_maximum_bandwidth },
/*
* Block Runtime PM in DP redrive mode for Intel Barlow Ridge host
* controllers.
*/
{ 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI, 0x0000, 0x0000,
quirk_block_rpm_in_redrive },
{ 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI, 0x0000, 0x0000,
quirk_block_rpm_in_redrive },
/*
* CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms.
*/
......
......@@ -356,7 +356,7 @@ static void tb_retimer_release(struct device *dev)
kfree(rt);
}
struct device_type tb_retimer_type = {
const struct device_type tb_retimer_type = {
.name = "thunderbolt_retimer",
.groups = retimer_groups,
.release = tb_retimer_release,
......
......@@ -676,6 +676,13 @@ int tb_port_disable(struct tb_port *port)
return __tb_port_enable(port, false);
}
static int tb_port_reset(struct tb_port *port)
{
if (tb_switch_is_usb4(port->sw))
return port->cap_usb4 ? usb4_port_reset(port) : 0;
return tb_lc_reset_port(port);
}
/*
* tb_init_port() - initialize a port
*
......@@ -771,7 +778,7 @@ static int tb_port_alloc_hopid(struct tb_port *port, bool in, int min_hopid,
if (max_hopid < 0 || max_hopid > port_max_hopid)
max_hopid = port_max_hopid;
return ida_simple_get(ida, min_hopid, max_hopid + 1, GFP_KERNEL);
return ida_alloc_range(ida, min_hopid, max_hopid, GFP_KERNEL);
}
/**
......@@ -809,7 +816,7 @@ int tb_port_alloc_out_hopid(struct tb_port *port, int min_hopid, int max_hopid)
*/
void tb_port_release_in_hopid(struct tb_port *port, int hopid)
{
ida_simple_remove(&port->in_hopids, hopid);
ida_free(&port->in_hopids, hopid);
}
/**
......@@ -819,7 +826,7 @@ void tb_port_release_in_hopid(struct tb_port *port, int hopid)
*/
void tb_port_release_out_hopid(struct tb_port *port, int hopid)
{
ida_simple_remove(&port->out_hopids, hopid);
ida_free(&port->out_hopids, hopid);
}
static inline bool tb_switch_is_reachable(const struct tb_switch *parent,
......@@ -1120,7 +1127,7 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
ret = tb_port_set_link_width(port->dual_link_port,
TB_LINK_WIDTH_DUAL);
if (ret)
goto err_lane0;
goto err_lane1;
}
/*
......@@ -1534,29 +1541,124 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw)
regs->__unknown1, regs->__unknown4);
}
static int tb_switch_reset_host(struct tb_switch *sw)
{
if (sw->generation > 1) {
struct tb_port *port;
tb_switch_for_each_port(sw, port) {
int i, ret;
/*
* For lane adapters we issue downstream port
* reset and clear up path config spaces.
*
* For protocol adapters we disable the path and
* clear path config space one by one (from 8 to
* Max Input HopID of the adapter).
*/
if (tb_port_is_null(port) && !tb_is_upstream_port(port)) {
ret = tb_port_reset(port);
if (ret)
return ret;
} else if (tb_port_is_usb3_down(port) ||
tb_port_is_usb3_up(port)) {
tb_usb3_port_enable(port, false);
} else if (tb_port_is_dpin(port) ||
tb_port_is_dpout(port)) {
tb_dp_port_enable(port, false);
} else if (tb_port_is_pcie_down(port) ||
tb_port_is_pcie_up(port)) {
tb_pci_port_enable(port, false);
} else {
continue;
}
/* Cleanup path config space of protocol adapter */
for (i = TB_PATH_MIN_HOPID;
i <= port->config.max_in_hop_id; i++) {
ret = tb_path_deactivate_hop(port, i);
if (ret)
return ret;
}
}
} else {
struct tb_cfg_result res;
/* Thunderbolt 1 uses the "reset" config space packet */
res.err = tb_sw_write(sw, ((u32 *) &sw->config) + 2,
TB_CFG_SWITCH, 2, 2);
if (res.err)
return res.err;
res = tb_cfg_reset(sw->tb->ctl, tb_route(sw));
if (res.err > 0)
return -EIO;
else if (res.err < 0)
return res.err;
}
return 0;
}
static int tb_switch_reset_device(struct tb_switch *sw)
{
return tb_port_reset(tb_switch_downstream_port(sw));
}
static bool tb_switch_enumerated(struct tb_switch *sw)
{
u32 val;
int ret;
/*
* Read directly from the hardware because we use this also
* during system sleep where sw->config.enabled is already set
* by us.
*/
ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_3, 1);
if (ret)
return false;
return !!(val & ROUTER_CS_3_V);
}
/**
* tb_switch_reset() - reconfigure route, enable and send TB_CFG_PKG_RESET
* @sw: Switch to reset
* tb_switch_reset() - Perform reset to the router
* @sw: Router to reset
*
* Return: Returns 0 on success or an error code on failure.
* Issues reset to the router @sw. Can be used for any router. For host
* routers, resets all the downstream ports and cleans up path config
* spaces accordingly. For device routers issues downstream port reset
* through the parent router, so as side effect there will be unplug
* soon after this is finished.
*
* If the router is not enumerated does nothing.
*
* Returns %0 on success or negative errno in case of failure.
*/
int tb_switch_reset(struct tb_switch *sw)
{
struct tb_cfg_result res;
int ret;
if (sw->generation > 1)
/*
* We cannot access the port config spaces unless the router is
* already enumerated. If the router is not enumerated it is
* equal to being reset so we can skip that here.
*/
if (!tb_switch_enumerated(sw))
return 0;
tb_sw_dbg(sw, "resetting switch\n");
tb_sw_dbg(sw, "resetting\n");
res.err = tb_sw_write(sw, ((u32 *) &sw->config) + 2,
TB_CFG_SWITCH, 2, 2);
if (res.err)
return res.err;
res = tb_cfg_reset(sw->tb->ctl, tb_route(sw));
if (res.err > 0)
return -EIO;
return res.err;
if (tb_route(sw))
ret = tb_switch_reset_device(sw);
else
ret = tb_switch_reset_host(sw);
if (ret)
tb_sw_warn(sw, "failed to reset\n");
return ret;
}
/**
......@@ -2228,7 +2330,7 @@ static const struct dev_pm_ops tb_switch_pm_ops = {
NULL)
};
struct device_type tb_switch_type = {
const struct device_type tb_switch_type = {
.name = "thunderbolt_device",
.release = tb_switch_release,
.uevent = tb_switch_uevent,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -139,6 +139,12 @@ static inline bool tb_tunnel_is_usb3(const struct tb_tunnel *tunnel)
return tunnel->type == TB_TUNNEL_USB3;
}
static inline bool tb_tunnel_direction_downstream(const struct tb_tunnel *tunnel)
{
return tb_port_path_direction_downstream(tunnel->src_port,
tunnel->dst_port);
}
const char *tb_tunnel_type_name(const struct tb_tunnel *tunnel);
#define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...) \
......
This diff is collapsed.
......@@ -243,7 +243,7 @@ static void usb4_port_device_release(struct device *dev)
kfree(usb4);
}
struct device_type usb4_port_device_type = {
const struct device_type usb4_port_device_type = {
.name = "usb4_port",
.groups = usb4_port_device_groups,
.release = usb4_port_device_release,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment