## Automatically generated incremental diff ## From: linux-2.5.63-bk7 ## To: linux-2.5.64 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.63-bk7/Documentation/ioctl-number.txt linux-2.5.64/Documentation/ioctl-number.txt --- linux-2.5.63-bk7/Documentation/ioctl-number.txt Mon Feb 24 11:05:45 2003 +++ linux-2.5.64/Documentation/ioctl-number.txt Mon Mar 31 12:22:14 2003 @@ -72,6 +72,7 @@ linux/blkpg.h 0x20 all drivers/cdrom/cm206.h 0x22 all scsi/sg.h +'#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem '1' 00-1F PPS kit from Ulrich Windl '6' 00-10 Intel IA32 microcode update driver diff -urN linux-2.5.63-bk7/Makefile linux-2.5.64/Makefile --- linux-2.5.63-bk7/Makefile Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/Makefile Mon Mar 31 12:22:14 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 63 -EXTRAVERSION = bk7 +SUBLEVEL = 64 +EXTRAVERSION = # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.63-bk7/arch/sparc64/kernel/setup.c linux-2.5.64/arch/sparc64/kernel/setup.c --- linux-2.5.63-bk7/arch/sparc64/kernel/setup.c Mon Feb 24 11:05:15 2003 +++ linux-2.5.64/arch/sparc64/kernel/setup.c Mon Mar 31 12:22:19 2003 @@ -688,6 +688,7 @@ sparc64_cpus = kmalloc(NR_CPUS * sizeof(struct cpu), GFP_KERNEL); if (!sparc64_cpus) return -ENOMEM; + memset(sparc64_cpus, 0, NR_CPUS * sizeof(struct cpu)); for (i = 0; i < NR_CPUS; i++) { if (cpu_possible(i)) register_cpu(&sparc64_cpus[i], i, NULL); diff -urN linux-2.5.63-bk7/drivers/base/Makefile linux-2.5.64/drivers/base/Makefile --- linux-2.5.63-bk7/drivers/base/Makefile Mon Feb 24 11:05:40 2003 +++ linux-2.5.64/drivers/base/Makefile Mon Mar 31 12:22:20 2003 @@ -2,7 +2,7 @@ obj-y := core.o sys.o interface.o power.o bus.o \ driver.o class.o intf.o platform.o \ - cpu.o firmware.o + cpu.o firmware.o init.o obj-$(CONFIG_NUMA) += node.o memblk.o obj-y += fs/ obj-$(CONFIG_HOTPLUG) += hotplug.o diff -urN linux-2.5.63-bk7/drivers/base/bus.c linux-2.5.64/drivers/base/bus.c --- linux-2.5.63-bk7/drivers/base/bus.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/base/bus.c Mon Mar 31 12:22:20 2003 @@ -544,12 +544,11 @@ subsystem_unregister(&bus->subsys); } -static int __init bus_subsys_init(void) +int __init buses_init(void) { return subsystem_register(&bus_subsys); } -core_initcall(bus_subsys_init); EXPORT_SYMBOL(bus_for_each_dev); EXPORT_SYMBOL(bus_for_each_drv); diff -urN linux-2.5.63-bk7/drivers/base/class.c linux-2.5.64/drivers/base/class.c --- linux-2.5.63-bk7/drivers/base/class.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/base/class.c Mon Mar 31 12:22:20 2003 @@ -266,13 +266,11 @@ subsystem_unregister(&cls->subsys); } -static int __init class_subsys_init(void) +int __init classes_init(void) { return subsystem_register(&class_subsys); } -core_initcall(class_subsys_init); - EXPORT_SYMBOL(devclass_create_file); EXPORT_SYMBOL(devclass_remove_file); EXPORT_SYMBOL(devclass_register); diff -urN linux-2.5.63-bk7/drivers/base/core.c linux-2.5.64/drivers/base/core.c --- linux-2.5.63-bk7/drivers/base/core.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/base/core.c Mon Mar 31 12:22:20 2003 @@ -309,13 +309,11 @@ put_device(dev); } -static int __init device_subsys_init(void) +int __init devices_init(void) { return subsystem_register(&devices_subsys); } -core_initcall(device_subsys_init); - EXPORT_SYMBOL(device_initialize); EXPORT_SYMBOL(device_add); EXPORT_SYMBOL(device_register); diff -urN linux-2.5.63-bk7/drivers/base/cpu.c linux-2.5.64/drivers/base/cpu.c --- linux-2.5.63-bk7/drivers/base/cpu.c Mon Feb 24 11:05:15 2003 +++ linux-2.5.64/drivers/base/cpu.c Mon Mar 31 12:22:20 2003 @@ -46,9 +46,8 @@ } -static int __init register_cpu_type(void) +int __init cpu_dev_init(void) { devclass_register(&cpu_devclass); return driver_register(&cpu_driver); } -postcore_initcall(register_cpu_type); diff -urN linux-2.5.63-bk7/drivers/base/firmware.c linux-2.5.64/drivers/base/firmware.c --- linux-2.5.63-bk7/drivers/base/firmware.c Mon Feb 24 11:05:33 2003 +++ linux-2.5.64/drivers/base/firmware.c Mon Mar 31 12:22:20 2003 @@ -19,12 +19,10 @@ subsystem_unregister(s); } -static int __init firmware_init(void) +int __init firmware_init(void) { return subsystem_register(&firmware_subsys); } -core_initcall(firmware_init); - EXPORT_SYMBOL(firmware_register); EXPORT_SYMBOL(firmware_unregister); diff -urN linux-2.5.63-bk7/drivers/base/hotplug.c linux-2.5.64/drivers/base/hotplug.c --- linux-2.5.63-bk7/drivers/base/hotplug.c Mon Feb 24 11:05:05 2003 +++ linux-2.5.64/drivers/base/hotplug.c Mon Mar 31 12:22:20 2003 @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "base.h" #include "fs/fs.h" diff -urN linux-2.5.63-bk7/drivers/base/init.c linux-2.5.64/drivers/base/init.c --- linux-2.5.63-bk7/drivers/base/init.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.64/drivers/base/init.c Mon Mar 31 12:22:20 2003 @@ -0,0 +1,34 @@ + +#include +#include + +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(); +} diff -urN linux-2.5.63-bk7/drivers/base/platform.c linux-2.5.64/drivers/base/platform.c --- linux-2.5.63-bk7/drivers/base/platform.c Mon Feb 24 11:05:09 2003 +++ linux-2.5.64/drivers/base/platform.c Mon Mar 31 12:22:20 2003 @@ -41,9 +41,29 @@ if (pdev) device_unregister(&pdev->dev); } - + + +/** + * platform_match - bind platform device to platform driver. + * @dev: device. + * @drv: driver. + * + * Platform device IDs are assumed to be encoded like this: + * "", where is a short description of the + * type of device, like "pci" or "floppy", and is the + * enumerated instance of the device, like '0' or '42'. + * Driver IDs are simply "". + * So, extract the from the device, and compare it against + * the name of the driver. Return whether they match or not. + */ + static int platform_match(struct device * dev, struct device_driver * drv) { + char name[BUS_ID_SIZE]; + + if (sscanf(dev->bus_id,"%s",name)) + return (strcmp(name,drv->name) == 0); + return 0; } @@ -52,13 +72,11 @@ .match = platform_match, }; -static int __init platform_bus_init(void) +int __init platform_bus_init(void) { device_register(&legacy_bus); return bus_register(&platform_bus_type); } -postcore_initcall(platform_bus_init); - EXPORT_SYMBOL(platform_device_register); EXPORT_SYMBOL(platform_device_unregister); diff -urN linux-2.5.63-bk7/drivers/base/sys.c linux-2.5.64/drivers/base/sys.c --- linux-2.5.63-bk7/drivers/base/sys.c Mon Feb 24 11:05:04 2003 +++ linux-2.5.64/drivers/base/sys.c Mon Mar 31 12:22:20 2003 @@ -138,13 +138,12 @@ .name = "system", }; -static int sys_bus_init(void) +int __init sys_bus_init(void) { bus_register(&system_bus_type); return device_register(&system_bus); } -postcore_initcall(sys_bus_init); EXPORT_SYMBOL(system_bus_type); EXPORT_SYMBOL(sys_device_register); EXPORT_SYMBOL(sys_device_unregister); diff -urN linux-2.5.63-bk7/drivers/ieee1394/Makefile linux-2.5.64/drivers/ieee1394/Makefile --- linux-2.5.63-bk7/drivers/ieee1394/Makefile Mon Feb 24 11:06:01 2003 +++ linux-2.5.64/drivers/ieee1394/Makefile Mon Mar 31 12:22:20 2003 @@ -18,13 +18,6 @@ clean-files := oui.c -ieee1394.o: $(ieee1394-objs) - $(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs) - -ifeq ($(obj),) -obj = . -endif - $(obj)/oui.o: $(obj)/oui.c $(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh $(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $(obj)/oui.c diff -urN linux-2.5.63-bk7/drivers/ieee1394/amdtp.c linux-2.5.64/drivers/ieee1394/amdtp.c --- linux-2.5.63-bk7/drivers/ieee1394/amdtp.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/ieee1394/amdtp.c Mon Mar 31 12:22:20 2003 @@ -74,6 +74,8 @@ #include #include #include +#include +#include #include #include @@ -1262,8 +1264,11 @@ static int __init amdtp_init_module (void) { - if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP, - THIS_MODULE, &amdtp_fops)) { + int ret; + + ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP, + THIS_MODULE, &amdtp_fops); + if (ret) { HPSB_ERR("amdtp: unable to get minor device block"); return -EIO; } @@ -1276,6 +1281,15 @@ return -EIO; } +#ifdef CONFIG_COMPAT + ret = register_ioctl32_conversion(AMDTP_IOC_CHANNEL, NULL); + ret |= register_ioctl32_conversion(AMDTP_IOC_PLUG, NULL); + ret |= register_ioctl32_conversion(AMDTP_IOC_PING, NULL); + ret |= register_ioctl32_conversion(AMDTP_IOC_ZAP, NULL); + if (ret) + HPSB_ERR("amdtp: Error registering ioctl32 translations"); +#endif + HPSB_INFO("Loaded AMDTP driver"); return 0; @@ -1283,6 +1297,17 @@ static void __exit amdtp_exit_module (void) { +#ifdef CONFIG_COMPAT + int ret; + + ret = unregister_ioctl32_conversion(AMDTP_IOC_CHANNEL); + ret |= unregister_ioctl32_conversion(AMDTP_IOC_PLUG); + ret |= unregister_ioctl32_conversion(AMDTP_IOC_PING); + ret |= unregister_ioctl32_conversion(AMDTP_IOC_ZAP); + if (ret) + HPSB_ERR("amdtp: Error unregistering ioctl32 translations"); +#endif + hpsb_unregister_highlevel(amdtp_highlevel); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP); diff -urN linux-2.5.63-bk7/drivers/ieee1394/dma.c linux-2.5.64/drivers/ieee1394/dma.c --- linux-2.5.63-bk7/drivers/ieee1394/dma.c Mon Feb 24 11:05:32 2003 +++ linux-2.5.64/drivers/ieee1394/dma.c Mon Mar 31 12:22:20 2003 @@ -10,6 +10,7 @@ #include #include #include +#include #include "dma.h" /* dma_prog_region */ diff -urN linux-2.5.63-bk7/drivers/ieee1394/dv1394.c linux-2.5.64/drivers/ieee1394/dv1394.c --- linux-2.5.63-bk7/drivers/ieee1394/dv1394.c Mon Feb 24 11:05:38 2003 +++ linux-2.5.64/drivers/ieee1394/dv1394.c Mon Mar 31 12:22:20 2003 @@ -111,6 +111,8 @@ #include #include #include +#include +#include #include "ieee1394.h" #include "ieee1394_types.h" @@ -2701,7 +2703,7 @@ struct ti_ohci *ohci; struct video_card *video = NULL; unsigned long flags; - struct list_head *lh; + struct list_head *lh, *templh; char buf[32]; int n; @@ -2715,7 +2717,7 @@ /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); if(!list_empty(&dv1394_cards)) { - list_for_each(lh, &dv1394_cards) { + list_for_each_safe(lh, templh, &dv1394_cards) { video = list_entry(lh, struct video_card, list); if((video->id >> 2) == ohci->id) dv1394_un_init(video); @@ -2907,6 +2909,98 @@ .host_reset = dv1394_host_reset, }; +#ifdef CONFIG_COMPAT + +#define DV1394_IOC32_INIT _IOW('#', 0x06, struct dv1394_init32) +#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32) + +struct dv1394_init32 { + u32 api_version; + u32 channel; + u32 n_frames; + u32 format; + u32 cip_n; + u32 cip_d; + u32 syt_offset; +}; + +struct dv1394_status32 { + struct dv1394_init32 init; + s32 active_frame; + u32 first_clear_frame; + u32 n_clear_frames; + u32 dropped_frames; +}; + +static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *file) +{ + struct dv1394_init32 dv32; + struct dv1394_init dv; + mm_segment_t old_fs; + int ret; + + if (file->f_op->ioctl != dv1394_ioctl) + return -EFAULT; + + if (copy_from_user(&dv32, (void *)arg, sizeof(dv32))) + return -EFAULT; + + dv.api_version = dv32.api_version; + dv.channel = dv32.channel; + dv.n_frames = dv32.n_frames; + dv.format = dv32.format; + dv.cip_n = (unsigned long)dv32.cip_n; + dv.cip_d = (unsigned long)dv32.cip_d; + dv.syt_offset = dv32.syt_offset; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = dv1394_ioctl(file->f_dentry->d_inode, file, + DV1394_IOC_INIT, (unsigned long)&dv); + set_fs(old_fs); + + return ret; +} + +static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *file) +{ + struct dv1394_status32 dv32; + struct dv1394_status dv; + mm_segment_t old_fs; + int ret; + + if (file->f_op->ioctl != dv1394_ioctl) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = dv1394_ioctl(file->f_dentry->d_inode, file, + DV1394_IOC_GET_STATUS, (unsigned long)&dv); + set_fs(old_fs); + + if (!ret) { + dv32.init.api_version = dv.init.api_version; + dv32.init.channel = dv.init.channel; + dv32.init.n_frames = dv.init.n_frames; + dv32.init.format = dv.init.format; + dv32.init.cip_n = (u32)dv.init.cip_n; + dv32.init.cip_d = (u32)dv.init.cip_d; + dv32.init.syt_offset = dv.init.syt_offset; + dv32.active_frame = dv.active_frame; + dv32.first_clear_frame = dv.first_clear_frame; + dv32.n_clear_frames = dv.n_clear_frames; + dv32.dropped_frames = dv.dropped_frames; + + if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32))) + ret = -EFAULT; + } + + return ret; +} +#endif /* CONFIG_COMPAT */ + /*** KERNEL MODULE HANDLERS ************************************************/ @@ -2917,6 +3011,20 @@ static void __exit dv1394_exit_module(void) { +#ifdef CONFIG_COMPAT + int ret; + + ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN); + ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES); + ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES); + ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES); + ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE); + ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT); + ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS); + if (ret) + printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n"); +#endif + hpsb_unregister_highlevel (hl_handle); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); #ifdef CONFIG_DEVFS_FS @@ -2929,14 +3037,18 @@ static int __init dv1394_init_module(void) { - if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394, - THIS_MODULE, &dv1394_fops)) { + int ret; + + ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394, + THIS_MODULE, &dv1394_fops); + if (ret) { printk(KERN_ERR "dv1394: unable to register character device\n"); return -EIO; } #ifdef CONFIG_DEVFS_FS - if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) { + ret = dv1394_devfs_add_dir("dv", NULL, NULL); + if (ret < 0) { printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); return -ENOMEM; @@ -2944,7 +3056,8 @@ #endif #ifdef CONFIG_PROC_FS - if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) { + ret = dv1394_procfs_add_dir("dv",NULL,NULL); + if (ret < 0) { printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); #ifdef CONFIG_DEVFS_FS @@ -2967,9 +3080,23 @@ return -ENOMEM; } +#ifdef CONFIG_COMPAT + /* First compatible ones */ + ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL); + ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL); + ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL); + ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL); + ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL); + + /* These need to be handled by translation */ + ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init); + ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status); + if (ret) + printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n"); +#endif + return 0; } module_init(dv1394_init_module); module_exit(dv1394_exit_module); - diff -urN linux-2.5.63-bk7/drivers/ieee1394/eth1394.c linux-2.5.64/drivers/ieee1394/eth1394.c --- linux-2.5.63-bk7/drivers/ieee1394/eth1394.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/ieee1394/eth1394.c Mon Mar 31 12:22:20 2003 @@ -65,6 +65,7 @@ #include "ieee1394_transactions.h" #include "ieee1394.h" #include "highlevel.h" +#include "iso.h" #include "eth1394.h" #define ETH1394_PRINT_G(level, fmt, args...) \ @@ -77,7 +78,7 @@ printk(KERN_ERR fmt, ## args) static char version[] __devinitdata = - "$Rev: 770 $ Ben Collins "; + "$Rev: 806 $ Ben Collins "; /* Our ieee1394 highlevel driver */ #define ETHER1394_DRIVER_NAME "ether1394" @@ -101,6 +102,9 @@ MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); MODULE_LICENSE("GPL"); +static void ether1394_iso(struct hpsb_iso *iso); + + /* Find our host_info struct for a given host pointer. Must be called * under spinlock. */ static inline struct host_info *find_host_info (struct hpsb_host *host) @@ -178,15 +182,26 @@ * XXX: This is where we need to create a list of skb's for fragmented * packets. */ static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev, - int proto) + int proto, struct packet_task *ptask) { union eth1394_hdr *hdr = (union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]); + hdr->words.word1 = 0; hdr->common.lf = ETH1394_HDR_LF_UF; hdr->words.word1 = htons(hdr->words.word1); hdr->uf.ether_type = proto; + /* Set the transmission type for the packet. Right now only ARP + * packets are sent via GASP. IP broadcast and IP multicast are not + * yet supported properly, they too should use GASP. */ + switch(proto) { + case __constant_htons(ETH_P_ARP): + ptask->tx_type = ETH1394_GASP; + break; + default: + ptask->tx_type = ETH1394_WRREQ; + } return; } @@ -199,14 +214,14 @@ { struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv); - u16 phy_id = priv->host->node_id & NODE_MASK; + u16 phy_id = NODEID_TO_NODE(priv->host->node_id); unsigned char *arp_ptr = (unsigned char *)skb->data; struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data; unsigned char arp_data[2*(dev->addr_len+4)]; /* Copy the main data that we need */ - arp_ptr = memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data)); + memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data)); /* Extend the buffer enough for our new header */ skb_put (skb, sizeof (struct eth1394_arp) - @@ -214,7 +229,7 @@ #define PROCESS_MEMBER(ptr,val,len) \ memcpy (val, ptr, len); ptr += len - arp_ptr += arp1394->hw_addr_len; + arp_ptr = arp_data + arp1394->hw_addr_len; PROCESS_MEMBER (arp_ptr, &arp1394->sip, arp1394->ip_addr_len); arp_ptr += arp1394->hw_addr_len; PROCESS_MEMBER (arp_ptr, &arp1394->tip, arp1394->ip_addr_len); @@ -279,7 +294,8 @@ { unsigned long flags; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - int phy_id = priv->host->node_id & NODE_MASK; + int phy_id = NODEID_TO_NODE(priv->host->node_id); + struct hpsb_host *host = priv->host; spin_lock_irqsave (&priv->lock, flags); @@ -289,20 +305,23 @@ memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi)); memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo)); + priv->bc_state = ETHER1394_BC_CHECK; + /* Register our limits now */ - ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf, - priv->host->speed_map[(phy_id << 6) + phy_id], - (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) | - be32_to_cpu(priv->host->csr.rom[4])), + ether1394_register_limits (phy_id, (be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf, + host->speed_map[(phy_id << 6) + phy_id], + (u64)(((u64)be32_to_cpu(host->csr.rom[3]) << 32) | + be32_to_cpu(host->csr.rom[4])), ETHER1394_REGION_ADDR >> 32, ETHER1394_REGION_ADDR & 0xffffffff, priv); /* We'll use our max_rec as the default mtu */ if (set_mtu) - dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr); + dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - /* mtu = max_rec - */ + (sizeof (union eth1394_hdr) + 8); /* (hdr + GASP) */ /* Set our hardware address while we're at it */ - *(nodeid_t *)dev->dev_addr = htons (priv->host->node_id); + *(nodeid_t *)dev->dev_addr = htons (host->node_id); spin_unlock_irqrestore (&priv->lock, flags); } @@ -383,6 +402,15 @@ list_add_tail (&hi->list, &host_info_list); spin_unlock_irq (&host_info_lock); + /* Ignore validity in hopes that it will be set in the future. It'll + * check it on transmit. */ + priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; + + priv->iso = hpsb_iso_recv_init(host, 8 * 4096, 8, priv->broadcast_channel, + 1, ether1394_iso); + if (priv->iso == NULL) { + priv->bc_state = ETHER1394_BC_CLOSED; + } return; out: @@ -396,11 +424,14 @@ /* Remove a card from our list */ static void ether1394_remove_host (struct hpsb_host *host) { + struct eth1394_priv *priv; struct host_info *hi; spin_lock_irq (&host_info_lock); hi = find_host_info (host); if (hi != NULL) { + priv = (struct eth1394_priv *)hi->dev->priv; + priv->bc_state = ETHER1394_BC_CLOSED; unregister_netdev (hi->dev); kfree (hi->dev); list_del (&hi->list); @@ -480,7 +511,7 @@ * about the sending machine. */ if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) { unsigned long flags; - u16 phy_id = srcid & NODE_MASK; + u16 phy_id = NODEID_TO_NODE(srcid); struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct eth1394_arp arp1394; @@ -498,7 +529,7 @@ spin_unlock_irqrestore (&priv->lock, flags); #define PROCESS_MEMBER(ptr,val,len) \ - ptr = memcpy (ptr, val, len) + len + memcpy (ptr, val, len); ptr += len PROCESS_MEMBER (arp_ptr, src_hw, dev->addr_len); PROCESS_MEMBER (arp_ptr, &arp1394.sip, 4); PROCESS_MEMBER (arp_ptr, dest_hw, dev->addr_len); @@ -591,6 +622,104 @@ return RCODE_COMPLETE; } +static void ether1394_iso(struct hpsb_iso *iso) +{ + struct sk_buff *skb; + quadlet_t *data; + char *buf; + int flags; + struct net_device *dev = ether1394_find_dev(iso->host); + struct eth1394_priv *priv; + unsigned int len; + u32 specifier_id; + u16 source_id; + int i; + int nready; + + if (dev == NULL) { + ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n", + iso->host->driver->name); + return; + } + + nready = hpsb_iso_n_ready(iso); + for(i = 0; i < nready; i++) { + struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; + data = (quadlet_t*) (iso->data_buf.kvirt + info->offset); + + /* skip over GASP header */ + buf = (char *)data + 8; + len = info->len - 8; + + specifier_id = (((be32_to_cpu(data[0]) & 0xffff) << 8) | + ((be32_to_cpu(data[1]) & 0xff000000) >> 24)); + source_id = be32_to_cpu(data[0]) >> 16; + + priv = (struct eth1394_priv *)dev->priv; + + if (info->channel != priv->broadcast_channel || + specifier_id != ETHER1394_GASP_SPECIFIER_ID) { + /* This packet is not for us */ + continue; + } + + /* A packet has been received by the ieee1394 bus. Build an skbuff + * around it so we can pass it to the high level network layer. */ + skb = dev_alloc_skb (len + dev->hard_header_len + 15); + if (!skb) { + HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n"); + priv->stats.rx_dropped++; + break; + } + + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); + + memcpy (skb_put (skb, len), buf, len); + + /* Write metadata, and then pass to the receive level */ + skb->dev = dev; + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ + + /* Parse the encapsulation header. This actually does the job of + * converting to an ethernet frame header, aswell as arp + * conversion if needed. ARP conversion is easier in this + * direction, since we are using ethernet as our backend. */ + skb->protocol = ether1394_parse_encap (skb, dev, source_id, + LOCAL_BUS | ALL_NODES); + + spin_lock_irqsave (&priv->lock, flags); + if (!skb->protocol) { + priv->stats.rx_errors++; + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + goto bad_proto; + } + + netif_stop_queue(dev); + if (netif_rx (skb) == NET_RX_DROP) { + priv->stats.rx_errors++; + priv->stats.rx_dropped++; + goto bad_proto; + } + + /* Statistics */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + + bad_proto: + spin_unlock_irqrestore (&priv->lock, flags); + } + + hpsb_iso_recv_release_packets(iso, i); + + netif_start_queue(dev); + + dev->last_rx = jiffies; + + return; +} + + /* This function is our scheduled write */ static void hpsb_write_sched (void *__ptask) { @@ -598,13 +727,26 @@ struct sk_buff *skb = ptask->skb; struct net_device *dev = ptask->skb->dev; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - unsigned long flags; + unsigned long flags; + int status; + + if (ptask->tx_type == ETH1394_GASP) { + status = hpsb_send_gasp(priv->host, priv->broadcast_channel, + get_hpsb_generation(priv->host), + (quadlet_t *)skb->data, skb->len, + ETHER1394_GASP_SPECIFIER_ID, + ETHER1394_GASP_VERSION); + } else { + status = hpsb_write(priv->host, ptask->dest_node, + get_hpsb_generation(priv->host), + ptask->addr, (quadlet_t *)skb->data, + skb->len); + } + /* Statistics */ spin_lock_irqsave (&priv->lock, flags); - if (!hpsb_write(priv->host, ptask->dest_node, - get_hpsb_generation(priv->host), - ptask->addr, (quadlet_t *)skb->data, skb->len)) { + if (!status) { priv->stats.tx_bytes += skb->len; priv->stats.tx_packets++; } else { @@ -636,6 +778,67 @@ struct packet_task *ptask = NULL; int ret = 0; + spin_lock_irqsave (&priv->lock, flags); + if (priv->bc_state == ETHER1394_BC_CLOSED) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Cannot send packet, no broadcast channel available."); + ret = -EAGAIN; + goto fail; + } + + /* First time sending? Need a broadcast channel for ARP and for + * listening on */ + if (priv->bc_state == ETHER1394_BC_CHECK) { + quadlet_t bc; + + /* Get the local copy of the broadcast channel and check its + * validity (the IRM should validate it for us) */ + + bc = priv->host->csr.broadcast_channel; + + if ((bc & 0xc0000000) != 0xc0000000) { + /* broadcast channel not validated yet */ + ETH1394_PRINT(KERN_WARNING, dev->name, + "Error BROADCAST_CHANNEL register valid " + "bit not set, can't send IP traffic\n"); + hpsb_iso_shutdown(priv->iso); + priv->bc_state = ETHER1394_BC_CLOSED; + ret = -EAGAIN; + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; + } + if (priv->broadcast_channel != (bc & 0x3f)) { + /* This really shouldn't be possible, but just in case + * the IEEE 1394 spec changes regarding broadcast + * channels in the future. */ + hpsb_iso_shutdown(priv->iso); + + priv->broadcast_channel = bc & 0x3f; + ETH1394_PRINT(KERN_WARNING, dev->name, + "Changing to broadcast channel %d...\n", + priv->broadcast_channel); + + priv->iso = hpsb_iso_recv_init(priv->host, 8 * 4096, + 8, priv->broadcast_channel, + 1, ether1394_iso); + if (priv->iso == NULL) { + ret = -EAGAIN; + goto fail; + } + } + if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Could not start async reception\n"); + hpsb_iso_shutdown(priv->iso); + priv->bc_state = ETHER1394_BC_CLOSED; + ret = -EAGAIN; + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; + } + priv->bc_state = ETHER1394_BC_OPENED; + } + spin_unlock_irqrestore (&priv->lock, flags); + if ((skb = skb_share_check (skb, kmflags)) == NULL) { ret = -ENOMEM; goto fail; @@ -654,8 +857,14 @@ if (proto == __constant_htons (ETH_P_ARP)) ether1394_arp_to_1394arp (skb, dev); + ptask = kmem_cache_alloc(packet_task_cache, kmflags); + if (ptask == NULL) { + ret = -ENOMEM; + goto fail; + } + /* Now add our encapsulation header */ - ether1394_encapsulate (skb, dev, proto); + ether1394_encapsulate (skb, dev, proto, ptask); /* TODO: The above encapsulate function needs to recognize when a * packet needs to be split for a specified node. It should create @@ -667,19 +876,13 @@ * need this hack. */ spin_lock_irqsave (&priv->lock, flags); - addr = (u64)priv->fifo_hi[dest_node & NODE_MASK] << 32 | - priv->fifo_lo[dest_node & NODE_MASK]; + addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 | + priv->fifo_lo[NODEID_TO_NODE(dest_node)]; spin_unlock_irqrestore (&priv->lock, flags); if (!addr) addr = ETHER1394_REGION_ADDR; - ptask = kmem_cache_alloc(packet_task_cache, kmflags); - if (ptask == NULL) { - ret = -ENOMEM; - goto fail; - } - ptask->skb = skb; ptask->addr = addr; ptask->dest_node = dest_node; @@ -702,7 +905,7 @@ netif_wake_queue (dev); spin_unlock_irqrestore (&priv->lock, flags); - return ret; + return 0; /* returning non-zero causes serious problems */ } /* Function for incoming 1394 packets */ @@ -738,6 +941,19 @@ static void __exit ether1394_exit_module (void) { + struct list_head *lh; + struct host_info *hi; + struct eth1394_priv *priv; + + lh = host_info_list.next; + while (lh != &host_info_list) { + hi = list_entry (lh, struct host_info, list); + priv = (struct eth1394_priv*)hi->dev->priv; + if (priv->bc_state != ETHER1394_BC_CLOSED) { + hpsb_iso_shutdown(priv->iso); + } + lh = lh->next; + } hpsb_unregister_highlevel (hl_handle); kmem_cache_destroy(packet_task_cache); } diff -urN linux-2.5.63-bk7/drivers/ieee1394/eth1394.h linux-2.5.64/drivers/ieee1394/eth1394.h --- linux-2.5.63-bk7/drivers/ieee1394/eth1394.h Mon Feb 24 11:05:42 2003 +++ linux-2.5.64/drivers/ieee1394/eth1394.h Mon Mar 31 12:22:20 2003 @@ -30,9 +30,16 @@ #define ETHER1394_REGION_ADDR 0xfffff0200000ULL #define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN) +/* GASP identifier numbers for IPv4 over IEEE 1394 */ +#define ETHER1394_GASP_SPECIFIER_ID 0x00005E +#define ETHER1394_GASP_VERSION 1 + /* Node set == 64 */ #define NODE_SET (ALL_NODES + 1) +enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED, + ETHER1394_BC_CHECK }; + /* Private structure for our ethernet driver */ struct eth1394_priv { struct net_device_stats stats; /* Device stats */ @@ -43,6 +50,9 @@ u32 fifo_lo[ALL_NODES]; /* 32bit lo fifo offset per node */ u64 eui[ALL_NODES]; /* EUI-64 per node */ spinlock_t lock; /* Private lock */ + int broadcast_channel; /* Async stream Broadcast Channel */ + enum eth1394_bc_states bc_state; /* broadcast channel state */ + struct hpsb_iso *iso; /* Async stream recv handle */ }; struct host_info { @@ -51,12 +61,15 @@ struct net_device *dev; }; +typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; + /* This is our task struct. It's used for the packet complete callback. */ struct packet_task { struct sk_buff *skb; /* Socket buffer we are sending */ nodeid_t dest_node; /* Destination of the packet */ u64 addr; /* Address */ struct hpsb_queue_struct tq; /* The task */ + eth1394_tx_type tx_type; /* Send data via GASP or Write Req. */ }; /* IP1394 headers */ diff -urN linux-2.5.63-bk7/drivers/ieee1394/hosts.c linux-2.5.64/drivers/ieee1394/hosts.c --- linux-2.5.63-bk7/drivers/ieee1394/hosts.c Mon Feb 24 11:05:16 2003 +++ linux-2.5.64/drivers/ieee1394/hosts.c Mon Mar 31 12:22:20 2003 @@ -71,9 +71,6 @@ list_for_each(lh, &hosts) { if (host == list_entry(lh, struct hpsb_host, host_list)) { if (try_module_get(host->driver->owner)) { - /* we're doing this twice and don't seem - to undo it.. --hch */ - (void)try_module_get(host->driver->owner); host->refcount++; retval = 1; } diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394-ioctl.h linux-2.5.64/drivers/ieee1394/ieee1394-ioctl.h --- linux-2.5.63-bk7/drivers/ieee1394/ieee1394-ioctl.h Mon Feb 24 11:05:07 2003 +++ linux-2.5.64/drivers/ieee1394/ieee1394-ioctl.h Mon Mar 31 12:22:20 2003 @@ -4,8 +4,8 @@ #ifndef __IEEE1394_IOCTL_H #define __IEEE1394_IOCTL_H -#include -#include +#include +#include /* AMDTP Gets 6 */ @@ -91,7 +91,7 @@ #define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \ _IOW ('#', 0x23, unsigned char) #define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \ - _IOW ('#', 0x24, u64) + _IOW ('#', 0x24, __u64) #define RAW1394_IOC_ISO_RECV_PACKETS \ _IOW ('#', 0x25, struct raw1394_iso_packets) #define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \ diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_core.c linux-2.5.64/drivers/ieee1394/ieee1394_core.c --- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_core.c Mon Feb 24 11:05:12 2003 +++ linux-2.5.64/drivers/ieee1394/ieee1394_core.c Mon Mar 31 12:22:20 2003 @@ -361,7 +361,7 @@ host->topology_map[host->selfid_count++] = sid; } else { HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d", - sid, (host->node_id & BUS_MASK) >> 6); + sid, NODEID_TO_BUS(host->node_id)); } } @@ -396,9 +396,6 @@ /* irm_id is kept up to date by check_selfids() */ if (host->irm_id == host->node_id) { host->is_irm = 1; - host->is_busmgr = 1; - host->busmgr_id = host->node_id; - host->csr.bus_manager_id = host->node_id; } else { host->is_busmgr = 0; host->is_irm = 0; @@ -535,8 +532,8 @@ if (packet->type == hpsb_async && packet->node_id != ALL_NODES) { packet->speed_code = - host->speed_map[(host->node_id & NODE_MASK) * 64 - + (packet->node_id & NODE_MASK)]; + host->speed_map[NODEID_TO_NODE(host->node_id) * 64 + + NODEID_TO_NODE(packet->node_id)]; } #ifdef CONFIG_IEEE1394_VERBOSEDEBUG @@ -748,7 +745,7 @@ addr, 4, flags); if (!write_acked - && (((data[0] >> 16) & NODE_MASK) != NODE_MASK) + && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) && (rcode >= 0)) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); @@ -763,7 +760,7 @@ addr, data[3]>>16, flags); if (!write_acked - && (((data[0] >> 16) & NODE_MASK) != NODE_MASK) + && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) && (rcode >= 0)) { /* not a broadcast write, reply */ PREP_REPLY_PACKET(0); @@ -1248,6 +1245,7 @@ EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_lock); EXPORT_SYMBOL(hpsb_lock64); +EXPORT_SYMBOL(hpsb_send_gasp); EXPORT_SYMBOL(hpsb_packet_success); /** highlevel.c **/ diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.c linux-2.5.64/drivers/ieee1394/ieee1394_transactions.c --- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.c Mon Feb 24 11:05:15 2003 +++ linux-2.5.64/drivers/ieee1394/ieee1394_transactions.c Mon Mar 31 12:22:20 2003 @@ -98,6 +98,17 @@ packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */ } +static void fill_async_stream_packet(struct hpsb_packet *packet, int length, + int channel, int tag, int sync) +{ + packet->header[0] = (length << 16) | (tag << 14) | (channel << 8) + | (TCODE_STREAM_DATA << 4) | sync; + + packet->header_size = 4; + packet->data_size = length; + packet->type = hpsb_async; + packet->tcode = TCODE_ISO_DATA; +} /** * hpsb_get_tlabel - allocate a transaction label @@ -495,7 +506,6 @@ } -/* We need a hpsb_lock64 function for the 64 bit equivalent. Probably. */ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, int extcode, quadlet_t *data, quadlet_t arg) { @@ -558,3 +568,58 @@ 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; +} diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.h linux-2.5.64/drivers/ieee1394/ieee1394_transactions.h --- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.h Mon Feb 24 11:05:14 2003 +++ linux-2.5.64/drivers/ieee1394/ieee1394_transactions.h Mon Mar 31 12:22:20 2003 @@ -55,5 +55,8 @@ u64 addr, int extcode, quadlet_t *data, quadlet_t arg); int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, u64 addr, int extcode, octlet_t *data, octlet_t arg); +int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, + quadlet_t *buffer, size_t length, u32 specifier_id, + unsigned int version); #endif /* _IEEE1394_TRANSACTIONS_H */ diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_types.h linux-2.5.64/drivers/ieee1394/ieee1394_types.h --- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_types.h Mon Feb 24 11:05:39 2003 +++ linux-2.5.64/drivers/ieee1394/ieee1394_types.h Mon Mar 31 12:22:20 2003 @@ -97,14 +97,17 @@ typedef u16 arm_length_t; #define BUS_MASK 0xffc0 +#define BUS_SHIFT 6 #define NODE_MASK 0x003f #define LOCAL_BUS 0xffc0 #define ALL_NODES 0x003f +#define NODEID_TO_BUS(nodeid) ((nodeid & BUS_MASK) >> BUS_SHIFT) +#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK) + /* Can be used to consistently print a node/bus ID. */ -#define NODE_BUS_FMT "%02d:%04d" -#define NODE_BUS_ARGS(nodeid) \ - (nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6) +#define NODE_BUS_FMT "%02d:%04d" +#define NODE_BUS_ARGS(nodeid) NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid) #define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args) diff -urN linux-2.5.63-bk7/drivers/ieee1394/nodemgr.c linux-2.5.64/drivers/ieee1394/nodemgr.c --- linux-2.5.63-bk7/drivers/ieee1394/nodemgr.c Mon Feb 24 11:05:34 2003 +++ linux-2.5.64/drivers/ieee1394/nodemgr.c Mon Mar 31 12:22:20 2003 @@ -1210,6 +1210,52 @@ return; } +/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other + * nodes of the broadcast channel. (Really we're only setting the validity + * bit). */ +static void nodemgr_do_irm_duties(struct hpsb_host *host) +{ + quadlet_t bc; + + if (!host->is_irm) + return; + + host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ + + bc = cpu_to_be32(host->csr.broadcast_channel); + + hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host), + (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), + &bc, + sizeof(quadlet_t)); +} + +/* We need to ensure that if we are not the IRM, that the IRM node is capable of + * everything we can do, otherwise issue a bus reset and try to become the IRM + * ourselves. */ +static int nodemgr_check_root_capability(struct hpsb_host *host) +{ + quadlet_t bc; + int status; + + if (host->is_irm) + return 1; + + status = hpsb_read(host, LOCAL_BUS | (host->irm_id), + get_hpsb_generation(host), + (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), + &bc, sizeof(quadlet_t)); + + if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { + /* The root node does not have a valid BROADCAST_CHANNEL + * register and we do, so reset the bus with force_root set */ + HPSB_INFO("Remote root is not IRM capable, resetting..."); + hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); + return 0; + } + return 1; +} + static int nodemgr_host_thread(void *__hi) { struct host_info *hi = (struct host_info *)__hi; @@ -1217,12 +1263,21 @@ /* No userlevel access needed */ daemonize("knodemgrd"); allow_signal(SIGTERM); - + /* Sit and wait for a signal to probe the nodes on the bus. This * happens when we get a bus reset. */ while (!down_interruptible(&hi->reset_sem) && !down_interruptible(&nodemgr_serialize)) { + + if (!nodemgr_check_root_capability(hi->host)) { + /* Do nothing, we are resetting */ + up(&nodemgr_serialize); + continue; + } + nodemgr_node_probe(hi->host); + nodemgr_do_irm_duties(hi->host); + up(&nodemgr_serialize); } #ifdef CONFIG_IEEE1394_VERBOSEDEBUG diff -urN linux-2.5.63-bk7/drivers/ieee1394/ohci1394.c linux-2.5.64/drivers/ieee1394/ohci1394.c --- linux-2.5.63-bk7/drivers/ieee1394/ohci1394.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/ieee1394/ohci1394.c Mon Mar 31 12:22:20 2003 @@ -31,9 +31,9 @@ * * Things implemented, but still in test phase: * . Iso Transmit + * . Async Stream Packets Transmit (Receive done via Iso interface) * * Things not implemented: - * . Async Stream Packets * . DMA error recovery * * Known bugs: @@ -160,7 +160,7 @@ printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) static char version[] __devinitdata = - "$Rev: 762 $ Ben Collins "; + "$Rev: 801 $ Ben Collins "; /* Module Parameters */ MODULE_PARM(phys_dma,"i"); @@ -649,18 +649,31 @@ } else { d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | (packet->header[0] & 0xFFFF); - d->prg_cpu[idx]->data[1] = - (packet->header[1] & 0xFFFF) | - (packet->header[0] & 0xFFFF0000); - d->prg_cpu[idx]->data[2] = packet->header[2]; - d->prg_cpu[idx]->data[3] = packet->header[3]; + + if (packet->tcode == TCODE_ISO_DATA) { + /* Sending an async stream packet */ + d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; + } else { + /* Sending a normal async request or response */ + d->prg_cpu[idx]->data[1] = + (packet->header[1] & 0xFFFF) | + (packet->header[0] & 0xFFFF0000); + d->prg_cpu[idx]->data[2] = packet->header[2]; + d->prg_cpu[idx]->data[3] = packet->header[3]; + } packet_swab(d->prg_cpu[idx]->data, packet->tcode); } if (packet->data_size) { /* block transmit */ - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_MORE | - DMA_CTL_IMMEDIATE | 0x10); + if (packet->tcode == TCODE_STREAM_DATA){ + d->prg_cpu[idx]->begin.control = + cpu_to_le32(DMA_CTL_OUTPUT_MORE | + DMA_CTL_IMMEDIATE | 0x8); + } else { + d->prg_cpu[idx]->begin.control = + cpu_to_le32(DMA_CTL_OUTPUT_MORE | + DMA_CTL_IMMEDIATE | 0x10); + } d->prg_cpu[idx]->end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_IRQ | @@ -830,7 +843,7 @@ /* Decide whether we have an iso, a request, or a response packet */ if (packet->type == hpsb_raw) d = &ohci->at_req_context; - else if (packet->tcode == TCODE_ISO_DATA) { + else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) { /* The legacy IT DMA context is initialized on first * use. However, the alloc cannot be run from * interrupt context, so we bail out if that is the @@ -856,7 +869,7 @@ } d = &ohci->it_legacy_context; - } else if (packet->tcode & 0x02) + } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA)) d = &ohci->at_resp_context; else d = &ohci->at_req_context; @@ -1295,6 +1308,8 @@ u32 *prev_branch = NULL; for (blk = 0; blk < recv->nblocks; blk++) { + u32 control; + /* the DMA descriptor */ struct dma_cmd *cmd = &recv->block[blk]; @@ -1305,29 +1320,29 @@ unsigned long buf_offset = blk * recv->buf_stride; if (recv->dma_mode == BUFFER_FILL_MODE) { - cmd->control = 2 << 28; /* INPUT_MORE */ + control = 2 << 28; /* INPUT_MORE */ } else { - cmd->control = 3 << 28; /* INPUT_LAST */ + control = 3 << 28; /* INPUT_LAST */ } - cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */ + control |= 8 << 24; /* s = 1, update xferStatus and resCount */ /* interrupt on last block, and at intervals */ if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) { - cmd->control |= 3 << 20; /* want interrupt */ + control |= 3 << 20; /* want interrupt */ } - cmd->control |= 3 << 18; /* enable branch to address */ - cmd->control |= recv->buf_stride; + control |= 3 << 18; /* enable branch to address */ + control |= recv->buf_stride; - cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset); + cmd->control = cpu_to_le32(control); + cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset)); cmd->branchAddress = 0; /* filled in on next loop */ - cmd->status = recv->buf_stride; + cmd->status = cpu_to_le32(recv->buf_stride); /* link the previous descriptor to this one */ if (prev_branch) { - *prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset); - *prev_branch |= 1; /* set Z=1 */ + *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1); } prev_branch = &cmd->branchAddress; @@ -1485,18 +1500,18 @@ /* 'next' becomes the new end of the DMA chain, so disable branch and enable interrupt */ next->branchAddress = 0; - next->control |= 3 << 20; + next->control |= cpu_to_le32(3 << 20); /* link prev to next */ - prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog, - sizeof(struct dma_cmd) * next_i) - | 1; /* Z=1 */ + prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, + sizeof(struct dma_cmd) * next_i) + | 1); /* Z=1 */ /* disable interrupt on previous DMA descriptor, except at intervals */ if((prev_i % recv->block_irq_interval) == 0) { - prev->control |= 3 << 20; /* enable interrupt */ + prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */ } else { - prev->control &= ~(3<<20); /* disable interrupt */ + prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */ } wmb(); @@ -1720,8 +1735,8 @@ struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma; /* check the DMA descriptor for new writes to xferStatus */ - u16 xferstatus = il->status >> 16; - u16 rescount = il->status & 0xFFFF; + u16 xferstatus = le32_to_cpu(il->status) >> 16; + u16 rescount = le32_to_cpu(il->status) & 0xFFFF; unsigned char event = xferstatus & 0x1F; @@ -1903,7 +1918,7 @@ struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma); /* check for new writes to xferStatus */ - u16 xferstatus = cmd->output_last.status >> 16; + u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16; u8 event = xferstatus & 0x1F; if(!event) { @@ -1919,7 +1934,7 @@ wake = 1; /* parse cycle */ - cycle = cmd->output_last.status & 0x1FFF; + cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; /* tell the subsystem the packet has gone out */ hpsb_iso_packet_sent(iso, cycle, event != 0x11); @@ -1972,7 +1987,7 @@ /* set up the OUTPUT_MORE_IMMEDIATE descriptor */ memset(next, 0, sizeof(struct iso_xmit_cmd)); - next->output_more_immediate.control = 0x02000008; + next->output_more_immediate.control = cpu_to_le32(0x02000008); /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */ @@ -1990,28 +2005,28 @@ next->iso_hdr[7] = len >> 8; /* set up the OUTPUT_LAST */ - next->output_last.control = 1 << 28; - next->output_last.control |= 1 << 27; /* update timeStamp */ - next->output_last.control |= 3 << 20; /* want interrupt */ - next->output_last.control |= 3 << 18; /* enable branch */ - next->output_last.control |= len; + next->output_last.control = cpu_to_le32(1 << 28); + next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */ + next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */ + next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */ + next->output_last.control |= cpu_to_le32(len); /* payload bus address */ - next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset); + next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset)); /* leave branchAddress at zero for now */ /* re-write the previous DMA descriptor to chain to this one */ /* set prev branch address to point to next (Z=3) */ - prev->output_last.branchAddress = - dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3; + prev->output_last.branchAddress = cpu_to_le32( + dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); /* disable interrupt, unless required by the IRQ interval */ if(prev_i % iso->irq_interval) { - prev->output_last.control &= ~(3 << 20); /* no interrupt */ + prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ } else { - prev->output_last.control |= 3 << 20; /* enable interrupt */ + prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */ } wmb(); @@ -3473,10 +3488,10 @@ static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { { - .class = PCI_CLASS_FIREWIRE_OHCI, - .class_mask = 0x00ffffff, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, + .class = PCI_CLASS_FIREWIRE_OHCI, + .class_mask = ~0, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, diff -urN linux-2.5.63-bk7/drivers/ieee1394/raw1394.c linux-2.5.64/drivers/ieee1394/raw1394.c --- linux-2.5.63-bk7/drivers/ieee1394/raw1394.c Mon Mar 31 12:22:10 2003 +++ linux-2.5.64/drivers/ieee1394/raw1394.c Mon Mar 31 12:22:20 2003 @@ -238,7 +238,7 @@ list_del(&hi->list); host_count--; /* - FIXME: addressranges should be removed + FIXME: address ranges should be removed and fileinfo states should be initialized (including setting generation to internal-generation ...) @@ -281,8 +281,8 @@ req->req.misc = (host->node_id << 16) | host->node_count; if (fi->protocol_version > 3) { - req->req.misc |= ((host->irm_id - & NODE_MASK) << 8); + req->req.misc |= (NODEID_TO_NODE(host->irm_id) + << 8); } queue_complete_req(req); @@ -571,8 +571,7 @@ req->req.misc = (fi->host->node_id << 16) | fi->host->node_count; if (fi->protocol_version > 3) { - req->req.misc |= - (fi->host->irm_id & NODE_MASK) << 8; + req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8; } } else { req->req.error = RAW1394_ERROR_INVALID_ARG; diff -urN linux-2.5.63-bk7/drivers/ieee1394/sbp2.c linux-2.5.64/drivers/ieee1394/sbp2.c --- linux-2.5.63-bk7/drivers/ieee1394/sbp2.c Mon Feb 24 11:05:09 2003 +++ linux-2.5.64/drivers/ieee1394/sbp2.c Mon Mar 31 12:22:21 2003 @@ -27,30 +27,6 @@ * driver. It also registers as a SCSI lower-level driver in order to accept * SCSI commands for transport using SBP-2. * - * - * Driver Loading: - * - * Currently, the SBP-2 driver is supported only as a module. Because the - * Linux SCSI stack is not Plug-N-Play aware, module load order is - * important. Assuming the SCSI core drivers are either built into the - * kernel or already loaded as modules, you should load the IEEE-1394 modules - * in the following order: - * - * ieee1394 (e.g. insmod ieee1394) - * ohci1394 (e.g. insmod ohci1394) - * sbp2 (e.g. insmod sbp2) - * - * The SBP-2 driver will attempt to discover any attached SBP-2 devices when first - * loaded, or after any IEEE-1394 bus reset (e.g. a hot-plug). It will then print - * out a debug message indicating if it was able to discover a SBP-2 device. - * - * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the - * initial scsi bus scan (when the driver is first loaded). To add or remove - * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a - * device after the SBP-2 driver is loaded), you must either use the scsi procfs - * add-single-device, remove-single-device, or a shell script such as - * rescan-scsi-bus.sh. - * * The easiest way to add/detect new SBP-2 devices is to run the shell script * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be * found at: @@ -136,14 +112,6 @@ * - Error Handling: SCSI aborts and bus reset requests are handled somewhat * but the code needs additional debugging. * - * - Module: The SBP-2 driver is currently only supported as a module. It would not take - * much work to allow it to be compiled into the kernel, but you'd have to - * add some init code to the kernel to support this... and modules are much - * more flexible anyway. ;-) - * - * - Hot-plugging: Interaction with the SCSI stack and support for hot-plugging could - * stand some improvement. - * * * History: * @@ -295,10 +263,11 @@ * 04/23/02 - Fix for Sony CD-ROM drives. Only send fetch agent reset to sbp2 device if it * returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one. * 04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG) - * 06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG) + * 06/09/02 - Don't force 36-byte SCSI inquiry, but leave in a define for badly behaved devices. (JSG) * 02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command). * Also save/restore irq flags in sbp2scsi_complete_command - Sancho Dauskardt * 02/06/03 - Removed spinlock debugging; use kernel stuff instead (sda) + * 02/10/03 - Adopt to new hot-plug aware SCSI inferface (hch@lst.de) * */ @@ -350,7 +319,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 779 $ James Goodwin "; + "$Rev: 797 $ James Goodwin "; /* * Module load parameter definitions @@ -497,6 +466,15 @@ * Globals */ +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 *)); + static Scsi_Host_Template scsi_driver_template; static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 }; @@ -822,7 +800,7 @@ { struct sbp2scsi_host_info *hi; - hi = (struct sbp2scsi_host_info *) command->Current_SCpnt->device->host->hostdata[0]; + hi = (struct sbp2scsi_host_info *)&command->Current_SCpnt->device->host->hostdata; if (hi == NULL) { printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__); @@ -871,59 +849,6 @@ * IEEE-1394 core driver stack related section *********************************************/ -/* - * This function is called at SCSI init in order to register our driver - * with the IEEE-1394 stack. - */ -int sbp2_init(void) -{ - SBP2_DEBUG("sbp2_init"); - - /* - * Register our high level driver with 1394 stack - */ - sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops); - - if (sbp2_hl_handle == NULL) { - SBP2_ERR("sbp2 failed to register with ieee1394 highlevel"); - return(-ENOMEM); - } - - /* - * Register our sbp2 status address space... - */ - hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS, - SBP2_STATUS_FIFO_ADDRESS + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1)); - - /* - * Handle data movement if physical dma is not enabled/supported on host controller - */ -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA - hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL); -#endif - - hpsb_register_protocol(&sbp2_driver); - - return 0; -} - -/* - * This function is called from cleanup module, or during shut-down, in - * order to unregister our driver. - */ -void sbp2_cleanup(void) -{ - SBP2_DEBUG("sbp2_cleanup"); - - hpsb_unregister_protocol(&sbp2_driver); - - if (sbp2_hl_handle) { - hpsb_unregister_highlevel(sbp2_hl_handle); - sbp2_hl_handle = NULL; - } -} - static int sbp2_probe(struct unit_directory *ud) { struct sbp2scsi_host_info *hi; @@ -999,35 +924,44 @@ { struct sbp2scsi_host_info *hi; unsigned long flags; + struct Scsi_Host *scsi_host; SBP2_DEBUG("sbp2_add_host"); - /* Allocate some memory for our host info structure */ - hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info), - in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL); - - if (hi == NULL) { - SBP2_ERR("out of memory in sbp2_add_host"); + /* Register our host with the SCSI stack. */ + scsi_host = scsi_register (&scsi_driver_template, sizeof(struct sbp2scsi_host_info)); + if (!scsi_host) { + SBP2_ERR("failed to register scsi host"); return; } - /* Initialize some host stuff */ + hi = (struct sbp2scsi_host_info *)&scsi_host->hostdata; memset(hi, 0, sizeof(struct sbp2scsi_host_info)); + + hi->scsi_host = scsi_host; INIT_LIST_HEAD(&hi->list); hi->host = host; hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; + hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; spin_lock_irqsave(&sbp2_host_info_lock, flags); list_add_tail(&hi->list, &sbp2_host_info_list); spin_unlock_irqrestore(&sbp2_host_info_lock, flags); - /* Register our host with the SCSI stack. */ - hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *)); - if (hi->scsi_host) { - hi->scsi_host->hostdata[0] = (unsigned long)hi; - hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; + /* + * XXX(hch): Hopefully the ieee1394 code will be converted + * to the driver model at some point. Until that happens + * we'll have to pass in NULL here. + */ + if (scsi_add_host(hi->scsi_host, NULL)) { + SBP2_ERR("failed to add scsi host"); + + spin_lock_irqsave(&sbp2_host_info_lock, flags); + list_del(&hi->list); + spin_unlock_irqrestore(&sbp2_host_info_lock, flags); + + scsi_unregister(hi->scsi_host); } - scsi_driver_template.present++; return; } @@ -1079,16 +1013,15 @@ SBP2_DEBUG("sbp2_remove_host"); spin_lock_irqsave(&sbp2_host_info_lock, flags); - hi = sbp2_find_host_info(host); - if (hi != NULL) { + if (hi) list_del(&hi->list); - kfree(hi); - } - else - SBP2_ERR("attempt to remove unknown host %p", host); - spin_unlock_irqrestore(&sbp2_host_info_lock, flags); + + if (hi) { + scsi_remove_host(hi->scsi_host); + scsi_unregister(hi->scsi_host); + } } /* @@ -1098,6 +1031,7 @@ static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud) { struct scsi_id_instance_data *scsi_id = NULL; + struct scsi_device *sdev; struct node_entry *ne; int i; @@ -1203,7 +1137,7 @@ /* * Find an empty spot to stick our scsi id instance data. */ - for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) { + for (i = 0; i < hi->scsi_host->max_id; i++) { if (!hi->scsi_id[i]) { hi->scsi_id[i] = scsi_id; scsi_id->id = i; @@ -1224,7 +1158,7 @@ /* * Make sure we are not out of space */ - if (i == SBP2SCSI_MAX_SCSI_IDS) { + if (i == hi->scsi_host->max_id) { SBP2_ERR("No slots left for SBP-2 device"); sbp2_remove_device(hi, scsi_id); return -EBUSY; @@ -1256,6 +1190,13 @@ */ sbp2_max_speed_and_size(hi, scsi_id); + /* Add this device to the scsi layer now */ + sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0); + if (IS_ERR(sdev)) { + SBP2_ERR("scsi_add_device failed"); + return PTR_ERR(sdev); + } + return 0; } @@ -1265,13 +1206,21 @@ static void sbp2_remove_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) { + struct scsi_device *sdev = scsi_find_device(hi->scsi_host, 0, scsi_id->id, 0); + SBP2_DEBUG("sbp2_remove_device"); /* Complete any pending commands with selection timeout */ sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT); - + + /* Remove it from the scsi layer now */ + if (scsi_remove_device(sdev)) + SBP2_ERR("scsi_remove_device failed"); + sbp2util_remove_command_orb_pool(scsi_id, hi); + hi->scsi_id[scsi_id->id] = NULL; + if (scsi_id->login_response) { pci_free_consistent(hi->host->pdev, sizeof(struct sbp2_login_response), @@ -1305,7 +1254,7 @@ } SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id); - hi->scsi_id[scsi_id->id] = NULL; + kfree(scsi_id); } @@ -1793,8 +1742,8 @@ SBP2_DEBUG("sbp2_max_speed_and_size"); /* Initial setting comes from the hosts speed map */ - scsi_id->speed_code = hi->host->speed_map[(hi->host->node_id & NODE_MASK) * 64 - + (scsi_id->ne->nodeid & NODE_MASK)]; + scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 + + NODEID_TO_NODE(scsi_id->ne->nodeid)]; /* Bump down our speed if the user requested it */ if (scsi_id->speed_code > sbp2_max_speed) { @@ -2661,7 +2610,7 @@ /* * Pull our host info and scsi id instance data from the scsi command */ - hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0]; + hi = (struct sbp2scsi_host_info *) &SCpnt->device->host->hostdata; if (!hi) { SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); @@ -2766,8 +2715,10 @@ * * This can be called in interrupt context. */ -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 *)) +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 *)) { unsigned long flags; @@ -2888,7 +2839,7 @@ */ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0]; + struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata; struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; struct sbp2_command_info *command; unsigned long flags; @@ -2938,7 +2889,7 @@ */ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0]; + struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata; struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; SBP2_ERR("reset requested"); @@ -2951,93 +2902,81 @@ return(SUCCESS); } -/* - * Called by scsi stack to get bios parameters (used by fdisk, and at boot). - */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,43) -static int sbp2scsi_biosparam (struct scsi_device *sdev, - struct block_device *dev, sector_t capacity, int geom[]) +static const char *sbp2scsi_info (struct Scsi_Host *host) { -#else -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]) + return "SCSI emulation for for IEEE-1394 Storage Devices"; +} + +/* Called for contents of procfs */ +#define SPRINTF(args...) \ + do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) + +static int sbp2scsi_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) { - unsigned capacity = disk->capacity; -#endif - int heads, sectors, cylinders; + Scsi_Device *scd; + struct Scsi_Host *host; + struct sbp2scsi_host_info *hi; + char *pos = buffer; - SBP2_DEBUG("Request for bios parameters"); + /* if someone is sending us data, just throw it away */ + if (inout) + return length; - heads = 64; - sectors = 32; - cylinders = (int)capacity / (heads * sectors); + host = scsi_host_hn_get(hostno); + if (!host) /* if we couldn't find it, we return an error */ + return -ESRCH; - if (cylinders > 1024) { - heads = 255; - sectors = 63; - cylinders = (int)capacity / (heads * sectors); - } + hi = sbp2_find_host_info_scsi(host); + if (!hi) /* shouldn't happen, but... */ + return -ESRCH; - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; + SPRINTF("Host scsi%d : SBP-2 IEEE-1394 (%s)\n", hostno, + hi->host->driver->name); + SPRINTF("Driver version : %s\n", version); - return(0); -} + SPRINTF("\nModule options :\n"); + SPRINTF(" sbp2_max_speed : %s\n", hpsb_speedto_str[sbp2_max_speed]); + SPRINTF(" sbp2_max_sectors : %d\n", sbp2_max_sectors); + SPRINTF(" sbp2_serialize_io : %s\n", sbp2_serialize_io ? "yes" : "no"); + SPRINTF(" sbp2_exclusive_login : %s\n", sbp2_exclusive_login ? "yes" : "no"); -/* - * Called by scsi stack after scsi driver is registered - */ -static int sbp2scsi_detect (Scsi_Host_Template *tpnt) -{ - SBP2_DEBUG("sbp2scsi_detect"); + SPRINTF("\nAttached devices : %s\n", !list_empty(&host->my_devices) ? + "" : "none"); - /* - * Call sbp2_init to register with the ieee1394 stack. This - * results in a callback to sbp2_add_host for each ieee1394 - * host controller currently registered, and for each of those - * we register a scsi host with the scsi stack. - */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_unlock_irq(&io_request_lock); - sbp2_init(); - spin_lock_irq(&io_request_lock); -#else - sbp2_init(); -#endif + list_for_each_entry (scd, &host->my_devices, siblings) { + int i; - /* We return the number of hosts registered. */ - return scsi_driver_template.present; -} + SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, + scd->id, scd->lun); + SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? + scsi_device_types[(short) scd->type] : "Unknown device"); + for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) + SPRINTF("%c", scd->vendor[i]); -/* - * Called for contents of procfs - */ -static const char *sbp2scsi_info (struct Scsi_Host *host) -{ - struct sbp2scsi_host_info *hi = sbp2_find_host_info_scsi(host); - static char info[1024]; + SPRINTF(" "); - if (!hi) /* shouldn't happen, but... */ - return "IEEE-1394 SBP-2 protocol driver"; + for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) + SPRINTF("%c", scd->model[i]); + + SPRINTF("\n"); + } - sprintf(info, "IEEE-1394 SBP-2 protocol driver (host: %s)\n%s\n" - "SBP-2 module load options:\n" - "- Max speed supported: %s\n" - "- Max sectors per I/O supported: %d\n" - "- Serialized I/O (debug): %s\n" - "- Exclusive login: %s", - hi->host->driver->name, - version, - hpsb_speedto_str[sbp2_max_speed], - sbp2_max_sectors, - sbp2_serialize_io ? "yes" : "no", - sbp2_exclusive_login ? "yes" : "no"); + SPRINTF("\n"); - return info; -} + /* release the reference count on this host */ + scsi_host_put(host); + /* Calculate start of next buffer, and return value. */ + *start = buffer + offset; + if ((pos - buffer) < offset) + return (0); + else if ((pos - buffer - offset) < length) + return (pos - buffer - offset); + else + return (length); +} MODULE_AUTHOR("James Goodwin "); MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); @@ -3046,25 +2985,23 @@ /* SCSI host template */ static Scsi_Host_Template scsi_driver_template = { - .name = "IEEE-1394 SBP-2 protocol driver", - .info = sbp2scsi_info, - .detect = sbp2scsi_detect, - .queuecommand = sbp2scsi_queuecommand, - .eh_abort_handler = sbp2scsi_abort, - .eh_device_reset_handler =sbp2scsi_reset, - .eh_bus_reset_handler = sbp2scsi_reset, - .eh_host_reset_handler =sbp2scsi_reset, - .bios_param = sbp2scsi_biosparam, - .this_id = -1, - .sg_tablesize = SG_ALL, - .use_clustering = ENABLE_CLUSTERING, - .cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, - .can_queue = SBP2_MAX_SCSI_QUEUE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - .use_new_eh_code = TRUE, -#endif - .emulated = 1, - .proc_name = SBP2_DEVICE_NAME, + .module = THIS_MODULE, + .name = "SBP-2 IEEE-1394", + .proc_name = SBP2_DEVICE_NAME, + .info = sbp2scsi_info, + .proc_info = sbp2scsi_proc_info, + .queuecommand = sbp2scsi_queuecommand, + .eh_abort_handler = sbp2scsi_abort, + .eh_device_reset_handler = sbp2scsi_reset, + .eh_bus_reset_handler = sbp2scsi_reset, + .eh_host_reset_handler = sbp2scsi_reset, + .this_id = -1, + .sg_tablesize = SG_ALL, + .use_clustering = ENABLE_CLUSTERING, + .cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, + .can_queue = SBP2_MAX_SCSI_QUEUE, + .emulated = 1, + .highmem_io = 1, }; static int sbp2_module_init(void) @@ -3084,23 +3021,36 @@ */ scsi_driver_template.max_sectors = sbp2_max_sectors; + /* - * Ideally we would register our scsi_driver_template with the - * scsi stack and after that register with the ieee1394 stack - * and process the add_host callbacks. However, the detect - * function in the scsi host template requires that we find at - * least one host, so we "nest" the registrations by calling - * sbp2_init from the detect function. - */ - scsi_driver_template.module = THIS_MODULE; - if (SCSI_REGISTER_HOST(&scsi_driver_template) || - !scsi_driver_template.present) { - SBP2_ERR("Please load the lower level IEEE-1394 driver " - "(e.g. ohci1394) before sbp2..."); - sbp2_cleanup(); - return -ENODEV; + * Register our high level driver with 1394 stack + */ + sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, + &sbp2_hl_ops); + if (!sbp2_hl_handle) { + SBP2_ERR("sbp2 failed to register with ieee1394 highlevel"); + return(-ENOMEM); } + /* + * Register our sbp2 status address space... + */ + hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, + SBP2_STATUS_FIFO_ADDRESS, + SBP2_STATUS_FIFO_ADDRESS + + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET( + SBP2SCSI_MAX_SCSI_IDS+1)); + + /* + * Handle data movement if physical dma is not enabled/supported + * on host controller + */ +#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA + hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops, + 0x0ULL, 0xfffffffcULL); +#endif + + hpsb_register_protocol(&sbp2_driver); return 0; } @@ -3108,17 +3058,9 @@ { SBP2_DEBUG("sbp2_module_exit"); - /* - * On module unload we unregister with the ieee1394 stack - * which results in remove_host callbacks for all ieee1394 - * host controllers. In the callbacks we unregister the - * corresponding scsi hosts. - */ - sbp2_cleanup(); - - if (SCSI_UNREGISTER_HOST(&scsi_driver_template)) - SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver"); - + hpsb_unregister_protocol(&sbp2_driver); + if (sbp2_hl_handle) + hpsb_unregister_highlevel(sbp2_hl_handle); } module_init(sbp2_module_init); diff -urN linux-2.5.63-bk7/drivers/ieee1394/sbp2.h linux-2.5.64/drivers/ieee1394/sbp2.h --- linux-2.5.63-bk7/drivers/ieee1394/sbp2.h Mon Feb 24 11:05:11 2003 +++ linux-2.5.64/drivers/ieee1394/sbp2.h Mon Mar 31 12:22:21 2003 @@ -22,15 +22,6 @@ #ifndef SBP2_H #define SBP2_H -/* Some compatibility code */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#define SCSI_REGISTER_HOST(tmpl) scsi_register_module(MODULE_SCSI_HA, tmpl) -#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_module(MODULE_SCSI_HA, tmpl) -#else -#define SCSI_REGISTER_HOST(tmpl) scsi_register_host(tmpl) -#define SCSI_UNREGISTER_HOST(tmpl) scsi_unregister_host(tmpl) -#endif - #define SBP2_DEVICE_NAME "sbp2" /* @@ -442,8 +433,6 @@ static void sbp2_add_host(struct hpsb_host *host); static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host); static void sbp2_remove_host(struct hpsb_host *host); -int sbp2_init(void); -void sbp2_cleanup(void); static int sbp2_probe(struct unit_directory *ud); static void sbp2_disconnect(struct unit_directory *ud); static void sbp2_update(struct unit_directory *ud); @@ -487,23 +476,4 @@ static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id); -/* - * Scsi interface related prototypes - */ -static int sbp2scsi_detect (Scsi_Host_Template *tpnt); -static const char *sbp2scsi_info (struct Scsi_Host *host); -void sbp2scsi_setup(char *str, int *ints); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44) -static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]); -#else -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]); -#endif -static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); -static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); -static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); -static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, - u32 status); -static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, - u32 scsi_status, Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); - #endif /* SBP2_H */ diff -urN linux-2.5.63-bk7/drivers/ieee1394/video1394.c linux-2.5.64/drivers/ieee1394/video1394.c --- linux-2.5.63-bk7/drivers/ieee1394/video1394.c Mon Feb 24 11:05:10 2003 +++ linux-2.5.64/drivers/ieee1394/video1394.c Mon Mar 31 12:22:21 2003 @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include "ieee1394.h" #include "ieee1394_types.h" @@ -1338,24 +1340,152 @@ MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME); MODULE_LICENSE("GPL"); +#ifdef CONFIG_COMPAT + +#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER \ + _IOW ('#', 0x12, struct video1394_wait32) +#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER \ + _IOWR('#', 0x13, struct video1394_wait32) +#define VIDEO1394_IOC32_TALK_WAIT_BUFFER \ + _IOW ('#', 0x17, struct video1394_wait32) +#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER \ + _IOWR('#', 0x18, struct video1394_wait32) + +struct video1394_wait32 { + u32 channel; + u32 buffer; + struct compat_timeval filltime; +}; + +static int video1394_wr_wait32(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *file) +{ + struct video1394_wait32 wait32; + struct video1394_wait wait; + mm_segment_t old_fs; + int ret; + + if (file->f_op->ioctl != video1394_ioctl) + return -EFAULT; + + if (copy_from_user(&wait32, (void *)arg, sizeof(wait32))) + return -EFAULT; + + wait.channel = wait32.channel; + wait.buffer = wait32.buffer; + wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec; + wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER) + ret = video1394_ioctl(file->f_dentry->d_inode, file, + VIDEO1394_IOC_LISTEN_WAIT_BUFFER, + (unsigned long) &wait); + else + ret = video1394_ioctl(file->f_dentry->d_inode, file, + VIDEO1394_IOC_LISTEN_POLL_BUFFER, + (unsigned long) &wait); + set_fs(old_fs); + + if (!ret) { + wait32.channel = wait.channel; + wait32.buffer = wait.buffer; + wait32.filltime.tv_sec = (int)wait.filltime.tv_sec; + wait32.filltime.tv_usec = (int)wait.filltime.tv_usec; + + if (copy_to_user((struct video1394_wait32 *)arg, &wait32, sizeof(wait32))) + ret = -EFAULT; + } + + return ret; +} + +static int video1394_w_wait32(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *file) +{ + struct video1394_wait32 wait32; + struct video1394_wait wait; + mm_segment_t old_fs; + int ret; + + if (file->f_op->ioctl != video1394_ioctl) + return -EFAULT; + + if (copy_from_user(&wait32, (void *)arg, sizeof(wait32))) + return -EFAULT; + + wait.channel = wait32.channel; + wait.buffer = wait32.buffer; + wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec; + wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER) + ret = video1394_ioctl(file->f_dentry->d_inode, file, + VIDEO1394_IOC_LISTEN_QUEUE_BUFFER, + (unsigned long) &wait); + else + ret = video1394_ioctl(file->f_dentry->d_inode, file, + VIDEO1394_IOC_TALK_WAIT_BUFFER, + (unsigned long) &wait); + set_fs(old_fs); + + return ret; +} + +static int video1394_queue_buf32(unsigned int fd, unsigned int cmd, unsigned long arg, + struct file *file) +{ + if (file->f_op->ioctl != video1394_ioctl) + return -EFAULT; + + return -EFAULT; + + return video1394_ioctl(file->f_dentry->d_inode, file, + VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg); +} + +#endif /* CONFIG_COMPAT */ + static void __exit video1394_exit_module (void) { +#ifdef CONFIG_COMPAT + int ret; + + ret = unregister_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER); + ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER); + if (ret) + PRINT_G(KERN_INFO, "Error unregistering ioctl32 translations"); +#endif + hpsb_unregister_highlevel (hl_handle); devfs_unregister(devfs_handle); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394); - + PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); } static int __init video1394_init_module (void) { - if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394, - THIS_MODULE, &video1394_fops)) { + int ret; + + ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394, + THIS_MODULE, &video1394_fops); + if (ret) { PRINT_G(KERN_ERR, "video1394: unable to get minor device block"); - return -EIO; - } - + return -EIO; + } + devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL); hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops); @@ -1366,9 +1496,32 @@ return -ENOMEM; } +#ifdef CONFIG_COMPAT + /* First the compatible ones */ + ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL); + ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL, NULL); + ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL, NULL); + ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL, NULL); + + /* These need translation */ + ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER, + video1394_w_wait32); + ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER, + video1394_wr_wait32); + ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER, + video1394_queue_buf32); + ret |= register_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER, + video1394_w_wait32); + ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER, + video1394_wr_wait32); + if (ret) + PRINT_G(KERN_INFO, "Error registering ioctl32 translations"); +#endif + PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module"); return 0; } + module_init(video1394_init_module); module_exit(video1394_exit_module); diff -urN linux-2.5.63-bk7/drivers/pnp/interface.c linux-2.5.64/drivers/pnp/interface.c --- linux-2.5.63-bk7/drivers/pnp/interface.c Mon Feb 24 11:05:10 2003 +++ linux-2.5.64/drivers/pnp/interface.c Mon Mar 31 12:22:22 2003 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "base.h" diff -urN linux-2.5.63-bk7/fs/dcache.c linux-2.5.64/fs/dcache.c --- linux-2.5.63-bk7/fs/dcache.c Mon Mar 31 12:22:11 2003 +++ linux-2.5.64/fs/dcache.c Mon Mar 31 12:22:24 2003 @@ -47,16 +47,8 @@ static unsigned int d_hash_mask; static unsigned int d_hash_shift; -static struct list_head *dentry_hashtable; +static struct hlist_head *dentry_hashtable; static LIST_HEAD(dentry_unused); -static int max_dentries; -static void * hashtable_end; - -static inline int is_bucket(void * addr) -{ - return ((addr < (void *)dentry_hashtable) - || (addr > hashtable_end) ? 0 : 1); -} /* Statistics gathering. */ struct dentry_stat_t dentry_stat = { @@ -292,6 +284,7 @@ while (next != head) { tmp = next; next = tmp->next; + prefetch(next); alias = list_entry(tmp, struct dentry, d_alias); if (!d_unhashed(alias)) { if (alias->d_flags & DCACHE_DISCONNECTED) @@ -378,6 +371,7 @@ if (tmp == &dentry_unused) break; list_del_init(tmp); + prefetch(dentry_unused.prev); dentry_stat.nr_unused--; dentry = list_entry(tmp, struct dentry, d_lru); @@ -603,15 +597,15 @@ * done under dcache_lock. * */ -void shrink_dcache_anon(struct list_head *head) +void shrink_dcache_anon(struct hlist_head *head) { - struct list_head *lp; + struct hlist_node *lp; int found; do { found = 0; spin_lock(&dcache_lock); - list_for_each(lp, head) { - struct dentry *this = list_entry(lp, struct dentry, d_hash); + hlist_for_each(lp, head) { + struct dentry *this = hlist_entry(lp, struct dentry, d_hash); list_del(&this->d_lru); /* don't add non zero d_count dentries @@ -727,7 +721,7 @@ dentry->d_mounted = 0; dentry->d_cookie = NULL; dentry->d_bucket = NULL; - INIT_LIST_HEAD(&dentry->d_hash); + INIT_HLIST_NODE(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); INIT_LIST_HEAD(&dentry->d_alias); @@ -797,7 +791,7 @@ return res; } -static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash) +static inline struct hlist_head * d_hash(struct dentry * parent, unsigned long hash) { hash += (unsigned long) parent / L1_CACHE_BYTES; hash = hash ^ (hash >> D_HASHBITS); @@ -860,7 +854,7 @@ res->d_flags |= DCACHE_DISCONNECTED; res->d_vfs_flags &= ~DCACHE_UNHASHED; list_add(&res->d_alias, &inode->i_dentry); - list_add(&res->d_hash, &inode->i_sb->s_anon); + hlist_add_head(&res->d_hash, &inode->i_sb->s_anon); spin_unlock(&res->d_lock); } inode = NULL; /* don't drop reference */ @@ -947,21 +941,21 @@ unsigned int len = name->len; unsigned int hash = name->hash; const unsigned char *str = name->name; - struct list_head *head = d_hash(parent,hash); + struct hlist_head *head = d_hash(parent,hash); struct dentry *found = NULL; - struct list_head *tmp; - int lookup_count = 0; + struct hlist_node *node; rcu_read_lock(); - /* lookup is terminated when flow reaches any bucket head */ - for(tmp = head->next; !is_bucket(tmp); tmp = tmp->next) { + hlist_for_each (node, head) { struct dentry *dentry; unsigned long move_count; struct qstr * qstr; + prefetch(node->next); + smp_read_barrier_depends(); - dentry = list_entry(tmp, struct dentry, d_hash); + dentry = hlist_entry(node, struct dentry, d_hash); /* if lookup ends up in a different bucket * due to concurrent rename, fail it @@ -969,12 +963,6 @@ if (unlikely(dentry->d_bucket != head)) break; - /* to avoid race if dentry keep coming back to original - * bucket due to double moves - */ - if (unlikely(++lookup_count > max_dentries)) - break; - /* * We must take a snapshot of d_move_count followed by * read memory barrier before any search key comparison @@ -1034,7 +1022,8 @@ unsigned long dent_addr = (unsigned long) dentry; unsigned long min_addr = PAGE_OFFSET; unsigned long align_mask = 0x0F; - struct list_head *base, *lhp; + struct hlist_head *base; + struct hlist_node *lhp; if (dent_addr < min_addr) goto out; @@ -1050,12 +1039,13 @@ goto out; spin_lock(&dcache_lock); - lhp = base = d_hash(dparent, dentry->d_name.hash); - while ((lhp = lhp->next) != base) { + base = d_hash(dparent, dentry->d_name.hash); + hlist_for_each(lhp,base) { + prefetch(lhp->next); /* read_barrier_depends() not required for d_hash list * as it is parsed under dcache_lock */ - if (dentry == list_entry(lhp, struct dentry, d_hash)) { + if (dentry == hlist_entry(lhp, struct dentry, d_hash)) { __dget_locked(dentry); spin_unlock(&dcache_lock); return 1; @@ -1116,12 +1106,11 @@ void d_rehash(struct dentry * entry) { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); + struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash); spin_lock(&dcache_lock); - if (!list_empty(&entry->d_hash) && !d_unhashed(entry)) BUG(); entry->d_vfs_flags &= ~DCACHE_UNHASHED; entry->d_bucket = list; - list_add_rcu(&entry->d_hash, list); + hlist_add_head_rcu(&entry->d_hash, list); spin_unlock(&dcache_lock); } @@ -1174,10 +1163,6 @@ * We could be nicer about the deleted file, and let it show * up under the name it got deleted rather than the name that * deleted it. - * - * Careful with the hash switch. The hash switch depends on - * the fact that any list-entry can be a head of the list. - * Think about it. */ /** @@ -1200,8 +1185,8 @@ /* Move the dentry to the target hash queue, if on different bucket */ if (dentry->d_bucket != target->d_bucket) { dentry->d_bucket = target->d_bucket; - list_del_rcu(&dentry->d_hash); - list_add_rcu(&dentry->d_hash, &target->d_hash); + hlist_del_rcu(&dentry->d_hash); + hlist_add_head_rcu(&dentry->d_hash, target->d_bucket); } /* Unhash the target: dput() will then get rid of it */ @@ -1284,6 +1269,7 @@ continue; } parent = dentry->d_parent; + prefetch(parent); namelen = dentry->d_name.len; buflen -= namelen + 1; if (buflen < 0) @@ -1503,7 +1489,7 @@ static void __init dcache_init(unsigned long mempages) { - struct list_head *d; + struct hlist_head *d; unsigned long order; unsigned int nr_hash; int i; @@ -1524,15 +1510,12 @@ if (!dentry_cache) panic("Cannot create dentry cache"); - /* approximate maximum number of dentries in one hash bucket */ - max_dentries = (mempages * (PAGE_SIZE / sizeof(struct dentry))); - set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory); #if PAGE_SHIFT < 13 mempages >>= (13 - PAGE_SHIFT); #endif - mempages *= sizeof(struct list_head); + mempages *= sizeof(struct hlist_head); for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) ; @@ -1540,7 +1523,7 @@ unsigned long tmp; nr_hash = (1UL << order) * PAGE_SIZE / - sizeof(struct list_head); + sizeof(struct hlist_head); d_hash_mask = (nr_hash - 1); tmp = nr_hash; @@ -1548,7 +1531,7 @@ while ((tmp >>= 1UL) != 0UL) d_hash_shift++; - dentry_hashtable = (struct list_head *) + dentry_hashtable = (struct hlist_head *) __get_free_pages(GFP_ATOMIC, order); } while (dentry_hashtable == NULL && --order >= 0); @@ -1558,12 +1541,10 @@ if (!dentry_hashtable) panic("Failed to allocate dcache hash table\n"); - hashtable_end = dentry_hashtable + nr_hash; - d = dentry_hashtable; i = nr_hash; do { - INIT_LIST_HEAD(d); + INIT_HLIST_HEAD(d); d++; i--; } while (i); diff -urN linux-2.5.63-bk7/fs/filesystems.c linux-2.5.64/fs/filesystems.c --- linux-2.5.63-bk7/fs/filesystems.c Mon Feb 24 11:05:40 2003 +++ linux-2.5.64/fs/filesystems.c Mon Mar 31 12:22:25 2003 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,38 @@ return p; } + +/* define fs_subsys */ +static decl_subsys(fs, NULL); + +static int register_fs_subsys(struct file_system_type * fs) +{ + struct subsystem *sub = &fs->subsys; + + snprintf(sub->kset.kobj.name, KOBJ_NAME_LEN, "%s", fs->name); + subsys_set_kset(fs, fs_subsys); + return subsystem_register(sub); +} + +static int unlink_fs(struct file_system_type * fs) +{ + struct file_system_type ** tmp; + + write_lock(&file_systems_lock); + tmp = &file_systems; + while (*tmp) { + if (fs == *tmp) { + *tmp = fs->next; + fs->next = NULL; + write_unlock(&file_systems_lock); + return 0; + } + tmp = &(*tmp)->next; + } + write_unlock(&file_systems_lock); + return -EINVAL; +} + /** * register_filesystem - register a new filesystem * @fs: the file system structure @@ -88,6 +121,14 @@ else *p = fs; write_unlock(&file_systems_lock); + + if (!res) { + /* we implicitly possess reference to @fs during registration, + * so it cannot be unregister from under us. */ + if (register_fs_subsys(fs)) + printk(KERN_WARNING "Failed to register '%s' in sysfs\n", + fs->name); + } return res; } @@ -105,21 +146,44 @@ int unregister_filesystem(struct file_system_type * fs) { - struct file_system_type ** tmp; + int res; - write_lock(&file_systems_lock); - tmp = &file_systems; - while (*tmp) { - if (fs == *tmp) { - *tmp = fs->next; - fs->next = NULL; - write_unlock(&file_systems_lock); - return 0; - } - tmp = &(*tmp)->next; - } - write_unlock(&file_systems_lock); - return -EINVAL; + res = unlink_fs(fs); + if (!res) + subsystem_unregister(&fs->subsys); + return res; +} + +extern int sysfs_init(void); + +/** + * fs_subsys_init - initialize sysfs and fs subsystem. + * + * In order to register filesystems in sysfs, it has to be + * initialized. Also, we need the base fs filesystem, so the + * registered filesystems have a home. + * + * During sysfs_init(), the registration of sysfs into itself + * will fail, since it's not mounted yet. To make sure that + * sysfs does show up, we re-register sysfs's embedded subsystem, + * which will get added, since sysfs is now mounted. + */ + +void __init fs_subsys_init(void) +{ + struct file_system_type ** p; + + /* make sure sysfs is up and running */ + sysfs_init(); + + /* register fs_subsys */ + subsystem_register(&fs_subsys); + + p = find_filesystem("sysfs"); + + if (p) + /* make sure it's registered */ + register_fs_subsys(*p); } static int fs_index(const char * __name) diff -urN linux-2.5.63-bk7/fs/fs-writeback.c linux-2.5.64/fs/fs-writeback.c --- linux-2.5.63-bk7/fs/fs-writeback.c Mon Feb 24 11:06:03 2003 +++ linux-2.5.64/fs/fs-writeback.c Mon Mar 31 12:22:25 2003 @@ -90,7 +90,7 @@ * Only add valid (hashed) inodes to the superblock's * dirty list. Add blockdev inodes as well. */ - if (list_empty(&inode->i_hash) && !S_ISBLK(inode->i_mode)) + if (hlist_unhashed(&inode->i_hash) && !S_ISBLK(inode->i_mode)) goto out; /* diff -urN linux-2.5.63-bk7/fs/hugetlbfs/inode.c linux-2.5.64/fs/hugetlbfs/inode.c --- linux-2.5.63-bk7/fs/hugetlbfs/inode.c Mon Feb 24 11:05:43 2003 +++ linux-2.5.64/fs/hugetlbfs/inode.c Mon Mar 31 12:22:25 2003 @@ -189,7 +189,7 @@ static void hugetlbfs_delete_inode(struct inode *inode) { - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); list_del_init(&inode->i_list); inode->i_state |= I_FREEING; inodes_stat.nr_inodes--; @@ -208,7 +208,7 @@ { struct super_block *super_block = inode->i_sb; - if (list_empty(&inode->i_hash)) + if (hlist_unhashed(&inode->i_hash)) goto out_truncate; if (!(inode->i_state & (I_DIRTY|I_LOCK))) { @@ -223,7 +223,7 @@ /* write_inode_now() ? */ inodes_stat.nr_unused--; - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); out_truncate: list_del_init(&inode->i_list); inode->i_state |= I_FREEING; diff -urN linux-2.5.63-bk7/fs/inode.c linux-2.5.64/fs/inode.c --- linux-2.5.63-bk7/fs/inode.c Mon Mar 31 12:22:11 2003 +++ linux-2.5.64/fs/inode.c Mon Mar 31 12:22:25 2003 @@ -69,8 +69,8 @@ LIST_HEAD(inode_in_use); LIST_HEAD(inode_unused); -static struct list_head *inode_hashtable; -static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */ +static struct hlist_head *inode_hashtable; +static HLIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */ /* * A simple spinlock to protect the list manipulations. @@ -172,7 +172,7 @@ void inode_init_once(struct inode *inode) { memset(inode, 0, sizeof(*inode)); - INIT_LIST_HEAD(&inode->i_hash); + INIT_HLIST_NODE(&inode->i_hash); INIT_LIST_HEAD(&inode->i_data.clean_pages); INIT_LIST_HEAD(&inode->i_data.dirty_pages); INIT_LIST_HEAD(&inode->i_data.locked_pages); @@ -294,7 +294,7 @@ continue; invalidate_inode_buffers(inode); if (!atomic_read(&inode->i_count)) { - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); list_del(&inode->i_list); list_add(&inode->i_list, dispose); inode->i_state |= I_FREEING; @@ -435,7 +435,7 @@ if (!can_unuse(inode)) continue; } - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); list_move(&inode->i_list, &freeable); inode->i_state |= I_FREEING; nr_pruned++; @@ -476,50 +476,42 @@ * by hand after calling find_inode now! This simplifies iunique and won't * add any additional branch in the common code. */ -static struct inode * find_inode(struct super_block * sb, struct list_head *head, int (*test)(struct inode *, void *), void *data) +static struct inode * find_inode(struct super_block * sb, struct hlist_head *head, int (*test)(struct inode *, void *), void *data) { - struct list_head *tmp; - struct inode * inode; + struct hlist_node *node; + struct inode * inode = NULL; - tmp = head; - for (;;) { - tmp = tmp->next; - inode = NULL; - if (tmp == head) - break; - inode = list_entry(tmp, struct inode, i_hash); + hlist_for_each (node, head) { + prefetch(node->next); + inode = hlist_entry(node, struct inode, i_hash); if (inode->i_sb != sb) continue; if (!test(inode, data)) continue; break; } - return inode; + return node ? inode : NULL; } /* * find_inode_fast is the fast path version of find_inode, see the comment at * iget_locked for details. */ -static struct inode * find_inode_fast(struct super_block * sb, struct list_head *head, unsigned long ino) +static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino) { - struct list_head *tmp; - struct inode * inode; + struct hlist_node *node; + struct inode * inode = NULL; - tmp = head; - for (;;) { - tmp = tmp->next; - inode = NULL; - if (tmp == head) - break; - inode = list_entry(tmp, struct inode, i_hash); + hlist_for_each (node, head) { + prefetch(node->next); + inode = list_entry(node, struct inode, i_hash); if (inode->i_ino != ino) continue; if (inode->i_sb != sb) continue; break; } - return inode; + return node ? inode : NULL; } /** @@ -569,7 +561,7 @@ * We no longer cache the sb_flags in i_flags - see fs.h * -- rmk@arm.uk.linux.org */ -static struct inode * get_new_inode(struct super_block *sb, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) +static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) { struct inode * inode; @@ -586,7 +578,7 @@ inodes_stat.nr_inodes++; list_add(&inode->i_list, &inode_in_use); - list_add(&inode->i_hash, head); + hlist_add_head(&inode->i_hash, head); inode->i_state = I_LOCK|I_NEW; spin_unlock(&inode_lock); @@ -619,7 +611,7 @@ * get_new_inode_fast is the fast path version of get_new_inode, see the * comment at iget_locked for details. */ -static struct inode * get_new_inode_fast(struct super_block *sb, struct list_head *head, unsigned long ino) +static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino) { struct inode * inode; @@ -634,7 +626,7 @@ inode->i_ino = ino; inodes_stat.nr_inodes++; list_add(&inode->i_list, &inode_in_use); - list_add(&inode->i_hash, head); + hlist_add_head(&inode->i_hash, head); inode->i_state = I_LOCK|I_NEW; spin_unlock(&inode_lock); @@ -686,7 +678,7 @@ { static ino_t counter = 0; struct inode *inode; - struct list_head * head; + struct hlist_head * head; ino_t res; spin_lock(&inode_lock); retry: @@ -740,7 +732,7 @@ * Note, @test is called with the inode_lock held, so can't sleep. */ static inline struct inode *ifind(struct super_block *sb, - struct list_head *head, int (*test)(struct inode *, void *), + struct hlist_head *head, int (*test)(struct inode *, void *), void *data) { struct inode *inode; @@ -772,7 +764,7 @@ * Otherwise NULL is returned. */ static inline struct inode *ifind_fast(struct super_block *sb, - struct list_head *head, unsigned long ino) + struct hlist_head *head, unsigned long ino) { struct inode *inode; @@ -810,7 +802,7 @@ struct inode *ilookup5(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), void *data) { - struct list_head *head = inode_hashtable + hash(sb, hashval); + struct hlist_head *head = inode_hashtable + hash(sb, hashval); return ifind(sb, head, test, data); } @@ -832,7 +824,7 @@ */ struct inode *ilookup(struct super_block *sb, unsigned long ino) { - struct list_head *head = inode_hashtable + hash(sb, ino); + struct hlist_head *head = inode_hashtable + hash(sb, ino); return ifind_fast(sb, head, ino); } @@ -864,7 +856,7 @@ int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) { - struct list_head *head = inode_hashtable + hash(sb, hashval); + struct hlist_head *head = inode_hashtable + hash(sb, hashval); struct inode *inode; inode = ifind(sb, head, test, data); @@ -897,7 +889,7 @@ */ struct inode *iget_locked(struct super_block *sb, unsigned long ino) { - struct list_head *head = inode_hashtable + hash(sb, ino); + struct hlist_head *head = inode_hashtable + hash(sb, ino); struct inode *inode; inode = ifind_fast(sb, head, ino); @@ -923,11 +915,11 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval) { - struct list_head *head = &anon_hash_chain; + struct hlist_head *head = &anon_hash_chain; if (inode->i_sb) head = inode_hashtable + hash(inode->i_sb, hashval); spin_lock(&inode_lock); - list_add(&inode->i_hash, head); + hlist_add_head(&inode->i_hash, head); spin_unlock(&inode_lock); } @@ -941,7 +933,7 @@ void remove_inode_hash(struct inode *inode) { spin_lock(&inode_lock); - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); spin_unlock(&inode_lock); } @@ -949,7 +941,7 @@ { struct super_operations *op = inode->i_sb->s_op; - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); list_del_init(&inode->i_list); inode->i_state|=I_FREEING; inodes_stat.nr_inodes--; @@ -978,7 +970,7 @@ { struct super_block *sb = inode->i_sb; - if (!list_empty(&inode->i_hash)) { + if (!hlist_unhashed(&inode->i_hash)) { if (!(inode->i_state & (I_DIRTY|I_LOCK))) { list_del(&inode->i_list); list_add(&inode->i_list, &inode_unused); @@ -990,7 +982,7 @@ write_inode_now(inode, 1); spin_lock(&inode_lock); inodes_stat.nr_unused--; - list_del_init(&inode->i_hash); + hlist_del_init(&inode->i_hash); } list_del_init(&inode->i_list); inode->i_state|=I_FREEING; @@ -1236,7 +1228,7 @@ */ void __init inode_init(unsigned long mempages) { - struct list_head *head; + struct hlist_head *head; unsigned long order; unsigned int nr_hash; int i; @@ -1253,7 +1245,7 @@ unsigned long tmp; nr_hash = (1UL << order) * PAGE_SIZE / - sizeof(struct list_head); + sizeof(struct hlist_head); i_hash_mask = (nr_hash - 1); tmp = nr_hash; @@ -1261,7 +1253,7 @@ while ((tmp >>= 1UL) != 0UL) i_hash_shift++; - inode_hashtable = (struct list_head *) + inode_hashtable = (struct hlist_head *) __get_free_pages(GFP_ATOMIC, order); } while (inode_hashtable == NULL && --order >= 0); @@ -1274,7 +1266,7 @@ head = inode_hashtable; i = nr_hash; do { - INIT_LIST_HEAD(head); + INIT_HLIST_HEAD(head); head++; i--; } while (i); diff -urN linux-2.5.63-bk7/fs/namespace.c linux-2.5.64/fs/namespace.c --- linux-2.5.63-bk7/fs/namespace.c Mon Feb 24 11:05:36 2003 +++ linux-2.5.64/fs/namespace.c Mon Mar 31 12:22:25 2003 @@ -26,6 +26,7 @@ extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); extern int do_remount_sb(struct super_block *sb, int flags, void * data); extern int __init init_rootfs(void); +extern int __init fs_subsys_init(void); static struct list_head *mount_hashtable; static int hash_mask, hash_bits; @@ -1132,6 +1133,7 @@ d++; i--; } while (i); + fs_subsys_init(); init_rootfs(); init_mount_tree(); } diff -urN linux-2.5.63-bk7/fs/super.c linux-2.5.64/fs/super.c --- linux-2.5.63-bk7/fs/super.c Mon Feb 24 11:05:31 2003 +++ linux-2.5.64/fs/super.c Mon Mar 31 12:22:25 2003 @@ -63,7 +63,7 @@ INIT_LIST_HEAD(&s->s_io); INIT_LIST_HEAD(&s->s_files); INIT_LIST_HEAD(&s->s_instances); - INIT_LIST_HEAD(&s->s_anon); + INIT_HLIST_HEAD(&s->s_anon); init_rwsem(&s->s_umount); sema_init(&s->s_lock, 1); down_write(&s->s_umount); diff -urN linux-2.5.63-bk7/fs/sysfs/bin.c linux-2.5.64/fs/sysfs/bin.c --- linux-2.5.63-bk7/fs/sysfs/bin.c Mon Mar 31 12:22:11 2003 +++ linux-2.5.64/fs/sysfs/bin.c Mon Mar 31 12:22:25 2003 @@ -226,6 +226,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) { sysfs_hash_and_remove(kobj->dentry,attr->attr.name); + return 0; } EXPORT_SYMBOL(sysfs_create_bin_file); diff -urN linux-2.5.63-bk7/fs/sysfs/mount.c linux-2.5.64/fs/sysfs/mount.c --- linux-2.5.63-bk7/fs/sysfs/mount.c Mon Mar 31 12:22:11 2003 +++ linux-2.5.64/fs/sysfs/mount.c Mon Mar 31 12:22:25 2003 @@ -7,6 +7,7 @@ #include #include #include +#include #include "sysfs.h" @@ -65,7 +66,7 @@ .kill_sb = kill_litter_super, }; -static int __init sysfs_init(void) +int __init sysfs_init(void) { int err; @@ -80,5 +81,3 @@ } return err; } - -core_initcall(sysfs_init); diff -urN linux-2.5.63-bk7/include/linux/dcache.h linux-2.5.64/include/linux/dcache.h --- linux-2.5.63-bk7/include/linux/dcache.h Mon Mar 31 12:22:11 2003 +++ linux-2.5.64/include/linux/dcache.h Mon Mar 31 12:22:26 2003 @@ -76,25 +76,25 @@ atomic_t d_count; unsigned long d_vfs_flags; /* moved here to be on same cacheline */ 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 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_child; /* child of parent list */ struct list_head d_subdirs; /* our children */ 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 */ struct dentry_operations *d_op; struct super_block * d_sb; /* The root of the dentry tree */ + unsigned int d_flags; + int d_mounted; void * d_fsdata; /* fs-specific data */ struct rcu_head d_rcu; 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 */ } ____cacheline_aligned; @@ -171,7 +171,7 @@ static __inline__ void __d_drop(struct dentry * dentry) { 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) @@ -198,7 +198,7 @@ extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern void shrink_dcache_sb(struct super_block *); 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 *); /* only used at mount-time */ diff -urN linux-2.5.63-bk7/include/linux/fs.h linux-2.5.64/include/linux/fs.h --- linux-2.5.63-bk7/include/linux/fs.h Mon Mar 31 12:22:11 2003 +++ linux-2.5.64/include/linux/fs.h Mon Mar 31 12:22:26 2003 @@ -18,6 +18,7 @@ #include #include #include +#include #include struct iovec; @@ -353,7 +354,7 @@ }; struct inode { - struct list_head i_hash; + struct hlist_node i_hash; struct list_head i_list; struct list_head i_dentry; unsigned long i_ino; @@ -601,7 +602,7 @@ struct list_head s_dirty; /* dirty inodes */ struct list_head s_io; /* parked for writeback */ - struct list_head s_anon; /* anonymous dentries for (nfs) exporting */ + struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ struct list_head s_files; struct block_device *s_bdev; @@ -610,6 +611,7 @@ char s_id[32]; /* Informational name */ + struct kobject kobj; /* anchor for sysfs */ void *s_fs_info; /* Filesystem private info */ /* @@ -913,6 +915,7 @@ struct file_system_type { const char *name; + struct subsystem subsys; int fs_flags; struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *); void (*kill_sb) (struct super_block *); diff -urN linux-2.5.63-bk7/include/linux/list.h linux-2.5.64/include/linux/list.h --- linux-2.5.63-bk7/include/linux/list.h Mon Feb 24 11:05:33 2003 +++ linux-2.5.64/include/linux/list.h Mon Mar 31 12:22:26 2003 @@ -319,6 +319,98 @@ for (pos = (head)->next, n = pos->next; pos != (head); \ 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 #warning "don't include kernel headers in userspace" #endif /* __KERNEL__ */ diff -urN linux-2.5.63-bk7/init/main.c linux-2.5.64/init/main.c --- linux-2.5.63-bk7/init/main.c Mon Feb 24 11:05:11 2003 +++ linux-2.5.64/init/main.c Mon Mar 31 12:22:26 2003 @@ -71,6 +71,7 @@ extern void radix_tree_init(void); extern void free_initmem(void); extern void populate_rootfs(void); +extern void driver_init(void); #ifdef CONFIG_TC extern void tc_init(void); @@ -476,6 +477,8 @@ */ static void __init do_basic_setup(void) { + driver_init(); + #ifdef CONFIG_SYSCTL sysctl_init(); #endif diff -urN linux-2.5.63-bk7/net/sunrpc/rpc_pipe.c linux-2.5.64/net/sunrpc/rpc_pipe.c --- linux-2.5.63-bk7/net/sunrpc/rpc_pipe.c Mon Feb 24 11:05:14 2003 +++ linux-2.5.64/net/sunrpc/rpc_pipe.c Mon Mar 31 12:22:27 2003 @@ -479,7 +479,7 @@ rpc_depopulate(struct dentry *parent) { struct inode *dir = parent->d_inode; - LIST_HEAD(head); + HLIST_HEAD(head); struct list_head *pos, *next; struct dentry *dentry; @@ -490,12 +490,12 @@ if (!d_unhashed(dentry)) { dget_locked(dentry); __d_drop(dentry); - list_add(&dentry->d_hash, &head); + hlist_add_head(&dentry->d_hash, &head); } } spin_unlock(&dcache_lock); - while (!list_empty(&head)) { - dentry = list_entry(head.next, struct dentry, d_hash); + while (!hlist_empty(&head)) { + dentry = list_entry(head.first, struct dentry, d_hash); /* Private list, so no dcache_lock needed and use __d_drop */ __d_drop(dentry); if (dentry->d_inode) {