summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 13:13:55 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 13:13:55 -0800
commitcff2f741b8ee8a70b208830e330de053efd4fc45 (patch)
tree83367ed74d889e2c8179f1f8b5d6f6f73b857982 /drivers/base
parentb0885d01f9ab1274109c02942c881d598f939623 (diff)
parent92e9e6d1f9844b73a26215025a922e7d7aeae361 (diff)
downloadop-kernel-dev-cff2f741b8ee8a70b208830e330de053efd4fc45.zip
op-kernel-dev-cff2f741b8ee8a70b208830e330de053efd4fc45.tar.gz
Merge tag 'driver-core-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg Kroah-Hartman: "Here's the large driver core updates for 3.8-rc1. The biggest thing here is the various __dev* marking removals. This is going to be a pain for the merge with different subsystem trees, I know, but all of the patches included here have been ACKed by their various subsystem maintainers, as they wanted them to go through here. If this is too much of a pain, I can pull all of them out of this tree and just send you one with the other fixes/updates and then, after 3.8-rc1 is out, do the rest of the removals to ensure we catch them all, it's up to you. The merges should all be trivial, and Stephen has been doing them all in linux-next for a few weeks now quite easily. Other than the __dev* marking removals, there's nothing major here, some firmware loading updates and other minor things in the driver core. All of these have (much to Stephen's annoyance), been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed up trivial conflicts in drivers/gpio/gpio-{em,stmpe}.c due to gpio update. * tag 'driver-core-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (93 commits) modpost.c: Stop checking __dev* section mismatches init.h: Remove __dev* sections from the kernel acpi: remove use of __devinit PCI: Remove __dev* markings PCI: Always build setup-bus when PCI is enabled PCI: Move pci_uevent into pci-driver.c PCI: Remove CONFIG_HOTPLUG ifdefs unicore32/PCI: Remove CONFIG_HOTPLUG ifdefs sh/PCI: Remove CONFIG_HOTPLUG ifdefs powerpc/PCI: Remove CONFIG_HOTPLUG ifdefs mips/PCI: Remove CONFIG_HOTPLUG ifdefs microblaze/PCI: Remove CONFIG_HOTPLUG ifdefs dma: remove use of __devinit dma: remove use of __devexit_p firewire: remove use of __devinitdata firewire: remove use of __devinit leds: remove use of __devexit leds: remove use of __devinit leds: remove use of __devexit_p mmc: remove use of __devexit ...
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/Kconfig7
-rw-r--r--drivers/base/attribute_container.c2
-rw-r--r--drivers/base/bus.c14
-rw-r--r--drivers/base/core.c8
-rw-r--r--drivers/base/devres.c4
-rw-r--r--drivers/base/firmware_class.c52
-rw-r--r--drivers/base/platform.c4
7 files changed, 53 insertions, 38 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index b34b5cd..c8b4539 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -57,7 +57,7 @@ config DEVTMPFS_MOUNT
on the rootfs is completely empty.
config STANDALONE
- bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
+ bool "Select only drivers that don't need compile-time external firmware"
default y
help
Select this option if you don't have magic firmware for drivers that
@@ -185,7 +185,6 @@ config DMA_SHARED_BUFFER
bool
default n
select ANON_INODES
- depends on EXPERIMENTAL
help
This option enables the framework for buffer-sharing between
multiple drivers. A buffer is associated with a file using driver
@@ -193,8 +192,8 @@ config DMA_SHARED_BUFFER
driver.
config CMA
- bool "Contiguous Memory Allocator (EXPERIMENTAL)"
- depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL
+ bool "Contiguous Memory Allocator"
+ depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
select MIGRATION
select MEMORY_ISOLATION
help
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 8fc200b..d78b204 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -158,7 +158,7 @@ attribute_container_add_device(struct device *dev,
ic = kzalloc(sizeof(*ic), GFP_KERNEL);
if (!ic) {
- dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+ dev_err(dev, "failed to allocate class container\n");
continue;
}
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 181ed26..24eb078 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -164,8 +164,6 @@ static const struct kset_uevent_ops bus_uevent_ops = {
static struct kset *bus_kset;
-
-#ifdef CONFIG_HOTPLUG
/* Manually detach a device from its associated driver. */
static ssize_t driver_unbind(struct device_driver *drv,
const char *buf, size_t count)
@@ -252,7 +250,6 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
return -EINVAL;
return count;
}
-#endif
static struct device *next_device(struct klist_iter *i)
{
@@ -618,11 +615,6 @@ static void driver_remove_attrs(struct bus_type *bus,
}
}
-#ifdef CONFIG_HOTPLUG
-/*
- * Thanks to drivers making their tables __devinit, we can't allow manual
- * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
- */
static int __must_check add_bind_files(struct device_driver *drv)
{
int ret;
@@ -666,12 +658,6 @@ static void remove_probe_files(struct bus_type *bus)
bus_remove_file(bus, &bus_attr_drivers_autoprobe);
bus_remove_file(bus, &bus_attr_drivers_probe);
}
-#else
-static inline int add_bind_files(struct device_driver *drv) { return 0; }
-static inline void remove_bind_files(struct device_driver *drv) {}
-static inline int add_probe_files(struct bus_type *bus) { return 0; }
-static inline void remove_probe_files(struct bus_type *bus) {}
-#endif
static ssize_t driver_uevent_store(struct device_driver *drv,
const char *buf, size_t count)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 150a415..4179139 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1399,7 +1399,7 @@ struct root_device {
struct module *owner;
};
-inline struct root_device *to_root_device(struct device *d)
+static inline struct root_device *to_root_device(struct device *d)
{
return container_of(d, struct root_device, dev);
}
@@ -1840,10 +1840,12 @@ void device_shutdown(void)
pm_runtime_barrier(dev);
if (dev->bus && dev->bus->shutdown) {
- dev_dbg(dev, "shutdown\n");
+ if (initcall_debug)
+ dev_info(dev, "shutdown\n");
dev->bus->shutdown(dev);
} else if (dev->driver && dev->driver->shutdown) {
- dev_dbg(dev, "shutdown\n");
+ if (initcall_debug)
+ dev_info(dev, "shutdown\n");
dev->driver->shutdown(dev);
}
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 8731979..6683906 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -50,8 +50,8 @@ static void devres_log(struct device *dev, struct devres_node *node,
const char *op)
{
if (unlikely(log_devres))
- dev_printk(KERN_ERR, dev, "DEVRES %3s %p %s (%lu bytes)\n",
- op, node, node->name, (unsigned long)node->size);
+ dev_err(dev, "DEVRES %3s %p %s (%lu bytes)\n",
+ op, node, node->name, (unsigned long)node->size);
}
#else /* CONFIG_DEBUG_DEVRES */
#define set_node_dbginfo(node, n, s) do {} while (0)
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8945f4e..d814603 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -143,7 +143,7 @@ struct fw_cache_entry {
};
struct firmware_priv {
- struct timer_list timeout;
+ struct delayed_work timeout_work;
bool nowait;
struct device dev;
struct firmware_buf *buf;
@@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *ref)
__func__, buf->fw_id, buf, buf->data,
(unsigned int)buf->size);
- spin_lock(&fwc->lock);
list_del(&buf->list);
spin_unlock(&fwc->lock);
@@ -263,19 +262,32 @@ static void __fw_free_buf(struct kref *ref)
static void fw_free_buf(struct firmware_buf *buf)
{
- kref_put(&buf->ref, __fw_free_buf);
+ struct firmware_cache *fwc = buf->fwc;
+ spin_lock(&fwc->lock);
+ if (!kref_put(&buf->ref, __fw_free_buf))
+ spin_unlock(&fwc->lock);
}
/* direct firmware loading support */
-static const char *fw_path[] = {
+static char fw_path_para[256];
+static const char * const fw_path[] = {
+ fw_path_para,
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
"/lib/firmware"
};
+/*
+ * Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH'
+ * from kernel command line because firmware_class is generally built in
+ * kernel instead of module.
+ */
+module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
+MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
+
/* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
+static noinline_for_stack long fw_file_size(struct file *file)
{
struct kstat st;
if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
@@ -315,6 +327,11 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
struct file *file;
+
+ /* skip the unset customized path */
+ if (!fw_path[i][0])
+ continue;
+
snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
file = filp_open(path, O_RDONLY, 0);
@@ -667,11 +684,18 @@ static struct bin_attribute firmware_attr_data = {
.write = firmware_data_write,
};
-static void firmware_class_timeout(u_long data)
+static void firmware_class_timeout_work(struct work_struct *work)
{
- struct firmware_priv *fw_priv = (struct firmware_priv *) data;
+ struct firmware_priv *fw_priv = container_of(work,
+ struct firmware_priv, timeout_work.work);
+ mutex_lock(&fw_lock);
+ if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) {
+ mutex_unlock(&fw_lock);
+ return;
+ }
fw_load_abort(fw_priv);
+ mutex_unlock(&fw_lock);
}
static struct firmware_priv *
@@ -690,8 +714,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
fw_priv->nowait = nowait;
fw_priv->fw = firmware;
- setup_timer(&fw_priv->timeout,
- firmware_class_timeout, (u_long) fw_priv);
+ INIT_DELAYED_WORK(&fw_priv->timeout_work,
+ firmware_class_timeout_work);
f_dev = &fw_priv->dev;
@@ -858,7 +882,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
dev_dbg(f_dev->parent, "firmware: direct-loading"
" firmware %s\n", buf->fw_id);
+ mutex_lock(&fw_lock);
set_bit(FW_STATUS_DONE, &buf->status);
+ mutex_unlock(&fw_lock);
complete_all(&buf->completion);
direct_load = 1;
goto handle_fw;
@@ -894,15 +920,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
dev_set_uevent_suppress(f_dev, false);
dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
if (timeout != MAX_SCHEDULE_TIMEOUT)
- mod_timer(&fw_priv->timeout,
- round_jiffies_up(jiffies + timeout));
+ schedule_delayed_work(&fw_priv->timeout_work, timeout);
kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
}
wait_for_completion(&buf->completion);
- del_timer_sync(&fw_priv->timeout);
+ cancel_delayed_work_sync(&fw_priv->timeout_work);
handle_fw:
mutex_lock(&fw_lock);
@@ -963,6 +988,9 @@ err_put_dev:
* firmware image for this or any other device.
*
* Caller must hold the reference count of @device.
+ *
+ * The function can be called safely inside device's suspend and
+ * resume callback.
**/
int
request_firmware(const struct firmware **firmware_p, const char *name,
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index b2ee3bc..c0b8df3 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -45,7 +45,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
* be setup before the platform_notifier is called. So if a user needs to
* manipulate any relevant information in the pdev_archdata they can do:
*
- * platform_devic_alloc()
+ * platform_device_alloc()
* ... manipulate ...
* platform_device_add()
*
@@ -123,7 +123,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
EXPORT_SYMBOL_GPL(platform_get_resource_byname);
/**
- * platform_get_irq - get an IRQ for a device
+ * platform_get_irq_byname - get an IRQ for a device by name
* @dev: platform device
* @name: IRQ name
*/
OpenPOWER on IntegriCloud