Commit b3f00969 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/sfr
parents 76b23457 ebd158e7
...@@ -72,6 +72,7 @@ Code Seq# Include File Comments ...@@ -72,6 +72,7 @@ Code Seq# Include File Comments
linux/blkpg.h linux/blkpg.h
0x20 all drivers/cdrom/cm206.h 0x20 all drivers/cdrom/cm206.h
0x22 all scsi/sg.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 '1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
<ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/> <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
'6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver '6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 5 PATCHLEVEL = 5
SUBLEVEL = 63 SUBLEVEL = 64
EXTRAVERSION = EXTRAVERSION =
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
obj-y := core.o sys.o interface.o power.o bus.o \ obj-y := core.o sys.o interface.o power.o bus.o \
driver.o class.o intf.o platform.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-$(CONFIG_NUMA) += node.o memblk.o
obj-y += fs/ obj-y += fs/
obj-$(CONFIG_HOTPLUG) += hotplug.o obj-$(CONFIG_HOTPLUG) += hotplug.o
...@@ -544,12 +544,11 @@ void bus_unregister(struct bus_type * bus) ...@@ -544,12 +544,11 @@ void bus_unregister(struct bus_type * bus)
subsystem_unregister(&bus->subsys); subsystem_unregister(&bus->subsys);
} }
static int __init bus_subsys_init(void) int __init buses_init(void)
{ {
return subsystem_register(&bus_subsys); return subsystem_register(&bus_subsys);
} }
core_initcall(bus_subsys_init);
EXPORT_SYMBOL(bus_for_each_dev); EXPORT_SYMBOL(bus_for_each_dev);
EXPORT_SYMBOL(bus_for_each_drv); EXPORT_SYMBOL(bus_for_each_drv);
......
...@@ -266,13 +266,11 @@ void devclass_unregister(struct device_class * cls) ...@@ -266,13 +266,11 @@ void devclass_unregister(struct device_class * cls)
subsystem_unregister(&cls->subsys); subsystem_unregister(&cls->subsys);
} }
static int __init class_subsys_init(void) int __init classes_init(void)
{ {
return subsystem_register(&class_subsys); return subsystem_register(&class_subsys);
} }
core_initcall(class_subsys_init);
EXPORT_SYMBOL(devclass_create_file); EXPORT_SYMBOL(devclass_create_file);
EXPORT_SYMBOL(devclass_remove_file); EXPORT_SYMBOL(devclass_remove_file);
EXPORT_SYMBOL(devclass_register); EXPORT_SYMBOL(devclass_register);
......
...@@ -309,13 +309,11 @@ void device_unregister(struct device * dev) ...@@ -309,13 +309,11 @@ void device_unregister(struct device * dev)
put_device(dev); put_device(dev);
} }
static int __init device_subsys_init(void) int __init devices_init(void)
{ {
return subsystem_register(&devices_subsys); return subsystem_register(&devices_subsys);
} }
core_initcall(device_subsys_init);
EXPORT_SYMBOL(device_initialize); EXPORT_SYMBOL(device_initialize);
EXPORT_SYMBOL(device_add); EXPORT_SYMBOL(device_add);
EXPORT_SYMBOL(device_register); EXPORT_SYMBOL(device_register);
......
...@@ -46,9 +46,8 @@ int __init register_cpu(struct cpu *cpu, int num, struct node *root) ...@@ -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); devclass_register(&cpu_devclass);
return driver_register(&cpu_driver); return driver_register(&cpu_driver);
} }
postcore_initcall(register_cpu_type);
...@@ -19,12 +19,10 @@ void firmware_unregister(struct subsystem * s) ...@@ -19,12 +19,10 @@ void firmware_unregister(struct subsystem * s)
subsystem_unregister(s); subsystem_unregister(s);
} }
static int __init firmware_init(void) int __init firmware_init(void)
{ {
return subsystem_register(&firmware_subsys); return subsystem_register(&firmware_subsys);
} }
core_initcall(firmware_init);
EXPORT_SYMBOL(firmware_register); EXPORT_SYMBOL(firmware_register);
EXPORT_SYMBOL(firmware_unregister); EXPORT_SYMBOL(firmware_unregister);
#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();
}
...@@ -42,8 +42,28 @@ void platform_device_unregister(struct platform_device * pdev) ...@@ -42,8 +42,28 @@ void platform_device_unregister(struct platform_device * pdev)
device_unregister(&pdev->dev); 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) 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; return 0;
} }
...@@ -52,13 +72,11 @@ struct bus_type platform_bus_type = { ...@@ -52,13 +72,11 @@ struct bus_type platform_bus_type = {
.match = platform_match, .match = platform_match,
}; };
static int __init platform_bus_init(void) int __init platform_bus_init(void)
{ {
device_register(&legacy_bus); device_register(&legacy_bus);
return bus_register(&platform_bus_type); return bus_register(&platform_bus_type);
} }
postcore_initcall(platform_bus_init);
EXPORT_SYMBOL(platform_device_register); EXPORT_SYMBOL(platform_device_register);
EXPORT_SYMBOL(platform_device_unregister); EXPORT_SYMBOL(platform_device_unregister);
...@@ -138,13 +138,12 @@ struct bus_type system_bus_type = { ...@@ -138,13 +138,12 @@ struct bus_type system_bus_type = {
.name = "system", .name = "system",
}; };
static int sys_bus_init(void) int __init sys_bus_init(void)
{ {
bus_register(&system_bus_type); bus_register(&system_bus_type);
return device_register(&system_bus); return device_register(&system_bus);
} }
postcore_initcall(sys_bus_init);
EXPORT_SYMBOL(system_bus_type); EXPORT_SYMBOL(system_bus_type);
EXPORT_SYMBOL(sys_device_register); EXPORT_SYMBOL(sys_device_register);
EXPORT_SYMBOL(sys_device_unregister); EXPORT_SYMBOL(sys_device_unregister);
...@@ -18,13 +18,6 @@ obj-$(CONFIG_IEEE1394_CMP) += cmp.o ...@@ -18,13 +18,6 @@ obj-$(CONFIG_IEEE1394_CMP) += cmp.o
clean-files := oui.c 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.o: $(obj)/oui.c
$(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh $(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh
$(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $(obj)/oui.c $(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $(obj)/oui.c
...@@ -74,6 +74,8 @@ ...@@ -74,6 +74,8 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/atomic.h> #include <asm/atomic.h>
...@@ -1262,8 +1264,11 @@ MODULE_LICENSE("GPL"); ...@@ -1262,8 +1264,11 @@ MODULE_LICENSE("GPL");
static int __init amdtp_init_module (void) static int __init amdtp_init_module (void)
{ {
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP, int ret;
THIS_MODULE, &amdtp_fops)) {
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
THIS_MODULE, &amdtp_fops);
if (ret) {
HPSB_ERR("amdtp: unable to get minor device block"); HPSB_ERR("amdtp: unable to get minor device block");
return -EIO; return -EIO;
} }
...@@ -1276,6 +1281,15 @@ static int __init amdtp_init_module (void) ...@@ -1276,6 +1281,15 @@ static int __init amdtp_init_module (void)
return -EIO; 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"); HPSB_INFO("Loaded AMDTP driver");
return 0; return 0;
...@@ -1283,6 +1297,17 @@ static int __init amdtp_init_module (void) ...@@ -1283,6 +1297,17 @@ static int __init amdtp_init_module (void)
static void __exit amdtp_exit_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); hpsb_unregister_highlevel(amdtp_highlevel);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h>
#include "dma.h" #include "dma.h"
/* dma_prog_region */ /* dma_prog_region */
......
...@@ -111,6 +111,8 @@ ...@@ -111,6 +111,8 @@
#include <linux/wrapper.h> #include <linux/wrapper.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
...@@ -2701,7 +2703,7 @@ static void dv1394_remove_host (struct hpsb_host *host) ...@@ -2701,7 +2703,7 @@ static void dv1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci; struct ti_ohci *ohci;
struct video_card *video = NULL; struct video_card *video = NULL;
unsigned long flags; unsigned long flags;
struct list_head *lh; struct list_head *lh, *templh;
char buf[32]; char buf[32];
int n; int n;
...@@ -2715,7 +2717,7 @@ static void dv1394_remove_host (struct hpsb_host *host) ...@@ -2715,7 +2717,7 @@ static void dv1394_remove_host (struct hpsb_host *host)
/* find the corresponding video_cards */ /* find the corresponding video_cards */
spin_lock_irqsave(&dv1394_cards_lock, flags); spin_lock_irqsave(&dv1394_cards_lock, flags);
if(!list_empty(&dv1394_cards)) { 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); video = list_entry(lh, struct video_card, list);
if((video->id >> 2) == ohci->id) if((video->id >> 2) == ohci->id)
dv1394_un_init(video); dv1394_un_init(video);
...@@ -2907,6 +2909,98 @@ static struct hpsb_highlevel_ops hl_ops = { ...@@ -2907,6 +2909,98 @@ static struct hpsb_highlevel_ops hl_ops = {
.host_reset = dv1394_host_reset, .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 ************************************************/ /*** KERNEL MODULE HANDLERS ************************************************/
...@@ -2917,6 +3011,20 @@ MODULE_LICENSE("GPL"); ...@@ -2917,6 +3011,20 @@ MODULE_LICENSE("GPL");
static void __exit dv1394_exit_module(void) 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); hpsb_unregister_highlevel (hl_handle);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
...@@ -2929,14 +3037,18 @@ static void __exit dv1394_exit_module(void) ...@@ -2929,14 +3037,18 @@ static void __exit dv1394_exit_module(void)
static int __init dv1394_init_module(void) static int __init dv1394_init_module(void)
{ {
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394, int ret;
THIS_MODULE, &dv1394_fops)) {
ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
THIS_MODULE, &dv1394_fops);
if (ret) {
printk(KERN_ERR "dv1394: unable to register character device\n"); printk(KERN_ERR "dv1394: unable to register character device\n");
return -EIO; return -EIO;
} }
#ifdef CONFIG_DEVFS_FS #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"); printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
return -ENOMEM; return -ENOMEM;
...@@ -2944,7 +3056,8 @@ static int __init dv1394_init_module(void) ...@@ -2944,7 +3056,8 @@ static int __init dv1394_init_module(void)
#endif #endif
#ifdef CONFIG_PROC_FS #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"); printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
...@@ -2967,9 +3080,23 @@ static int __init dv1394_init_module(void) ...@@ -2967,9 +3080,23 @@ static int __init dv1394_init_module(void)
return -ENOMEM; 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; return 0;
} }
module_init(dv1394_init_module); module_init(dv1394_init_module);
module_exit(dv1394_exit_module); module_exit(dv1394_exit_module);
This diff is collapsed.
...@@ -30,9 +30,16 @@ ...@@ -30,9 +30,16 @@
#define ETHER1394_REGION_ADDR 0xfffff0200000ULL #define ETHER1394_REGION_ADDR 0xfffff0200000ULL
#define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN) #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 */ /* Node set == 64 */
#define NODE_SET (ALL_NODES + 1) #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 */ /* Private structure for our ethernet driver */
struct eth1394_priv { struct eth1394_priv {
struct net_device_stats stats; /* Device stats */ struct net_device_stats stats; /* Device stats */
...@@ -43,6 +50,9 @@ struct eth1394_priv { ...@@ -43,6 +50,9 @@ struct eth1394_priv {
u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */ u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */
u64 eui[ALL_NODES]; /* EUI-64 per node */ u64 eui[ALL_NODES]; /* EUI-64 per node */
spinlock_t lock; /* Private lock */ 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 { struct host_info {
...@@ -51,12 +61,15 @@ struct host_info { ...@@ -51,12 +61,15 @@ struct host_info {
struct net_device *dev; 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. */ /* This is our task struct. It's used for the packet complete callback. */
struct packet_task { struct packet_task {
struct sk_buff *skb; /* Socket buffer we are sending */ struct sk_buff *skb; /* Socket buffer we are sending */
nodeid_t dest_node; /* Destination of the packet */ nodeid_t dest_node; /* Destination of the packet */
u64 addr; /* Address */ u64 addr; /* Address */
struct hpsb_queue_struct tq; /* The task */ struct hpsb_queue_struct tq; /* The task */
eth1394_tx_type tx_type; /* Send data via GASP or Write Req. */
}; };
/* IP1394 headers */ /* IP1394 headers */
......
...@@ -71,9 +71,6 @@ int hpsb_ref_host(struct hpsb_host *host) ...@@ -71,9 +71,6 @@ int hpsb_ref_host(struct hpsb_host *host)
list_for_each(lh, &hosts) { list_for_each(lh, &hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) { if (host == list_entry(lh, struct hpsb_host, host_list)) {
if (try_module_get(host->driver->owner)) { 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++; host->refcount++;
retval = 1; retval = 1;
} }
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#ifndef __IEEE1394_IOCTL_H #ifndef __IEEE1394_IOCTL_H
#define __IEEE1394_IOCTL_H #define __IEEE1394_IOCTL_H
#include <asm/ioctl.h> #include <linux/ioctl.h>
#include <asm/types.h> #include <linux/types.h>
/* AMDTP Gets 6 */ /* AMDTP Gets 6 */
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \ #define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \
_IOW ('#', 0x23, unsigned char) _IOW ('#', 0x23, unsigned char)
#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \ #define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \
_IOW ('#', 0x24, u64) _IOW ('#', 0x24, __u64)
#define RAW1394_IOC_ISO_RECV_PACKETS \ #define RAW1394_IOC_ISO_RECV_PACKETS \
_IOW ('#', 0x25, struct raw1394_iso_packets) _IOW ('#', 0x25, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \ #define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \
......
...@@ -361,7 +361,7 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid) ...@@ -361,7 +361,7 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
host->topology_map[host->selfid_count++] = sid; host->topology_map[host->selfid_count++] = sid;
} else { } else {
HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d", 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) ...@@ -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() */ /* irm_id is kept up to date by check_selfids() */
if (host->irm_id == host->node_id) { if (host->irm_id == host->node_id) {
host->is_irm = 1; host->is_irm = 1;
host->is_busmgr = 1;
host->busmgr_id = host->node_id;
host->csr.bus_manager_id = host->node_id;
} else { } else {
host->is_busmgr = 0; host->is_busmgr = 0;
host->is_irm = 0; host->is_irm = 0;
...@@ -535,8 +532,8 @@ int hpsb_send_packet(struct hpsb_packet *packet) ...@@ -535,8 +532,8 @@ int hpsb_send_packet(struct hpsb_packet *packet)
if (packet->type == hpsb_async && packet->node_id != ALL_NODES) { if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
packet->speed_code = packet->speed_code =
host->speed_map[(host->node_id & NODE_MASK) * 64 host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+ (packet->node_id & NODE_MASK)]; + NODEID_TO_NODE(packet->node_id)];
} }
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
...@@ -748,7 +745,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, ...@@ -748,7 +745,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
addr, 4, flags); addr, 4, flags);
if (!write_acked if (!write_acked
&& (((data[0] >> 16) & NODE_MASK) != NODE_MASK) && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) { && (rcode >= 0)) {
/* not a broadcast write, reply */ /* not a broadcast write, reply */
PREP_REPLY_PACKET(0); PREP_REPLY_PACKET(0);
...@@ -763,7 +760,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, ...@@ -763,7 +760,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
addr, data[3]>>16, flags); addr, data[3]>>16, flags);
if (!write_acked if (!write_acked
&& (((data[0] >> 16) & NODE_MASK) != NODE_MASK) && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) { && (rcode >= 0)) {
/* not a broadcast write, reply */ /* not a broadcast write, reply */
PREP_REPLY_PACKET(0); PREP_REPLY_PACKET(0);
...@@ -1248,6 +1245,7 @@ EXPORT_SYMBOL(hpsb_read); ...@@ -1248,6 +1245,7 @@ EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_lock); EXPORT_SYMBOL(hpsb_lock);
EXPORT_SYMBOL(hpsb_lock64); EXPORT_SYMBOL(hpsb_lock64);
EXPORT_SYMBOL(hpsb_send_gasp);
EXPORT_SYMBOL(hpsb_packet_success); EXPORT_SYMBOL(hpsb_packet_success);
/** highlevel.c **/ /** highlevel.c **/
......
...@@ -98,6 +98,17 @@ static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data) ...@@ -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 */ 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 * hpsb_get_tlabel - allocate a transaction label
...@@ -495,7 +506,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, ...@@ -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, int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg) 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, ...@@ -558,3 +568,58 @@ int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return retval; 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, ...@@ -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); u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, octlet_t *data, octlet_t arg); 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 */ #endif /* _IEEE1394_TRANSACTIONS_H */
...@@ -97,14 +97,17 @@ typedef u64 nodeaddr_t; ...@@ -97,14 +97,17 @@ typedef u64 nodeaddr_t;
typedef u16 arm_length_t; typedef u16 arm_length_t;
#define BUS_MASK 0xffc0 #define BUS_MASK 0xffc0
#define BUS_SHIFT 6
#define NODE_MASK 0x003f #define NODE_MASK 0x003f
#define LOCAL_BUS 0xffc0 #define LOCAL_BUS 0xffc0
#define ALL_NODES 0x003f #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. */ /* Can be used to consistently print a node/bus ID. */
#define NODE_BUS_FMT "%02d:%04d" #define NODE_BUS_FMT "%02d:%04d"
#define NODE_BUS_ARGS(nodeid) \ #define NODE_BUS_ARGS(nodeid) NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid)
(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args) #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) ...@@ -1210,6 +1210,52 @@ static void nodemgr_node_probe(struct hpsb_host *host)
return; 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) static int nodemgr_host_thread(void *__hi)
{ {
struct host_info *hi = (struct host_info *)__hi; struct host_info *hi = (struct host_info *)__hi;
...@@ -1222,7 +1268,16 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1222,7 +1268,16 @@ static int nodemgr_host_thread(void *__hi)
* happens when we get a bus reset. */ * happens when we get a bus reset. */
while (!down_interruptible(&hi->reset_sem) && while (!down_interruptible(&hi->reset_sem) &&
!down_interruptible(&nodemgr_serialize)) { !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_node_probe(hi->host);
nodemgr_do_irm_duties(hi->host);
up(&nodemgr_serialize); up(&nodemgr_serialize);
} }
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
......
...@@ -31,9 +31,9 @@ ...@@ -31,9 +31,9 @@
* *
* Things implemented, but still in test phase: * Things implemented, but still in test phase:
* . Iso Transmit * . Iso Transmit
* . Async Stream Packets Transmit (Receive done via Iso interface)
* *
* Things not implemented: * Things not implemented:
* . Async Stream Packets
* . DMA error recovery * . DMA error recovery
* *
* Known bugs: * Known bugs:
...@@ -160,7 +160,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) ...@@ -160,7 +160,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 762 $ Ben Collins <bcollins@debian.org>"; "$Rev: 801 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */ /* Module Parameters */
MODULE_PARM(phys_dma,"i"); MODULE_PARM(phys_dma,"i");
...@@ -649,18 +649,31 @@ static void insert_packet(struct ti_ohci *ohci, ...@@ -649,18 +649,31 @@ static void insert_packet(struct ti_ohci *ohci,
} else { } else {
d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
(packet->header[0] & 0xFFFF); (packet->header[0] & 0xFFFF);
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] = d->prg_cpu[idx]->data[1] =
(packet->header[1] & 0xFFFF) | (packet->header[1] & 0xFFFF) |
(packet->header[0] & 0xFFFF0000); (packet->header[0] & 0xFFFF0000);
d->prg_cpu[idx]->data[2] = packet->header[2]; d->prg_cpu[idx]->data[2] = packet->header[2];
d->prg_cpu[idx]->data[3] = packet->header[3]; d->prg_cpu[idx]->data[3] = packet->header[3];
}
packet_swab(d->prg_cpu[idx]->data, packet->tcode); packet_swab(d->prg_cpu[idx]->data, packet->tcode);
} }
if (packet->data_size) { /* block transmit */ if (packet->data_size) { /* block transmit */
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 = d->prg_cpu[idx]->begin.control =
cpu_to_le32(DMA_CTL_OUTPUT_MORE | cpu_to_le32(DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 0x10); DMA_CTL_IMMEDIATE | 0x10);
}
d->prg_cpu[idx]->end.control = d->prg_cpu[idx]->end.control =
cpu_to_le32(DMA_CTL_OUTPUT_LAST | cpu_to_le32(DMA_CTL_OUTPUT_LAST |
DMA_CTL_IRQ | DMA_CTL_IRQ |
...@@ -830,7 +843,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) ...@@ -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 */ /* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw) if (packet->type == hpsb_raw)
d = &ohci->at_req_context; 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 /* The legacy IT DMA context is initialized on first
* use. However, the alloc cannot be run from * use. However, the alloc cannot be run from
* interrupt context, so we bail out if that is the * 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) ...@@ -856,7 +869,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
} }
d = &ohci->it_legacy_context; 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; d = &ohci->at_resp_context;
else else
d = &ohci->at_req_context; d = &ohci->at_req_context;
...@@ -1295,6 +1308,8 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso) ...@@ -1295,6 +1308,8 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
u32 *prev_branch = NULL; u32 *prev_branch = NULL;
for (blk = 0; blk < recv->nblocks; blk++) { for (blk = 0; blk < recv->nblocks; blk++) {
u32 control;
/* the DMA descriptor */ /* the DMA descriptor */
struct dma_cmd *cmd = &recv->block[blk]; struct dma_cmd *cmd = &recv->block[blk];
...@@ -1305,29 +1320,29 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso) ...@@ -1305,29 +1320,29 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso)
unsigned long buf_offset = blk * recv->buf_stride; unsigned long buf_offset = blk * recv->buf_stride;
if (recv->dma_mode == BUFFER_FILL_MODE) { if (recv->dma_mode == BUFFER_FILL_MODE) {
cmd->control = 2 << 28; /* INPUT_MORE */ control = 2 << 28; /* INPUT_MORE */
} else { } 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 */ /* interrupt on last block, and at intervals */
if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) { 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 */ control |= 3 << 18; /* enable branch to address */
cmd->control |= recv->buf_stride; 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->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 */ /* link the previous descriptor to this one */
if (prev_branch) { if (prev_branch) {
*prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset); *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
*prev_branch |= 1; /* set Z=1 */
} }
prev_branch = &cmd->branchAddress; prev_branch = &cmd->branchAddress;
...@@ -1485,18 +1500,18 @@ static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block) ...@@ -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, /* 'next' becomes the new end of the DMA chain,
so disable branch and enable interrupt */ so disable branch and enable interrupt */
next->branchAddress = 0; next->branchAddress = 0;
next->control |= 3 << 20; next->control |= cpu_to_le32(3 << 20);
/* link prev to next */ /* link prev to next */
prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog, prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog,
sizeof(struct dma_cmd) * next_i) sizeof(struct dma_cmd) * next_i)
| 1; /* Z=1 */ | 1); /* Z=1 */
/* disable interrupt on previous DMA descriptor, except at intervals */ /* disable interrupt on previous DMA descriptor, except at intervals */
if((prev_i % recv->block_irq_interval) == 0) { if((prev_i % recv->block_irq_interval) == 0) {
prev->control |= 3 << 20; /* enable interrupt */ prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
} else { } else {
prev->control &= ~(3<<20); /* disable interrupt */ prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
} }
wmb(); wmb();
...@@ -1720,8 +1735,8 @@ static void ohci_iso_recv_packetperbuf_task(unsigned long data) ...@@ -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; struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
/* check the DMA descriptor for new writes to xferStatus */ /* check the DMA descriptor for new writes to xferStatus */
u16 xferstatus = il->status >> 16; u16 xferstatus = le32_to_cpu(il->status) >> 16;
u16 rescount = il->status & 0xFFFF; u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
unsigned char event = xferstatus & 0x1F; unsigned char event = xferstatus & 0x1F;
...@@ -1903,7 +1918,7 @@ static void ohci_iso_xmit_task(unsigned long data) ...@@ -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); struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
/* check for new writes to xferStatus */ /* 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; u8 event = xferstatus & 0x1F;
if(!event) { if(!event) {
...@@ -1919,7 +1934,7 @@ static void ohci_iso_xmit_task(unsigned long data) ...@@ -1919,7 +1934,7 @@ static void ohci_iso_xmit_task(unsigned long data)
wake = 1; wake = 1;
/* parse cycle */ /* 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 */ /* tell the subsystem the packet has gone out */
hpsb_iso_packet_sent(iso, cycle, event != 0x11); 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 ...@@ -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 */ /* set up the OUTPUT_MORE_IMMEDIATE descriptor */
memset(next, 0, sizeof(struct iso_xmit_cmd)); 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 */ /* 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 ...@@ -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; next->iso_hdr[7] = len >> 8;
/* set up the OUTPUT_LAST */ /* set up the OUTPUT_LAST */
next->output_last.control = 1 << 28; next->output_last.control = cpu_to_le32(1 << 28);
next->output_last.control |= 1 << 27; /* update timeStamp */ next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
next->output_last.control |= 3 << 20; /* want interrupt */ next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
next->output_last.control |= 3 << 18; /* enable branch */ next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
next->output_last.control |= len; next->output_last.control |= cpu_to_le32(len);
/* payload bus address */ /* 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 */ /* leave branchAddress at zero for now */
/* re-write the previous DMA descriptor to chain to this one */ /* re-write the previous DMA descriptor to chain to this one */
/* set prev branch address to point to next (Z=3) */ /* set prev branch address to point to next (Z=3) */
prev->output_last.branchAddress = prev->output_last.branchAddress = cpu_to_le32(
dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3; dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
/* disable interrupt, unless required by the IRQ interval */ /* disable interrupt, unless required by the IRQ interval */
if(prev_i % iso->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 { } else {
prev->output_last.control |= 3 << 20; /* enable interrupt */ prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
} }
wmb(); wmb();
...@@ -3474,7 +3489,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) ...@@ -3474,7 +3489,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
{ {
.class = PCI_CLASS_FIREWIRE_OHCI, .class = PCI_CLASS_FIREWIRE_OHCI,
.class_mask = 0x00ffffff, .class_mask = ~0,
.vendor = PCI_ANY_ID, .vendor = PCI_ANY_ID,
.device = PCI_ANY_ID, .device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
......
...@@ -238,7 +238,7 @@ static void remove_host(struct hpsb_host *host) ...@@ -238,7 +238,7 @@ static void remove_host(struct hpsb_host *host)
list_del(&hi->list); list_del(&hi->list);
host_count--; host_count--;
/* /*
FIXME: addressranges should be removed FIXME: address ranges should be removed
and fileinfo states should be initialized and fileinfo states should be initialized
(including setting generation to (including setting generation to
internal-generation ...) internal-generation ...)
...@@ -281,8 +281,8 @@ static void host_reset(struct hpsb_host *host) ...@@ -281,8 +281,8 @@ static void host_reset(struct hpsb_host *host)
req->req.misc = (host->node_id << 16) req->req.misc = (host->node_id << 16)
| host->node_count; | host->node_count;
if (fi->protocol_version > 3) { if (fi->protocol_version > 3) {
req->req.misc |= ((host->irm_id req->req.misc |= (NODEID_TO_NODE(host->irm_id)
& NODE_MASK) << 8); << 8);
} }
queue_complete_req(req); queue_complete_req(req);
...@@ -571,8 +571,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *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) req->req.misc = (fi->host->node_id << 16)
| fi->host->node_count; | fi->host->node_count;
if (fi->protocol_version > 3) { if (fi->protocol_version > 3) {
req->req.misc |= req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
(fi->host->irm_id & NODE_MASK) << 8;
} }
} else { } else {
req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.error = RAW1394_ERROR_INVALID_ARG;
......
This diff is collapsed.
...@@ -22,15 +22,6 @@ ...@@ -22,15 +22,6 @@
#ifndef SBP2_H #ifndef SBP2_H
#define 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" #define SBP2_DEVICE_NAME "sbp2"
/* /*
...@@ -442,8 +433,6 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i ...@@ -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 void sbp2_add_host(struct hpsb_host *host);
static struct sbp2scsi_host_info *sbp2_find_host_info(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); 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 int sbp2_probe(struct unit_directory *ud);
static void sbp2_disconnect(struct unit_directory *ud); static void sbp2_disconnect(struct unit_directory *ud);
static void sbp2_update(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); ...@@ -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_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); 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 */ #endif /* SBP2_H */
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ioctl32.h>
#include <linux/compat.h>
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
...@@ -1338,8 +1340,133 @@ MODULE_DESCRIPTION("driver for digital video on OHCI board"); ...@@ -1338,8 +1340,133 @@ MODULE_DESCRIPTION("driver for digital video on OHCI board");
MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME); MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
MODULE_LICENSE("GPL"); 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) 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); hpsb_unregister_highlevel (hl_handle);
devfs_unregister(devfs_handle); devfs_unregister(devfs_handle);
...@@ -1350,8 +1477,11 @@ static void __exit video1394_exit_module (void) ...@@ -1350,8 +1477,11 @@ static void __exit video1394_exit_module (void)
static int __init video1394_init_module (void) static int __init video1394_init_module (void)
{ {
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394, int ret;
THIS_MODULE, &video1394_fops)) {
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"); PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
return -EIO; return -EIO;
} }
...@@ -1366,9 +1496,32 @@ static int __init video1394_init_module (void) ...@@ -1366,9 +1496,32 @@ static int __init video1394_init_module (void)
return -ENOMEM; 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"); PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
return 0; return 0;
} }
module_init(video1394_init_module); module_init(video1394_init_module);
module_exit(video1394_exit_module); module_exit(video1394_exit_module);
...@@ -981,7 +981,7 @@ dgrs_download(struct net_device *dev0) ...@@ -981,7 +981,7 @@ dgrs_download(struct net_device *dev0)
{ {
DGRS_PRIV *priv0 = (DGRS_PRIV *) dev0->priv; DGRS_PRIV *priv0 = (DGRS_PRIV *) dev0->priv;
int is; int is;
int i; unsigned long i;
static int iv2is[16] = { static int iv2is[16] = {
0, 0, 0, ES4H_IS_INT3, 0, 0, 0, ES4H_IS_INT3,
...@@ -1140,7 +1140,7 @@ int __init ...@@ -1140,7 +1140,7 @@ int __init
dgrs_probe1(struct net_device *dev) dgrs_probe1(struct net_device *dev)
{ {
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv; DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
int i; unsigned long i;
int rc; int rc;
printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n", printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n",
......
...@@ -88,10 +88,10 @@ ...@@ -88,10 +88,10 @@
#include <net/arp.h> #include <net/arp.h>
struct shaper_cb { struct shaper_cb {
unsigned long shapeclock; /* Time it should go out */
unsigned long shapestamp; /* Stamp for shaper */
__u32 shapelatency; /* Latency on frame */ __u32 shapelatency; /* Latency on frame */
__u32 shapeclock; /* Time it should go out */
__u32 shapelen; /* Frame length in clocks */ __u32 shapelen; /* Frame length in clocks */
__u32 shapestamp; /* Stamp for shaper */
__u16 shapepend; /* Pending */ __u16 shapepend; /* Pending */
}; };
#define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb)) #define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb))
...@@ -335,7 +335,7 @@ static void shaper_kick(struct shaper *shaper) ...@@ -335,7 +335,7 @@ static void shaper_kick(struct shaper *shaper)
*/ */
if(sh_debug) 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)) 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) ...@@ -509,7 +509,7 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
{ {
struct sis900_private * sis_priv = net_dev->priv; struct sis900_private * sis_priv = net_dev->priv;
u16 poll_bit = MII_STAT_LINK, status = 0; u16 poll_bit = MII_STAT_LINK, status = 0;
unsigned int timeout = jiffies + 5 * HZ; unsigned long timeout = jiffies + 5 * HZ;
int phy_addr; int phy_addr;
u8 revision; u8 revision;
......
...@@ -694,7 +694,7 @@ static inline void isp2x00_disable_irqs(struct Scsi_Host *host) ...@@ -694,7 +694,7 @@ static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
int isp2x00_detect(Scsi_Host_Template * tmpt) int isp2x00_detect(Scsi_Host_Template * tmpt)
{ {
int hosts = 0; int hosts = 0;
int wait_time; unsigned long wait_time;
struct Scsi_Host *host = NULL; struct Scsi_Host *host = NULL;
struct isp2x00_hostdata *hostdata; struct isp2x00_hostdata *hostdata;
struct pci_dev *pdev; struct pci_dev *pdev;
......
...@@ -47,16 +47,8 @@ static kmem_cache_t *dentry_cache; ...@@ -47,16 +47,8 @@ static kmem_cache_t *dentry_cache;
static unsigned int d_hash_mask; static unsigned int d_hash_mask;
static unsigned int d_hash_shift; static unsigned int d_hash_shift;
static struct list_head *dentry_hashtable; static struct hlist_head *dentry_hashtable;
static LIST_HEAD(dentry_unused); 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. */ /* Statistics gathering. */
struct dentry_stat_t dentry_stat = { struct dentry_stat_t dentry_stat = {
...@@ -292,6 +284,7 @@ struct dentry * d_find_alias(struct inode *inode) ...@@ -292,6 +284,7 @@ struct dentry * d_find_alias(struct inode *inode)
while (next != head) { while (next != head) {
tmp = next; tmp = next;
next = tmp->next; next = tmp->next;
prefetch(next);
alias = list_entry(tmp, struct dentry, d_alias); alias = list_entry(tmp, struct dentry, d_alias);
if (!d_unhashed(alias)) { if (!d_unhashed(alias)) {
if (alias->d_flags & DCACHE_DISCONNECTED) if (alias->d_flags & DCACHE_DISCONNECTED)
...@@ -378,6 +371,7 @@ static void prune_dcache(int count) ...@@ -378,6 +371,7 @@ static void prune_dcache(int count)
if (tmp == &dentry_unused) if (tmp == &dentry_unused)
break; break;
list_del_init(tmp); list_del_init(tmp);
prefetch(dentry_unused.prev);
dentry_stat.nr_unused--; dentry_stat.nr_unused--;
dentry = list_entry(tmp, struct dentry, d_lru); dentry = list_entry(tmp, struct dentry, d_lru);
...@@ -603,15 +597,15 @@ void shrink_dcache_parent(struct dentry * parent) ...@@ -603,15 +597,15 @@ void shrink_dcache_parent(struct dentry * parent)
* done under dcache_lock. * 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; int found;
do { do {
found = 0; found = 0;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
list_for_each(lp, head) { hlist_for_each(lp, head) {
struct dentry *this = list_entry(lp, struct dentry, d_hash); struct dentry *this = hlist_entry(lp, struct dentry, d_hash);
list_del(&this->d_lru); list_del(&this->d_lru);
/* don't add non zero d_count dentries /* don't add non zero d_count dentries
...@@ -727,7 +721,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) ...@@ -727,7 +721,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
dentry->d_mounted = 0; dentry->d_mounted = 0;
dentry->d_cookie = NULL; dentry->d_cookie = NULL;
dentry->d_bucket = 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_lru);
INIT_LIST_HEAD(&dentry->d_subdirs); INIT_LIST_HEAD(&dentry->d_subdirs);
INIT_LIST_HEAD(&dentry->d_alias); INIT_LIST_HEAD(&dentry->d_alias);
...@@ -797,7 +791,7 @@ struct dentry * d_alloc_root(struct inode * root_inode) ...@@ -797,7 +791,7 @@ struct dentry * d_alloc_root(struct inode * root_inode)
return res; 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 += (unsigned long) parent / L1_CACHE_BYTES;
hash = hash ^ (hash >> D_HASHBITS); hash = hash ^ (hash >> D_HASHBITS);
...@@ -860,7 +854,7 @@ struct dentry * d_alloc_anon(struct inode *inode) ...@@ -860,7 +854,7 @@ struct dentry * d_alloc_anon(struct inode *inode)
res->d_flags |= DCACHE_DISCONNECTED; res->d_flags |= DCACHE_DISCONNECTED;
res->d_vfs_flags &= ~DCACHE_UNHASHED; res->d_vfs_flags &= ~DCACHE_UNHASHED;
list_add(&res->d_alias, &inode->i_dentry); 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); spin_unlock(&res->d_lock);
} }
inode = NULL; /* don't drop reference */ inode = NULL; /* don't drop reference */
...@@ -947,21 +941,21 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name) ...@@ -947,21 +941,21 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
unsigned int len = name->len; unsigned int len = name->len;
unsigned int hash = name->hash; unsigned int hash = name->hash;
const unsigned char *str = name->name; 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 dentry *found = NULL;
struct list_head *tmp; struct hlist_node *node;
int lookup_count = 0;
rcu_read_lock(); rcu_read_lock();
/* lookup is terminated when flow reaches any bucket head */ hlist_for_each (node, head) {
for(tmp = head->next; !is_bucket(tmp); tmp = tmp->next) {
struct dentry *dentry; struct dentry *dentry;
unsigned long move_count; unsigned long move_count;
struct qstr * qstr; struct qstr * qstr;
prefetch(node->next);
smp_read_barrier_depends(); 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 /* if lookup ends up in a different bucket
* due to concurrent rename, fail it * due to concurrent rename, fail it
...@@ -969,12 +963,6 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name) ...@@ -969,12 +963,6 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
if (unlikely(dentry->d_bucket != head)) if (unlikely(dentry->d_bucket != head))
break; 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 * We must take a snapshot of d_move_count followed by
* read memory barrier before any search key comparison * read memory barrier before any search key comparison
...@@ -1034,7 +1022,8 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) ...@@ -1034,7 +1022,8 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
unsigned long dent_addr = (unsigned long) dentry; unsigned long dent_addr = (unsigned long) dentry;
unsigned long min_addr = PAGE_OFFSET; unsigned long min_addr = PAGE_OFFSET;
unsigned long align_mask = 0x0F; unsigned long align_mask = 0x0F;
struct list_head *base, *lhp; struct hlist_head *base;
struct hlist_node *lhp;
if (dent_addr < min_addr) if (dent_addr < min_addr)
goto out; goto out;
...@@ -1050,12 +1039,13 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) ...@@ -1050,12 +1039,13 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
goto out; goto out;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
lhp = base = d_hash(dparent, dentry->d_name.hash); base = d_hash(dparent, dentry->d_name.hash);
while ((lhp = lhp->next) != base) { hlist_for_each(lhp,base) {
prefetch(lhp->next);
/* read_barrier_depends() not required for d_hash list /* read_barrier_depends() not required for d_hash list
* as it is parsed under dcache_lock * 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); __dget_locked(dentry);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
return 1; return 1;
...@@ -1116,12 +1106,11 @@ void d_delete(struct dentry * dentry) ...@@ -1116,12 +1106,11 @@ void d_delete(struct dentry * dentry)
void d_rehash(struct dentry * entry) 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); spin_lock(&dcache_lock);
if (!list_empty(&entry->d_hash) && !d_unhashed(entry)) BUG();
entry->d_vfs_flags &= ~DCACHE_UNHASHED; entry->d_vfs_flags &= ~DCACHE_UNHASHED;
entry->d_bucket = list; entry->d_bucket = list;
list_add_rcu(&entry->d_hash, list); hlist_add_head_rcu(&entry->d_hash, list);
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
} }
...@@ -1174,10 +1163,6 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target) ...@@ -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 * We could be nicer about the deleted file, and let it show
* up under the name it got deleted rather than the name that * up under the name it got deleted rather than the name that
* deleted it. * 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) ...@@ -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 */ /* Move the dentry to the target hash queue, if on different bucket */
if (dentry->d_bucket != target->d_bucket) { if (dentry->d_bucket != target->d_bucket) {
dentry->d_bucket = target->d_bucket; dentry->d_bucket = target->d_bucket;
list_del_rcu(&dentry->d_hash); hlist_del_rcu(&dentry->d_hash);
list_add_rcu(&dentry->d_hash, &target->d_hash); hlist_add_head_rcu(&dentry->d_hash, target->d_bucket);
} }
/* Unhash the target: dput() will then get rid of it */ /* Unhash the target: dput() will then get rid of it */
...@@ -1284,6 +1269,7 @@ static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt, ...@@ -1284,6 +1269,7 @@ static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
continue; continue;
} }
parent = dentry->d_parent; parent = dentry->d_parent;
prefetch(parent);
namelen = dentry->d_name.len; namelen = dentry->d_name.len;
buflen -= namelen + 1; buflen -= namelen + 1;
if (buflen < 0) if (buflen < 0)
...@@ -1503,7 +1489,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name) ...@@ -1503,7 +1489,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
static void __init dcache_init(unsigned long mempages) static void __init dcache_init(unsigned long mempages)
{ {
struct list_head *d; struct hlist_head *d;
unsigned long order; unsigned long order;
unsigned int nr_hash; unsigned int nr_hash;
int i; int i;
...@@ -1524,15 +1510,12 @@ static void __init dcache_init(unsigned long mempages) ...@@ -1524,15 +1510,12 @@ static void __init dcache_init(unsigned long mempages)
if (!dentry_cache) if (!dentry_cache)
panic("Cannot create 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); set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
#if PAGE_SHIFT < 13 #if PAGE_SHIFT < 13
mempages >>= (13 - PAGE_SHIFT); mempages >>= (13 - PAGE_SHIFT);
#endif #endif
mempages *= sizeof(struct list_head); mempages *= sizeof(struct hlist_head);
for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
; ;
...@@ -1540,7 +1523,7 @@ static void __init dcache_init(unsigned long mempages) ...@@ -1540,7 +1523,7 @@ static void __init dcache_init(unsigned long mempages)
unsigned long tmp; unsigned long tmp;
nr_hash = (1UL << order) * PAGE_SIZE / nr_hash = (1UL << order) * PAGE_SIZE /
sizeof(struct list_head); sizeof(struct hlist_head);
d_hash_mask = (nr_hash - 1); d_hash_mask = (nr_hash - 1);
tmp = nr_hash; tmp = nr_hash;
...@@ -1548,7 +1531,7 @@ static void __init dcache_init(unsigned long mempages) ...@@ -1548,7 +1531,7 @@ static void __init dcache_init(unsigned long mempages)
while ((tmp >>= 1UL) != 0UL) while ((tmp >>= 1UL) != 0UL)
d_hash_shift++; d_hash_shift++;
dentry_hashtable = (struct list_head *) dentry_hashtable = (struct hlist_head *)
__get_free_pages(GFP_ATOMIC, order); __get_free_pages(GFP_ATOMIC, order);
} while (dentry_hashtable == NULL && --order >= 0); } while (dentry_hashtable == NULL && --order >= 0);
...@@ -1558,12 +1541,10 @@ static void __init dcache_init(unsigned long mempages) ...@@ -1558,12 +1541,10 @@ static void __init dcache_init(unsigned long mempages)
if (!dentry_hashtable) if (!dentry_hashtable)
panic("Failed to allocate dcache hash table\n"); panic("Failed to allocate dcache hash table\n");
hashtable_end = dentry_hashtable + nr_hash;
d = dentry_hashtable; d = dentry_hashtable;
i = nr_hash; i = nr_hash;
do { do {
INIT_LIST_HEAD(d); INIT_HLIST_HEAD(d);
d++; d++;
i--; i--;
} while (i); } while (i);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -58,6 +59,38 @@ static struct file_system_type **find_filesystem(const char *name) ...@@ -58,6 +59,38 @@ static struct file_system_type **find_filesystem(const char *name)
return p; 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 * register_filesystem - register a new filesystem
* @fs: the file system structure * @fs: the file system structure
...@@ -88,6 +121,14 @@ int register_filesystem(struct file_system_type * fs) ...@@ -88,6 +121,14 @@ int register_filesystem(struct file_system_type * fs)
else else
*p = fs; *p = fs;
write_unlock(&file_systems_lock); 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; return res;
} }
...@@ -105,21 +146,44 @@ int register_filesystem(struct file_system_type * fs) ...@@ -105,21 +146,44 @@ int register_filesystem(struct file_system_type * fs)
int unregister_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); res = unlink_fs(fs);
tmp = &file_systems; if (!res)
while (*tmp) { subsystem_unregister(&fs->subsys);
if (fs == *tmp) { return res;
*tmp = fs->next; }
fs->next = NULL;
write_unlock(&file_systems_lock); extern int sysfs_init(void);
return 0;
} /**
tmp = &(*tmp)->next; * fs_subsys_init - initialize sysfs and fs subsystem.
} *
write_unlock(&file_systems_lock); * In order to register filesystems in sysfs, it has to be
return -EINVAL; * 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) static int fs_index(const char * __name)
......
...@@ -90,7 +90,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) ...@@ -90,7 +90,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
* Only add valid (hashed) inodes to the superblock's * Only add valid (hashed) inodes to the superblock's
* dirty list. Add blockdev inodes as well. * 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; goto out;
/* /*
......
...@@ -189,7 +189,7 @@ void truncate_hugepages(struct address_space *mapping, loff_t lstart) ...@@ -189,7 +189,7 @@ void truncate_hugepages(struct address_space *mapping, loff_t lstart)
static void hugetlbfs_delete_inode(struct inode *inode) 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); list_del_init(&inode->i_list);
inode->i_state |= I_FREEING; inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--; inodes_stat.nr_inodes--;
...@@ -208,7 +208,7 @@ static void hugetlbfs_forget_inode(struct inode *inode) ...@@ -208,7 +208,7 @@ static void hugetlbfs_forget_inode(struct inode *inode)
{ {
struct super_block *super_block = inode->i_sb; struct super_block *super_block = inode->i_sb;
if (list_empty(&inode->i_hash)) if (hlist_unhashed(&inode->i_hash))
goto out_truncate; goto out_truncate;
if (!(inode->i_state & (I_DIRTY|I_LOCK))) { if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
...@@ -223,7 +223,7 @@ static void hugetlbfs_forget_inode(struct inode *inode) ...@@ -223,7 +223,7 @@ static void hugetlbfs_forget_inode(struct inode *inode)
/* write_inode_now() ? */ /* write_inode_now() ? */
inodes_stat.nr_unused--; inodes_stat.nr_unused--;
list_del_init(&inode->i_hash); hlist_del_init(&inode->i_hash);
out_truncate: out_truncate:
list_del_init(&inode->i_list); list_del_init(&inode->i_list);
inode->i_state |= I_FREEING; inode->i_state |= I_FREEING;
......
...@@ -69,8 +69,8 @@ static unsigned int i_hash_shift; ...@@ -69,8 +69,8 @@ static unsigned int i_hash_shift;
LIST_HEAD(inode_in_use); LIST_HEAD(inode_in_use);
LIST_HEAD(inode_unused); LIST_HEAD(inode_unused);
static struct list_head *inode_hashtable; static struct hlist_head *inode_hashtable;
static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */ static HLIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */
/* /*
* A simple spinlock to protect the list manipulations. * A simple spinlock to protect the list manipulations.
...@@ -172,7 +172,7 @@ void destroy_inode(struct inode *inode) ...@@ -172,7 +172,7 @@ void destroy_inode(struct inode *inode)
void inode_init_once(struct inode *inode) void inode_init_once(struct inode *inode)
{ {
memset(inode, 0, sizeof(*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.clean_pages);
INIT_LIST_HEAD(&inode->i_data.dirty_pages); INIT_LIST_HEAD(&inode->i_data.dirty_pages);
INIT_LIST_HEAD(&inode->i_data.locked_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 ...@@ -294,7 +294,7 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru
continue; continue;
invalidate_inode_buffers(inode); invalidate_inode_buffers(inode);
if (!atomic_read(&inode->i_count)) { if (!atomic_read(&inode->i_count)) {
list_del_init(&inode->i_hash); hlist_del_init(&inode->i_hash);
list_del(&inode->i_list); list_del(&inode->i_list);
list_add(&inode->i_list, dispose); list_add(&inode->i_list, dispose);
inode->i_state |= I_FREEING; inode->i_state |= I_FREEING;
...@@ -435,7 +435,7 @@ static void prune_icache(int nr_to_scan) ...@@ -435,7 +435,7 @@ static void prune_icache(int nr_to_scan)
if (!can_unuse(inode)) if (!can_unuse(inode))
continue; continue;
} }
list_del_init(&inode->i_hash); hlist_del_init(&inode->i_hash);
list_move(&inode->i_list, &freeable); list_move(&inode->i_list, &freeable);
inode->i_state |= I_FREEING; inode->i_state |= I_FREEING;
nr_pruned++; nr_pruned++;
...@@ -476,50 +476,42 @@ static int shrink_icache_memory(int nr, unsigned int gfp_mask) ...@@ -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 * by hand after calling find_inode now! This simplifies iunique and won't
* add any additional branch in the common code. * 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 hlist_node *node;
struct inode * inode; struct inode * inode = NULL;
tmp = head; hlist_for_each (node, head) {
for (;;) { prefetch(node->next);
tmp = tmp->next; inode = hlist_entry(node, struct inode, i_hash);
inode = NULL;
if (tmp == head)
break;
inode = list_entry(tmp, struct inode, i_hash);
if (inode->i_sb != sb) if (inode->i_sb != sb)
continue; continue;
if (!test(inode, data)) if (!test(inode, data))
continue; continue;
break; break;
} }
return inode; return node ? inode : NULL;
} }
/* /*
* find_inode_fast is the fast path version of find_inode, see the comment at * find_inode_fast is the fast path version of find_inode, see the comment at
* iget_locked for details. * 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 hlist_node *node;
struct inode * inode; struct inode * inode = NULL;
tmp = head; hlist_for_each (node, head) {
for (;;) { prefetch(node->next);
tmp = tmp->next; inode = list_entry(node, struct inode, i_hash);
inode = NULL;
if (tmp == head)
break;
inode = list_entry(tmp, struct inode, i_hash);
if (inode->i_ino != ino) if (inode->i_ino != ino)
continue; continue;
if (inode->i_sb != sb) if (inode->i_sb != sb)
continue; continue;
break; break;
} }
return inode; return node ? inode : NULL;
} }
/** /**
...@@ -569,7 +561,7 @@ EXPORT_SYMBOL(unlock_new_inode); ...@@ -569,7 +561,7 @@ EXPORT_SYMBOL(unlock_new_inode);
* We no longer cache the sb_flags in i_flags - see fs.h * We no longer cache the sb_flags in i_flags - see fs.h
* -- rmk@arm.uk.linux.org * -- 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; struct inode * inode;
...@@ -586,7 +578,7 @@ static struct inode * get_new_inode(struct super_block *sb, struct list_head *he ...@@ -586,7 +578,7 @@ static struct inode * get_new_inode(struct super_block *sb, struct list_head *he
inodes_stat.nr_inodes++; inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use); 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; inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
...@@ -619,7 +611,7 @@ static struct inode * get_new_inode(struct super_block *sb, struct list_head *he ...@@ -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 * get_new_inode_fast is the fast path version of get_new_inode, see the
* comment at iget_locked for details. * 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; struct inode * inode;
...@@ -634,7 +626,7 @@ static struct inode * get_new_inode_fast(struct super_block *sb, struct list_hea ...@@ -634,7 +626,7 @@ static struct inode * get_new_inode_fast(struct super_block *sb, struct list_hea
inode->i_ino = ino; inode->i_ino = ino;
inodes_stat.nr_inodes++; inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use); 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; inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
...@@ -686,7 +678,7 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved) ...@@ -686,7 +678,7 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved)
{ {
static ino_t counter = 0; static ino_t counter = 0;
struct inode *inode; struct inode *inode;
struct list_head * head; struct hlist_head * head;
ino_t res; ino_t res;
spin_lock(&inode_lock); spin_lock(&inode_lock);
retry: retry:
...@@ -740,7 +732,7 @@ struct inode *igrab(struct inode *inode) ...@@ -740,7 +732,7 @@ struct inode *igrab(struct inode *inode)
* Note, @test is called with the inode_lock held, so can't sleep. * Note, @test is called with the inode_lock held, so can't sleep.
*/ */
static inline struct inode *ifind(struct super_block *sb, 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) void *data)
{ {
struct inode *inode; struct inode *inode;
...@@ -772,7 +764,7 @@ static inline struct inode *ifind(struct super_block *sb, ...@@ -772,7 +764,7 @@ static inline struct inode *ifind(struct super_block *sb,
* Otherwise NULL is returned. * Otherwise NULL is returned.
*/ */
static inline struct inode *ifind_fast(struct super_block *sb, 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; struct inode *inode;
...@@ -810,7 +802,7 @@ static inline struct inode *ifind_fast(struct super_block *sb, ...@@ -810,7 +802,7 @@ static inline struct inode *ifind_fast(struct super_block *sb,
struct inode *ilookup5(struct super_block *sb, unsigned long hashval, struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), void *data) 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); return ifind(sb, head, test, data);
} }
...@@ -832,7 +824,7 @@ EXPORT_SYMBOL(ilookup5); ...@@ -832,7 +824,7 @@ EXPORT_SYMBOL(ilookup5);
*/ */
struct inode *ilookup(struct super_block *sb, unsigned long ino) 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); return ifind_fast(sb, head, ino);
} }
...@@ -864,7 +856,7 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, ...@@ -864,7 +856,7 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *), void *data) 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; struct inode *inode;
inode = ifind(sb, head, test, data); inode = ifind(sb, head, test, data);
...@@ -897,7 +889,7 @@ EXPORT_SYMBOL(iget5_locked); ...@@ -897,7 +889,7 @@ EXPORT_SYMBOL(iget5_locked);
*/ */
struct inode *iget_locked(struct super_block *sb, unsigned long ino) 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; struct inode *inode;
inode = ifind_fast(sb, head, ino); inode = ifind_fast(sb, head, ino);
...@@ -923,11 +915,11 @@ EXPORT_SYMBOL(iget_locked); ...@@ -923,11 +915,11 @@ EXPORT_SYMBOL(iget_locked);
void __insert_inode_hash(struct inode *inode, unsigned long hashval) 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) if (inode->i_sb)
head = inode_hashtable + hash(inode->i_sb, hashval); head = inode_hashtable + hash(inode->i_sb, hashval);
spin_lock(&inode_lock); spin_lock(&inode_lock);
list_add(&inode->i_hash, head); hlist_add_head(&inode->i_hash, head);
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
} }
...@@ -941,7 +933,7 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval) ...@@ -941,7 +933,7 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
void remove_inode_hash(struct inode *inode) void remove_inode_hash(struct inode *inode)
{ {
spin_lock(&inode_lock); spin_lock(&inode_lock);
list_del_init(&inode->i_hash); hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
} }
...@@ -949,7 +941,7 @@ void generic_delete_inode(struct inode *inode) ...@@ -949,7 +941,7 @@ void generic_delete_inode(struct inode *inode)
{ {
struct super_operations *op = inode->i_sb->s_op; 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); list_del_init(&inode->i_list);
inode->i_state|=I_FREEING; inode->i_state|=I_FREEING;
inodes_stat.nr_inodes--; inodes_stat.nr_inodes--;
...@@ -978,7 +970,7 @@ static void generic_forget_inode(struct inode *inode) ...@@ -978,7 +970,7 @@ static void generic_forget_inode(struct inode *inode)
{ {
struct super_block *sb = inode->i_sb; 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))) { if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
list_del(&inode->i_list); list_del(&inode->i_list);
list_add(&inode->i_list, &inode_unused); list_add(&inode->i_list, &inode_unused);
...@@ -990,7 +982,7 @@ static void generic_forget_inode(struct inode *inode) ...@@ -990,7 +982,7 @@ static void generic_forget_inode(struct inode *inode)
write_inode_now(inode, 1); write_inode_now(inode, 1);
spin_lock(&inode_lock); spin_lock(&inode_lock);
inodes_stat.nr_unused--; inodes_stat.nr_unused--;
list_del_init(&inode->i_hash); hlist_del_init(&inode->i_hash);
} }
list_del_init(&inode->i_list); list_del_init(&inode->i_list);
inode->i_state|=I_FREEING; inode->i_state|=I_FREEING;
...@@ -1236,7 +1228,7 @@ void wake_up_inode(struct inode *inode) ...@@ -1236,7 +1228,7 @@ void wake_up_inode(struct inode *inode)
*/ */
void __init inode_init(unsigned long mempages) void __init inode_init(unsigned long mempages)
{ {
struct list_head *head; struct hlist_head *head;
unsigned long order; unsigned long order;
unsigned int nr_hash; unsigned int nr_hash;
int i; int i;
...@@ -1253,7 +1245,7 @@ void __init inode_init(unsigned long mempages) ...@@ -1253,7 +1245,7 @@ void __init inode_init(unsigned long mempages)
unsigned long tmp; unsigned long tmp;
nr_hash = (1UL << order) * PAGE_SIZE / nr_hash = (1UL << order) * PAGE_SIZE /
sizeof(struct list_head); sizeof(struct hlist_head);
i_hash_mask = (nr_hash - 1); i_hash_mask = (nr_hash - 1);
tmp = nr_hash; tmp = nr_hash;
...@@ -1261,7 +1253,7 @@ void __init inode_init(unsigned long mempages) ...@@ -1261,7 +1253,7 @@ void __init inode_init(unsigned long mempages)
while ((tmp >>= 1UL) != 0UL) while ((tmp >>= 1UL) != 0UL)
i_hash_shift++; i_hash_shift++;
inode_hashtable = (struct list_head *) inode_hashtable = (struct hlist_head *)
__get_free_pages(GFP_ATOMIC, order); __get_free_pages(GFP_ATOMIC, order);
} while (inode_hashtable == NULL && --order >= 0); } while (inode_hashtable == NULL && --order >= 0);
...@@ -1274,7 +1266,7 @@ void __init inode_init(unsigned long mempages) ...@@ -1274,7 +1266,7 @@ void __init inode_init(unsigned long mempages)
head = inode_hashtable; head = inode_hashtable;
i = nr_hash; i = nr_hash;
do { do {
INIT_LIST_HEAD(head); INIT_HLIST_HEAD(head);
head++; head++;
i--; i--;
} while (i); } while (i);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); 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 do_remount_sb(struct super_block *sb, int flags, void * data);
extern int __init init_rootfs(void); extern int __init init_rootfs(void);
extern int __init fs_subsys_init(void);
static struct list_head *mount_hashtable; static struct list_head *mount_hashtable;
static int hash_mask, hash_bits; static int hash_mask, hash_bits;
...@@ -1132,6 +1133,7 @@ void __init mnt_init(unsigned long mempages) ...@@ -1132,6 +1133,7 @@ void __init mnt_init(unsigned long mempages)
d++; d++;
i--; i--;
} while (i); } while (i);
fs_subsys_init();
init_rootfs(); init_rootfs();
init_mount_tree(); init_mount_tree();
} }
...@@ -63,7 +63,7 @@ static struct super_block *alloc_super(void) ...@@ -63,7 +63,7 @@ static struct super_block *alloc_super(void)
INIT_LIST_HEAD(&s->s_io); INIT_LIST_HEAD(&s->s_io);
INIT_LIST_HEAD(&s->s_files); INIT_LIST_HEAD(&s->s_files);
INIT_LIST_HEAD(&s->s_instances); INIT_LIST_HEAD(&s->s_instances);
INIT_LIST_HEAD(&s->s_anon); INIT_HLIST_HEAD(&s->s_anon);
init_rwsem(&s->s_umount); init_rwsem(&s->s_umount);
sema_init(&s->s_lock, 1); sema_init(&s->s_lock, 1);
down_write(&s->s_umount); down_write(&s->s_umount);
......
...@@ -226,6 +226,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) ...@@ -226,6 +226,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{ {
sysfs_hash_and_remove(kobj->dentry,attr->attr.name); sysfs_hash_and_remove(kobj->dentry,attr->attr.name);
return 0;
} }
EXPORT_SYMBOL(sysfs_create_bin_file); EXPORT_SYMBOL(sysfs_create_bin_file);
......
...@@ -66,7 +66,7 @@ static struct file_system_type sysfs_fs_type = { ...@@ -66,7 +66,7 @@ static struct file_system_type sysfs_fs_type = {
.kill_sb = kill_litter_super, .kill_sb = kill_litter_super,
}; };
static int __init sysfs_init(void) int __init sysfs_init(void)
{ {
int err; int err;
...@@ -81,5 +81,3 @@ static int __init sysfs_init(void) ...@@ -81,5 +81,3 @@ static int __init sysfs_init(void)
} }
return err; return err;
} }
core_initcall(sysfs_init);
...@@ -76,25 +76,25 @@ struct dentry { ...@@ -76,25 +76,25 @@ struct dentry {
atomic_t d_count; atomic_t d_count;
unsigned long d_vfs_flags; /* moved here to be on same cacheline */ unsigned long d_vfs_flags; /* moved here to be on same cacheline */
spinlock_t d_lock; /* per dentry lock */ spinlock_t d_lock; /* per dentry lock */
unsigned int d_flags;
unsigned long d_move_count; /* to indicated moved dentry while lockless lookup */
struct inode * d_inode; /* Where the name belongs to - NULL is negative */ struct inode * d_inode; /* Where the name belongs to - NULL is negative */
struct dentry * d_parent; /* parent directory */
struct list_head * d_bucket; /* lookup hash bucket */
struct list_head d_hash; /* lookup hash list */
struct list_head d_lru; /* LRU list */ struct list_head d_lru; /* LRU list */
struct list_head d_child; /* child of parent list */ struct list_head d_child; /* child of parent list */
struct list_head d_subdirs; /* our children */ struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */ struct list_head d_alias; /* inode alias list */
int d_mounted;
struct qstr d_name;
struct qstr * d_qstr; /* quick str ptr used in lockless lookup and concurrent d_move */
unsigned long d_time; /* used by d_revalidate */ unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op; struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */ struct super_block * d_sb; /* The root of the dentry tree */
unsigned int d_flags;
int d_mounted;
void * d_fsdata; /* fs-specific data */ void * d_fsdata; /* fs-specific data */
struct rcu_head d_rcu; struct rcu_head d_rcu;
struct dcookie_struct * d_cookie; /* cookie, if any */ struct dcookie_struct * d_cookie; /* cookie, if any */
unsigned long d_move_count; /* to indicated moved dentry while lockless lookup */
struct qstr * d_qstr; /* quick str ptr used in lockless lookup and concurrent d_move */
struct dentry * d_parent; /* parent directory */
struct qstr d_name;
struct hlist_node d_hash; /* lookup hash list */
struct hlist_head * d_bucket; /* lookup hash bucket */
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
} ____cacheline_aligned; } ____cacheline_aligned;
...@@ -171,7 +171,7 @@ extern rwlock_t dparent_lock; ...@@ -171,7 +171,7 @@ extern rwlock_t dparent_lock;
static __inline__ void __d_drop(struct dentry * dentry) static __inline__ void __d_drop(struct dentry * dentry)
{ {
dentry->d_vfs_flags |= DCACHE_UNHASHED; dentry->d_vfs_flags |= DCACHE_UNHASHED;
list_del_rcu(&dentry->d_hash); hlist_del_rcu(&dentry->d_hash);
} }
static __inline__ void d_drop(struct dentry * dentry) static __inline__ void d_drop(struct dentry * dentry)
...@@ -198,7 +198,7 @@ extern struct dentry * d_alloc_anon(struct inode *); ...@@ -198,7 +198,7 @@ extern struct dentry * d_alloc_anon(struct inode *);
extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_sb(struct super_block *);
extern void shrink_dcache_parent(struct dentry *); extern void shrink_dcache_parent(struct dentry *);
extern void shrink_dcache_anon(struct list_head *); extern void shrink_dcache_anon(struct hlist_head *);
extern int d_invalidate(struct dentry *); extern int d_invalidate(struct dentry *);
/* only used at mount-time */ /* only used at mount-time */
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/radix-tree.h> #include <linux/radix-tree.h>
#include <linux/kobject.h>
#include <asm/atomic.h> #include <asm/atomic.h>
struct iovec; struct iovec;
...@@ -353,7 +354,7 @@ struct block_device { ...@@ -353,7 +354,7 @@ struct block_device {
}; };
struct inode { struct inode {
struct list_head i_hash; struct hlist_node i_hash;
struct list_head i_list; struct list_head i_list;
struct list_head i_dentry; struct list_head i_dentry;
unsigned long i_ino; unsigned long i_ino;
...@@ -601,7 +602,7 @@ struct super_block { ...@@ -601,7 +602,7 @@ struct super_block {
struct list_head s_dirty; /* dirty inodes */ struct list_head s_dirty; /* dirty inodes */
struct list_head s_io; /* parked for writeback */ 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 list_head s_files;
struct block_device *s_bdev; struct block_device *s_bdev;
...@@ -610,6 +611,7 @@ struct super_block { ...@@ -610,6 +611,7 @@ struct super_block {
char s_id[32]; /* Informational name */ char s_id[32]; /* Informational name */
struct kobject kobj; /* anchor for sysfs */
void *s_fs_info; /* Filesystem private info */ void *s_fs_info; /* Filesystem private info */
/* /*
...@@ -913,6 +915,7 @@ struct export_operations { ...@@ -913,6 +915,7 @@ struct export_operations {
struct file_system_type { struct file_system_type {
const char *name; const char *name;
struct subsystem subsys;
int fs_flags; int fs_flags;
struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *); struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
void (*kill_sb) (struct super_block *); void (*kill_sb) (struct super_block *);
......
...@@ -21,7 +21,7 @@ struct shaper ...@@ -21,7 +21,7 @@ struct shaper
__u32 bitspersec; __u32 bitspersec;
__u32 shapelatency; __u32 shapelatency;
__u32 shapeclock; __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 */ an empty queue */
unsigned long locked; unsigned long locked;
struct net_device_stats stats; struct net_device_stats stats;
......
...@@ -319,6 +319,98 @@ static inline void list_splice_init(struct list_head *list, ...@@ -319,6 +319,98 @@ static inline void list_splice_init(struct list_head *list,
for (pos = (head)->next, n = pos->next; pos != (head); \ for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, ({ read_barrier_depends(); 0;}), n = pos->next) pos = n, ({ read_barrier_depends(); 0;}), n = pos->next)
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
static __inline__ int hlist_unhashed(struct hlist_node *h)
{
return !h->pprev;
}
static __inline__ int hlist_empty(struct hlist_head *h)
{
return !h->first;
}
static __inline__ void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static __inline__ void hlist_del(struct hlist_node *n)
{
if (n->pprev)
__hlist_del(n);
}
#define hlist_del_rcu hlist_del /* list_del_rcu is identical too? */
static __inline__ void hlist_del_init(struct hlist_node *n)
{
if (n->pprev) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static __inline__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
static __inline__ void hlist_add_head_rcu(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
n->pprev = &h->first;
smp_wmb();
if (first)
first->pprev = &n->next;
h->first = n;
}
/* next must be != NULL */
static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
/* Cannot easily do prefetch unfortunately */
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos; \
pos = pos->next)
#else #else
#warning "don't include kernel headers in userspace" #warning "don't include kernel headers in userspace"
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -294,7 +294,7 @@ struct tty_struct { ...@@ -294,7 +294,7 @@ struct tty_struct {
unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
unsigned char closing:1; unsigned char closing:1;
unsigned short minimum_to_wake; unsigned short minimum_to_wake;
unsigned overrun_time; unsigned long overrun_time;
int num_overrun; int num_overrun;
unsigned long process_char_map[256/(8*sizeof(unsigned long))]; unsigned long process_char_map[256/(8*sizeof(unsigned long))];
char *read_buf; char *read_buf;
......
...@@ -71,6 +71,7 @@ extern void pte_chain_init(void); ...@@ -71,6 +71,7 @@ extern void pte_chain_init(void);
extern void radix_tree_init(void); extern void radix_tree_init(void);
extern void free_initmem(void); extern void free_initmem(void);
extern void populate_rootfs(void); extern void populate_rootfs(void);
extern void driver_init(void);
#ifdef CONFIG_TC #ifdef CONFIG_TC
extern void tc_init(void); extern void tc_init(void);
...@@ -476,6 +477,8 @@ static void __init do_initcalls(void) ...@@ -476,6 +477,8 @@ static void __init do_initcalls(void)
*/ */
static void __init do_basic_setup(void) static void __init do_basic_setup(void)
{ {
driver_init();
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
sysctl_init(); sysctl_init();
#endif #endif
......
...@@ -479,7 +479,7 @@ static void ...@@ -479,7 +479,7 @@ static void
rpc_depopulate(struct dentry *parent) rpc_depopulate(struct dentry *parent)
{ {
struct inode *dir = parent->d_inode; struct inode *dir = parent->d_inode;
LIST_HEAD(head); HLIST_HEAD(head);
struct list_head *pos, *next; struct list_head *pos, *next;
struct dentry *dentry; struct dentry *dentry;
...@@ -490,12 +490,12 @@ rpc_depopulate(struct dentry *parent) ...@@ -490,12 +490,12 @@ rpc_depopulate(struct dentry *parent)
if (!d_unhashed(dentry)) { if (!d_unhashed(dentry)) {
dget_locked(dentry); dget_locked(dentry);
__d_drop(dentry); __d_drop(dentry);
list_add(&dentry->d_hash, &head); hlist_add_head(&dentry->d_hash, &head);
} }
} }
spin_unlock(&dcache_lock); spin_unlock(&dcache_lock);
while (!list_empty(&head)) { while (!hlist_empty(&head)) {
dentry = list_entry(head.next, struct dentry, d_hash); dentry = list_entry(head.first, struct dentry, d_hash);
/* Private list, so no dcache_lock needed and use __d_drop */ /* Private list, so no dcache_lock needed and use __d_drop */
__d_drop(dentry); __d_drop(dentry);
if (dentry->d_inode) { if (dentry->d_inode) {
......
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