summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt5
-rw-r--r--Documentation/devicetree/bindings/usb/mediatek,mtu3.txt5
-rw-r--r--Documentation/devicetree/bindings/usb/usb-ehci.txt6
-rw-r--r--Documentation/devicetree/bindings/usb/usb-hcd.txt9
-rw-r--r--Documentation/devicetree/bindings/usb/usb-ohci.txt6
-rw-r--r--Documentation/devicetree/bindings/usb/usb-uhci.txt3
-rw-r--r--Documentation/devicetree/bindings/usb/usb-xhci.txt5
-rw-r--r--drivers/staging/typec/tcpci.c127
-rw-r--r--drivers/staging/typec/tcpci.h14
-rw-r--r--drivers/usb/chipidea/debug.c65
-rw-r--r--drivers/usb/chipidea/host.c6
-rw-r--r--drivers/usb/core/Makefile2
-rw-r--r--drivers/usb/core/hcd.c64
-rw-r--r--drivers/usb/core/hub.c12
-rw-r--r--drivers/usb/core/phy.c158
-rw-r--r--drivers/usb/core/phy.h7
-rw-r--r--drivers/usb/core/usb-acpi.c4
-rw-r--r--drivers/usb/dwc2/debugfs.c84
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c33
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c17
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c20
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c42
-rw-r--r--drivers/usb/host/ehci-fsl.c2
-rw-r--r--drivers/usb/host/ehci-mem.c3
-rw-r--r--drivers/usb/host/ehci-platform.c55
-rw-r--r--drivers/usb/host/ehci-sched.c6
-rw-r--r--drivers/usb/host/ehci-tegra.c1
-rw-r--r--drivers/usb/host/fhci-dbg.c26
-rw-r--r--drivers/usb/host/imx21-dbg.c65
-rw-r--r--drivers/usb/host/isp116x-hcd.c15
-rw-r--r--drivers/usb/host/ohci-omap.c1
-rw-r--r--drivers/usb/host/ohci-platform.c56
-rw-r--r--drivers/usb/host/sl811-hcd.c17
-rw-r--r--drivers/usb/host/whci/debug.c48
-rw-r--r--drivers/usb/host/xhci-dbgtty.c5
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci-mtk.c98
-rw-r--r--drivers/usb/host/xhci-plat.c1
-rw-r--r--drivers/usb/host/xhci-ring.c27
-rw-r--r--drivers/usb/host/xhci.c139
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/isp1760/isp1760-udc.c6
-rw-r--r--drivers/usb/misc/adutux.c4
-rw-r--r--drivers/usb/misc/chaoskey.c8
-rw-r--r--drivers/usb/misc/usbtest.c5
-rw-r--r--drivers/usb/musb/musb_debugfs.c13
-rw-r--r--drivers/usb/typec/fusb302/fusb302.c17
-rw-r--r--drivers/usb/typec/tcpm.c33
-rw-r--r--drivers/usb/typec/tps6598x.c15
-rw-r--r--drivers/usb/typec/typec.c44
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c31
-rw-r--r--drivers/usb/usb-skeleton.c2
-rw-r--r--drivers/usb/usbip/Kconfig2
-rw-r--r--drivers/usb/wusbcore/crypto.c8
-rw-r--r--drivers/usb/wusbcore/wa-nep.c1
-rw-r--r--drivers/uwb/uwb-debug.c32
-rw-r--r--include/linux/usb/hcd.h8
-rw-r--r--include/linux/usb/pd.h185
-rw-r--r--include/linux/usb/pd_ado.h42
-rw-r--r--include/linux/usb/pd_ext_sdb.h31
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.c23
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h11
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.c5
-rw-r--r--tools/usb/usbip/src/usbip_attach.c10
-rw-r--r--tools/usb/usbip/src/usbip_list.c6
-rw-r--r--tools/usb/usbip/src/usbip_network.c10
-rw-r--r--tools/usb/usbip/src/usbip_network.h6
-rw-r--r--tools/usb/usbip/src/usbipd.c18
68 files changed, 946 insertions, 893 deletions
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
index 88d9f4a4b280..266c2d917a28 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
@@ -32,7 +32,7 @@ Required properties:
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
Optional properties:
- wakeup-source : enable USB remote wakeup;
@@ -52,6 +52,9 @@ Optional properties:
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- imod-interval-ns: default interrupt moderation interval is 5000ns
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
Example:
usb30: usb@11270000 {
compatible = "mediatek,mt8173-xhci";
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index d589a1ef96a1..3382b5cb471d 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
@@ -17,7 +17,7 @@ Required properties:
- clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dam_ck";
- - phys : a list of phandle + phy specifier pairs
+ - phys : see usb-hcd.txt in the current directory
- dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
@@ -53,6 +53,9 @@ Optional properties:
- mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
Sub-nodes:
The xhci should be added as subnode to mtu3 as shown in the following example
if host mode is enabled. The DT binding details of xhci can be found in:
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index 3efde12b5d68..0f1b75386207 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -16,10 +16,12 @@ Optional properties:
- has-transaction-translator : boolean, set this if EHCI have a Transaction
Translator built into the root hub.
- clocks : a list of phandle + clock specifier pairs
- - phys : phandle + phy specifier pair
- - phy-names : "usb"
+ - phys : see usb-hcd.txt in the current directory
- resets : phandle + reset specifier pair
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
Example (Sequoia 440EPx):
ehci@e0000300 {
compatible = "ibm,usb-ehci-440epx", "usb-ehci";
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.txt b/Documentation/devicetree/bindings/usb/usb-hcd.txt
new file mode 100644
index 000000000000..50529b838c9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.txt
@@ -0,0 +1,9 @@
+Generic USB HCD (Host Controller Device) Properties
+
+Optional properties:
+- phys: a list of all USB PHYs on this HCD
+
+Example:
+ &usb1 {
+ phys = <&usb2_phy1>, <&usb3_phy1>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 09e70c875bc6..a8d2103d1f3d 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -13,10 +13,12 @@ Optional properties:
- remote-wakeup-connected: remote wakeup is wired on the platform
- num-ports : u32, to override the detected port count
- clocks : a list of phandle + clock specifier pairs
-- phys : phandle + phy specifier pair
-- phy-names : "usb"
+- phys : see usb-hcd.txt in the current directory
- resets : a list of phandle + reset specifier pairs
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
Example:
ohci0: usb@1c14400 {
diff --git a/Documentation/devicetree/bindings/usb/usb-uhci.txt b/Documentation/devicetree/bindings/usb/usb-uhci.txt
index 298133416c97..cc2e6f7d602e 100644
--- a/Documentation/devicetree/bindings/usb/usb-uhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-uhci.txt
@@ -6,6 +6,9 @@ Required properties:
- reg : Should contain 1 register ranges(address and length)
- interrupts : UHCI controller interrupt
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
Example:
uhci@d8007b00 {
diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
index 1651483a7048..c4c00dff4b56 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -33,6 +33,11 @@ Optional properties:
- usb3-lpm-capable: determines if platform is USB3 LPM capable
- quirk-broken-port-ped: set if the controller has broken port disable mechanism
- imod-interval-ns: default interrupt moderation interval is 5000ns
+ - phys : see usb-hcd.txt in the current directory
+
+additionally the properties from usb-hcd.txt (in the current directory) are
+supported.
+
Example:
usb@f0931000 {
diff --git a/drivers/staging/typec/tcpci.c b/drivers/staging/typec/tcpci.c
index 9bd4412356c9..076d97eaff6f 100644
--- a/drivers/staging/typec/tcpci.c
+++ b/drivers/staging/typec/tcpci.c
@@ -21,7 +21,6 @@
struct tcpci {
struct device *dev;
- struct i2c_client *client;
struct tcpm_port *port;
@@ -30,6 +29,12 @@ struct tcpci {
bool controls_vbus;
struct tcpc_dev tcpc;
+ struct tcpci_data *data;
+};
+
+struct tcpci_chip {
+ struct tcpci *tcpci;
+ struct tcpci_data data;
};
static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
@@ -37,8 +42,7 @@ static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
return container_of(tcpc, struct tcpci, tcpc);
}
-static int tcpci_read16(struct tcpci *tcpci, unsigned int reg,
- u16 *val)
+static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, u16 *val)
{
return regmap_raw_read(tcpci->regmap, reg, val, sizeof(u16));
}
@@ -98,9 +102,17 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc,
enum typec_cc_status cc)
{
+ int ret;
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg = TCPC_ROLE_CTRL_DRP;
+ /* Handle vendor drp toggling */
+ if (tcpci->data->start_drp_toggling) {
+ ret = tcpci->data->start_drp_toggling(tcpci, tcpci->data, cc);
+ if (ret < 0)
+ return ret;
+ }
+
switch (cc) {
default:
case TYPEC_CC_RP_DEF:
@@ -117,7 +129,17 @@ static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc,
break;
}
- return regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
+ if (cc == TYPEC_CC_RD)
+ reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
+ (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
+ else
+ reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
+ (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT);
+ ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
+ if (ret < 0)
+ return ret;
+ return regmap_write(tcpci->regmap, TCPC_COMMAND,
+ TCPC_CMD_LOOK4CONNECTION);
}
static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink)
@@ -178,6 +200,13 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
int ret;
+ /* Handle vendor set vconn */
+ if (tcpci->data->set_vconn) {
+ ret = tcpci->data->set_vconn(tcpci, tcpci->data, enable);
+ if (ret < 0)
+ return ret;
+ }
+
ret = regmap_write(tcpci->regmap, TCPC_POWER_CTRL,
enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0);
if (ret < 0)
@@ -323,6 +352,13 @@ static int tcpci_init(struct tcpc_dev *tcpc)
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
+ /* Handle vendor init */
+ if (tcpci->data->init) {
+ ret = tcpci->data->init(tcpci, tcpci->data);
+ if (ret < 0)
+ return ret;
+ }
+
/* Clear all events */
ret = tcpci_write16(tcpci, TCPC_ALERT, 0xffff);
if (ret < 0)
@@ -344,9 +380,8 @@ static int tcpci_init(struct tcpc_dev *tcpc)
return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
}
-static irqreturn_t tcpci_irq(int irq, void *dev_id)
+irqreturn_t tcpci_irq(struct tcpci *tcpci)
{
- struct tcpci *tcpci = dev_id;
u16 status;
tcpci_read16(tcpci, TCPC_ALERT, &status);
@@ -412,6 +447,14 @@ static irqreturn_t tcpci_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(tcpci_irq);
+
+static irqreturn_t _tcpci_irq(int irq, void *dev_id)
+{
+ struct tcpci_chip *chip = dev_id;
+
+ return tcpci_irq(chip->tcpci);
+}
static const struct regmap_config tcpci_regmap_config = {
.reg_bits = 8,
@@ -435,22 +478,18 @@ static int tcpci_parse_config(struct tcpci *tcpci)
return 0;
}
-static int tcpci_probe(struct i2c_client *client,
- const struct i2c_device_id *i2c_id)
+struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
{
struct tcpci *tcpci;
int err;
- tcpci = devm_kzalloc(&client->dev, sizeof(*tcpci), GFP_KERNEL);
+ tcpci = devm_kzalloc(dev, sizeof(*tcpci), GFP_KERNEL);
if (!tcpci)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- tcpci->client = client;
- tcpci->dev = &client->dev;
- i2c_set_clientdata(client, tcpci);
- tcpci->regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config);
- if (IS_ERR(tcpci->regmap))
- return PTR_ERR(tcpci->regmap);
+ tcpci->dev = dev;
+ tcpci->data = data;
+ tcpci->regmap = data->regmap;
tcpci->tcpc.init = tcpci_init;
tcpci->tcpc.get_vbus = tcpci_get_vbus;
@@ -467,27 +506,63 @@ static int tcpci_probe(struct i2c_client *client,
err = tcpci_parse_config(tcpci);
if (err < 0)
- return err;
+ return ERR_PTR(err);
- /* Disable chip interrupts */
- tcpci_write16(tcpci, TCPC_ALERT_MASK, 0);
+ tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc);
+ if (PTR_ERR_OR_ZERO(tcpci->port))
+ return ERR_CAST(tcpci->port);
- err = devm_request_threaded_irq(tcpci->dev, client->irq, NULL,
- tcpci_irq,
+ return tcpci;
+}
+EXPORT_SYMBOL_GPL(tcpci_register_port);
+
+void tcpci_unregister_port(struct tcpci *tcpci)
+{
+ tcpm_unregister_port(tcpci->port);
+}
+EXPORT_SYMBOL_GPL(tcpci_unregister_port);
+
+static int tcpci_probe(struct i2c_client *client,
+ const struct i2c_device_id *i2c_id)
+{
+ struct tcpci_chip *chip;
+ int err;
+ u16 val = 0;
+
+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->data.regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config);
+ if (IS_ERR(chip->data.regmap))
+ return PTR_ERR(chip->data.regmap);
+
+ /* Disable chip interrupts before requesting irq */
+ err = regmap_raw_write(chip->data.regmap, TCPC_ALERT_MASK, &val,
+ sizeof(u16));
+ if (err < 0)
+ return err;
+
+ err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ _tcpci_irq,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
- dev_name(tcpci->dev), tcpci);
+ dev_name(&client->dev), chip);
if (err < 0)
return err;
- tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc);
- return PTR_ERR_OR_ZERO(tcpci->port);
+ chip->tcpci = tcpci_register_port(&client->dev, &chip->data);
+ if (PTR_ERR_OR_ZERO(chip->tcpci))
+ return PTR_ERR(chip->tcpci);
+
+ i2c_set_clientdata(client, chip);
+ return 0;
}
static int tcpci_remove(struct i2c_client *client)
{
- struct tcpci *tcpci = i2c_get_clientdata(client);
+ struct tcpci_chip *chip = i2c_get_clientdata(client);
- tcpm_unregister_port(tcpci->port);
+ tcpci_unregister_port(chip->tcpci);
return 0;
}
diff --git a/drivers/staging/typec/tcpci.h b/drivers/staging/typec/tcpci.h
index fdfb06cc3b86..34c865f0dcf6 100644
--- a/drivers/staging/typec/tcpci.h
+++ b/drivers/staging/typec/tcpci.h
@@ -121,4 +121,18 @@
#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
+struct tcpci;
+struct tcpci_data {
+ struct regmap *regmap;
+ int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
+ int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
+ bool enable);
+ int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data,
+ enum typec_cc_status cc);
+};
+
+struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data);
+void tcpci_unregister_port(struct tcpci *tcpci);
+irqreturn_t tcpci_irq(struct tcpci *tcpci);
+
#endif /* __LINUX_USB_TCPCI_H */
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index c9e1a165ed82..ce648cb3ed94 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -45,18 +45,7 @@ static int ci_device_show(struct seq_file *s, void *data)
return 0;
}
-
-static int ci_device_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ci_device_show, inode->i_private);
-}
-
-static const struct file_operations ci_device_fops = {
- .open = ci_device_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ci_device);
/**
* ci_port_test_show: reads port test mode
@@ -156,18 +145,7 @@ static int ci_qheads_show(struct seq_file *s, void *data)
return 0;
}
-
-static int ci_qheads_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ci_qheads_show, inode->i_private);
-}
-
-static const struct file_operations ci_qheads_fops = {
- .open = ci_qheads_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ci_qheads);
/**
* ci_requests_show: DMA contents of all requests currently queued (all endpts)
@@ -204,18 +182,7 @@ static int ci_requests_show(struct seq_file *s, void *data)
return 0;
}
-
-static int ci_requests_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ci_requests_show, inode->i_private);
-}
-
-static const struct file_operations ci_requests_fops = {
- .open = ci_requests_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ci_requests);
static int ci_otg_show(struct seq_file *s, void *unused)
{
@@ -278,18 +245,7 @@ static int ci_otg_show(struct seq_file *s, void *unused)
return 0;
}
-
-static int ci_otg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ci_otg_show, inode->i_private);
-}
-
-static const struct file_operations ci_otg_fops = {
- .open = ci_otg_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ci_otg);
static int ci_role_show(struct seq_file *s, void *data)
{
@@ -376,18 +332,7 @@ static int ci_registers_show(struct seq_file *s, void *unused)
return 0;
}
-
-static int ci_registers_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ci_registers_show, inode->i_private);
-}
-
-static const struct file_operations ci_registers_fops = {
- .open = ci_registers_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ci_registers);
/**
* dbg_create_files: initializes the attribute interface
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 19d60ed7e41f..af45aa3222b5 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -124,10 +124,8 @@ static int host_start(struct ci_hdrc *ci)
hcd->power_budget = ci->platdata->power_budget;
hcd->tpl_support = ci->platdata->tpl_support;
- if (ci->phy)
- hcd->phy = ci->phy;
- else
- hcd->usb_phy = ci->usb_phy;
+ if (ci->phy || ci->usb_phy)
+ hcd->skip_phy_initialization = 1;
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 92c9cefb4317..18e874b0441e 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -6,7 +6,7 @@
usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
usbcore-y += devio.o notify.o generic.o quirks.o devices.o
-usbcore-y += port.o
+usbcore-y += phy.o port.o
usbcore-$(CONFIG_OF) += of.o
usbcore-$(CONFIG_USB_PCI) += hcd-pci.o
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index fc32391a34d5..5a92d8f7c484 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -37,6 +37,7 @@
#include <linux/usb/otg.h>
#include "usb.h"
+#include "phy.h"
/*-------------------------------------------------------------------------*/
@@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
+ if (!PMSG_IS_AUTO(msg))
+ usb_phy_roothub_power_off(hcd->phy_roothub);
+
/* Did we race with a root-hub wakeup event? */
if (rhdev->do_remote_wakeup) {
char buffer[6];
@@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
return 0;
}
+
+ if (!PMSG_IS_AUTO(msg)) {
+ status = usb_phy_roothub_power_on(hcd->phy_roothub);
+ if (status)
+ return status;
+ }
+
if (!hcd->driver->bus_resume)
return -ENOENT;
if (HCD_RH_RUNNING(hcd))
@@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
}
} else {
hcd->state = old_state;
+ usb_phy_roothub_power_off(hcd->phy_roothub);
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
"resume", status);
if (status != -ESHUTDOWN)
@@ -2727,7 +2739,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
- if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
+ if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0);
if (IS_ERR(phy)) {
@@ -2745,28 +2757,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
}
}
- if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
- struct phy *phy = phy_get(hcd->self.sysdev, "usb");
-
- if (IS_ERR(phy)) {
- retval = PTR_ERR(phy);
- if (retval == -EPROBE_DEFER)
- goto err_phy;
- } else {
- retval = phy_init(phy);
- if (retval) {
- phy_put(phy);
- goto err_phy;
- }
- retval = phy_power_on(phy);
- if (retval) {
- phy_exit(phy);
- phy_put(phy);
- goto err_phy;
- }
- hcd->phy = phy;
- hcd->remove_phy = 1;
+ if (!hcd->skip_phy_initialization) {
+ hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
+ if (IS_ERR(hcd->phy_roothub)) {
+ retval = PTR_ERR(hcd->phy_roothub);
+ goto err_phy_roothub_init;
}
+
+ retval = usb_phy_roothub_power_on(hcd->phy_roothub);
+ if (retval)
+ goto err_usb_phy_roothub_power_on;
}
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
@@ -2933,13 +2933,10 @@ err_allocate_root_hub:
err_register_bus:
hcd_buffer_destroy(hcd);
err_create_buf:
- if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
- phy_power_off(hcd->phy);
- phy_exit(hcd->phy);
- phy_put(hcd->phy);
- hcd->phy = NULL;
- }
-err_phy:
+ usb_phy_roothub_power_off(hcd->phy_roothub);
+err_usb_phy_roothub_power_on:
+ usb_phy_roothub_exit(hcd->phy_roothub);
+err_phy_roothub_init:
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
@@ -3017,12 +3014,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_deregister_bus(&hcd->self);
hcd_buffer_destroy(hcd);
- if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
- phy_power_off(hcd->phy);
- phy_exit(hcd->phy);
- phy_put(hcd->phy);
- hcd->phy = NULL;
- }
+ usb_phy_roothub_power_off(hcd->phy_roothub);
+ usb_phy_roothub_exit(hcd->phy_roothub);
+
if (hcd->remove_phy && hcd->usb_phy) {
usb_phy_shutdown(hcd->usb_phy);
usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c5c1f6cf3228..ac7bab772a3a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5505,21 +5505,15 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
if (udev->usb2_hw_lpm_enabled == 1)
usb_set_usb2_hardware_lpm(udev, 0);
- /* Disable LPM and LTM while we reset the device and reinstall the alt
- * settings. Device-initiated LPM settings, and system exit latency
- * settings are cleared when the device is reset, so we have to set
- * them up again.
+ /* Disable LPM while we reset the device and reinstall the alt settings.
+ * Device-initiated LPM, and system exit latency settings are cleared
+ * when the device is reset, so we have to set them up again.
*/
ret = usb_unlocked_disable_lpm(udev);
if (ret) {
dev_err(&udev->dev, "%s Failed to disable LPM\n", __func__);
goto re_enumerate_no_bos;
}
- ret = usb_disable_ltm(udev);
- if (ret) {
- dev_err(&udev->dev, "%s Failed to disable LTM\n", __func__);
- goto re_enumerate_no_bos;
- }
bos = udev->bos;
udev->bos = NULL;
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
new file mode 100644
index 000000000000..09b7c43c0ea4
--- /dev/null
+++ b/drivers/usb/core/phy.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * A wrapper for multiple PHYs which passes all phy_* function calls to
+ * multiple (actual) PHY devices. This is comes handy when initializing
+ * all PHYs on a HCD and to keep them all in the same state.
+ *
+ * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/phy/phy.h>
+#include <linux/of.h>
+
+#include "phy.h"
+
+struct usb_phy_roothub {
+ struct phy *phy;
+ struct list_head list;
+};
+
+static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
+{
+ struct usb_phy_roothub *roothub_entry;
+
+ roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
+ if (!roothub_entry)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&roothub_entry->list);
+
+ return roothub_entry;
+}
+
+static int usb_phy_roothub_add_phy(struct device *dev, int index,
+ struct list_head *list)
+{
+ struct usb_phy_roothub *roothub_entry;
+ struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index);
+
+ if (IS_ERR_OR_NULL(phy)) {
+ if (!phy || PTR_ERR(phy) == -ENODEV)
+ return 0;
+ else
+ return PTR_ERR(phy);
+ }
+
+ roothub_entry = usb_phy_roothub_alloc(dev);
+ if (IS_ERR(roothub_entry))
+ return PTR_ERR(roothub_entry);
+
+ roothub_entry->phy = phy;
+
+ list_add_tail(&roothub_entry->list, list);
+
+ return 0;
+}
+
+struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
+{
+ struct usb_phy_roothub *phy_roothub;
+ struct usb_phy_roothub *roothub_entry;
+ struct list_head *head;
+ int i, num_phys, err;
+
+ num_phys = of_count_phandle_with_args(dev->of_node, "phys",
+ "#phy-cells");
+ if (num_phys <= 0)
+ return NULL;
+
+ phy_roothub = usb_phy_roothub_alloc(dev);
+ if (IS_ERR(phy_roothub))
+ return phy_roothub;
+
+ for (i = 0; i < num_phys; i++) {
+ err = usb_phy_roothub_add_phy(dev, i, &phy_roothub->list);
+ if (err)
+ goto err_out;
+ }
+
+ head = &phy_roothub->list;
+
+ list_for_each_entry(roothub_entry, head, list) {
+ err = phy_init(roothub_entry->phy);
+ if (err)
+ goto err_exit_phys;
+ }
+
+ return phy_roothub;
+
+err_exit_phys:
+ list_for_each_entry_continue_reverse(roothub_entry, head, list)
+ phy_exit(roothub_entry->phy);
+
+err_out:
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_init);
+
+int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub)
+{
+ struct usb_phy_roothub *roothub_entry;
+ struct list_head *head;
+ int err, ret = 0;
+
+ if (!phy_roothub)
+ return 0;
+
+ head = &phy_roothub->list;
+
+ list_for_each_entry(roothub_entry, head, list) {
+ err = phy_exit(roothub_entry->phy);
+ if (err)
+ ret = ret;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_exit);
+
+int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub)
+{
+ struct usb_phy_roothub *roothub_entry;
+ struct list_head *head;
+ int err;
+
+ if (!phy_roothub)
+ return 0;
+
+ head = &phy_roothub->list;
+
+ list_for_each_entry(roothub_entry, head, list) {
+ err = phy_power_on(roothub_entry->phy);
+ if (err)
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ list_for_each_entry_continue_reverse(roothub_entry, head, list)
+ phy_power_off(roothub_entry->phy);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_power_on);
+
+void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub)
+{
+ struct usb_phy_roothub *roothub_entry;
+
+ if (!phy_roothub)
+ return;
+
+ list_for_each_entry_reverse(roothub_entry, &phy_roothub->list, list)
+ phy_power_off(roothub_entry->phy);
+}
+EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
new file mode 100644
index 000000000000..6fde59bfbff8
--- /dev/null
+++ b/drivers/usb/core/phy.h
@@ -0,0 +1,7 @@
+struct usb_phy_roothub;
+
+struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev);
+int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub);
+
+int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub);
+void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub);
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 84da17460568..e221861b3187 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -90,8 +90,8 @@ static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle,
acpi_status status;
/*
- * According to ACPI Spec 9.13. PLD indicates whether usb port is
- * user visible and _UPC indicates whether it is connectable. If
+ * According to 9.14 in ACPI Spec 6.2. _PLD indicates whether usb port
+ * is user visible and _UPC indicates whether it is connectable. If
* the port was visible and connectable, it could be freely connected
* and disconnected with USB devices. If no visible and connectable,
* a usb device is directly hard-wired to the port. If no visible and
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index f4650a88be78..5e0d7f2bd2af 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -170,19 +170,7 @@ static int state_show(struct seq_file *seq, void *v)
return 0;
}
-
-static int state_open(struct inode *inode, struct file *file)
-{
- return single_open(file, state_show, inode->i_private);
-}
-
-static const struct file_operations state_fops = {
- .owner = THIS_MODULE,
- .open = state_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(state);
/**
* fifo_show - debugfs: show the fifo information
@@ -219,19 +207,7 @@ static int fifo_show(struct seq_file *seq, void *v)
return 0;
}
-
-static int fifo_open(struct inode *inode, struct file *file)
-{
- return single_open(file, fifo_show, inode->i_private);
-}
-
-static const struct file_operations fifo_fops = {
- .owner = THIS_MODULE,
- .open = fifo_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(fifo);
static const char *decode_direction(int is_in)
{
@@ -303,19 +279,7 @@ static int ep_show(struct seq_file *seq, void *v)
return 0;
}
-
-static int ep_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ep_show, inode->i_private);
-}
-
-static const struct file_operations ep_fops = {
- .owner = THIS_MODULE,
- .open = ep_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ep);
/**
* dwc2_hsotg_create_debug - create debugfs directory and files
@@ -770,19 +734,7 @@ static int params_show(struct seq_file *seq, void *v)
return 0;
}
-
-static int params_open(struct inode *inode, struct file *file)
-{
- return single_open(file, params_show, inode->i_private);
-}
-
-static const struct file_operations params_fops = {
- .owner = THIS_MODULE,
- .open = params_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(params);
static int hw_params_show(struct seq_file *seq, void *v)
{
@@ -817,19 +769,7 @@ static int hw_params_show(struct seq_file *seq, void *v)
return 0;
}
-
-static int hw_params_open(struct inode *inode, struct file *file)
-{
- return single_open(file, hw_params_show, inode->i_private);
-}
-
-static const struct file_operations hw_params_fops = {
- .owner = THIS_MODULE,
- .open = hw_params_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(hw_params);
static int dr_mode_show(struct seq_file *seq, void *v)
{
@@ -840,19 +780,7 @@ static int dr_mode_show(struct seq_file *seq, void *v)
seq_printf(seq, "%s\n", dr_mode);
return 0;
}
-
-static int dr_mode_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dr_mode_show, inode->i_private);
-}
-
-static const struct file_operations dr_mode_fops = {
- .owner = THIS_MODULE,
- .open = dr_mode_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(dr_mode);
int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
{
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
index 465ccd1104de..3a8df8601074 100644
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -2158,6 +2158,7 @@ static int bcm63xx_usbd_dbg_show(struct seq_file *s, void *p)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(bcm63xx_usbd_dbg);
/*
* bcm63xx_iudma_dbg_show - Show IUDMA status and descriptors.
@@ -2238,33 +2239,7 @@ static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p)
return 0;
}
-
-static int bcm63xx_usbd_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, bcm63xx_usbd_dbg_show, inode->i_private);
-}
-
-static int bcm63xx_iudma_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, bcm63xx_iudma_dbg_show, inode->i_private);
-}
-
-static const struct file_operations usbd_dbg_fops = {
- .owner = THIS_MODULE,
- .open = bcm63xx_usbd_dbg_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
-
-static const struct file_operations iudma_dbg_fops = {
- .owner = THIS_MODULE,
- .open = bcm63xx_iudma_dbg_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
-
+DEFINE_SHOW_ATTRIBUTE(bcm63xx_iudma_dbg);
/**
* bcm63xx_udc_init_debugfs - Create debugfs entries.
@@ -2282,11 +2257,11 @@ static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc)
goto err_root;
usbd = debugfs_create_file("usbd", 0400, root, udc,
- &usbd_dbg_fops);
+ &bcm63xx_usbd_dbg_fops);
if (!usbd)
goto err_usbd;
iudma = debugfs_create_file("iudma", 0400, root, udc,
- &iudma_dbg_fops);
+ &bcm63xx_iudma_dbg_fops);
if (!iudma)
goto err_iudma;
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index b3fb1bbdb854..ca83c15d8ea4 100644
--- a/drivers/usb/gadget/udc/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -179,8 +179,7 @@ static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
seq_puts(seq, "\n");
}
-
-static int gr_seq_show(struct seq_file *seq, void *v)
+static int gr_dfs_show(struct seq_file *seq, void *v)
{
struct gr_udc *dev = seq->private;
u32 control = gr_read32(&dev->regs->control);
@@ -203,19 +202,7 @@ static int gr_seq_show(struct seq_file *seq, void *v)
return 0;
}
-
-static int gr_dfs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gr_seq_show, inode->i_private);
-}
-
-static const struct file_operations gr_dfs_fops = {
- .owner = THIS_MODULE,
- .open = gr_dfs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(gr_dfs);
static void gr_dfs_create(struct gr_udc *dev)
{
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index 0e3f5faa000e..d4be53559f2e 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -1233,8 +1233,7 @@ static const struct usb_gadget_ops pxa25x_udc_ops = {
#ifdef CONFIG_USB_GADGET_DEBUG_FS
-static int
-udc_seq_show(struct seq_file *m, void *_d)
+static int udc_debug_show(struct seq_file *m, void *_d)
{
struct pxa25x_udc *dev = m->private;
unsigned long flags;
@@ -1335,25 +1334,12 @@ done:
local_irq_restore(flags);
return 0;
}
-
-static int
-udc_debugfs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, udc_seq_show, inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
- .open = udc_debugfs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(udc_debug);
#define create_debug_files(dev) \
do { \
dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
- S_IRUGO, NULL, dev, &debug_fops); \
+ S_IRUGO, NULL, dev, &udc_debug_fops); \
} while (0)
#define remove_debug_files(dev) debugfs_remove(dev->debugfs_udc)
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index fadcf2653c3d..a58242e901df 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -131,6 +131,7 @@ static int state_dbg_show(struct seq_file *s, void *p)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(state_dbg);
static int queues_dbg_show(struct seq_file *s, void *p)
{
@@ -163,6 +164,7 @@ static int queues_dbg_show(struct seq_file *s, void *p)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(queues_dbg);
static int eps_dbg_show(struct seq_file *s, void *p)
{
@@ -199,45 +201,7 @@ static int eps_dbg_show(struct seq_file *s, void *p)
return 0;
}
-
-static int eps_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, eps_dbg_show, inode->i_private);
-}
-
-static int queues_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, queues_dbg_show, inode->i_private);
-}
-
-static int state_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, state_dbg_show, inode->i_private);
-}
-
-static const struct file_operations state_dbg_fops = {
- .owner = THIS_MODULE,
- .open = state_dbg_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
-
-static const struct file_operations queues_dbg_fops = {
- .owner = THIS_MODULE,
- .open = queues_dbg_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
-
-static const struct file_operations eps_dbg_fops = {
- .owner = THIS_MODULE,
- .open = eps_dbg_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(eps_dbg);
static void pxa_init_debugfs(struct pxa_udc *udc)
{
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index c5094cb88cd5..0a9fd2022acf 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -155,6 +155,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
retval = -ENODEV;
goto err2;
}
+
+ hcd->skip_phy_initialization = 1;
}
#endif
return retval;
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 21307d862af6..4c6c08b675b5 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -73,10 +73,9 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
if (!qh)
goto done;
qh->hw = (struct ehci_qh_hw *)
- dma_pool_alloc(ehci->qh_pool, flags, &dma);
+ dma_pool_zalloc(ehci->qh_pool, flags, &dma);
if (!qh->hw)
goto fail;
- memset(qh->hw, 0, sizeof *qh->hw);
qh->qh_dma = dma;
// INIT_LIST_HEAD (&qh->qh_list);
INIT_LIST_HEAD (&qh->qtd_list);
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index b065a960adc2..4c306fb6b069 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -27,7 +27,6 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/usb.h>
@@ -44,8 +43,6 @@
struct ehci_platform_priv {
struct clk *clks[EHCI_MAX_CLKS];
struct reset_control *rsts;
- struct phy **phys;
- int num_phys;
bool reset_on_resume;
};
@@ -80,7 +77,7 @@ static int ehci_platform_power_on(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
- int clk, ret, phy_num;
+ int clk, ret;
for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -88,24 +85,8 @@ static int ehci_platform_power_on(struct platform_device *dev)
goto err_disable_clks;
}
- for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
- ret = phy_init(priv->phys[phy_num]);
- if (ret)
- goto err_exit_phy;
- ret = phy_power_on(priv->phys[phy_num]);
- if (ret) {
- phy_exit(priv->phys[phy_num]);
- goto err_exit_phy;
- }
- }
-
return 0;
-err_exit_phy:
- while (--phy_num >= 0) {
- phy_power_off(priv->phys[phy_num]);
- phy_exit(priv->phys[phy_num]);
- }
err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -117,12 +98,7 @@ static void ehci_platform_power_off(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
- int clk, phy_num;
-
- for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
- phy_power_off(priv->phys[phy_num]);
- phy_exit(priv->phys[phy_num]);
- }
+ int clk;
for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -149,7 +125,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
struct ehci_platform_priv *priv;
struct ehci_hcd *ehci;
- int err, irq, phy_num, clk = 0;
+ int err, irq, clk = 0;
if (usb_disabled())
return -ENODEV;
@@ -202,29 +178,6 @@ static int ehci_platform_probe(struct platform_device *dev)
"has-transaction-translator"))
hcd->has_tt = 1;
- priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
- "phys", "#phy-cells");
-
- if (priv->num_phys > 0) {
- priv->phys = devm_kcalloc(&dev->dev, priv->num_phys,
- sizeof(struct phy *), GFP_KERNEL);
- if (!priv->phys)
- return -ENOMEM;
- } else
- priv->num_phys = 0;
-
- for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
- priv->phys[phy_num] = devm_of_phy_get_by_index(
- &dev->dev, dev->dev.of_node, phy_num);
- if (IS_ERR(priv->phys[phy_num])) {
- err = PTR_ERR(priv->phys[phy_num]);
- goto err_put_hcd;
- } else if (!hcd->phy) {
- /* Avoiding phy_get() in usb_add_hcd() */
- hcd->phy = priv->phys[phy_num];
- }
- }
-
for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -306,7 +259,7 @@ err_reset:
err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_put_hcd:
+
if (pdata == &ehci_platform_defaults)
dev->dev.platform_data = NULL;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index e56db44708bc..28e2a338b481 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1287,7 +1287,7 @@ itd_urb_transaction(
} else {
alloc_itd:
spin_unlock_irqrestore(&ehci->lock, flags);
- itd = dma_pool_alloc(ehci->itd_pool, mem_flags,
+ itd = dma_pool_zalloc(ehci->itd_pool, mem_flags,
&itd_dma);
spin_lock_irqsave(&ehci->lock, flags);
if (!itd) {
@@ -1297,7 +1297,6 @@ itd_urb_transaction(
}
}
- memset(itd, 0, sizeof(*itd));
itd->itd_dma = itd_dma;
itd->frame = NO_FRAME;
list_add(&itd->itd_list, &sched->td_list);
@@ -2081,7 +2080,7 @@ sitd_urb_transaction(
} else {
alloc_sitd:
spin_unlock_irqrestore(&ehci->lock, flags);
- sitd = dma_pool_alloc(ehci->sitd_pool, mem_flags,
+ sitd = dma_pool_zalloc(ehci->sitd_pool, mem_flags,
&sitd_dma);
spin_lock_irqsave(&ehci->lock, flags);
if (!sitd) {
@@ -2091,7 +2090,6 @@ sitd_urb_transaction(
}
}
- memset(sitd, 0, sizeof(*sitd));
sitd->sitd_dma = sitd_dma;
sitd->frame = NO_FRAME;
list_add(&sitd->sitd_list, &iso_sched->td_list);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c809f7d2f08f..a6f4389f7e88 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -461,6 +461,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_clk_en;
}
hcd->usb_phy = u_phy;
+ hcd->skip_phy_initialization = 1;
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvidia,needs-double-reset");
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c
index fafa91189e45..ebf9bb219f75 100644
--- a/drivers/usb/host/fhci-dbg.c
+++ b/drivers/usb/host/fhci-dbg.c
@@ -55,6 +55,7 @@ static int fhci_dfs_regs_show(struct seq_file *s, void *v)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(fhci_dfs_regs);
static int fhci_dfs_irq_stat_show(struct seq_file *s, void *v)
{
@@ -75,30 +76,7 @@ static int fhci_dfs_irq_stat_show(struct seq_file *s, void *v)
return 0;
}
-
-static int fhci_dfs_regs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, fhci_dfs_regs_show, inode->i_private);
-}
-
-static int fhci_dfs_irq_stat_open(struct inode *inode, struct file *file)
-{
- return single_open(file, fhci_dfs_irq_stat_show, inode->i_private);
-}
-
-static const struct file_operations fhci_dfs_regs_fops = {
- .open = fhci_dfs_regs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations fhci_dfs_irq_stat_fops = {
- .open = fhci_dfs_irq_stat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(fhci_dfs_irq_stat);
void fhci_dfs_create(struct fhci_hcd *fhci)
{
diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c
index b964f9a51d87..a213ed6f07b5 100644
--- a/drivers/usb/host/imx21-dbg.c
+++ b/drivers/usb/host/imx21-dbg.c
@@ -245,6 +245,7 @@ static int debug_status_show(struct seq_file *s, void *v)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(debug_status);
static int debug_dmem_show(struct seq_file *s, void *v)
{
@@ -266,6 +267,7 @@ static int debug_dmem_show(struct seq_file *s, void *v)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(debug_dmem);
static int debug_etd_show(struct seq_file *s, void *v)
{
@@ -334,6 +336,7 @@ static int debug_etd_show(struct seq_file *s, void *v)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(debug_etd);
static void debug_statistics_show_one(struct seq_file *s,
const char *name, struct debug_stats *stats)
@@ -368,6 +371,7 @@ static int debug_statistics_show(struct seq_file *s, void *v)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(debug_statistics);
static void debug_isoc_show_one(struct seq_file *s,
const char *name, int index, struct debug_isoc_trace *trace)
@@ -409,66 +413,7 @@ static int debug_isoc_show(struct seq_file *s, void *v)
return 0;
}
-
-static int debug_status_open(struct inode *inode, struct file *file)
-{
- return single_open(file, debug_status_show, inode->i_private);
-}
-
-static int debug_dmem_open(struct inode *inode, struct file *file)
-{
- return single_open(file, debug_dmem_show, inode->i_private);
-}
-
-static int debug_etd_open(struct inode *inode, struct file *file)
-{
- return single_open(file, debug_etd_show, inode->i_private);
-}
-
-static int debug_statistics_open(struct inode *inode, struct file *file)
-{
- return single_open(file, debug_statistics_show, inode->i_private);
-}
-
-static int debug_isoc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, debug_isoc_show, inode->i_private);
-}
-
-static const struct file_operations debug_status_fops = {
- .open = debug_status_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations debug_dmem_fops = {
- .open = debug_dmem_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations debug_etd_fops = {
- .open = debug_etd_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations debug_statistics_fops = {
- .open = debug_statistics_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations debug_isoc_fops = {
- .open = debug_isoc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(debug_isoc);
static void create_debug_files(struct imx21 *imx21)
{
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 5f9234b9cf7b..4602ed801f0a 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1168,7 +1168,7 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
}
-static int isp116x_show_dbg(struct seq_file *s, void *unused)
+static int isp116x_debug_show(struct seq_file *s, void *unused)
{
struct isp116x *isp116x = s->private;
@@ -1196,18 +1196,7 @@ static int isp116x_show_dbg(struct seq_file *s, void *unused)
return 0;
}
-
-static int isp116x_open_seq(struct inode *inode, struct file *file)
-{
- return single_open(file, isp116x_show_dbg, inode->i_private);
-}
-
-static const struct file_operations isp116x_debug_fops = {
- .open = isp116x_open_seq,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(isp116x_debug);
static int create_debug_file(struct isp116x *isp116x)
{
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 0201c49bc4fc..d8d35d456456 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -230,6 +230,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd)
} else {
return -EPROBE_DEFER;
}
+ hcd->skip_phy_initialization = 1;
ohci->start_hnp = start_hnp;
}
#endif
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 1e6c954f4b3f..65a1c3fdc88c 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -21,7 +21,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
-#include <linux/phy/phy.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
@@ -38,8 +38,6 @@
struct ohci_platform_priv {
struct clk *clks[OHCI_MAX_CLKS];
struct reset_control *resets;
- struct phy **phys;
- int num_phys;
};
static const char hcd_name[] = "ohci-platform";
@@ -48,7 +46,7 @@ static int ohci_platform_power_on(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
- int clk, ret, phy_num;
+ int clk, ret;
for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
ret = clk_prepare_enable(priv->clks[clk]);
@@ -56,24 +54,8 @@ static int ohci_platform_power_on(struct platform_device *dev)
goto err_disable_clks;
}
- for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
- ret = phy_init(priv->phys[phy_num]);
- if (ret)
- goto err_exit_phy;
- ret = phy_power_on(priv->phys[phy_num]);
- if (ret) {
- phy_exit(priv->phys[phy_num]);
- goto err_exit_phy;
- }
- }
-
return 0;
-err_exit_phy:
- while (--phy_num >= 0) {
- phy_power_off(priv->phys[phy_num]);
- phy_exit(priv->phys[phy_num]);
- }
err_disable_clks:
while (--clk >= 0)
clk_disable_unprepare(priv->clks[clk]);
@@ -85,12 +67,7 @@ static void ohci_platform_power_off(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
- int clk, phy_num;
-
- for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
- phy_power_off(priv->phys[phy_num]);
- phy_exit(priv->phys[phy_num]);
- }
+ int clk;
for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
if (priv->clks[clk])
@@ -117,7 +94,7 @@ static int ohci_platform_probe(struct platform_device *dev)
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
struct ohci_platform_priv *priv;
struct ohci_hcd *ohci;
- int err, irq, phy_num, clk = 0;
+ int err, irq, clk = 0;
if (usb_disabled())
return -ENODEV;
@@ -169,29 +146,6 @@ static int ohci_platform_probe(struct platform_device *dev)
of_property_read_u32(dev->dev.of_node, "num-ports",
&ohci->num_ports);
- priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
- "phys", "#phy-cells");
-
- if (priv->num_phys > 0) {
- priv->phys = devm_kcalloc(&dev->dev, priv->num_phys,
- sizeof(struct phy *), GFP_KERNEL);
- if (!priv->phys)
- return -ENOMEM;
- } else
- priv->num_phys = 0;
-
- for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
- priv->phys[phy_num] = devm_of_phy_get_by_index(
- &dev->dev, dev->dev.of_node, phy_num);
- if (IS_ERR(priv->phys[phy_num])) {
- err = PTR_ERR(priv->phys[phy_num]);
- goto err_put_hcd;
- } else if (!hcd->phy) {
- /* Avoiding phy_get() in usb_add_hcd() */
- hcd->phy = priv->phys[phy_num];
- }
- }
-
for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
if (IS_ERR(priv->clks[clk])) {
@@ -277,7 +231,7 @@ err_reset:
err_put_clks:
while (--clk >= 0)
clk_put(priv->clks[clk]);
-err_put_hcd:
+
if (pdata == &ohci_platform_defaults)
dev->dev.platform_data = NULL;
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index fa88a903fa2e..5b061e599948 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1381,7 +1381,7 @@ static void dump_irq(struct seq_file *s, char *label, u8 mask)
(mask & SL11H_INTMASK_DP) ? " dp" : "");
}
-static int sl811h_show(struct seq_file *s, void *unused)
+static int sl811h_debug_show(struct seq_file *s, void *unused)
{
struct sl811 *sl811 = s->private;
struct sl811h_ep *ep;
@@ -1491,25 +1491,14 @@ static int sl811h_show(struct seq_file *s, void *unused)
return 0;
}
-
-static int sl811h_open(struct inode *inode, struct file *file)
-{
- return single_open(file, sl811h_show, inode->i_private);
-}
-
-static const struct file_operations debug_ops = {
- .open = sl811h_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(sl811h_debug);
/* expect just one sl811 per system */
static void create_debug_file(struct sl811 *sl811)
{
sl811->debug_file = debugfs_create_file("sl811h", S_IRUGO,
usb_debug_root, sl811,
- &debug_ops);
+ &sl811h_debug_fops);
}
static void remove_debug_file(struct sl811 *sl811)
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c
index f154e5791bfd..8ddfe3f1f693 100644
--- a/drivers/usb/host/whci/debug.c
+++ b/drivers/usb/host/whci/debug.c
@@ -72,7 +72,7 @@ static void qset_print(struct seq_file *s, struct whc_qset *qset)
}
}
-static int di_print(struct seq_file *s, void *p)
+static int di_show(struct seq_file *s, void *p)
{
struct whc *whc = s->private;
int d;
@@ -91,8 +91,9 @@ static int di_print(struct seq_file *s, void *p)
}
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(di);
-static int asl_print(struct seq_file *s, void *p)
+static int asl_show(struct seq_file *s, void *p)
{
struct whc *whc = s->private;
struct whc_qset *qset;
@@ -103,8 +104,9 @@ static int asl_print(struct seq_file *s, void *p)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(asl);
-static int pzl_print(struct seq_file *s, void *p)
+static int pzl_show(struct seq_file *s, void *p)
{
struct whc *whc = s->private;
struct whc_qset *qset;
@@ -118,45 +120,7 @@ static int pzl_print(struct seq_file *s, void *p)
}
return 0;
}
-
-static int di_open(struct inode *inode, struct file *file)
-{
- return single_open(file, di_print, inode->i_private);
-}
-
-static int asl_open(struct inode *inode, struct file *file)
-{
- return single_open(file, asl_print, inode->i_private);
-}
-
-static int pzl_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pzl_print, inode->i_private);
-}
-
-static const struct file_operations di_fops = {
- .open = di_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations asl_fops = {
- .open = asl_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static const struct file_operations pzl_fops = {
- .open = pzl_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(pzl);
void whc_dbg_init(struct whc *whc)
{
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index 75f0b92694ba..48779c44c361 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -447,9 +447,10 @@ int xhci_dbc_tty_register_device(struct xhci_hcd *xhci)
xhci_dbc_tty_init_port(xhci, port);
tty_dev = tty_port_register_device(&port->port,
dbc_tty_driver, 0, NULL);
- ret = IS_ERR_OR_NULL(tty_dev);
- if (ret)
+ if (IS_ERR(tty_dev)) {
+ ret = PTR_ERR(tty_dev);
goto register_fail;
+ }
ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
if (ret)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 332420d10be9..e5ace8995b3b 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -913,6 +913,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
if (dev->out_ctx)
xhci_free_container_ctx(xhci, dev->out_ctx);
+ if (dev->udev && dev->udev->slot_id)
+ dev->udev->slot_id = 0;
kfree(xhci->devs[slot_id]);
xhci->devs[slot_id] = NULL;
}
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index b0ab4d5e2751..7334da9e9779 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -14,7 +14,6 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -352,62 +351,6 @@ static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
static struct hc_driver __read_mostly xhci_mtk_hc_driver;
-static int xhci_mtk_phy_init(struct xhci_hcd_mtk *mtk)
-{
- int i;
- int ret;
-
- for (i = 0; i < mtk->num_phys; i++) {
- ret = phy_init(mtk->phys[i]);
- if (ret)
- goto exit_phy;
- }
- return 0;
-
-exit_phy:
- for (; i > 0; i--)
- phy_exit(mtk->phys[i - 1]);
-
- return ret;
-}
-
-static int xhci_mtk_phy_exit(struct xhci_hcd_mtk *mtk)
-{
- int i;
-
- for (i = 0; i < mtk->num_phys; i++)
- phy_exit(mtk->phys[i]);
-
- return 0;
-}
-
-static int xhci_mtk_phy_power_on(struct xhci_hcd_mtk *mtk)
-{
- int i;
- int ret;
-
- for (i = 0; i < mtk->num_phys; i++) {
- ret = phy_power_on(mtk->phys[i]);
- if (ret)
- goto power_off_phy;
- }
- return 0;
-
-power_off_phy:
- for (; i > 0; i--)
- phy_power_off(mtk->phys[i - 1]);
-
- return ret;
-}
-
-static void xhci_mtk_phy_power_off(struct xhci_hcd_mtk *mtk)
-{
- unsigned int i;
-
- for (i = 0; i < mtk->num_phys; i++)
- phy_power_off(mtk->phys[i]);
-}
-
static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
{
int ret;
@@ -488,8 +431,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
- struct phy *phy;
- int phy_num;
int ret = -ENODEV;
int irq;
@@ -529,16 +470,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
return ret;
}
- mtk->num_phys = of_count_phandle_with_args(node,
- "phys", "#phy-cells");
- if (mtk->num_phys > 0) {
- mtk->phys = devm_kcalloc(dev, mtk->num_phys,
- sizeof(*mtk->phys), GFP_KERNEL);
- if (!mtk->phys)
- return -ENOMEM;
- } else {
- mtk->num_phys = 0;
- }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
device_enable_async_suspend(dev);
@@ -596,23 +527,6 @@ static int xhci_mtk_probe(struct platform_device *pdev)
mtk->has_ippc = false;
}
- for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
- phy = devm_of_phy_get_by_index(dev, node, phy_num);
- if (IS_ERR(phy)) {
- ret = PTR_ERR(phy);
- goto put_usb2_hcd;
- }
- mtk->phys[phy_num] = phy;
- }
-
- ret = xhci_mtk_phy_init(mtk);
- if (ret)
- goto put_usb2_hcd;
-
- ret = xhci_mtk_phy_power_on(mtk);
- if (ret)
- goto exit_phys;
-
device_init_wakeup(dev, true);
xhci = hcd_to_xhci(hcd);
@@ -630,7 +544,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
dev_name(dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
- goto power_off_phys;
+ goto disable_device_wakeup;
}
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -653,13 +567,9 @@ put_usb3_hcd:
xhci_mtk_sch_exit(mtk);
usb_put_hcd(xhci->shared_hcd);
-power_off_phys:
- xhci_mtk_phy_power_off(mtk);
+disable_device_wakeup:
device_init_wakeup(dev, false);
-exit_phys:
- xhci_mtk_phy_exit(mtk);
-
put_usb2_hcd:
usb_put_hcd(hcd);
@@ -682,8 +592,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
usb_remove_hcd(xhci->shared_hcd);
- xhci_mtk_phy_power_off(mtk);
- xhci_mtk_phy_exit(mtk);
device_init_wakeup(&dev->dev, false);
usb_remove_hcd(hcd);
@@ -718,7 +626,6 @@ static int __maybe_unused xhci_mtk_suspend(struct device *dev)
del_timer_sync(&xhci->shared_hcd->rh_timer);
xhci_mtk_host_disable(mtk);
- xhci_mtk_phy_power_off(mtk);
xhci_mtk_clks_disable(mtk);
usb_wakeup_set(mtk, true);
return 0;
@@ -732,7 +639,6 @@ static int __maybe_unused xhci_mtk_resume(struct device *dev)
usb_wakeup_set(mtk, false);
xhci_mtk_clks_enable(mtk);
- xhci_mtk_phy_power_on(mtk);
xhci_mtk_host_enable(mtk);
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 6652e2d5bd2e..df327dcc2bac 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -284,6 +284,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
ret = usb_phy_init(hcd->usb_phy);
if (ret)
goto put_usb3_hcd;
+ hcd->skip_phy_initialization = 1;
}
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index daa94c3aed80..91a1a824673d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1436,7 +1436,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
case TRB_STOP_RING:
WARN_ON(slot_id != TRB_TO_SLOT_ID(
le32_to_cpu(cmd_trb->generic.field[3])));
- xhci_handle_cmd_stop_ep(xhci, slot_id, cmd_trb, event);
+ if (!cmd->completion)
+ xhci_handle_cmd_stop_ep(xhci, slot_id, cmd_trb, event);
break;
case TRB_SET_DEQ:
WARN_ON(slot_id != TRB_TO_SLOT_ID(
@@ -1815,8 +1816,7 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci,
static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
- unsigned int stream_id,
- struct xhci_td *td, union xhci_trb *ep_trb,
+ unsigned int stream_id, struct xhci_td *td,
enum xhci_ep_reset_type reset_type)
{
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
@@ -1829,9 +1829,10 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
xhci_queue_reset_ep(xhci, command, slot_id, ep_index, reset_type);
- if (reset_type == EP_HARD_RESET)
+ if (reset_type == EP_HARD_RESET) {
+ ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td);
-
+ }
xhci_ring_cmd_db(xhci);
}
@@ -1922,7 +1923,7 @@ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
}
static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+ struct xhci_transfer_event *event,
struct xhci_virt_ep *ep, int *status)
{
struct xhci_virt_device *xdev;
@@ -1957,8 +1958,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
* The class driver clears the device side halt later.
*/
xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
- ep_ring->stream_id, td, ep_trb,
- EP_HARD_RESET);
+ ep_ring->stream_id, td, EP_HARD_RESET);
} else {
/* Update ring dequeue pointer */
while (ep_ring->dequeue != td->last_trb)
@@ -2083,7 +2083,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length = requested;
finish_td:
- return finish_td(xhci, td, ep_trb, event, ep, status);
+ return finish_td(xhci, td, event, ep, status);
}
/*
@@ -2170,7 +2170,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
td->urb->actual_length += frame->actual_length;
- return finish_td(xhci, td, ep_trb, event, ep, status);
+ return finish_td(xhci, td, event, ep, status);
}
static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
@@ -2260,7 +2260,7 @@ finish_td:
remaining);
td->urb->actual_length = 0;
}
- return finish_td(xhci, td, ep_trb, event, ep, status);
+ return finish_td(xhci, td, event, ep, status);
}
/*
@@ -2318,7 +2318,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
case COMP_INVALID_STREAM_TYPE_ERROR:
case COMP_INVALID_STREAM_ID_ERROR:
xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index, 0,
- NULL, NULL, EP_SOFT_RESET);
+ NULL, EP_SOFT_RESET);
goto cleanup;
case COMP_RING_UNDERRUN:
case COMP_RING_OVERRUN:
@@ -2584,8 +2584,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
xhci_cleanup_halted_endpoint(xhci, slot_id,
ep_index,
ep_ring->stream_id,
- td, ep_trb,
- EP_HARD_RESET);
+ td, EP_HARD_RESET);
goto cleanup;
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 5d37700ae4b0..9b27798ecce5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1290,7 +1290,8 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
unsigned long flags;
int ret = 0;
- unsigned int slot_id, ep_index, ep_state;
+ unsigned int slot_id, ep_index;
+ unsigned int *ep_state;
struct urb_priv *urb_priv;
int num_tds;
@@ -1300,6 +1301,7 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
slot_id = urb->dev->slot_id;
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+ ep_state = &xhci->devs[slot_id]->eps[ep_index].ep_state;
if (!HCD_HW_ACCESSIBLE(hcd)) {
if (!in_interrupt())
@@ -1351,6 +1353,17 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
ret = -ESHUTDOWN;
goto free_priv;
}
+ if (*ep_state & (EP_GETTING_STREAMS | EP_GETTING_NO_STREAMS)) {
+ xhci_warn(xhci, "WARN: Can't enqueue URB, ep in streams transition state %x\n",
+ *ep_state);
+ ret = -EINVAL;
+ goto free_priv;
+ }
+ if (*ep_state & EP_SOFT_CLEAR_TOGGLE) {
+ xhci_warn(xhci, "Can't enqueue URB while manually clearing toggle\n");
+ ret = -EINVAL;
+ goto free_priv;
+ }
switch (usb_endpoint_type(&urb->ep->desc)) {
@@ -1359,23 +1372,13 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
slot_id, ep_index);
break;
case USB_ENDPOINT_XFER_BULK:
- ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
- if (ep_state & (EP_GETTING_STREAMS | EP_GETTING_NO_STREAMS)) {
- xhci_warn(xhci, "WARN: Can't enqueue URB, ep in streams transition state %x\n",
- ep_state);
- ret = -EINVAL;
- break;
- }
ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
break;
-
-
case USB_ENDPOINT_XFER_INT:
ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
break;
-
case USB_ENDPOINT_XFER_ISOC:
ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
@@ -2874,33 +2877,103 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
}
}
-/* Called when clearing halted device. The core should have sent the control
- * message to clear the device halt condition. The host side of the halt should
- * already be cleared with a reset endpoint command issued when the STALL tx
- * event was received.
+/*
+ * Called after usb core issues a clear halt control message.
+ * The host side of the halt should already be cleared by a reset endpoint
+ * command issued when the STALL event was received.
*
- * Context: in_interrupt
+ * The reset endpoint command may only be issued to endpoints in the halted
+ * state. For software that wishes to reset the data toggle or sequence number
+ * of an endpoint that isn't in the halted state this function will issue a
+ * configure endpoint command with the Drop and Add bits set for the target
+ * endpoint. Refer to the additional note in xhci spcification section 4.6.8.
*/
static void xhci_endpoint_reset(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep)
+ struct usb_host_endpoint *host_ep)
{
struct xhci_hcd *xhci;
+ struct usb_device *udev;
+ struct xhci_virt_device *vdev;
+ struct xhci_virt_ep *ep;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_command *stop_cmd, *cfg_cmd;
+ unsigned int ep_index;
+ unsigned long flags;
+ u32 ep_flag;
xhci = hcd_to_xhci(hcd);
+ if (!host_ep->hcpriv)
+ return;
+ udev = (struct usb_device *) host_ep->hcpriv;
+ vdev = xhci->devs[udev->slot_id];
+ ep_index = xhci_get_endpoint_index(&host_ep->desc);
+ ep = &vdev->eps[ep_index];
+
+ /* Bail out if toggle is already being cleared by a endpoint reset */
+ if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
+ ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE;
+ return;
+ }
+ /* Only interrupt and bulk ep's use data toggle, USB2 spec 5.5.4-> */
+ if (usb_endpoint_xfer_control(&host_ep->desc) ||
+ usb_endpoint_xfer_isoc(&host_ep->desc))
+ return;
+
+ ep_flag = xhci_get_endpoint_flag(&host_ep->desc);
+
+ if (ep_flag == SLOT_FLAG || ep_flag == EP0_FLAG)
+ return;
+
+ stop_cmd = xhci_alloc_command(xhci, true, GFP_NOWAIT);
+ if (!stop_cmd)
+ return;
+
+ cfg_cmd = xhci_alloc_command_with_ctx(xhci, true, GFP_NOWAIT);
+ if (!cfg_cmd)
+ goto cleanup;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ /* block queuing new trbs and ringing ep doorbell */
+ ep->ep_state |= EP_SOFT_CLEAR_TOGGLE;
/*
- * We might need to implement the config ep cmd in xhci 4.8.1 note:
- * The Reset Endpoint Command may only be issued to endpoints in the
- * Halted state. If software wishes reset the Data Toggle or Sequence
- * Number of an endpoint that isn't in the Halted state, then software
- * may issue a Configure Endpoint Command with the Drop and Add bits set
- * for the target endpoint. that is in the Stopped state.
+ * Make sure endpoint ring is empty before resetting the toggle/seq.
+ * Driver is required to synchronously cancel all transfer request.
+ * Stop the endpoint to force xHC to update the output context
*/
- /* For now just print debug to follow the situation */
- xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n",
- ep->desc.bEndpointAddress);
+ if (!list_empty(&ep->ring->td_list)) {
+ dev_err(&udev->dev, "EP not empty, refuse reset\n");
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ goto cleanup;
+ }
+ xhci_queue_stop_endpoint(xhci, stop_cmd, udev->slot_id, ep_index, 0);
+ xhci_ring_cmd_db(xhci);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ wait_for_completion(stop_cmd->completion);
+
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ /* config ep command clears toggle if add and drop ep flags are set */
+ ctrl_ctx = xhci_get_input_control_ctx(cfg_cmd->in_ctx);
+ xhci_setup_input_ctx_for_config_ep(xhci, cfg_cmd->in_ctx, vdev->out_ctx,
+ ctrl_ctx, ep_flag, ep_flag);
+ xhci_endpoint_copy(xhci, cfg_cmd->in_ctx, vdev->out_ctx, ep_index);
+
+ xhci_queue_configure_endpoint(xhci, cfg_cmd, cfg_cmd->in_ctx->dma,
+ udev->slot_id, false);
+ xhci_ring_cmd_db(xhci);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ wait_for_completion(cfg_cmd->completion);
+
+ ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE;
+ xhci_free_command(xhci, cfg_cmd);
+cleanup:
+ xhci_free_command(xhci, stop_cmd);
}
static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
@@ -4768,6 +4841,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
* quirks
*/
struct device *dev = hcd->self.sysdev;
+ unsigned int minor_rev;
int retval;
/* Accept arbitrarily long scatter-gather lists */
@@ -4795,12 +4869,19 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
*/
hcd->has_tt = 1;
} else {
- /* Some 3.1 hosts return sbrn 0x30, can't rely on sbrn alone */
- if (xhci->sbrn == 0x31 || xhci->usb3_rhub.min_rev >= 1) {
- xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n");
+ /*
+ * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol
+ * minor revision instead of sbrn
+ */
+ minor_rev = xhci->usb3_rhub.min_rev;
+ if (minor_rev) {
hcd->speed = HCD_USB31;
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
}
+ xhci_info(xhci, "Host supports USB 3.%x %s SuperSpeed\n",
+ minor_rev,
+ minor_rev ? "Enhanced" : "");
+
/* xHCI private pointer was set in xhci_pci_probe for the second
* registered roothub.
*/
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 866e141d4972..8acc8f8d790f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -922,6 +922,8 @@ struct xhci_virt_ep {
#define EP_HAS_STREAMS (1 << 4)
/* Transitioning the endpoint to not using streams, don't enqueue URBs */
#define EP_GETTING_NO_STREAMS (1 << 5)
+#define EP_HARD_CLEAR_TOGGLE (1 << 6)
+#define EP_SOFT_CLEAR_TOGGLE (1 << 7)
/* ---- Related to URB cancellation ---- */
struct list_head cancelled_td_list;
/* Watchdog timer for stop endpoint command to cancel URBs */
diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c
index bac4ef5d9512..1714b2258b54 100644
--- a/drivers/usb/isp1760/isp1760-udc.c
+++ b/drivers/usb/isp1760/isp1760-udc.c
@@ -1441,7 +1441,6 @@ int isp1760_udc_register(struct isp1760_device *isp, int irq,
unsigned long irqflags)
{
struct isp1760_udc *udc = &isp->udc;
- const char *devname;
int ret;
udc->irq = -1;
@@ -1455,13 +1454,10 @@ int isp1760_udc_register(struct isp1760_device *isp, int irq,
if (ret < 0)
return ret;
- devname = dev_name(isp->dev);
- udc->irqname = kmalloc(strlen(devname) + 7, GFP_KERNEL);
+ udc->irqname = kasprintf(GFP_KERNEL, "%s (udc)", dev_name(isp->dev));
if (!udc->irqname)
return -ENOMEM;
- sprintf(udc->irqname, "%s (udc)", devname);
-
ret = request_irq(irq, isp1760_udc_irq, IRQF_SHARED | irqflags,
udc->irqname, udc);
if (ret < 0)
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 4b8712733fc7..b3160afe0458 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -54,7 +54,7 @@ MODULE_DEVICE_TABLE(usb, device_table);
/* we can have up to this number of device plugged in at once */
#define MAX_DEVICES 16
-#define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */
+#define COMMAND_TIMEOUT (2*HZ)
/*
* The locking scheme is a vanilla 3-lock:
@@ -132,6 +132,8 @@ static void adu_abort_transfers(struct adu_device *dev)
spin_lock_irqsave(&dev->buflock, flags);
if (!dev->out_urb_finished) {
spin_unlock_irqrestore(&dev->buflock, flags);
+ wait_event_timeout(dev->write_wait, dev->out_urb_finished,
+ COMMAND_TIMEOUT);
usb_kill_urb(dev->interrupt_out_urb);
} else
spin_unlock_irqrestore(&dev->buflock, flags);
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
index 716cb515523e..cf5828ce927a 100644
--- a/drivers/usb/misc/chaoskey.c
+++ b/drivers/usb/misc/chaoskey.c
@@ -168,14 +168,10 @@ static int chaoskey_probe(struct usb_interface *interface,
*/
if (udev->product && udev->serial) {
- dev->name = kmalloc(strlen(udev->product) + 1 +
- strlen(udev->serial) + 1, GFP_KERNEL);
+ dev->name = kasprintf(GFP_KERNEL, "%s-%s", udev->product,
+ udev->serial);
if (dev->name == NULL)
goto out;
-
- strcpy(dev->name, udev->product);
- strcat(dev->name, "-");
- strcat(dev->name, udev->serial);
}
dev->interface = interface;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 90028ef541e3..9e1142b8b91b 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2028,11 +2028,14 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param,
unsigned i;
unsigned long packets = 0;
int status = 0;
- struct urb *urbs[param->sglen];
+ struct urb *urbs[MAX_SGLEN];
if (!param->sglen || param->iterations > UINT_MAX / param->sglen)
return -EINVAL;
+ if (param->sglen > MAX_SGLEN)
+ return -EINVAL;
+
memset(&context, 0, sizeof(context));
context.count = param->iterations * param->sglen;
context.dev = dev;
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
index 7cf5a1bbdaff..025b2c8630df 100644
--- a/drivers/usb/musb/musb_debugfs.c
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -112,11 +112,7 @@ static int musb_regdump_show(struct seq_file *s, void *unused)
pm_runtime_put_autosuspend(musb->controller);
return 0;
}
-
-static int musb_regdump_open(struct inode *inode, struct file *file)
-{
- return single_open(file, musb_regdump_show, inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(musb_regdump);
static int musb_test_mode_show(struct seq_file *s, void *unused)
{
@@ -161,13 +157,6 @@ static int musb_test_mode_show(struct seq_file *s, void *unused)
return 0;
}
-static const struct file_operations musb_regdump_fops = {
- .open = musb_regdump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static int musb_test_mode_open(struct inode *inode, struct file *file)
{
return single_open(file, musb_test_mode_show, inode->i_private);
diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c
index dcd8ef085b30..06794c06330f 100644
--- a/drivers/usb/typec/fusb302/fusb302.c
+++ b/drivers/usb/typec/fusb302/fusb302.c
@@ -199,7 +199,7 @@ static void fusb302_log(struct fusb302_chip *chip, const char *fmt, ...)
va_end(args);
}
-static int fusb302_seq_show(struct seq_file *s, void *v)
+static int fusb302_debug_show(struct seq_file *s, void *v)
{
struct fusb302_chip *chip = (struct fusb302_chip *)s->private;
int tail;
@@ -216,18 +216,7 @@ static int fusb302_seq_show(struct seq_file *s, void *v)
return 0;
}
-
-static int fusb302_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, fusb302_seq_show, inode->i_private);
-}
-
-static const struct file_operations fusb302_debug_operations = {
- .open = fusb302_debug_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(fusb302_debug);
static struct dentry *rootdir;
@@ -242,7 +231,7 @@ static int fusb302_debugfs_init(struct fusb302_chip *chip)
chip->dentry = debugfs_create_file(dev_name(chip->dev),
S_IFREG | 0444, rootdir,
- chip, &fusb302_debug_operations);
+ chip, &fusb302_debug_fops);
return 0;
}
diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index 8b637a4b474b..4c0fc5493d58 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -503,7 +503,7 @@ static void tcpm_log_source_caps(struct tcpm_port *port)
}
}
-static int tcpm_seq_show(struct seq_file *s, void *v)
+static int tcpm_debug_show(struct seq_file *s, void *v)
{
struct tcpm_port *port = (struct tcpm_port *)s->private;
int tail;
@@ -520,18 +520,7 @@ static int tcpm_seq_show(struct seq_file *s, void *v)
return 0;
}
-
-static int tcpm_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, tcpm_seq_show, inode->i_private);
-}
-
-static const struct file_operations tcpm_debug_operations = {
- .open = tcpm_debug_open,
- .llseek = seq_lseek,
- .read = seq_read,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(tcpm_debug);
static struct dentry *rootdir;
@@ -547,7 +536,7 @@ static int tcpm_debugfs_init(struct tcpm_port *port)
port->dentry = debugfs_create_file(dev_name(port->dev),
S_IFREG | 0444, rootdir,
- port, &tcpm_debug_operations);
+ port, &tcpm_debug_fops);
return 0;
}
@@ -1041,7 +1030,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
break;
case CMDT_RSP_ACK:
/* silently drop message if we are not connected */
- if (!port->partner)
+ if (IS_ERR_OR_NULL(port->partner))
break;
switch (cmd) {
@@ -3664,8 +3653,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
port->port_type = tcpc->config->type;
port->typec_port = typec_register_port(port->dev, &port->typec_caps);
- if (!port->typec_port) {
- err = -ENOMEM;
+ if (IS_ERR(port->typec_port)) {
+ err = PTR_ERR(port->typec_port);
goto out_destroy_wq;
}
@@ -3674,15 +3663,17 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
i = 0;
while (paltmode->svid && i < ARRAY_SIZE(port->port_altmode)) {
- port->port_altmode[i] =
- typec_port_register_altmode(port->typec_port,
- paltmode);
- if (!port->port_altmode[i]) {
+ struct typec_altmode *alt;
+
+ alt = typec_port_register_altmode(port->typec_port,
+ paltmode);
+ if (IS_ERR(alt)) {
tcpm_log(port,
"%s: failed to register port alternate mode 0x%x",
dev_name(dev), paltmode->svid);
break;
}
+ port->port_altmode[i] = alt;
i++;
paltmode++;
}
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 2719f5d382f7..37a15c14a6c6 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -158,15 +158,15 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
desc.identity = &tps->partner_identity;
}
- tps->partner = typec_register_partner(tps->port, &desc);
- if (!tps->partner)
- return -ENODEV;
-
typec_set_pwr_opmode(tps->port, mode);
typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
typec_set_data_role(tps->port, TPS_STATUS_DATAROLE(status));
+ tps->partner = typec_register_partner(tps->port, &desc);
+ if (IS_ERR(tps->partner))
+ return PTR_ERR(tps->partner);
+
if (desc.identity)
typec_partner_set_identity(tps->partner);
@@ -175,7 +175,8 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
{
- typec_unregister_partner(tps->partner);
+ if (!IS_ERR(tps->partner))
+ typec_unregister_partner(tps->partner);
tps->partner = NULL;
typec_set_pwr_opmode(tps->port, TYPEC_PWR_MODE_USB);
typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
@@ -418,8 +419,8 @@ static int tps6598x_probe(struct i2c_client *client)
tps->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
tps->port = typec_register_port(&client->dev, &tps->typec_cap);
- if (!tps->port)
- return -ENODEV;
+ if (IS_ERR(tps->port))
+ return PTR_ERR(tps->port);
if (status & TPS_STATUS_PLUG_PRESENT) {
ret = tps6598x_connect(tps, status);
diff --git a/drivers/usb/typec/typec.c b/drivers/usb/typec/typec.c
index 735726ced602..dc28ad868d93 100644
--- a/drivers/usb/typec/typec.c
+++ b/drivers/usb/typec/typec.c
@@ -386,7 +386,7 @@ typec_register_altmode(struct device *parent,
alt = kzalloc(sizeof(*alt), GFP_KERNEL);
if (!alt)
- return NULL;
+ return ERR_PTR(-ENOMEM);
alt->svid = desc->svid;
alt->n_modes = desc->n_modes;
@@ -402,7 +402,7 @@ typec_register_altmode(struct device *parent,
dev_err(parent, "failed to register alternate mode (%d)\n",
ret);
put_device(&alt->dev);
- return NULL;
+ return ERR_PTR(ret);
}
return alt;
@@ -417,7 +417,7 @@ typec_register_altmode(struct device *parent,
*/
void typec_unregister_altmode(struct typec_altmode *alt)
{
- if (alt)
+ if (!IS_ERR_OR_NULL(alt))
device_unregister(&alt->dev);
}
EXPORT_SYMBOL_GPL(typec_unregister_altmode);
@@ -509,7 +509,7 @@ EXPORT_SYMBOL_GPL(typec_partner_register_altmode);
*
* Registers a device for USB Type-C Partner described in @desc.
*
- * Returns handle to the partner on success or NULL on failure.
+ * Returns handle to the partner on success or ERR_PTR on failure.
*/
struct typec_partner *typec_register_partner(struct typec_port *port,
struct typec_partner_desc *desc)
@@ -519,7 +519,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
partner = kzalloc(sizeof(*partner), GFP_KERNEL);
if (!partner)
- return NULL;
+ return ERR_PTR(-ENOMEM);
partner->usb_pd = desc->usb_pd;
partner->accessory = desc->accessory;
@@ -542,7 +542,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
if (ret) {
dev_err(&port->dev, "failed to register partner (%d)\n", ret);
put_device(&partner->dev);
- return NULL;
+ return ERR_PTR(ret);
}
return partner;
@@ -557,7 +557,7 @@ EXPORT_SYMBOL_GPL(typec_register_partner);
*/
void typec_unregister_partner(struct typec_partner *partner)
{
- if (partner)
+ if (!IS_ERR_OR_NULL(partner))
device_unregister(&partner->dev);
}
EXPORT_SYMBOL_GPL(typec_unregister_partner);
@@ -587,7 +587,7 @@ static const struct device_type typec_plug_dev_type = {
* the plug lists in response to Discover Modes command need to be listed in an
* array in @desc.
*
- * Returns handle to the alternate mode on success or NULL on failure.
+ * Returns handle to the alternate mode on success or ERR_PTR on failure.
*/
struct typec_altmode *
typec_plug_register_altmode(struct typec_plug *plug,
@@ -606,7 +606,7 @@ EXPORT_SYMBOL_GPL(typec_plug_register_altmode);
* Cable Plug represents a plug with electronics in it that can response to USB
* Power Delivery SOP Prime or SOP Double Prime packages.
*
- * Returns handle to the cable plug on success or NULL on failure.
+ * Returns handle to the cable plug on success or ERR_PTR on failure.
*/
struct typec_plug *typec_register_plug(struct typec_cable *cable,
struct typec_plug_desc *desc)
@@ -617,7 +617,7 @@ struct typec_plug *typec_register_plug(struct typec_cable *cable,
plug = kzalloc(sizeof(*plug), GFP_KERNEL);
if (!plug)
- return NULL;
+ return ERR_PTR(-ENOMEM);
sprintf(name, "plug%d", desc->index);
@@ -631,7 +631,7 @@ struct typec_plug *typec_register_plug(struct typec_cable *cable,
if (ret) {
dev_err(&cable->dev, "failed to register plug (%d)\n", ret);
put_device(&plug->dev);
- return NULL;
+ return ERR_PTR(ret);
}
return plug;
@@ -646,7 +646,7 @@ EXPORT_SYMBOL_GPL(typec_register_plug);
*/
void typec_unregister_plug(struct typec_plug *plug)
{
- if (plug)
+ if (!IS_ERR_OR_NULL(plug))
device_unregister(&plug->dev);
}
EXPORT_SYMBOL_GPL(typec_unregister_plug);
@@ -724,7 +724,7 @@ EXPORT_SYMBOL_GPL(typec_cable_set_identity);
* Registers a device for USB Type-C Cable described in @desc. The cable will be
* parent for the optional cable plug devises.
*
- * Returns handle to the cable on success or NULL on failure.
+ * Returns handle to the cable on success or ERR_PTR on failure.
*/
struct typec_cable *typec_register_cable(struct typec_port *port,
struct typec_cable_desc *desc)
@@ -734,7 +734,7 @@ struct typec_cable *typec_register_cable(struct typec_port *port,
cable = kzalloc(sizeof(*cable), GFP_KERNEL);
if (!cable)
- return NULL;
+ return ERR_PTR(-ENOMEM);
cable->type = desc->type;
cable->active = desc->active;
@@ -757,7 +757,7 @@ struct typec_cable *typec_register_cable(struct typec_port *port,
if (ret) {
dev_err(&port->dev, "failed to register cable (%d)\n", ret);
put_device(&cable->dev);
- return NULL;
+ return ERR_PTR(ret);
}
return cable;
@@ -772,7 +772,7 @@ EXPORT_SYMBOL_GPL(typec_register_cable);
*/
void typec_unregister_cable(struct typec_cable *cable)
{
- if (cable)
+ if (!IS_ERR_OR_NULL(cable))
device_unregister(&cable->dev);
}
EXPORT_SYMBOL_GPL(typec_unregister_cable);
@@ -1256,7 +1256,7 @@ EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
* This routine is used to register an alternate mode that @port is capable of
* supporting.
*
- * Returns handle to the alternate mode on success or NULL on failure.
+ * Returns handle to the alternate mode on success or ERR_PTR on failure.
*/
struct typec_altmode *
typec_port_register_altmode(struct typec_port *port,
@@ -1273,7 +1273,7 @@ EXPORT_SYMBOL_GPL(typec_port_register_altmode);
*
* Registers a device for USB Type-C Port described in @cap.
*
- * Returns handle to the port on success or NULL on failure.
+ * Returns handle to the port on success or ERR_PTR on failure.
*/
struct typec_port *typec_register_port(struct device *parent,
const struct typec_capability *cap)
@@ -1285,12 +1285,12 @@ struct typec_port *typec_register_port(struct device *parent,
port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
- return NULL;
+ return ERR_PTR(-ENOMEM);
id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL);
if (id < 0) {
kfree(port);
- return NULL;
+ return ERR_PTR(id);
}
if (cap->type == TYPEC_PORT_DFP)
@@ -1326,7 +1326,7 @@ struct typec_port *typec_register_port(struct device *parent,
if (ret) {
dev_err(parent, "failed to register port (%d)\n", ret);
put_device(&port->dev);
- return NULL;
+ return ERR_PTR(ret);
}
return port;
@@ -1341,7 +1341,7 @@ EXPORT_SYMBOL_GPL(typec_register_port);
*/
void typec_unregister_port(struct typec_port *port)
{
- if (port)
+ if (!IS_ERR_OR_NULL(port))
device_unregister(&port->dev);
}
EXPORT_SYMBOL_GPL(typec_unregister_port);
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 79046fe66426..69d544cfcd45 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -260,38 +260,45 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
static int ucsi_register_partner(struct ucsi_connector *con)
{
- struct typec_partner_desc partner;
+ struct typec_partner_desc desc;
+ struct typec_partner *partner;
if (con->partner)
return 0;
- memset(&partner, 0, sizeof(partner));
+ memset(&desc, 0, sizeof(desc));
switch (con->status.partner_type) {
case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
- partner.accessory = TYPEC_ACCESSORY_DEBUG;
+ desc.accessory = TYPEC_ACCESSORY_DEBUG;
break;
case UCSI_CONSTAT_PARTNER_TYPE_AUDIO:
- partner.accessory = TYPEC_ACCESSORY_AUDIO;
+ desc.accessory = TYPEC_ACCESSORY_AUDIO;
break;
default:
break;
}
- partner.usb_pd = con->status.pwr_op_mode == UCSI_CONSTAT_PWR_OPMODE_PD;
+ desc.usb_pd = con->status.pwr_op_mode == UCSI_CONSTAT_PWR_OPMODE_PD;
- con->partner = typec_register_partner(con->port, &partner);
- if (!con->partner) {
- dev_err(con->ucsi->dev, "con%d: failed to register partner\n",
- con->num);
- return -ENODEV;
+ partner = typec_register_partner(con->port, &desc);
+ if (IS_ERR(partner)) {
+ dev_err(con->ucsi->dev,
+ "con%d: failed to register partner (%ld)\n", con->num,
+ PTR_ERR(partner));
+ return PTR_ERR(partner);
}
+ con->partner = partner;
+
return 0;
}
static void ucsi_unregister_partner(struct ucsi_connector *con)
{
+ if (!con->partner)
+ return;
+
typec_unregister_partner(con->partner);
con->partner = NULL;
}
@@ -606,8 +613,8 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
/* Register the connector */
con->port = typec_register_port(ucsi->dev, cap);
- if (!con->port)
- return -ENODEV;
+ if (IS_ERR(con->port))
+ return PTR_ERR(con->port);
/* Get the status */
UCSI_CMD_GET_CONNECTOR_STATUS(ctrl, con->num);
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 26ca0ec01fd5..c3ddd0f1f449 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -640,4 +640,4 @@ static struct usb_driver skel_driver = {
module_usb_driver(skel_driver);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/usbip/Kconfig b/drivers/usb/usbip/Kconfig
index eeefa29f8aa2..a20b65cb6678 100644
--- a/drivers/usb/usbip/Kconfig
+++ b/drivers/usb/usbip/Kconfig
@@ -27,7 +27,7 @@ config USBIP_VHCI_HCD
config USBIP_VHCI_HC_PORTS
int "Number of ports per USB/IP virtual host controller"
- range 1 31
+ range 1 15
default 8
depends on USBIP_VHCI_HCD
---help---
diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c
index 4c00be2d1993..aff50eb09ca9 100644
--- a/drivers/usb/wusbcore/crypto.c
+++ b/drivers/usb/wusbcore/crypto.c
@@ -202,7 +202,7 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
struct scatterlist sg[4], sg_dst;
void *dst_buf;
size_t dst_size;
- u8 iv[crypto_skcipher_ivsize(tfm_cbc)];
+ u8 *iv;
size_t zero_padding;
/*
@@ -224,7 +224,9 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
if (!dst_buf)
goto error_dst_buf;
- memset(iv, 0, sizeof(iv));
+ iv = kzalloc(crypto_skcipher_ivsize(tfm_cbc), GFP_KERNEL);
+ if (!iv)
+ goto error_iv;
/* Setup B0 */
scratch->b0.flags = 0x59; /* Format B0 */
@@ -276,6 +278,8 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
bytewise_xor(mic, &scratch->ax, iv, 8);
result = 8;
error_cbc_crypt:
+ kfree(iv);
+error_iv:
kfree(dst_buf);
error_dst_buf:
return result;
diff --git a/drivers/usb/wusbcore/wa-nep.c b/drivers/usb/wusbcore/wa-nep.c
index 9fdcb6b84abf..5f0656db5482 100644
--- a/drivers/usb/wusbcore/wa-nep.c
+++ b/drivers/usb/wusbcore/wa-nep.c
@@ -93,7 +93,6 @@ static void wa_notif_dispatch(struct work_struct *ws)
goto out; /* screw it */
#endif
atomic_dec(&wa->notifs_queued); /* Throttling ctl */
- dev = &wa->usb_iface->dev;
size = nw->size;
itr = nw->data;
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index 991374b13571..f1622bae13be 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -206,7 +206,7 @@ static const struct file_operations command_fops = {
.owner = THIS_MODULE,
};
-static int reservations_print(struct seq_file *s, void *p)
+static int reservations_show(struct seq_file *s, void *p)
{
struct uwb_rc *rc = s->private;
struct uwb_rsv *rsv;
@@ -240,21 +240,9 @@ static int reservations_print(struct seq_file *s, void *p)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(reservations);
-static int reservations_open(struct inode *inode, struct file *file)
-{
- return single_open(file, reservations_print, inode->i_private);
-}
-
-static const struct file_operations reservations_fops = {
- .open = reservations_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int drp_avail_print(struct seq_file *s, void *p)
+static int drp_avail_show(struct seq_file *s, void *p)
{
struct uwb_rc *rc = s->private;
@@ -264,19 +252,7 @@ static int drp_avail_print(struct seq_file *s, void *p)
return 0;
}
-
-static int drp_avail_open(struct inode *inode, struct file *file)
-{
- return single_open(file, drp_avail_print, inode->i_private);
-}
-
-static const struct file_operations drp_avail_fops = {
- .open = drp_avail_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(drp_avail);
static void uwb_dbg_channel_changed(struct uwb_pal *pal, int channel)
{
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 176900528822..aef50cb2ed1b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -103,7 +103,7 @@ struct usb_hcd {
* other external phys should be software-transparent
*/
struct usb_phy *usb_phy;
- struct phy *phy;
+ struct usb_phy_roothub *phy_roothub;
/* Flags that need to be manipulated atomically because they can
* change while the host controller is running. Always use
@@ -151,6 +151,12 @@ struct usb_hcd {
unsigned msix_enabled:1; /* driver has MSI-X enabled? */
unsigned msi_enabled:1; /* driver has MSI enabled? */
unsigned remove_phy:1; /* auto-remove USB phy */
+ /*
+ * do not manage the PHY state in the HCD core, instead let the driver
+ * handle this (for example if the PHY can only be turned on after a
+ * specific event)
+ */
+ unsigned skip_phy_initialization:1;
/* The next flag is a stopgap, to be removed when all the HCDs
* support the new root-hub polling mechanism. */
diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h
index b3d41d7409b3..ff359bdfdc7b 100644
--- a/include/linux/usb/pd.h
+++ b/include/linux/usb/pd.h
@@ -35,6 +35,13 @@ enum pd_ctrl_msg_type {
PD_CTRL_WAIT = 12,
PD_CTRL_SOFT_RESET = 13,
/* 14-15 Reserved */
+ PD_CTRL_NOT_SUPP = 16,
+ PD_CTRL_GET_SOURCE_CAP_EXT = 17,
+ PD_CTRL_GET_STATUS = 18,
+ PD_CTRL_FR_SWAP = 19,
+ PD_CTRL_GET_PPS_STATUS = 20,
+ PD_CTRL_GET_COUNTRY_CODES = 21,
+ /* 22-31 Reserved */
};
enum pd_data_msg_type {
@@ -43,13 +50,39 @@ enum pd_data_msg_type {
PD_DATA_REQUEST = 2,
PD_DATA_BIST = 3,
PD_DATA_SINK_CAP = 4,
- /* 5-14 Reserved */
+ PD_DATA_BATT_STATUS = 5,
+ PD_DATA_ALERT = 6,
+ PD_DATA_GET_COUNTRY_INFO = 7,
+ /* 8-14 Reserved */
PD_DATA_VENDOR_DEF = 15,
+ /* 16-31 Reserved */
+};
+
+enum pd_ext_msg_type {
+ /* 0 Reserved */
+ PD_EXT_SOURCE_CAP_EXT = 1,
+ PD_EXT_STATUS = 2,
+ PD_EXT_GET_BATT_CAP = 3,
+ PD_EXT_GET_BATT_STATUS = 4,
+ PD_EXT_BATT_CAP = 5,
+ PD_EXT_GET_MANUFACTURER_INFO = 6,
+ PD_EXT_MANUFACTURER_INFO = 7,
+ PD_EXT_SECURITY_REQUEST = 8,
+ PD_EXT_SECURITY_RESPONSE = 9,
+ PD_EXT_FW_UPDATE_REQUEST = 10,
+ PD_EXT_FW_UPDATE_RESPONSE = 11,
+ PD_EXT_PPS_STATUS = 12,
+ PD_EXT_COUNTRY_INFO = 13,
+ PD_EXT_COUNTRY_CODES = 14,
+ /* 15-31 Reserved */
};
#define PD_REV10 0x0
#define PD_REV20 0x1
+#define PD_REV30 0x2
+#define PD_MAX_REV PD_REV30
+#define PD_HEADER_EXT_HDR BIT(15)
#define PD_HEADER_CNT_SHIFT 12
#define PD_HEADER_CNT_MASK 0x7
#define PD_HEADER_ID_SHIFT 9
@@ -59,18 +92,19 @@ enum pd_data_msg_type {
#define PD_HEADER_REV_MASK 0x3
#define PD_HEADER_DATA_ROLE BIT(5)
#define PD_HEADER_TYPE_SHIFT 0
-#define PD_HEADER_TYPE_MASK 0xf
+#define PD_HEADER_TYPE_MASK 0x1f
-#define PD_HEADER(type, pwr, data, id, cnt) \
+#define PD_HEADER(type, pwr, data, rev, id, cnt, ext_hdr) \
((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \
((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \
((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \
- (PD_REV20 << PD_HEADER_REV_SHIFT) | \
+ (rev << PD_HEADER_REV_SHIFT) | \
(((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \
- (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT))
+ (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) | \
+ ((ext_hdr) ? PD_HEADER_EXT_HDR : 0))
#define PD_HEADER_LE(type, pwr, data, id, cnt) \
- cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt)))
+ cpu_to_le16(PD_HEADER((type), (pwr), (data), PD_REV20, (id), (cnt), (0)))
static inline unsigned int pd_header_cnt(u16 header)
{
@@ -102,16 +136,75 @@ static inline unsigned int pd_header_msgid_le(__le16 header)
return pd_header_msgid(le16_to_cpu(header));
}
+static inline unsigned int pd_header_rev(u16 header)
+{
+ return (header >> PD_HEADER_REV_SHIFT) & PD_HEADER_REV_MASK;
+}
+
+static inline unsigned int pd_header_rev_le(__le16 header)
+{
+ return pd_header_rev(le16_to_cpu(header));
+}
+
+#define PD_EXT_HDR_CHUNKED BIT(15)
+#define PD_EXT_HDR_CHUNK_NUM_SHIFT 11
+#define PD_EXT_HDR_CHUNK_NUM_MASK 0xf
+#define PD_EXT_HDR_REQ_CHUNK BIT(10)
+#define PD_EXT_HDR_DATA_SIZE_SHIFT 0
+#define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff
+
+#define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) \
+ ((((data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << PD_EXT_HDR_DATA_SIZE_SHIFT) | \
+ ((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | \
+ (((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << PD_EXT_HDR_CHUNK_NUM_SHIFT) | \
+ ((chunked) ? PD_EXT_HDR_CHUNKED : 0))
+
+#define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \
+ cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), (chunked)))
+
+static inline unsigned int pd_ext_header_chunk_num(u16 ext_header)
+{
+ return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) &
+ PD_EXT_HDR_CHUNK_NUM_MASK;
+}
+
+static inline unsigned int pd_ext_header_data_size(u16 ext_header)
+{
+ return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) &
+ PD_EXT_HDR_DATA_SIZE_MASK;
+}
+
+static inline unsigned int pd_ext_header_data_size_le(__le16 ext_header)
+{
+ return pd_ext_header_data_size(le16_to_cpu(ext_header));
+}
+
#define PD_MAX_PAYLOAD 7
+#define PD_EXT_MAX_CHUNK_DATA 26
/**
- * struct pd_message - PD message as seen on wire
- * @header: PD message header
- * @payload: PD message payload
- */
+ * struct pd_chunked_ext_message_data - PD chunked extended message data as
+ * seen on wire
+ * @header: PD extended message header
+ * @data: PD extended message data
+ */
+struct pd_chunked_ext_message_data {
+ __le16 header;
+ u8 data[PD_EXT_MAX_CHUNK_DATA];
+} __packed;
+
+/**
+ * struct pd_message - PD message as seen on wire
+ * @header: PD message header
+ * @payload: PD message payload
+ * @ext_msg: PD message chunked extended message data
+ */
struct pd_message {
__le16 header;
- __le32 payload[PD_MAX_PAYLOAD];
+ union {
+ __le32 payload[PD_MAX_PAYLOAD];
+ struct pd_chunked_ext_message_data ext_msg;
+ };
} __packed;
/* PDO: Power Data Object */
@@ -121,6 +214,7 @@ enum pd_pdo_type {
PDO_TYPE_FIXED = 0,
PDO_TYPE_BATT = 1,
PDO_TYPE_VAR = 2,
+ PDO_TYPE_APDO = 3,
};
#define PDO_TYPE_SHIFT 30
@@ -174,6 +268,34 @@ enum pd_pdo_type {
(PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \
PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma))
+enum pd_apdo_type {
+ APDO_TYPE_PPS = 0,
+};
+
+#define PDO_APDO_TYPE_SHIFT 28 /* Only valid value currently is 0x0 - PPS */
+#define PDO_APDO_TYPE_MASK 0x3
+
+#define PDO_APDO_TYPE(t) ((t) << PDO_APDO_TYPE_SHIFT)
+
+#define PDO_PPS_APDO_MAX_VOLT_SHIFT 17 /* 100mV units */
+#define PDO_PPS_APDO_MIN_VOLT_SHIFT 8 /* 100mV units */
+#define PDO_PPS_APDO_MAX_CURR_SHIFT 0 /* 50mA units */
+
+#define PDO_PPS_APDO_VOLT_MASK 0xff
+#define PDO_PPS_APDO_CURR_MASK 0x7f
+
+#define PDO_PPS_APDO_MIN_VOLT(mv) \
+ ((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MIN_VOLT_SHIFT)
+#define PDO_PPS_APDO_MAX_VOLT(mv) \
+ ((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MAX_VOLT_SHIFT)
+#define PDO_PPS_APDO_MAX_CURR(ma) \
+ ((((ma) / 50) & PDO_PPS_APDO_CURR_MASK) << PDO_PPS_APDO_MAX_CURR_SHIFT)
+
+#define PDO_PPS_APDO(min_mv, max_mv, max_ma) \
+ (PDO_TYPE(PDO_TYPE_APDO) | PDO_APDO_TYPE(APDO_TYPE_PPS) | \
+ PDO_PPS_APDO_MIN_VOLT(min_mv) | PDO_PPS_APDO_MAX_VOLT(max_mv) | \
+ PDO_PPS_APDO_MAX_CURR(max_ma))
+
static inline enum pd_pdo_type pdo_type(u32 pdo)
{
return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK;
@@ -204,6 +326,29 @@ static inline unsigned int pdo_max_power(u32 pdo)
return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250;
}
+static inline enum pd_apdo_type pdo_apdo_type(u32 pdo)
+{
+ return (pdo >> PDO_APDO_TYPE_SHIFT) & PDO_APDO_TYPE_MASK;
+}
+
+static inline unsigned int pdo_pps_apdo_min_voltage(u32 pdo)
+{
+ return ((pdo >> PDO_PPS_APDO_MIN_VOLT_SHIFT) &
+ PDO_PPS_APDO_VOLT_MASK) * 100;
+}
+
+static inline unsigned int pdo_pps_apdo_max_voltage(u32 pdo)
+{
+ return ((pdo >> PDO_PPS_APDO_MAX_VOLT_SHIFT) &
+ PDO_PPS_APDO_VOLT_MASK) * 100;
+}
+
+static inline unsigned int pdo_pps_apdo_max_current(u32 pdo)
+{
+ return ((pdo >> PDO_PPS_APDO_MAX_CURR_SHIFT) &
+ PDO_PPS_APDO_CURR_MASK) * 50;
+}
+
/* RDO: Request Data Object */
#define RDO_OBJ_POS_SHIFT 28
#define RDO_OBJ_POS_MASK 0x7
@@ -237,6 +382,24 @@ static inline unsigned int pdo_max_power(u32 pdo)
(RDO_OBJ(idx) | (flags) | \
RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw))
+#define RDO_PROG_VOLT_MASK 0x7ff
+#define RDO_PROG_CURR_MASK 0x7f
+
+#define RDO_PROG_VOLT_SHIFT 9
+#define RDO_PROG_CURR_SHIFT 0
+
+#define RDO_PROG_VOLT_MV_STEP 20
+#define RDO_PROG_CURR_MA_STEP 50
+
+#define PDO_PROG_OUT_VOLT(mv) \
+ ((((mv) / RDO_PROG_VOLT_MV_STEP) & RDO_PROG_VOLT_MASK) << RDO_PROG_VOLT_SHIFT)
+#define PDO_PROG_OP_CURR(ma) \
+ ((((ma) / RDO_PROG_CURR_MA_STEP) & RDO_PROG_CURR_MASK) << RDO_PROG_CURR_SHIFT)
+
+#define RDO_PROG(idx, out_mv, op_ma, flags) \
+ (RDO_OBJ(idx) | (flags) | \
+ PDO_PROG_OUT_VOLT(out_mv) | PDO_PROG_OP_CURR(op_ma))
+
static inline unsigned int rdo_index(u32 rdo)
{
return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK;
diff --git a/include/linux/usb/pd_ado.h b/include/linux/usb/pd_ado.h
new file mode 100644
index 000000000000..9aa1cf31c93c
--- /dev/null
+++ b/include/linux/usb/pd_ado.h
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ */
+
+#ifndef __LINUX_USB_PD_ADO_H
+#define __LINUX_USB_PD_ADO_H
+
+/* ADO : Alert Data Object */
+#define USB_PD_ADO_TYPE_SHIFT 24
+#define USB_PD_ADO_TYPE_MASK 0xff
+#define USB_PD_ADO_FIXED_BATT_SHIFT 20
+#define USB_PD_ADO_FIXED_BATT_MASK 0xf
+#define USB_PD_ADO_HOT_SWAP_BATT_SHIFT 16
+#define USB_PD_ADO_HOT_SWAP_BATT_MASK 0xf
+
+#define USB_PD_ADO_TYPE_BATT_STATUS_CHANGE BIT(1)
+#define USB_PD_ADO_TYPE_OCP BIT(2)
+#define USB_PD_ADO_TYPE_OTP BIT(3)
+#define USB_PD_ADO_TYPE_OP_COND_CHANGE BIT(4)
+#define USB_PD_ADO_TYPE_SRC_INPUT_CHANGE BIT(5)
+#define USB_PD_ADO_TYPE_OVP BIT(6)
+
+static inline unsigned int usb_pd_ado_type(u32 ado)
+{
+ return (ado >> USB_PD_ADO_TYPE_SHIFT) & USB_PD_ADO_TYPE_MASK;
+}
+
+static inline unsigned int usb_pd_ado_fixed_batt(u32 ado)
+{
+ return (ado >> USB_PD_ADO_FIXED_BATT_SHIFT) &
+ USB_PD_ADO_FIXED_BATT_MASK;
+}
+
+static inline unsigned int usb_pd_ado_hot_swap_batt(u32 ado)
+{
+ return (ado >> USB_PD_ADO_HOT_SWAP_BATT_SHIFT) &
+ USB_PD_ADO_HOT_SWAP_BATT_MASK;
+}
+#endif /* __LINUX_USB_PD_ADO_H */
diff --git a/include/linux/usb/pd_ext_sdb.h b/include/linux/usb/pd_ext_sdb.h
new file mode 100644
index 000000000000..0eb83ce19597
--- /dev/null
+++ b/include/linux/usb/pd_ext_sdb.h
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ */
+
+#ifndef __LINUX_USB_PD_EXT_SDB_H
+#define __LINUX_USB_PD_EXT_SDB_H
+
+/* SDB : Status Data Block */
+enum usb_pd_ext_sdb_fields {
+ USB_PD_EXT_SDB_INTERNAL_TEMP = 0,
+ USB_PD_EXT_SDB_PRESENT_INPUT,
+ USB_PD_EXT_SDB_PRESENT_BATT_INPUT,
+ USB_PD_EXT_SDB_EVENT_FLAGS,
+ USB_PD_EXT_SDB_TEMP_STATUS,
+ USB_PD_EXT_SDB_DATA_SIZE,
+};
+
+/* Event Flags */
+#define USB_PD_EXT_SDB_EVENT_OCP BIT(1)
+#define USB_PD_EXT_SDB_EVENT_OTP BIT(2)
+#define USB_PD_EXT_SDB_EVENT_OVP BIT(3)
+#define USB_PD_EXT_SDB_EVENT_CF_CV_MODE BIT(4)
+
+#define USB_PD_EXT_SDB_PPS_EVENTS (USB_PD_EXT_SDB_EVENT_OCP | \
+ USB_PD_EXT_SDB_EVENT_OTP | \
+ USB_PD_EXT_SDB_EVENT_OVP)
+
+#endif /* __LINUX_USB_PD_EXT_SDB_H */
diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c
index 001bb8e8f668..bb424638d75b 100644
--- a/tools/usb/usbip/libsrc/usbip_common.c
+++ b/tools/usb/usbip/libsrc/usbip_common.c
@@ -66,6 +66,29 @@ const char *usbip_speed_string(int num)
return "Unknown Speed";
}
+struct op_common_status_string {
+ int num;
+ char *desc;
+};
+
+static struct op_common_status_string op_common_status_strings[] = {
+ { ST_OK, "Request Completed Successfully" },
+ { ST_NA, "Request Failed" },
+ { ST_DEV_BUSY, "Device busy (exported)" },
+ { ST_DEV_ERR, "Device in error state" },
+ { ST_NODEV, "Device not found" },
+ { ST_ERROR, "Unexpected response" },
+ { 0, NULL}
+};
+
+const char *usbip_op_common_status_string(int status)
+{
+ for (int i = 0; op_common_status_strings[i].desc != NULL; i++)
+ if (op_common_status_strings[i].num == status)
+ return op_common_status_strings[i].desc;
+
+ return "Unknown Op Common Status";
+}
#define DBG_UDEV_INTEGER(name)\
dbg("%-20s = %x", to_string(name), (int) udev->name)
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
index e45ec9d2fdbc..73a367a7fa10 100644
--- a/tools/usb/usbip/libsrc/usbip_common.h
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -43,6 +43,16 @@
#define SYSFS_PATH_MAX 256
#define SYSFS_BUS_ID_SIZE 32
+/* Defines for op_code status in server/client op_common PDUs */
+#define ST_OK 0x00
+#define ST_NA 0x01
+ /* Device requested for import is not available */
+#define ST_DEV_BUSY 0x02
+ /* Device requested for import is in error state */
+#define ST_DEV_ERR 0x03
+#define ST_NODEV 0x04
+#define ST_ERROR 0x05
+
extern int usbip_use_syslog;
extern int usbip_use_stderr;
extern int usbip_use_debug ;
@@ -130,6 +140,7 @@ int read_usb_interface(struct usbip_usb_device *udev, int i,
const char *usbip_speed_string(int num);
const char *usbip_status_string(int32_t status);
+const char *usbip_op_common_status_string(int status);
int usbip_names_init(char *);
void usbip_names_free(void);
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c
index 6ff7b601f854..dc93fadbee96 100644
--- a/tools/usb/usbip/libsrc/usbip_host_common.c
+++ b/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -234,14 +234,17 @@ int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
switch (edev->status) {
case SDEV_ST_ERROR:
dbg("status SDEV_ST_ERROR");
+ ret = ST_DEV_ERR;
break;
case SDEV_ST_USED:
dbg("status SDEV_ST_USED");
+ ret = ST_DEV_BUSY;
break;
default:
dbg("status unknown: 0x%x", edev->status);
+ ret = -1;
}
- return -1;
+ return ret;
}
/* only the first interface is true */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index 7f07b2d50f59..ba88728483ff 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -135,6 +135,7 @@ static int query_import_device(int sockfd, char *busid)
struct op_import_request request;
struct op_import_reply reply;
uint16_t code = OP_REP_IMPORT;
+ int status;
memset(&request, 0, sizeof(request));
memset(&reply, 0, sizeof(reply));
@@ -157,9 +158,10 @@ static int query_import_device(int sockfd, char *busid)
}
/* receive a reply */
- rc = usbip_net_recv_op_common(sockfd, &code);
+ rc = usbip_net_recv_op_common(sockfd, &code, &status);
if (rc < 0) {
- err("recv op_common");
+ err("Attach Request for %s failed - %s\n",
+ busid, usbip_op_common_status_string(status));
return -1;
}
@@ -194,10 +196,8 @@ static int attach_device(char *host, char *busid)
}
rhport = query_import_device(sockfd, busid);
- if (rhport < 0) {
- err("query");
+ if (rhport < 0)
return -1;
- }
close(sockfd);
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index d65a9f444174..8d4ccf4b9480 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -62,6 +62,7 @@ static int get_exported_devices(char *host, int sockfd)
struct usbip_usb_interface uintf;
unsigned int i;
int rc, j;
+ int status;
rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
if (rc < 0) {
@@ -69,9 +70,10 @@ static int get_exported_devices(char *host, int sockfd)
return -1;
}
- rc = usbip_net_recv_op_common(sockfd, &code);
+ rc = usbip_net_recv_op_common(sockfd, &code, &status);
if (rc < 0) {
- dbg("usbip_net_recv_op_common failed");
+ err("Exported Device List Request failed - %s\n",
+ usbip_op_common_status_string(status));
return -1;
}
diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c
index b4c37e76a6e0..8ffcd47d9638 100644
--- a/tools/usb/usbip/src/usbip_network.c
+++ b/tools/usb/usbip/src/usbip_network.c
@@ -163,7 +163,7 @@ int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
return 0;
}
-int usbip_net_recv_op_common(int sockfd, uint16_t *code)
+int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status)
{
struct op_common op_common;
int rc;
@@ -179,8 +179,8 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code)
PACK_OP_COMMON(0, &op_common);
if (op_common.version != USBIP_VERSION) {
- dbg("version mismatch: %d %d", op_common.version,
- USBIP_VERSION);
+ err("USBIP Kernel and tool version mismatch: %d %d:",
+ op_common.version, USBIP_VERSION);
goto err;
}
@@ -191,10 +191,14 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code)
if (op_common.code != *code) {
dbg("unexpected pdu %#0x for %#0x", op_common.code,
*code);
+ /* return error status */
+ *status = ST_ERROR;
goto err;
}
}
+ *status = op_common.status;
+
if (op_common.status != ST_OK) {
dbg("request failed at peer: %d", op_common.status);
goto err;
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
index 7032687621d3..555215eae43e 100644
--- a/tools/usb/usbip/src/usbip_network.h
+++ b/tools/usb/usbip/src/usbip_network.h
@@ -27,9 +27,7 @@ struct op_common {
#define OP_REPLY (0x00 << 8)
uint16_t code;
- /* add more error code */
-#define ST_OK 0x00
-#define ST_NA 0x01
+ /* status codes defined in usbip_common.h */
uint32_t status; /* op_code status (for reply) */
} __attribute__((packed));
@@ -176,7 +174,7 @@ void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
-int usbip_net_recv_op_common(int sockfd, uint16_t *code);
+int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status);
int usbip_net_set_reuseaddr(int sockfd);
int usbip_net_set_nodelay(int sockfd);
int usbip_net_set_keepalive(int sockfd);
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index c6dad2a13c80..f8ff735eb100 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -107,7 +107,7 @@ static int recv_request_import(int sockfd)
struct usbip_usb_device pdu_udev;
struct list_head *i;
int found = 0;
- int error = 0;
+ int status = ST_OK;
int rc;
memset(&req, 0, sizeof(req));
@@ -133,22 +133,21 @@ static int recv_request_import(int sockfd)
usbip_net_set_nodelay(sockfd);
/* export device needs a TCP/IP socket descriptor */
- rc = usbip_export_device(edev, sockfd);
- if (rc < 0)
- error = 1;
+ status = usbip_export_device(edev, sockfd);
+ if (status < 0)
+ status = ST_NA;
} else {
info("requested device not found: %s", req.busid);
- error = 1;
+ status = ST_NODEV;
}
- rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
- (!error ? ST_OK : ST_NA));
+ rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, status);
if (rc < 0) {
dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
return -1;
}
- if (error) {
+ if (status) {
dbg("import request busid %s: failed", req.busid);
return -1;
}
@@ -251,8 +250,9 @@ static int recv_pdu(int connfd)
{
uint16_t code = OP_UNSPEC;
int ret;
+ int status;
- ret = usbip_net_recv_op_common(connfd, &code);
+ ret = usbip_net_recv_op_common(connfd, &code, &status);
if (ret < 0) {
dbg("could not receive opcode: %#0x", code);
return -1;