#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
-#include <linux/mutex.h>
+#include <asm/semaphore.h>
#include <linux/firmware.h>
#include "base.h"
FW_STATUS_READY_NOHOTPLUG,
};
-static int loading_timeout = 60; /* In seconds */
+static int loading_timeout = 10; /* In seconds */
/* fw_lock could be moved to 'struct firmware_priv' but since it is just
* guarding for corner cases a global lock should be OK */
-static DEFINE_MUTEX(fw_lock);
+static DECLARE_MUTEX(fw_lock);
struct firmware_priv {
char fw_id[FIRMWARE_NAME_MAX];
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
static void fw_class_dev_release(struct class_device *class_dev);
+int firmware_class_uevent(struct class_device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size);
-static int firmware_class_uevent(struct class_device *class_dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static struct class firmware_class = {
+ .name = "firmware",
+ .uevent = firmware_class_uevent,
+ .release = fw_class_dev_release,
+};
+
+int
+firmware_class_uevent(struct class_device *class_dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
int i = 0, len = 0;
return 0;
}
-static struct class firmware_class = {
- .name = "firmware",
- .uevent = firmware_class_uevent,
- .release = fw_class_dev_release,
-};
-
static ssize_t
firmware_loading_show(struct class_device *class_dev, char *buf)
{
switch (loading) {
case 1:
- mutex_lock(&fw_lock);
+ down(&fw_lock);
if (!fw_priv->fw) {
- mutex_unlock(&fw_lock);
+ up(&fw_lock);
break;
}
vfree(fw_priv->fw->data);
fw_priv->fw->size = 0;
fw_priv->alloc_size = 0;
set_bit(FW_STATUS_LOADING, &fw_priv->status);
- mutex_unlock(&fw_lock);
+ up(&fw_lock);
break;
case 0:
if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
struct firmware *fw;
ssize_t ret_count = count;
- mutex_lock(&fw_lock);
+ down(&fw_lock);
fw = fw_priv->fw;
if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
ret_count = -ENODEV;
memcpy(buffer, fw->data + offset, ret_count);
out:
- mutex_unlock(&fw_lock);
+ up(&fw_lock);
return ret_count;
}
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- mutex_lock(&fw_lock);
+ down(&fw_lock);
fw = fw_priv->fw;
if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
retval = -ENODEV;
fw->size = max_t(size_t, offset + count, fw->size);
retval = count;
out:
- mutex_unlock(&fw_lock);
+ up(&fw_lock);
return retval;
}
} else
wait_for_completion(&fw_priv->completion);
- mutex_lock(&fw_lock);
+ down(&fw_lock);
if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
retval = -ENOENT;
release_firmware(fw_priv->fw);
*firmware_p = NULL;
}
fw_priv->fw = NULL;
- mutex_unlock(&fw_lock);
+ up(&fw_lock);
class_device_unregister(class_dev);
goto out;
}
}
+/**
+ * register_firmware: - provide a firmware image for later usage
+ * @name: name of firmware image file
+ * @data: buffer pointer for the firmware image
+ * @size: size of the data buffer area
+ *
+ * Make sure that @data will be available by requesting firmware @name.
+ *
+ * Note: This will not be possible until some kind of persistence
+ * is available.
+ **/
+void
+register_firmware(const char *name, const u8 *data, size_t size)
+{
+ /* This is meaningless without firmware caching, so until we
+ * decide if firmware caching is reasonable just leave it as a
+ * noop */
+}
+
/* Async support */
struct firmware_work {
struct work_struct work;
EXPORT_SYMBOL(release_firmware);
EXPORT_SYMBOL(request_firmware);
EXPORT_SYMBOL(request_firmware_nowait);
+EXPORT_SYMBOL(register_firmware);