Linux-USB Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/5] Add Apple MFi fastcharge USB device driver
@ 2019-10-09 13:43 Bastien Nocera
  2019-10-09 13:43 ` [PATCH 1/5] USB: Export generic USB device driver functions Bastien Nocera
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 13:43 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Benjamin Tissoires

As discussed in the thread "Driver for something that's neither a
device nor an interface driver?", here's a patchset that makes it
possible for device drivers to extend the generic device driver.

An example usage is provided in the shape of a driver that allows
changing the charge type of an Apple MFi device to be fast.

Bastien Nocera (5):
  USB: Export generic USB device driver functions
  USB: Make it possible to "subclass" usb_device_driver
  USB: Implement usb_device_match_id()
  USB: Select better matching USB drivers when available
  USB: Add driver to control USB fast charge for iOS devices

 drivers/usb/core/driver.c               |  66 +++-
 drivers/usb/core/generic.c              |  49 ++-
 drivers/usb/core/usb.h                  |   4 +
 drivers/usb/misc/Kconfig                |  10 +
 drivers/usb/misc/Makefile               |   1 +
 drivers/usb/misc/apple-mfi-fastcharge.c | 500 ++++++++++++++++++++++++
 include/linux/usb.h                     |   5 +
 7 files changed, 619 insertions(+), 16 deletions(-)
 create mode 100644 drivers/usb/misc/apple-mfi-fastcharge.c

-- 
2.21.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/5] USB: Export generic USB device driver functions
  2019-10-09 13:43 [PATCH 0/5] Add Apple MFi fastcharge USB device driver Bastien Nocera
@ 2019-10-09 13:43 ` Bastien Nocera
  2019-10-09 13:43 ` [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver Bastien Nocera
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 13:43 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Benjamin Tissoires

This will make it possible to implement device drivers which extend the
generic driver without needing to reimplement it.

Signed-off-by: Bastien Nocera <hadess@hadess.net>
---
 drivers/usb/core/generic.c | 20 ++++++++++++--------
 drivers/usb/core/usb.h     |  4 ++++
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 38f8b3e31762..7454c74d43ee 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -195,7 +195,7 @@ int usb_choose_configuration(struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(usb_choose_configuration);
 
-static int generic_probe(struct usb_device *udev)
+int usb_generic_driver_probe(struct usb_device *udev)
 {
 	int err, c;
 
@@ -221,8 +221,9 @@ static int generic_probe(struct usb_device *udev)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_generic_driver_probe);
 
-static void generic_disconnect(struct usb_device *udev)
+void usb_generic_driver_disconnect(struct usb_device *udev)
 {
 	usb_notify_remove_device(udev);
 
@@ -231,10 +232,11 @@ static void generic_disconnect(struct usb_device *udev)
 	if (udev->actconfig)
 		usb_set_configuration(udev, -1);
 }
+EXPORT_SYMBOL_GPL(usb_generic_driver_disconnect);
 
 #ifdef	CONFIG_PM
 
-static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+int usb_generic_driver_suspend(struct usb_device *udev, pm_message_t msg)
 {
 	int rc;
 
@@ -261,8 +263,9 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg)
 		usbfs_notify_suspend(udev);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(usb_generic_driver_suspend);
 
-static int generic_resume(struct usb_device *udev, pm_message_t msg)
+int usb_generic_driver_resume(struct usb_device *udev, pm_message_t msg)
 {
 	int rc;
 
@@ -280,16 +283,17 @@ static int generic_resume(struct usb_device *udev, pm_message_t msg)
 		usbfs_notify_resume(udev);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(usb_generic_driver_resume);
 
 #endif	/* CONFIG_PM */
 
 struct usb_device_driver usb_generic_driver = {
 	.name =	"usb",
-	.probe = generic_probe,
-	.disconnect = generic_disconnect,
+	.probe = usb_generic_driver_probe,
+	.disconnect = usb_generic_driver_disconnect,
 #ifdef	CONFIG_PM
-	.suspend = generic_suspend,
-	.resume = generic_resume,
+	.suspend = usb_generic_driver_suspend,
+	.resume = usb_generic_driver_resume,
 #endif
 	.supports_autosuspend = 1,
 };
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index cf4783cf661a..7423c4c5700f 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -47,6 +47,10 @@ extern void usb_release_bos_descriptor(struct usb_device *dev);
 extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 extern int usb_choose_configuration(struct usb_device *udev);
+extern int usb_generic_driver_probe(struct usb_device *udev);
+extern void usb_generic_driver_disconnect(struct usb_device *udev);
+extern int usb_generic_driver_suspend(struct usb_device *udev, pm_message_t msg);
+extern int usb_generic_driver_resume(struct usb_device *udev, pm_message_t msg);
 
 static inline unsigned usb_get_max_power(struct usb_device *udev,
 		struct usb_host_config *c)
-- 
2.21.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver
  2019-10-09 13:43 [PATCH 0/5] Add Apple MFi fastcharge USB device driver Bastien Nocera
  2019-10-09 13:43 ` [PATCH 1/5] USB: Export generic USB device driver functions Bastien Nocera
@ 2019-10-09 13:43 ` Bastien Nocera
  2019-10-09 14:34   ` Alan Stern
  2019-10-10  9:58   ` kbuild test robot
  2019-10-09 13:43 ` [PATCH 3/5] USB: Implement usb_device_match_id() Bastien Nocera
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 13:43 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Benjamin Tissoires

The kernel currenly has only 2 usb_device_drivers, one generic one, one
that completely replaces the generic one to make USB devices usable over
a network.

Use the newly exported generic driver functions when a driver declares
to want them run, in addition to its own code. This makes it possible to
write drivers that extend the generic USB driver.

Signed-off-by: Bastien Nocera <hadess@hadess.net>
---
 drivers/usb/core/driver.c | 36 ++++++++++++++++++++++++++++++------
 include/linux/usb.h       |  1 +
 2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2b27d232d7a7..863e380a272b 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -261,10 +261,17 @@ static int usb_probe_device(struct device *dev)
 	 */
 	if (!udriver->supports_autosuspend)
 		error = usb_autoresume_device(udev);
+	if (error)
+		return error;
 
-	if (!error)
-		error = udriver->probe(udev);
-	return error;
+	if (udriver->generic_init)
+		error = usb_generic_driver_probe(udev);
+	if (error)
+		return error;
+
+	if (udriver->probe)
+		return udriver->probe(udev);
+	return 0;
 }
 
 /* called from driver core with dev locked */
@@ -273,7 +280,10 @@ static int usb_unbind_device(struct device *dev)
 	struct usb_device *udev = to_usb_device(dev);
 	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
 
-	udriver->disconnect(udev);
+	if (udriver->generic_init)
+		usb_generic_driver_disconnect(udev);
+	if (udriver->disconnect)
+		udriver->disconnect(udev);
 	if (!udriver->supports_autosuspend)
 		usb_autosuspend_device(udev);
 	return 0;
@@ -886,6 +896,14 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver,
 	if (usb_disabled())
 		return -ENODEV;
 
+	if (new_udriver->probe == NULL &&
+	    !new_udriver->generic_init) {
+		printk(KERN_ERR "%s: error %d registering device "
+		       "	driver %s, no probe() function\n",
+		       usbcore_name, retval, new_udriver->name);
+		return -EINVAL;
+	}
+
 	new_udriver->drvwrap.for_devices = 1;
 	new_udriver->drvwrap.driver.name = new_udriver->name;
 	new_udriver->drvwrap.driver.bus = &usb_bus_type;
@@ -1149,7 +1167,10 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
 		udev->do_remote_wakeup = 0;
 		udriver = &usb_generic_driver;
 	}
-	status = udriver->suspend(udev, msg);
+	if (udriver->generic_init)
+		status = usb_generic_driver_suspend (udev, msg);
+	if (status == 0 && udriver->suspend)
+		status = udriver->suspend(udev, msg);
 
  done:
 	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
@@ -1181,7 +1202,10 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
 		udev->reset_resume = 1;
 
 	udriver = to_usb_device_driver(udev->dev.driver);
-	status = udriver->resume(udev, msg);
+	if (udriver->generic_init)
+		status = usb_generic_driver_resume (udev, msg);
+	if (status == 0 && udriver->resume)
+		status = udriver->resume(udev, msg);
 
  done:
 	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e656e7b4b1e4..fb9ad3511e55 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1242,6 +1242,7 @@ struct usb_device_driver {
 	const struct attribute_group **dev_groups;
 	struct usbdrv_wrap drvwrap;
 	unsigned int supports_autosuspend:1;
+	unsigned int generic_init:1;
 };
 #define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
 		drvwrap.driver)
-- 
2.21.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 3/5] USB: Implement usb_device_match_id()
  2019-10-09 13:43 [PATCH 0/5] Add Apple MFi fastcharge USB device driver Bastien Nocera
  2019-10-09 13:43 ` [PATCH 1/5] USB: Export generic USB device driver functions Bastien Nocera
  2019-10-09 13:43 ` [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver Bastien Nocera
@ 2019-10-09 13:43 ` Bastien Nocera
  2019-10-09 14:36   ` Alan Stern
  2019-10-09 13:43 ` [PATCH 4/5] USB: Select better matching USB drivers when available Bastien Nocera
  2019-10-09 13:43 ` [PATCH 5/5] USB: Add driver to control USB fast charge for iOS devices Bastien Nocera
  4 siblings, 1 reply; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 13:43 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Benjamin Tissoires

Match a usb_device with a table of IDs.

Signed-off-by: Bastien Nocera <hadess@hadess.net>
---
 drivers/usb/core/driver.c | 15 +++++++++++++++
 include/linux/usb.h       |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 863e380a272b..50f92da8afcf 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -800,6 +800,21 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 }
 EXPORT_SYMBOL_GPL(usb_match_id);
 
+const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
+				const struct usb_device_id *id)
+{
+	if (!id)
+		return NULL;
+
+	for (; id->idVendor || id->idProduct ; id++) {
+		if (usb_match_device(udev, id))
+			return id;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(usb_device_match_id);
+
 static int usb_device_match(struct device *dev, struct device_driver *drv)
 {
 	/* devices and interfaces are handled separately */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index fb9ad3511e55..66bd4344e298 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -864,6 +864,8 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 					 const struct usb_device_id *id);
 extern int usb_match_one_id(struct usb_interface *interface,
 			    const struct usb_device_id *id);
+const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
+				const struct usb_device_id *id);
 
 extern int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *));
 extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
-- 
2.21.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 13:43 [PATCH 0/5] Add Apple MFi fastcharge USB device driver Bastien Nocera
                   ` (2 preceding siblings ...)
  2019-10-09 13:43 ` [PATCH 3/5] USB: Implement usb_device_match_id() Bastien Nocera
@ 2019-10-09 13:43 ` Bastien Nocera
  2019-10-09 14:43   ` Alan Stern
  2019-10-10 10:33   ` kbuild test robot
  2019-10-09 13:43 ` [PATCH 5/5] USB: Add driver to control USB fast charge for iOS devices Bastien Nocera
  4 siblings, 2 replies; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 13:43 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Benjamin Tissoires

Now that USB device drivers can reuse code from the generic USB device
driver, we need to make sure that they get selected rather than the
generic driver. Add an id_table and match vfunc to the usb_device_driver
struct, which will get used to select a better matching driver at
->probe time.

This is a similar mechanism to that used in the HID drivers, with the
generic driver being selected unless there's a better matching one found
in the registered drivers (see hid_generic_match() in
drivers/hid/hid-generic.c).

Signed-off-by: Bastien Nocera <hadess@hadess.net>
---
 drivers/usb/core/driver.c  | 15 +++++++++++++--
 drivers/usb/core/generic.c | 29 +++++++++++++++++++++++++++++
 include/linux/usb.h        |  2 ++
 3 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 50f92da8afcf..27ce63ed902d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -819,13 +819,24 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
 {
 	/* devices and interfaces are handled separately */
 	if (is_usb_device(dev)) {
+		struct usb_device *udev;
+		struct usb_device_driver *udrv;
 
 		/* interface drivers never match devices */
 		if (!is_usb_device_driver(drv))
 			return 0;
 
-		/* TODO: Add real matching code */
-		return 1;
+		udev = to_usb_device(dev);
+		udrv = to_usb_device_driver(drv);
+
+		if (udrv->id_table &&
+		    usb_device_match_id(udev, udrv->id_table) != NULL) {
+			return 1;
+		}
+
+		if (udrv->match)
+			return udrv->match(udev);
+		return 0;
 
 	} else if (is_usb_interface(dev)) {
 		struct usb_interface *intf;
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 7454c74d43ee..89f9c026a4d1 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -195,6 +195,34 @@ int usb_choose_configuration(struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(usb_choose_configuration);
 
+static int __check_usb_generic(struct device_driver *drv, void *data)
+{
+	struct usb_device *udev = data;
+	struct usb_device_driver *udrv;
+
+	if (!is_usb_device_driver(drv))
+		return 0;
+	udrv = to_usb_device_driver(drv);
+	if (udrv == &usb_generic_driver)
+		return 0;
+	if (!udrv->id_table)
+		return 0;
+
+	return usb_device_match_id(udev, udrv->id_table) != NULL;
+}
+
+static bool usb_generic_driver_match(struct usb_device *udev)
+{
+        /*
+         * If any other driver wants the device, leave the device to this other
+         * driver.
+         */
+        if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_usb_generic))
+                return false;
+
+        return true;
+}
+
 int usb_generic_driver_probe(struct usb_device *udev)
 {
 	int err, c;
@@ -289,6 +317,7 @@ EXPORT_SYMBOL_GPL(usb_generic_driver_resume);
 
 struct usb_device_driver usb_generic_driver = {
 	.name =	"usb",
+	.match = usb_generic_driver_match,
 	.probe = usb_generic_driver_probe,
 	.disconnect = usb_generic_driver_disconnect,
 #ifdef	CONFIG_PM
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 66bd4344e298..df5604f41118 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1236,6 +1236,7 @@ struct usb_driver {
 struct usb_device_driver {
 	const char *name;
 
+	bool (*match) (struct usb_device *udev);
 	int (*probe) (struct usb_device *udev);
 	void (*disconnect) (struct usb_device *udev);
 
@@ -1243,6 +1244,7 @@ struct usb_device_driver {
 	int (*resume) (struct usb_device *udev, pm_message_t message);
 	const struct attribute_group **dev_groups;
 	struct usbdrv_wrap drvwrap;
+	const struct usb_device_id *id_table;
 	unsigned int supports_autosuspend:1;
 	unsigned int generic_init:1;
 };
-- 
2.21.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 5/5] USB: Add driver to control USB fast charge for iOS devices
  2019-10-09 13:43 [PATCH 0/5] Add Apple MFi fastcharge USB device driver Bastien Nocera
                   ` (3 preceding siblings ...)
  2019-10-09 13:43 ` [PATCH 4/5] USB: Select better matching USB drivers when available Bastien Nocera
@ 2019-10-09 13:43 ` Bastien Nocera
  4 siblings, 0 replies; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 13:43 UTC (permalink / raw)
  To: linux-usb; +Cc: Greg Kroah-Hartman, Benjamin Tissoires

iOS devices will not draw more than 500mA unless instructed to do so.
Setting the charge type power supply property to "fast" tells the device
to start drawing more power, using the same procedure that official
"MFi" chargers would.

Signed-off-by: Bastien Nocera <hadess@hadess.net>
---
 drivers/usb/misc/Kconfig                |  10 +
 drivers/usb/misc/Makefile               |   1 +
 drivers/usb/misc/apple-mfi-fastcharge.c | 500 ++++++++++++++++++++++++
 3 files changed, 511 insertions(+)
 create mode 100644 drivers/usb/misc/apple-mfi-fastcharge.c

diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index bdae62b2ffe0..f52a49478f1c 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -147,6 +147,16 @@ config USB_APPLEDISPLAY
 	  Say Y here if you want to control the backlight of Apple Cinema
 	  Displays over USB. This driver provides a sysfs interface.
 
+config APPLE_MFI_FASTCHARGE
+	tristate "Fast charge control for iOS devices"
+	select POWER_SUPPLY
+	help
+	  Say Y here if you want to control whether iOS devices will
+	  fast charge from the USB interface, as implemented in "MFi"
+	  chargers.
+
+	  It is safe to say M here.
+
 source "drivers/usb/misc/sisusbvga/Kconfig"
 
 config USB_LD
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 109f54f5b9aa..b75106cf3948 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_USB_EMI26)			+= emi26.o
 obj-$(CONFIG_USB_EMI62)			+= emi62.o
 obj-$(CONFIG_USB_EZUSB_FX2)		+= ezusb.o
 obj-$(CONFIG_USB_FTDI_ELAN)		+= ftdi-elan.o
+obj-$(CONFIG_APPLE_MFI_FASTCHARGE)	+= apple-mfi-fastcharge.o
 obj-$(CONFIG_USB_IDMOUSE)		+= idmouse.o
 obj-$(CONFIG_USB_IOWARRIOR)		+= iowarrior.o
 obj-$(CONFIG_USB_ISIGHTFW)		+= isight_firmware.o
diff --git a/drivers/usb/misc/apple-mfi-fastcharge.c b/drivers/usb/misc/apple-mfi-fastcharge.c
new file mode 100644
index 000000000000..e28300018adc
--- /dev/null
+++ b/drivers/usb/misc/apple-mfi-fastcharge.c
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Fast-charge control for Apple "MFi" devices
+ *
+ * Copyright (C) 2019 Bastien Nocera <hadess@hadess.net>
+ */
+
+/* Standard include files */
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("Fast-charge control for Apple \"MFi\" devices");
+MODULE_LICENSE("GPL");
+
+#define TRICKLE_CURRENT_MA		0
+#define FAST_CURRENT_MA			2500
+
+#define APPLE_VENDOR_ID			0x05ac	/* Apple */
+#define INTERFACE_NUMBER		0
+
+/* The product ID is defined as starting with 0x12nn, as per the
+ * "Choosing an Apple Device USB Configuration" section in
+ * release R9 (2012) of the "MFi Accessory Hardware Specification"
+ *
+ * To distinguish an Apple device, a USB host can check the device
+ * descriptor of attached USB devices for the following fields:
+ * ■ Vendor ID: 0x05AC
+ * ■ Product ID: 0x12nn
+ *
+ * The table is generated with the following lua program:
+ * i = 0x1200
+ * while i <= 0x12ff do
+ *     print(string.format("\t{ USB_DEVICE(APPLE_VENDOR_ID, 0x%x) },", i))
+ *     i = i + 1
+ * end
+ */
+
+static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1200) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1201) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1202) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1203) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1204) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1205) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1206) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1207) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1208) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1209) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x120a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x120b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x120c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x120d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x120e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x120f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1210) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1211) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1212) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1213) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1214) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1215) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1216) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1217) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1218) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1219) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x121a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x121b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x121c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x121d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x121e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x121f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1220) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1221) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1222) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1223) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1224) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1225) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1226) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1227) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1228) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1229) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x122a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x122b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x122c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x122d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x122e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x122f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1230) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1231) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1232) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1233) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1234) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1235) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1236) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1237) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1238) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1239) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x123a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x123b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x123c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x123d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x123e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x123f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1240) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1241) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1242) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1243) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1244) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1245) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1246) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1247) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1248) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1249) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x124a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x124b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x124c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x124d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x124e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x124f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1250) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1251) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1252) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1253) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1254) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1255) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1256) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1257) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1258) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1259) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x125a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x125b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x125c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x125d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x125e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x125f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1260) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1261) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1262) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1263) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1264) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1265) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1266) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1267) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1268) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1269) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x126a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x126b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x126c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x126d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x126e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x126f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1270) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1271) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1272) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1273) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1274) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1275) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1276) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1277) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1278) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1279) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x127a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x127b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x127c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x127d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x127e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x127f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1280) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1281) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1282) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1283) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1284) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1285) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1286) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1287) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1288) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1289) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x128a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x128b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x128c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x128d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x128e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x128f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1290) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1291) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1292) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1293) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1294) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1295) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1296) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1297) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1298) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x1299) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x129a) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x129b) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x129c) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x129d) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x129e) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x129f) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a0) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a1) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a2) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a3) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a4) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a5) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a6) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a7) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a8) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12a9) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12aa) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ab) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ac) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ad) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ae) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12af) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b0) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b1) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b2) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b3) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b4) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b5) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b6) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b7) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b8) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12b9) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ba) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12bb) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12bc) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12bd) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12be) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12bf) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c0) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c1) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c2) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c3) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c4) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c5) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c6) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c7) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c8) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12c9) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ca) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12cb) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12cc) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12cd) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ce) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12cf) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d0) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d1) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d2) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d3) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d4) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d5) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d6) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d7) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d8) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12d9) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12da) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12db) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12dc) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12dd) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12de) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12df) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e0) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e1) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e2) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e3) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e4) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e5) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e6) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e7) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e8) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12e9) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ea) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12eb) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ec) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ed) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ee) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ef) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f0) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f1) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f2) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f3) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f4) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f5) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f6) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f7) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f8) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12f9) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12fa) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12fb) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12fc) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12fd) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12fe) },
+	{ USB_DEVICE(APPLE_VENDOR_ID, 0x12ff) },
+	{ },
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+/* Driver-local specific stuff */
+struct mfi_device {
+	struct usb_device *udev;
+	struct power_supply *battery;
+	int charge_type;
+};
+
+static int apple_mfi_fc_set_charge_type(struct mfi_device *mfi,
+                const union power_supply_propval *val)
+{
+        int current_ma;
+        int retval;
+
+        if (mfi->charge_type == val->intval) {
+                dev_dbg(&mfi->udev->dev, "charge type %d already set\n", mfi->charge_type);
+                return 0;
+	}
+
+        switch (val->intval) {
+        case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
+                current_ma = TRICKLE_CURRENT_MA;
+                break;
+        case POWER_SUPPLY_CHARGE_TYPE_FAST:
+                current_ma = FAST_CURRENT_MA;
+                break;
+        default:
+                return -EINVAL;
+        }
+
+        retval = usb_control_msg(mfi->udev, usb_sndctrlpipe(mfi->udev, 0),
+                                 0x40, /* Vendor-defined USB get enabled capabilities request. */
+                                 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                                 current_ma, /* wValue, current offset */
+                                 current_ma, /* wIndex, current offset */
+                                 NULL, 0, USB_CTRL_GET_TIMEOUT);
+        if (retval) {
+                dev_dbg(&mfi->udev->dev, "retval = %d\n", retval);
+                return retval;
+        }
+
+        mfi->charge_type = val->intval;
+
+	return 0;
+}
+
+static int apple_mfi_fc_get_property(struct power_supply *psy,
+                enum power_supply_property psp, union power_supply_propval *val)
+{
+        struct mfi_device *mfi = power_supply_get_drvdata(psy);
+
+        dev_dbg(&mfi->udev->dev, "prop: %d\n", psp);
+
+        switch (psp) {
+        case POWER_SUPPLY_PROP_CHARGE_TYPE:
+                val->intval = mfi->charge_type;
+                break;
+        case POWER_SUPPLY_PROP_SCOPE:
+                val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+                break;
+        default:
+                return -ENODATA;
+        }
+
+        return 0;
+}
+
+static int apple_mfi_fc_set_property(struct power_supply *psy,
+                enum power_supply_property psp,
+                const union power_supply_propval *val)
+{
+        struct mfi_device *mfi = power_supply_get_drvdata(psy);
+        int ret;
+
+        dev_dbg(&mfi->udev->dev, "prop: %d\n", psp);
+
+        ret = pm_runtime_get_sync(&mfi->udev->dev);
+        if (ret < 0)
+                return ret;
+
+        switch (psp) {
+        case POWER_SUPPLY_PROP_CHARGE_TYPE:
+                ret = apple_mfi_fc_set_charge_type(mfi, val);
+                break;
+        default:
+                ret = -EINVAL;
+        }
+
+        pm_runtime_mark_last_busy(&mfi->udev->dev);
+        pm_runtime_put_autosuspend(&mfi->udev->dev);
+
+        return ret;
+}
+
+static int apple_mfi_fc_property_is_writeable(struct power_supply *psy,
+                enum power_supply_property psp)
+{
+        switch (psp) {
+        case POWER_SUPPLY_PROP_CHARGE_TYPE:
+                return 1;
+        default:
+                return 0;
+        }
+}
+
+static enum power_supply_property apple_mfi_fc_properties[] = {
+        POWER_SUPPLY_PROP_CHARGE_TYPE,
+        POWER_SUPPLY_PROP_SCOPE
+};
+
+static const struct power_supply_desc apple_mfi_fc_desc = {
+        .name                   = "apple_mfi_fastcharge",
+        .type                   = POWER_SUPPLY_TYPE_BATTERY,
+        .properties             = apple_mfi_fc_properties,
+        .num_properties         = ARRAY_SIZE(apple_mfi_fc_properties),
+        .get_property           = apple_mfi_fc_get_property,
+        .set_property           = apple_mfi_fc_set_property,
+        .property_is_writeable  = apple_mfi_fc_property_is_writeable
+};
+
+static int mfi_fc_probe(struct usb_device *udev)
+{
+	struct power_supply_config battery_cfg = {};
+	struct mfi_device *mfi = NULL;
+	int err;
+
+	dev_err(&udev->dev, "mfi_fc_probe\n");
+
+	mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL);
+	if (!mfi) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	battery_cfg.drv_data = mfi;
+
+	mfi->charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+	mfi->battery = power_supply_register(&udev->dev, &apple_mfi_fc_desc,
+                                                     &battery_cfg);
+        if (IS_ERR(mfi->battery)) {
+                dev_err(&udev->dev, "Can't register battery\n");
+                err = PTR_ERR(mfi->battery);
+                goto error;
+        }
+
+	mfi->udev = usb_get_dev(udev);
+	dev_set_drvdata(&udev->dev, mfi);
+	dev_err(&udev->dev, "Registered fast charge\n");
+
+	return 0;
+
+error:
+	kfree(mfi);
+	return err;
+}
+
+static void mfi_fc_disconnect(struct usb_device *udev)
+{
+	struct mfi_device *mfi;
+
+	dev_err(&udev->dev, "De-registering fast charge\n");
+
+	mfi = dev_get_drvdata(&udev->dev);
+	if (mfi->battery)
+		power_supply_unregister(mfi->battery);
+	dev_set_drvdata(&udev->dev, NULL);
+	usb_put_dev(mfi->udev);
+	kfree(mfi);
+}
+
+static struct usb_device_driver mfi_fc_driver = {
+	.name =		"apple-mfi-fastcharge",
+	.probe =	mfi_fc_probe,
+	.disconnect =	mfi_fc_disconnect,
+	.id_table =	id_table,
+	.generic_init =	1,
+};
+
+static int __init mfi_fc_driver_init(void)
+{
+        int ret;
+
+        pr_err("mfi_fc_driver_init\n");
+
+        ret = usb_register_device_driver(&mfi_fc_driver, THIS_MODULE);
+        if (ret)
+                pr_err("usb_register failed %d\n", ret);
+
+        return ret;
+}
+
+static void __exit mfi_fc_driver_exit(void)
+{
+        pr_err("mfi_fc_driver_exit\n");
+        usb_deregister_device_driver(&mfi_fc_driver);
+}
+
+module_init(mfi_fc_driver_init);
+module_exit(mfi_fc_driver_exit);
-- 
2.21.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver
  2019-10-09 13:43 ` [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver Bastien Nocera
@ 2019-10-09 14:34   ` Alan Stern
  2019-10-09 14:41     ` Alan Stern
  2019-10-10  8:10     ` Bastien Nocera
  2019-10-10  9:58   ` kbuild test robot
  1 sibling, 2 replies; 21+ messages in thread
From: Alan Stern @ 2019-10-09 14:34 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Bastien Nocera wrote:

> The kernel currenly has only 2 usb_device_drivers, one generic one, one
> that completely replaces the generic one to make USB devices usable over
> a network.

Presumably your first driver is in generic.c.  Where is the second one?

> Use the newly exported generic driver functions when a driver declares
> to want them run, in addition to its own code. This makes it possible to
> write drivers that extend the generic USB driver.
> 
> Signed-off-by: Bastien Nocera <hadess@hadess.net>

This has a few problems.  The biggest one is that the device core does 
not guarantee any order of driver probing.  If generic.c is probed 
first, the subclass driver will never get probed -- which is a pretty 
fatal flaw.

> ---
>  drivers/usb/core/driver.c | 36 ++++++++++++++++++++++++++++++------
>  include/linux/usb.h       |  1 +
>  2 files changed, 31 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index 2b27d232d7a7..863e380a272b 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -261,10 +261,17 @@ static int usb_probe_device(struct device *dev)
>  	 */
>  	if (!udriver->supports_autosuspend)
>  		error = usb_autoresume_device(udev);
> +	if (error)
> +		return error;
>  
> -	if (!error)
> -		error = udriver->probe(udev);
> -	return error;
> +	if (udriver->generic_init)
> +		error = usb_generic_driver_probe(udev);
> +	if (error)
> +		return error;
> +
> +	if (udriver->probe)
> +		return udriver->probe(udev);
> +	return 0;
>  }
>  
>  /* called from driver core with dev locked */
> @@ -273,7 +280,10 @@ static int usb_unbind_device(struct device *dev)
>  	struct usb_device *udev = to_usb_device(dev);
>  	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
>  
> -	udriver->disconnect(udev);
> +	if (udriver->generic_init)
> +		usb_generic_driver_disconnect(udev);
> +	if (udriver->disconnect)
> +		udriver->disconnect(udev);

The order is wrong.  The disconnects should always be done in reverse 
order of probing.  This is true whenever you have a destructor for a 
subclass; the subclasses destructor runs before the superclass's 
destructor.

>  	if (!udriver->supports_autosuspend)
>  		usb_autosuspend_device(udev);
>  	return 0;
> @@ -886,6 +896,14 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver,
>  	if (usb_disabled())
>  		return -ENODEV;
>  
> +	if (new_udriver->probe == NULL &&
> +	    !new_udriver->generic_init) {

There's no point adding this extra test.  Even subclass drivers should 
have a probe function.

> +		printk(KERN_ERR "%s: error %d registering device "
> +		       "	driver %s, no probe() function\n",

Don't split character strings.  They are an exception to the 80-column 
limit.

> +		       usbcore_name, retval, new_udriver->name);
> +		return -EINVAL;
> +	}
> +
>  	new_udriver->drvwrap.for_devices = 1;
>  	new_udriver->drvwrap.driver.name = new_udriver->name;
>  	new_udriver->drvwrap.driver.bus = &usb_bus_type;
> @@ -1149,7 +1167,10 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
>  		udev->do_remote_wakeup = 0;
>  		udriver = &usb_generic_driver;
>  	}
> -	status = udriver->suspend(udev, msg);
> +	if (udriver->generic_init)
> +		status = usb_generic_driver_suspend (udev, msg);
> +	if (status == 0 && udriver->suspend)
> +		status = udriver->suspend(udev, msg);

Again, the order is wrong.  Suspend the subclass driver first.

>   done:
>  	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
> @@ -1181,7 +1202,10 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
>  		udev->reset_resume = 1;
>  
>  	udriver = to_usb_device_driver(udev->dev.driver);
> -	status = udriver->resume(udev, msg);
> +	if (udriver->generic_init)
> +		status = usb_generic_driver_resume (udev, msg);
> +	if (status == 0 && udriver->resume)
> +		status = udriver->resume(udev, msg);
>  
>   done:
>  	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
> diff --git a/include/linux/usb.h b/include/linux/usb.h
> index e656e7b4b1e4..fb9ad3511e55 100644
> --- a/include/linux/usb.h
> +++ b/include/linux/usb.h
> @@ -1242,6 +1242,7 @@ struct usb_device_driver {
>  	const struct attribute_group **dev_groups;
>  	struct usbdrv_wrap drvwrap;
>  	unsigned int supports_autosuspend:1;
> +	unsigned int generic_init:1;

How about using a name that actually says something about the driver?  
Such as generic_subclass?  Or subclass_of_generic?

"init" has nothing to do with anything.

>  };
>  #define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
>  		drvwrap.driver)

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/5] USB: Implement usb_device_match_id()
  2019-10-09 13:43 ` [PATCH 3/5] USB: Implement usb_device_match_id() Bastien Nocera
@ 2019-10-09 14:36   ` Alan Stern
  2019-10-09 15:40     ` Bastien Nocera
  0 siblings, 1 reply; 21+ messages in thread
From: Alan Stern @ 2019-10-09 14:36 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Bastien Nocera wrote:

> Match a usb_device with a table of IDs.
> 
> Signed-off-by: Bastien Nocera <hadess@hadess.net>
> ---
>  drivers/usb/core/driver.c | 15 +++++++++++++++
>  include/linux/usb.h       |  2 ++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index 863e380a272b..50f92da8afcf 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -800,6 +800,21 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
>  }
>  EXPORT_SYMBOL_GPL(usb_match_id);
>  
> +const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
> +				const struct usb_device_id *id)
> +{
> +	if (!id)
> +		return NULL;
> +
> +	for (; id->idVendor || id->idProduct ; id++) {
> +		if (usb_match_device(udev, id))
> +			return id;
> +	}

This would be better if you allowed matching against just the idVendor 
field rather than matching against both.  That would make it a lot 
simpler to match all Apple devices, for instance.

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver
  2019-10-09 14:34   ` Alan Stern
@ 2019-10-09 14:41     ` Alan Stern
  2019-10-10  8:10     ` Bastien Nocera
  1 sibling, 0 replies; 21+ messages in thread
From: Alan Stern @ 2019-10-09 14:41 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Alan Stern wrote:

> On Wed, 9 Oct 2019, Bastien Nocera wrote:
> 
> > The kernel currenly has only 2 usb_device_drivers, one generic one, one
> > that completely replaces the generic one to make USB devices usable over
> > a network.
> 
> Presumably your first driver is in generic.c.  Where is the second one?
> 
> > Use the newly exported generic driver functions when a driver declares
> > to want them run, in addition to its own code. This makes it possible to
> > write drivers that extend the generic USB driver.
> > 
> > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> 
> This has a few problems.  The biggest one is that the device core does 
> not guarantee any order of driver probing.  If generic.c is probed 
> first, the subclass driver will never get probed -- which is a pretty 
> fatal flaw.

I wrote this before reading patch 4/5.  So the situation isn't so bad.

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 13:43 ` [PATCH 4/5] USB: Select better matching USB drivers when available Bastien Nocera
@ 2019-10-09 14:43   ` Alan Stern
  2019-10-09 15:35     ` Bastien Nocera
  2019-10-10 10:33   ` kbuild test robot
  1 sibling, 1 reply; 21+ messages in thread
From: Alan Stern @ 2019-10-09 14:43 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Bastien Nocera wrote:

> Now that USB device drivers can reuse code from the generic USB device
> driver, we need to make sure that they get selected rather than the
> generic driver. Add an id_table and match vfunc to the usb_device_driver
> struct, which will get used to select a better matching driver at
> ->probe time.
> 
> This is a similar mechanism to that used in the HID drivers, with the
> generic driver being selected unless there's a better matching one found
> in the registered drivers (see hid_generic_match() in
> drivers/hid/hid-generic.c).
> 
> Signed-off-by: Bastien Nocera <hadess@hadess.net>
> ---
>  drivers/usb/core/driver.c  | 15 +++++++++++++--
>  drivers/usb/core/generic.c | 29 +++++++++++++++++++++++++++++
>  include/linux/usb.h        |  2 ++
>  3 files changed, 44 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index 50f92da8afcf..27ce63ed902d 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -819,13 +819,24 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
>  {
>  	/* devices and interfaces are handled separately */
>  	if (is_usb_device(dev)) {
> +		struct usb_device *udev;
> +		struct usb_device_driver *udrv;
>  
>  		/* interface drivers never match devices */
>  		if (!is_usb_device_driver(drv))
>  			return 0;
>  
> -		/* TODO: Add real matching code */
> -		return 1;
> +		udev = to_usb_device(dev);
> +		udrv = to_usb_device_driver(drv);
> +
> +		if (udrv->id_table &&
> +		    usb_device_match_id(udev, udrv->id_table) != NULL) {
> +			return 1;
> +		}
> +
> +		if (udrv->match)
> +			return udrv->match(udev);
> +		return 0;

What happens if the subclass driver's probe routine returns an error?  
Don't you still want the device to be bound to the generic driver?

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 14:43   ` Alan Stern
@ 2019-10-09 15:35     ` Bastien Nocera
  2019-10-09 17:28       ` Alan Stern
  0 siblings, 1 reply; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 15:35 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 2019-10-09 at 10:43 -0400, Alan Stern wrote:
> On Wed, 9 Oct 2019, Bastien Nocera wrote:
> 
> > Now that USB device drivers can reuse code from the generic USB
> device
> > driver, we need to make sure that they get selected rather than the
> > generic driver. Add an id_table and match vfunc to the
> usb_device_driver
> > struct, which will get used to select a better matching driver at
> > ->probe time.
> > 
> > This is a similar mechanism to that used in the HID drivers, with
> the
> > generic driver being selected unless there's a better matching one
> found
> > in the registered drivers (see hid_generic_match() in
> > drivers/hid/hid-generic.c).
> > 
> > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> > ---
> >  drivers/usb/core/driver.c  | 15 +++++++++++++--
> >  drivers/usb/core/generic.c | 29 +++++++++++++++++++++++++++++
> >  include/linux/usb.h        |  2 ++
> >  3 files changed, 44 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> > index 50f92da8afcf..27ce63ed902d 100644
> > --- a/drivers/usb/core/driver.c
> > +++ b/drivers/usb/core/driver.c
> > @@ -819,13 +819,24 @@ static int usb_device_match(struct device
> *dev, struct device_driver *drv)
> >  {
> >       /* devices and interfaces are handled separately */
> >       if (is_usb_device(dev)) {
> > +             struct usb_device *udev;
> > +             struct usb_device_driver *udrv;
> >  
> >               /* interface drivers never match devices */
> >               if (!is_usb_device_driver(drv))
> >                       return 0;
> >  
> > -             /* TODO: Add real matching code */
> > -             return 1;
> > +             udev = to_usb_device(dev);
> > +             udrv = to_usb_device_driver(drv);
> > +
> > +             if (udrv->id_table &&
> > +                 usb_device_match_id(udev, udrv->id_table) !=
> NULL) {
> > +                     return 1;
> > +             }
> > +
> > +             if (udrv->match)
> > +                     return udrv->match(udev);
> > +             return 0;
> 
> What happens if the subclass driver's probe routine returns an
> error?  
> Don't you still want the device to be bound to the generic driver?

I don't know whether that's what you'd want to do. But if we did,
that'd only be for devices which have "generic_init" set.

We'd need to remember the result of the ->probe() call at the end of
usb_probe_device() (as modified in patch 2), and only call the generic
driver (not the specific device driver)'s functions in later usage.

Is that what you would expect?


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/5] USB: Implement usb_device_match_id()
  2019-10-09 14:36   ` Alan Stern
@ 2019-10-09 15:40     ` Bastien Nocera
  2019-10-09 17:29       ` Alan Stern
  0 siblings, 1 reply; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 15:40 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 2019-10-09 at 10:36 -0400, Alan Stern wrote:
> On Wed, 9 Oct 2019, Bastien Nocera wrote:
> 
> > Match a usb_device with a table of IDs.
> > 
> > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> > ---
> >  drivers/usb/core/driver.c | 15 +++++++++++++++
> >  include/linux/usb.h       |  2 ++
> >  2 files changed, 17 insertions(+)
> > 
> > diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> > index 863e380a272b..50f92da8afcf 100644
> > --- a/drivers/usb/core/driver.c
> > +++ b/drivers/usb/core/driver.c
> > @@ -800,6 +800,21 @@ const struct usb_device_id
> *usb_match_id(struct usb_interface *interface,
> >  }
> >  EXPORT_SYMBOL_GPL(usb_match_id);
> >  
> > +const struct usb_device_id *usb_device_match_id(struct usb_device
> *udev,
> > +                             const struct usb_device_id *id)
> > +{
> > +     if (!id)
> > +             return NULL;
> > +
> > +     for (; id->idVendor || id->idProduct ; id++) {
> > +             if (usb_match_device(udev, id))
> > +                     return id;
> > +     }
> 
> This would be better if you allowed matching against just the
> idVendor 
> field rather than matching against both.  That would make it a lot 
> simpler to match all Apple devices, for instance.

That should already be possible. The matching code is the same as for
the USB interface drivers.

Something like:
static const struct usb_device_id apple_match[] = {
    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR,
      .idVendor = USB_VENDOR_APPLE
    },
    {}
}

And I couldn't use it in patch 5/5, as that's a range of product IDs,
not all of them (which would be quite a lot more).


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 15:35     ` Bastien Nocera
@ 2019-10-09 17:28       ` Alan Stern
  2019-10-09 18:24         ` Bastien Nocera
  0 siblings, 1 reply; 21+ messages in thread
From: Alan Stern @ 2019-10-09 17:28 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Bastien Nocera wrote:

> On Wed, 2019-10-09 at 10:43 -0400, Alan Stern wrote:
> > On Wed, 9 Oct 2019, Bastien Nocera wrote:
> > 
> > > Now that USB device drivers can reuse code from the generic USB
> > device
> > > driver, we need to make sure that they get selected rather than the
> > > generic driver. Add an id_table and match vfunc to the
> > usb_device_driver
> > > struct, which will get used to select a better matching driver at
> > > ->probe time.
> > > 
> > > This is a similar mechanism to that used in the HID drivers, with
> > the
> > > generic driver being selected unless there's a better matching one
> > found
> > > in the registered drivers (see hid_generic_match() in
> > > drivers/hid/hid-generic.c).
> > > 
> > > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> > > ---
> > >  drivers/usb/core/driver.c  | 15 +++++++++++++--
> > >  drivers/usb/core/generic.c | 29 +++++++++++++++++++++++++++++
> > >  include/linux/usb.h        |  2 ++
> > >  3 files changed, 44 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> > > index 50f92da8afcf..27ce63ed902d 100644
> > > --- a/drivers/usb/core/driver.c
> > > +++ b/drivers/usb/core/driver.c
> > > @@ -819,13 +819,24 @@ static int usb_device_match(struct device
> > *dev, struct device_driver *drv)
> > >  {
> > >       /* devices and interfaces are handled separately */
> > >       if (is_usb_device(dev)) {
> > > +             struct usb_device *udev;
> > > +             struct usb_device_driver *udrv;
> > >  
> > >               /* interface drivers never match devices */
> > >               if (!is_usb_device_driver(drv))
> > >                       return 0;
> > >  
> > > -             /* TODO: Add real matching code */
> > > -             return 1;
> > > +             udev = to_usb_device(dev);
> > > +             udrv = to_usb_device_driver(drv);
> > > +
> > > +             if (udrv->id_table &&
> > > +                 usb_device_match_id(udev, udrv->id_table) !=
> > NULL) {
> > > +                     return 1;
> > > +             }
> > > +
> > > +             if (udrv->match)
> > > +                     return udrv->match(udev);
> > > +             return 0;
> > 
> > What happens if the subclass driver's probe routine returns an
> > error?  
> > Don't you still want the device to be bound to the generic driver?
> 
> I don't know whether that's what you'd want to do. But if we did,
> that'd only be for devices which have "generic_init" set.
> 
> We'd need to remember the result of the ->probe() call at the end of
> usb_probe_device() (as modified in patch 2), and only call the generic
> driver (not the specific device driver)'s functions in later usage.
> 
> Is that what you would expect?

No, that's not quite it.

Here's what should happen when the subclass driver is being probed:
First, call the generic_probe routine, and return immediately if that
fails.  Then call the subclass driver's probe routine.  If that gets an
error, fail the probe call but tell the device core that the device is
now bound to the generic driver, not to the subclass driver.

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/5] USB: Implement usb_device_match_id()
  2019-10-09 15:40     ` Bastien Nocera
@ 2019-10-09 17:29       ` Alan Stern
  0 siblings, 0 replies; 21+ messages in thread
From: Alan Stern @ 2019-10-09 17:29 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Bastien Nocera wrote:

> > This would be better if you allowed matching against just the
> > idVendor 
> > field rather than matching against both.  That would make it a lot 
> > simpler to match all Apple devices, for instance.
> 
> That should already be possible. The matching code is the same as for
> the USB interface drivers.
> 
> Something like:
> static const struct usb_device_id apple_match[] = {
>     { .match_flags = USB_DEVICE_ID_MATCH_VENDOR,
>       .idVendor = USB_VENDOR_APPLE
>     },
>     {}
> }
> 
> And I couldn't use it in patch 5/5, as that's a range of product IDs,
> not all of them (which would be quite a lot more).

You can still use it in patch 5/5.  Match any device with Apple's VID;
then have the probe routine return -ENODEV if the PID is outside the
range you want.

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 17:28       ` Alan Stern
@ 2019-10-09 18:24         ` Bastien Nocera
  2019-10-09 18:45           ` Alan Stern
  0 siblings, 1 reply; 21+ messages in thread
From: Bastien Nocera @ 2019-10-09 18:24 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 2019-10-09 at 13:28 -0400, Alan Stern wrote:
<snip>
> No, that's not quite it.
> 
> Here's what should happen when the subclass driver is being probed:
> First, call the generic_probe routine, and return immediately if that
> fails.  Then call the subclass driver's probe routine.  If that gets
> an
> error, fail the probe call but tell the device core that the device
> is
> now bound to the generic driver, not to the subclass driver.

So, something like that, on top of the existing patches? (I'm not sure
whether device_driver_attach is the correct call to use here).

-       if (udriver->probe)
-               return udriver->probe(udev);
-       return 0;
+       if (!udriver->probe)
+               return 0;
+       error = udriver->probe(udev);
+       if (error == -ENODEV &&
+           udrv != &usb_generic_driver)
+               return device_driver_attach(usb_generic_driver.drvwrap.driver, dev);
+       return error;

Anything else in this patch series? I was concerned about the naming
for "generic_init" in patch 2 ("subclass").

If there's nothing, I'll test and respin the patchset with the above
changes tomorrow.

Cheers


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 18:24         ` Bastien Nocera
@ 2019-10-09 18:45           ` Alan Stern
  2019-10-10  8:26             ` Bastien Nocera
  0 siblings, 1 reply; 21+ messages in thread
From: Alan Stern @ 2019-10-09 18:45 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 9 Oct 2019, Bastien Nocera wrote:

> On Wed, 2019-10-09 at 13:28 -0400, Alan Stern wrote:
> <snip>
> > No, that's not quite it.
> > 
> > Here's what should happen when the subclass driver is being probed:
> > First, call the generic_probe routine, and return immediately if that
> > fails.  Then call the subclass driver's probe routine.  If that gets
> > an
> > error, fail the probe call but tell the device core that the device
> > is
> > now bound to the generic driver, not to the subclass driver.
> 
> So, something like that, on top of the existing patches? (I'm not sure
> whether device_driver_attach is the correct call to use here).
> 
> -       if (udriver->probe)
> -               return udriver->probe(udev);
> -       return 0;
> +       if (!udriver->probe)
> +               return 0;

This test is unnecessary; all drivers must have a probe routine.  
Otherwise how would they know when they get bound to a device?

> +       error = udriver->probe(udev);
> +       if (error == -ENODEV &&
> +           udrv != &usb_generic_driver)

No need to test for usb_generic_driver; its probe routine always 
returns 0.  But if you want to include the test anyway, at least don't 
split the line -- it will all fit in under 80 columns.

> +               return device_driver_attach(usb_generic_driver.drvwrap.driver, dev);
> +       return error;

I think that's right.  A little testing wouldn't hurt.

> Anything else in this patch series? I was concerned about the naming
> for "generic_init" in patch 2 ("subclass").

Yes; see the suggestions in

	https://marc.info/?l=linux-usb&m=157063168632242&w=2

Also (I didn't notice this earlier), in patch 1/5 it's not necessary to 
EXPORT the usb_generic_* routines.  They don't get used in the subclass 
driver, only in usbcore.

> If there's nothing, I'll test and respin the patchset with the above
> changes tomorrow.

Okay, good.

Alan Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver
  2019-10-09 14:34   ` Alan Stern
  2019-10-09 14:41     ` Alan Stern
@ 2019-10-10  8:10     ` Bastien Nocera
  1 sibling, 0 replies; 21+ messages in thread
From: Bastien Nocera @ 2019-10-10  8:10 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

More replies inline (which I always miss)

On Wed, 2019-10-09 at 10:34 -0400, Alan Stern wrote:
> On Wed, 9 Oct 2019, Bastien Nocera wrote:
> 
> > The kernel currenly has only 2 usb_device_drivers, one generic one,
> one
> > that completely replaces the generic one to make USB devices usable
> over
> > a network.
> 
> Presumably your first driver is in generic.c.  Where is the second
> one?
> 
> > Use the newly exported generic driver functions when a driver
> declares
> > to want them run, in addition to its own code. This makes it
> possible to
> > write drivers that extend the generic USB driver.
> > 
> > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> 
> This has a few problems.  The biggest one is that the device core
> does 
> not guarantee any order of driver probing.  If generic.c is probed 
> first, the subclass driver will never get probed -- which is a
> pretty 
> fatal flaw.
> 
> > ---
> >  drivers/usb/core/driver.c | 36 ++++++++++++++++++++++++++++++-----
> -
> >  include/linux/usb.h       |  1 +
> >  2 files changed, 31 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> > index 2b27d232d7a7..863e380a272b 100644
> > --- a/drivers/usb/core/driver.c
> > +++ b/drivers/usb/core/driver.c
> > @@ -261,10 +261,17 @@ static int usb_probe_device(struct device
> *dev)
> >        */
> >       if (!udriver->supports_autosuspend)
> >               error = usb_autoresume_device(udev);
> > +     if (error)
> > +             return error;
> >  
> > -     if (!error)
> > -             error = udriver->probe(udev);
> > -     return error;
> > +     if (udriver->generic_init)
> > +             error = usb_generic_driver_probe(udev);
> > +     if (error)
> > +             return error;
> > +
> > +     if (udriver->probe)
> > +             return udriver->probe(udev);
> > +     return 0;
> >  }
> >  
> >  /* called from driver core with dev locked */
> > @@ -273,7 +280,10 @@ static int usb_unbind_device(struct device
> *dev)
> >       struct usb_device *udev = to_usb_device(dev);
> >       struct usb_device_driver *udriver = to_usb_device_driver(dev-
> >driver);
> >  
> > -     udriver->disconnect(udev);
> > +     if (udriver->generic_init)
> > +             usb_generic_driver_disconnect(udev);
> > +     if (udriver->disconnect)
> > +             udriver->disconnect(udev);
> 
> The order is wrong.  The disconnects should always be done in
> reverse 
> order of probing.  This is true whenever you have a destructor for a 
> subclass; the subclasses destructor runs before the superclass's 
> destructor.

Fixed. Fixed in the suspend function as well.

> >       if (!udriver->supports_autosuspend)
> >               usb_autosuspend_device(udev);
> >       return 0;
> > @@ -886,6 +896,14 @@ int usb_register_device_driver(struct
> usb_device_driver *new_udriver,
> >       if (usb_disabled())
> >               return -ENODEV;
> >  
> > +     if (new_udriver->probe == NULL &&
> > +         !new_udriver->generic_init) {
> 
> There's no point adding this extra test.  Even subclass drivers
> should 
> have a probe function.

Removed.

> > +             printk(KERN_ERR "%s: error %d registering device "
> > +                    "        driver %s, no probe() function\n",
> 
> Don't split character strings.  They are an exception to the 80-
> column 
> limit.

I was using the error message just below in the function as an example.
A bad one apparently. This is gone in any case.

> > +                    usbcore_name, retval, new_udriver->name);
> > +             return -EINVAL;
> > +     }
> > +
> >       new_udriver->drvwrap.for_devices = 1;
> >       new_udriver->drvwrap.driver.name = new_udriver->name;
> >       new_udriver->drvwrap.driver.bus = &usb_bus_type;
> > @@ -1149,7 +1167,10 @@ static int usb_suspend_device(struct
> usb_device *udev, pm_message_t msg)
> >               udev->do_remote_wakeup = 0;
> >               udriver = &usb_generic_driver;
> >       }
> > -     status = udriver->suspend(udev, msg);
> > +     if (udriver->generic_init)
> > +             status = usb_generic_driver_suspend (udev, msg);
> > +     if (status == 0 && udriver->suspend)
> > +             status = udriver->suspend(udev, msg);
> 
> Again, the order is wrong.  Suspend the subclass driver first.

Done, as mentioned above.

> >   done:
> >       dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
> > @@ -1181,7 +1202,10 @@ static int usb_resume_device(struct
> usb_device *udev, pm_message_t msg)
> >               udev->reset_resume = 1;
> >  
> >       udriver = to_usb_device_driver(udev->dev.driver);
> > -     status = udriver->resume(udev, msg);
> > +     if (udriver->generic_init)
> > +             status = usb_generic_driver_resume (udev, msg);
> > +     if (status == 0 && udriver->resume)
> > +             status = udriver->resume(udev, msg);
> >  
> >   done:
> >       dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
> > diff --git a/include/linux/usb.h b/include/linux/usb.h
> > index e656e7b4b1e4..fb9ad3511e55 100644
> > --- a/include/linux/usb.h
> > +++ b/include/linux/usb.h
> > @@ -1242,6 +1242,7 @@ struct usb_device_driver {
> >       const struct attribute_group **dev_groups;
> >       struct usbdrv_wrap drvwrap;
> >       unsigned int supports_autosuspend:1;
> > +     unsigned int generic_init:1;
> 
> How about using a name that actually says something about the
> driver?  
> Such as generic_subclass?  Or subclass_of_generic?
> 
> "init" has nothing to do with anything.

generic_subclass it will be. I've also documented it in the header.

> >  };
> >  #define      to_usb_device_driver(d) container_of(d, struct
> usb_device_driver, \
> >               drvwrap.driver)
> 
> Alan Stern
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 18:45           ` Alan Stern
@ 2019-10-10  8:26             ` Bastien Nocera
  2019-10-10 14:19               ` Alan Stern
  0 siblings, 1 reply; 21+ messages in thread
From: Bastien Nocera @ 2019-10-10  8:26 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Wed, 2019-10-09 at 14:45 -0400, Alan Stern wrote:
> 
On Wed, 9 Oct 2019, Bastien Nocera wrote:
> 
> <snip>
> > +               return
> device_driver_attach(usb_generic_driver.drvwrap.driver, dev);
> > +       return error;
> 
> I think that's right.  A little testing wouldn't hurt.

device_driver_attach() isn't available to this part of the code.

I think the only way to do things here might be to set status bit for
the usb_device and launch device_reprobe(). The second time around, we
wouldn't match or probe the specific driver.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver
  2019-10-09 13:43 ` [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver Bastien Nocera
  2019-10-09 14:34   ` Alan Stern
@ 2019-10-10  9:58   ` kbuild test robot
  1 sibling, 0 replies; 21+ messages in thread
From: kbuild test robot @ 2019-10-10  9:58 UTC (permalink / raw)
  To: Bastien Nocera
  Cc: kbuild-all, linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

[-- Attachment #1: Type: text/plain, Size: 19888 bytes --]

Hi Bastien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on usb/usb-testing]
[cannot apply to v5.4-rc2 next-20191010]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Bastien-Nocera/Add-Apple-MFi-fastcharge-USB-device-driver/20191010-155853
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
reproduce: make htmldocs

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   Warning: The Sphinx 'sphinx_rtd_theme' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.
   WARNING: dot(1) not found, for better output quality install graphviz from http://www.graphviz.org
   WARNING: convert(1) not found, for SVG to PDF conversion install ImageMagick (https://www.imagemagick.org)
   include/linux/regulator/machine.h:196: warning: Function parameter or member 'max_uV_step' not described in 'regulation_constraints'
   include/linux/regulator/driver.h:223: warning: Function parameter or member 'resume' not described in 'regulator_ops'
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file include/linux/reservation.h
   Error: Cannot open file include/linux/reservation.h
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quotactl' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quota_on' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_free_mnt_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_eat_lsm_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_kern_mount' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_show_options' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_add_mnt_opt' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'd_instantiate' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'getprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'setprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'locked_down' not described in 'security_list_options'
   include/linux/spi/spi.h:190: warning: Function parameter or member 'driver_override' not described in 'spi_device'
   lib/genalloc.c:1: warning: 'gen_pool_add_virt' not found
   lib/genalloc.c:1: warning: 'gen_pool_alloc' not found
   lib/genalloc.c:1: warning: 'gen_pool_free' not found
   lib/genalloc.c:1: warning: 'gen_pool_alloc_algo' not found
   drivers/gpio/gpiolib-of.c:92: warning: Excess function parameter 'dev' description in 'of_gpio_need_valid_mask'
   include/linux/i2c.h:337: warning: Function parameter or member 'init_irq' not described in 'i2c_client'
   drivers/usb/typec/bus.c:1: warning: 'typec_altmode_unregister_driver' not found
   drivers/usb/typec/bus.c:1: warning: 'typec_altmode_register_driver' not found
   drivers/usb/typec/class.c:1: warning: 'typec_altmode_unregister_notifier' not found
   drivers/usb/typec/class.c:1: warning: 'typec_altmode_register_notifier' not found
>> include/linux/usb.h:1247: warning: Function parameter or member 'generic_init' not described in 'usb_device_driver'
   include/linux/w1.h:277: warning: Function parameter or member 'of_match_table' not described in 'w1_family'
   fs/fs-writeback.c:913: warning: Excess function parameter 'nr_pages' description in 'cgroup_writeback_by_id'
   fs/direct-io.c:258: warning: Excess function parameter 'offset' description in 'dio_complete'
   fs/libfs.c:496: warning: Excess function parameter 'available' description in 'simple_write_end'
   fs/posix_acl.c:647: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:647: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:647: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode'
   kernel/dma/coherent.c:1: warning: no structured comments found
   include/linux/input/sparse-keymap.h:43: warning: Function parameter or member 'sw' not described in 'key_entry'
   include/linux/skbuff.h:888: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'list' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'head_frag' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'encapsulation' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_valid' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_vlan_present_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'vlan_present' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_level' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff'
   include/net/sock.h:233: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_portpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_daddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_rcv_saddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_cookie' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_listener' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_dr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_rcv_wnd' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_rcv_nxt' not described in 'sock_common'
   include/net/sock.h:515: warning: Function parameter or member 'sk_rx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_wq_raw' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'tcp_rtx_queue' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_tx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_route_forced_caps' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_txtime_report_errors' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_validate_xmit_skb' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_bpf_storage' not described in 'sock'
   include/net/sock.h:2439: warning: Function parameter or member 'tcp_rx_skb_cache_key' not described in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'sk' description in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'skb' description in 'DECLARE_STATIC_KEY_FALSE'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'gso_partial_features' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'l3mdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xfrmdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'tlsdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'name_assign_type' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'ieee802154_ptr' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'mpls_ptr' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xdp_prog' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'gro_flush_timeout' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member '____cacheline_aligned_in_smp' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'qdisc_hash' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_cpus_map' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_rxqs_map' not described in 'net_device'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state'
   drivers/net/phy/phylink.c:595: warning: Function parameter or member 'config' not described in 'phylink_create'
   drivers/net/phy/phylink.c:595: warning: Excess function parameter 'ndev' description in 'phylink_create'
   include/linux/bitmap.h:341: warning: Function parameter or member 'nbits' not described in 'bitmap_or_equal'
   include/linux/rculist.h:374: warning: Excess function parameter 'cond' description in 'list_for_each_entry_rcu'
   include/linux/rculist.h:651: warning: Excess function parameter 'cond' description in 'hlist_for_each_entry_rcu'
   mm/util.c:1: warning: 'get_user_pages_fast' not found
   mm/slab.c:4215: warning: Function parameter or member 'objp' not described in '__ksize'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:335: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:336: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:142: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:347: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:348: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:494: warning: Function parameter or member 'start' not described in 'amdgpu_vm_pt_first_dfs'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:823: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:2823: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:378: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Function parameter or member 'ih' not described in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:1: warning: 'pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie' not found

vim +1247 include/linux/usb.h

8bb54ab573ecd1 Alan Stern         2006-07-01  1212  
8bb54ab573ecd1 Alan Stern         2006-07-01  1213  /**
8bb54ab573ecd1 Alan Stern         2006-07-01  1214   * struct usb_device_driver - identifies USB device driver to usbcore
8bb54ab573ecd1 Alan Stern         2006-07-01  1215   * @name: The driver name should be unique among USB drivers,
8bb54ab573ecd1 Alan Stern         2006-07-01  1216   *	and should normally be the same as the module name.
8bb54ab573ecd1 Alan Stern         2006-07-01  1217   * @probe: Called to see if the driver is willing to manage a particular
8bb54ab573ecd1 Alan Stern         2006-07-01  1218   *	device.  If it is, probe returns zero and uses dev_set_drvdata()
8bb54ab573ecd1 Alan Stern         2006-07-01  1219   *	to associate driver-specific data with the device.  If unwilling
8bb54ab573ecd1 Alan Stern         2006-07-01  1220   *	to manage the device, return a negative errno value.
8bb54ab573ecd1 Alan Stern         2006-07-01  1221   * @disconnect: Called when the device is no longer accessible, usually
8bb54ab573ecd1 Alan Stern         2006-07-01  1222   *	because it has been (or is being) disconnected or the driver's
8bb54ab573ecd1 Alan Stern         2006-07-01  1223   *	module is being unloaded.
8bb54ab573ecd1 Alan Stern         2006-07-01  1224   * @suspend: Called when the device is going to be suspended by the system.
8bb54ab573ecd1 Alan Stern         2006-07-01  1225   * @resume: Called when the device is being resumed by the system.
7d9c1d2f7aca26 Greg Kroah-Hartman 2019-08-06  1226   * @dev_groups: Attributes attached to the device that will be created once it
7d9c1d2f7aca26 Greg Kroah-Hartman 2019-08-06  1227   *	is bound to the driver.
8bb54ab573ecd1 Alan Stern         2006-07-01  1228   * @drvwrap: Driver-model core structure wrapper.
645daaab0b6adc Alan Stern         2006-08-30  1229   * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
645daaab0b6adc Alan Stern         2006-08-30  1230   *	for devices bound to this driver.
8bb54ab573ecd1 Alan Stern         2006-07-01  1231   *
8bb54ab573ecd1 Alan Stern         2006-07-01  1232   * USB drivers must provide all the fields listed above except drvwrap.
8bb54ab573ecd1 Alan Stern         2006-07-01  1233   */
8bb54ab573ecd1 Alan Stern         2006-07-01  1234  struct usb_device_driver {
8bb54ab573ecd1 Alan Stern         2006-07-01  1235  	const char *name;
8bb54ab573ecd1 Alan Stern         2006-07-01  1236  
8bb54ab573ecd1 Alan Stern         2006-07-01  1237  	int (*probe) (struct usb_device *udev);
8bb54ab573ecd1 Alan Stern         2006-07-01  1238  	void (*disconnect) (struct usb_device *udev);
8bb54ab573ecd1 Alan Stern         2006-07-01  1239  
8bb54ab573ecd1 Alan Stern         2006-07-01  1240  	int (*suspend) (struct usb_device *udev, pm_message_t message);
65bfd2967c906c Alan Stern         2008-11-25  1241  	int (*resume) (struct usb_device *udev, pm_message_t message);
7d9c1d2f7aca26 Greg Kroah-Hartman 2019-08-06  1242  	const struct attribute_group **dev_groups;
8bb54ab573ecd1 Alan Stern         2006-07-01  1243  	struct usbdrv_wrap drvwrap;
645daaab0b6adc Alan Stern         2006-08-30  1244  	unsigned int supports_autosuspend:1;
e4877e9d91a42a Bastien Nocera     2019-10-09  1245  	unsigned int generic_init:1;
8bb54ab573ecd1 Alan Stern         2006-07-01  1246  };
8bb54ab573ecd1 Alan Stern         2006-07-01 @1247  #define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
8bb54ab573ecd1 Alan Stern         2006-07-01  1248  		drvwrap.driver)
^1da177e4c3f41 Linus Torvalds     2005-04-16  1249  

:::::: The code at line 1247 was first introduced by commit
:::::: 8bb54ab573ecd1b4fe2ed66416a8d99a86e65316 usbcore: add usb_device_driver definition

:::::: TO: Alan Stern <stern@rowland.harvard.edu>
:::::: CC: Greg Kroah-Hartman <gregkh@suse.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7278 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-09 13:43 ` [PATCH 4/5] USB: Select better matching USB drivers when available Bastien Nocera
  2019-10-09 14:43   ` Alan Stern
@ 2019-10-10 10:33   ` kbuild test robot
  1 sibling, 0 replies; 21+ messages in thread
From: kbuild test robot @ 2019-10-10 10:33 UTC (permalink / raw)
  To: Bastien Nocera
  Cc: kbuild-all, linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

[-- Attachment #1: Type: text/plain, Size: 20198 bytes --]

Hi Bastien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on usb/usb-testing]
[cannot apply to v5.4-rc2 next-20191010]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Bastien-Nocera/Add-Apple-MFi-fastcharge-USB-device-driver/20191010-155853
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
reproduce: make htmldocs

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   Warning: The Sphinx 'sphinx_rtd_theme' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.
   WARNING: dot(1) not found, for better output quality install graphviz from http://www.graphviz.org
   WARNING: convert(1) not found, for SVG to PDF conversion install ImageMagick (https://www.imagemagick.org)
   include/linux/regulator/machine.h:196: warning: Function parameter or member 'max_uV_step' not described in 'regulation_constraints'
   include/linux/regulator/driver.h:223: warning: Function parameter or member 'resume' not described in 'regulator_ops'
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file drivers/dma-buf/reservation.c
   Error: Cannot open file include/linux/reservation.h
   Error: Cannot open file include/linux/reservation.h
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quotactl' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'quota_on' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_free_mnt_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_eat_lsm_opts' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_kern_mount' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_show_options' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'sb_add_mnt_opt' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'd_instantiate' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'getprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'setprocattr' not described in 'security_list_options'
   include/linux/lsm_hooks.h:1822: warning: Function parameter or member 'locked_down' not described in 'security_list_options'
   include/linux/spi/spi.h:190: warning: Function parameter or member 'driver_override' not described in 'spi_device'
   lib/genalloc.c:1: warning: 'gen_pool_add_virt' not found
   lib/genalloc.c:1: warning: 'gen_pool_alloc' not found
   lib/genalloc.c:1: warning: 'gen_pool_free' not found
   lib/genalloc.c:1: warning: 'gen_pool_alloc_algo' not found
   drivers/gpio/gpiolib-of.c:92: warning: Excess function parameter 'dev' description in 'of_gpio_need_valid_mask'
   include/linux/i2c.h:337: warning: Function parameter or member 'init_irq' not described in 'i2c_client'
   drivers/usb/typec/bus.c:1: warning: 'typec_altmode_unregister_driver' not found
   drivers/usb/typec/bus.c:1: warning: 'typec_altmode_register_driver' not found
   drivers/usb/typec/class.c:1: warning: 'typec_altmode_unregister_notifier' not found
   drivers/usb/typec/class.c:1: warning: 'typec_altmode_register_notifier' not found
>> include/linux/usb.h:1251: warning: Function parameter or member 'match' not described in 'usb_device_driver'
>> include/linux/usb.h:1251: warning: Function parameter or member 'id_table' not described in 'usb_device_driver'
   include/linux/usb.h:1251: warning: Function parameter or member 'generic_init' not described in 'usb_device_driver'
   include/linux/w1.h:277: warning: Function parameter or member 'of_match_table' not described in 'w1_family'
   fs/fs-writeback.c:913: warning: Excess function parameter 'nr_pages' description in 'cgroup_writeback_by_id'
   fs/direct-io.c:258: warning: Excess function parameter 'offset' description in 'dio_complete'
   fs/libfs.c:496: warning: Excess function parameter 'available' description in 'simple_write_end'
   fs/posix_acl.c:647: warning: Function parameter or member 'inode' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:647: warning: Function parameter or member 'mode_p' not described in 'posix_acl_update_mode'
   fs/posix_acl.c:647: warning: Function parameter or member 'acl' not described in 'posix_acl_update_mode'
   kernel/dma/coherent.c:1: warning: no structured comments found
   include/linux/input/sparse-keymap.h:43: warning: Function parameter or member 'sw' not described in 'key_entry'
   include/linux/skbuff.h:888: warning: Function parameter or member 'dev_scratch' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'list' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'ip_defrag_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'skb_mstamp_ns' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__cloned_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'head_frag' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_type_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'encapsulation' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'encap_hdr_csum' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_valid' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member '__pkt_vlan_present_offset' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'vlan_present' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_complete_sw' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'csum_level' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'inner_protocol_type' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'remcsum_offload' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'sender_cpu' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'reserved_tailroom' not described in 'sk_buff'
   include/linux/skbuff.h:888: warning: Function parameter or member 'inner_ipproto' not described in 'sk_buff'
   include/net/sock.h:233: warning: Function parameter or member 'skc_addrpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_portpair' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_ipv6only' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_net_refcnt' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_daddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_v6_rcv_saddr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_cookie' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_listener' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_dr' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_rcv_wnd' not described in 'sock_common'
   include/net/sock.h:233: warning: Function parameter or member 'skc_tw_rcv_nxt' not described in 'sock_common'
   include/net/sock.h:515: warning: Function parameter or member 'sk_rx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_wq_raw' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'tcp_rtx_queue' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_tx_skb_cache' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_route_forced_caps' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_txtime_report_errors' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_validate_xmit_skb' not described in 'sock'
   include/net/sock.h:515: warning: Function parameter or member 'sk_bpf_storage' not described in 'sock'
   include/net/sock.h:2439: warning: Function parameter or member 'tcp_rx_skb_cache_key' not described in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'sk' description in 'DECLARE_STATIC_KEY_FALSE'
   include/net/sock.h:2439: warning: Excess function parameter 'skb' description in 'DECLARE_STATIC_KEY_FALSE'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'gso_partial_features' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'l3mdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xfrmdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'tlsdev_ops' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'name_assign_type' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'ieee802154_ptr' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'mpls_ptr' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xdp_prog' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'gro_flush_timeout' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member '____cacheline_aligned_in_smp' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'qdisc_hash' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_cpus_map' not described in 'net_device'
   include/linux/netdevice.h:2053: warning: Function parameter or member 'xps_rxqs_map' not described in 'net_device'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising' not described in 'phylink_link_state'
   include/linux/phylink.h:56: warning: Function parameter or member '__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising' not described in 'phylink_link_state'
   drivers/net/phy/phylink.c:595: warning: Function parameter or member 'config' not described in 'phylink_create'
   drivers/net/phy/phylink.c:595: warning: Excess function parameter 'ndev' description in 'phylink_create'
   include/linux/bitmap.h:341: warning: Function parameter or member 'nbits' not described in 'bitmap_or_equal'
   include/linux/rculist.h:374: warning: Excess function parameter 'cond' description in 'list_for_each_entry_rcu'
   include/linux/rculist.h:651: warning: Excess function parameter 'cond' description in 'hlist_for_each_entry_rcu'
   mm/util.c:1: warning: 'get_user_pages_fast' not found
   mm/slab.c:4215: warning: Function parameter or member 'objp' not described in '__ksize'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:335: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:336: warning: Excess function parameter 'dev' description in 'amdgpu_gem_prime_export'
   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c:142: warning: Function parameter or member 'blockable' not described in 'amdgpu_mn_read_lock'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:347: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:348: warning: cannot understand function prototype: 'struct amdgpu_vm_pt_cursor '
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:494: warning: Function parameter or member 'start' not described in 'amdgpu_vm_pt_first_dfs'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'adev' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'vm' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'start' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'cursor' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:546: warning: Function parameter or member 'entry' not described in 'for_each_amdgpu_vm_pt_dfs_safe'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:823: warning: Function parameter or member 'level' not described in 'amdgpu_vm_bo_param'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'params' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'bo' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'level' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'pe' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'addr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'count' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'incr' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1285: warning: Function parameter or member 'flags' not described in 'amdgpu_vm_update_flags'
   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:2823: warning: Function parameter or member 'pasid' not described in 'amdgpu_vm_make_compute'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:378: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Function parameter or member 'ih' not described in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:379: warning: Excess function parameter 'entry' description in 'amdgpu_irq_dispatch'
   drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c:1: warning: no structured comments found
   drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1: warning: no structured comments found

vim +1251 include/linux/usb.h

8bb54ab573ecd1 Alan Stern         2006-07-01  1214  
8bb54ab573ecd1 Alan Stern         2006-07-01  1215  /**
8bb54ab573ecd1 Alan Stern         2006-07-01  1216   * struct usb_device_driver - identifies USB device driver to usbcore
8bb54ab573ecd1 Alan Stern         2006-07-01  1217   * @name: The driver name should be unique among USB drivers,
8bb54ab573ecd1 Alan Stern         2006-07-01  1218   *	and should normally be the same as the module name.
8bb54ab573ecd1 Alan Stern         2006-07-01  1219   * @probe: Called to see if the driver is willing to manage a particular
8bb54ab573ecd1 Alan Stern         2006-07-01  1220   *	device.  If it is, probe returns zero and uses dev_set_drvdata()
8bb54ab573ecd1 Alan Stern         2006-07-01  1221   *	to associate driver-specific data with the device.  If unwilling
8bb54ab573ecd1 Alan Stern         2006-07-01  1222   *	to manage the device, return a negative errno value.
8bb54ab573ecd1 Alan Stern         2006-07-01  1223   * @disconnect: Called when the device is no longer accessible, usually
8bb54ab573ecd1 Alan Stern         2006-07-01  1224   *	because it has been (or is being) disconnected or the driver's
8bb54ab573ecd1 Alan Stern         2006-07-01  1225   *	module is being unloaded.
8bb54ab573ecd1 Alan Stern         2006-07-01  1226   * @suspend: Called when the device is going to be suspended by the system.
8bb54ab573ecd1 Alan Stern         2006-07-01  1227   * @resume: Called when the device is being resumed by the system.
7d9c1d2f7aca26 Greg Kroah-Hartman 2019-08-06  1228   * @dev_groups: Attributes attached to the device that will be created once it
7d9c1d2f7aca26 Greg Kroah-Hartman 2019-08-06  1229   *	is bound to the driver.
8bb54ab573ecd1 Alan Stern         2006-07-01  1230   * @drvwrap: Driver-model core structure wrapper.
645daaab0b6adc Alan Stern         2006-08-30  1231   * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
645daaab0b6adc Alan Stern         2006-08-30  1232   *	for devices bound to this driver.
8bb54ab573ecd1 Alan Stern         2006-07-01  1233   *
8bb54ab573ecd1 Alan Stern         2006-07-01  1234   * USB drivers must provide all the fields listed above except drvwrap.
8bb54ab573ecd1 Alan Stern         2006-07-01  1235   */
8bb54ab573ecd1 Alan Stern         2006-07-01  1236  struct usb_device_driver {
8bb54ab573ecd1 Alan Stern         2006-07-01  1237  	const char *name;
8bb54ab573ecd1 Alan Stern         2006-07-01  1238  
47ff64ea1ecb52 Bastien Nocera     2019-10-09  1239  	bool (*match) (struct usb_device *udev);
8bb54ab573ecd1 Alan Stern         2006-07-01  1240  	int (*probe) (struct usb_device *udev);
8bb54ab573ecd1 Alan Stern         2006-07-01  1241  	void (*disconnect) (struct usb_device *udev);
8bb54ab573ecd1 Alan Stern         2006-07-01  1242  
8bb54ab573ecd1 Alan Stern         2006-07-01  1243  	int (*suspend) (struct usb_device *udev, pm_message_t message);
65bfd2967c906c Alan Stern         2008-11-25  1244  	int (*resume) (struct usb_device *udev, pm_message_t message);
7d9c1d2f7aca26 Greg Kroah-Hartman 2019-08-06  1245  	const struct attribute_group **dev_groups;
8bb54ab573ecd1 Alan Stern         2006-07-01  1246  	struct usbdrv_wrap drvwrap;
47ff64ea1ecb52 Bastien Nocera     2019-10-09  1247  	const struct usb_device_id *id_table;
645daaab0b6adc Alan Stern         2006-08-30  1248  	unsigned int supports_autosuspend:1;
e4877e9d91a42a Bastien Nocera     2019-10-09  1249  	unsigned int generic_init:1;
8bb54ab573ecd1 Alan Stern         2006-07-01  1250  };
8bb54ab573ecd1 Alan Stern         2006-07-01 @1251  #define	to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
8bb54ab573ecd1 Alan Stern         2006-07-01  1252  		drvwrap.driver)
^1da177e4c3f41 Linus Torvalds     2005-04-16  1253  

:::::: The code at line 1251 was first introduced by commit
:::::: 8bb54ab573ecd1b4fe2ed66416a8d99a86e65316 usbcore: add usb_device_driver definition

:::::: TO: Alan Stern <stern@rowland.harvard.edu>
:::::: CC: Greg Kroah-Hartman <gregkh@suse.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7278 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/5] USB: Select better matching USB drivers when available
  2019-10-10  8:26             ` Bastien Nocera
@ 2019-10-10 14:19               ` Alan Stern
  0 siblings, 0 replies; 21+ messages in thread
From: Alan Stern @ 2019-10-10 14:19 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-usb, Greg Kroah-Hartman, Benjamin Tissoires

On Thu, 10 Oct 2019, Bastien Nocera wrote:

> On Wed, 2019-10-09 at 14:45 -0400, Alan Stern wrote:
> > 
> On Wed, 9 Oct 2019, Bastien Nocera wrote:
> > 
> > <snip>
> > > +               return
> > device_driver_attach(usb_generic_driver.drvwrap.driver, dev);
> > > +       return error;
> > 
> > I think that's right.  A little testing wouldn't hurt.
> 
> device_driver_attach() isn't available to this part of the code.
> 
> I think the only way to do things here might be to set status bit for
> the usb_device and launch device_reprobe(). The second time around, we
> wouldn't match or probe the specific driver.

That would mean probing generic_driver twice, right?  You probably
should call its disconnect routine in between.

That sounds pretty awkward, but if there's no other way then go ahead 
and do it.

Ala Stern


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, back to index

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-09 13:43 [PATCH 0/5] Add Apple MFi fastcharge USB device driver Bastien Nocera
2019-10-09 13:43 ` [PATCH 1/5] USB: Export generic USB device driver functions Bastien Nocera
2019-10-09 13:43 ` [PATCH 2/5] USB: Make it possible to "subclass" usb_device_driver Bastien Nocera
2019-10-09 14:34   ` Alan Stern
2019-10-09 14:41     ` Alan Stern
2019-10-10  8:10     ` Bastien Nocera
2019-10-10  9:58   ` kbuild test robot
2019-10-09 13:43 ` [PATCH 3/5] USB: Implement usb_device_match_id() Bastien Nocera
2019-10-09 14:36   ` Alan Stern
2019-10-09 15:40     ` Bastien Nocera
2019-10-09 17:29       ` Alan Stern
2019-10-09 13:43 ` [PATCH 4/5] USB: Select better matching USB drivers when available Bastien Nocera
2019-10-09 14:43   ` Alan Stern
2019-10-09 15:35     ` Bastien Nocera
2019-10-09 17:28       ` Alan Stern
2019-10-09 18:24         ` Bastien Nocera
2019-10-09 18:45           ` Alan Stern
2019-10-10  8:26             ` Bastien Nocera
2019-10-10 14:19               ` Alan Stern
2019-10-10 10:33   ` kbuild test robot
2019-10-09 13:43 ` [PATCH 5/5] USB: Add driver to control USB fast charge for iOS devices Bastien Nocera

Linux-USB Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-usb/0 linux-usb/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-usb linux-usb/ https://lore.kernel.org/linux-usb \
		linux-usb@vger.kernel.org linux-usb@archiver.kernel.org
	public-inbox-index linux-usb

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-usb


AGPL code for this site: git clone https://public-inbox.org/ public-inbox