Commit 86e7191b authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 5cd8a503 8f2df25d
......@@ -72,6 +72,7 @@ Code Seq# Include File Comments
linux/blkpg.h
0x20 all drivers/cdrom/cm206.h
0x22 all scsi/sg.h
'#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem
'1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
<ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
'6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver
......
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 63
SUBLEVEL = 64
EXTRAVERSION =
# *DOCUMENTATION*
......
......@@ -151,9 +151,14 @@ config CPU_FREQ
If in doubt, say N.
config CPU_FREQ_TABLE
tristate
tristate "CPU frequency table helpers"
depends on CPU_FREQ
default y
help
Many CPUFreq drivers use these helpers, so only say N here if
the CPUFreq driver of your choice doesn't need these helpers.
If in doubt, say Y.
config US3_FREQ
tristate "UltraSPARC-III CPU Frequency driver"
......
......@@ -688,6 +688,7 @@ static int __init topology_init(void)
sparc64_cpus = kmalloc(NR_CPUS * sizeof(struct cpu), GFP_KERNEL);
if (!sparc64_cpus)
return -ENOMEM;
memset(sparc64_cpus, 0, NR_CPUS * sizeof(struct cpu));
for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i))
register_cpu(&sparc64_cpus[i], i, NULL);
......
......@@ -2,7 +2,7 @@
obj-y := core.o sys.o interface.o power.o bus.o \
driver.o class.o intf.o platform.o \
cpu.o firmware.o
cpu.o firmware.o init.o
obj-$(CONFIG_NUMA) += node.o memblk.o
obj-y += fs/
obj-$(CONFIG_HOTPLUG) += hotplug.o
#undef DEBUG
extern struct semaphore device_sem;
extern struct semaphore devclass_sem;
extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
......
......@@ -544,12 +544,11 @@ void bus_unregister(struct bus_type * bus)
subsystem_unregister(&bus->subsys);
}
static int __init bus_subsys_init(void)
int __init buses_init(void)
{
return subsystem_register(&bus_subsys);
}
core_initcall(bus_subsys_init);
EXPORT_SYMBOL(bus_for_each_dev);
EXPORT_SYMBOL(bus_for_each_drv);
......
......@@ -13,6 +13,8 @@
#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
#define to_class(obj) container_of(obj,struct device_class,subsys.kset.kobj)
DECLARE_MUTEX(devclass_sem);
static ssize_t
devclass_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
......@@ -163,29 +165,34 @@ int devclass_add_device(struct device * dev)
struct device_class * cls;
int error = 0;
down(&devclass_sem);
if (dev->driver) {
cls = get_devclass(dev->driver->devclass);
if (cls) {
down_write(&cls->subsys.rwsem);
pr_debug("device class %s: adding device %s\n",
cls->name,dev->name);
if (cls->add_device)
error = cls->add_device(dev);
if (!error) {
enum_device(cls,dev);
interface_add_dev(dev);
}
list_add_tail(&dev->class_list,&cls->devices.list);
/* notify userspace (call /sbin/hotplug) */
class_hotplug (dev, "add");
up_write(&cls->subsys.rwsem);
if (error)
put_devclass(cls);
if (!cls)
goto Done;
pr_debug("device class %s: adding device %s\n",
cls->name,dev->name);
if (cls->add_device)
error = cls->add_device(dev);
if (error) {
put_devclass(cls);
goto Done;
}
down_write(&cls->subsys.rwsem);
enum_device(cls,dev);
list_add_tail(&dev->class_list,&cls->devices.list);
/* notify userspace (call /sbin/hotplug) */
class_hotplug (dev, "add");
up_write(&cls->subsys.rwsem);
interface_add_dev(dev);
}
Done:
up(&devclass_sem);
return error;
}
......@@ -193,26 +200,33 @@ void devclass_remove_device(struct device * dev)
{
struct device_class * cls;
down(&devclass_sem);
if (dev->driver) {
cls = dev->driver->devclass;
if (cls) {
down_write(&cls->subsys.rwsem);
pr_debug("device class %s: removing device %s\n",
cls->name,dev->name);
interface_remove_dev(dev);
unenum_device(cls,dev);
if (!cls)
goto Done;
list_del(&dev->class_list);
interface_remove_dev(dev);
/* notify userspace (call /sbin/hotplug) */
class_hotplug (dev, "remove");
down_write(&cls->subsys.rwsem);
pr_debug("device class %s: removing device %s\n",
cls->name,dev->name);
if (cls->remove_device)
cls->remove_device(dev);
up_write(&cls->subsys.rwsem);
put_devclass(cls);
}
unenum_device(cls,dev);
list_del(&dev->class_list);
/* notify userspace (call /sbin/hotplug) */
class_hotplug (dev, "remove");
up_write(&cls->subsys.rwsem);
if (cls->remove_device)
cls->remove_device(dev);
put_devclass(cls);
}
Done:
up(&devclass_sem);
}
struct device_class * get_devclass(struct device_class * cls)
......@@ -252,13 +266,11 @@ void devclass_unregister(struct device_class * cls)
subsystem_unregister(&cls->subsys);
}
static int __init class_subsys_init(void)
int __init classes_init(void)
{
return subsystem_register(&class_subsys);
}
core_initcall(class_subsys_init);
EXPORT_SYMBOL(devclass_create_file);
EXPORT_SYMBOL(devclass_remove_file);
EXPORT_SYMBOL(devclass_register);
......
......@@ -143,7 +143,6 @@ void device_initialize(struct device *dev)
INIT_LIST_HEAD(&dev->driver_list);
INIT_LIST_HEAD(&dev->bus_list);
INIT_LIST_HEAD(&dev->class_list);
INIT_LIST_HEAD(&dev->intf_list);
}
/**
......@@ -310,13 +309,11 @@ void device_unregister(struct device * dev)
put_device(dev);
}
static int __init device_subsys_init(void)
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
}
core_initcall(device_subsys_init);
EXPORT_SYMBOL(device_initialize);
EXPORT_SYMBOL(device_add);
EXPORT_SYMBOL(device_register);
......
......@@ -46,9 +46,8 @@ int __init register_cpu(struct cpu *cpu, int num, struct node *root)
}
static int __init register_cpu_type(void)
int __init cpu_dev_init(void)
{
devclass_register(&cpu_devclass);
return driver_register(&cpu_driver);
}
postcore_initcall(register_cpu_type);
......@@ -19,12 +19,10 @@ void firmware_unregister(struct subsystem * s)
subsystem_unregister(s);
}
static int __init firmware_init(void)
int __init firmware_init(void)
{
return subsystem_register(&firmware_subsys);
}
core_initcall(firmware_init);
EXPORT_SYMBOL(firmware_register);
EXPORT_SYMBOL(firmware_unregister);
......@@ -17,6 +17,8 @@
#include <linux/err.h>
#include <linux/kmod.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/string.h>
#include "base.h"
#include "fs/fs.h"
......
#include <linux/device.h>
#include <linux/init.h>
extern int devices_init(void);
extern int buses_init(void);
extern int classes_init(void);
extern int firmware_init(void);
extern int platform_bus_init(void);
extern int sys_bus_init(void);
extern int cpu_dev_init(void);
/**
* driver_init - initialize driver model.
*
* Call the driver model init functions to initialize their
* subsystems. Called early from init/main.c.
*/
void __init driver_init(void)
{
/* These are the core pieces */
devices_init();
buses_init();
classes_init();
firmware_init();
/* These are also core pieces, but must come after the
* core core pieces.
*/
platform_bus_init();
sys_bus_init();
cpu_dev_init();
}
......@@ -12,80 +12,31 @@
#define to_intf(node) container_of(node,struct device_interface,kset.kobj.entry)
#define to_data(e) container_of(e,struct intf_data,kobj.entry)
#define to_dev(d) container_of(d,struct device,class_list)
/**
* intf_dev_link - create sysfs symlink for interface.
* @data: interface data descriptor.
* @intf: interface.
* @dev: device.
*
* Create a symlink 'phys' in the interface's directory to
*/
static int intf_dev_link(struct intf_data * data)
static int intf_dev_link(struct device_interface * intf, struct device * dev)
{
char name[16];
snprintf(name,16,"%d",data->intf_num);
return sysfs_create_link(&data->intf->kset.kobj,&data->dev->kobj,name);
return sysfs_create_link(&intf->kset.kobj,&dev->kobj,dev->bus_id);
}
/**
* intf_dev_unlink - remove symlink for interface.
* @intf: interface data descriptor.
*
*/
static void intf_dev_unlink(struct intf_data * data)
{
char name[16];
snprintf(name,16,"%d",data->intf_num);
sysfs_remove_link(&data->intf->kset.kobj,name);
}
/**
* interface_add_data - attach data descriptor
* @data: interface data descriptor.
*
* This attaches the per-instance interface object to the
* interface (by registering its kobject) and the device
* itself (by inserting it into the device's list).
*
* Note that there is no explicit protection done in this
* function. This should be called from the interface's
* add_device() method, which is called under the protection
* of the class's rwsem.
*/
int interface_add_data(struct intf_data * data)
{
struct device_interface * intf = data->intf;
if (intf) {
data->intf_num = intf->devnum++;
data->kobj.kset = &intf->kset;
kobject_register(&data->kobj);
list_add_tail(&data->dev_entry,&data->dev->intf_list);
return intf_dev_link(data);
}
return -EINVAL;
}
/**
* interface_remove_data - detach data descriptor.
* @data: interface data descriptor.
* @intf: interface.
* @dev: device.
*
* This detaches the per-instance data descriptor by removing
* it from the device's list and unregistering the kobject from
* the subsystem.
*/
void interface_remove_data(struct intf_data * data)
static void intf_dev_unlink(struct device_interface * intf, struct device * dev)
{
intf_dev_unlink(data);
list_del_init(&data->dev_entry);
kobject_unregister(&data->kobj);
sysfs_remove_link(&intf->kset.kobj,dev->bus_id);
}
......@@ -103,33 +54,28 @@ static int add(struct device_interface * intf, struct device * dev)
{
int error = 0;
if (intf->add_device)
error = intf->add_device(dev);
if (intf->add_device) {
if (!(error = intf->add_device(dev)))
intf_dev_link(intf,dev);
}
pr_debug(" -> %s (%d)\n",dev->bus_id,error);
return error;
}
/**
* del - detach device from interface.
* @data: interface data descriptor.
*
* Another simple helper. Remove the data descriptor from
* the device and the interface, then call the interface's
* remove_device() method.
* @intf: interface.
* @dev: device.
*/
static void del(struct intf_data * data)
static void del(struct device_interface * intf, struct device * dev)
{
struct device_interface * intf = data->intf;
pr_debug(" -> %s ",intf->name);
interface_remove_data(data);
if (intf->remove_device)
intf->remove_device(data);
intf->remove_device(dev);
intf_dev_unlink(intf,dev);
}
#define to_dev(entry) container_of(entry,struct device,class_list)
/**
* add_intf - add class's devices to interface.
......@@ -145,10 +91,8 @@ static void add_intf(struct device_interface * intf)
struct device_class * cls = intf->devclass;
struct list_head * entry;
down_write(&cls->subsys.rwsem);
list_for_each(entry,&cls->devices.list)
add(intf,to_dev(entry));
up_write(&cls->subsys.rwsem);
}
/**
......@@ -164,6 +108,7 @@ int interface_register(struct device_interface * intf)
{
struct device_class * cls = get_devclass(intf->devclass);
down(&devclass_sem);
if (cls) {
pr_debug("register interface '%s' with class '%s'\n",
intf->name,cls->name);
......@@ -173,6 +118,7 @@ int interface_register(struct device_interface * intf)
kset_register(&intf->kset);
add_intf(intf);
}
up(&devclass_sem);
return 0;
}
......@@ -188,14 +134,13 @@ int interface_register(struct device_interface * intf)
static void del_intf(struct device_interface * intf)
{
struct device_class * cls = intf->devclass;
struct list_head * entry;
down_write(&intf->devclass->subsys.rwsem);
list_for_each(entry,&intf->kset.list) {
struct intf_data * data = to_data(entry);
del(data);
list_for_each(entry,&cls->devices.list) {
struct device * dev = to_dev(entry);
del(intf,dev);
}
up_write(&intf->devclass->subsys.rwsem);
}
/**
......@@ -210,6 +155,8 @@ static void del_intf(struct device_interface * intf)
void interface_unregister(struct device_interface * intf)
{
struct device_class * cls = intf->devclass;
down(&devclass_sem);
if (cls) {
pr_debug("unregistering interface '%s' from class '%s'\n",
intf->name,cls->name);
......@@ -217,6 +164,7 @@ void interface_unregister(struct device_interface * intf)
kset_unregister(&intf->kset);
put_devclass(cls);
}
up(&devclass_sem);
}
......@@ -255,20 +203,21 @@ int interface_add_dev(struct device * dev)
* This is another helper for the class driver core, and called
* when the device is being removed from the class.
*
* We iterate over the list of interface data descriptors attached
* to the device, and call del() [above] for each. Again, the
* class's rwsem is assumed to be held during this.
* We iterate over the list of the class's devices and call del()
* [above] for each. Again, the class's rwsem is _not_ held, but
* the devclass_sem is (see class.c).
*/
void interface_remove_dev(struct device * dev)
{
struct list_head * entry, * next;
struct device_class * cls = dev->driver->devclass;
pr_debug("interfaces: removing device %s\n",dev->name);
list_for_each_safe(entry,next,&dev->intf_list) {
struct intf_data * intf_data = to_data(entry);
del(intf_data);
list_for_each_safe(entry,next,&cls->subsys.kset.list) {
struct device_interface * intf = to_intf(entry);
del(intf,dev);
}
}
......
......@@ -41,9 +41,29 @@ void platform_device_unregister(struct platform_device * pdev)
if (pdev)
device_unregister(&pdev->dev);
}
/**
* platform_match - bind platform device to platform driver.
* @dev: device.
* @drv: driver.
*
* Platform device IDs are assumed to be encoded like this:
* "<name><instance>", where <name> is a short description of the
* type of device, like "pci" or "floppy", and <instance> is the
* enumerated instance of the device, like '0' or '42'.
* Driver IDs are simply "<name>".
* So, extract the <name> from the device, and compare it against
* the name of the driver. Return whether they match or not.
*/
static int platform_match(struct device * dev, struct device_driver * drv)
{
char name[BUS_ID_SIZE];
if (sscanf(dev->bus_id,"%s",name))
return (strcmp(name,drv->name) == 0);
return 0;
}
......@@ -52,13 +72,11 @@ struct bus_type platform_bus_type = {
.match = platform_match,
};
static int __init platform_bus_init(void)
int __init platform_bus_init(void)
{
device_register(&legacy_bus);
return bus_register(&platform_bus_type);
}
postcore_initcall(platform_bus_init);
EXPORT_SYMBOL(platform_device_register);
EXPORT_SYMBOL(platform_device_unregister);
......@@ -138,13 +138,12 @@ struct bus_type system_bus_type = {
.name = "system",
};
static int sys_bus_init(void)
int __init sys_bus_init(void)
{
bus_register(&system_bus_type);
return device_register(&system_bus);
}
postcore_initcall(sys_bus_init);
EXPORT_SYMBOL(system_bus_type);
EXPORT_SYMBOL(sys_device_register);
EXPORT_SYMBOL(sys_device_unregister);
......@@ -1944,27 +1944,25 @@ static void flush_to_ldisc(void *private_)
schedule_delayed_work(&tty->flip.work, 1);
return;
}
spin_lock_irqsave(&tty->read_lock, flags);
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
tty->flip.buf_num = 0;
local_irq_save(flags); // FIXME: is this safe?
tty->flip.char_buf_ptr = tty->flip.char_buf;
tty->flip.flag_buf_ptr = tty->flip.flag_buf;
} else {
cp = tty->flip.char_buf;
fp = tty->flip.flag_buf;
tty->flip.buf_num = 1;
local_irq_save(flags); // FIXME: is this safe?
tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
}
count = tty->flip.count;
tty->flip.count = 0;
local_irq_restore(flags); // FIXME: is this safe?
spin_unlock_irqrestore(&tty->read_lock, flags);
tty->ldisc.receive_buf(tty, cp, fp, count);
}
......
......@@ -18,13 +18,6 @@ obj-$(CONFIG_IEEE1394_CMP) += cmp.o
clean-files := oui.c
ieee1394.o: $(ieee1394-objs)
$(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs)
ifeq ($(obj),)
obj = .
endif
$(obj)/oui.o: $(obj)/oui.c
$(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh
$(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $(obj)/oui.c
......@@ -74,6 +74,8 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
......@@ -1262,8 +1264,11 @@ MODULE_LICENSE("GPL");
static int __init amdtp_init_module (void)
{
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
THIS_MODULE, &amdtp_fops)) {
int ret;
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
THIS_MODULE, &amdtp_fops);
if (ret) {
HPSB_ERR("amdtp: unable to get minor device block");
return -EIO;
}
......@@ -1276,6 +1281,15 @@ static int __init amdtp_init_module (void)
return -EIO;
}
#ifdef CONFIG_COMPAT
ret = register_ioctl32_conversion(AMDTP_IOC_CHANNEL, NULL);
ret |= register_ioctl32_conversion(AMDTP_IOC_PLUG, NULL);
ret |= register_ioctl32_conversion(AMDTP_IOC_PING, NULL);
ret |= register_ioctl32_conversion(AMDTP_IOC_ZAP, NULL);
if (ret)
HPSB_ERR("amdtp: Error registering ioctl32 translations");
#endif
HPSB_INFO("Loaded AMDTP driver");
return 0;
......@@ -1283,6 +1297,17 @@ static int __init amdtp_init_module (void)
static void __exit amdtp_exit_module (void)
{
#ifdef CONFIG_COMPAT
int ret;
ret = unregister_ioctl32_conversion(AMDTP_IOC_CHANNEL);
ret |= unregister_ioctl32_conversion(AMDTP_IOC_PLUG);
ret |= unregister_ioctl32_conversion(AMDTP_IOC_PING);
ret |= unregister_ioctl32_conversion(AMDTP_IOC_ZAP);
if (ret)
HPSB_ERR("amdtp: Error unregistering ioctl32 translations");
#endif
hpsb_unregister_highlevel(amdtp_highlevel);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
......
......@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include "dma.h"
/* dma_prog_region */
......
......@@ -111,6 +111,8 @@
#include <linux/wrapper.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
......@@ -2701,7 +2703,7 @@ static void dv1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci;
struct video_card *video = NULL;
unsigned long flags;
struct list_head *lh;
struct list_head *lh, *templh;
char buf[32];
int n;
......@@ -2715,7 +2717,7 @@ static void dv1394_remove_host (struct hpsb_host *host)
/* find the corresponding video_cards */
spin_lock_irqsave(&dv1394_cards_lock, flags);
if(!list_empty(&dv1394_cards)) {
list_for_each(lh, &dv1394_cards) {
list_for_each_safe(lh, templh, &dv1394_cards) {
video = list_entry(lh, struct video_card, list);
if((video->id >> 2) == ohci->id)
dv1394_un_init(video);
......@@ -2907,6 +2909,98 @@ static struct hpsb_highlevel_ops hl_ops = {
.host_reset = dv1394_host_reset,
};
#ifdef CONFIG_COMPAT
#define DV1394_IOC32_INIT _IOW('#', 0x06, struct dv1394_init32)
#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32)
struct dv1394_init32 {
u32 api_version;
u32 channel;
u32 n_frames;
u32 format;
u32 cip_n;
u32 cip_d;
u32 syt_offset;
};
struct dv1394_status32 {
struct dv1394_init32 init;
s32 active_frame;
u32 first_clear_frame;
u32 n_clear_frames;
u32 dropped_frames;
};
static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct dv1394_init32 dv32;
struct dv1394_init dv;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != dv1394_ioctl)
return -EFAULT;
if (copy_from_user(&dv32, (void *)arg, sizeof(dv32)))
return -EFAULT;
dv.api_version = dv32.api_version;
dv.channel = dv32.channel;
dv.n_frames = dv32.n_frames;
dv.format = dv32.format;
dv.cip_n = (unsigned long)dv32.cip_n;
dv.cip_d = (unsigned long)dv32.cip_d;
dv.syt_offset = dv32.syt_offset;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = dv1394_ioctl(file->f_dentry->d_inode, file,
DV1394_IOC_INIT, (unsigned long)&dv);
set_fs(old_fs);
return ret;
}
static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct dv1394_status32 dv32;
struct dv1394_status dv;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != dv1394_ioctl)
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = dv1394_ioctl(file->f_dentry->d_inode, file,
DV1394_IOC_GET_STATUS, (unsigned long)&dv);
set_fs(old_fs);
if (!ret) {
dv32.init.api_version = dv.init.api_version;
dv32.init.channel = dv.init.channel;
dv32.init.n_frames = dv.init.n_frames;
dv32.init.format = dv.init.format;
dv32.init.cip_n = (u32)dv.init.cip_n;
dv32.init.cip_d = (u32)dv.init.cip_d;
dv32.init.syt_offset = dv.init.syt_offset;
dv32.active_frame = dv.active_frame;
dv32.first_clear_frame = dv.first_clear_frame;
dv32.n_clear_frames = dv.n_clear_frames;
dv32.dropped_frames = dv.dropped_frames;
if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32)))
ret = -EFAULT;
}
return ret;
}
#endif /* CONFIG_COMPAT */
/*** KERNEL MODULE HANDLERS ************************************************/
......@@ -2917,6 +3011,20 @@ MODULE_LICENSE("GPL");
static void __exit dv1394_exit_module(void)
{
#ifdef CONFIG_COMPAT
int ret;
ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN);
ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES);
ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES);
ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES);
ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE);
ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT);
ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS);
if (ret)
printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
#endif
hpsb_unregister_highlevel (hl_handle);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
#ifdef CONFIG_DEVFS_FS
......@@ -2929,14 +3037,18 @@ static void __exit dv1394_exit_module(void)
static int __init dv1394_init_module(void)
{
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
THIS_MODULE, &dv1394_fops)) {
int ret;
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
THIS_MODULE, &dv1394_fops);
if (ret) {
printk(KERN_ERR "dv1394: unable to register character device\n");
return -EIO;
}
#ifdef CONFIG_DEVFS_FS
if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) {
ret = dv1394_devfs_add_dir("dv", NULL, NULL);
if (ret < 0) {
printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
return -ENOMEM;
......@@ -2944,7 +3056,8 @@ static int __init dv1394_init_module(void)
#endif
#ifdef CONFIG_PROC_FS
if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) {
ret = dv1394_procfs_add_dir("dv",NULL,NULL);
if (ret < 0) {
printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
#ifdef CONFIG_DEVFS_FS
......@@ -2967,9 +3080,23 @@ static int __init dv1394_init_module(void)
return -ENOMEM;
}
#ifdef CONFIG_COMPAT
/* First compatible ones */
ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL);
ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL);
/* These need to be handled by translation */
ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init);
ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status);
if (ret)
printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n");
#endif
return 0;
}
module_init(dv1394_init_module);
module_exit(dv1394_exit_module);
This diff is collapsed.
......@@ -30,9 +30,16 @@
#define ETHER1394_REGION_ADDR 0xfffff0200000ULL
#define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN)
/* GASP identifier numbers for IPv4 over IEEE 1394 */
#define ETHER1394_GASP_SPECIFIER_ID 0x00005E
#define ETHER1394_GASP_VERSION 1
/* Node set == 64 */
#define NODE_SET (ALL_NODES + 1)
enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
ETHER1394_BC_CHECK };
/* Private structure for our ethernet driver */
struct eth1394_priv {
struct net_device_stats stats; /* Device stats */
......@@ -43,6 +50,9 @@ struct eth1394_priv {
u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */
u64 eui[ALL_NODES]; /* EUI-64 per node */
spinlock_t lock; /* Private lock */
int broadcast_channel; /* Async stream Broadcast Channel */
enum eth1394_bc_states bc_state; /* broadcast channel state */
struct hpsb_iso *iso; /* Async stream recv handle */
};
struct host_info {
......@@ -51,12 +61,15 @@ struct host_info {
struct net_device *dev;
};
typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
/* This is our task struct. It's used for the packet complete callback. */
struct packet_task {
struct sk_buff *skb; /* Socket buffer we are sending */
nodeid_t dest_node; /* Destination of the packet */
u64 addr; /* Address */
struct hpsb_queue_struct tq; /* The task */
eth1394_tx_type tx_type; /* Send data via GASP or Write Req. */
};
/* IP1394 headers */
......
......@@ -71,9 +71,6 @@ int hpsb_ref_host(struct hpsb_host *host)
list_for_each(lh, &hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) {
if (try_module_get(host->driver->owner)) {
/* we're doing this twice and don't seem
to undo it.. --hch */
(void)try_module_get(host->driver->owner);
host->refcount++;
retval = 1;
}
......
......@@ -4,8 +4,8 @@
#ifndef __IEEE1394_IOCTL_H
#define __IEEE1394_IOCTL_H
#include <asm/ioctl.h>
#include <asm/types.h>
#include <linux/ioctl.h>
#include <linux/types.h>
/* AMDTP Gets 6 */
......@@ -91,7 +91,7 @@
#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \
_IOW ('#', 0x23, unsigned char)
#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \
_IOW ('#', 0x24, u64)
_IOW ('#', 0x24, __u64)
#define RAW1394_IOC_ISO_RECV_PACKETS \
_IOW ('#', 0x25, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \
......
......@@ -361,7 +361,7 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
host->topology_map[host->selfid_count++] = sid;
} else {
HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
sid, (host->node_id & BUS_MASK) >> 6);
sid, NODEID_TO_BUS(host->node_id));
}
}
......@@ -396,9 +396,6 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
/* irm_id is kept up to date by check_selfids() */
if (host->irm_id == host->node_id) {
host->is_irm = 1;
host->is_busmgr = 1;
host->busmgr_id = host->node_id;
host->csr.bus_manager_id = host->node_id;
} else {
host->is_busmgr = 0;
host->is_irm = 0;
......@@ -535,8 +532,8 @@ int hpsb_send_packet(struct hpsb_packet *packet)
if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
packet->speed_code =
host->speed_map[(host->node_id & NODE_MASK) * 64
+ (packet->node_id & NODE_MASK)];
host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+ NODEID_TO_NODE(packet->node_id)];
}
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
......@@ -748,7 +745,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
addr, 4, flags);
if (!write_acked
&& (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
&& (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
......@@ -763,7 +760,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
addr, data[3]>>16, flags);
if (!write_acked
&& (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
&& (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
......@@ -1248,6 +1245,7 @@ EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_lock);
EXPORT_SYMBOL(hpsb_lock64);
EXPORT_SYMBOL(hpsb_send_gasp);
EXPORT_SYMBOL(hpsb_packet_success);
/** highlevel.c **/
......
......@@ -98,6 +98,17 @@ static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
}
static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
int channel, int tag, int sync)
{
packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
| (TCODE_STREAM_DATA << 4) | sync;
packet->header_size = 4;
packet->data_size = length;
packet->type = hpsb_async;
packet->tcode = TCODE_ISO_DATA;
}
/**
* hpsb_get_tlabel - allocate a transaction label
......@@ -495,7 +506,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
}
/* We need a hpsb_lock64 function for the 64 bit equivalent. Probably. */
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
{
......@@ -558,3 +568,58 @@ int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return retval;
}
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
quadlet_t *buffer, size_t length, u32 specifier_id,
unsigned int version)
{
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
int i;
#endif
struct hpsb_packet *packet;
int retval = 0;
u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
u8 specifier_id_lo = specifier_id & 0xff;
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("Send GASP: channel = %d, length = %d", channel, length);
#endif
length += 8;
packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
if (!packet)
return -ENOMEM;
if (length % 4) {
packet->data[length / 4] = 0;
}
packet->host = host;
fill_async_stream_packet(packet, length, channel, 3, 0);
packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
memcpy(&(packet->data[2]), buffer, length - 4);
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG("GASP: packet->header_size = %d", packet->header_size);
HPSB_DEBUG("GASP: packet->data_size = %d", packet->data_size);
for(i=0; i<(packet->data_size/4); i++)
HPSB_DEBUG("GASP: data[%d]: 0x%08x", i*4, be32_to_cpu(packet->data[i]));
#endif
packet->generation = generation;
packet->no_waiter = 1;
if (!hpsb_send_packet(packet)) {
free_hpsb_packet(packet);
retval = -EINVAL;
}
return retval;
}
......@@ -55,5 +55,8 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, octlet_t *data, octlet_t arg);
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
quadlet_t *buffer, size_t length, u32 specifier_id,
unsigned int version);
#endif /* _IEEE1394_TRANSACTIONS_H */
......@@ -97,14 +97,17 @@ typedef u64 nodeaddr_t;
typedef u16 arm_length_t;
#define BUS_MASK 0xffc0
#define BUS_SHIFT 6
#define NODE_MASK 0x003f
#define LOCAL_BUS 0xffc0
#define ALL_NODES 0x003f
#define NODEID_TO_BUS(nodeid) ((nodeid & BUS_MASK) >> BUS_SHIFT)
#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK)
/* Can be used to consistently print a node/bus ID. */
#define NODE_BUS_FMT "%02d:%04d"
#define NODE_BUS_ARGS(nodeid) \
(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
#define NODE_BUS_FMT "%02d:%04d"
#define NODE_BUS_ARGS(nodeid) NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid)
#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
......
......@@ -1210,6 +1210,52 @@ static void nodemgr_node_probe(struct hpsb_host *host)
return;
}
/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other
* nodes of the broadcast channel. (Really we're only setting the validity
* bit). */
static void nodemgr_do_irm_duties(struct hpsb_host *host)
{
quadlet_t bc;
if (!host->is_irm)
return;
host->csr.broadcast_channel |= 0x40000000; /* set validity bit */
bc = cpu_to_be32(host->csr.broadcast_channel);
hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
(CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
&bc,
sizeof(quadlet_t));
}
/* We need to ensure that if we are not the IRM, that the IRM node is capable of
* everything we can do, otherwise issue a bus reset and try to become the IRM
* ourselves. */
static int nodemgr_check_root_capability(struct hpsb_host *host)
{
quadlet_t bc;
int status;
if (host->is_irm)
return 1;
status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
get_hpsb_generation(host),
(CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
&bc, sizeof(quadlet_t));
if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
/* The root node does not have a valid BROADCAST_CHANNEL
* register and we do, so reset the bus with force_root set */
HPSB_INFO("Remote root is not IRM capable, resetting...");
hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
return 0;
}
return 1;
}
static int nodemgr_host_thread(void *__hi)
{
struct host_info *hi = (struct host_info *)__hi;
......@@ -1217,12 +1263,21 @@ static int nodemgr_host_thread(void *__hi)
/* No userlevel access needed */
daemonize("knodemgrd");
allow_signal(SIGTERM);
/* Sit and wait for a signal to probe the nodes on the bus. This
* happens when we get a bus reset. */
while (!down_interruptible(&hi->reset_sem) &&
!down_interruptible(&nodemgr_serialize)) {
if (!nodemgr_check_root_capability(hi->host)) {
/* Do nothing, we are resetting */
up(&nodemgr_serialize);
continue;
}
nodemgr_node_probe(hi->host);
nodemgr_do_irm_duties(hi->host);
up(&nodemgr_serialize);
}
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
......
......@@ -31,9 +31,9 @@
*
* Things implemented, but still in test phase:
* . Iso Transmit
* . Async Stream Packets Transmit (Receive done via Iso interface)
*
* Things not implemented:
* . Async Stream Packets
* . DMA error recovery
*
* Known bugs:
......@@ -160,7 +160,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
"$Rev: 762 $ Ben Collins <bcollins@debian.org>";
"$Rev: 801 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
MODULE_PARM(phys_dma,"i");
......@@ -649,18 +649,31 @@ static void insert_packet(struct ti_ohci *ohci,
} else {
d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
(packet->header[0] & 0xFFFF);
d->prg_cpu[idx]->data[1] =
(packet->header[1] & 0xFFFF) |
(packet->header[0] & 0xFFFF0000);
d->prg_cpu[idx]->data[2] = packet->header[2];
d->prg_cpu[idx]->data[3] = packet->header[3];
if (packet->tcode == TCODE_ISO_DATA) {
/* Sending an async stream packet */
d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
} else {
/* Sending a normal async request or response */
d->prg_cpu[idx]->data[1] =
(packet->header[1] & 0xFFFF) |
(packet->header[0] & 0xFFFF0000);
d->prg_cpu[idx]->data[2] = packet->header[2];
d->prg_cpu[idx]->data[3] = packet->header[3];
}
packet_swab(d->prg_cpu[idx]->data, packet->tcode);
}
if (packet->data_size) { /* block transmit */
d->prg_cpu[idx]->begin.control =
cpu_to_le32(DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 0x10);
if (packet->tcode == TCODE_STREAM_DATA){
d->prg_cpu[idx]->begin.control =
cpu_to_le32(DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 0x8);
} else {
d->prg_cpu[idx]->begin.control =
cpu_to_le32(DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 0x10);
}
d->prg_cpu[idx]->end.control =
cpu_to_le32(DMA_CTL_OUTPUT_LAST |
DMA_CTL_IRQ |
......@@ -830,7 +843,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
/* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw)
d = &ohci->at_req_context;
else if (packet->tcode == TCODE_ISO_DATA) {
else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
/* The legacy IT DMA context is initialized on first
* use. However, the alloc cannot be run from
* interrupt context, so we bail out if that is the
......@@ -856,7 +869,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
}
d = &ohci->it_legacy_context;
} else if (packet->tcode & 0x02)
} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
d = &ohci->at_resp_context;
else
d = &ohci->at_req_context;
......@@ -1295,6 +1308,8 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
u32 *prev_branch = NULL;
for (blk = 0; blk < recv->nblocks; blk++) {
u32 control;
/* the DMA descriptor */
struct dma_cmd *cmd = &recv->block[blk];
......@@ -1305,29 +1320,29 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
unsigned long buf_offset = blk * recv->buf_stride;
if (recv->dma_mode == BUFFER_FILL_MODE) {
cmd->control = 2 << 28; /* INPUT_MORE */
control = 2 << 28; /* INPUT_MORE */
} else {
cmd->control = 3 << 28; /* INPUT_LAST */
control = 3 << 28; /* INPUT_LAST */
}
cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */
control |= 8 << 24; /* s = 1, update xferStatus and resCount */
/* interrupt on last block, and at intervals */
if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) {
cmd->control |= 3 << 20; /* want interrupt */
control |= 3 << 20; /* want interrupt */
}
cmd->control |= 3 << 18; /* enable branch to address */
cmd->control |= recv->buf_stride;
control |= 3 << 18; /* enable branch to address */
control |= recv->buf_stride;
cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset);
cmd->control = cpu_to_le32(control);
cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset));
cmd->branchAddress = 0; /* filled in on next loop */
cmd->status = recv->buf_stride;
cmd->status = cpu_to_le32(recv->buf_stride);
/* link the previous descriptor to this one */
if (prev_branch) {
*prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset);
*prev_branch |= 1; /* set Z=1 */
*prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
}
prev_branch = &cmd->branchAddress;
......@@ -1485,18 +1500,18 @@ static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
/* 'next' becomes the new end of the DMA chain,
so disable branch and enable interrupt */
next->branchAddress = 0;
next->control |= 3 << 20;
next->control |= cpu_to_le32(3 << 20);
/* link prev to next */
prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog,
sizeof(struct dma_cmd) * next_i)
| 1; /* Z=1 */
prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog,
sizeof(struct dma_cmd) * next_i)
| 1); /* Z=1 */
/* disable interrupt on previous DMA descriptor, except at intervals */
if((prev_i % recv->block_irq_interval) == 0) {
prev->control |= 3 << 20; /* enable interrupt */
prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
} else {
prev->control &= ~(3<<20); /* disable interrupt */
prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
}
wmb();
......@@ -1720,8 +1735,8 @@ static void ohci_iso_recv_packetperbuf_task(unsigned long data)
struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
/* check the DMA descriptor for new writes to xferStatus */
u16 xferstatus = il->status >> 16;
u16 rescount = il->status & 0xFFFF;
u16 xferstatus = le32_to_cpu(il->status) >> 16;
u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
unsigned char event = xferstatus & 0x1F;
......@@ -1903,7 +1918,7 @@ static void ohci_iso_xmit_task(unsigned long data)
struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
/* check for new writes to xferStatus */
u16 xferstatus = cmd->output_last.status >> 16;
u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16;
u8 event = xferstatus & 0x1F;
if(!event) {
......@@ -1919,7 +1934,7 @@ static void ohci_iso_xmit_task(unsigned long data)
wake = 1;
/* parse cycle */
cycle = cmd->output_last.status & 0x1FFF;
cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
/* tell the subsystem the packet has gone out */
hpsb_iso_packet_sent(iso, cycle, event != 0x11);
......@@ -1972,7 +1987,7 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
/* set up the OUTPUT_MORE_IMMEDIATE descriptor */
memset(next, 0, sizeof(struct iso_xmit_cmd));
next->output_more_immediate.control = 0x02000008;
next->output_more_immediate.control = cpu_to_le32(0x02000008);
/* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
......@@ -1990,28 +2005,28 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
next->iso_hdr[7] = len >> 8;
/* set up the OUTPUT_LAST */
next->output_last.control = 1 << 28;
next->output_last.control |= 1 << 27; /* update timeStamp */
next->output_last.control |= 3 << 20; /* want interrupt */
next->output_last.control |= 3 << 18; /* enable branch */
next->output_last.control |= len;
next->output_last.control = cpu_to_le32(1 << 28);
next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
next->output_last.control |= cpu_to_le32(len);
/* payload bus address */
next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset);
next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset));
/* leave branchAddress at zero for now */
/* re-write the previous DMA descriptor to chain to this one */
/* set prev branch address to point to next (Z=3) */
prev->output_last.branchAddress =
dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3;
prev->output_last.branchAddress = cpu_to_le32(
dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
/* disable interrupt, unless required by the IRQ interval */
if(prev_i % iso->irq_interval) {
prev->output_last.control &= ~(3 << 20); /* no interrupt */
prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
} else {
prev->output_last.control |= 3 << 20; /* enable interrupt */
prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
}
wmb();
......@@ -3473,10 +3488,10 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
{
.class = PCI_CLASS_FIREWIRE_OHCI,
.class_mask = 0x00ffffff,
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.class = PCI_CLASS_FIREWIRE_OHCI,
.class_mask = ~0,
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
......
......@@ -238,7 +238,7 @@ static void remove_host(struct hpsb_host *host)
list_del(&hi->list);
host_count--;
/*
FIXME: addressranges should be removed
FIXME: address ranges should be removed
and fileinfo states should be initialized
(including setting generation to
internal-generation ...)
......@@ -281,8 +281,8 @@ static void host_reset(struct hpsb_host *host)
req->req.misc = (host->node_id << 16)
| host->node_count;
if (fi->protocol_version > 3) {
req->req.misc |= ((host->irm_id
& NODE_MASK) << 8);
req->req.misc |= (NODEID_TO_NODE(host->irm_id)
<< 8);
}
queue_complete_req(req);
......@@ -571,8 +571,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
req->req.misc = (fi->host->node_id << 16)
| fi->host->node_count;
if (fi->protocol_version > 3) {
req->req.misc |=
(fi->host->irm_id & NODE_MASK) << 8;
req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
}
} else {
req->req.error = RAW1394_ERROR_INVALID_ARG;
......
This diff is collapsed.
......@@ -22,15 +22,6 @@
#ifndef SBP2_H
#define SBP2_H
/* Some compatibility code */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define SCSI_REGISTER_HOST(tmpl) scsi_register_module(MODULE_SCSI_HA, tmpl)
#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_module(MODULE_SCSI_HA, tmpl)
#else
#define SCSI_REGISTER_HOST(tmpl) scsi_register_host(tmpl)
#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_host(tmpl)
#endif
#define SBP2_DEVICE_NAME "sbp2"
/*
......@@ -442,8 +433,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
static void sbp2_add_host(struct hpsb_host *host);
static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
static void sbp2_remove_host(struct hpsb_host *host);
int sbp2_init(void);
void sbp2_cleanup(void);
static int sbp2_probe(struct unit_directory *ud);
static void sbp2_disconnect(struct unit_directory *ud);
static void sbp2_update(struct unit_directory *ud);
......@@ -487,23 +476,4 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id);
static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
/*
* Scsi interface related prototypes
*/
static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
static const char *sbp2scsi_info (struct Scsi_Host *host);
void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]);
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#endif
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt);
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt);
static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
u32 status);
static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
#endif /* SBP2_H */
......@@ -43,6 +43,8 @@
#include <linux/vmalloc.h>
#include <linux/timex.h>
#include <linux/mm.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
......@@ -1338,24 +1340,152 @@ MODULE_DESCRIPTION("driver for digital video on OHCI board");
MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
MODULE_LICENSE("GPL");
#ifdef CONFIG_COMPAT
#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER \
_IOW ('#', 0x12, struct video1394_wait32)
#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER \
_IOWR('#', 0x13, struct video1394_wait32)
#define VIDEO1394_IOC32_TALK_WAIT_BUFFER \
_IOW ('#', 0x17, struct video1394_wait32)
#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER \
_IOWR('#', 0x18, struct video1394_wait32)
struct video1394_wait32 {
u32 channel;
u32 buffer;
struct compat_timeval filltime;
};
static int video1394_wr_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct video1394_wait32 wait32;
struct video1394_wait wait;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != video1394_ioctl)
return -EFAULT;
if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
return -EFAULT;
wait.channel = wait32.channel;
wait.buffer = wait32.buffer;
wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
old_fs = get_fs();
set_fs(KERNEL_DS);
if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
(unsigned long) &wait);
else
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_LISTEN_POLL_BUFFER,
(unsigned long) &wait);
set_fs(old_fs);
if (!ret) {
wait32.channel = wait.channel;
wait32.buffer = wait.buffer;
wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
if (copy_to_user((struct video1394_wait32 *)arg, &wait32, sizeof(wait32)))
ret = -EFAULT;
}
return ret;
}
static int video1394_w_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
struct video1394_wait32 wait32;
struct video1394_wait wait;
mm_segment_t old_fs;
int ret;
if (file->f_op->ioctl != video1394_ioctl)
return -EFAULT;
if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
return -EFAULT;
wait.channel = wait32.channel;
wait.buffer = wait32.buffer;
wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
old_fs = get_fs();
set_fs(KERNEL_DS);
if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
(unsigned long) &wait);
else
ret = video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_TALK_WAIT_BUFFER,
(unsigned long) &wait);
set_fs(old_fs);
return ret;
}
static int video1394_queue_buf32(unsigned int fd, unsigned int cmd, unsigned long arg,
struct file *file)
{
if (file->f_op->ioctl != video1394_ioctl)
return -EFAULT;
return -EFAULT;
return video1394_ioctl(file->f_dentry->d_inode, file,
VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
}
#endif /* CONFIG_COMPAT */
static void __exit video1394_exit_module (void)
{
#ifdef CONFIG_COMPAT
int ret;
ret = unregister_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER);
ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER);
if (ret)
PRINT_G(KERN_INFO, "Error unregistering ioctl32 translations");
#endif
hpsb_unregister_highlevel (hl_handle);
devfs_unregister(devfs_handle);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
}
static int __init video1394_init_module (void)
{
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
THIS_MODULE, &video1394_fops)) {
int ret;
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
THIS_MODULE, &video1394_fops);
if (ret) {
PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
return -EIO;
}
return -EIO;
}
devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL);
hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
......@@ -1366,9 +1496,32 @@ static int __init video1394_init_module (void)
return -ENOMEM;
}
#ifdef CONFIG_COMPAT
/* First the compatible ones */
ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL, NULL);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL, NULL);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL, NULL);
/* These need translation */
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER,
video1394_w_wait32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER,
video1394_wr_wait32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER,
video1394_queue_buf32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER,
video1394_w_wait32);
ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER,
video1394_wr_wait32);
if (ret)
PRINT_G(KERN_INFO, "Error registering ioctl32 translations");
#endif
PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
return 0;
}
module_init(video1394_init_module);
module_exit(video1394_exit_module);
......@@ -981,7 +981,7 @@ dgrs_download(struct net_device *dev0)
{
DGRS_PRIV *priv0 = (DGRS_PRIV *) dev0->priv;
int is;
int i;
unsigned long i;
static int iv2is[16] = {
0, 0, 0, ES4H_IS_INT3,
......@@ -1140,7 +1140,7 @@ int __init
dgrs_probe1(struct net_device *dev)
{
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
int i;
unsigned long i;
int rc;
printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n",
......
......@@ -88,10 +88,10 @@
#include <net/arp.h>
struct shaper_cb {
unsigned long shapeclock; /* Time it should go out */
unsigned long shapestamp; /* Stamp for shaper */
__u32 shapelatency; /* Latency on frame */
__u32 shapeclock; /* Time it should go out */
__u32 shapelen; /* Frame length in clocks */
__u32 shapestamp; /* Stamp for shaper */
__u16 shapepend; /* Pending */
};
#define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb))
......@@ -335,7 +335,7 @@ static void shaper_kick(struct shaper *shaper)
*/
if(sh_debug)
printk("Clock = %d, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies);
printk("Clock = %ld, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies);
if(time_before_eq(SHAPERCB(skb)->shapeclock - jiffies, SHAPER_BURST))
{
/*
......
......@@ -509,7 +509,7 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
{
struct sis900_private * sis_priv = net_dev->priv;
u16 poll_bit = MII_STAT_LINK, status = 0;
unsigned int timeout = jiffies + 5 * HZ;
unsigned long timeout = jiffies + 5 * HZ;
int phy_addr;
u8 revision;
......
......@@ -13,6 +13,7 @@
#include <linux/types.h>
#include <linux/stat.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include "base.h"
......
......@@ -694,7 +694,7 @@ static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
int isp2x00_detect(Scsi_Host_Template * tmpt)
{
int hosts = 0;
int wait_time;
unsigned long wait_time;
struct Scsi_Host *host = NULL;
struct isp2x00_hostdata *hostdata;
struct pci_dev *pdev;
......
......@@ -1490,9 +1490,9 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
{
if (scsi_eh_bus_device_reset(shost, work_q, done_q))
if (scsi_eh_bus_reset(shost, work_q, done_q))
if (scsi_eh_host_reset(work_q, done_q))
if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
if (!scsi_eh_bus_reset(shost, work_q, done_q))
if (!scsi_eh_host_reset(work_q, done_q))
scsi_eh_offline_sdevs(work_q, done_q);
}
......
......@@ -33,11 +33,11 @@
* Local functions.
*/
static int bw2_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int bw2_set_par(struct fb_info *);
static int bw2_blank(int, struct fb_info *);
static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static int bw2_ioctl(struct inode *, struct file *, unsigned int,
unsigned long, struct fb_info *);
/*
* Frame buffer operations
......@@ -45,13 +45,12 @@ static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static struct fb_ops bw2_ops = {
.owner = THIS_MODULE,
.fb_check_var = bw2_check_var,
.fb_set_par = bw2_set_par,
.fb_blank = bw2_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = bw2_mmap,
.fb_ioctl = bw2_ioctl,
.fb_cursor = soft_cursor,
};
......@@ -123,39 +122,6 @@ struct bw2_par {
struct list_head list;
};
/**
* bw2_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int bw2_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 8)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
return 0;
}
/**
* bw2_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
bw2_set_par(struct fb_info *info)
{
return 0;
}
/**
* bw2_blank - Optional function. Blanks the display.
* @blank_mode: the blank mode we want.
......@@ -212,6 +178,15 @@ static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info)
{
struct bw2_par *par = (struct bw2_par *) info->par;
return sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_SUN2BW, 1, par->fbsize);
}
/*
* Initialisation
*/
......@@ -387,7 +362,6 @@ static void bw2_init_one(struct sbus_dev *sdev)
bw2_blank(0, &all->info);
bw2_set_par(&all->info);
bw2_init_fix(&all->info, linebytes);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -28,8 +28,6 @@
* Local functions.
*/
static int cg14_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int cg14_set_par(struct fb_info *);
static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
......@@ -43,8 +41,6 @@ static int cg14_ioctl(struct inode *, struct file *, unsigned int,
static struct fb_ops cg14_ops = {
.owner = THIS_MODULE,
.fb_check_var = cg14_check_var,
.fb_set_par = cg14_set_par,
.fb_setcolreg = cg14_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
......@@ -219,39 +215,6 @@ static void __cg14_reset(struct cg14_par *par)
sbus_writeb(val, &regs->mcr);
}
/**
* cg14_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int cg14_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 8)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
return 0;
}
/**
* cg14_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
cg14_set_par(struct fb_info *info)
{
return 0;
}
/**
* cg14_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
......@@ -358,7 +321,8 @@ static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
break;
default:
ret = -EINVAL;
ret = sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_MDICOLOR, 24, par->fbsize);
break;
};
......@@ -523,7 +487,6 @@ static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
return;
}
cg14_set_par(&all->info);
cg14_init_fix(&all->info, linebytes);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -29,13 +29,13 @@
* Local functions.
*/
static int cg3_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int cg3_set_par(struct fb_info *);
static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int cg3_blank(int, struct fb_info *);
static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static int cg3_ioctl(struct inode *, struct file *, unsigned int,
unsigned long, struct fb_info *);
/*
* Frame buffer operations
......@@ -43,14 +43,13 @@ static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static struct fb_ops cg3_ops = {
.owner = THIS_MODULE,
.fb_check_var = cg3_check_var,
.fb_set_par = cg3_set_par,
.fb_setcolreg = cg3_setcolreg,
.fb_blank = cg3_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = cg3_mmap,
.fb_ioctl = cg3_ioctl,
.fb_cursor = soft_cursor,
};
......@@ -126,39 +125,6 @@ struct cg3_par {
struct list_head list;
};
/**
* cg3_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int cg3_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 8)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
return 0;
}
/**
* cg3_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
cg3_set_par(struct fb_info *info)
{
return 0;
}
/**
* cg3_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
......@@ -269,6 +235,15 @@ static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info)
{
struct cg3_par *par = (struct cg3_par *) info->par;
return sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_SUN3COLOR, 8, par->fbsize);
}
/*
* Initialisation
*/
......@@ -445,7 +420,6 @@ static void cg3_init_one(struct sbus_dev *sdev)
return;
}
cg3_set_par(&all->info);
cg3_init_fix(&all->info, linebytes);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -29,8 +29,6 @@
* Local functions.
*/
static int cg6_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int cg6_set_par(struct fb_info *);
static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int cg6_blank(int, struct fb_info *);
......@@ -39,6 +37,8 @@ static void cg6_imageblit(struct fb_info *, struct fb_image *);
static void cg6_fillrect(struct fb_info *, struct fb_fillrect *);
static int cg6_sync(struct fb_info *);
static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static int cg6_ioctl(struct inode *, struct file *, unsigned int,
unsigned long, struct fb_info *);
/*
* Frame buffer operations
......@@ -46,8 +46,6 @@ static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static struct fb_ops cg6_ops = {
.owner = THIS_MODULE,
.fb_check_var = cg6_check_var,
.fb_set_par = cg6_set_par,
.fb_setcolreg = cg6_setcolreg,
.fb_blank = cg6_blank,
.fb_fillrect = cg6_fillrect,
......@@ -55,6 +53,7 @@ static struct fb_ops cg6_ops = {
.fb_imageblit = cg6_imageblit,
.fb_sync = cg6_sync,
.fb_mmap = cg6_mmap,
.fb_ioctl = cg6_ioctl,
.fb_cursor = soft_cursor,
};
......@@ -405,39 +404,6 @@ static void cg6_imageblit(struct fb_info *info, struct fb_image *image)
spin_unlock_irqrestore(&par->lock, flags);
}
/**
* cg6_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int cg6_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 8)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
return 0;
}
/**
* cg6_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
cg6_set_par(struct fb_info *info)
{
return 0;
}
/**
* cg6_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
......@@ -535,6 +501,15 @@ static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info)
{
struct cg6_par *par = (struct cg6_par *) info->par;
return sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_SUNFAST_COLOR, 8, par->fbsize);
}
/*
* Initialisation
*/
......@@ -731,7 +706,6 @@ static void cg6_init_one(struct sbus_dev *sdev)
return;
}
cg6_set_par(&all->info);
cg6_init_fix(&all->info, linebytes);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -20,6 +20,7 @@
#include <asm/io.h>
#include <asm/upa.h>
#include <asm/oplib.h>
#include <asm/fbio.h>
#include "sbuslib.h"
......@@ -27,8 +28,6 @@
* Local functions.
*/
static int ffb_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int ffb_set_par(struct fb_info *);
static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int ffb_blank(int, struct fb_info *);
......@@ -39,6 +38,8 @@ static void ffb_fillrect(struct fb_info *, struct fb_fillrect *);
static void ffb_copyarea(struct fb_info *, struct fb_copyarea *);
static int ffb_sync(struct fb_info *);
static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static int ffb_ioctl(struct inode *, struct file *, unsigned int,
unsigned long, struct fb_info *);
/*
* Frame buffer operations
......@@ -46,8 +47,6 @@ static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static struct fb_ops ffb_ops = {
.owner = THIS_MODULE,
.fb_check_var = ffb_check_var,
.fb_set_par = ffb_set_par,
.fb_setcolreg = ffb_setcolreg,
.fb_blank = ffb_blank,
.fb_fillrect = ffb_fillrect,
......@@ -55,6 +54,7 @@ static struct fb_ops ffb_ops = {
.fb_imageblit = ffb_imageblit,
.fb_sync = ffb_sync,
.fb_mmap = ffb_mmap,
.fb_ioctl = ffb_ioctl,
/* XXX Use FFB hw cursor once fb cursor API is better understood... */
.fb_cursor = soft_cursor,
......@@ -672,41 +672,6 @@ static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
var->transp.length = 0;
}
/**
* ffb_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int ffb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 32)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
ffb_fixup_var_rgb(var);
return 0;
}
/**
* ffb_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
ffb_set_par(struct fb_info *info)
{
return 0;
}
/**
* ffb_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
......@@ -818,6 +783,15 @@ static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
0, vma);
}
static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info)
{
struct ffb_par *par = (struct ffb_par *) info->par;
return sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_CREATOR, 24, par->fbsize);
}
/*
* Initialisation
*/
......@@ -972,7 +946,6 @@ static void ffb_init_one(int node, int parent)
return;
}
ffb_set_par(&all->info);
ffb_init_fix(&all->info);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -27,13 +27,13 @@
* Local functions.
*/
static int p9100_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int p9100_set_par(struct fb_info *);
static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int p9100_blank(int, struct fb_info *);
static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static int p9100_ioctl(struct inode *, struct file *, unsigned int,
unsigned long, struct fb_info *);
/*
* Frame buffer operations
......@@ -41,14 +41,13 @@ static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static struct fb_ops p9100_ops = {
.owner = THIS_MODULE,
.fb_check_var = p9100_check_var,
.fb_set_par = p9100_set_par,
.fb_setcolreg = p9100_setcolreg,
.fb_blank = p9100_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = p9100_mmap,
.fb_ioctl = p9100_ioctl,
.fb_cursor = soft_cursor,
};
......@@ -142,39 +141,6 @@ struct p9100_par {
struct list_head list;
};
/**
* p9100_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int p9100_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 8)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
return 0;
}
/**
* p9100_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
p9100_set_par(struct fb_info *info)
{
return 0;
}
/**
* p9100_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
......@@ -265,6 +231,16 @@ static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_st
vma);
}
static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info)
{
struct p9100_par *par = (struct p9100_par *) info->par;
/* Make it look like a cg3. */
return sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_SUN3COLOR, 8, par->fbsize);
}
/*
* Initialisation
*/
......@@ -344,7 +320,6 @@ static void p9100_init_one(struct sbus_dev *sdev)
return;
}
p9100_set_par(&all->info);
p9100_init_fix(&all->info, linebytes);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -9,6 +9,7 @@
#include <linux/fb.h>
#include <asm/oplib.h>
#include <asm/fbio.h>
#include "sbuslib.h"
......@@ -83,3 +84,84 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map,
return 0;
}
EXPORT_SYMBOL(sbusfb_mmap_helper);
int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
struct fb_info *info,
int type, int fb_depth, unsigned long fb_size)
{
switch(cmd) {
case FBIOGTYPE: {
struct fbtype *f = (struct fbtype *) arg;
if (put_user(type, &f->fb_type) ||
__put_user(info->var.yres, &f->fb_height) ||
__put_user(info->var.xres, &f->fb_width) ||
__put_user(fb_depth, &f->fb_depth) ||
__put_user(0, &f->fb_cmsize) ||
__put_user(fb_size, &f->fb_cmsize))
return -EFAULT;
return 0;
}
case FBIOPUTCMAP_SPARC: {
struct fbcmap *c = (struct fbcmap *) arg;
struct fb_cmap cmap;
u16 red, green, blue;
unsigned char *ured, *ugreen, *ublue;
int index, count, i;
if (get_user(index, &c->index) ||
__get_user(count, &c->count) ||
__get_user(ured, &c->red) ||
__get_user(ugreen, &c->green) ||
__get_user(ublue, &c->blue))
return -EFAULT;
cmap.len = 1;
cmap.red = &red;
cmap.green = &green;
cmap.blue = &blue;
for (i = 0; i < count; i++) {
int err;
if (get_user(red, &ured[i]) ||
get_user(green, &ugreen[i]) ||
get_user(blue, &ublue[i]))
return -EFAULT;
cmap.start = index + i;
err = fb_set_cmap(&cmap, 0, info);
if (err)
return err;
}
return 0;
}
case FBIOGETCMAP_SPARC: {
struct fbcmap *c = (struct fbcmap *) arg;
unsigned char *ured, *ugreen, *ublue;
struct fb_cmap *cmap = &info->cmap;
int index, count, i;
if (get_user(index, &c->index) ||
__get_user(count, &c->count) ||
__get_user(ured, &c->red) ||
__get_user(ugreen, &c->green) ||
__get_user(ublue, &c->blue))
return -EFAULT;
if (index + count > cmap->len)
return -EINVAL;
for (i = 0; i < count; i++) {
if (put_user(cmap->red[index + i], &ured[i]) ||
put_user(cmap->green[index + i], &ugreen[i]) ||
put_user(cmap->blue[index + i], &ublue[i]))
return -EFAULT;
}
return 0;
}
default:
return -EINVAL;
};
}
EXPORT_SYMBOL(sbusfb_ioctl_helper);
......@@ -17,5 +17,8 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
unsigned long physbase, unsigned long fbsize,
unsigned long iospace,
struct vm_area_struct *vma);
int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
struct fb_info *info,
int type, int fb_depth, unsigned long fb_size);
#endif /* _SBUSLIB_H */
......@@ -29,13 +29,13 @@
* Local functions.
*/
static int tcx_check_var(struct fb_var_screeninfo *, struct fb_info *);
static int tcx_set_par(struct fb_info *);
static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int tcx_blank(int, struct fb_info *);
static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static int tcx_ioctl(struct inode *, struct file *, unsigned int,
unsigned long, struct fb_info *);
/*
* Frame buffer operations
......@@ -43,14 +43,13 @@ static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
static struct fb_ops tcx_ops = {
.owner = THIS_MODULE,
.fb_check_var = tcx_check_var,
.fb_set_par = tcx_set_par,
.fb_setcolreg = tcx_setcolreg,
.fb_blank = tcx_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = tcx_mmap,
.fb_ioctl = tcx_ioctl,
.fb_cursor = soft_cursor,
};
......@@ -154,39 +153,6 @@ static void tcx_reset (struct fb_info *info)
spin_unlock_irqrestore(&par->lock, flags);
}
/**
* tcx_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static int tcx_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->bits_per_pixel != 8)
return -EINVAL;
if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
return -EINVAL;
if (var->nonstd)
return -EINVAL;
if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
if (var->xres != info->var.xres || var->yres != info->var.yres)
return -EINVAL;
return 0;
}
/**
* tcx_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static int
tcx_set_par(struct fb_info *info)
{
return 0;
}
/**
* tcx_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
......@@ -298,6 +264,17 @@ static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg, struct fb_info *info)
{
struct tcx_par *par = (struct tcx_par *) info->par;
return sbusfb_ioctl_helper(cmd, arg, info,
FBTYPE_TCXCOLOR,
(par->lowdepth ? 8 : 24),
par->fbsize);
}
/*
* Initialisation
*/
......@@ -431,7 +408,6 @@ static void tcx_init_one(struct sbus_dev *sdev)
return;
}
tcx_set_par(&all->info);
tcx_init_fix(&all->info, linebytes);
if (register_framebuffer(&all->info) < 0) {
......
......@@ -47,16 +47,8 @@ static kmem_cache_t *dentry_cache;
static unsigned int d_hash_mask;
static unsigned int d_hash_shift;
static struct list_head *dentry_hashtable;
static struct hlist_head *dentry_hashtable;
static LIST_HEAD(dentry_unused);
static int max_dentries;
static void * hashtable_end;
static inline int is_bucket(void * addr)
{
return ((addr < (void *)dentry_hashtable)
|| (addr > hashtable_end) ? 0 : 1);
}
/* Statistics gathering. */
struct dentry_stat_t dentry_stat = {
......@@ -292,6 +284,7 @@ struct dentry * d_find_alias(struct inode *inode)
while (next != head) {
tmp = next;
next = tmp->next;
prefetch(next);
alias = list_entry(tmp, struct dentry, d_alias);
if (!d_unhashed(alias)) {
if (alias->d_flags & DCACHE_DISCONNECTED)
......@@ -378,6 +371,7 @@ static void prune_dcache(int count)
if (tmp == &dentry_unused)
break;
list_del_init(tmp);
prefetch(dentry_unused.prev);
dentry_stat.nr_unused--;
dentry = list_entry(tmp, struct dentry, d_lru);
......@@ -603,15 +597,15 @@ void shrink_dcache_parent(struct dentry * parent)
* done under dcache_lock.
*
*/
void shrink_dcache_anon(struct list_head *head)
void shrink_dcache_anon(struct hlist_head *head)
{
struct list_head *lp;
struct hlist_node *lp;
int found;
do {
found = 0;
spin_lock(&dcache_lock);
list_for_each(lp, head) {
struct dentry *this = list_entry(lp, struct dentry, d_hash);
hlist_for_each(lp, head) {
struct dentry *this = hlist_entry(lp, struct dentry, d_hash);
list_del(&this->d_lru);
/* don't add non zero d_count dentries
......@@ -727,7 +721,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
dentry->d_mounted = 0;
dentry->d_cookie = NULL;
dentry->d_bucket = NULL;
INIT_LIST_HEAD(&dentry->d_hash);
INIT_HLIST_NODE(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
INIT_LIST_HEAD(&dentry->d_alias);
......@@ -797,7 +791,7 @@ struct dentry * d_alloc_root(struct inode * root_inode)
return res;
}
static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)
static inline struct hlist_head * d_hash(struct dentry * parent, unsigned long hash)
{
hash += (unsigned long) parent / L1_CACHE_BYTES;
hash = hash ^ (hash >> D_HASHBITS);
......@@ -860,7 +854,7 @@ struct dentry * d_alloc_anon(struct inode *inode)
res->d_flags |= DCACHE_DISCONNECTED;
res->d_vfs_flags &= ~DCACHE_UNHASHED;
list_add(&res->d_alias, &inode->i_dentry);
list_add(&res->d_hash, &inode->i_sb->s_anon);
hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
spin_unlock(&res->d_lock);
}
inode = NULL; /* don't drop reference */
......@@ -947,21 +941,21 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
unsigned int len = name->len;
unsigned int hash = name->hash;
const unsigned char *str = name->name;
struct list_head *head = d_hash(parent,hash);
struct hlist_head *head = d_hash(parent,hash);
struct dentry *found = NULL;
struct list_head *tmp;
int lookup_count = 0;
struct hlist_node *node;
rcu_read_lock();
/* lookup is terminated when flow reaches any bucket head */
for(tmp = head->next; !is_bucket(tmp); tmp = tmp->next) {
hlist_for_each (node, head) {
struct dentry *dentry;
unsigned long move_count;
struct qstr * qstr;
prefetch(node->next);
smp_read_barrier_depends();
dentry = list_entry(tmp, struct dentry, d_hash);
dentry = hlist_entry(node, struct dentry, d_hash);
/* if lookup ends up in a different bucket
* due to concurrent rename, fail it
......@@ -969,12 +963,6 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
if (unlikely(dentry->d_bucket != head))
break;
/* to avoid race if dentry keep coming back to original
* bucket due to double moves
*/
if (unlikely(++lookup_count > max_dentries))
break;
/*
* We must take a snapshot of d_move_count followed by
* read memory barrier before any search key comparison
......@@ -1034,7 +1022,8 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
unsigned long dent_addr = (unsigned long) dentry;
unsigned long min_addr = PAGE_OFFSET;
unsigned long align_mask = 0x0F;
struct list_head *base, *lhp;
struct hlist_head *base;
struct hlist_node *lhp;
if (dent_addr < min_addr)
goto out;
......@@ -1050,12 +1039,13 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
goto out;
spin_lock(&dcache_lock);
lhp = base = d_hash(dparent, dentry->d_name.hash);
while ((lhp = lhp->next) != base) {
base = d_hash(dparent, dentry->d_name.hash);
hlist_for_each(lhp,base) {
prefetch(lhp->next);
/* read_barrier_depends() not required for d_hash list
* as it is parsed under dcache_lock
*/
if (dentry == list_entry(lhp, struct dentry, d_hash)) {
if (dentry == hlist_entry(lhp, struct dentry, d_hash)) {
__dget_locked(dentry);
spin_unlock(&dcache_lock);
return 1;
......@@ -1116,12 +1106,11 @@ void d_delete(struct dentry * dentry)
void d_rehash(struct dentry * entry)
{
struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);
spin_lock(&dcache_lock);
if (!list_empty(&entry->d_hash) && !d_unhashed(entry)) BUG();
entry->d_vfs_flags &= ~DCACHE_UNHASHED;
entry->d_bucket = list;
list_add_rcu(&entry->d_hash, list);
hlist_add_head_rcu(&entry->d_hash, list);
spin_unlock(&dcache_lock);
}
......@@ -1174,10 +1163,6 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target)
* We could be nicer about the deleted file, and let it show
* up under the name it got deleted rather than the name that
* deleted it.
*
* Careful with the hash switch. The hash switch depends on
* the fact that any list-entry can be a head of the list.
* Think about it.
*/
/**
......@@ -1200,8 +1185,8 @@ void d_move(struct dentry * dentry, struct dentry * target)
/* Move the dentry to the target hash queue, if on different bucket */
if (dentry->d_bucket != target->d_bucket) {
dentry->d_bucket = target->d_bucket;
list_del_rcu(&dentry->d_hash);
list_add_rcu(&dentry->d_hash, &target->d_hash);
hlist_del_rcu(&dentry->d_hash);
hlist_add_head_rcu(&dentry->d_hash, target->d_bucket);
}
/* Unhash the target: dput() will then get rid of it */
......@@ -1284,6 +1269,7 @@ static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
continue;
}
parent = dentry->d_parent;
prefetch(parent);
namelen = dentry->d_name.len;
buflen -= namelen + 1;
if (buflen < 0)
......@@ -1503,7 +1489,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
static void __init dcache_init(unsigned long mempages)
{
struct list_head *d;
struct hlist_head *d;
unsigned long order;
unsigned int nr_hash;
int i;
......@@ -1524,15 +1510,12 @@ static void __init dcache_init(unsigned long mempages)
if (!dentry_cache)
panic("Cannot create dentry cache");
/* approximate maximum number of dentries in one hash bucket */
max_dentries = (mempages * (PAGE_SIZE / sizeof(struct dentry)));
set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
#if PAGE_SHIFT < 13
mempages >>= (13 - PAGE_SHIFT);
#endif
mempages *= sizeof(struct list_head);
mempages *= sizeof(struct hlist_head);
for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
;
......@@ -1540,7 +1523,7 @@ static void __init dcache_init(unsigned long mempages)
unsigned long tmp;
nr_hash = (1UL << order) * PAGE_SIZE /
sizeof(struct list_head);
sizeof(struct hlist_head);
d_hash_mask = (nr_hash - 1);
tmp = nr_hash;
......@@ -1548,7 +1531,7 @@ static void __init dcache_init(unsigned long mempages)
while ((tmp >>= 1UL) != 0UL)
d_hash_shift++;
dentry_hashtable = (struct list_head *)
dentry_hashtable = (struct hlist_head *)
__get_free_pages(GFP_ATOMIC, order);
} while (dentry_hashtable == NULL && --order >= 0);
......@@ -1558,12 +1541,10 @@ static void __init dcache_init(unsigned long mempages)
if (!dentry_hashtable)
panic("Failed to allocate dcache hash table\n");
hashtable_end = dentry_hashtable + nr_hash;
d = dentry_hashtable;
i = nr_hash;
do {
INIT_LIST_HEAD(d);
INIT_HLIST_HEAD(d);
d++;
i--;
} while (i);
......
......@@ -9,6 +9,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
......@@ -58,6 +59,38 @@ static struct file_system_type **find_filesystem(const char *name)
return p;
}
/* define fs_subsys */
static decl_subsys(fs, NULL);
static int register_fs_subsys(struct file_system_type * fs)
{
struct subsystem *sub = &fs->subsys;
snprintf(sub->kset.kobj.name, KOBJ_NAME_LEN, "%s", fs->name);
subsys_set_kset(fs, fs_subsys);
return subsystem_register(sub);
}
static int unlink_fs(struct file_system_type * fs)
{
struct file_system_type ** tmp;
write_lock(&file_systems_lock);
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
return 0;
}
tmp = &(*tmp)->next;
}
write_unlock(&file_systems_lock);
return -EINVAL;
}
/**
* register_filesystem - register a new filesystem
* @fs: the file system structure
......@@ -88,6 +121,14 @@ int register_filesystem(struct file_system_type * fs)
else
*p = fs;
write_unlock(&file_systems_lock);
if (!res) {
/* we implicitly possess reference to @fs during registration,
* so it cannot be unregister from under us. */
if (register_fs_subsys(fs))
printk(KERN_WARNING "Failed to register '%s' in sysfs\n",
fs->name);
}
return res;
}
......@@ -105,21 +146,44 @@ int register_filesystem(struct file_system_type * fs)
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
int res;
write_lock(&file_systems_lock);
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
return 0;
}
tmp = &(*tmp)->next;
}
write_unlock(&file_systems_lock);
return -EINVAL;
res = unlink_fs(fs);
if (!res)
subsystem_unregister(&fs->subsys);
return res;
}
extern int sysfs_init(void);
/**
* fs_subsys_init - initialize sysfs and fs subsystem.
*
* In order to register filesystems in sysfs, it has to be
* initialized. Also, we need the base fs filesystem, so the
* registered filesystems have a home.
*
* During sysfs_init(), the registration of sysfs into itself
* will fail, since it's not mounted yet. To make sure that
* sysfs does show up, we re-register sysfs's embedded subsystem,
* which will get added, since sysfs is now mounted.
*/
void __init fs_subsys_init(void)
{
struct file_system_type ** p;
/* make sure sysfs is up and running */
sysfs_init();
/* register fs_subsys */
subsystem_register(&fs_subsys);
p = find_filesystem("sysfs");
if (p)
/* make sure it's registered */
register_fs_subsys(*p);
}
static int fs_index(const char * __name)
......
......@@ -90,7 +90,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
* Only add valid (hashed) inodes to the superblock's
* dirty list. Add blockdev inodes as well.
*/
if (list_empty(&inode->i_hash) && !S_ISBLK(inode->i_mode))
if (hlist_unhashed(&inode->i_hash) && !S_ISBLK(inode->i_mode))
goto out;
/*
......
......@@ -189,7 +189,7 @@ void truncate_hugepages(struct address_space *mapping, loff_t lstart)
static void hugetlbfs_delete_inode(struct inode *inode)
{
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
list_del_init(&inode->i_list);
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
......@@ -208,7 +208,7 @@ static void hugetlbfs_forget_inode(struct inode *inode)
{
struct super_block *super_block = inode->i_sb;
if (list_empty(&inode->i_hash))
if (hlist_unhashed(&inode->i_hash))
goto out_truncate;
if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
......@@ -223,7 +223,7 @@ static void hugetlbfs_forget_inode(struct inode *inode)
/* write_inode_now() ? */
inodes_stat.nr_unused--;
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
out_truncate:
list_del_init(&inode->i_list);
inode->i_state |= I_FREEING;
......
......@@ -69,8 +69,8 @@ static unsigned int i_hash_shift;
LIST_HEAD(inode_in_use);
LIST_HEAD(inode_unused);
static struct list_head *inode_hashtable;
static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */
static struct hlist_head *inode_hashtable;
static HLIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */
/*
* A simple spinlock to protect the list manipulations.
......@@ -172,7 +172,7 @@ void destroy_inode(struct inode *inode)
void inode_init_once(struct inode *inode)
{
memset(inode, 0, sizeof(*inode));
INIT_LIST_HEAD(&inode->i_hash);
INIT_HLIST_NODE(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_data.clean_pages);
INIT_LIST_HEAD(&inode->i_data.dirty_pages);
INIT_LIST_HEAD(&inode->i_data.locked_pages);
......@@ -294,7 +294,7 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru
continue;
invalidate_inode_buffers(inode);
if (!atomic_read(&inode->i_count)) {
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
list_del(&inode->i_list);
list_add(&inode->i_list, dispose);
inode->i_state |= I_FREEING;
......@@ -435,7 +435,7 @@ static void prune_icache(int nr_to_scan)
if (!can_unuse(inode))
continue;
}
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
list_move(&inode->i_list, &freeable);
inode->i_state |= I_FREEING;
nr_pruned++;
......@@ -476,50 +476,42 @@ static int shrink_icache_memory(int nr, unsigned int gfp_mask)
* by hand after calling find_inode now! This simplifies iunique and won't
* add any additional branch in the common code.
*/
static struct inode * find_inode(struct super_block * sb, struct list_head *head, int (*test)(struct inode *, void *), void *data)
static struct inode * find_inode(struct super_block * sb, struct hlist_head *head, int (*test)(struct inode *, void *), void *data)
{
struct list_head *tmp;
struct inode * inode;
struct hlist_node *node;
struct inode * inode = NULL;
tmp = head;
for (;;) {
tmp = tmp->next;
inode = NULL;
if (tmp == head)
break;
inode = list_entry(tmp, struct inode, i_hash);
hlist_for_each (node, head) {
prefetch(node->next);
inode = hlist_entry(node, struct inode, i_hash);
if (inode->i_sb != sb)
continue;
if (!test(inode, data))
continue;
break;
}
return inode;
return node ? inode : NULL;
}
/*
* find_inode_fast is the fast path version of find_inode, see the comment at
* iget_locked for details.
*/
static struct inode * find_inode_fast(struct super_block * sb, struct list_head *head, unsigned long ino)
static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino)
{
struct list_head *tmp;
struct inode * inode;
struct hlist_node *node;
struct inode * inode = NULL;
tmp = head;
for (;;) {
tmp = tmp->next;
inode = NULL;
if (tmp == head)
break;
inode = list_entry(tmp, struct inode, i_hash);
hlist_for_each (node, head) {
prefetch(node->next);
inode = list_entry(node, struct inode, i_hash);
if (inode->i_ino != ino)
continue;
if (inode->i_sb != sb)
continue;
break;
}
return inode;
return node ? inode : NULL;
}
/**
......@@ -569,7 +561,7 @@ EXPORT_SYMBOL(unlock_new_inode);
* We no longer cache the sb_flags in i_flags - see fs.h
* -- rmk@arm.uk.linux.org
*/
static struct inode * get_new_inode(struct super_block *sb, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
{
struct inode * inode;
......@@ -586,7 +578,7 @@ static struct inode * get_new_inode(struct super_block *sb, struct list_head *he
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
hlist_add_head(&inode->i_hash, head);
inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock);
......@@ -619,7 +611,7 @@ static struct inode * get_new_inode(struct super_block *sb, struct list_head *he
* get_new_inode_fast is the fast path version of get_new_inode, see the
* comment at iget_locked for details.
*/
static struct inode * get_new_inode_fast(struct super_block *sb, struct list_head *head, unsigned long ino)
static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino)
{
struct inode * inode;
......@@ -634,7 +626,7 @@ static struct inode * get_new_inode_fast(struct super_block *sb, struct list_hea
inode->i_ino = ino;
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
hlist_add_head(&inode->i_hash, head);
inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock);
......@@ -686,7 +678,7 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved)
{
static ino_t counter = 0;
struct inode *inode;
struct list_head * head;
struct hlist_head * head;
ino_t res;
spin_lock(&inode_lock);
retry:
......@@ -740,7 +732,7 @@ struct inode *igrab(struct inode *inode)
* Note, @test is called with the inode_lock held, so can't sleep.
*/
static inline struct inode *ifind(struct super_block *sb,
struct list_head *head, int (*test)(struct inode *, void *),
struct hlist_head *head, int (*test)(struct inode *, void *),
void *data)
{
struct inode *inode;
......@@ -772,7 +764,7 @@ static inline struct inode *ifind(struct super_block *sb,
* Otherwise NULL is returned.
*/
static inline struct inode *ifind_fast(struct super_block *sb,
struct list_head *head, unsigned long ino)
struct hlist_head *head, unsigned long ino)
{
struct inode *inode;
......@@ -810,7 +802,7 @@ static inline struct inode *ifind_fast(struct super_block *sb,
struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), void *data)
{
struct list_head *head = inode_hashtable + hash(sb, hashval);
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
return ifind(sb, head, test, data);
}
......@@ -832,7 +824,7 @@ EXPORT_SYMBOL(ilookup5);
*/
struct inode *ilookup(struct super_block *sb, unsigned long ino)
{
struct list_head *head = inode_hashtable + hash(sb, ino);
struct hlist_head *head = inode_hashtable + hash(sb, ino);
return ifind_fast(sb, head, ino);
}
......@@ -864,7 +856,7 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *), void *data)
{
struct list_head *head = inode_hashtable + hash(sb, hashval);
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode;
inode = ifind(sb, head, test, data);
......@@ -897,7 +889,7 @@ EXPORT_SYMBOL(iget5_locked);
*/
struct inode *iget_locked(struct super_block *sb, unsigned long ino)
{
struct list_head *head = inode_hashtable + hash(sb, ino);
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
inode = ifind_fast(sb, head, ino);
......@@ -923,11 +915,11 @@ EXPORT_SYMBOL(iget_locked);
void __insert_inode_hash(struct inode *inode, unsigned long hashval)
{
struct list_head *head = &anon_hash_chain;
struct hlist_head *head = &anon_hash_chain;
if (inode->i_sb)
head = inode_hashtable + hash(inode->i_sb, hashval);
spin_lock(&inode_lock);
list_add(&inode->i_hash, head);
hlist_add_head(&inode->i_hash, head);
spin_unlock(&inode_lock);
}
......@@ -941,7 +933,7 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
void remove_inode_hash(struct inode *inode)
{
spin_lock(&inode_lock);
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock);
}
......@@ -949,7 +941,7 @@ void generic_delete_inode(struct inode *inode)
{
struct super_operations *op = inode->i_sb->s_op;
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
list_del_init(&inode->i_list);
inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--;
......@@ -978,7 +970,7 @@ static void generic_forget_inode(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
if (!list_empty(&inode->i_hash)) {
if (!hlist_unhashed(&inode->i_hash)) {
if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
list_del(&inode->i_list);
list_add(&inode->i_list, &inode_unused);
......@@ -990,7 +982,7 @@ static void generic_forget_inode(struct inode *inode)
write_inode_now(inode, 1);
spin_lock(&inode_lock);
inodes_stat.nr_unused--;
list_del_init(&inode->i_hash);
hlist_del_init(&inode->i_hash);
}
list_del_init(&inode->i_list);
inode->i_state|=I_FREEING;
......@@ -1236,7 +1228,7 @@ void wake_up_inode(struct inode *inode)
*/
void __init inode_init(unsigned long mempages)
{
struct list_head *head;
struct hlist_head *head;
unsigned long order;
unsigned int nr_hash;
int i;
......@@ -1253,7 +1245,7 @@ void __init inode_init(unsigned long mempages)
unsigned long tmp;
nr_hash = (1UL << order) * PAGE_SIZE /
sizeof(struct list_head);
sizeof(struct hlist_head);
i_hash_mask = (nr_hash - 1);
tmp = nr_hash;
......@@ -1261,7 +1253,7 @@ void __init inode_init(unsigned long mempages)
while ((tmp >>= 1UL) != 0UL)
i_hash_shift++;
inode_hashtable = (struct list_head *)
inode_hashtable = (struct hlist_head *)
__get_free_pages(GFP_ATOMIC, order);
} while (inode_hashtable == NULL && --order >= 0);
......@@ -1274,7 +1266,7 @@ void __init inode_init(unsigned long mempages)
head = inode_hashtable;
i = nr_hash;
do {
INIT_LIST_HEAD(head);
INIT_HLIST_HEAD(head);
head++;
i--;
} while (i);
......
......@@ -26,6 +26,7 @@
extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
extern int do_remount_sb(struct super_block *sb, int flags, void * data);
extern int __init init_rootfs(void);
extern int __init fs_subsys_init(void);
static struct list_head *mount_hashtable;
static int hash_mask, hash_bits;
......@@ -1132,6 +1133,7 @@ void __init mnt_init(unsigned long mempages)
d++;
i--;
} while (i);
fs_subsys_init();
init_rootfs();
init_mount_tree();
}
......@@ -63,7 +63,7 @@ static struct super_block *alloc_super(void)
INIT_LIST_HEAD(&s->s_io);
INIT_LIST_HEAD(&s->s_files);
INIT_LIST_HEAD(&s->s_instances);
INIT_LIST_HEAD(&s->s_anon);
INIT_HLIST_HEAD(&s->s_anon);
init_rwsem(&s->s_umount);
sema_init(&s->s_lock, 1);
down_write(&s->s_umount);
......
......@@ -2,4 +2,4 @@
# Makefile for the sysfs virtual filesystem
#
obj-y := inode.o
obj-y := inode.o file.o dir.o symlink.o mount.o bin.o
/*
* bin.c - binary file operations for sysfs.
*/
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include "sysfs.h"
static struct file_operations bin_fops;
static int fill_read(struct file * file, struct sysfs_bin_buffer * buffer)
{
struct bin_attribute * attr = file->f_dentry->d_fsdata;
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
if (!buffer->data)
attr->read(kobj,buffer);
return buffer->size ? 0 : -ENOENT;
}
static int flush_read(struct file * file, char * userbuf,
struct sysfs_bin_buffer * buffer)
{
return copy_to_user(userbuf,buffer->data + buffer->offset,buffer->count) ?
-EFAULT : 0;
}
static ssize_t
read(struct file * file, char * userbuf, size_t count, loff_t * off)
{
struct sysfs_bin_buffer * buffer = file->private_data;
int ret;
ret = fill_read(file,buffer);
if (ret)
goto Done;
buffer->offset = *off;
if (count > (buffer->size - *off))
count = buffer->size - *off;
buffer->count = count;
ret = flush_read(file,userbuf,buffer);
if (!ret) {
*off += count;
ret = count;
}
Done:
return ret;
}
int alloc_buf_data(struct sysfs_bin_buffer * buffer)
{
buffer->data = kmalloc(buffer->count,GFP_KERNEL);
if (buffer->data) {
memset(buffer->data,0,buffer->count);
return 0;
} else
return -ENOMEM;
}
static int fill_write(struct file * file, const char * userbuf,
struct sysfs_bin_buffer * buffer)
{
return copy_from_user(buffer,userbuf,buffer->count) ?
-EFAULT : 0;
}
static int flush_write(struct file * file, const char * userbuf,
struct sysfs_bin_buffer * buffer)
{
struct bin_attribute * attr = file->f_dentry->d_fsdata;
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
return attr->write(kobj,buffer);
}
static ssize_t write(struct file * file, const char * userbuf,
size_t count, loff_t * off)
{
struct sysfs_bin_buffer * buffer = file->private_data;
int ret;
if (count > PAGE_SIZE)
count = PAGE_SIZE;
buffer->count = count;
ret = alloc_buf_data(buffer);
if (ret)
goto Done;
ret = fill_write(file,userbuf,buffer);
if (ret)
goto Done;
ret = flush_write(file,userbuf,buffer);
if (ret > 0)
*off += count;
Done:
if (buffer->data) {
kfree(buffer->data);
buffer->data = NULL;
}
return ret;
}
static int check_perm(struct inode * inode, struct file * file)
{
struct kobject * kobj = kobject_get(file->f_dentry->d_parent->d_fsdata);
struct bin_attribute * attr = file->f_dentry->d_fsdata;
struct sysfs_bin_buffer * buffer;
int error = 0;
if (!kobj || !attr)
goto Einval;
/* File needs write support.
* The inode's perms must say it's ok,
* and we must have a store method.
*/
if (file->f_mode & FMODE_WRITE) {
if (!(inode->i_mode & S_IWUGO) || !attr->write)
goto Eaccess;
}
/* File needs read support.
* The inode's perms must say it's ok, and we there
* must be a show method for it.
*/
if (file->f_mode & FMODE_READ) {
if (!(inode->i_mode & S_IRUGO) || !attr->read)
goto Eaccess;
}
buffer = kmalloc(sizeof(struct sysfs_bin_buffer),GFP_KERNEL);
if (buffer) {
memset(buffer,0,sizeof(struct sysfs_bin_buffer));
file->private_data = buffer;
} else
error = -ENOMEM;
goto Done;
Einval:
error = -EINVAL;
goto Done;
Eaccess:
error = -EACCES;
Done:
if (error && kobj)
kobject_put(kobj);
return error;
}
static int open(struct inode * inode, struct file * file)
{
return check_perm(inode,file);
}
static int release(struct inode * inode, struct file * file)
{
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
u8 * buffer = file->private_data;
if (kobj)
kobject_put(kobj);
if (buffer)
kfree(buffer);
return 0;
}
static struct file_operations bin_fops = {
.read = read,
.write = write,
.llseek = generic_file_llseek,
.open = open,
.release = release,
};
/**
* sysfs_create_bin_file - create binary file for object.
* @kobj: object.
* @attr: attribute descriptor.
*
*/
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
struct dentry * dentry;
struct dentry * parent;
int error = 0;
if (!kobj || !attr)
return -EINVAL;
parent = kobj->dentry;
down(&parent->d_inode->i_sem);
dentry = sysfs_get_dentry(parent,attr->attr.name);
if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)attr;
error = sysfs_create(dentry,
(attr->attr.mode & S_IALLUGO) | S_IFREG,
NULL);
if (!error) {
dentry->d_inode->i_size = attr->size;
dentry->d_inode->i_fop = &bin_fops;
}
} else
error = PTR_ERR(dentry);
up(&parent->d_inode->i_sem);
return error;
}
/**
* sysfs_remove_bin_file - remove binary file for object.
* @kobj: object.
* @attr: attribute descriptor.
*
*/
int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
sysfs_hash_and_remove(kobj->dentry,attr->attr.name);
return 0;
}
EXPORT_SYMBOL(sysfs_create_bin_file);
EXPORT_SYMBOL(sysfs_remove_bin_file);
/*
* dir.c - Operations for sysfs directories.
*/
#undef DEBUG
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include "sysfs.h"
static int init_dir(struct inode * inode)
{
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inode->i_nlink++;
return 0;
}
/**
* sysfs_create_dir - create a directory for an object.
* @parent: parent parent object.
* @kobj: object we're creating directory for.
*/
int sysfs_create_dir(struct kobject * kobj)
{
struct dentry * dentry = NULL;
struct dentry * parent;
int error = 0;
if (!kobj)
return -EINVAL;
if (kobj->parent)
parent = kobj->parent->dentry;
else if (sysfs_mount && sysfs_mount->mnt_sb)
parent = sysfs_mount->mnt_sb->s_root;
else
return -EFAULT;
down(&parent->d_inode->i_sem);
dentry = sysfs_get_dentry(parent,kobj->name);
if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)kobj;
kobj->dentry = dentry;
error = sysfs_create(dentry,(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
init_dir);
if (!error)
parent->d_inode->i_nlink++;
} else
error = PTR_ERR(dentry);
up(&parent->d_inode->i_sem);
return error;
}
/**
* sysfs_remove_dir - remove an object's directory.
* @kobj: object.
*
* The only thing special about this is that we remove any files in
* the directory before we remove the directory, and we've inlined
* what used to be sysfs_rmdir() below, instead of calling separately.
*/
void sysfs_remove_dir(struct kobject * kobj)
{
struct list_head * node, * next;
struct dentry * dentry = dget(kobj->dentry);
struct dentry * parent;
if (!dentry)
return;
pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
parent = dget(dentry->d_parent);
down(&parent->d_inode->i_sem);
down(&dentry->d_inode->i_sem);
list_for_each_safe(node,next,&dentry->d_subdirs) {
struct dentry * d = dget(list_entry(node,struct dentry,d_child));
/**
* Make sure dentry is still there
*/
pr_debug(" o %s: ",d->d_name.name);
if (d->d_inode) {
pr_debug("removing");
/**
* Unlink and unhash.
*/
simple_unlink(dentry->d_inode,d);
d_delete(d);
/**
* Drop reference from initial sysfs_get_dentry().
*/
dput(d);
}
pr_debug(" done (%d)\n",atomic_read(&d->d_count));
/**
* drop reference from dget() above.
*/
dput(d);
}
up(&dentry->d_inode->i_sem);
d_invalidate(dentry);
simple_rmdir(parent->d_inode,dentry);
d_delete(dentry);
pr_debug(" o %s removing done (%d)\n",dentry->d_name.name,
atomic_read(&dentry->d_count));
/**
* Drop reference from initial sysfs_get_dentry().
*/
dput(dentry);
/**
* Drop reference from dget() on entrance.
*/
dput(dentry);
up(&parent->d_inode->i_sem);
dput(parent);
}
EXPORT_SYMBOL(sysfs_create_dir);
EXPORT_SYMBOL(sysfs_remove_dir);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
extern struct vfsmount * sysfs_mount;
extern struct inode * sysfs_new_inode(mode_t mode);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern struct dentry * sysfs_get_dentry(struct dentry *, char *);
extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
......@@ -67,7 +67,8 @@ struct cpufreq_policy {
unsigned int policy; /* see above */
struct cpufreq_governor *governor; /* see below */
struct cpufreq_cpuinfo cpuinfo; /* see above */
struct intf_data intf; /* interface data */
struct device * dev;
struct kobject kobj;
};
#define CPUFREQ_ADJUST (0)
......
This diff is collapsed.
This diff is collapsed.
......@@ -18,6 +18,7 @@
#include <linux/stat.h>
#include <linux/cache.h>
#include <linux/radix-tree.h>
#include <linux/kobject.h>
#include <asm/atomic.h>
struct iovec;
......@@ -353,7 +354,7 @@ struct block_device {
};
struct inode {
struct list_head i_hash;
struct hlist_node i_hash;
struct list_head i_list;
struct list_head i_dentry;
unsigned long i_ino;
......@@ -601,7 +602,7 @@ struct super_block {
struct list_head s_dirty; /* dirty inodes */
struct list_head s_io; /* parked for writeback */
struct list_head s_anon; /* anonymous dentries for (nfs) exporting */
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
struct list_head s_files;
struct block_device *s_bdev;
......@@ -610,6 +611,7 @@ struct super_block {
char s_id[32]; /* Informational name */
struct kobject kobj; /* anchor for sysfs */
void *s_fs_info; /* Filesystem private info */
/*
......@@ -913,6 +915,7 @@ struct export_operations {
struct file_system_type {
const char *name;
struct subsystem subsys;
int fs_flags;
struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
void (*kill_sb) (struct super_block *);
......
......@@ -21,7 +21,7 @@ struct shaper
__u32 bitspersec;
__u32 shapelatency;
__u32 shapeclock;
__u32 recovery; /* Time we can next clock a packet out on
unsigned long recovery; /* Time we can next clock a packet out on
an empty queue */
unsigned long locked;
struct net_device_stats stats;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment