4e57b68178
I recently picked up my older work to remove unnecessary #includes of sched.h, starting from a patch by Dave Jones to not include sched.h from module.h. This reduces the number of indirect includes of sched.h by ~300. Another ~400 pointless direct includes can be removed after this disentangling (patch to follow later). However, quite a few indirect includes need to be fixed up for this. In order to feed the patches through -mm with as little disturbance as possible, I've split out the fixes I accumulated up to now (complete for i386 and x86_64, more archs to follow later) and post them before the real patch. This way this large part of the patch is kept simple with only adding #includes, and all hunks are independent of each other. So if any hunk rejects or gets in the way of other patches, just drop it. My scripts will pick it up again in the next round. Signed-off-by: Tim Schmielau <tim@physik3.uni-rostock.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
207 lines
5.1 KiB
C
207 lines
5.1 KiB
C
/*
|
|
* firmware_sample_firmware_class.c -
|
|
*
|
|
* Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
|
|
*
|
|
* NOTE: This is just a probe of concept, if you think that your driver would
|
|
* be well served by this mechanism please contact me first.
|
|
*
|
|
* DON'T USE THIS CODE AS IS
|
|
*
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/timer.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/string.h>
|
|
#include <linux/firmware.h>
|
|
|
|
|
|
MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
|
|
MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
static inline struct class_device *to_class_dev(struct kobject *obj)
|
|
{
|
|
return container_of(obj,struct class_device,kobj);
|
|
}
|
|
static inline
|
|
struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
|
|
{
|
|
return container_of(_attr,struct class_device_attribute,attr);
|
|
}
|
|
|
|
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
|
|
int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
|
|
|
|
struct firmware_priv {
|
|
char fw_id[FIRMWARE_NAME_MAX];
|
|
s32 loading:2;
|
|
u32 abort:1;
|
|
};
|
|
|
|
extern struct class firmware_class;
|
|
|
|
static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
|
|
{
|
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
|
return sprintf(buf, "%d\n", fw_priv->loading);
|
|
}
|
|
static ssize_t firmware_loading_store(struct class_device *class_dev,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
|
int prev_loading = fw_priv->loading;
|
|
|
|
fw_priv->loading = simple_strtol(buf, NULL, 10);
|
|
|
|
switch(fw_priv->loading){
|
|
case -1:
|
|
/* abort load an panic */
|
|
break;
|
|
case 1:
|
|
/* setup load */
|
|
break;
|
|
case 0:
|
|
if(prev_loading==1){
|
|
/* finish load and get the device back to working
|
|
* state */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
static CLASS_DEVICE_ATTR(loading, 0644,
|
|
firmware_loading_show, firmware_loading_store);
|
|
|
|
static ssize_t firmware_data_read(struct kobject *kobj,
|
|
char *buffer, loff_t offset, size_t count)
|
|
{
|
|
struct class_device *class_dev = to_class_dev(kobj);
|
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
|
|
|
/* read from the devices firmware memory */
|
|
|
|
return count;
|
|
}
|
|
static ssize_t firmware_data_write(struct kobject *kobj,
|
|
char *buffer, loff_t offset, size_t count)
|
|
{
|
|
struct class_device *class_dev = to_class_dev(kobj);
|
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
|
|
|
/* write to the devices firmware memory */
|
|
|
|
return count;
|
|
}
|
|
static struct bin_attribute firmware_attr_data = {
|
|
.attr = {.name = "data", .mode = 0644},
|
|
.size = 0,
|
|
.read = firmware_data_read,
|
|
.write = firmware_data_write,
|
|
};
|
|
static int fw_setup_class_device(struct class_device *class_dev,
|
|
const char *fw_name,
|
|
struct device *device)
|
|
{
|
|
int retval = 0;
|
|
struct firmware_priv *fw_priv = kmalloc(sizeof(struct firmware_priv),
|
|
GFP_KERNEL);
|
|
|
|
if(!fw_priv){
|
|
retval = -ENOMEM;
|
|
goto out;
|
|
}
|
|
memset(fw_priv, 0, sizeof(*fw_priv));
|
|
memset(class_dev, 0, sizeof(*class_dev));
|
|
|
|
strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
|
|
fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
|
|
|
|
strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
|
|
class_dev->class_id[BUS_ID_SIZE-1] = '\0';
|
|
class_dev->dev = device;
|
|
|
|
class_dev->class = &firmware_class,
|
|
class_set_devdata(class_dev, fw_priv);
|
|
retval = class_device_register(class_dev);
|
|
if (retval){
|
|
printk(KERN_ERR "%s: class_device_register failed\n",
|
|
__FUNCTION__);
|
|
goto error_free_fw_priv;
|
|
}
|
|
|
|
retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
|
|
if (retval){
|
|
printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
|
|
__FUNCTION__);
|
|
goto error_unreg_class_dev;
|
|
}
|
|
|
|
retval = class_device_create_file(class_dev,
|
|
&class_device_attr_loading);
|
|
if (retval){
|
|
printk(KERN_ERR "%s: class_device_create_file failed\n",
|
|
__FUNCTION__);
|
|
goto error_remove_data;
|
|
}
|
|
|
|
goto out;
|
|
|
|
error_remove_data:
|
|
sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
|
|
error_unreg_class_dev:
|
|
class_device_unregister(class_dev);
|
|
error_free_fw_priv:
|
|
kfree(fw_priv);
|
|
out:
|
|
return retval;
|
|
}
|
|
static void fw_remove_class_device(struct class_device *class_dev)
|
|
{
|
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
|
|
|
class_device_remove_file(class_dev, &class_device_attr_loading);
|
|
sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
|
|
class_device_unregister(class_dev);
|
|
}
|
|
|
|
static struct class_device *class_dev;
|
|
|
|
static struct device my_device = {
|
|
.name = "Sample Device",
|
|
.bus_id = "my_dev0",
|
|
};
|
|
|
|
static int __init firmware_sample_init(void)
|
|
{
|
|
int error;
|
|
|
|
device_initialize(&my_device);
|
|
class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
|
|
if(!class_dev)
|
|
return -ENOMEM;
|
|
|
|
error = fw_setup_class_device(class_dev, "my_firmware_image",
|
|
&my_device);
|
|
if(error){
|
|
kfree(class_dev);
|
|
return error;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
static void __exit firmware_sample_exit(void)
|
|
{
|
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
|
fw_remove_class_device(class_dev);
|
|
kfree(fw_priv);
|
|
kfree(class_dev);
|
|
}
|
|
module_init(firmware_sample_init);
|
|
module_exit(firmware_sample_exit);
|
|
|