* [PATCH 2/6] driver: make struct bus_type::probe optional
2024-02-28 16:05 [PATCH 1/6] driver: make struct bus_type::match optional Ahmad Fatoum
@ 2024-02-28 16:05 ` Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 3/6] treewide: remove bus probe functions that just call driver probe Ahmad Fatoum
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2024-02-28 16:05 UTC (permalink / raw)
To: barebox; +Cc: mfe, Ahmad Fatoum
Newly introduce soc_bus_type doesn't define .probe, which would crash
once a driver is registered on that bus. Do as Linux does and defer
to the driver probe function if there's no bus probe function and
treat non-existence of either as a successful probe.
This has the added benefit that it will allow us to drop very simple bus
probe functions that just call the driver probe and do nothing else.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/driver.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index babc08f8b6b2..b2d428b70550 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -137,7 +137,12 @@ int device_probe(struct device *dev)
list_add(&dev->active, &active_device_list);
- ret = dev->bus->probe(dev);
+ if (dev->bus->probe)
+ ret = dev->bus->probe(dev);
+ else if (dev->driver->probe)
+ ret = dev->driver->probe(dev);
+ else
+ ret = 0;
depth--;
--
2.39.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/6] treewide: remove bus probe functions that just call driver probe
2024-02-28 16:05 [PATCH 1/6] driver: make struct bus_type::match optional Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 2/6] driver: make struct bus_type::probe optional Ahmad Fatoum
@ 2024-02-28 16:05 ` Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 4/6] usb: otg: maintain list of USB OTG controllers Ahmad Fatoum
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2024-02-28 16:05 UTC (permalink / raw)
To: barebox; +Cc: mfe, Ahmad Fatoum
Now that the driver core will call the driver probe function if there is
no bus probe function, remove all bus probe functions that do what the
core can do instead.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/bus/acpi.c | 6 ------
drivers/i2c/i2c.c | 6 ------
drivers/spi/spi.c | 6 ------
drivers/tee/tee_core.c | 6 ------
4 files changed, 24 deletions(-)
diff --git a/drivers/bus/acpi.c b/drivers/bus/acpi.c
index cf85e886d0a2..0d11b604ae5d 100644
--- a/drivers/bus/acpi.c
+++ b/drivers/bus/acpi.c
@@ -205,15 +205,9 @@ static int acpi_bus_match(struct device *dev, struct driver *drv)
return acpi_sigcmp(acpidrv->signature, sdt->signature);
}
-static int acpi_bus_probe(struct device *dev)
-{
- return dev->driver->probe(dev);
-}
-
struct bus_type acpi_bus = {
.name = "acpi",
.match = acpi_bus_match,
- .probe = acpi_bus_probe,
};
static int efi_acpi_probe(void)
diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index 997fc8d81725..547151904517 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -743,15 +743,9 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adapter)
}
EXPORT_SYMBOL(i2c_add_numbered_adapter);
-static int i2c_probe(struct device *dev)
-{
- return dev->driver->probe(dev);
-}
-
struct bus_type i2c_bus = {
.name = "i2c",
.match = device_match_of_modalias,
- .probe = i2c_probe,
};
static int i2c_bus_init(void)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fd9c8da17100..c627d88954a7 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -412,15 +412,9 @@ int spi_write_then_read(struct spi_device *spi,
}
EXPORT_SYMBOL(spi_write_then_read);
-static int spi_probe(struct device *dev)
-{
- return dev->driver->probe(dev);
-}
-
struct bus_type spi_bus = {
.name = "spi",
.match = device_match_of_modalias,
- .probe = spi_probe,
};
static int spi_bus_init(void)
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 36c6210b8b1d..45fa9b567072 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -770,15 +770,9 @@ static int tee_client_device_match(struct device *dev,
return -1;
}
-static int tee_bus_probe(struct device *dev)
-{
- return dev->driver->probe(dev);
-}
-
struct bus_type tee_bus_type = {
.name = "tee",
.match = tee_client_device_match,
- .probe = tee_bus_probe,
};
EXPORT_SYMBOL_GPL(tee_bus_type);
--
2.39.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/6] usb: otg: maintain list of USB OTG controllers
2024-02-28 16:05 [PATCH 1/6] driver: make struct bus_type::match optional Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 2/6] driver: make struct bus_type::probe optional Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 3/6] treewide: remove bus probe functions that just call driver probe Ahmad Fatoum
@ 2024-02-28 16:05 ` Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 5/6] usb: otg: turn global otg device into device alias Ahmad Fatoum
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2024-02-28 16:05 UTC (permalink / raw)
To: barebox; +Cc: mfe, Ahmad Fatoum
We register devices for OTG controllers only to associate a .mode device
parameter with them. Follow-up commits will need to refer to previously
registered OTG controllers, so let's register a bus type for them and
use it to maintain a list of controllers.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/usb/otg/otgdev.c | 11 +++++++++++
include/linux/usb/usb.h | 2 ++
2 files changed, 13 insertions(+)
diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c
index d0a1cecc85cf..e035c988af2d 100644
--- a/drivers/usb/otg/otgdev.c
+++ b/drivers/usb/otg/otgdev.c
@@ -63,6 +63,10 @@ static struct device otg_device = {
.id = DEVICE_ID_SINGLE,
};
+struct bus_type otg_bus_type = {
+ .name = "usbotg" /* "otg" is already taken for the alias */
+};
+
int usb_register_otg_device(struct device *parent,
int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx)
{
@@ -72,6 +76,7 @@ int usb_register_otg_device(struct device *parent,
otg = xzalloc(sizeof(*otg));
otg->dev.priv = otg;
otg->dev.parent = parent;
+ otg->dev.bus = &otg_bus_type;
otg->dev.id = DEVICE_ID_DYNAMIC;
dev_set_name(&otg->dev, "otg");
@@ -90,3 +95,9 @@ int usb_register_otg_device(struct device *parent,
return register_otg_device(&otg->dev, otg);
}
+
+static int otg_bus_init(void)
+{
+ return bus_register(&otg_bus_type);
+}
+pure_initcall(otg_bus_init);
diff --git a/include/linux/usb/usb.h b/include/linux/usb/usb.h
index ffeceec88f9e..a611d19b4a17 100644
--- a/include/linux/usb/usb.h
+++ b/include/linux/usb/usb.h
@@ -480,6 +480,8 @@ enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np,
int usb_register_otg_device(struct device *parent,
int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx);
+extern struct bus_type otg_bus_type;
+
extern struct list_head usb_device_list;
bool usb_hub_is_root_hub(struct usb_device *hdev);
--
2.39.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 5/6] usb: otg: turn global otg device into device alias
2024-02-28 16:05 [PATCH 1/6] driver: make struct bus_type::match optional Ahmad Fatoum
` (2 preceding siblings ...)
2024-02-28 16:05 ` [PATCH 4/6] usb: otg: maintain list of USB OTG controllers Ahmad Fatoum
@ 2024-02-28 16:05 ` Ahmad Fatoum
2024-02-28 16:05 ` [PATCH 6/6] usb: print number of skipped OTG controllers when scanning Ahmad Fatoum
2024-02-29 8:10 ` [PATCH 1/6] driver: make struct bus_type::match optional Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2024-02-28 16:05 UTC (permalink / raw)
To: barebox; +Cc: mfe, Jules Maselbas, Ahmad Fatoum
barebox supports manual switching of USB OTG ports to either peripheral
or host via the otgX.mode={host,peripheral} device parameter.
When support for configuring multiple OTG ports was added, the old
singleton otg device was kept, as not to break existing scripts.
Since then, barebox has gained support for device aliases, which are a
light weight mechanism to resolve device names and point at a different
device. This is exactly what's required here, so make use of it.
Cc: Jules Maselbas <jmaselbas@zdiv.net>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/usb/otg/otgdev.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c
index e035c988af2d..b4315c2d3c28 100644
--- a/drivers/usb/otg/otgdev.c
+++ b/drivers/usb/otg/otgdev.c
@@ -58,11 +58,6 @@ static int register_otg_device(struct device *dev, struct otg_mode *otg)
return PTR_ERR_OR_ZERO(param_mode);
}
-static struct device otg_device = {
- .name = "otg",
- .id = DEVICE_ID_SINGLE,
-};
-
struct bus_type otg_bus_type = {
.name = "usbotg" /* "otg" is already taken for the alias */
};
@@ -70,6 +65,7 @@ struct bus_type otg_bus_type = {
int usb_register_otg_device(struct device *parent,
int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx)
{
+ bool first_otg = list_empty(&otg_bus_type.device_list);
int ret;
struct otg_mode *otg;
@@ -85,15 +81,15 @@ int usb_register_otg_device(struct device *parent,
otg->set_mode_callback = set_mode;
otg->ctx = ctx;
- /* register otg.mode as an alias of otg0.mode */
- if (otg_device.parent == NULL) {
- otg_device.parent = parent;
- ret = register_otg_device(&otg_device, otg);
- if (ret)
- return ret;
- }
+ ret = register_otg_device(&otg->dev, otg);
+ if (ret)
+ return ret;
- return register_otg_device(&otg->dev, otg);
+ /* register otg.mode as an alias of otg0.mode */
+ if (first_otg)
+ dev_add_alias(&otg->dev, "otg");
+
+ return 0;
}
static int otg_bus_init(void)
--
2.39.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 6/6] usb: print number of skipped OTG controllers when scanning
2024-02-28 16:05 [PATCH 1/6] driver: make struct bus_type::match optional Ahmad Fatoum
` (3 preceding siblings ...)
2024-02-28 16:05 ` [PATCH 5/6] usb: otg: turn global otg device into device alias Ahmad Fatoum
@ 2024-02-28 16:05 ` Ahmad Fatoum
2024-02-29 8:10 ` [PATCH 1/6] driver: make struct bus_type::match optional Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2024-02-28 16:05 UTC (permalink / raw)
To: barebox; +Cc: mfe, Ahmad Fatoum
I often get confused by running usb and wondering why devices behind
unconfigured OTG controllers are not enumerated. Improve the user
experience by printing a message when doing a USB scan while some OTG
controllers are not yet configured (i.e. the otg.mode device parameter
hasn't been set to "peripheral" or "host").
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/usb/core/usb.c | 14 ++++++++++++++
drivers/usb/otg/otgdev.c | 12 ++++++++++++
include/linux/usb/usb.h | 2 ++
3 files changed, 28 insertions(+)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 614527fecbf3..1f6f1d7c4184 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -616,6 +616,20 @@ int usb_rescan(void)
pr_info("%d USB Device(s) found\n", dev_count);
+ if (IS_ENABLED(CONFIG_USB_OTGDEV)) {
+ unsigned int skipped_otg = 0;
+ struct device *dev;
+
+ bus_for_each_device(&otg_bus_type, dev) {
+ if (otg_device_get_mode(dev) == USB_DR_MODE_OTG)
+ skipped_otg++;
+ }
+
+ if (skipped_otg)
+ pr_notice("%u unconfigured OTG controller(s) were not scanned\n",
+ skipped_otg);
+ }
+
return dev_count;
}
diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c
index b4315c2d3c28..5a8626343056 100644
--- a/drivers/usb/otg/otgdev.c
+++ b/drivers/usb/otg/otgdev.c
@@ -62,6 +62,18 @@ struct bus_type otg_bus_type = {
.name = "usbotg" /* "otg" is already taken for the alias */
};
+int otg_device_get_mode(struct device *dev)
+{
+ struct otg_mode *otg;
+
+ if (dev->bus != &otg_bus_type)
+ return -ENODEV;
+
+ otg = dev->priv;
+
+ return otg->cur_mode;
+}
+
int usb_register_otg_device(struct device *parent,
int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx)
{
diff --git a/include/linux/usb/usb.h b/include/linux/usb/usb.h
index a611d19b4a17..4ad2fd32d217 100644
--- a/include/linux/usb/usb.h
+++ b/include/linux/usb/usb.h
@@ -480,6 +480,8 @@ enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np,
int usb_register_otg_device(struct device *parent,
int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx);
+int otg_device_get_mode(struct device *dev);
+
extern struct bus_type otg_bus_type;
extern struct list_head usb_device_list;
--
2.39.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/6] driver: make struct bus_type::match optional
2024-02-28 16:05 [PATCH 1/6] driver: make struct bus_type::match optional Ahmad Fatoum
` (4 preceding siblings ...)
2024-02-28 16:05 ` [PATCH 6/6] usb: print number of skipped OTG controllers when scanning Ahmad Fatoum
@ 2024-02-29 8:10 ` Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-02-29 8:10 UTC (permalink / raw)
To: barebox, Ahmad Fatoum; +Cc: mfe
On Wed, 28 Feb 2024 17:05:13 +0100, Ahmad Fatoum wrote:
> Newly introduce soc_bus_type doesn't define .match, which would crash
> once a driver is registered on that bus. Do as Linux does and treat a
> non-existent match callback as meaning that all drivers should be
> matched and that the probe function should indicate via -ENODEV/-ENXIO
> whether a device is indeed suitable.
>
>
> [...]
Applied, thanks!
[1/6] driver: make struct bus_type::match optional
https://git.pengutronix.de/cgit/barebox/commit/?id=78096501a5f9 (link may not be stable)
[2/6] driver: make struct bus_type::probe optional
https://git.pengutronix.de/cgit/barebox/commit/?id=15a18149a615 (link may not be stable)
[3/6] treewide: remove bus probe functions that just call driver probe
https://git.pengutronix.de/cgit/barebox/commit/?id=5ec36ba8cad4 (link may not be stable)
[4/6] usb: otg: maintain list of USB OTG controllers
https://git.pengutronix.de/cgit/barebox/commit/?id=8489b552f071 (link may not be stable)
[5/6] usb: otg: turn global otg device into device alias
https://git.pengutronix.de/cgit/barebox/commit/?id=eb633952b0be (link may not be stable)
[6/6] usb: print number of skipped OTG controllers when scanning
https://git.pengutronix.de/cgit/barebox/commit/?id=0b90c781d183 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 7+ messages in thread