From ddd5d35a8f7c1924049e8b6877b3177c1787e6a3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 10 Aug 2006 01:18:18 -0400 Subject: class_device_create(): make fmt argument 'const char *' Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 1e5f30da98b..1fec2854652 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -277,7 +277,7 @@ extern struct class_device *class_device_create(struct class *cls, struct class_device *parent, dev_t devt, struct device *device, - char *fmt, ...) + const char *fmt, ...) __attribute__((format(printf,5,6))); extern void class_device_destroy(struct class *cls, dev_t devt); -- cgit v1.2.3 From 5cbe5f8a5897470698222ac9924429056e57d84c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 10 Aug 2006 01:19:19 -0400 Subject: device_create(): make fmt argument 'const char *' Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 1fec2854652..8d92013f9ce 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -384,7 +384,7 @@ extern void device_reprobe(struct device *dev); * Easy functions for dynamically creating devices on the fly */ extern struct device *device_create(struct class *cls, struct device *parent, - dev_t devt, char *fmt, ...) + dev_t devt, const char *fmt, ...) __attribute__((format(printf,4,5))); extern void device_destroy(struct class *cls, dev_t devt); -- cgit v1.2.3 From ab7d7371acc68fa9130b079a9ba879191202035f Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Sandonis Date: Wed, 13 Sep 2006 15:34:05 +0200 Subject: Driver core: add const to class_create Adds const to class_create second parameter, because: struct class { const char * name; /*...*/ } Signed-off-by: Miguel Ojeda Sandonis Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 8d92013f9ce..8a648cd94fa 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -271,7 +271,7 @@ struct class_interface { extern int class_interface_register(struct class_interface *); extern void class_interface_unregister(struct class_interface *); -extern struct class *class_create(struct module *owner, char *name); +extern struct class *class_create(struct module *owner, const char *name); extern void class_destroy(struct class *cls); extern struct class_device *class_device_create(struct class *cls, struct class_device *parent, -- cgit v1.2.3 From 7c8265f51073bc8632a99de78d5fd19117ed78b7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 24 Jun 2006 14:50:29 -0700 Subject: Suspend infrastructure cleanup and extension Allow devices to participate in the suspend process more intimately, in particular, allow the final phase (with interrupts disabled) to also be open to normal devices, not just system devices. Also, allow classes to participate in device suspend. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 11 +++++++++-- include/linux/pm.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 8a648cd94fa..b40be6fca6f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -51,8 +51,12 @@ struct bus_type { int (*probe)(struct device * dev); int (*remove)(struct device * dev); void (*shutdown)(struct device * dev); - int (*suspend)(struct device * dev, pm_message_t state); - int (*resume)(struct device * dev); + + int (*suspend_prepare)(struct device * dev, pm_message_t state); + int (*suspend)(struct device * dev, pm_message_t state); + int (*suspend_late)(struct device * dev, pm_message_t state); + int (*resume_early)(struct device * dev); + int (*resume)(struct device * dev); }; extern int bus_register(struct bus_type * bus); @@ -154,6 +158,9 @@ struct class { void (*release)(struct class_device *dev); void (*class_release)(struct class *class); + + int (*suspend)(struct device *, pm_message_t state); + int (*resume)(struct device *); }; extern int class_register(struct class *); diff --git a/include/linux/pm.h b/include/linux/pm.h index 658c1b93d5b..096fb6f754c 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -190,6 +190,7 @@ extern void device_resume(void); extern suspend_disk_method_t pm_disk_mode; extern int device_suspend(pm_message_t state); +extern int device_prepare_suspend(pm_message_t state); #define device_set_wakeup_enable(dev,val) \ ((dev)->power.should_wakeup = !!(val)) -- cgit v1.2.3 From cbd69dbbf1adfce6e048f15afc8629901ca9dae5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 24 Jun 2006 14:50:29 -0700 Subject: Suspend changes for PCI core Changes the PCI core to use the new suspend infrastructure changes. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/pci.h b/include/linux/pci.h index 8565b81d7fb..4b2e629467c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -345,7 +345,10 @@ struct pci_driver { const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ + int (*suspend_prepare) (struct pci_dev *dev, pm_message_t state); int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */ + int (*suspend_late) (struct pci_dev *dev, pm_message_t state); + int (*resume_early) (struct pci_dev *dev); int (*resume) (struct pci_dev *dev); /* Device woken up */ int (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable); /* Enable wake event */ void (*shutdown) (struct pci_dev *dev); -- cgit v1.2.3 From 82bb67f2c1f9ef438c56ac24e7dca027fe7289b5 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 14 Aug 2006 23:11:04 -0700 Subject: PM: define PM_EVENT_PRETHAW This adds a new pm_message_t event type to use when preparing to restore a swsusp snapshot. Devices that have been initialized by Linux after resume (rather than left in power-up-reset state) may need to be reset; this new event type give drivers the chance to do that. The drivers that will care about this are those which understand more hardware states than just "on" and "reset", relying on hardware state during resume() methods to be either the state left by the preceding suspend(), or a power-lost reset. The best current example of this class of drivers are USB host controller drivers, which currently do not work through swsusp when they're statically linked. When the swsusp freeze/thaw mechanism kicks in, a troublesome third state could exist: one state set up by a different kernel instance, before a snapshot image is resumed. This mechanism lets drivers prevent that state. Signed-off-by: David Brownell Cc: "Rafael J. Wysocki" Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pm.h | 62 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/linux/pm.h b/include/linux/pm.h index 096fb6f754c..6b27e07aef1 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -142,29 +142,61 @@ typedef struct pm_message { } pm_message_t; /* - * There are 4 important states driver can be in: - * ON -- driver is working - * FREEZE -- stop operations and apply whatever policy is applicable to a - * suspended driver of that class, freeze queues for block like IDE - * does, drop packets for ethernet, etc... stop DMA engine too etc... - * so a consistent image can be saved; but do not power any hardware - * down. - * SUSPEND - like FREEZE, but hardware is doing as much powersaving as - * possible. Roughly pci D3. + * Several driver power state transitions are externally visible, affecting + * the state of pending I/O queues and (for drivers that touch hardware) + * interrupts, wakeups, DMA, and other hardware state. There may also be + * internal transitions to various low power modes, which are transparent + * to the rest of the driver stack (such as a driver that's ON gating off + * clocks which are not in active use). * - * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 - * (SUSPEND). We'll need to fix the drivers. So yes, putting 3 to all different - * defines is intentional, and will go away as soon as drivers are fixed. Also - * note that typedef is neccessary, we'll probably want to switch to - * typedef struct pm_message_t { int event; int flags; } pm_message_t - * or something similar soon. + * One transition is triggered by resume(), after a suspend() call; the + * message is implicit: + * + * ON Driver starts working again, responding to hardware events + * and software requests. The hardware may have gone through + * a power-off reset, or it may have maintained state from the + * previous suspend() which the driver will rely on while + * resuming. On most platforms, there are no restrictions on + * availability of resources like clocks during resume(). + * + * Other transitions are triggered by messages sent using suspend(). All + * these transitions quiesce the driver, so that I/O queues are inactive. + * That commonly entails turning off IRQs and DMA; there may be rules + * about how to quiesce that are specific to the bus or the device's type. + * (For example, network drivers mark the link state.) Other details may + * differ according to the message: + * + * SUSPEND Quiesce, enter a low power device state appropriate for + * the upcoming system state (such as PCI_D3hot), and enable + * wakeup events as appropriate. + * + * FREEZE Quiesce operations so that a consistent image can be saved; + * but do NOT otherwise enter a low power device state, and do + * NOT emit system wakeup events. + * + * PRETHAW Quiesce as if for FREEZE; additionally, prepare for restoring + * the system from a snapshot taken after an earlier FREEZE. + * Some drivers will need to reset their hardware state instead + * of preserving it, to ensure that it's never mistaken for the + * state which that earlier snapshot had set up. + * + * A minimally power-aware driver treats all messages as SUSPEND, fully + * reinitializes its device during resume() -- whether or not it was reset + * during the suspend/resume cycle -- and can't issue wakeup events. + * + * More power-aware drivers may also use low power states at runtime as + * well as during system sleep states like PM_SUSPEND_STANDBY. They may + * be able to use wakeup events to exit from runtime low-power states, + * or from system low-power states such as standby or suspend-to-RAM. */ #define PM_EVENT_ON 0 #define PM_EVENT_FREEZE 1 #define PM_EVENT_SUSPEND 2 +#define PM_EVENT_PRETHAW 3 #define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, }) +#define PMSG_PRETHAW ((struct pm_message){ .event = PM_EVENT_PRETHAW, }) #define PMSG_SUSPEND ((struct pm_message){ .event = PM_EVENT_SUSPEND, }) #define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, }) -- cgit v1.2.3 From 1d3a82af45428c5e8deaa119cdeb79611ae46371 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 30 Aug 2006 14:09:47 -0700 Subject: PM: no suspend_prepare() phase Remove the new suspend_prepare() phase. It doesn't seem very usable, has never been tested, doesn't address fault cleanup, and would need a sibling resume_complete(); plus there are no real use cases. It could be restored later if those issues get resolved. Signed-off-by: David Brownell Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 1 - include/linux/pci.h | 1 - 2 files changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index b40be6fca6f..b3646462d6d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -52,7 +52,6 @@ struct bus_type { int (*remove)(struct device * dev); void (*shutdown)(struct device * dev); - int (*suspend_prepare)(struct device * dev, pm_message_t state); int (*suspend)(struct device * dev, pm_message_t state); int (*suspend_late)(struct device * dev, pm_message_t state); int (*resume_early)(struct device * dev); diff --git a/include/linux/pci.h b/include/linux/pci.h index 4b2e629467c..9514bbfe96e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -345,7 +345,6 @@ struct pci_driver { const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ - int (*suspend_prepare) (struct pci_dev *dev, pm_message_t state); int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */ int (*suspend_late) (struct pci_dev *dev, pm_message_t state); int (*resume_early) (struct pci_dev *dev); -- cgit v1.2.3 From 386415d88b1ae50304f9c61aa3e0db082fa90428 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 3 Sep 2006 13:16:45 -0700 Subject: PM: platform_bus and late_suspend/early_resume Teach platform_bus about the new suspend_late/resume_early PM calls, issued with IRQs off. Do we really need sysdev and friends any more, or can janitors start switching its users over to platform_device so we can do a minor code-ectomy? Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- include/linux/platform_device.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 782090c6893..29cd6dee13d 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -49,6 +49,8 @@ struct platform_driver { int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); + int (*suspend_late)(struct platform_device *, pm_message_t state); + int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); struct device_driver driver; }; -- cgit v1.2.3 From de0ff00d723fd821d372496e2c084805644aa5e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 Jun 2006 00:06:09 -0700 Subject: Driver core: add groups support to struct device This is needed for the network class devices in order to be able to convert over to use struct device. Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index b3646462d6d..994d3ebd53f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -344,6 +344,7 @@ struct device { struct list_head node; struct class *class; /* optional*/ dev_t devt; /* dev_t, creates the sysfs "dev" */ + struct attribute_group **groups; /* optional groups */ void (*release)(struct device * dev); }; -- cgit v1.2.3 From 2620efef7029bb040430f50f0fc148f2d5e002ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 Jun 2006 16:19:58 -0700 Subject: Driver core: add ability for classes to handle devices properly This adds two new callbacks to the class structure: int (*dev_uevent)(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); void (*dev_release)(struct device *dev); And one pointer: struct device_attribute * dev_attrs; which all corrispond with the same thing as the "normal" class devices do, yet this is for when a struct device is bound to a class. Someday soon, struct class_device will go away, and then the other fields in this structure can be removed too. But this is necessary in order to get the transition to work properly. Tested out on a network core patch that converted it to use struct device instead of struct class_device. Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 994d3ebd53f..3122bd25ce4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -151,12 +151,16 @@ struct class { struct class_attribute * class_attrs; struct class_device_attribute * class_dev_attrs; + struct device_attribute * dev_attrs; int (*uevent)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size); + int (*dev_uevent)(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size); void (*release)(struct class_device *dev); void (*class_release)(struct class *class); + void (*dev_release)(struct device *dev); int (*suspend)(struct device *, pm_message_t state); int (*resume)(struct device *); -- cgit v1.2.3 From a2de48cace5d0993da6cfa28b276ae724dc3569b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 3 Jul 2006 14:31:12 -0700 Subject: Driver core: add device_rename function The network layer needs this to convert to using struct device instead of a struct class_device. Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 3122bd25ce4..3400e09bf45 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -380,6 +380,7 @@ extern int device_add(struct device * dev); extern void device_del(struct device * dev); extern int device_for_each_child(struct device *, void *, int (*fn)(struct device *, void *)); +extern int device_rename(struct device *dev, char *new_name); /* * Manual binding of a device to driver. See drivers/base/bus.c -- cgit v1.2.3 From c205ef4880273d2de4ee5388d4e52227ff688cc4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: create devices/virtual/ tree This change creates a devices/virtual/CLASS_NAME tree for struct devices that belong to a class, yet do not have a "real" struct device for a parent. It automatically creates the directories on the fly as needed. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 3400e09bf45..bbb0d6b5d23 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -149,6 +149,8 @@ struct class { struct list_head interfaces; struct semaphore sem; /* locks both the children and interfaces lists */ + struct kobject *virtual_dir; + struct class_attribute * class_attrs; struct class_device_attribute * class_dev_attrs; struct device_attribute * dev_attrs; @@ -291,7 +293,6 @@ extern struct class_device *class_device_create(struct class *cls, __attribute__((format(printf,5,6))); extern void class_device_destroy(struct class *cls, dev_t devt); - /* interface for exporting device attributes */ struct device_attribute { struct attribute attr; @@ -400,6 +401,8 @@ extern struct device *device_create(struct class *cls, struct device *parent, __attribute__((format(printf,4,5))); extern void device_destroy(struct class *cls, dev_t devt); +extern int virtual_device_parent(struct device *dev); + /* * Platform "fixup" functions - allow the platform to have their say * about devices and actions that the general device layer doesn't -- cgit v1.2.3 From c47ed219ba81632595e9f02e27318151fec16c9e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 13 Sep 2006 15:34:05 +0200 Subject: Class: add support for class interfaces for devices When moving class_device usage over to device, we need to handle class_interfaces properly with devices. This patch adds that support. Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index bbb0d6b5d23..e0fae0e76fa 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -278,6 +278,8 @@ struct class_interface { int (*add) (struct class_device *, struct class_interface *); void (*remove) (struct class_device *, struct class_interface *); + int (*add_dev) (struct device *, struct class_interface *); + void (*remove_dev) (struct device *, struct class_interface *); }; extern int class_interface_register(struct class_interface *); -- cgit v1.2.3 From 2589f1887b0bf9f08ec3d7f3c5705ccb7c628076 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Sep 2006 09:39:19 -0700 Subject: Driver core: add ability for devices to create and remove bin files Makes it easier for devices to create and remove binary attribute files so they don't have to call directly into sysfs. This is needed to help with the conversion from struct class_device to struct device. Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index e0fae0e76fa..7d447d7271c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -309,6 +309,10 @@ struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store) extern int device_create_file(struct device *device, struct device_attribute * entry); extern void device_remove_file(struct device * dev, struct device_attribute * attr); +extern int __must_check device_create_bin_file(struct device *dev, + struct bin_attribute *attr); +extern void device_remove_bin_file(struct device *dev, + struct bin_attribute *attr); struct device { struct klist klist_children; struct klist_node knode_parent; /* node in sibling list */ -- cgit v1.2.3 From 995982ca79d9262869513948ec7c540f32035491 Mon Sep 17 00:00:00 2001 From: "Randy.Dunlap" Date: Mon, 10 Jul 2006 23:05:25 -0700 Subject: sysfs_remove_bin_file: no return value, dump_stack on error Make sysfs_remove_bin_file() void. If it detects an error, printk the file name and call dump_stack(). sysfs_hash_and_remove() now returns an error code indicating its success or failure so that sysfs_remove_bin_file() can know success/failure. Convert the only driver that checked the return value of sysfs_remove_bin_file(). Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 1ea5d3cda6a..95f6db54d8d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -114,7 +114,7 @@ extern void sysfs_remove_link(struct kobject *, const char * name); int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); -int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); +void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); int sysfs_create_group(struct kobject *, const struct attribute_group *); void sysfs_remove_group(struct kobject *, const struct attribute_group *); -- cgit v1.2.3 From 4a7fb6363f2d1a6c09a10253937f672f3c7929e1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 14 Aug 2006 22:43:17 -0700 Subject: add __must_check to device management code We're getting a lot of crashes in the sysfs/kobject/device/bus/class code and they're very hard to diagnose. I'm suspecting that in some cases this is because drivers aren't checking return values and aren't handling errors correctly. So the code blithely blunders on and crashes later in very obscure ways. There's just no reason to ignore errors which can and do occur. So the patch sprinkles __must_check all over these APIs. Causes 1,513 new warnings. Heh. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 52 ++++++++++++++++++++++++++----------------------- include/linux/kobject.h | 16 ++++++++------- include/linux/pci.h | 34 +++++++++++++++++--------------- include/linux/sysfs.h | 19 ++++++++++-------- 4 files changed, 66 insertions(+), 55 deletions(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 7d447d7271c..ad4db72f573 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -58,7 +59,7 @@ struct bus_type { int (*resume)(struct device * dev); }; -extern int bus_register(struct bus_type * bus); +extern int __must_check bus_register(struct bus_type * bus); extern void bus_unregister(struct bus_type * bus); extern void bus_rescan_devices(struct bus_type * bus); @@ -70,9 +71,9 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, struct device * bus_find_device(struct bus_type *bus, struct device *start, void *data, int (*match)(struct device *, void *)); -int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, - void * data, int (*fn)(struct device_driver *, void *)); - +int __must_check bus_for_each_drv(struct bus_type *bus, + struct device_driver *start, void *data, + int (*fn)(struct device_driver *, void *)); /* driverfs interface for exporting bus attributes */ @@ -85,7 +86,8 @@ struct bus_attribute { #define BUS_ATTR(_name,_mode,_show,_store) \ struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) -extern int bus_create_file(struct bus_type *, struct bus_attribute *); +extern int __must_check bus_create_file(struct bus_type *, + struct bus_attribute *); extern void bus_remove_file(struct bus_type *, struct bus_attribute *); struct device_driver { @@ -107,14 +109,13 @@ struct device_driver { }; -extern int driver_register(struct device_driver * drv); +extern int __must_check driver_register(struct device_driver * drv); extern void driver_unregister(struct device_driver * drv); extern struct device_driver * get_driver(struct device_driver * drv); extern void put_driver(struct device_driver * drv); extern struct device_driver *driver_find(const char *name, struct bus_type *bus); - /* driverfs interface for exporting driver attributes */ struct driver_attribute { @@ -126,16 +127,17 @@ struct driver_attribute { #define DRIVER_ATTR(_name,_mode,_show,_store) \ struct driver_attribute driver_attr_##_name = __ATTR(_name,_mode,_show,_store) -extern int driver_create_file(struct device_driver *, struct driver_attribute *); +extern int __must_check driver_create_file(struct device_driver *, + struct driver_attribute *); extern void driver_remove_file(struct device_driver *, struct driver_attribute *); -extern int driver_for_each_device(struct device_driver * drv, struct device * start, - void * data, int (*fn)(struct device *, void *)); +extern int __must_check driver_for_each_device(struct device_driver * drv, + struct device *start, void *data, + int (*fn)(struct device *, void *)); struct device * driver_find_device(struct device_driver *drv, struct device *start, void *data, int (*match)(struct device *, void *)); - /* * device classes */ @@ -168,7 +170,7 @@ struct class { int (*resume)(struct device *); }; -extern int class_register(struct class *); +extern int __must_check class_register(struct class *); extern void class_unregister(struct class *); @@ -181,7 +183,8 @@ struct class_attribute { #define CLASS_ATTR(_name,_mode,_show,_store) \ struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store) -extern int class_create_file(struct class *, const struct class_attribute *); +extern int __must_check class_create_file(struct class *, + const struct class_attribute *); extern void class_remove_file(struct class *, const struct class_attribute *); struct class_device_attribute { @@ -194,7 +197,7 @@ struct class_device_attribute { struct class_device_attribute class_device_attr_##_name = \ __ATTR(_name,_mode,_show,_store) -extern int class_device_create_file(struct class_device *, +extern int __must_check class_device_create_file(struct class_device *, const struct class_device_attribute *); /** @@ -254,10 +257,10 @@ class_set_devdata (struct class_device *dev, void *data) } -extern int class_device_register(struct class_device *); +extern int __must_check class_device_register(struct class_device *); extern void class_device_unregister(struct class_device *); extern void class_device_initialize(struct class_device *); -extern int class_device_add(struct class_device *); +extern int __must_check class_device_add(struct class_device *); extern void class_device_del(struct class_device *); extern int class_device_rename(struct class_device *, char *); @@ -267,7 +270,7 @@ extern void class_device_put(struct class_device *); extern void class_device_remove_file(struct class_device *, const struct class_device_attribute *); -extern int class_device_create_bin_file(struct class_device *, +extern int __must_check class_device_create_bin_file(struct class_device *, struct bin_attribute *); extern void class_device_remove_bin_file(struct class_device *, struct bin_attribute *); @@ -282,7 +285,7 @@ struct class_interface { void (*remove_dev) (struct device *, struct class_interface *); }; -extern int class_interface_register(struct class_interface *); +extern int __must_check class_interface_register(struct class_interface *); extern void class_interface_unregister(struct class_interface *); extern struct class *class_create(struct module *owner, const char *name); @@ -307,7 +310,8 @@ struct device_attribute { #define DEVICE_ATTR(_name,_mode,_show,_store) \ struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store) -extern int device_create_file(struct device *device, struct device_attribute * entry); +extern int __must_check device_create_file(struct device *device, + struct device_attribute * entry); extern void device_remove_file(struct device * dev, struct device_attribute * attr); extern int __must_check device_create_bin_file(struct device *dev, struct bin_attribute *attr); @@ -380,12 +384,12 @@ static inline int device_is_registered(struct device *dev) /* * High level routines for use by the bus drivers */ -extern int device_register(struct device * dev); +extern int __must_check device_register(struct device * dev); extern void device_unregister(struct device * dev); extern void device_initialize(struct device * dev); -extern int device_add(struct device * dev); +extern int __must_check device_add(struct device * dev); extern void device_del(struct device * dev); -extern int device_for_each_child(struct device *, void *, +extern int __must_check device_for_each_child(struct device *, void *, int (*fn)(struct device *, void *)); extern int device_rename(struct device *dev, char *new_name); @@ -395,7 +399,7 @@ extern int device_rename(struct device *dev, char *new_name); */ extern void device_bind_driver(struct device * dev); extern void device_release_driver(struct device * dev); -extern int device_attach(struct device * dev); +extern int __must_check device_attach(struct device * dev); extern void driver_attach(struct device_driver * drv); extern void device_reprobe(struct device *dev); @@ -433,7 +437,7 @@ extern void device_shutdown(void); /* drivers/base/firmware.c */ -extern int firmware_register(struct subsystem *); +extern int __must_check firmware_register(struct subsystem *); extern void firmware_unregister(struct subsystem *); /* debugging and troubleshooting/diagnostic helpers. */ diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 2d229327959..bcd9cd173c2 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -71,12 +72,12 @@ static inline const char * kobject_name(const struct kobject * kobj) extern void kobject_init(struct kobject *); extern void kobject_cleanup(struct kobject *); -extern int kobject_add(struct kobject *); +extern int __must_check kobject_add(struct kobject *); extern void kobject_del(struct kobject *); -extern int kobject_rename(struct kobject *, const char *new_name); +extern int __must_check kobject_rename(struct kobject *, const char *new_name); -extern int kobject_register(struct kobject *); +extern int __must_check kobject_register(struct kobject *); extern void kobject_unregister(struct kobject *); extern struct kobject * kobject_get(struct kobject *); @@ -128,8 +129,8 @@ struct kset { extern void kset_init(struct kset * k); -extern int kset_add(struct kset * k); -extern int kset_register(struct kset * k); +extern int __must_check kset_add(struct kset * k); +extern int __must_check kset_register(struct kset * k); extern void kset_unregister(struct kset * k); static inline struct kset * to_kset(struct kobject * kobj) @@ -239,7 +240,7 @@ extern struct subsystem hypervisor_subsys; (obj)->subsys.kset.kobj.kset = &(_subsys).kset extern void subsystem_init(struct subsystem *); -extern int subsystem_register(struct subsystem *); +extern int __must_check subsystem_register(struct subsystem *); extern void subsystem_unregister(struct subsystem *); static inline struct subsystem * subsys_get(struct subsystem * s) @@ -258,7 +259,8 @@ struct subsys_attribute { ssize_t (*store)(struct subsystem *, const char *, size_t); }; -extern int subsys_create_file(struct subsystem * , struct subsys_attribute *); +extern int __must_check subsys_create_file(struct subsystem * , + struct subsys_attribute *); #if defined(CONFIG_HOTPLUG) void kobject_uevent(struct kobject *kobj, enum kobject_action action); diff --git a/include/linux/pci.h b/include/linux/pci.h index 9514bbfe96e..3ec72551ac3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -403,7 +404,7 @@ extern struct list_head pci_root_buses; /* list of all known PCI buses */ extern struct list_head pci_devices; /* list of all devices */ void pcibios_fixup_bus(struct pci_bus *); -int pcibios_enable_device(struct pci_dev *, int mask); +int __must_check pcibios_enable_device(struct pci_dev *, int mask); char *pcibios_setup (char *str); /* Used only when drivers/pci/setup.c is used */ @@ -490,19 +491,19 @@ static inline int pci_write_config_dword(struct pci_dev *dev, int where, u32 val return pci_bus_write_config_dword (dev->bus, dev->devfn, where, val); } -int pci_enable_device(struct pci_dev *dev); -int pci_enable_device_bars(struct pci_dev *dev, int mask); +int __must_check pci_enable_device(struct pci_dev *dev); +int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask); void pci_disable_device(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev); #define HAVE_PCI_SET_MWI -int pci_set_mwi(struct pci_dev *dev); +int __must_check pci_set_mwi(struct pci_dev *dev); void pci_clear_mwi(struct pci_dev *dev); void pci_intx(struct pci_dev *dev, int enable); int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); -int pci_assign_resource(struct pci_dev *dev, int i); -int pci_assign_resource_fixed(struct pci_dev *dev, int i); +int __must_check pci_assign_resource(struct pci_dev *dev, int i); +int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); void pci_restore_bars(struct pci_dev *dev); /* ROM control related routines */ @@ -528,23 +529,24 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); #define HAVE_PCI_REQ_REGIONS 2 -int pci_request_regions(struct pci_dev *, const char *); +int __must_check pci_request_regions(struct pci_dev *, const char *); void pci_release_regions(struct pci_dev *); -int pci_request_region(struct pci_dev *, int, const char *); +int __must_check pci_request_region(struct pci_dev *, int, const char *); void pci_release_region(struct pci_dev *, int); /* drivers/pci/bus.c */ -int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, - resource_size_t size, resource_size_t align, - resource_size_t min, unsigned int type_mask, - void (*alignf)(void *, struct resource *, - resource_size_t, resource_size_t), - void *alignf_data); +int __must_check pci_bus_alloc_resource(struct pci_bus *bus, + struct resource *res, resource_size_t size, + resource_size_t align, resource_size_t min, + unsigned int type_mask, + void (*alignf)(void *, struct resource *, + resource_size_t, resource_size_t), + void *alignf_data); void pci_enable_bridges(struct pci_bus *bus); /* Proper probing supporting hot-pluggable devices */ -int __pci_register_driver(struct pci_driver *, struct module *); -static inline int pci_register_driver(struct pci_driver *driver) +int __must_check __pci_register_driver(struct pci_driver *, struct module *); +static inline int __must_check pci_register_driver(struct pci_driver *driver) { return __pci_register_driver(driver, THIS_MODULE); } diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 95f6db54d8d..02ad790921f 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -10,6 +10,7 @@ #ifndef _SYSFS_H_ #define _SYSFS_H_ +#include #include struct kobject; @@ -86,37 +87,39 @@ struct sysfs_dirent { #ifdef CONFIG_SYSFS -extern int +extern int __must_check sysfs_create_dir(struct kobject *); extern void sysfs_remove_dir(struct kobject *); -extern int +extern int __must_check sysfs_rename_dir(struct kobject *, const char *new_name); -extern int +extern int __must_check sysfs_create_file(struct kobject *, const struct attribute *); -extern int +extern int __must_check sysfs_update_file(struct kobject *, const struct attribute *); -extern int +extern int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); extern void sysfs_remove_file(struct kobject *, const struct attribute *); -extern int +extern int __must_check sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name); extern void sysfs_remove_link(struct kobject *, const char * name); -int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); +int __must_check sysfs_create_bin_file(struct kobject *kobj, + struct bin_attribute *attr); void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); -int sysfs_create_group(struct kobject *, const struct attribute_group *); +int __must_check sysfs_create_group(struct kobject *, + const struct attribute_group *); void sysfs_remove_group(struct kobject *, const struct attribute_group *); void sysfs_notify(struct kobject * k, char *dir, char *attr); -- cgit v1.2.3 From cebc04ba9aeb3a646cc746300421fc0e5aa4f253 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 14 Aug 2006 22:43:18 -0700 Subject: add CONFIG_ENABLE_MUST_CHECK Those 1500 warnings can be a bit of a pain. Add a config option to shut them up. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/compiler.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 9b4f1109493..060b96112ec 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -99,6 +99,11 @@ extern void __chk_io_ptr(void __iomem *); #define __must_check #endif +#ifndef CONFIG_ENABLE_MUST_CHECK +#undef __must_check +#define __must_check +#endif + /* * Allow us to avoid 'defined but not used' warnings on functions and data, * as well as force them to be emitted to the assembly file. -- cgit v1.2.3 From 8a6914ab7c95d471c23b42268aa8e1f55b3d2fdb Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 14 Aug 2006 22:43:19 -0700 Subject: v4l-dev2: handle __must_check We get hundreds of these: include/media/v4l2-dev.h:348: warning: ignoring return value of 'class_device_create_file', declared with attribute warn_unused_result Handle it, and propagate the __must_check back a level. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/media/v4l2-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 810462f8a37..bb495b7f468 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -341,7 +341,7 @@ extern int video_usercopy(struct inode *inode, struct file *file, extern struct video_device* video_devdata(struct file*); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) -static inline int +static inline int __must_check video_device_create_file(struct video_device *vfd, struct class_device_attribute *attr) { -- cgit v1.2.3 From f86db396ff455ed586751d21816a1ebd431264e5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 14 Aug 2006 22:43:20 -0700 Subject: drivers/base: check errors Add lots of return-value checking. : fix bus_rescan_devices()] Cc: "Randy.Dunlap" Signed-off-by: Cornelia Huck Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index ad4db72f573..b3da9a870cf 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -62,7 +62,7 @@ struct bus_type { extern int __must_check bus_register(struct bus_type * bus); extern void bus_unregister(struct bus_type * bus); -extern void bus_rescan_devices(struct bus_type * bus); +extern int __must_check bus_rescan_devices(struct bus_type * bus); /* iterator helpers for buses */ @@ -397,11 +397,11 @@ extern int device_rename(struct device *dev, char *new_name); * Manual binding of a device to driver. See drivers/base/bus.c * for information on use. */ -extern void device_bind_driver(struct device * dev); +extern int __must_check device_bind_driver(struct device *dev); extern void device_release_driver(struct device * dev); extern int __must_check device_attach(struct device * dev); -extern void driver_attach(struct device_driver * drv); -extern void device_reprobe(struct device *dev); +extern int __must_check driver_attach(struct device_driver *drv); +extern int __must_check device_reprobe(struct device *dev); /* * Easy functions for dynamically creating devices on the fly -- cgit v1.2.3 From f20a9ead0d005fbeeae3fc21a96f9bf197ac1c1c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 14 Aug 2006 22:43:23 -0700 Subject: sysfs: add proper sysfs_init() prototype Don't be crufty. Mark it __must_check too. Cc: "Randy.Dunlap" Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 02ad790921f..6d5c43d31de 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -123,6 +123,8 @@ int __must_check sysfs_create_group(struct kobject *, void sysfs_remove_group(struct kobject *, const struct attribute_group *); void sysfs_notify(struct kobject * k, char *dir, char *attr); +extern int __must_check sysfs_init(void); + #else /* CONFIG_SYSFS */ static inline int sysfs_create_dir(struct kobject * k) @@ -194,6 +196,11 @@ static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) { } +static inline int __must_check sysfs_init(void) +{ + return 0; +} + #endif /* CONFIG_SYSFS */ #endif /* _SYSFS_H_ */ -- cgit v1.2.3 From d779249ed4cb3b50690de6de8448829d65a1cd08 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Jul 2006 10:59:59 -0700 Subject: Driver Core: add ability for drivers to do a threaded probe This adds the infrastructure for drivers to do a threaded probe, and waits at init time for all currently outstanding probes to complete. A new kernel thread will be created when the probe() function for the driver is called, if the multithread_probe bit is set in the driver saying it can support this kind of operation. I have tested this with USB and PCI, and it works, and shaves off a lot of time in the boot process, but there are issues with finding root boot disks, and some USB drivers assume that this can never happen, so it is currently not enabled for any bus type. Individual drivers can enable this right now if they wish, and bus authors can selectivly turn it on as well, once they determine that their subsystem will work properly with it. Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index b3da9a870cf..74246efba93 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -106,6 +106,8 @@ struct device_driver { void (*shutdown) (struct device * dev); int (*suspend) (struct device * dev, pm_message_t state); int (*resume) (struct device * dev); + + unsigned int multithread_probe:1; }; @@ -115,6 +117,7 @@ extern void driver_unregister(struct device_driver * drv); extern struct device_driver * get_driver(struct device_driver * drv); extern void put_driver(struct device_driver * drv); extern struct device_driver *driver_find(const char *name, struct bus_type *bus); +extern int driver_probe_done(void); /* driverfs interface for exporting driver attributes */ -- cgit v1.2.3 From f2eaae197f4590c4d96f31b09b0ee9067421a95c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 18 Sep 2006 16:22:34 -0400 Subject: Driver core: Fix potential deadlock in driver core There is a potential deadlock in the driver core. It boils down to the fact that bus_remove_device() calls klist_remove() instead of klist_del(), thereby waiting until the reference count of the klist_node in the bus's klist of devices drops to 0. The refcount can't reach 0 so long as a modprobe process is trying to bind a new driver to the device being removed, by calling __driver_attach(). The problem is that __driver_attach() tries to acquire the device's parent's semaphore, but the caller of bus_remove_device() is quite likely to own that semaphore already. It isn't sufficient just to replace klist_remove() with klist_del(). Doing so runs the risk that the device would remain on the bus's klist of devices for some time, and so could be bound to another driver even after it was unregistered. What's needed is a new way to distinguish whether or not a device is registered, based on a criterion other than whether its klist_node is linked into the bus's klist of devices. That way driver binding can fail when the device is unregistered, even if it is still linked into the klist. This patch (as782) implements the solution, by adding a new bitflag to indiate when a struct device is registered, by testing the flag before allowing a driver to bind a device, and by changing the definition of the device_is_registered() inline. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 74246efba93..662e6a10144 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -329,6 +329,7 @@ struct device { struct kobject kobj; char bus_id[BUS_ID_SIZE]; /* position on parent bus */ + unsigned is_registered:1; struct device_attribute uevent_attr; struct device_attribute *devt_attr; @@ -381,7 +382,7 @@ dev_set_drvdata (struct device *dev, void *data) static inline int device_is_registered(struct device *dev) { - return klist_node_attached(&dev->knode_bus); + return dev->is_registered; } /* -- cgit v1.2.3