## Automatically generated incremental diff ## From: linux-2.5.69-bk8 ## To: linux-2.5.69-bk9 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.69-bk8/Makefile linux-2.5.69-bk9/Makefile --- linux-2.5.69-bk8/Makefile 2003-05-14 04:43:37.000000000 -0700 +++ linux-2.5.69-bk9/Makefile 2003-05-14 04:43:42.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 69 -EXTRAVERSION = -bk8 +EXTRAVERSION = -bk9 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.69-bk8/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.5.69-bk9/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- linux-2.5.69-bk8/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2003-05-14 04:43:37.000000000 -0700 +++ linux-2.5.69-bk9/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2003-05-14 04:43:42.000000000 -0700 @@ -24,6 +24,7 @@ #include #include #include +#include #include "powernow-k7.h" diff -urN linux-2.5.69-bk8/arch/i386/kernel/process.c linux-2.5.69-bk9/arch/i386/kernel/process.c --- linux-2.5.69-bk8/arch/i386/kernel/process.c 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk9/arch/i386/kernel/process.c 2003-05-14 04:43:42.000000000 -0700 @@ -529,12 +529,12 @@ struct task_struct *p; unsigned long clone_flags; unsigned long newsp; - int *parent_tidptr, *child_tidptr; + int __user *parent_tidptr, *child_tidptr; clone_flags = regs.ebx; newsp = regs.ecx; - parent_tidptr = (int *)regs.edx; - child_tidptr = (int *)regs.edi; + parent_tidptr = (int __user *)regs.edx; + child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); diff -urN linux-2.5.69-bk8/arch/i386/lib/usercopy.c linux-2.5.69-bk9/arch/i386/lib/usercopy.c --- linux-2.5.69-bk8/arch/i386/lib/usercopy.c 2003-05-14 04:43:37.000000000 -0700 +++ linux-2.5.69-bk9/arch/i386/lib/usercopy.c 2003-05-14 04:43:42.000000000 -0700 @@ -12,14 +12,16 @@ #include #include -static inline int movsl_is_ok(const void *a1, const void *a2, unsigned long n) +static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n) { #ifdef CONFIG_X86_INTEL_USERCOPY - if (n >= 64 && (((const long)a1 ^ (const long)a2) & movsl_mask.mask)) + if (n >= 64 && ((a1 ^ a2) & movsl_mask.mask)) return 0; #endif return 1; } +#define movsl_is_ok(a1,a2,n) \ + __movsl_is_ok((unsigned long)(a1),(unsigned long)(a2),(n)) /* * Copy a null terminated string from userspace. @@ -74,7 +76,7 @@ * and returns @count. */ long -__strncpy_from_user(char *dst, const char *src, long count) +__strncpy_from_user(char *dst, const char __user *src, long count) { long res; __do_strncpy_from_user(dst, src, count, res); @@ -100,7 +102,7 @@ * and returns @count. */ long -strncpy_from_user(char *dst, const char *src, long count) +strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) @@ -145,7 +147,7 @@ * On success, this will be zero. */ unsigned long -clear_user(void *to, unsigned long n) +clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) __do_clear_user(to, n); @@ -164,7 +166,7 @@ * On success, this will be zero. */ unsigned long -__clear_user(void *to, unsigned long n) +__clear_user(void __user *to, unsigned long n) { __do_clear_user(to, n); return n; @@ -181,7 +183,7 @@ * On exception, returns 0. * If the string is too long, returns a value greater than @n. */ -long strnlen_user(const char *s, long n) +long strnlen_user(const char __user *s, long n) { unsigned long mask = -__addr_ok(s); unsigned long res, tmp; @@ -484,7 +486,7 @@ } while (0) -unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n) +unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) { #ifndef CONFIG_X86_WP_WORKS_OK if (unlikely(boot_cpu_data.wp_works_ok == 0) && @@ -534,17 +536,17 @@ } #endif if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); + __copy_user((void *)to, from, n); else - n = __copy_user_intel(to, from, n); + n = __copy_user_intel((void *)to, from, n); return n; } -unsigned long __copy_from_user_ll(void *to, const void *from, unsigned long n) +unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned long n) { if (movsl_is_ok(to, from, n)) - __copy_user_zeroing(to, from, n); + __copy_user_zeroing(to, (const void *) from, n); else - n = __copy_user_zeroing_intel(to, from, n); + n = __copy_user_zeroing_intel(to, (const void *) from, n); return n; } diff -urN linux-2.5.69-bk8/arch/sparc64/defconfig linux-2.5.69-bk9/arch/sparc64/defconfig --- linux-2.5.69-bk8/arch/sparc64/defconfig 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk9/arch/sparc64/defconfig 2003-05-14 04:43:42.000000000 -0700 @@ -477,7 +477,16 @@ # CONFIG_SCTP_ADLER32 is not set # CONFIG_SCTP_DBG_MSG is not set # CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_ATM is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y CONFIG_VLAN_8021Q=m CONFIG_LLC=m CONFIG_LLC_UI=y @@ -487,17 +496,24 @@ # CONFIG_DEV_APPLETALK is not set CONFIG_DECNET=m CONFIG_DECNET_SIOCGIFCONF=y -# CONFIG_DECNET_ROUTER is not set +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m CONFIG_BRIDGE=m CONFIG_BRIDGE_NF_EBTABLES=m CONFIG_BRIDGE_EBT_T_FILTER=m CONFIG_BRIDGE_EBT_T_NAT=m CONFIG_BRIDGE_EBT_BROUTE=m CONFIG_BRIDGE_EBT_LOG=m -CONFIG_BRIDGE_EBT_IPF=m -CONFIG_BRIDGE_EBT_ARPF=m -CONFIG_BRIDGE_EBT_VLANF=m -CONFIG_BRIDGE_EBT_MARKF=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_DNAT=m CONFIG_BRIDGE_EBT_REDIRECT=m @@ -517,6 +533,7 @@ CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_ATM=y CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m @@ -632,13 +649,14 @@ # CONFIG_ROADRUNNER is not set CONFIG_PLIP=m CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set +CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m CONFIG_PPPOE=m +CONFIG_PPPOATM=m CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y @@ -647,7 +665,19 @@ # # Wireless LAN (non-hamradio) # -# CONFIG_NET_RADIO is not set +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_AIRO is not set +# CONFIG_HERMES is not set +CONFIG_NET_WIRELESS=y # # Token Ring devices (depends on LLC=y) @@ -663,6 +693,30 @@ # CONFIG_WAN is not set # +# ATM drivers +# +CONFIG_ATM_TCP=m +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +CONFIG_ATM_FORE200E_PCA=y +CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_SBA=y +CONFIG_ATM_FORE200E_SBA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E=m +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y + +# # Amateur Radio support # CONFIG_HAMRADIO=y @@ -759,9 +813,11 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=m CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y CONFIG_JBD=m # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1127,7 +1183,9 @@ CONFIG_USB_RIO500=m # CONFIG_USB_BRLVGER is not set CONFIG_USB_LCD=m +CONFIG_USB_SPEEDTOUCH=m CONFIG_USB_TEST=m +# CONFIG_USB_GADGET is not set # # Bluetooth support diff -urN linux-2.5.69-bk8/drivers/atm/he.c linux-2.5.69-bk9/drivers/atm/he.c --- linux-2.5.69-bk8/drivers/atm/he.c 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/atm/he.c 2003-05-14 04:43:42.000000000 -0700 @@ -128,7 +128,7 @@ #include -#define hprintk(fmt,args...) printk(KERN_ERR DEV_LABEL "%d: " fmt, he_dev->number, ##args) +#define hprintk(fmt,args...) printk(KERN_ERR DEV_LABEL "%d: " fmt, he_dev->number , ##args) #undef DEBUG #ifdef DEBUG diff -urN linux-2.5.69-bk8/drivers/bluetooth/hci_ldisc.c linux-2.5.69-bk9/drivers/bluetooth/hci_ldisc.c --- linux-2.5.69-bk8/drivers/bluetooth/hci_ldisc.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk9/drivers/bluetooth/hci_ldisc.c 2003-05-14 04:43:42.000000000 -0700 @@ -535,6 +535,7 @@ hci_uart_ldisc.receive_room= hci_uart_tty_room; hci_uart_ldisc.receive_buf = hci_uart_tty_receive; hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup; + hci_uart_ldisc.owner = THIS_MODULE; if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { BT_ERR("HCI line discipline registration failed. (%d)", err); diff -urN linux-2.5.69-bk8/drivers/char/agp/Makefile linux-2.5.69-bk9/drivers/char/agp/Makefile --- linux-2.5.69-bk8/drivers/char/agp/Makefile 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/agp/Makefile 2003-05-14 04:43:42.000000000 -0700 @@ -1,4 +1,4 @@ -agpgart-y := backend.o frontend.o generic.o generic-3.0.o +agpgart-y := backend.o frontend.o generic.o isoch.o obj-$(CONFIG_AGP) += agpgart.o obj-$(CONFIG_AGP_ALI) += ali-agp.o diff -urN linux-2.5.69-bk8/drivers/char/agp/agp.h linux-2.5.69-bk9/drivers/char/agp/agp.h --- linux-2.5.69-bk8/drivers/char/agp/agp.h 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/agp/agp.h 2003-05-14 04:43:42.000000000 -0700 @@ -139,6 +139,8 @@ int max_memory_agp; /* in number of pages */ int aperture_size_idx; int capndx; + char major_version; + char minor_version; }; #define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr)) @@ -388,27 +390,38 @@ int agp_num_entries(void); u32 agp_collect_device_status(u32 mode, u32 command); void agp_device_command(u32 command, int agp_v3); -int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor); +int agp_3_0_enable(struct agp_bridge_data *bridge, u32 mode); +int agp_3_5_enable(struct agp_bridge_data *bridge, u32 mode); void global_cache_flush(void); +void get_agp_version(struct agp_bridge_data *bridge); /* Standard agp registers */ #define AGPSTAT 0x4 #define AGPCMD 0x8 +#define AGPNISTAT 0xc #define AGPNEPG 0x16 +#define AGPNICMD 0x20 #define AGP_MAJOR_VERSION_SHIFT (20) #define AGP_MINOR_VERSION_SHIFT (16) #define AGPSTAT_RQ_DEPTH (0xff000000) +#define AGPSTAT_CAL_MASK (1<<12|1<<11|1<<10) +#define AGPSTAT_ARQSZ (1<<15|1<<14|1<<13) #define AGPSTAT_ARQSZ_SHIFT 13 -#define AGPSTAT_AGP_ENABLE (1<<8) #define AGPSTAT_SBA (1<<9) +#define AGPSTAT_AGP_ENABLE (1<<8) +#define AGPSTAT_FW (1<<4) +#define AGPSTAT_MODE_3_0 (1<<3) #define AGPSTAT2_1X (1<<0) #define AGPSTAT2_2X (1<<1) #define AGPSTAT2_4X (1<<2) -#define AGPSTAT_FW (1<<4) + +#define AGPSTAT3_RSVD (1<<2) +#define AGPSTAT3_8X (1<<1) +#define AGPSTAT3_4X (1) #endif /* _AGP_BACKEND_PRIV_H */ diff -urN linux-2.5.69-bk8/drivers/char/agp/amd-k8-agp.c linux-2.5.69-bk9/drivers/char/agp/amd-k8-agp.c --- linux-2.5.69-bk8/drivers/char/agp/amd-k8-agp.c 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/agp/amd-k8-agp.c 2003-05-14 04:43:42.000000000 -0700 @@ -253,8 +253,10 @@ { struct agp_bridge_data *bridge; struct pci_dev *loop_dev; + u8 rev_id; u8 cap_ptr; int i = 0; + char *revstring=" "; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) @@ -266,14 +268,38 @@ if (!bridge) return -ENOMEM; + /* Assume here we have an 8151. (Later this assumption will be fixed). */ + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); + switch (rev_id) { + case 0x01: revstring="A0"; + break; + case 0x02: revstring="A1"; + break; + case 0x11: revstring="B0"; + break; + case 0x12: revstring="B1"; + break; + case 0x13: revstring="B2"; + break; + default: revstring="??"; + break; + } + printk ("Detected AMD 8151 AGP Bridge rev %s", revstring); + /* + * Work around errata. + * Chips before B2 stepping incorrectly reporting v3.5 + */ + if (rev_id < 0x13) { + bridge->major_version = 3; + bridge->minor_version = 0; + } + bridge->driver = &amd_8151_driver; bridge->dev = pdev; bridge->capndx = cap_ptr; /* Fill in the mode register */ - pci_read_config_dword(pdev, - bridge->capndx+PCI_AGP_STATUS, - &bridge->mode); + pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); /* cache pci_devs of northbridges. */ pci_for_each_dev(loop_dev) { @@ -290,7 +316,7 @@ pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); - out_free: +out_free: agp_put_bridge(bridge); return -ENOMEM; } diff -urN linux-2.5.69-bk8/drivers/char/agp/generic-3.0.c linux-2.5.69-bk9/drivers/char/agp/generic-3.0.c --- linux-2.5.69-bk8/drivers/char/agp/generic-3.0.c 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/agp/generic-3.0.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,537 +0,0 @@ -/* - * Generic routines for AGP 3.0 compliant bridges. - */ - -#include -#include -#include -#include - -#include "agp.h" - -/* Generic AGP 3.0 enabling routines */ - -struct agp_3_0_dev { - struct list_head list; - u8 capndx; - u32 maxbw; - struct pci_dev *dev; -}; - -static void agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new) -{ - struct agp_3_0_dev *cur, *n = list_entry(new, struct agp_3_0_dev, list); - struct list_head *pos; - - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - if(cur->maxbw > n->maxbw) - break; - } - list_add_tail(new, pos); -} - -static void agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs) -{ - struct agp_3_0_dev *cur; - struct pci_dev *dev; - struct list_head *pos, *tmp, *head = &list->list, *start = head->next; - u32 nistat; - - INIT_LIST_HEAD(head); - - for(pos = start; pos != head;) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - pci_read_config_dword(dev, cur->capndx + 0x0c, &nistat); - cur->maxbw = (nistat >> 16) & 0xff; - - tmp = pos; - pos = pos->next; - agp_3_0_dev_list_insert(head, tmp); - } -} - -/* - * Initialize all isochronous transfer parameters for an AGP 3.0 - * node (i.e. a host bridge in combination with the adapters - * lying behind it...) - */ - -static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge, - struct agp_3_0_dev *dev_list, unsigned int ndevs) -{ - /* - * Convenience structure to make the calculations clearer - * here. The field names come straight from the AGP 3.0 spec. - */ - struct isoch_data { - u32 maxbw; - u32 n; - u32 y; - u32 l; - u32 rq; - struct agp_3_0_dev *dev; - }; - - struct pci_dev *td = bridge->dev, *dev; - struct list_head *head = &dev_list->list, *pos; - struct agp_3_0_dev *cur; - struct isoch_data *master, target; - unsigned int cdev = 0; - u32 mnistat, tnistat, tstatus, mcmd; - u16 tnicmd, mnicmd; - u8 mcapndx; - u32 tot_bw = 0, tot_n = 0, tot_rq = 0, y_max, rq_isoch, rq_async; - u32 step, rem, rem_isoch, rem_async; - int ret = 0; - - /* - * We'll work with an array of isoch_data's (one for each - * device in dev_list) throughout this function. - */ - if((master = kmalloc(ndevs * sizeof(*master), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto get_out; - } - - /* - * Sort the device list by maxbw. We need to do this because the - * spec suggests that the devices with the smallest requirements - * have their resources allocated first, with all remaining resources - * falling to the device with the largest requirement. - * - * We don't exactly do this, we divide target resources by ndevs - * and split them amongst the AGP 3.0 devices. The remainder of such - * division operations are dropped on the last device, sort of like - * the spec mentions it should be done. - * - * We can't do this sort when we initially construct the dev_list - * because we don't know until this function whether isochronous - * transfers are enabled and consequently whether maxbw will mean - * anything. - */ - agp_3_0_dev_list_sort(dev_list, ndevs); - - pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat); - pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus); - - /* Extract power-on defaults from the target */ - target.maxbw = (tnistat >> 16) & 0xff; - target.n = (tnistat >> 8) & 0xff; - target.y = (tnistat >> 6) & 0x3; - target.l = (tnistat >> 3) & 0x7; - target.rq = (tstatus >> 24) & 0xff; - - y_max = target.y; - - /* - * Extract power-on defaults for each device in dev_list. Along - * the way, calculate the total isochronous bandwidth required - * by these devices and the largest requested payload size. - */ - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - mcapndx = cur->capndx; - - pci_read_config_dword(dev, cur->capndx + 0x0c, &mnistat); - - master[cdev].maxbw = (mnistat >> 16) & 0xff; - master[cdev].n = (mnistat >> 8) & 0xff; - master[cdev].y = (mnistat >> 6) & 0x3; - master[cdev].dev = cur; - - tot_bw += master[cdev].maxbw; - y_max = max(y_max, master[cdev].y); - - cdev++; - } - - /* Check if this configuration has any chance of working */ - if(tot_bw > target.maxbw) { - printk(KERN_ERR PFX "isochronous bandwidth required " - "by AGP 3.0 devices exceeds that which is supported by " - "the AGP 3.0 bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - target.y = y_max; - - /* - * Write the calculated payload size into the target's NICMD - * register. Doing this directly effects the ISOCH_N value - * in the target's NISTAT register, so we need to do this now - * to get an accurate value for ISOCH_N later. - */ - pci_read_config_word(td, bridge->capndx + 0x20, &tnicmd); - tnicmd &= ~(0x3 << 6); - tnicmd |= target.y << 6; - pci_write_config_word(td, bridge->capndx + 0x20, tnicmd); - - /* Reread the target's ISOCH_N */ - pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat); - target.n = (tnistat >> 8) & 0xff; - - /* Calculate the minimum ISOCH_N needed by each master */ - for(cdev = 0; cdev < ndevs; cdev++) { - master[cdev].y = target.y; - master[cdev].n = master[cdev].maxbw / (master[cdev].y + 1); - - tot_n += master[cdev].n; - } - - /* Exit if the minimal ISOCH_N allocation among the masters is more - * than the target can handle. */ - if(tot_n > target.n) { - printk(KERN_ERR PFX "number of isochronous " - "transactions per period required by AGP 3.0 devices " - "exceeds that which is supported by the AGP 3.0 " - "bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - /* Calculate left over ISOCH_N capability in the target. We'll give - * this to the hungriest device (as per the spec) */ - rem = target.n - tot_n; - - /* - * Calculate the minimum isochronous RQ depth needed by each master. - * Along the way, distribute the extra ISOCH_N capability calculated - * above. - */ - for(cdev = 0; cdev < ndevs; cdev++) { - /* - * This is a little subtle. If ISOCH_Y > 64B, then ISOCH_Y - * byte isochronous writes will be broken into 64B pieces. - * This means we need to budget more RQ depth to account for - * these kind of writes (each isochronous write is actually - * many writes on the AGP bus). - */ - master[cdev].rq = master[cdev].n; - if(master[cdev].y > 0x1) { - master[cdev].rq *= (1 << (master[cdev].y - 1)); - } - - tot_rq += master[cdev].rq; - - if(cdev == ndevs - 1) - master[cdev].n += rem; - } - - /* Figure the number of isochronous and asynchronous RQ slots the - * target is providing. */ - rq_isoch = (target.y > 0x1) ? target.n * (1 << (target.y - 1)) : target.n; - rq_async = target.rq - rq_isoch; - - /* Exit if the minimal RQ needs of the masters exceeds what the target - * can provide. */ - if(tot_rq > rq_isoch) { - printk(KERN_ERR PFX "number of request queue slots " - "required by the isochronous bandwidth requested by " - "AGP 3.0 devices exceeds the number provided by the " - "AGP 3.0 bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - /* Calculate asynchronous RQ capability in the target (per master) as - * well as the total number of leftover isochronous RQ slots. */ - step = rq_async / ndevs; - rem_async = step + (rq_async % ndevs); - rem_isoch = rq_isoch - tot_rq; - - /* Distribute the extra RQ slots calculated above and write our - * isochronous settings out to the actual devices. */ - for(cdev = 0; cdev < ndevs; cdev++) { - cur = master[cdev].dev; - dev = cur->dev; - - mcapndx = cur->capndx; - - master[cdev].rq += (cdev == ndevs - 1) - ? (rem_async + rem_isoch) : step; - - pci_read_config_word(dev, cur->capndx + 0x20, &mnicmd); - pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd); - - mnicmd &= ~(0xff << 8); - mnicmd &= ~(0x3 << 6); - mcmd &= ~(0xff << 24); - - mnicmd |= master[cdev].n << 8; - mnicmd |= master[cdev].y << 6; - mcmd |= master[cdev].rq << 24; - - pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd); - pci_write_config_word(dev, cur->capndx + 0x20, mnicmd); - } - -free_and_exit: - kfree(master); - -get_out: - return ret; -} - -/* - * This function basically allocates request queue slots among the - * AGP 3.0 systems in nonisochronous nodes. The algorithm is - * pretty stupid, divide the total number of RQ slots provided by the - * target by ndevs. Distribute this many slots to each AGP 3.0 device, - * giving any left over slots to the last device in dev_list. - */ -static void agp_3_0_nonisochronous_node_enable(struct agp_bridge_data *bridge, - struct agp_3_0_dev *dev_list, unsigned int ndevs) -{ - struct agp_3_0_dev *cur; - struct list_head *head = &dev_list->list, *pos; - u32 tstatus, mcmd; - u32 trq, mrq, rem; - unsigned int cdev = 0; - - pci_read_config_dword(bridge->dev, bridge->capndx + 0x04, &tstatus); - - trq = (tstatus >> 24) & 0xff; - mrq = trq / ndevs; - - rem = mrq + (trq % ndevs); - - for(pos = head->next; cdev < ndevs; cdev++, pos = pos->next) { - cur = list_entry(pos, struct agp_3_0_dev, list); - - pci_read_config_dword(cur->dev, cur->capndx+AGPCMD, &mcmd); - mcmd &= ~(0xff << 24); - mcmd |= ((cdev == ndevs - 1) ? rem : mrq) << 24; - pci_write_config_dword(cur->dev, cur->capndx+AGPCMD, mcmd); - } -} - -/* - * Fully configure and enable an AGP 3.0 host bridge and all the devices - * lying behind it. - */ -int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor) -{ - struct pci_dev *td = bridge->dev, *dev; - u8 mcapndx; - u32 isoch, arqsz, cal_cycle, tmp, rate; - u32 tstatus, tcmd, mcmd, mstatus, ncapid; - u32 mmajor, mminor; - u16 mpstat; - struct agp_3_0_dev *dev_list, *cur; - struct list_head *head, *pos; - unsigned int ndevs = 0; - int ret = 0; - - /* - * Allocate a head for our AGP 3.0 device list (multiple AGP 3.0 - * devices are allowed behind a single bridge). - */ - if((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto get_out; - } - head = &dev_list->list; - INIT_LIST_HEAD(head); - - /* Find all AGP devices, and add them to dev_list. */ - pci_for_each_dev(dev) { - mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); - switch ((dev->class >>8) & 0xff00) { - case 0x0600: /* Bridge */ - /* Skip bridges. We should call this function for each one. */ - continue; - - case 0x0001: /* Unclassified device */ - /* Don't know what this is, but log it for investigation. */ - if (mcapndx != 0) { - printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n", - dev->vendor, dev->device); - } - continue; - - case 0x0300: /* Display controller */ - case 0x0400: /* Multimedia controller */ - if (mcapndx == 0) - continue; - - if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto free_and_exit; - } - cur->dev = dev; - - pos = &cur->list; - list_add(pos, head); - ndevs++; - continue; - - default: - continue; - } - } - - /* Extract some power-on defaults from the target */ - pci_read_config_dword(td, bridge->capndx + 0x04, &tstatus); - isoch = (tstatus >> 17) & 0x1; - arqsz = (tstatus >> 13) & 0x7; - cal_cycle = (tstatus >> 10) & 0x7; - rate = tstatus & 0x7; - - /* - * Take an initial pass through the devices lying behind our host - * bridge. Make sure each one is actually an AGP 3.0 device, otherwise - * exit with an error message. Along the way store the AGP 3.0 - * cap_ptr for each device, the minimum supported cal_cycle, and the - * minimum supported data rate. - */ - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - pci_read_config_word(dev, PCI_STATUS, &mpstat); - if((mpstat & PCI_STATUS_CAP_LIST) == 0) - continue; - - pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &mcapndx); - if (mcapndx != 0x00) { - do { - pci_read_config_dword(dev, mcapndx, &ncapid); - if ((ncapid & 0xff) != 0x02) - mcapndx = (ncapid >> 8) & 0xff; - } - while (((ncapid & 0xff) != 0x02) && (mcapndx != 0x00)); - } - - if(mcapndx == 0) { - printk(KERN_ERR PFX "woah! Non-AGP device " - "found on the secondary bus of an AGP 3.0 bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; - mminor = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; - - if(mmajor < 3) { - printk(KERN_ERR PFX "woah! AGP 2.0 device " - "found on the secondary bus of an AGP 3.0 " - "bridge operating with AGP 3.0 electricals!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - cur->capndx = mcapndx; - - pci_read_config_dword(dev, cur->capndx + 0x04, &mstatus); - - if(((mstatus >> 3) & 0x1) == 0) { - printk(KERN_ERR PFX "woah! AGP 3.0 device " - "not operating in AGP 3.0 mode found on the " - "secondary bus of an AGP 3.0 bridge operating " - "with AGP 3.0 electricals!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - tmp = (mstatus >> 10) & 0x7; - cal_cycle = min(cal_cycle, tmp); - - /* figure the lesser rate */ - tmp = mstatus & 0x7; - if(tmp < rate) - rate = tmp; - - } - - /* Turn rate into something we can actually write out to AGPCMD */ - switch(rate) { - case 0x1: - case 0x2: - break; - case 0x3: - rate = 0x2; - break; - default: - printk(KERN_ERR PFX "woah! Bogus AGP rate (%d) " - "value found advertised behind an AGP 3.0 bridge!\n", rate); - ret = -ENODEV; - goto free_and_exit; - } - - /* - * Call functions to divide target resources amongst the AGP 3.0 - * masters. This process is dramatically different depending on - * whether isochronous transfers are supported. - */ - if (isoch) { - ret = agp_3_0_isochronous_node_enable(bridge, dev_list, ndevs); - if (ret) { - printk(KERN_INFO PFX "Something bad happened setting " - "up isochronous xfers. Falling back to " - "non-isochronous xfer mode.\n"); - } - } - agp_3_0_nonisochronous_node_enable(bridge, dev_list, ndevs); - - /* - * Set the calculated minimum supported cal_cycle and minimum - * supported transfer rate in the target's AGPCMD register. - * Also set the AGP_ENABLE bit, effectively 'turning on' the - * target (this has to be done _before_ turning on the masters). - */ - pci_read_config_dword(td, bridge->capndx+AGPCMD, &tcmd); - - tcmd &= ~(0x7 << 10); - tcmd &= ~0x7; - - tcmd |= cal_cycle << 10; - tcmd |= 0x1 << 8; - tcmd |= rate; - - pci_write_config_dword(td, bridge->capndx+AGPCMD, tcmd); - - /* - * Set the target's advertised arqsz value, the minimum supported - * transfer rate, and the AGP_ENABLE bit in each master's AGPCMD - * register. - */ - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - mcapndx = cur->capndx; - - pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd); - - mcmd &= ~(0x7 << AGPSTAT_ARQSZ_SHIFT); - mcmd &= ~0x7; - - mcmd |= arqsz << 13; - mcmd |= AGPSTAT_AGP_ENABLE; - mcmd |= rate; - - pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd); - } - -free_and_exit: - /* Be sure to free the dev_list */ - for(pos = head->next; pos != head;) { - cur = list_entry(pos, struct agp_3_0_dev, list); - - pos = pos->next; - kfree(cur); - } - kfree(dev_list); - -get_out: - return ret; -} - -EXPORT_SYMBOL_GPL(agp_3_0_node_enable); - diff -urN linux-2.5.69-bk8/drivers/char/agp/generic.c linux-2.5.69-bk9/drivers/char/agp/generic.c --- linux-2.5.69-bk8/drivers/char/agp/generic.c 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/agp/generic.c 2003-05-14 04:43:42.000000000 -0700 @@ -270,14 +270,16 @@ int agp_copy_info(agp_kern_info * info) { memset(info, 0, sizeof(agp_kern_info)); - if (agp_bridge->type == NOT_SUPPORTED) { - info->chipset = agp_bridge->type; + if (!agp_bridge || agp_bridge->type == NOT_SUPPORTED || + !agp_bridge->version) { + info->chipset = NOT_SUPPORTED; return -EIO; } + info->version.major = agp_bridge->version->major; info->version.minor = agp_bridge->version->minor; - info->device = agp_bridge->dev; info->chipset = agp_bridge->type; + info->device = agp_bridge->dev; info->mode = agp_bridge->mode; info->aper_base = agp_bridge->gart_bus_addr; info->aper_size = agp_return_size(); @@ -366,60 +368,106 @@ /* Generic Agp routines - Start */ +static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp) +{ + /* disable SBA if it's not supported */ + if (!((*cmd & AGPSTAT_SBA) && (*tmp & AGPSTAT_SBA) && (*mode & AGPSTAT_SBA))) + *cmd &= ~AGPSTAT_SBA; + + /* disable FW if it's not supported */ + if (!((*cmd & AGPSTAT_FW) && (*tmp & AGPSTAT_FW) && (*mode & AGPSTAT_FW))) + *cmd &= ~AGPSTAT_FW; + + /* Set speed */ + if (!((*cmd & AGPSTAT2_4X) && (*tmp & AGPSTAT2_4X) && (*mode & AGPSTAT2_4X))) + *cmd &= ~AGPSTAT2_4X; + + if (!((*cmd & AGPSTAT2_2X) && (*tmp & AGPSTAT2_2X) && (*mode & AGPSTAT2_2X))) + *cmd &= ~AGPSTAT2_2X; + + if (!((*cmd & AGPSTAT2_1X) && (*tmp & AGPSTAT2_1X) && (*mode & AGPSTAT2_1X))) + *cmd &= ~AGPSTAT2_1X; -u32 agp_collect_device_status(u32 mode, u32 command) + /* Now we know what mode it should be, clear out the unwanted bits. */ + if (*cmd & AGPSTAT2_4X) + *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */ + + if (*cmd & AGPSTAT2_2X) + *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ + + if (*cmd & AGPSTAT2_1X) + *cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1Xf */ +} + + +static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp) +{ + /* ARQSZ - Set the value to the maximum one. + * Don't allow the mode register to override values. */ + *cmd = ((*cmd & ~AGPSTAT_ARQSZ) | + max_t(u32,(*cmd & AGPSTAT_ARQSZ),(*tmp & AGPSTAT_ARQSZ))); + + /* Calibration cycle. + * Don't allow the mode register to override values. */ + *cmd = ((*cmd & ~AGPSTAT_CAL_MASK) | + min_t(u32,(*cmd & AGPSTAT_CAL_MASK),(*tmp & AGPSTAT_CAL_MASK))); + + /* SBA *must* be supported for AGP v3 */ + *cmd |= AGPSTAT_SBA; + + /* disable FW if it's not supported */ + if (!((*cmd & AGPSTAT_FW) && (*tmp & AGPSTAT_FW) && (*mode & AGPSTAT_FW))) + *cmd &= ~AGPSTAT_FW; + + /* Set speed. */ + if (!((*cmd & AGPSTAT3_8X) && (*tmp & AGPSTAT3_8X) && (*mode & AGPSTAT3_8X))) + *cmd &= ~AGPSTAT3_8X; + + if (!((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X) && (*mode & AGPSTAT3_4X))) + *cmd &= ~AGPSTAT3_4X; + + /* Clear out unwanted bits. */ + if (*cmd & AGPSTAT3_8X) + *cmd *= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); + if (*cmd & AGPSTAT3_4X) + *cmd *= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); +} + +//FIXME: This doesn't smell right. +//We need a function we pass an agp_device to. +u32 agp_collect_device_status(u32 mode, u32 cmd) { struct pci_dev *device; - u8 agp; - u32 scratch; + u8 cap_ptr; + u32 tmp; + u32 agp3; pci_for_each_dev(device) { - agp = pci_find_capability(device, PCI_CAP_ID_AGP); - if (!agp) + cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); + if (!cap_ptr) continue; /* * Ok, here we have a AGP device. Disable impossible * settings, and adjust the readqueue to the minimum. */ - pci_read_config_dword(device, agp + PCI_AGP_STATUS, &scratch); + pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp); /* adjust RQ depth */ - command = ((command & ~AGPSTAT_RQ_DEPTH) | + cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) | min_t(u32, (mode & AGPSTAT_RQ_DEPTH), - min_t(u32, (command & AGPSTAT_RQ_DEPTH), - (scratch & AGPSTAT_RQ_DEPTH)))); - - /* disable SBA if it's not supported */ - if (!((command & AGPSTAT_SBA) && (scratch & AGPSTAT_SBA) && (mode & AGPSTAT_SBA))) - command &= ~AGPSTAT_SBA; - - /* disable FW if it's not supported */ - if (!((command & AGPSTAT_FW) && (scratch & AGPSTAT_FW) && (mode & AGPSTAT_FW))) - command &= ~AGPSTAT_FW; - - /* Set speed */ - if (!((command & AGPSTAT2_4X) && (scratch & AGPSTAT2_4X) && (mode & AGPSTAT2_4X))) - command &= ~AGPSTAT2_4X; - - if (!((command & AGPSTAT2_2X) && (scratch & AGPSTAT2_2X) && (mode & AGPSTAT2_2X))) - command &= ~AGPSTAT2_2X; + min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH)))); + + pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3); - if (!((command & AGPSTAT2_1X) && (scratch & AGPSTAT2_1X) && (mode & AGPSTAT2_1X))) - command &= ~AGPSTAT2_1X; + /* Check to see if we are operating in 3.0 mode */ + if (agp3 & AGPSTAT_MODE_3_0) { + agp_v3_parse_one(&mode, &cmd, &tmp); + } else { + agp_v2_parse_one(&mode, &cmd, &tmp); + } } - - /* Now we know what mode it should be, clear out the unwanted bits. */ - if (command & AGPSTAT2_4X) - command &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */ - - if (command & AGPSTAT2_2X) - command &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ - - if (command & AGPSTAT2_1X) - command &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1Xf */ - - return command; + return cmd; } EXPORT_SYMBOL(agp_collect_device_status); @@ -446,29 +494,33 @@ EXPORT_SYMBOL(agp_device_command); -void agp_generic_enable(u32 mode) +void get_agp_version(struct agp_bridge_data *bridge) { - u32 command, ncapid, major, minor; + u32 ncapid; + + /* Exit early if already set by errata workarounds. */ + if (agp_bridge->major_version != 0) + return; pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx, &ncapid); - major = (ncapid >> 20) & 0xf; - minor = (ncapid >> 16) & 0xf; - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device.\n",major, minor); + agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; + agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; +} +EXPORT_SYMBOL(get_agp_version); - if(major >= 3) { - u32 agp_3_0; - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x4, &agp_3_0); - /* Check to see if we are operating in 3.0 mode */ - if((agp_3_0 >> 3) & 0x1) { - agp_3_0_node_enable(agp_bridge, mode, minor); - return; - } else { - printk (KERN_INFO PFX "not in AGP 3.0 mode, falling back to 2.x\n"); - } - } +void agp_generic_enable(u32 mode) +{ + u32 command; + u32 agp3; + + get_agp_version(agp_bridge); + + printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", + agp_bridge->major_version, + agp_bridge->minor_version, + agp_bridge->dev->slot_name); - /* AGP v<3 */ pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); @@ -477,7 +529,27 @@ pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_COMMAND, command); - agp_device_command(command, 0); + + /* Do AGP version specific frobbing. */ + if(agp_bridge->major_version >= 3) { + pci_read_config_dword(agp_bridge->dev, + agp_bridge->capndx+AGPSTAT, &agp3); + + /* Check to see if we are operating in 3.0 mode */ + if (agp3 & AGPSTAT_MODE_3_0) { + /* If we have 3.5, we can do the isoch stuff. */ + if (agp_bridge->minor_version >= 5) + agp_3_5_enable(agp_bridge, mode); + agp_device_command(command, TRUE); + return; + } else { + printk (KERN_INFO PFX "Device is in legacy mode," + " falling back to 2.x\n"); + } + } + + /* AGP v<3 */ + agp_device_command(command, FALSE); } EXPORT_SYMBOL(agp_generic_enable); @@ -831,6 +903,7 @@ } EXPORT_SYMBOL(agp_enable); + #ifdef CONFIG_SMP static void ipi_handler(void *null) { diff -urN linux-2.5.69-bk8/drivers/char/agp/intel-agp.c linux-2.5.69-bk9/drivers/char/agp/intel-agp.c --- linux-2.5.69-bk8/drivers/char/agp/intel-agp.c 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/agp/intel-agp.c 2003-05-14 04:43:42.000000000 -0700 @@ -1275,8 +1275,6 @@ u8 cap_ptr = 0; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); - if (!cap_ptr) - return -ENODEV; bridge = agp_alloc_bridge(); if (!bridge) @@ -1417,9 +1415,11 @@ printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name); /* Fill in the mode register */ - pci_read_config_dword(pdev, - bridge->capndx+PCI_AGP_STATUS, - &bridge->mode); + if (cap_ptr) { + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); + } pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); diff -urN linux-2.5.69-bk8/drivers/char/agp/isoch.c linux-2.5.69-bk9/drivers/char/agp/isoch.c --- linux-2.5.69-bk8/drivers/char/agp/isoch.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk9/drivers/char/agp/isoch.c 2003-05-14 04:43:42.000000000 -0700 @@ -0,0 +1,468 @@ +/* + * Setup routines for AGP 3.5 compliant bridges. + */ + +#include +#include +#include +#include + +#include "agp.h" + +/* Generic AGP 3.5 enabling routines */ + +struct agp_3_5_dev { + struct list_head list; + u8 capndx; + u32 maxbw; + struct pci_dev *dev; +}; + +static void agp_3_5_dev_list_insert(struct list_head *head, struct list_head *new) +{ + struct agp_3_5_dev *cur, *n = list_entry(new, struct agp_3_5_dev, list); + struct list_head *pos; + + list_for_each(pos, head) { + cur = list_entry(pos, struct agp_3_5_dev, list); + if(cur->maxbw > n->maxbw) + break; + } + list_add_tail(new, pos); +} + +static void agp_3_5_dev_list_sort(struct agp_3_5_dev *list, unsigned int ndevs) +{ + struct agp_3_5_dev *cur; + struct pci_dev *dev; + struct list_head *pos, *tmp, *head = &list->list, *start = head->next; + u32 nistat; + + INIT_LIST_HEAD(head); + + for (pos=start; pos!=head; ) { + cur = list_entry(pos, struct agp_3_5_dev, list); + dev = cur->dev; + + pci_read_config_dword(dev, cur->capndx+AGPNISTAT, &nistat); + cur->maxbw = (nistat >> 16) & 0xff; + + tmp = pos; + pos = pos->next; + agp_3_5_dev_list_insert(head, tmp); + } +} + +/* + * Initialize all isochronous transfer parameters for an AGP 3.0 + * node (i.e. a host bridge in combination with the adapters + * lying behind it...) + */ + +static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, + struct agp_3_5_dev *dev_list, unsigned int ndevs) +{ + /* + * Convenience structure to make the calculations clearer + * here. The field names come straight from the AGP 3.0 spec. + */ + struct isoch_data { + u32 maxbw; + u32 n; + u32 y; + u32 l; + u32 rq; + struct agp_3_5_dev *dev; + }; + + struct pci_dev *td = bridge->dev, *dev; + struct list_head *head = &dev_list->list, *pos; + struct agp_3_5_dev *cur; + struct isoch_data *master, target; + unsigned int cdev = 0; + u32 mnistat, tnistat, tstatus, mcmd; + u16 tnicmd, mnicmd; + u8 mcapndx; + u32 tot_bw = 0, tot_n = 0, tot_rq = 0, y_max, rq_isoch, rq_async; + u32 step, rem, rem_isoch, rem_async; + int ret = 0; + + /* + * We'll work with an array of isoch_data's (one for each + * device in dev_list) throughout this function. + */ + if ((master = kmalloc(ndevs * sizeof(*master), GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto get_out; + } + + /* + * Sort the device list by maxbw. We need to do this because the + * spec suggests that the devices with the smallest requirements + * have their resources allocated first, with all remaining resources + * falling to the device with the largest requirement. + * + * We don't exactly do this, we divide target resources by ndevs + * and split them amongst the AGP 3.0 devices. The remainder of such + * division operations are dropped on the last device, sort of like + * the spec mentions it should be done. + * + * We can't do this sort when we initially construct the dev_list + * because we don't know until this function whether isochronous + * transfers are enabled and consequently whether maxbw will mean + * anything. + */ + agp_3_5_dev_list_sort(dev_list, ndevs); + + pci_read_config_dword(td, bridge->capndx+AGPNISTAT, &tnistat); + pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus); + + /* Extract power-on defaults from the target */ + target.maxbw = (tnistat >> 16) & 0xff; + target.n = (tnistat >> 8) & 0xff; + target.y = (tnistat >> 6) & 0x3; + target.l = (tnistat >> 3) & 0x7; + target.rq = (tstatus >> 24) & 0xff; + + y_max = target.y; + + /* + * Extract power-on defaults for each device in dev_list. Along + * the way, calculate the total isochronous bandwidth required + * by these devices and the largest requested payload size. + */ + list_for_each(pos, head) { + cur = list_entry(pos, struct agp_3_5_dev, list); + dev = cur->dev; + + mcapndx = cur->capndx; + + pci_read_config_dword(dev, cur->capndx+AGPNISTAT, &mnistat); + + master[cdev].maxbw = (mnistat >> 16) & 0xff; + master[cdev].n = (mnistat >> 8) & 0xff; + master[cdev].y = (mnistat >> 6) & 0x3; + master[cdev].dev = cur; + + tot_bw += master[cdev].maxbw; + y_max = max(y_max, master[cdev].y); + + cdev++; + } + + /* Check if this configuration has any chance of working */ + if (tot_bw > target.maxbw) { + printk(KERN_ERR PFX "isochronous bandwidth required " + "by AGP 3.0 devices exceeds that which is supported by " + "the AGP 3.0 bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + target.y = y_max; + + /* + * Write the calculated payload size into the target's NICMD + * register. Doing this directly effects the ISOCH_N value + * in the target's NISTAT register, so we need to do this now + * to get an accurate value for ISOCH_N later. + */ + pci_read_config_word(td, bridge->capndx+AGPNICMD, &tnicmd); + tnicmd &= ~(0x3 << 6); + tnicmd |= target.y << 6; + pci_write_config_word(td, bridge->capndx+AGPNICMD, tnicmd); + + /* Reread the target's ISOCH_N */ + pci_read_config_dword(td, bridge->capndx+AGPNISTAT, &tnistat); + target.n = (tnistat >> 8) & 0xff; + + /* Calculate the minimum ISOCH_N needed by each master */ + for (cdev=0; cdev target.n) { + printk(KERN_ERR PFX "number of isochronous " + "transactions per period required by AGP 3.0 devices " + "exceeds that which is supported by the AGP 3.0 " + "bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + /* Calculate left over ISOCH_N capability in the target. We'll give + * this to the hungriest device (as per the spec) */ + rem = target.n - tot_n; + + /* + * Calculate the minimum isochronous RQ depth needed by each master. + * Along the way, distribute the extra ISOCH_N capability calculated + * above. + */ + for (cdev=0; cdev 64B, then ISOCH_Y + * byte isochronous writes will be broken into 64B pieces. + * This means we need to budget more RQ depth to account for + * these kind of writes (each isochronous write is actually + * many writes on the AGP bus). + */ + master[cdev].rq = master[cdev].n; + if(master[cdev].y > 0x1) + master[cdev].rq *= (1 << (master[cdev].y - 1)); + + tot_rq += master[cdev].rq; + + if (cdev == ndevs-1) + master[cdev].n += rem; + } + + /* Figure the number of isochronous and asynchronous RQ slots the + * target is providing. */ + rq_isoch = (target.y > 0x1) ? target.n * (1 << (target.y - 1)) : target.n; + rq_async = target.rq - rq_isoch; + + /* Exit if the minimal RQ needs of the masters exceeds what the target + * can provide. */ + if (tot_rq > rq_isoch) { + printk(KERN_ERR PFX "number of request queue slots " + "required by the isochronous bandwidth requested by " + "AGP 3.0 devices exceeds the number provided by the " + "AGP 3.0 bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + /* Calculate asynchronous RQ capability in the target (per master) as + * well as the total number of leftover isochronous RQ slots. */ + step = rq_async / ndevs; + rem_async = step + (rq_async % ndevs); + rem_isoch = rq_isoch - tot_rq; + + /* Distribute the extra RQ slots calculated above and write our + * isochronous settings out to the actual devices. */ + for (cdev=0; cdevdev; + + mcapndx = cur->capndx; + + master[cdev].rq += (cdev == ndevs - 1) + ? (rem_async + rem_isoch) : step; + + pci_read_config_word(dev, cur->capndx+AGPNICMD, &mnicmd); + pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd); + + mnicmd &= ~(0xff << 8); + mnicmd &= ~(0x3 << 6); + mcmd &= ~(0xff << 24); + + mnicmd |= master[cdev].n << 8; + mnicmd |= master[cdev].y << 6; + mcmd |= master[cdev].rq << 24; + + pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd); + pci_write_config_word(dev, cur->capndx+AGPNICMD, mnicmd); + } + +free_and_exit: + kfree(master); + +get_out: + return ret; +} + +/* + * This function basically allocates request queue slots among the + * AGP 3.0 systems in nonisochronous nodes. The algorithm is + * pretty stupid, divide the total number of RQ slots provided by the + * target by ndevs. Distribute this many slots to each AGP 3.0 device, + * giving any left over slots to the last device in dev_list. + */ +static void agp_3_5_nonisochronous_node_enable(struct agp_bridge_data *bridge, + struct agp_3_5_dev *dev_list, unsigned int ndevs) +{ + struct agp_3_5_dev *cur; + struct list_head *head = &dev_list->list, *pos; + u32 tstatus, mcmd; + u32 trq, mrq, rem; + unsigned int cdev = 0; + + pci_read_config_dword(bridge->dev, bridge->capndx+AGPSTAT, &tstatus); + + trq = (tstatus >> 24) & 0xff; + mrq = trq / ndevs; + + rem = mrq + (trq % ndevs); + + for (pos=head->next; cdevnext) { + cur = list_entry(pos, struct agp_3_5_dev, list); + + pci_read_config_dword(cur->dev, cur->capndx+AGPCMD, &mcmd); + mcmd &= ~(0xff << 24); + mcmd |= ((cdev == ndevs - 1) ? rem : mrq) << 24; + pci_write_config_dword(cur->dev, cur->capndx+AGPCMD, mcmd); + } +} + +/* + * Fully configure and enable an AGP 3.0 host bridge and all the devices + * lying behind it. + */ +int agp_3_5_enable(struct agp_bridge_data *bridge, u32 mode) +{ + struct pci_dev *td = bridge->dev, *dev; + u8 mcapndx; + u32 isoch, arqsz; + u32 tstatus, mstatus, ncapid; + u32 mmajor; + u16 mpstat; + struct agp_3_5_dev *dev_list, *cur; + struct list_head *head, *pos; + unsigned int ndevs = 0; + int ret = 0; + + /* Extract some power-on defaults from the target */ + pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus); + isoch = (tstatus >> 17) & 0x1; + if (isoch == 0) /* isoch xfers not available, bail out. */ + return -ENODEV; + + arqsz = (tstatus >> 13) & 0x7; + + /* + * Allocate a head for our AGP 3.5 device list + * (multiple AGP v3 devices are allowed behind a single bridge). + */ + if ((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto get_out; + } + head = &dev_list->list; + INIT_LIST_HEAD(head); + + /* Find all AGP devices, and add them to dev_list. */ + pci_for_each_dev(dev) { + mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); + if (mcapndx == 0) + continue; + + switch ((dev->class >>8) & 0xff00) { + case 0x0600: /* Bridge */ + /* Skip bridges. We should call this function for each one. */ + continue; + + case 0x0001: /* Unclassified device */ + /* Don't know what this is, but log it for investigation. */ + if (mcapndx != 0) { + printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n", + dev->vendor, dev->device); + } + continue; + + case 0x0300: /* Display controller */ + case 0x0400: /* Multimedia controller */ + if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto free_and_exit; + } + cur->dev = dev; + + pos = &cur->list; + list_add(pos, head); + ndevs++; + continue; + + default: + continue; + } + } + + /* + * Take an initial pass through the devices lying behind our host + * bridge. Make sure each one is actually an AGP 3.0 device, otherwise + * exit with an error message. Along the way store the AGP 3.0 + * cap_ptr for each device + */ + list_for_each(pos, head) { + cur = list_entry(pos, struct agp_3_5_dev, list); + dev = cur->dev; + + pci_read_config_word(dev, PCI_STATUS, &mpstat); + if ((mpstat & PCI_STATUS_CAP_LIST) == 0) + continue; + + pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &mcapndx); + if (mcapndx != 0) { + do { + pci_read_config_dword(dev, mcapndx, &ncapid); + if ((ncapid & 0xff) != 2) + mcapndx = (ncapid >> 8) & 0xff; + } + while (((ncapid & 0xff) != 2) && (mcapndx != 0)); + } + + if (mcapndx == 0) { + printk(KERN_ERR PFX "woah! Non-AGP device " + "found on the secondary bus of an AGP 3.5 bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; + if (mmajor < 3) { + printk(KERN_ERR PFX "woah! AGP 2.0 device " + "found on the secondary bus of an AGP 3.5 " + "bridge operating with AGP 3.0 electricals!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + cur->capndx = mcapndx; + + pci_read_config_dword(dev, cur->capndx+AGPSTAT, &mstatus); + + if (((mstatus >> 3) & 0x1) == 0) { + printk(KERN_ERR PFX "woah! AGP 3.x device " + "not operating in AGP 3.x mode found on the " + "secondary bus of an AGP 3.5 bridge operating " + "with AGP 3.0 electricals!\n"); + ret = -ENODEV; + goto free_and_exit; + } + } + + /* + * Call functions to divide target resources amongst the AGP 3.0 + * masters. This process is dramatically different depending on + * whether isochronous transfers are supported. + */ + if (isoch) { + ret = agp_3_5_isochronous_node_enable(bridge, dev_list, ndevs); + if (ret) { + printk(KERN_INFO PFX "Something bad happened setting " + "up isochronous xfers. Falling back to " + "non-isochronous xfer mode.\n"); + } + } + agp_3_5_nonisochronous_node_enable(bridge, dev_list, ndevs); + +free_and_exit: + /* Be sure to free the dev_list */ + for (pos=head->next; pos!=head; ) { + cur = list_entry(pos, struct agp_3_5_dev, list); + + pos = pos->next; + kfree(cur); + } + kfree(dev_list); + +get_out: + return ret; +} + diff -urN linux-2.5.69-bk8/drivers/char/drm/Kconfig linux-2.5.69-bk9/drivers/char/drm/Kconfig --- linux-2.5.69-bk8/drivers/char/drm/Kconfig 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/drm/Kconfig 2003-05-14 04:43:42.000000000 -0700 @@ -49,7 +49,7 @@ config DRM_I810 tristate "Intel I810" - depends on DRM && AGP + depends on DRM && AGP && AGP_INTEL help Choose this option if you have an Intel I810 graphics card. If M is selected, the module will be called i810. AGP support is required @@ -57,7 +57,7 @@ config DRM_I830 tristate "Intel 830M, 845G, 852GM, 855GM, 865G" - depends on DRM && AGP + depends on DRM && AGP && AGP_INTEL help Choose this option if you have a system that has Intel 830M, 845G, 852GM, 855GM or 865G integrated graphics. If M is selected, the diff -urN linux-2.5.69-bk8/drivers/char/vt_ioctl.c linux-2.5.69-bk9/drivers/char/vt_ioctl.c --- linux-2.5.69-bk8/drivers/char/vt_ioctl.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk9/drivers/char/vt_ioctl.c 2003-05-14 04:43:43.000000000 -0700 @@ -869,13 +869,13 @@ if (clin > 32) return -EINVAL; - if (vlin) - vc->vc_scan_lines = vlin; - if (clin) - vc->vc_font.height = clin; - - for (i = 0; i < MAX_NR_CONSOLES; i++) + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (vlin) + vc_cons[i].d->vc_scan_lines = vlin; + if (clin) + vc_cons[i].d->vc_font.height = clin; vc_resize(i, cc, ll); + } return 0; } diff -urN linux-2.5.69-bk8/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-2.5.69-bk9/drivers/scsi/aic7xxx/aic7xxx_osm.c --- linux-2.5.69-bk8/drivers/scsi/aic7xxx/aic7xxx_osm.c 2003-05-14 04:43:38.000000000 -0700 +++ linux-2.5.69-bk9/drivers/scsi/aic7xxx/aic7xxx_osm.c 2003-05-14 04:43:44.000000000 -0700 @@ -784,14 +784,18 @@ static int ahc_linux_slave_alloc(Scsi_Device *); static int ahc_linux_slave_configure(Scsi_Device *); static void ahc_linux_slave_destroy(Scsi_Device *); +#if defined(__i386__) static int ahc_linux_biosparam(struct scsi_device*, struct block_device*, sector_t, int[]); +#endif #else static void ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs); +#if defined(__i386__) static int ahc_linux_biosparam(Disk *, kdev_t, int[]); #endif +#endif static int ahc_linux_bus_reset(Scsi_Cmnd *); static int ahc_linux_dev_reset(Scsi_Cmnd *); static int ahc_linux_abort(Scsi_Cmnd *); @@ -1194,6 +1198,7 @@ /* * Return the disk geometry for the given SCSI device. */ +#if defined(__i386__) static int #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, @@ -1257,6 +1262,7 @@ geom[2] = cylinders; return (0); } +#endif /* * Abort the current SCSI command(s). diff -urN linux-2.5.69-bk8/drivers/video/console/fbcon.c linux-2.5.69-bk9/drivers/video/console/fbcon.c --- linux-2.5.69-bk8/drivers/video/console/fbcon.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk9/drivers/video/console/fbcon.c 2003-05-14 04:43:45.000000000 -0700 @@ -294,13 +294,16 @@ * Maps a virtual console @unit to a frame buffer device * @newidx. */ -void set_con2fb_map(int unit, int newidx) +int set_con2fb_map(int unit, int newidx) { struct vc_data *vc = vc_cons[unit].d; + if (!vc) + return -ENODEV; con2fb_map[unit] = newidx; fbcon_is_default = (vc->vc_sw == &fb_con) ? 1 : 0; take_over_console(&fb_con, unit, unit, fbcon_is_default); + return 0; } /* @@ -1047,6 +1050,11 @@ cursor.set |= FB_CUR_SETSIZE; } + if (info->cursor.hot.x || info->cursor.hot.y) { + cursor.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)) { char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); int cur_height, size, i = 0; diff -urN linux-2.5.69-bk8/drivers/video/console/fbcon.h linux-2.5.69-bk9/drivers/video/console/fbcon.h --- linux-2.5.69-bk8/drivers/video/console/fbcon.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk9/drivers/video/console/fbcon.h 2003-05-14 04:43:45.000000000 -0700 @@ -38,7 +38,7 @@ /* drivers/video/console/fbcon.c */ extern char con2fb_map[MAX_NR_CONSOLES]; -extern void set_con2fb_map(int unit, int newidx); +extern int set_con2fb_map(int unit, int newidx); /* * Attribute Decoding diff -urN linux-2.5.69-bk8/drivers/video/riva/fbdev.c linux-2.5.69-bk9/drivers/video/riva/fbdev.c --- linux-2.5.69-bk8/drivers/video/riva/fbdev.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk9/drivers/video/riva/fbdev.c 2003-05-14 04:43:45.000000000 -0700 @@ -1469,10 +1469,10 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct riva_par *par = (struct riva_par *) info->par; - int i, j, d_idx = 0, s_idx = 0; u8 data[MAX_CURS * MAX_CURS/8]; u8 mask[MAX_CURS * MAX_CURS/8]; u16 fg, bg; + int i; par->riva.ShowHideCursor(&par->riva, 0); diff -urN linux-2.5.69-bk8/drivers/video/vesafb.c linux-2.5.69-bk9/drivers/video/vesafb.c --- linux-2.5.69-bk8/drivers/video/vesafb.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk9/drivers/video/vesafb.c 2003-05-14 04:43:45.000000000 -0700 @@ -215,7 +215,6 @@ int __init vesafb_init(void) { int video_cmap_len; - char *edid = 0; int i; if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) @@ -300,18 +299,10 @@ ypan = 0; } -#ifdef __i386__ - edid = get_EDID_from_BIOS(0); - if (edid) - parse_edid(edid, &vesafb_defined); - else -#endif - { - /* some dummy values for timing to make fbset happy */ - vesafb_defined.pixclock = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres; - vesafb_defined.left_margin = (vesafb_defined.xres / 8) & 0xf8; - vesafb_defined.hsync_len = (vesafb_defined.xres / 8) & 0xf8; - } + /* some dummy values for timing to make fbset happy */ + vesafb_defined.pixclock = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres; + vesafb_defined.left_margin = (vesafb_defined.xres / 8) & 0xf8; + vesafb_defined.hsync_len = (vesafb_defined.xres / 8) & 0xf8; if (vesafb_defined.bits_per_pixel > 8) { vesafb_defined.red.offset = screen_info.red_pos; diff -urN linux-2.5.69-bk8/fs/block_dev.c linux-2.5.69-bk9/fs/block_dev.c --- linux-2.5.69-bk8/fs/block_dev.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk9/fs/block_dev.c 2003-05-14 04:43:45.000000000 -0700 @@ -681,18 +681,18 @@ return blkdev_put(inode->i_bdev, BDEV_FILE); } -static ssize_t blkdev_file_write(struct file *file, const char *buf, +static ssize_t blkdev_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count }; + struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count }; return generic_file_write_nolock(file, &local_iov, 1, ppos); } -static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char *buf, +static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) { - struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count }; + struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count }; return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); } diff -urN linux-2.5.69-bk8/fs/fcntl.c linux-2.5.69-bk9/fs/fcntl.c --- linux-2.5.69-bk8/fs/fcntl.c 2003-05-04 16:53:34.000000000 -0700 +++ linux-2.5.69-bk9/fs/fcntl.c 2003-05-14 04:43:45.000000000 -0700 @@ -305,11 +305,11 @@ err = setfl(fd, filp, arg); break; case F_GETLK: - err = fcntl_getlk(filp, (struct flock *) arg); + err = fcntl_getlk(filp, (struct flock __user *) arg); break; case F_SETLK: case F_SETLKW: - err = fcntl_setlk(filp, cmd, (struct flock *) arg); + err = fcntl_setlk(filp, cmd, (struct flock __user *) arg); break; case F_GETOWN: /* @@ -393,11 +393,11 @@ switch (cmd) { case F_GETLK64: - err = fcntl_getlk64(filp, (struct flock64 *) arg); + err = fcntl_getlk64(filp, (struct flock64 __user *) arg); break; case F_SETLK64: case F_SETLKW64: - err = fcntl_setlk64(filp, cmd, (struct flock64 *) arg); + err = fcntl_setlk64(filp, cmd, (struct flock64 __user *) arg); break; default: err = do_fcntl(fd, cmd, arg, filp); diff -urN linux-2.5.69-bk8/fs/filesystems.c linux-2.5.69-bk9/fs/filesystems.c --- linux-2.5.69-bk8/fs/filesystems.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk9/fs/filesystems.c 2003-05-14 04:43:45.000000000 -0700 @@ -174,7 +174,7 @@ register_fs_subsys(*p); } -static int fs_index(const char * __name) +static int fs_index(const char __user * __name) { struct file_system_type * tmp; char * name; @@ -198,7 +198,7 @@ return err; } -static int fs_name(unsigned int index, char * buf) +static int fs_name(unsigned int index, char __user * buf) { struct file_system_type * tmp; int len, res; @@ -239,11 +239,11 @@ switch (option) { case 1: - retval = fs_index((const char *) arg1); + retval = fs_index((const char __user *) arg1); break; case 2: - retval = fs_name(arg1, (char *) arg2); + retval = fs_name(arg1, (char __user *) arg2); break; case 3: diff -urN linux-2.5.69-bk8/fs/ioctl.c linux-2.5.69-bk9/fs/ioctl.c --- linux-2.5.69-bk8/fs/ioctl.c 2003-05-04 16:53:07.000000000 -0700 +++ linux-2.5.69-bk9/fs/ioctl.c 2003-05-14 04:43:45.000000000 -0700 @@ -75,7 +75,7 @@ break; case FIONBIO: - if ((error = get_user(on, (int *)arg)) != 0) + if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = O_NONBLOCK; #ifdef __sparc__ @@ -90,7 +90,7 @@ break; case FIOASYNC: - if ((error = get_user(on, (int *)arg)) != 0) + if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = on ? FASYNC : 0; @@ -114,7 +114,7 @@ S_ISREG(filp->f_dentry->d_inode->i_mode) || S_ISLNK(filp->f_dentry->d_inode->i_mode)) { loff_t res = inode_get_bytes(filp->f_dentry->d_inode); - error = copy_to_user((loff_t *)arg, &res, sizeof(res)) ? -EFAULT : 0; + error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; diff -urN linux-2.5.69-bk8/fs/libfs.c linux-2.5.69-bk9/fs/libfs.c --- linux-2.5.69-bk8/fs/libfs.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk9/fs/libfs.c 2003-05-14 04:43:45.000000000 -0700 @@ -157,7 +157,7 @@ return 0; } -ssize_t generic_read_dir(struct file *filp, char *buf, size_t siz, loff_t *ppos) +ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos) { return -EISDIR; } diff -urN linux-2.5.69-bk8/fs/locks.c linux-2.5.69-bk9/fs/locks.c --- linux-2.5.69-bk8/fs/locks.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk9/fs/locks.c 2003-05-14 04:43:45.000000000 -0700 @@ -1342,7 +1342,7 @@ /* Report the first existing lock that would conflict with l. * This implements the F_GETLK command of fcntl(). */ -int fcntl_getlk(struct file *filp, struct flock *l) +int fcntl_getlk(struct file *filp, struct flock __user *l) { struct file_lock *fl, file_lock; struct flock flock; @@ -1404,7 +1404,7 @@ /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l) +int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) { struct file_lock *file_lock = locks_alloc_lock(); struct flock flock; @@ -1492,7 +1492,7 @@ /* Report the first existing lock that would conflict with l. * This implements the F_GETLK command of fcntl(). */ -int fcntl_getlk64(struct file *filp, struct flock64 *l) +int fcntl_getlk64(struct file *filp, struct flock64 __user *l) { struct file_lock *fl, file_lock; struct flock64 flock; @@ -1542,7 +1542,7 @@ /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l) +int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) { struct file_lock *file_lock = locks_alloc_lock(); struct flock64 flock; diff -urN linux-2.5.69-bk8/fs/nfs/symlink.c linux-2.5.69-bk9/fs/nfs/symlink.c --- linux-2.5.69-bk8/fs/nfs/symlink.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk9/fs/nfs/symlink.c 2003-05-14 04:43:45.000000000 -0700 @@ -75,7 +75,7 @@ return (char*)page; } -static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen) +static int nfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct inode *inode = dentry->d_inode; struct page *page = NULL; diff -urN linux-2.5.69-bk8/fs/pipe.c linux-2.5.69-bk9/fs/pipe.c --- linux-2.5.69-bk8/fs/pipe.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/fs/pipe.c 2003-05-14 04:43:45.000000000 -0700 @@ -44,7 +44,7 @@ } static ssize_t -pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) +pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; int do_wakeup; @@ -126,7 +126,7 @@ } static ssize_t -pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) +pipe_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; ssize_t ret; @@ -216,13 +216,13 @@ } static ssize_t -bad_pipe_r(struct file *filp, char *buf, size_t count, loff_t *ppos) +bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { return -EBADF; } static ssize_t -bad_pipe_w(struct file *filp, const char *buf, size_t count, loff_t *ppos) +bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { return -EBADF; } @@ -233,7 +233,7 @@ { switch (cmd) { case FIONREAD: - return put_user(PIPE_LEN(*pino), (int *)arg); + return put_user(PIPE_LEN(*pino), (int __user *)arg); default: return -EINVAL; } diff -urN linux-2.5.69-bk8/include/linux/fs.h linux-2.5.69-bk9/include/linux/fs.h --- linux-2.5.69-bk8/include/linux/fs.h 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/include/linux/fs.h 2003-05-14 04:43:45.000000000 -0700 @@ -521,12 +521,12 @@ #include -extern int fcntl_getlk(struct file *, struct flock *); -extern int fcntl_setlk(struct file *, unsigned int, struct flock *); +extern int fcntl_getlk(struct file *, struct flock __user *); +extern int fcntl_setlk(struct file *, unsigned int, struct flock __user *); #if BITS_PER_LONG == 32 -extern int fcntl_getlk64(struct file *, struct flock64 *); -extern int fcntl_setlk64(struct file *, unsigned int, struct flock64 *); +extern int fcntl_getlk64(struct file *, struct flock64 __user *); +extern int fcntl_setlk64(struct file *, unsigned int, struct flock64 __user *); #endif /* fs/locks.c */ @@ -1263,8 +1263,8 @@ extern int vfs_readdir(struct file *, filldir_t, void *); -extern int vfs_stat(char *, struct kstat *); -extern int vfs_lstat(char *, struct kstat *); +extern int vfs_stat(char __user *, struct kstat *); +extern int vfs_lstat(char __user *, struct kstat *); extern int vfs_fstat(unsigned int, struct kstat *); extern struct file_system_type *get_fs_type(const char *name); @@ -1291,7 +1291,7 @@ unsigned offset, unsigned to); extern struct dentry *simple_lookup(struct inode *, struct dentry *); -extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *); +extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); extern struct file_operations simple_dir_operations; extern struct inode_operations simple_dir_inode_operations; struct tree_descr { char *name; struct file_operations *ops; int mode; }; diff -urN linux-2.5.69-bk8/include/linux/netfilter_ipv4/compat_firewall.h linux-2.5.69-bk9/include/linux/netfilter_ipv4/compat_firewall.h --- linux-2.5.69-bk8/include/linux/netfilter_ipv4/compat_firewall.h 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk9/include/linux/netfilter_ipv4/compat_firewall.h 2003-05-14 04:43:45.000000000 -0700 @@ -21,20 +21,20 @@ { struct firewall_ops *next; int (*fw_forward)(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb); int (*fw_input)(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb); int (*fw_output)(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb); /* These may be NULL. */ int (*fw_acct_in)(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb); int (*fw_acct_out)(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb); }; diff -urN linux-2.5.69-bk8/include/linux/netfilter_ipv4/ipfwadm_core.h linux-2.5.69-bk9/include/linux/netfilter_ipv4/ipfwadm_core.h --- linux-2.5.69-bk8/include/linux/netfilter_ipv4/ipfwadm_core.h 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk9/include/linux/netfilter_ipv4/ipfwadm_core.h 2003-05-14 04:43:45.000000000 -0700 @@ -250,7 +250,7 @@ extern int ip_fw_masq_timeouts(void *user, int len); -extern int ip_fw_chk(struct iphdr *, struct net_device *, __u16 *, +extern int ip_fw_chk(struct sk_buff **, struct net_device *, __u16 *, struct ip_fw *, int, int); #endif /* KERNEL */ #endif /* _IP_FW_H */ diff -urN linux-2.5.69-bk8/include/linux/sunrpc/rpc_pipe_fs.h linux-2.5.69-bk9/include/linux/sunrpc/rpc_pipe_fs.h --- linux-2.5.69-bk8/include/linux/sunrpc/rpc_pipe_fs.h 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk9/include/linux/sunrpc/rpc_pipe_fs.h 2003-05-14 04:43:45.000000000 -0700 @@ -12,8 +12,8 @@ }; struct rpc_pipe_ops { - ssize_t (*upcall)(struct file *, struct rpc_pipe_msg *, char *, size_t); - ssize_t (*downcall)(struct file *, const char *, size_t); + ssize_t (*upcall)(struct file *, struct rpc_pipe_msg *, char __user *, size_t); + ssize_t (*downcall)(struct file *, const char __user *, size_t); void (*destroy_msg)(struct rpc_pipe_msg *); }; diff -urN linux-2.5.69-bk8/include/net/atmclip.h linux-2.5.69-bk9/include/net/atmclip.h --- linux-2.5.69-bk8/include/net/atmclip.h 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk9/include/net/atmclip.h 2003-05-14 04:43:45.000000000 -0700 @@ -55,13 +55,22 @@ }; -extern struct atm_vcc *atmarpd; /* ugly */ -extern struct neigh_table clip_tbl; +#ifdef __KERNEL__ +struct atm_clip_ops { + int (*clip_create)(int number); + int (*clip_mkip)(struct atm_vcc *vcc,int timeout); + int (*clip_setentry)(struct atm_vcc *vcc,u32 ip); + int (*clip_encap)(struct atm_vcc *vcc,int mode); + void (*clip_push)(struct atm_vcc *vcc,struct sk_buff *skb); + int (*atm_init_atmarp)(struct atm_vcc *vcc); + struct module *owner; +}; + +void atm_clip_ops_set(struct atm_clip_ops *); +int try_atm_clip_ops(void); -int clip_create(int number); -int clip_mkip(struct atm_vcc *vcc,int timeout); -int clip_setentry(struct atm_vcc *vcc,u32 ip); -int clip_encap(struct atm_vcc *vcc,int mode); -void atm_clip_init(void); +extern struct neigh_table *clip_tbl_hook; +extern struct atm_clip_ops *atm_clip_ops; +#endif #endif diff -urN linux-2.5.69-bk8/include/net/bluetooth/l2cap.h linux-2.5.69-bk9/include/net/bluetooth/l2cap.h --- linux-2.5.69-bk8/include/net/bluetooth/l2cap.h 2003-05-04 16:53:03.000000000 -0700 +++ linux-2.5.69-bk9/include/net/bluetooth/l2cap.h 2003-05-14 04:43:45.000000000 -0700 @@ -231,8 +231,10 @@ struct sock *prev_c; }; -#define CONF_REQ_SENT 0x01 -#define CONF_INPUT_DONE 0x02 -#define CONF_OUTPUT_DONE 0x04 +#define L2CAP_CONF_REQ_SENT 0x01 +#define L2CAP_CONF_INPUT_DONE 0x02 +#define L2CAP_CONF_OUTPUT_DONE 0x04 + +void l2cap_load(void); #endif /* __L2CAP_H */ diff -urN linux-2.5.69-bk8/include/net/bluetooth/rfcomm.h linux-2.5.69-bk9/include/net/bluetooth/rfcomm.h --- linux-2.5.69-bk8/include/net/bluetooth/rfcomm.h 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk9/include/net/bluetooth/rfcomm.h 2003-05-14 04:43:45.000000000 -0700 @@ -185,10 +185,11 @@ atomic_t refcnt; u8 dlci; u8 addr; - - uint mtu; + u8 priority; u8 v24_sig; + u8 mscex; + uint mtu; uint credits; uint rx_credits; uint tx_credits; @@ -213,6 +214,11 @@ #define RFCOMM_SCHED_TIMEO 3 #define RFCOMM_SCHED_WAKEUP 31 +/* MSC exchange flags */ +#define RFCOMM_MSCEX_TX 1 +#define RFCOMM_MSCEX_RX 2 +#define RFCOMM_MSCEX_OK (RFCOMM_MSCEX_TX + RFCOMM_MSCEX_RX) + extern struct task_struct *rfcomm_thread; extern unsigned long rfcomm_event; diff -urN linux-2.5.69-bk8/include/net/sock.h linux-2.5.69-bk9/include/net/sock.h --- linux-2.5.69-bk8/include/net/sock.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk9/include/net/sock.h 2003-05-14 04:43:45.000000000 -0700 @@ -405,12 +405,12 @@ extern void sock_rfree(struct sk_buff *skb); extern int sock_setsockopt(struct socket *sock, int level, - int op, char *optval, + int op, char __user *optval, int optlen); extern int sock_getsockopt(struct socket *sock, int level, - int op, char *optval, - int *optlen); + int op, char __user *optval, + int __user *optlen); extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, diff -urN linux-2.5.69-bk8/include/sound/seq_kernel.h linux-2.5.69-bk9/include/sound/seq_kernel.h --- linux-2.5.69-bk8/include/sound/seq_kernel.h 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk9/include/sound/seq_kernel.h 2003-05-14 04:43:45.000000000 -0700 @@ -158,7 +158,7 @@ extern int snd_seq_delete_kernel_client(int client); extern int snd_seq_kernel_client_enqueue(int client, snd_seq_event_t *ev, int atomic, int hop); extern int snd_seq_kernel_client_dispatch(int client, snd_seq_event_t *ev, int atomic, int hop); -extern int snd_seq_kernel_client_ctl(int client, unsigned int cmd, void *arg); +extern int snd_seq_kernel_client_ctl(int client, unsigned int cmd, void __user *arg); #define SNDRV_SEQ_EXT_MASK 0xc0000000 #define SNDRV_SEQ_EXT_USRPTR 0x80000000 diff -urN linux-2.5.69-bk8/net/Kconfig linux-2.5.69-bk9/net/Kconfig --- linux-2.5.69-bk8/net/Kconfig 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/Kconfig 2003-05-14 04:43:45.000000000 -0700 @@ -230,7 +230,7 @@ further details. config ATM_CLIP - bool "Classical IP over ATM (EXPERIMENTAL)" + tristate "Classical IP over ATM (EXPERIMENTAL)" depends on ATM && INET help Classical IP over ATM for PVCs and SVCs, supporting InARP and diff -urN linux-2.5.69-bk8/net/atm/Makefile linux-2.5.69-bk9/net/atm/Makefile --- linux-2.5.69-bk8/net/atm/Makefile 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/atm/Makefile 2003-05-14 04:43:45.000000000 -0700 @@ -2,13 +2,15 @@ # Makefile for the ATM Protocol Families. # +atm-y := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o -obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o - -obj-$(CONFIG_ATM_CLIP) += clip.o ipcommon.o -obj-$(CONFIG_ATM_BR2684) += br2684.o ipcommon.o -obj-$(CONFIG_NET_SCH_ATM) += ipcommon.o +obj-$(CONFIG_ATM) += atm.o +obj-$(CONFIG_ATM_CLIP) += clip.o +atm-$(subst m,y,$(CONFIG_ATM_CLIP)) += ipcommon.o +obj-$(CONFIG_ATM_BR2684) += br2684.o +atm-$(subst m,y,$(CONFIG_ATM_BR2684)) += ipcommon.o +atm-$(subst m,y,$CONFIG_NET_SCH_ATM)) += ipcommon.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_ATM_LANE) += lec.o diff -urN linux-2.5.69-bk8/net/atm/clip.c linux-2.5.69-bk9/net/atm/clip.c --- linux-2.5.69-bk8/net/atm/clip.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/atm/clip.c 2003-05-14 04:43:45.000000000 -0700 @@ -7,6 +7,8 @@ #include #include #include /* for UINT_MAX */ +#include +#include #include #include #include @@ -45,6 +47,7 @@ struct net_device *clip_devs = NULL; struct atm_vcc *atmarpd = NULL; +static struct neigh_table clip_tbl; static struct timer_list idle_timer; static int start_timer = 1; @@ -187,7 +190,7 @@ } -void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) +static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) { struct clip_vcc *clip_vcc = CLIP_VCC(vcc); @@ -325,7 +328,7 @@ } -struct neigh_table clip_tbl = { +static struct neigh_table clip_tbl = { NULL, /* next */ AF_INET, /* family */ sizeof(struct neighbour)+sizeof(struct atmarp_entry), /* entry_size */ @@ -371,7 +374,7 @@ */ -int clip_encap(struct atm_vcc *vcc,int mode) +static int clip_encap(struct atm_vcc *vcc,int mode) { CLIP_VCC(vcc)->encap = mode; return 0; @@ -468,7 +471,7 @@ } -int clip_mkip(struct atm_vcc *vcc,int timeout) +static int clip_mkip(struct atm_vcc *vcc,int timeout) { struct clip_vcc *clip_vcc; struct sk_buff_head copy; @@ -508,7 +511,7 @@ } -int clip_setentry(struct atm_vcc *vcc,u32 ip) +static int clip_setentry(struct atm_vcc *vcc,u32 ip) { struct neighbour *neigh; struct atmarp_entry *entry; @@ -581,7 +584,7 @@ } -int clip_create(int number) +static int clip_create(int number) { struct net_device *dev; struct clip_priv *clip_priv; @@ -701,28 +704,23 @@ "pending\n"); skb_queue_purge(&vcc->sk->receive_queue); DPRINTK("(done)\n"); + module_put(THIS_MODULE); } static struct atmdev_ops atmarpd_dev_ops = { - .close =atmarpd_close, + .close = atmarpd_close }; static struct atm_dev atmarpd_dev = { - &atmarpd_dev_ops, - NULL, /* no PHY */ - "arpd", /* type */ - 999, /* dummy device number */ - NULL,NULL, /* pretend not to have any VCCs */ - NULL,NULL, /* no data */ - 0, /* no flags */ - NULL, /* no local address */ - { 0 } /* no ESI, no statistics */ + .ops = &atmarpd_dev_ops, + .type = "arpd", + .number = 999, }; -int atm_init_atmarp(struct atm_vcc *vcc) +static int atm_init_atmarp(struct atm_vcc *vcc) { struct net_device *dev; @@ -752,10 +750,57 @@ return 0; } +static struct atm_clip_ops __atm_clip_ops = { + .clip_create = clip_create, + .clip_mkip = clip_mkip, + .clip_setentry = clip_setentry, + .clip_encap = clip_encap, + .clip_push = clip_push, + .atm_init_atmarp = atm_init_atmarp, + .owner = THIS_MODULE +}; -void atm_clip_init(void) +static int __init atm_clip_init(void) { + /* we should use neigh_table_init() */ clip_tbl.lock = RW_LOCK_UNLOCKED; clip_tbl.kmem_cachep = kmem_cache_create(clip_tbl.id, clip_tbl.entry_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + /* so neigh_ifdown() doesn't complain */ + clip_tbl.proxy_timer.data = 0; + clip_tbl.proxy_timer.function = 0; + init_timer(&clip_tbl.proxy_timer); + skb_queue_head_init(&clip_tbl.proxy_queue); + + clip_tbl_hook = &clip_tbl; + atm_clip_ops_set(&__atm_clip_ops); + + return 0; +} + +static void __exit atm_clip_exit(void) +{ + struct net_device *dev, *next; + + atm_clip_ops_set(NULL); + + neigh_ifdown(&clip_tbl, NULL); + dev = clip_devs; + while (dev) { + next = PRIV(dev)->next; + unregister_netdev(dev); + kfree(dev); + dev = next; + } + if (start_timer == 0) del_timer(&idle_timer); + + kmem_cache_destroy(clip_tbl.kmem_cachep); + + clip_tbl_hook = NULL; } + +module_init(atm_clip_init); +module_exit(atm_clip_exit); + +MODULE_LICENSE("GPL"); diff -urN linux-2.5.69-bk8/net/atm/common.c linux-2.5.69-bk9/net/atm/common.c --- linux-2.5.69-bk8/net/atm/common.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/atm/common.c 2003-05-14 04:43:45.000000000 -0700 @@ -57,6 +57,36 @@ #endif #endif +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) +#include +struct atm_clip_ops *atm_clip_ops; +static DECLARE_MUTEX(atm_clip_ops_mutex); + +void atm_clip_ops_set(struct atm_clip_ops *hook) +{ + down(&atm_clip_ops_mutex); + atm_clip_ops = hook; + up(&atm_clip_ops_mutex); +} + +int try_atm_clip_ops(void) +{ + down(&atm_clip_ops_mutex); + if (atm_clip_ops && try_module_get(atm_clip_ops->owner)) { + up(&atm_clip_ops_mutex); + return 1; + } + up(&atm_clip_ops_mutex); + return 0; +} + +#ifdef CONFIG_ATM_CLIP_MODULE +EXPORT_SYMBOL(atm_clip_ops); +EXPORT_SYMBOL(atm_clip_ops_mutex); +EXPORT_SYMBOL(atm_clip_ops_set); +#endif +#endif + #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE) int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long); EXPORT_SYMBOL(pppoatm_ioctl_hook); @@ -623,39 +653,67 @@ if (!error) sock->state = SS_CONNECTED; ret_val = error; goto done; -#ifdef CONFIG_ATM_CLIP +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) case SIOCMKCLIP: - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) { ret_val = -EPERM; - else - ret_val = clip_create(arg); + goto done; + } + if (try_atm_clip_ops()) { + ret_val = atm_clip_ops->clip_create(arg); + module_put(atm_clip_ops->owner); + } else + ret_val = -ENOSYS; goto done; case ATMARPD_CTRL: if (!capable(CAP_NET_ADMIN)) { ret_val = -EPERM; goto done; } - error = atm_init_atmarp(vcc); - if (!error) sock->state = SS_CONNECTED; - ret_val = error; +#if defined(CONFIG_ATM_CLIP_MODULE) + if (!atm_clip_ops) + request_module("clip"); +#endif + if (try_atm_clip_ops()) { + error = atm_clip_ops->atm_init_atmarp(vcc); + if (!error) + sock->state = SS_CONNECTED; + ret_val = error; + } else + ret_val = -ENOSYS; goto done; case ATMARP_MKIP: - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) { ret_val = -EPERM; - else - ret_val = clip_mkip(vcc,arg); + goto done; + } + if (try_atm_clip_ops()) { + ret_val = atm_clip_ops->clip_mkip(vcc, arg); + module_put(atm_clip_ops->owner); + } else + ret_val = -ENOSYS; goto done; case ATMARP_SETENTRY: - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) { ret_val = -EPERM; - else - ret_val = clip_setentry(vcc,arg); + goto done; + } + if (try_atm_clip_ops()) { + ret_val = atm_clip_ops->clip_setentry(vcc, arg); + module_put(atm_clip_ops->owner); + } else + ret_val = -ENOSYS; goto done; case ATMARP_ENCAP: - if (!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) { ret_val = -EPERM; - else - ret_val = clip_encap(vcc,arg); + goto done; + } + if (try_atm_clip_ops()) { + ret_val = atm_clip_ops->clip_encap(vcc, arg); + module_put(atm_clip_ops->owner); + } else + ret_val = -ENOSYS; goto done; #endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) diff -urN linux-2.5.69-bk8/net/atm/ipcommon.c linux-2.5.69-bk9/net/atm/ipcommon.c --- linux-2.5.69-bk8/net/atm/ipcommon.c 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk9/net/atm/ipcommon.c 2003-05-14 04:43:45.000000000 -0700 @@ -67,4 +67,5 @@ } +EXPORT_SYMBOL(llc_oui); EXPORT_SYMBOL(skb_migrate); diff -urN linux-2.5.69-bk8/net/atm/proc.c linux-2.5.69-bk9/net/atm/proc.c --- linux-2.5.69-bk8/net/atm/proc.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/atm/proc.c 2003-05-14 04:43:45.000000000 -0700 @@ -39,10 +39,9 @@ #include "common.h" /* atm_proc_init prototype */ #include "signaling.h" /* to get sigd - ugly too */ -#ifdef CONFIG_ATM_CLIP +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #include #include "ipcommon.h" -extern void clip_push(struct atm_vcc *vcc,struct sk_buff *skb); #endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) @@ -91,7 +90,7 @@ } -#ifdef CONFIG_ATM_CLIP +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) static int svc_addr(char *buf,struct sockaddr_atmsvc *addr) @@ -180,16 +179,21 @@ aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr, class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr, class_name[vcc->qos.txtp.traffic_class]); -#ifdef CONFIG_ATM_CLIP - if (vcc->push == clip_push) { - struct clip_vcc *clip_vcc = CLIP_VCC(vcc); - struct net_device *dev; - - dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL; - off += sprintf(buf+off,"CLIP, Itf:%s, Encap:", - dev ? dev->name : "none?"); - if (clip_vcc->encap) off += sprintf(buf+off,"LLC/SNAP"); - else off += sprintf(buf+off,"None"); +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) + if (try_atm_clip_ops()) { + if (vcc->push == atm_clip_ops->clip_push) { + struct clip_vcc *clip_vcc = CLIP_VCC(vcc); + struct net_device *dev; + + dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL; + off += sprintf(buf+off,"CLIP, Itf:%s, Encap:", + dev ? dev->name : "none?"); + if (clip_vcc->encap) + off += sprintf(buf+off,"LLC/SNAP"); + else + off += sprintf(buf+off,"None"); + } + module_put(atm_clip_ops->owner); } #endif strcpy(buf+off,"\n"); @@ -409,7 +413,7 @@ return 0; } -#ifdef CONFIG_ATM_CLIP +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) static int atm_arp_info(loff_t pos,char *buf) { struct neighbour *n; @@ -419,28 +423,33 @@ return sprintf(buf,"IPitf TypeEncp Idle IP address " "ATM address\n"); } + if (!try_atm_clip_ops()) + return 0; count = pos; - read_lock_bh(&clip_tbl.lock); + read_lock_bh(&clip_tbl_hook->lock); for (i = 0; i <= NEIGH_HASHMASK; i++) - for (n = clip_tbl.hash_buckets[i]; n; n = n->next) { + for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) { struct atmarp_entry *entry = NEIGH2ENTRY(n); struct clip_vcc *vcc; if (!entry->vccs) { if (--count) continue; atmarp_info(n->dev,entry,NULL,buf); - read_unlock_bh(&clip_tbl.lock); + read_unlock_bh(&clip_tbl_hook->lock); + module_put(atm_clip_ops->owner); return strlen(buf); } for (vcc = entry->vccs; vcc; vcc = vcc->next) { if (--count) continue; atmarp_info(n->dev,entry,vcc,buf); - read_unlock_bh(&clip_tbl.lock); + read_unlock_bh(&clip_tbl_hook->lock); + module_put(atm_clip_ops->owner); return strlen(buf); } } - read_unlock_bh(&clip_tbl.lock); + read_unlock_bh(&clip_tbl_hook->lock); + module_put(atm_clip_ops->owner); return 0; } #endif @@ -612,7 +621,7 @@ CREATE_ENTRY(pvc); CREATE_ENTRY(svc); CREATE_ENTRY(vc); -#ifdef CONFIG_ATM_CLIP +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) CREATE_ENTRY(arp); #endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) diff -urN linux-2.5.69-bk8/net/atm/pvc.c linux-2.5.69-bk9/net/atm/pvc.c --- linux-2.5.69-bk8/net/atm/pvc.c 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk9/net/atm/pvc.c 2003-05-14 04:43:45.000000000 -0700 @@ -7,16 +7,12 @@ #include /* struct socket, struct proto_ops */ #include /* ATM stuff */ #include /* ATM devices */ -#include /* Classical IP over ATM */ #include /* error codes */ #include /* printk */ #include #include #include #include /* for sock_no_* */ -#ifdef CONFIG_ATM_CLIP -#include -#endif #include "resources.h" /* devs and vccs */ #include "common.h" /* common for PVCs and SVCs */ @@ -129,9 +125,6 @@ printk(KERN_ERR "ATMPVC: can't register (%d)",error); return error; } -#ifdef CONFIG_ATM_CLIP - atm_clip_init(); -#endif #ifdef CONFIG_PROC_FS error = atm_proc_init(); if (error) printk("atm_proc_init fails with %d\n",error); diff -urN linux-2.5.69-bk8/net/bluetooth/af_bluetooth.c linux-2.5.69-bk9/net/bluetooth/af_bluetooth.c --- linux-2.5.69-bk8/net/bluetooth/af_bluetooth.c 2003-05-04 16:53:03.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/af_bluetooth.c 2003-05-14 04:43:45.000000000 -0700 @@ -92,6 +92,8 @@ static int bt_sock_create(struct socket *sock, int proto) { + int err = 0; + if (proto >= BT_MAX_PROTO) return -EINVAL; @@ -102,11 +104,12 @@ request_module(module_name); } #endif - - if (!bt_proto[proto]) - return -ENOENT; - - return bt_proto[proto]->create(sock, proto); + err = -EPROTONOSUPPORT; + if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { + err = bt_proto[proto]->create(sock, proto); + module_put(bt_proto[proto]->owner); + } + return err; } struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio) diff -urN linux-2.5.69-bk8/net/bluetooth/bnep/core.c linux-2.5.69-bk9/net/bluetooth/bnep/core.c --- linux-2.5.69-bk8/net/bluetooth/bnep/core.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/bnep/core.c 2003-05-14 04:43:45.000000000 -0700 @@ -85,14 +85,17 @@ static void __bnep_link_session(struct bnep_session *s) { - MOD_INC_USE_COUNT; + /* It's safe to call __module_get() here because sessions are added + by the socket layer which has to hold the refference to this module. + */ + __module_get(THIS_MODULE); list_add(&s->list, &bnep_session_list); } static void __bnep_unlink_session(struct bnep_session *s) { list_del(&s->list); - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } static int bnep_send(struct bnep_session *s, void *data, size_t len) @@ -677,7 +680,9 @@ static int __init bnep_init_module(void) { - char flt[50] = ""; + char flt[50] = ""; + + l2cap_load(); #ifdef CONFIG_BT_BNEP_PROTO_FILTER strcat(flt, "protocol "); diff -urN linux-2.5.69-bk8/net/bluetooth/bnep/sock.c linux-2.5.69-bk9/net/bluetooth/bnep/sock.c --- linux-2.5.69-bk8/net/bluetooth/bnep/sock.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/bnep/sock.c 2003-05-14 04:43:45.000000000 -0700 @@ -67,8 +67,6 @@ sock_orphan(sk); sock_put(sk); - - MOD_DEC_USE_COUNT; return 0; } @@ -179,13 +177,10 @@ return -ENOMEM; sock->ops = &bnep_sock_ops; - MOD_INC_USE_COUNT; - - sock->state = SS_UNCONNECTED; + sock->state = SS_UNCONNECTED; sk->destruct = NULL; sk->protocol = protocol; - return 0; } diff -urN linux-2.5.69-bk8/net/bluetooth/l2cap.c linux-2.5.69-bk9/net/bluetooth/l2cap.c --- linux-2.5.69-bk8/net/bluetooth/l2cap.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/l2cap.c 2003-05-14 04:43:45.000000000 -0700 @@ -145,8 +145,6 @@ conn->chan_list.lock = RW_LOCK_UNLOCKED; BT_DBG("hcon %p conn %p", hcon, conn); - - MOD_INC_USE_COUNT; return conn; } @@ -173,8 +171,6 @@ hcon->l2cap_data = NULL; kfree(conn); - - MOD_DEC_USE_COUNT; return 0; } @@ -242,8 +238,6 @@ if (sk->protinfo) kfree(sk->protinfo); - - MOD_DEC_USE_COUNT; } static void l2cap_sock_cleanup_listen(struct sock *parent) @@ -356,6 +350,8 @@ if (!sk) return NULL; + sk_set_owner(sk, THIS_MODULE); + sk->destruct = l2cap_sock_destruct; sk->sndtimeo = L2CAP_CONN_TIMEOUT; @@ -365,8 +361,6 @@ l2cap_sock_init_timer(sk); bt_sock_link(&l2cap_sk_list, sk); - - MOD_INC_USE_COUNT; return sk; } @@ -1319,15 +1313,18 @@ { struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; + u16 flags = 0; BT_DBG("sk %p complete %d", sk, result ? 1 : 0); if (result) *result = l2cap_conf_output(sk, &ptr); + else + flags = 0x0001; rsp->scid = __cpu_to_le16(l2cap_pi(sk)->dcid); rsp->result = __cpu_to_le16(result ? *result : 0); - rsp->flags = __cpu_to_le16(0); + rsp->flags = __cpu_to_le16(flags); return ptr - data; } @@ -1440,7 +1437,7 @@ case L2CAP_CR_SUCCESS: sk->state = BT_CONFIG; l2cap_pi(sk)->dcid = dcid; - l2cap_pi(sk)->conf_state |= CONF_REQ_SENT; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); break; @@ -1475,7 +1472,7 @@ l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req)); - if (flags & 0x01) { + if (flags & 0x0001) { /* Incomplete config. Send empty response. */ l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, NULL), rsp); goto unlock; @@ -1488,12 +1485,12 @@ goto unlock; /* Output config done */ - l2cap_pi(sk)->conf_state |= CONF_OUTPUT_DONE; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE; - if (l2cap_pi(sk)->conf_state & CONF_INPUT_DONE) { + if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { sk->state = BT_CONNECTED; l2cap_chan_ready(sk); - } else if (!(l2cap_pi(sk)->conf_state & CONF_REQ_SENT)) { + } else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { u8 req[64]; l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); } @@ -1538,9 +1535,9 @@ goto done; /* Input config done */ - l2cap_pi(sk)->conf_state |= CONF_INPUT_DONE; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; - if (l2cap_pi(sk)->conf_state & CONF_OUTPUT_DONE) { + if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { sk->state = BT_CONNECTED; l2cap_chan_ready(sk); } @@ -1943,21 +1940,27 @@ } if (skb->len < 2) { - BT_ERR("Frame is too small (len %d)", skb->len); + BT_ERR("Frame is too short (len %d)", skb->len); goto drop; } hdr = (struct l2cap_hdr *) skb->data; len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; - BT_DBG("Start: total len %d, frag len %d", len, skb->len); - if (len == skb->len) { /* Complete frame received */ l2cap_recv_frame(conn, skb); return 0; } + BT_DBG("Start: total len %d, frag len %d", len, skb->len); + + if (skb->len > len) { + BT_ERR("Frame is too long (len %d, expected len %d)", + skb->len, len); + goto drop; + } + /* Allocate skb for the complete frame (with header) */ if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC))) goto drop; @@ -1973,7 +1976,7 @@ } if (skb->len > conn->rx_len) { - BT_ERR("Fragment is too large (len %d, expect %d)", + BT_ERR("Fragment is too long (len %d, expected %d)", skb->len, conn->rx_len); kfree_skb(conn->rx_skb); conn->rx_skb = NULL; @@ -2134,7 +2137,6 @@ return err; } - l2cap_proc_init(); BT_INFO("L2CAP ver %s", VERSION); @@ -2155,6 +2157,15 @@ BT_ERR("L2CAP protocol unregistration failed"); } +void l2cap_load(void) +{ + /* Dummy function to trigger automatic L2CAP module loading by + other modules that use L2CAP sockets but don not use any other + symbols from it. */ + return; +} +EXPORT_SYMBOL(l2cap_load); + module_init(l2cap_init); module_exit(l2cap_cleanup); diff -urN linux-2.5.69-bk8/net/bluetooth/rfcomm/core.c linux-2.5.69-bk9/net/bluetooth/rfcomm/core.c --- linux-2.5.69-bk8/net/bluetooth/rfcomm/core.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/rfcomm/core.c 2003-05-14 04:43:45.000000000 -0700 @@ -52,7 +52,7 @@ #include #include -#define VERSION "0.3" +#define VERSION "1.0" #ifndef CONFIG_BT_RFCOMM_DEBUG #undef BT_DBG @@ -203,6 +203,7 @@ d->state = BT_OPEN; d->flags = 0; + d->mscex = 0; d->mtu = RFCOMM_DEFAULT_MTU; d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV; @@ -304,10 +305,11 @@ rfcomm_dlc_clear_state(d); - d->dlci = dlci; - d->addr = __addr(s->initiator, dlci); + d->dlci = dlci; + d->addr = __addr(s->initiator, dlci); + d->priority = 7; - d->state = BT_CONFIG; + d->state = BT_CONFIG; rfcomm_dlc_link(s, d); d->mtu = s->mtu; @@ -481,9 +483,12 @@ list_add(&s->list, &session_list); /* Do not increment module usage count for listeting sessions. - * Otherwise we won't be able to unload the module. */ + * Otherwise we won't be able to unload the module. + * Non listening session are added either by a socket or a TTYs + * which means that we already hold refcount to this module. + */ if (state != BT_LISTEN) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); return s; } @@ -502,7 +507,7 @@ kfree(s); if (state != BT_LISTEN) - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) @@ -741,7 +746,7 @@ pn = (void *) ptr; ptr += sizeof(*pn); pn->dlci = d->dlci; - pn->priority = 0; + pn->priority = d->priority; pn->ack_timer = 0; pn->max_retrans = 0; @@ -1099,8 +1104,6 @@ set_bit(RFCOMM_TX_THROTTLED, &d->flags); d->credits = 0; } - - d->mtu = btohs(pn->mtu); } else { if (pn->flow_ctrl == 0xe0) { d->tx_credits = pn->credits; @@ -1108,10 +1111,12 @@ set_bit(RFCOMM_TX_THROTTLED, &d->flags); d->credits = 0; } - - d->mtu = btohs(pn->mtu); } + d->priority = pn->priority; + + d->mtu = btohs(pn->mtu); + return 0; } @@ -1137,7 +1142,7 @@ switch (d->state) { case BT_CONFIG: rfcomm_apply_pn(d, cr, pn); - + d->state = BT_CONNECT; rfcomm_send_sabm(s, d->dlci); break; @@ -1148,7 +1153,7 @@ if (!cr) return 0; - + /* PN request for non existing DLC. * Assume incoming connection. */ if (rfcomm_connect_ind(s, channel, &d)) { @@ -1157,7 +1162,7 @@ rfcomm_dlc_link(s, d); rfcomm_apply_pn(d, cr, pn); - + d->state = BT_OPEN; rfcomm_send_pn(s, 0, d); } else { @@ -1229,21 +1234,21 @@ if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) { BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl); - rpn->flow_ctrl = RFCOMM_RPN_FLOW_NONE; + flow_ctrl = RFCOMM_RPN_FLOW_NONE; rpn_mask ^= RFCOMM_RPN_PM_FLOW; } } if (rpn->param_mask & RFCOMM_RPN_PM_XON) { if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) { BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char); - rpn->xon_char = RFCOMM_RPN_XON_CHAR; + xon_char = RFCOMM_RPN_XON_CHAR; rpn_mask ^= RFCOMM_RPN_PM_XON; } } if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) { BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char); - rpn->xoff_char = RFCOMM_RPN_XOFF_CHAR; + xoff_char = RFCOMM_RPN_XOFF_CHAR; rpn_mask ^= RFCOMM_RPN_PM_XOFF; } } @@ -1284,11 +1289,11 @@ BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); - if (!cr) + d = rfcomm_dlc_get(s, dlci); + if (!d) return 0; - d = rfcomm_dlc_get(s, dlci); - if (d) { + if (cr) { if (msc->v24_sig & RFCOMM_V24_FC && !d->credits) set_bit(RFCOMM_TX_THROTTLED, &d->flags); else @@ -1300,7 +1305,11 @@ rfcomm_dlc_unlock(d); rfcomm_send_msc(s, 0, dlci, msc->v24_sig); - } + + d->mscex |= RFCOMM_MSCEX_RX; + } else + d->mscex |= RFCOMM_MSCEX_TX; + return 0; } @@ -1524,7 +1533,8 @@ continue; } - if (d->state == BT_CONNECTED || d->state == BT_DISCONN) + if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) && + d->mscex == RFCOMM_MSCEX_OK) rfcomm_process_tx(d); } } @@ -1869,6 +1879,8 @@ /* ---- Initialization ---- */ int __init rfcomm_init(void) { + l2cap_load(); + kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); BT_INFO("RFCOMM ver %s", VERSION); diff -urN linux-2.5.69-bk8/net/bluetooth/rfcomm/sock.c linux-2.5.69-bk9/net/bluetooth/rfcomm/sock.c --- linux-2.5.69-bk8/net/bluetooth/rfcomm/sock.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/rfcomm/sock.c 2003-05-14 04:43:45.000000000 -0700 @@ -182,8 +182,6 @@ if (sk->protinfo) kfree(sk->protinfo); - - MOD_DEC_USE_COUNT; } static void rfcomm_sock_cleanup_listen(struct sock *parent) @@ -265,6 +263,8 @@ if (!sk) return NULL; + sk_set_owner(sk, THIS_MODULE); + d = rfcomm_dlc_alloc(prio); if (!d) { sk_free(sk); @@ -288,8 +288,6 @@ bt_sock_link(&rfcomm_sk_list, sk); BT_DBG("sk %p", sk); - - MOD_INC_USE_COUNT; return sk; } diff -urN linux-2.5.69-bk8/net/bluetooth/rfcomm/tty.c linux-2.5.69-bk9/net/bluetooth/rfcomm/tty.c --- linux-2.5.69-bk8/net/bluetooth/rfcomm/tty.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/rfcomm/tty.c 2003-05-14 04:43:45.000000000 -0700 @@ -99,7 +99,9 @@ rfcomm_dlc_put(dlc); kfree(dev); - MOD_DEC_USE_COUNT; + /* It's safe to call module_put() here because socket still + holds refference to this module. */ + module_put(THIS_MODULE); } static inline void rfcomm_dev_hold(struct rfcomm_dev *dev) @@ -211,8 +213,9 @@ dev->dlc = dlc; rfcomm_dlc_unlock(dlc); - MOD_INC_USE_COUNT; - + /* It's safe to call __module_get() here because socket already + holds refference to this module. */ + __module_get(THIS_MODULE); out: write_unlock_bh(&rfcomm_dev_lock); diff -urN linux-2.5.69-bk8/net/bluetooth/sco.c linux-2.5.69-bk9/net/bluetooth/sco.c --- linux-2.5.69-bk8/net/bluetooth/sco.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/bluetooth/sco.c 2003-05-14 04:43:45.000000000 -0700 @@ -145,8 +145,6 @@ conn->mtu = 60; BT_DBG("hcon %p conn %p", hcon, conn); - - MOD_INC_USE_COUNT; return conn; } @@ -180,8 +178,6 @@ hcon->sco_data = NULL; kfree(conn); - - MOD_DEC_USE_COUNT; return 0; } @@ -347,8 +343,6 @@ if (sk->protinfo) kfree(sk->protinfo); - - MOD_DEC_USE_COUNT; } static void sco_sock_cleanup_listen(struct sock *parent) @@ -434,6 +428,8 @@ if (!sk) return NULL; + sk_set_owner(sk, THIS_MODULE); + sk->destruct = sco_sock_destruct; sk->sndtimeo = SCO_CONN_TIMEOUT; sk->state = BT_OPEN; @@ -441,8 +437,6 @@ sco_sock_init_timer(sk); bt_sock_link(&sco_sk_list, sk); - - MOD_INC_USE_COUNT; return sk; } diff -urN linux-2.5.69-bk8/net/core/dev.c linux-2.5.69-bk9/net/core/dev.c --- linux-2.5.69-bk8/net/core/dev.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/core/dev.c 2003-05-14 04:43:45.000000000 -0700 @@ -1482,15 +1482,29 @@ #endif -#ifdef CONFIG_NET_DIVERT -static inline int handle_diverter(struct sk_buff *skb) +static inline void handle_diverter(struct sk_buff *skb) { +#ifdef CONFIG_NET_DIVERT /* if diversion is supported on device, then divert */ if (skb->dev->divert && skb->dev->divert->divert) divert_frame(skb); +#endif +} + +static inline int __handle_bridge(struct sk_buff *skb, + struct packet_type **pt_prev, int *ret) +{ +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + if (skb->dev->br_port) { + *ret = handle_bridge(skb, *pt_prev); + if (br_handle_frame_hook(skb) == 0) + return 1; + + *pt_prev = NULL; + } +#endif return 0; } -#endif /* CONFIG_NET_DIVERT */ int netif_receive_skb(struct sk_buff *skb) { @@ -1532,20 +1546,10 @@ } } -#ifdef CONFIG_NET_DIVERT - if (skb->dev->divert && skb->dev->divert->divert) - ret = handle_diverter(skb); -#endif /* CONFIG_NET_DIVERT */ - -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - if (skb->dev->br_port) { - ret = handle_bridge(skb, pt_prev); - if (br_handle_frame_hook(skb) == 0) - goto out; + handle_diverter(skb); - pt_prev = NULL; - } -#endif + if (__handle_bridge(skb, &pt_prev, &ret)) + goto out; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { if (ptype->type == type && @@ -1578,7 +1582,7 @@ ret = NET_RX_DROP; } - out: +out: rcu_read_unlock(); return ret; } diff -urN linux-2.5.69-bk8/net/core/sock.c linux-2.5.69-bk9/net/core/sock.c --- linux-2.5.69-bk8/net/core/sock.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk9/net/core/sock.c 2003-05-14 04:43:45.000000000 -0700 @@ -134,7 +134,7 @@ /* Maximal space eaten by iovec or ancilliary data plus some space */ int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512); -static int sock_set_timeout(long *timeo_p, char *optval, int optlen) +static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) { struct timeval tv; @@ -163,7 +163,7 @@ */ int sock_setsockopt(struct socket *sock, int level, int optname, - char *optval, int optlen) + char __user *optval, int optlen) { struct sock *sk=sock->sk; struct sk_filter *filter; @@ -188,7 +188,7 @@ if(optlensk; @@ -548,7 +548,7 @@ return -ENOTCONN; if (lv < len) return -EINVAL; - if(copy_to_user((void*)optval, address, len)) + if (copy_to_user(optval, address, len)) return -EFAULT; goto lenout; } @@ -996,7 +996,8 @@ msg.msg_controllen = 0; msg.msg_flags = flags; - iov.iov_base = kaddr + offset; + /* This cast is ok because of the "set_fs(KERNEL_DS)" */ + iov.iov_base = (void __user *) (kaddr + offset); iov.iov_len = size; old_fs = get_fs(); diff -urN linux-2.5.69-bk8/net/ipv4/arp.c linux-2.5.69-bk9/net/ipv4/arp.c --- linux-2.5.69-bk8/net/ipv4/arp.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv4/arp.c 2003-05-14 04:43:45.000000000 -0700 @@ -108,8 +108,9 @@ #include #endif #endif -#ifdef CONFIG_ATM_CLIP +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #include +struct neigh_table *clip_tbl_hook; #endif #include @@ -443,8 +444,8 @@ if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT)) nexthop = 0; n = __neigh_lookup_errno( -#ifdef CONFIG_ATM_CLIP - dev->type == ARPHRD_ATM ? &clip_tbl : +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) + dev->type == ARPHRD_ATM ? clip_tbl_hook : #endif &arp_tbl, &nexthop, dev); if (IS_ERR(n)) diff -urN linux-2.5.69-bk8/net/ipv4/netfilter/ip_fw_compat.c linux-2.5.69-bk9/net/ipv4/netfilter/ip_fw_compat.c --- linux-2.5.69-bk8/net/ipv4/netfilter/ip_fw_compat.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv4/netfilter/ip_fw_compat.c 2003-05-14 04:43:45.000000000 -0700 @@ -51,31 +51,17 @@ int ret = FW_BLOCK; u_int16_t redirpt; - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - /* Assume worse case: any hook could change packet */ (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; if ((*pskb)->ip_summed == CHECKSUM_HW) (*pskb)->ip_summed = CHECKSUM_NONE; - /* Firewall rules can alter TOS: raw socket (tcpdump) may have - clone of incoming skb: don't disturb it --RR */ - if (skb_cloned(*pskb) && !(*pskb)->sk) { - struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); - if (!nskb) - return NF_DROP; - kfree_skb(*pskb); - *pskb = nskb; - } - switch (hooknum) { case NF_IP_PRE_ROUTING: if (fwops->fw_acct_in) fwops->fw_acct_in(fwops, PF_INET, (struct net_device *)in, - (*pskb)->nh.raw, &redirpt, pskb); + &redirpt, pskb); if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { *pskb = ip_ct_gather_frags(*pskb); @@ -85,7 +71,7 @@ } ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in, - (*pskb)->nh.raw, &redirpt, pskb); + &redirpt, pskb); break; case NF_IP_FORWARD: @@ -95,18 +81,18 @@ ret = FW_ACCEPT; else ret = fwops->fw_forward(fwops, PF_INET, (struct net_device *)out, - (*pskb)->nh.raw, &redirpt, pskb); + &redirpt, pskb); break; case NF_IP_POST_ROUTING: ret = fwops->fw_output(fwops, PF_INET, (struct net_device *)out, - (*pskb)->nh.raw, &redirpt, pskb); + &redirpt, pskb); if (ret == FW_ACCEPT || ret == FW_SKIP) { if (fwops->fw_acct_out) fwops->fw_acct_out(fwops, PF_INET, (struct net_device *)out, - (*pskb)->nh.raw, &redirpt, + &redirpt, pskb); /* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */ @@ -169,10 +155,6 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - return ip_conntrack_confirm(*pskb); } diff -urN linux-2.5.69-bk8/net/ipv4/netfilter/ipchains_core.c linux-2.5.69-bk9/net/ipv4/netfilter/ipchains_core.c --- linux-2.5.69-bk8/net/ipv4/netfilter/ipchains_core.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv4/netfilter/ipchains_core.c 2003-05-14 04:43:45.000000000 -0700 @@ -94,6 +94,7 @@ #include #include #include +#include #include #include @@ -280,11 +281,13 @@ /* Returns whether matches rule or not. */ static int ip_rule_match(struct ip_fwkernel *f, const char *ifname, - struct iphdr *ip, + struct sk_buff **pskb, char tcpsyn, __u16 src_port, __u16 dst_port, char isfrag) { + struct iphdr *ip = (*pskb)->nh.iph; + #define FWINV(bool,invflg) ((bool) ^ !!(f->ipfw.fw_invflg & invflg)) /* * This is a bit simpler as we don't have to walk @@ -401,7 +404,7 @@ * VERY ugly piece of code which actually * makes kernel printf for matching packets... */ -static void dump_packet(const struct iphdr *ip, +static void dump_packet(struct sk_buff **pskb, const char *ifname, struct ip_fwkernel *f, const ip_chainlabel chainlabel, @@ -410,7 +413,7 @@ unsigned int count, int syn) { - __u32 *opt = (__u32 *) (ip + 1); + __u32 *opt = (__u32 *) ((*pskb)->nh.iph + 1); int opti; if (f) { @@ -422,13 +425,18 @@ printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu" " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", - ifname, ip->protocol, NIPQUAD(ip->saddr), - src_port, NIPQUAD(ip->daddr), + ifname, (*pskb)->nh.iph->protocol, + NIPQUAD((*pskb)->nh.iph->saddr), + src_port, + NIPQUAD((*pskb)->nh.iph->daddr), dst_port, - ntohs(ip->tot_len), ip->tos, ntohs(ip->id), - ntohs(ip->frag_off), ip->ttl); + ntohs((*pskb)->nh.iph->tot_len), + (*pskb)->nh.iph->tos, + ntohs((*pskb)->nh.iph->id), + ntohs((*pskb)->nh.iph->frag_off), + (*pskb)->nh.iph->ttl); - for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++) + for (opti = 0; opti < ((*pskb)->nh.iph->ihl - sizeof(struct iphdr) / 4); opti++) printk(" O=0x%8.8X", *opt++); printk(" %s(#%d)\n", syn ? "SYN " : /* "PENANCE" */ "", count); } @@ -509,34 +517,35 @@ static inline int ip_fw_domatch(struct ip_fwkernel *f, - struct iphdr *ip, const char *rif, const ip_chainlabel label, - struct sk_buff *skb, + struct sk_buff **pskb, unsigned int slot, __u16 src_port, __u16 dst_port, unsigned int count, - int tcpsyn) + int tcpsyn, + unsigned char *tos) { - f->counters[slot].bcnt+=ntohs(ip->tot_len); + f->counters[slot].bcnt+=ntohs((*pskb)->nh.iph->tot_len); f->counters[slot].pcnt++; if (f->ipfw.fw_flg & IP_FW_F_PRN) { - dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn); + dump_packet(pskb,rif,f,label,src_port,dst_port,count,tcpsyn); } - ip->tos = (ip->tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor; + + *tos = (*tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor; /* This functionality is useless in stock 2.0.x series, but we don't * discard the mark thing altogether, to avoid breaking ipchains (and, * more importantly, the ipfwadm wrapper) --PR */ if (f->ipfw.fw_flg & IP_FW_F_MARKABS) { - skb->nfmark = f->ipfw.fw_mark; + (*pskb)->nfmark = f->ipfw.fw_mark; } else { - skb->nfmark += f->ipfw.fw_mark; + (*pskb)->nfmark += f->ipfw.fw_mark; } if (f->ipfw.fw_flg & IP_FW_F_NETLINK) { #if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE) - size_t len = min_t(unsigned int, f->ipfw.fw_outputsize, ntohs(ip->tot_len)) - + sizeof(__u32) + sizeof(skb->nfmark) + IFNAMSIZ; + size_t len = min_t(unsigned int, f->ipfw.fw_outputsize, ntohs((*pskb)->nh.iph->tot_len)) + + sizeof(__u32) + sizeof((*pskb)->nfmark) + IFNAMSIZ; struct sk_buff *outskb=alloc_skb(len, GFP_ATOMIC); duprintf("Sending packet out NETLINK (length = %u).\n", @@ -545,10 +554,13 @@ /* Prepend length, mark & interface */ skb_put(outskb, len); *((__u32 *)outskb->data) = (__u32)len; - *((__u32 *)(outskb->data+sizeof(__u32))) = skb->nfmark; + *((__u32 *)(outskb->data+sizeof(__u32))) = + (*pskb)->nfmark; strcpy(outskb->data+sizeof(__u32)*2, rif); - memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip, - len-(sizeof(__u32)*2+IFNAMSIZ)); + skb_copy_bits(*pskb, + ((char *)(*pskb)->nh.iph - (char *)(*pskb)->data), + outskb->data+sizeof(__u32)*2+IFNAMSIZ, + len-(sizeof(__u32)*2+IFNAMSIZ)); netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC); } else { @@ -571,22 +583,18 @@ * user checking mode (counters are not updated, TOS & mark not done). */ static int -ip_fw_check(struct iphdr *ip, - const char *rif, +ip_fw_check(const char *rif, __u16 *redirport, struct ip_chain *chain, - struct sk_buff *skb, + struct sk_buff **pskb, unsigned int slot, int testing) { - struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl); - struct udphdr *udp=(struct udphdr *)((__u32 *)ip+ip->ihl); - struct icmphdr *icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl); __u32 src, dst; __u16 src_port = 0xFFFF, dst_port = 0xFFFF; char tcpsyn=0; __u16 offset; - unsigned char oldtos; + unsigned char tos; struct ip_fwkernel *f; int ret = FW_SKIP+2; unsigned int count; @@ -598,7 +606,7 @@ * rule is also a fragment-specific rule, non-fragments won't * match it. */ - offset = ntohs(ip->frag_off) & IP_OFFSET; + offset = ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET; /* * Don't allow a fragment of TCP 8 bytes in. Nobody @@ -606,10 +614,10 @@ * in by doing a flag overwrite to pass the direction * checks. */ - if (offset == 1 && ip->protocol == IPPROTO_TCP) { + if (offset == 1 && (*pskb)->nh.iph->protocol == IPPROTO_TCP) { if (!testing && net_ratelimit()) { printk("Suspect TCP fragment.\n"); - dump_packet(ip,rif,NULL,NULL,0,0,0,0); + dump_packet(pskb,rif,NULL,NULL,0,0,0,0); } return FW_BLOCK; } @@ -621,7 +629,7 @@ */ if (offset == 0) { unsigned int size_req; - switch (ip->protocol) { + switch ((*pskb)->nh.iph->protocol) { case IPPROTO_TCP: /* Don't care about things past flags word */ size_req = 16; @@ -640,18 +648,19 @@ * used to rewrite port information, and thus should * be blocked. */ - if (ntohs(ip->tot_len) < (ip->ihl<<2)+size_req) { + if (ntohs((*pskb)->nh.iph->tot_len) < + ((*pskb)->nh.iph->ihl<<2)+size_req) { if (!testing && net_ratelimit()) { printk("Suspect short first fragment.\n"); - dump_packet(ip,rif,NULL,NULL,0,0,0,0); + dump_packet(pskb,rif,NULL,NULL,0,0,0,0); } return FW_BLOCK; } } - src = ip->saddr; - dst = ip->daddr; - oldtos = ip->tos; + src = (*pskb)->nh.iph->saddr; + dst = (*pskb)->nh.iph->daddr; + tos = (*pskb)->nh.iph->tos; /* * If we got interface from which packet came @@ -662,47 +671,68 @@ */ dprintf("Packet "); - switch(ip->protocol) - { + switch ((*pskb)->nh.iph->protocol) { case IPPROTO_TCP: dprintf("TCP "); if (!offset) { - src_port=ntohs(tcp->source); - dst_port=ntohs(tcp->dest); + struct tcphdr tcph; + + if (skb_copy_bits(*pskb, + (*pskb)->nh.iph->ihl * 4, + &tcph, sizeof(tcph))) + return FW_BLOCK; + + src_port = ntohs(tcph.source); + dst_port = ntohs(tcph.dest); /* Connection initilisation can only * be made when the syn bit is set and * neither of the ack or reset is * set. */ - if(tcp->syn && !(tcp->ack || tcp->rst)) - tcpsyn=1; + if (tcph.syn && !(tcph.ack || tcph.rst)) + tcpsyn = 1; } break; case IPPROTO_UDP: dprintf("UDP "); if (!offset) { - src_port=ntohs(udp->source); - dst_port=ntohs(udp->dest); + struct udphdr udph; + + if (skb_copy_bits(*pskb, + (*pskb)->nh.iph->ihl * 4, + &udph, sizeof(udph))) + return FW_BLOCK; + + src_port = ntohs(udph.source); + dst_port = ntohs(udph.dest); } break; case IPPROTO_ICMP: if (!offset) { - src_port=(__u16)icmp->type; - dst_port=(__u16)icmp->code; + struct icmphdr icmph; + + if (skb_copy_bits(*pskb, + (*pskb)->nh.iph->ihl * 4, + &icmph, sizeof(icmph))) + return FW_BLOCK; + + src_port = (__u16) icmph.type; + dst_port = (__u16) icmph.code; } dprintf("ICMP "); break; default: - dprintf("p=%d ",ip->protocol); + dprintf("p=%d ", (*pskb)->nh.iph->protocol); break; } #ifdef DEBUG_IP_FIREWALL - print_ip(ip->saddr); + print_ip((*pskb)->nh.iph->saddr); if (offset) dprintf(":fragment (%i) ", ((int)offset)<<2); - else if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP - || ip->protocol==IPPROTO_ICMP) + else if ((*pskb)->nh.iph->protocol == IPPROTO_TCP || + (*pskb)->nh.iph->protocol == IPPROTO_UDP || + (*pskb)->nh.iph->protocol == IPPROTO_ICMP) dprintf(":%hu:%hu", src_port, dst_port); dprintf("\n"); #endif @@ -715,13 +745,14 @@ count = 0; for (; f; f = f->next) { count++; - if (ip_rule_match(f,rif,ip, - tcpsyn,src_port,dst_port,offset)) { + if (ip_rule_match(f, rif, pskb, + tcpsyn, src_port, dst_port, + offset)) { if (!testing - && !ip_fw_domatch(f, ip, rif, chain->label, - skb, slot, + && !ip_fw_domatch(f, rif, chain->label, + pskb, slot, src_port, dst_port, - count, tcpsyn)) { + count, tcpsyn, &tos)) { ret = FW_BLOCK; cleanup(chain, 0, slot); goto out; @@ -780,7 +811,7 @@ if (!testing) { chain->reent[slot].counters.pcnt++; chain->reent[slot].counters.bcnt - += ntohs(ip->tot_len); + += ntohs((*pskb)->nh.iph->tot_len); } } } @@ -790,10 +821,16 @@ if (!testing) FWC_READ_UNLOCK(&ip_fw_lock); /* Recalculate checksum if not going to reject, and TOS changed. */ - if (ip->tos != oldtos + if ((*pskb)->nh.iph->tos != tos && ret != FW_REJECT && ret != FW_BLOCK - && !testing) - ip_send_check(ip); + && !testing) { + if (!skb_ip_make_writable(pskb, offsetof(struct iphdr, tos)+1)) + ret = FW_BLOCK; + else { + (*pskb)->nh.iph->tos = tos; + ip_send_check((*pskb)->nh.iph); + } + } if (ret == FW_REDIRECT && redirport) { if ((*redirport = htons(f->ipfw.fw_redirpt)) == 0) { @@ -1349,18 +1386,40 @@ if ((chain = find_label(new->fwt_label)) == NULL) ret = ENOENT; else { + struct sk_buff *tmp_skb; + int hdrlen; + + hdrlen = sizeof(struct ip_fwpkt) - + sizeof(struct in_addr) - + IFNAMSIZ; + ip = &(new->fwt_packet.fwp_iph); - if (ip->ihl != sizeof(struct iphdr) / sizeof(int)) { - duprintf("ip_fw_ctl: ip->ihl=%d, want %d\n", - ip->ihl, - sizeof(struct iphdr) / sizeof(int)); - ret = EINVAL; - } - else { - ret = ip_fw_check(ip, new->fwt_packet.fwp_vianame, + /* Fix this one up by hand, who knows how many + * tools will break if we start to barf on this. + */ + if (ntohs(ip->tot_len) > hdrlen) + ip->tot_len = htons(hdrlen); + + if (ip->ihl != sizeof(struct iphdr) / sizeof(u32)) { + duprintf("ip_fw_ctl: ip->ihl=%d, want %d\n", + ip->ihl, + sizeof(struct iphdr) / sizeof(u32)); + ret = EINVAL; + } else if ((tmp_skb = alloc_skb(hdrlen, + GFP_ATOMIC)) == NULL) { + duprintf("ip_fw_ctl: tmp_skb alloc failure\n"); + ret = EFAULT; + } else { + skb_reserve(tmp_skb, hdrlen); + skb_push(tmp_skb, hdrlen); + memcpy(tmp_skb->data, ip, hdrlen); + tmp_skb->nh.raw = + (unsigned char *) tmp_skb->data; + ret = ip_fw_check(new->fwt_packet.fwp_vianame, NULL, chain, - NULL, SLOT_NUMBER(), 1); + &tmp_skb, SLOT_NUMBER(), 1); + kfree_skb(tmp_skb); switch (ret) { case FW_ACCEPT: ret = 0; break; @@ -1690,41 +1749,37 @@ * Interface to the generic firewall chains. */ int ipfw_input_check(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb) { - return ip_fw_check(phdr, dev->name, - arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0); + return ip_fw_check(dev->name, + arg, IP_FW_INPUT_CHAIN, pskb, SLOT_NUMBER(), 0); } int ipfw_output_check(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb) { /* Locally generated bogus packets by root. . */ - if (((struct iphdr *)phdr)->ihl * 4 < sizeof(struct iphdr) - || (*pskb)->len < sizeof(struct iphdr)) + if ((*pskb)->len < sizeof(struct iphdr) || + (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) return FW_ACCEPT; - return ip_fw_check(phdr, dev->name, - arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0); + return ip_fw_check(dev->name, + arg, IP_FW_OUTPUT_CHAIN, pskb, SLOT_NUMBER(), 0); } int ipfw_forward_check(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb) { - return ip_fw_check(phdr, dev->name, - arg, IP_FW_FORWARD_CHAIN, *pskb, SLOT_NUMBER(), 0); + return ip_fw_check(dev->name, + arg, IP_FW_FORWARD_CHAIN, pskb, SLOT_NUMBER(), 0); } -struct firewall_ops ipfw_ops= -{ - NULL, - ipfw_forward_check, - ipfw_input_check, - ipfw_output_check, - NULL, - NULL +struct firewall_ops ipfw_ops = { + .fw_forward = ipfw_forward_check, + .fw_input = ipfw_input_check, + .fw_output = ipfw_output_check, }; int ipfw_init_or_cleanup(int init) diff -urN linux-2.5.69-bk8/net/ipv4/netfilter/ipfwadm_core.c linux-2.5.69-bk9/net/ipv4/netfilter/ipfwadm_core.c --- linux-2.5.69-bk8/net/ipv4/netfilter/ipfwadm_core.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv4/netfilter/ipfwadm_core.c 2003-05-14 04:43:45.000000000 -0700 @@ -126,6 +126,7 @@ #include #include #include +#include #include #include @@ -259,18 +260,18 @@ } } -static void print_packet(struct iphdr *ip, +static void print_packet(struct sk_buff **pskb, u16 src_port, u16 dst_port, u16 icmp_type, char *chain, char *rule, char *devname) { - __u32 *opt = (__u32 *) (ip + 1); + __u32 *opt = (__u32 *) ((*pskb)->nh.iph + 1); int opti; - __u16 foff = ntohs(ip->frag_off); + __u16 foff = ntohs((*pskb)->nh.iph->frag_off); + int protocol = (*pskb)->nh.iph->protocol; printk(KERN_INFO "IP %s %s%s", chain, rule, devname); - switch(ip->protocol) - { + switch (protocol) { case IPPROTO_TCP: printk(" TCP "); break; @@ -281,22 +282,28 @@ printk(" ICMP/%d ", icmp_type); break; default: - printk(" PROTO=%d ", ip->protocol); + printk(" PROTO=%d ", protocol); break; - } - print_ip(ip->saddr); - if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP) + }; + + print_ip((*pskb)->nh.iph->saddr); + if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) printk(":%hu", src_port); printk(" "); - print_ip(ip->daddr); - if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP) + print_ip((*pskb)->nh.iph->daddr); + if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) printk(":%hu", dst_port); printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu", - ntohs(ip->tot_len), ip->tos, ntohs(ip->id), - foff & IP_OFFSET, ip->ttl); - if (foff & IP_DF) printk(" DF=1"); - if (foff & IP_MF) printk(" MF=1"); - for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++) + ntohs((*pskb)->nh.iph->tot_len), + (*pskb)->nh.iph->tos, + ntohs((*pskb)->nh.iph->id), + foff & IP_OFFSET, + (*pskb)->nh.iph->ttl); + if (foff & IP_DF) + printk(" DF=1"); + if (foff & IP_MF) + printk(" MF=1"); + for (opti = 0; opti < ((*pskb)->nh.iph->ihl - sizeof(struct iphdr) / 4); opti++) printk(" O=0x%8.8X", *opt++); printk("\n"); } @@ -314,13 +321,11 @@ */ -int ip_fw_chk(struct iphdr *ip, struct net_device *rif, __u16 *redirport, +int ip_fw_chk(struct sk_buff **pskb, + struct net_device *rif, __u16 *redirport, struct ip_fw *chain, int policy, int mode) { struct ip_fw *f; - struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl); - struct udphdr *udp=(struct udphdr *)((__u32 *)ip+ip->ihl); - struct icmphdr *icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl); __u32 src, dst; __u16 src_port=0xFFFF, dst_port=0xFFFF, icmp_type=0xFF; unsigned short f_prt=0, prt; @@ -328,6 +333,7 @@ unsigned short offset; int answer; unsigned char tosand, tosxor; + int protocol; /* * If the chain is empty follow policy. The BSD one @@ -335,9 +341,6 @@ * flushing and rebuilding the tables. */ - src = ip->saddr; - dst = ip->daddr; - /* * This way we handle fragmented packets. * we ignore all fragments but the first one @@ -352,7 +355,8 @@ * of system. */ - offset = ntohs(ip->frag_off) & IP_OFFSET; + offset = ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET; + protocol = (*pskb)->nh.iph->protocol; /* * Don't allow a fragment of TCP 8 bytes in. Nobody @@ -361,19 +365,21 @@ * checks. */ - if (offset == 1 && ip->protocol == IPPROTO_TCP) + if (offset == 1 && protocol == IPPROTO_TCP) return FW_BLOCK; if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) && - (ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP || - ip->protocol == IPPROTO_ICMP)) + (protocol == IPPROTO_TCP || + protocol == IPPROTO_UDP || + protocol == IPPROTO_ICMP)) return FW_ACCEPT; /* * Header fragment for TCP is too small to check the bits. */ - if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len)) + if (protocol == IPPROTO_TCP && + ((*pskb)->nh.iph->ihl<<2)+16 > ntohs((*pskb)->nh.iph->tot_len)) return FW_BLOCK; /* @@ -382,11 +388,13 @@ * But only too short for a packet with ports... */ - else if((ntohs(ip->tot_len)<8+(ip->ihl<<2))&&(ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)) + else if ((ntohs((*pskb)->nh.iph->tot_len) < + 8 + ((*pskb)->nh.iph->ihl << 2)) && + (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)) return FW_BLOCK; - src = ip->saddr; - dst = ip->daddr; + src = (*pskb)->nh.iph->saddr; + dst = (*pskb)->nh.iph->daddr; /* * If we got interface from which packet came @@ -397,54 +405,76 @@ */ dprintf1("Packet "); - switch(ip->protocol) - { + switch (protocol) { case IPPROTO_TCP: dprintf1("TCP "); /* ports stay 0xFFFF if it is not the first fragment */ if (!offset) { - src_port=ntohs(tcp->source); - dst_port=ntohs(tcp->dest); - if(!tcp->ack && !tcp->rst) + struct tcphdr tcph; + + if (skb_copy_bits(*pskb, + (*pskb)->nh.iph->ihl * 4, + &tcph, sizeof(tcph))) + return FW_BLOCK; + + src_port = ntohs(tcph.source); + dst_port = ntohs(tcph.dest); + + if(!tcph.ack && !tcph.rst) /* We do NOT have ACK, value TRUE */ - notcpack=1; - if(!tcp->syn || !notcpack) + notcpack = 1; + if(!tcph.syn || !notcpack) /* We do NOT have SYN, value TRUE */ - notcpsyn=1; + notcpsyn = 1; } - prt=IP_FW_F_TCP; + prt = IP_FW_F_TCP; break; case IPPROTO_UDP: dprintf1("UDP "); /* ports stay 0xFFFF if it is not the first fragment */ if (!offset) { - src_port=ntohs(udp->source); - dst_port=ntohs(udp->dest); + struct udphdr udph; + + if (skb_copy_bits(*pskb, + (*pskb)->nh.iph->ihl * 4, + &udph, sizeof(udph))) + return FW_BLOCK; + + src_port = ntohs(udph.source); + dst_port = ntohs(udph.dest); } - prt=IP_FW_F_UDP; + prt = IP_FW_F_UDP; break; case IPPROTO_ICMP: /* icmp_type stays 255 if it is not the first fragment */ - if (!offset) - icmp_type=(__u16)(icmp->type); - dprintf2("ICMP:%d ",icmp_type); - prt=IP_FW_F_ICMP; + if (!offset) { + struct icmphdr icmph; + + if (skb_copy_bits(*pskb, + (*pskb)->nh.iph->ihl * 4, + &icmph, sizeof(icmph))) + return FW_BLOCK; + + icmp_type = (__u16) icmph.type; + } + dprintf2("ICMP:%d ", icmp_type); + prt = IP_FW_F_ICMP; break; default: - dprintf2("p=%d ",ip->protocol); - prt=IP_FW_F_ALL; + dprintf2("p=%d ", protocol); + prt = IP_FW_F_ALL; break; } #ifdef DEBUG_IP_FIREWALL - dprint_ip(ip->saddr); + dprint_ip(src); - if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) + if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) /* This will print 65535 when it is not the first fragment! */ dprintf2(":%d ", src_port); - dprint_ip(ip->daddr); - if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP) + dprint_ip(dst); + if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) /* This will print 65535 when it is not the first fragment! */ - dprintf2(":%d ",dst_port); + dprintf2(":%d ", dst_port); dprintf1("\n"); #endif @@ -453,8 +483,7 @@ else WRITE_LOCK(&ip_fw_lock); - for (f=chain;f;f=f->fw_next) - { + for (f = chain; f; f = f->fw_next) { /* * This is a bit simpler as we don't have to walk * an interface chain as you do in BSD - same logic @@ -474,14 +503,14 @@ */ match = 0x00; - if ((src&f->fw_smsk.s_addr)==f->fw_src.s_addr - && (dst&f->fw_dmsk.s_addr)==f->fw_dst.s_addr) + if ((src & f->fw_smsk.s_addr) == f->fw_src.s_addr && + (dst & f->fw_dmsk.s_addr) == f->fw_dst.s_addr) /* normal direction */ match |= 0x01; if ((f->fw_flg & IP_FW_F_BIDIR) && - (dst&f->fw_smsk.s_addr)==f->fw_src.s_addr - && (src&f->fw_dmsk.s_addr)==f->fw_dst.s_addr) + (dst & f->fw_smsk.s_addr) == f->fw_src.s_addr && + (src & f->fw_dmsk.s_addr) == f->fw_dst.s_addr) /* reverse direction */ match |= 0x02; @@ -491,9 +520,8 @@ /* * Look for a VIA device match */ - if(f->fw_viadev) - { - if(rif!=f->fw_viadev) + if (f->fw_viadev) { + if (rif != f->fw_viadev) continue; /* Mismatch */ } @@ -560,14 +588,13 @@ continue; f_prt=f->fw_flg&IP_FW_F_KIND; - if (f_prt!=IP_FW_F_ALL) - { + if (f_prt != IP_FW_F_ALL) { /* * Specific firewall - packet's protocol * must match firewall's. */ - if(prt!=f_prt) + if (prt != f_prt) continue; if((prt==IP_FW_F_ICMP && @@ -592,14 +619,14 @@ { char buf[16]; - print_packet(ip, src_port, dst_port, icmp_type, + print_packet(pskb, src_port, dst_port, icmp_type, chain_name(chain, mode), rule_name(f, mode, buf), rif ? rif->name : "-"); } #endif if (mode != IP_FW_MODE_CHK) { - f->fw_bcnt+=ntohs(ip->tot_len); + f->fw_bcnt += ntohs((*pskb)->nh.iph->tot_len); f->fw_pcnt++; } if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) @@ -614,23 +641,30 @@ * of firewall. */ - if (f!=NULL) { - policy=f->fw_flg; - tosand=f->fw_tosand; - tosxor=f->fw_tosxor; + if (f != NULL) { + policy = f->fw_flg; + tosand = f->fw_tosand; + tosxor = f->fw_tosxor; } else { - tosand=0xFF; - tosxor=0x00; + tosand = 0xFF; + tosxor = 0x00; } - if (policy&IP_FW_F_ACCEPT) { + if (policy & IP_FW_F_ACCEPT) { /* Adjust priority and recompute checksum */ - __u8 old_tos = ip->tos; - ip->tos = (old_tos & tosand) ^ tosxor; - if (ip->tos != old_tos) - ip_send_check(ip); + __u8 tos = (*pskb)->nh.iph->tos; + + if (((tos & tosand) ^ tosxor) != tos) { + if (!skb_ip_make_writable(pskb, + offsetof(struct iphdr, tos)+1)) + goto drop_it; + + (*pskb)->nh.iph->tos = (tos & tosand) ^ tosxor; + ip_send_check((*pskb)->nh.iph); + } + #ifdef CONFIG_IP_TRANSPARENT_PROXY - if (policy&IP_FW_F_REDIR) { + if (policy & IP_FW_F_REDIR) { if (redirport) if ((*redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp])) == 0) { /* Wildcard redirection. @@ -643,30 +677,36 @@ } else #endif #ifdef CONFIG_IP_MASQUERADE - if (policy&IP_FW_F_MASQ) + if (policy & IP_FW_F_MASQ) answer = FW_MASQUERADE; else #endif answer = FW_ACCEPT; - } else if(policy&IP_FW_F_ICMPRPL) + } else if (policy & IP_FW_F_ICMPRPL) answer = FW_REJECT; - else + else { + drop_it: answer = FW_BLOCK; + } #ifdef CONFIG_IP_FIREWALL_NETLINK - if((policy&IP_FW_F_PRN) && (answer == FW_REJECT || answer == FW_BLOCK)) + if ((policy & IP_FW_F_PRN) && (answer == FW_REJECT || answer == FW_BLOCK)) { - struct sk_buff *skb=alloc_skb(128, (mode == IP_FW_MODE_CHK) ? - GFP_KERNEL : GFP_ATOMIC); - if(skb) - { + struct sk_buff *skb = alloc_skb(128, + (mode == IP_FW_MODE_CHK) ? + GFP_KERNEL : GFP_ATOMIC); + if (skb) { int len = min_t(unsigned int, - 128, ntohs(ip->tot_len)); + 128, + ntohs((*pskb)->nh.iph->tot_len)); - skb_put(skb,len); - memcpy(skb->data,ip,len); - if(netlink_post(NETLINK_FIREWALL, skb)) + skb_put(skb, len); + skb_copy_bits(*pskb, + ((char *)(*pskb)->nh.iph - + (char *)(*pskb)->data), + skb->data, len); + if (netlink_post(NETLINK_FIREWALL, skb)) kfree_skb(skb); } } @@ -706,6 +746,9 @@ struct ip_fw *ftmp; ftmp = *chainptr; *chainptr = ftmp->fw_next; + if (ftmp->fw_viadev + && ftmp->fw_viadev != (struct net_device *)-1) + dev_put(ftmp->fw_viadev); kfree(ftmp); /* We will block in cleanup's unregister sockopt if unloaded, so this is safe. */ @@ -856,6 +899,9 @@ if(matches) { was_found=1; + if (ftmp->fw_viadev + && ftmp->fw_viadev != (struct net_device *)-1) + dev_put(ftmp->fw_viadev); if (ltmp) { ltmp->fw_next=ftmp->fw_next; @@ -1035,9 +1081,15 @@ if ( cmd == IP_FW_CHECK ) { + struct sk_buff *tmp_skb; struct net_device *viadev; struct ip_fwpkt *ipfwp; struct iphdr *ip; + int hdrlen, ret; + + hdrlen = sizeof(struct ip_fwpkt) - + sizeof(struct in_addr) - + IFNAMSIZ; if ( len != sizeof(struct ip_fwpkt) ) { @@ -1061,12 +1113,34 @@ printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl, sizeof(struct iphdr)/sizeof(int)); #endif + dev_put(viadev); return(EINVAL); } - switch (ip_fw_chk(ip, viadev, NULL, *chains[fwtype], - *policies[fwtype], IP_FW_MODE_CHK)) - { + /* Fix this one up by hand, who knows how many + * tools will break if we start to barf on this. + */ + if (ntohs(ip->tot_len) > hdrlen) + ip->tot_len = htons(hdrlen); + + if ((tmp_skb = alloc_skb(hdrlen, GFP_ATOMIC)) == NULL) { +#ifdef DEBUG_IP_FIREWALL + printk("ip_fw_ctl: tmp_skb alloc failure\n"); +#endif + dev_put(viadev); + return(EFAULT); + } + skb_reserve(tmp_skb, hdrlen); + skb_push(tmp_skb, hdrlen); + memcpy(tmp_skb->data, ip, hdrlen); + + ret = ip_fw_chk(&tmp_skb, viadev, NULL, *chains[fwtype], + *policies[fwtype], IP_FW_MODE_CHK); + + kfree_skb(tmp_skb); + dev_put(viadev); + + switch (ret) { case FW_ACCEPT: return(0); case FW_REDIRECT: @@ -1242,55 +1316,50 @@ */ int ipfw_input_check(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb) { - return ip_fw_chk(phdr, dev, arg, ip_fw_in_chain, ip_fw_in_policy, + return ip_fw_chk(pskb, dev, arg, ip_fw_in_chain, ip_fw_in_policy, IP_FW_MODE_FW); } int ipfw_output_check(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb) { - return ip_fw_chk(phdr, dev, arg, ip_fw_out_chain, ip_fw_out_policy, + return ip_fw_chk(pskb, dev, arg, ip_fw_out_chain, ip_fw_out_policy, IP_FW_MODE_FW); } int ipfw_forward_check(struct firewall_ops *this, int pf, - struct net_device *dev, void *phdr, void *arg, + struct net_device *dev, void *arg, struct sk_buff **pskb) { - return ip_fw_chk(phdr, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy, + return ip_fw_chk(pskb, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy, IP_FW_MODE_FW); } #ifdef CONFIG_IP_ACCT int ipfw_acct_in(struct firewall_ops *this, int pf, struct net_device *dev, - void *phdr, void *arg, struct sk_buff **pskb) + void *arg, struct sk_buff **pskb) { - return ip_fw_chk(phdr,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN); + return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN); } int ipfw_acct_out(struct firewall_ops *this, int pf, struct net_device *dev, - void *phdr, void *arg, struct sk_buff **pskb) + void *arg, struct sk_buff **pskb) { - return ip_fw_chk(phdr,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT); + return ip_fw_chk(pskb,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT); } #endif -struct firewall_ops ipfw_ops= -{ - NULL, - ipfw_forward_check, - ipfw_input_check, - ipfw_output_check, +struct firewall_ops ipfw_ops = { + .fw_forward = ipfw_forward_check, + .fw_input = ipfw_input_check, + .fw_output = ipfw_output_check, #ifdef CONFIG_IP_ACCT - ipfw_acct_in, - ipfw_acct_out -#else - NULL, - NULL + .fw_acct_in = ipfw_acct_in, + .fw_acct_out = ipfw_acct_out, #endif }; @@ -1311,23 +1380,29 @@ for (chn = 0; chn < IP_FW_CHAINS; chn++) for (fw = *chains[chn]; fw; fw = fw->fw_next) if ((fw->fw_vianame)[0] && !strncmp(devname, - fw->fw_vianame, IFNAMSIZ)) + fw->fw_vianame, IFNAMSIZ)) { + dev_hold(dev); fw->fw_viadev = dev; + } } else if (event == NETDEV_DOWN) { for (chn = 0; chn < IP_FW_CHAINS; chn++) for (fw = *chains[chn]; fw; fw = fw->fw_next) /* we could compare just the pointers ... */ if ((fw->fw_vianame)[0] && !strncmp(devname, - fw->fw_vianame, IFNAMSIZ)) + fw->fw_vianame, IFNAMSIZ)){ + if (fw->fw_viadev + && fw->fw_viadev != (struct net_device *)-1) + dev_put(fw->fw_viadev); fw->fw_viadev = (struct net_device*)-1; + } } WRITE_UNLOCK(&ip_fw_lock); return NOTIFY_DONE; } -static struct notifier_block ipfw_dev_notifier={ - .notifier_call = ipfw_device_event, +static struct notifier_block ipfw_dev_notifier = { + .notifier_call = ipfw_device_event, }; #endif diff -urN linux-2.5.69-bk8/net/ipv4/tcp_diag.c linux-2.5.69-bk9/net/ipv4/tcp_diag.c --- linux-2.5.69-bk8/net/ipv4/tcp_diag.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv4/tcp_diag.c 2003-05-14 04:43:45.000000000 -0700 @@ -88,8 +88,10 @@ r->tcpdiag_inode = 0; #ifdef CONFIG_IPV6 if (r->tcpdiag_family == AF_INET6) { - memcpy(r->id.tcpdiag_src, &tw->v6_rcv_saddr, 16); - memcpy(r->id.tcpdiag_dst, &tw->v6_daddr, 16); + ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, + &tw->v6_rcv_saddr); + ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst, + &tw->v6_daddr); } #endif nlh->nlmsg_len = skb->tail - b; @@ -105,8 +107,10 @@ if (r->tcpdiag_family == AF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); - memcpy(r->id.tcpdiag_src, &np->rcv_saddr, 16); - memcpy(r->id.tcpdiag_dst, &np->daddr, 16); + ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, + &np->rcv_saddr); + ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst, + &np->daddr); } #endif diff -urN linux-2.5.69-bk8/net/ipv4/tcp_minisocks.c linux-2.5.69-bk9/net/ipv4/tcp_minisocks.c --- linux-2.5.69-bk8/net/ipv4/tcp_minisocks.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv4/tcp_minisocks.c 2003-05-14 04:43:45.000000000 -0700 @@ -381,10 +381,8 @@ if(tw->family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); - memcpy(&tw->v6_daddr, &np->daddr, - sizeof(struct in6_addr)); - memcpy(&tw->v6_rcv_saddr, &np->rcv_saddr, - sizeof(struct in6_addr)); + ipv6_addr_copy(&tw->v6_daddr, &np->daddr); + ipv6_addr_copy(&tw->v6_rcv_saddr, &np->rcv_saddr); } #endif /* Linkage updates. */ diff -urN linux-2.5.69-bk8/net/ipv6/addrconf.c linux-2.5.69-bk9/net/ipv6/addrconf.c --- linux-2.5.69-bk8/net/ipv6/addrconf.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/addrconf.c 2003-05-14 04:43:45.000000000 -0700 @@ -1195,7 +1195,7 @@ struct in6_rtmsg rtmsg; memset(&rtmsg, 0, sizeof(rtmsg)); - memcpy(&rtmsg.rtmsg_dst, pfx, sizeof(struct in6_addr)); + ipv6_addr_copy(&rtmsg.rtmsg_dst, pfx); rtmsg.rtmsg_dst_len = plen; rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; rtmsg.rtmsg_ifindex = dev->ifindex; diff -urN linux-2.5.69-bk8/net/ipv6/af_inet6.c linux-2.5.69-bk9/net/ipv6/af_inet6.c --- linux-2.5.69-bk8/net/ipv6/af_inet6.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/af_inet6.c 2003-05-14 04:43:45.000000000 -0700 @@ -437,16 +437,14 @@ if (((1<state)&(TCPF_CLOSE|TCPF_SYN_SENT)) && peer == 1) return -ENOTCONN; sin->sin6_port = inet->dport; - memcpy(&sin->sin6_addr, &np->daddr, sizeof(struct in6_addr)); + ipv6_addr_copy(&sin->sin6_addr, &np->daddr); if (np->sndflow) sin->sin6_flowinfo = np->flow_label; } else { if (ipv6_addr_type(&np->rcv_saddr) == IPV6_ADDR_ANY) - memcpy(&sin->sin6_addr, &np->saddr, - sizeof(struct in6_addr)); + ipv6_addr_copy(&sin->sin6_addr, &np->saddr); else - memcpy(&sin->sin6_addr, &np->rcv_saddr, - sizeof(struct in6_addr)); + ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr); sin->sin6_port = inet->sport; } @@ -873,6 +871,9 @@ ipv6_sysctl_unregister(); #endif cleanup_ipv6_mibs(); + kmem_cache_destroy(tcp6_sk_cachep); + kmem_cache_destroy(udp6_sk_cachep); + kmem_cache_destroy(raw6_sk_cachep); } module_exit(inet6_exit); #endif /* MODULE */ diff -urN linux-2.5.69-bk8/net/ipv6/ah6.c linux-2.5.69-bk9/net/ipv6/ah6.c --- linux-2.5.69-bk8/net/ipv6/ah6.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/ah6.c 2003-05-14 04:43:45.000000000 -0700 @@ -75,8 +75,10 @@ skb->nh.ipv6h->version = 6; skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); skb->nh.ipv6h->nexthdr = IPPROTO_AH; - memcpy(&skb->nh.ipv6h->saddr, &x->props.saddr, sizeof(struct in6_addr)); - memcpy(&skb->nh.ipv6h->daddr, &x->id.daddr, sizeof(struct in6_addr)); + ipv6_addr_copy(&skb->nh.ipv6h->saddr, + (struct in6_addr *) &x->props.saddr); + ipv6_addr_copy(&skb->nh.ipv6h->daddr, + (struct in6_addr *) &x->id.daddr); ah = (struct ip_auth_hdr*)(skb->nh.ipv6h+1); ah->nexthdr = IPPROTO_IPV6; } else { diff -urN linux-2.5.69-bk8/net/ipv6/datagram.c linux-2.5.69-bk9/net/ipv6/datagram.c --- linux-2.5.69-bk8/net/ipv6/datagram.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/datagram.c 2003-05-14 04:43:45.000000000 -0700 @@ -80,7 +80,7 @@ iph = (struct ipv6hdr*)skb_put(skb, sizeof(struct ipv6hdr)); skb->nh.ipv6h = iph; - memcpy(&iph->daddr, fl->fl6_dst, 16); + ipv6_addr_copy(&iph->daddr, fl->fl6_dst); serr = SKB_EXT_ERR(skb); serr->ee.ee_errno = err; @@ -141,7 +141,8 @@ sin->sin6_port = serr->port; sin->sin6_scope_id = 0; if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { - memcpy(&sin->sin6_addr, skb->nh.raw + serr->addr_offset, 16); + ipv6_addr_copy(&sin->sin6_addr, + (struct in6_addr *)(skb->nh.raw + serr->addr_offset)); if (np->sndflow) sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) { @@ -163,7 +164,7 @@ sin->sin6_flowinfo = 0; sin->sin6_scope_id = 0; if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { - memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr, 16); + ipv6_addr_copy(&sin->sin6_addr, &skb->nh.ipv6h->saddr); if (np->rxopt.all) datagram_recv_ctl(sk, msg, skb); if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) { diff -urN linux-2.5.69-bk8/net/ipv6/esp6.c linux-2.5.69-bk9/net/ipv6/esp6.c --- linux-2.5.69-bk8/net/ipv6/esp6.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/esp6.c 2003-05-14 04:43:45.000000000 -0700 @@ -184,8 +184,10 @@ top_iph->nexthdr = IPPROTO_ESP; top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr)); top_iph->hop_limit = iph->hop_limit; - memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr)); - memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr)); + ipv6_addr_copy(&top_iph->saddr, + (struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, + (struct in6_addr *)&x->id.daddr); } else { /* XXX exthdr */ esph = (struct ipv6_esp_hdr*)skb_push(skb, x->props.header_len); diff -urN linux-2.5.69-bk8/net/ipv6/ip6_fib.c linux-2.5.69-bk9/net/ipv6/ip6_fib.c --- linux-2.5.69-bk8/net/ipv6/ip6_fib.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/ip6_fib.c 2003-05-14 04:43:45.000000000 -0700 @@ -1227,17 +1227,17 @@ void __init fib6_init(void) { - if (!fib6_node_kmem) - fib6_node_kmem = kmem_cache_create("fib6_nodes", - sizeof(struct fib6_node), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); + fib6_node_kmem = kmem_cache_create("fib6_nodes", + sizeof(struct fib6_node), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); } #ifdef MODULE void fib6_gc_cleanup(void) { del_timer(&ip6_fib_timer); + kmem_cache_destroy(fib6_node_kmem); } #endif diff -urN linux-2.5.69-bk8/net/ipv6/ip6_output.c linux-2.5.69-bk9/net/ipv6/ip6_output.c --- linux-2.5.69-bk8/net/ipv6/ip6_output.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/ip6_output.c 2003-05-14 04:43:45.000000000 -0700 @@ -141,7 +141,7 @@ int ip6_output(struct sk_buff *skb) { - if ((skb->len > skb->dst->dev->mtu || skb_shinfo(skb)->frag_list)) + if ((skb->len > dst_pmtu(skb->dst) || skb_shinfo(skb)->frag_list)) return ip6_fragment(skb, ip6_output2); else return ip6_output2(skb); @@ -1463,8 +1463,8 @@ hdr->payload_len = 0; hdr->hop_limit = np->hop_limit; hdr->nexthdr = proto; - memcpy(&hdr->saddr, fl->fl6_src, sizeof(struct in6_addr)); - memcpy(&hdr->daddr, final_dst, sizeof(struct in6_addr)); + ipv6_addr_copy(&hdr->saddr, fl->fl6_src); + ipv6_addr_copy(&hdr->daddr, final_dst); skb->dst = dst_clone(&rt->u.dst); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); diff -urN linux-2.5.69-bk8/net/ipv6/mcast.c linux-2.5.69-bk9/net/ipv6/mcast.c --- linux-2.5.69-bk8/net/ipv6/mcast.c 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/mcast.c 2003-05-14 04:43:45.000000000 -0700 @@ -179,7 +179,7 @@ return -ENOMEM; mc_lst->next = NULL; - memcpy(&mc_lst->addr, addr, sizeof(struct in6_addr)); + ipv6_addr_copy(&mc_lst->addr, addr); if (ifindex == 0) { struct rt6_info *rt; @@ -825,7 +825,7 @@ mc->mca_timer.function = igmp6_timer_handler; mc->mca_timer.data = (unsigned long) mc; - memcpy(&mc->mca_addr, addr, sizeof(struct in6_addr)); + ipv6_addr_copy(&mc->mca_addr, addr); mc->idev = idev; mc->mca_users = 1; atomic_set(&mc->mca_refcnt, 2); diff -urN linux-2.5.69-bk8/net/ipv6/raw.c linux-2.5.69-bk9/net/ipv6/raw.c --- linux-2.5.69-bk8/net/ipv6/raw.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/raw.c 2003-05-14 04:43:45.000000000 -0700 @@ -398,8 +398,7 @@ /* Copy the address. */ if (sin6) { sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, - sizeof(struct in6_addr)); + ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); sin6->sin6_flowinfo = 0; sin6->sin6_scope_id = 0; if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { diff -urN linux-2.5.69-bk8/net/ipv6/route.c linux-2.5.69-bk9/net/ipv6/route.c --- linux-2.5.69-bk8/net/ipv6/route.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/route.c 2003-05-14 04:43:45.000000000 -0700 @@ -1934,5 +1934,6 @@ xfrm6_fini(); rt6_ifdown(NULL); fib6_gc_cleanup(); + kmem_cache_destroy(ip6_dst_ops.kmem_cachep); } #endif /* MODULE */ diff -urN linux-2.5.69-bk8/net/ipv6/udp.c linux-2.5.69-bk9/net/ipv6/udp.c --- linux-2.5.69-bk8/net/ipv6/udp.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/udp.c 2003-05-14 04:43:45.000000000 -0700 @@ -467,8 +467,7 @@ if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); } else { - memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, - sizeof(struct in6_addr)); + ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); if (np->rxopt.all) datagram_recv_ctl(sk, msg, skb); diff -urN linux-2.5.69-bk8/net/ipv6/xfrm6_state.c linux-2.5.69-bk9/net/ipv6/xfrm6_state.c --- linux-2.5.69-bk8/net/ipv6/xfrm6_state.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/ipv6/xfrm6_state.c 2003-05-14 04:43:45.000000000 -0700 @@ -25,8 +25,8 @@ { /* Initialize temporary selector matching only * to current session. */ - memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr)); - memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr)); + ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, fl->fl6_dst); + ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, fl->fl6_src); x->sel.dport = fl->fl_ip_dport; x->sel.dport_mask = ~0; x->sel.sport = fl->fl_ip_sport; @@ -93,13 +93,17 @@ if (x0) { xfrm_state_hold(x0); } else if (create && (x0 = xfrm_state_alloc()) != NULL) { - memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr)); - memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr)); + ipv6_addr_copy((struct in6_addr *)x0->sel.daddr.a6, + (struct in6_addr *)daddr); + ipv6_addr_copy((struct in6_addr *)x0->sel.saddr.a6, + (struct in6_addr *)saddr); x0->sel.prefixlen_d = 128; x0->sel.prefixlen_s = 128; - memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr)); + ipv6_addr_copy((struct in6_addr *)x0->props.saddr.a6, + (struct in6_addr *)saddr); x0->km.state = XFRM_STATE_ACQ; - memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr)); + ipv6_addr_copy((struct in6_addr *)x0->id.daddr.a6, + (struct in6_addr *)daddr); x0->id.proto = proto; x0->props.family = AF_INET6; x0->props.mode = mode; diff -urN linux-2.5.69-bk8/net/netsyms.c linux-2.5.69-bk9/net/netsyms.c --- linux-2.5.69-bk8/net/netsyms.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/netsyms.c 2003-05-14 04:43:46.000000000 -0700 @@ -45,6 +45,9 @@ #include #include #include +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) +#include +#endif #include #include #include @@ -526,6 +529,9 @@ EXPORT_SYMBOL(ip_rcv); EXPORT_SYMBOL(arp_rcv); EXPORT_SYMBOL(arp_tbl); +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) +EXPORT_SYMBOL(clip_tbl_hook); +#endif EXPORT_SYMBOL(arp_find); #endif /* CONFIG_INET */ diff -urN linux-2.5.69-bk8/net/sunrpc/rpc_pipe.c linux-2.5.69-bk9/net/sunrpc/rpc_pipe.c --- linux-2.5.69-bk8/net/sunrpc/rpc_pipe.c 2003-05-14 04:43:39.000000000 -0700 +++ linux-2.5.69-bk9/net/sunrpc/rpc_pipe.c 2003-05-14 04:43:46.000000000 -0700 @@ -156,7 +156,7 @@ } static ssize_t -rpc_pipe_read(struct file *filp, char *buf, size_t len, loff_t *offset) +rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) { struct inode *inode = filp->f_dentry->d_inode; struct rpc_inode *rpci = RPC_I(inode); @@ -193,7 +193,7 @@ } static ssize_t -rpc_pipe_write(struct file *filp, const char *buf, size_t len, loff_t *offset) +rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) { struct inode *inode = filp->f_dentry->d_inode; struct rpc_inode *rpci = RPC_I(inode); diff -urN linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_device.h linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_device.h --- linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_device.h 2003-05-04 16:53:29.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_device.h 2003-05-14 04:43:46.000000000 -0700 @@ -135,8 +135,8 @@ int snd_seq_oss_open(struct file *file, int level); void snd_seq_oss_release(seq_oss_devinfo_t *dp); int snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long arg); -int snd_seq_oss_read(seq_oss_devinfo_t *dev, char *buf, int count); -int snd_seq_oss_write(seq_oss_devinfo_t *dp, const char *buf, int count, struct file *opt); +int snd_seq_oss_read(seq_oss_devinfo_t *dev, char __user *buf, int count); +int snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt); unsigned int snd_seq_oss_poll(seq_oss_devinfo_t *dp, struct file *file, poll_table * wait); void snd_seq_oss_reset(seq_oss_devinfo_t *dp); diff -urN linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_ioctl.c linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_ioctl.c --- linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_ioctl.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_ioctl.c 2003-05-14 04:43:46.000000000 -0700 @@ -35,7 +35,7 @@ struct synth_info inf; struct midi_info minf; unsigned char ev[8]; - void *arg = (void*)carg; + void __user *arg = (void __user *)carg; snd_seq_event_t tmpev; switch (cmd) { diff -urN linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_rw.c linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_rw.c --- linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_rw.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_rw.c 2003-05-14 04:43:46.000000000 -0700 @@ -41,7 +41,7 @@ */ int -snd_seq_oss_read(seq_oss_devinfo_t *dp, char *buf, int count) +snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count) { seq_oss_readq_t *readq = dp->readq; int cnt, pos; @@ -81,7 +81,7 @@ */ int -snd_seq_oss_write(seq_oss_devinfo_t *dp, const char *buf, int count, struct file *opt) +snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt) { int rc, c, p, ev_size; evrec_t rec; diff -urN linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_synth.c linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_synth.c --- linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_synth.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_synth.c 2003-05-14 04:43:46.000000000 -0700 @@ -450,7 +450,7 @@ */ int snd_seq_oss_synth_load_patch(seq_oss_devinfo_t *dp, int dev, int fmt, - const char *buf, int p, int c) + const char __user *buf, int p, int c) { seq_oss_synth_t *rec; int rc; diff -urN linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_timer.c linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_timer.c --- linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_timer.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_timer.c 2003-05-14 04:43:46.000000000 -0700 @@ -227,19 +227,19 @@ * ioctls */ int -snd_seq_oss_timer_ioctl(seq_oss_timer_t *timer, unsigned int cmd, void *arg) +snd_seq_oss_timer_ioctl(seq_oss_timer_t *timer, unsigned int cmd, int __user *arg) { int value; if (cmd == SNDCTL_SEQ_CTRLRATE) { debug_printk(("ctrl rate\n")); /* if *arg == 0, just return the current rate */ - if (get_user(value, (int *)arg)) + if (get_user(value, arg)) return -EFAULT; if (value) return -EINVAL; value = ((timer->oss_tempo * timer->oss_timebase) + 30) / 60; - return put_user(value, (int *)arg) ? -EFAULT : 0; + return put_user(value, arg) ? -EFAULT : 0; } if (timer->dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) @@ -257,12 +257,12 @@ return snd_seq_oss_timer_continue(timer); case SNDCTL_TMR_TEMPO: debug_printk(("timer tempo\n")); - if (get_user(value, (int *)arg)) + if (get_user(value, arg)) return -EFAULT; return snd_seq_oss_timer_tempo(timer, value); case SNDCTL_TMR_TIMEBASE: debug_printk(("timer timebase\n")); - if (get_user(value, (int *)arg)) + if (get_user(value, arg)) return -EFAULT; if (value < MIN_OSS_TIMEBASE) value = MIN_OSS_TIMEBASE; diff -urN linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_timer.h linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_timer.h --- linux-2.5.69-bk8/sound/core/seq/oss/seq_oss_timer.h 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/oss/seq_oss_timer.h 2003-05-14 04:43:46.000000000 -0700 @@ -46,7 +46,7 @@ int snd_seq_oss_timer_tempo(seq_oss_timer_t *timer, int value); #define snd_seq_oss_timer_reset snd_seq_oss_timer_start -int snd_seq_oss_timer_ioctl(seq_oss_timer_t *timer, unsigned int cmd, void *arg); +int snd_seq_oss_timer_ioctl(seq_oss_timer_t *timer, unsigned int cmd, int __user *arg); /* * get current processed time diff -urN linux-2.5.69-bk8/sound/core/seq/seq_clientmgr.c linux-2.5.69-bk9/sound/core/seq/seq_clientmgr.c --- linux-2.5.69-bk8/sound/core/seq/seq_clientmgr.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk9/sound/core/seq/seq_clientmgr.c 2003-05-14 04:43:46.000000000 -0700 @@ -365,7 +365,7 @@ * -EINVAL no enough user-space buffer to write the whole event * -EFAULT seg. fault during copy to user space */ -static ssize_t snd_seq_read(struct file *file, char *buf, size_t count, loff_t *offset) +static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { client_t *client = (client_t *) file->private_data; fifo_t *fifo; @@ -959,7 +959,7 @@ * -EMLINK too many hops * others depends on return value from driver callback */ -static ssize_t snd_seq_write(struct file *file, const char *buf, size_t count, loff_t *offset) +static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { client_t *client = (client_t *) file->private_data; int written = 0, len; @@ -1077,7 +1077,7 @@ /* SYSTEM_INFO ioctl() */ -static int snd_seq_ioctl_system_info(client_t *client, unsigned long arg) +static int snd_seq_ioctl_system_info(client_t *client, void __user *arg) { snd_seq_system_info_t info; @@ -1090,20 +1090,20 @@ info.cur_clients = client_usage.cur; info.cur_queues = snd_seq_queue_get_cur_queues(); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } /* RUNNING_MODE ioctl() */ -static int snd_seq_ioctl_running_mode(client_t *client, unsigned long arg) +static int snd_seq_ioctl_running_mode(client_t *client, void __user *arg) { struct sndrv_seq_running_info info; client_t *cptr; int err = 0; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; /* requested client number */ @@ -1148,12 +1148,12 @@ memset(info->reserved, 0, sizeof(info->reserved)); } -static int snd_seq_ioctl_get_client_info(client_t * client, unsigned long arg) +static int snd_seq_ioctl_get_client_info(client_t * client, void __user *arg) { client_t *cptr; snd_seq_client_info_t client_info; - if (copy_from_user(&client_info, (void*)arg, sizeof(client_info))) + if (copy_from_user(&client_info, arg, sizeof(client_info))) return -EFAULT; /* requested client number */ @@ -1164,18 +1164,18 @@ get_client_info(cptr, &client_info); snd_seq_client_unlock(cptr); - if (copy_to_user((void*)arg, &client_info, sizeof(client_info))) + if (copy_to_user(arg, &client_info, sizeof(client_info))) return -EFAULT; return 0; } /* CLIENT_INFO ioctl() */ -static int snd_seq_ioctl_set_client_info(client_t * client, unsigned long arg) +static int snd_seq_ioctl_set_client_info(client_t * client, void __user *arg) { snd_seq_client_info_t client_info; - if (copy_from_user(&client_info, (void*)arg, sizeof(client_info))) + if (copy_from_user(&client_info, arg, sizeof(client_info))) return -EFAULT; /* it is not allowed to set the info fields for an another client */ @@ -1201,13 +1201,13 @@ /* * CREATE PORT ioctl() */ -static int snd_seq_ioctl_create_port(client_t * client, unsigned long arg) +static int snd_seq_ioctl_create_port(client_t * client, void __user *arg) { client_port_t *port; snd_seq_port_info_t info; snd_seq_port_callback_t *callback; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; /* it is not allowed to create the port for an another client */ @@ -1242,7 +1242,7 @@ snd_seq_set_port_info(port, &info); snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; @@ -1251,13 +1251,13 @@ /* * DELETE PORT ioctl() */ -static int snd_seq_ioctl_delete_port(client_t * client, unsigned long arg) +static int snd_seq_ioctl_delete_port(client_t * client, void __user *arg) { snd_seq_port_info_t info; int err; /* set passed parameters */ - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; /* it is not allowed to remove the port for an another client */ @@ -1274,13 +1274,13 @@ /* * GET_PORT_INFO ioctl() (on any client) */ -static int snd_seq_ioctl_get_port_info(client_t *client, unsigned long arg) +static int snd_seq_ioctl_get_port_info(client_t *client, void __user *arg) { client_t *cptr; client_port_t *port; snd_seq_port_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; cptr = snd_seq_client_use_ptr(info.addr.client); if (cptr == NULL) @@ -1297,7 +1297,7 @@ snd_seq_port_unlock(port); snd_seq_client_unlock(cptr); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } @@ -1306,12 +1306,12 @@ /* * SET_PORT_INFO ioctl() (only ports on this/own client) */ -static int snd_seq_ioctl_set_port_info(client_t * client, unsigned long arg) +static int snd_seq_ioctl_set_port_info(client_t * client, void __user *arg) { client_port_t *port; snd_seq_port_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (info.addr.client != client->number) /* only set our own ports ! */ @@ -1381,14 +1381,14 @@ /* * add to port's subscription list IOCTL interface */ -static int snd_seq_ioctl_subscribe_port(client_t * client, unsigned long arg) +static int snd_seq_ioctl_subscribe_port(client_t * client, void __user *arg) { int result = -EINVAL; client_t *receiver = NULL, *sender = NULL; client_port_t *sport = NULL, *dport = NULL; snd_seq_port_subscribe_t subs; - if (copy_from_user(&subs, (void*)arg, sizeof(subs))) + if (copy_from_user(&subs, arg, sizeof(subs))) return -EFAULT; if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) @@ -1425,14 +1425,14 @@ /* * remove from port's subscription list */ -static int snd_seq_ioctl_unsubscribe_port(client_t * client, unsigned long arg) +static int snd_seq_ioctl_unsubscribe_port(client_t * client, void __user *arg) { int result = -ENXIO; client_t *receiver = NULL, *sender = NULL; client_port_t *sport = NULL, *dport = NULL; snd_seq_port_subscribe_t subs; - if (copy_from_user(&subs, (void*)arg, sizeof(subs))) + if (copy_from_user(&subs, arg, sizeof(subs))) return -EFAULT; if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) @@ -1466,13 +1466,13 @@ /* CREATE_QUEUE ioctl() */ -static int snd_seq_ioctl_create_queue(client_t *client, unsigned long arg) +static int snd_seq_ioctl_create_queue(client_t *client, void __user *arg) { snd_seq_queue_info_t info; int result; queue_t *q; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; result = snd_seq_queue_alloc(client->number, info.locked, info.flags); @@ -1494,30 +1494,30 @@ q->name[sizeof(q->name)-1] = 0; queuefree(q); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } /* DELETE_QUEUE ioctl() */ -static int snd_seq_ioctl_delete_queue(client_t *client, unsigned long arg) +static int snd_seq_ioctl_delete_queue(client_t *client, void __user *arg) { snd_seq_queue_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; return snd_seq_queue_delete(client->number, info.queue); } /* GET_QUEUE_INFO ioctl() */ -static int snd_seq_ioctl_get_queue_info(client_t *client, unsigned long arg) +static int snd_seq_ioctl_get_queue_info(client_t *client, void __user *arg) { snd_seq_queue_info_t info; queue_t *q; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; q = queueptr(info.queue); @@ -1532,19 +1532,19 @@ info.name[sizeof(info.name)-1] = 0; queuefree(q); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } /* SET_QUEUE_INFO ioctl() */ -static int snd_seq_ioctl_set_queue_info(client_t *client, unsigned long arg) +static int snd_seq_ioctl_set_queue_info(client_t *client, void __user *arg) { snd_seq_queue_info_t info; queue_t *q; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (info.owner != client->number) @@ -1575,12 +1575,12 @@ } /* GET_NAMED_QUEUE ioctl() */ -static int snd_seq_ioctl_get_named_queue(client_t *client, unsigned long arg) +static int snd_seq_ioctl_get_named_queue(client_t *client, void __user *arg) { snd_seq_queue_info_t info; queue_t *q; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; q = snd_seq_queue_find_name(info.name); @@ -1591,20 +1591,20 @@ info.locked = q->locked; queuefree(q); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } /* GET_QUEUE_STATUS ioctl() */ -static int snd_seq_ioctl_get_queue_status(client_t * client, unsigned long arg) +static int snd_seq_ioctl_get_queue_status(client_t * client, void __user *arg) { snd_seq_queue_status_t status; queue_t *queue; seq_timer_t *tmr; - if (copy_from_user(&status, (void*)arg, sizeof(status))) + if (copy_from_user(&status, arg, sizeof(status))) return -EFAULT; queue = queueptr(status.queue); @@ -1624,20 +1624,20 @@ status.flags = queue->flags; queuefree(queue); - if (copy_to_user((void*)arg, &status, sizeof(status))) + if (copy_to_user(arg, &status, sizeof(status))) return -EFAULT; return 0; } /* GET_QUEUE_TEMPO ioctl() */ -static int snd_seq_ioctl_get_queue_tempo(client_t * client, unsigned long arg) +static int snd_seq_ioctl_get_queue_tempo(client_t * client, void __user *arg) { snd_seq_queue_tempo_t tempo; queue_t *queue; seq_timer_t *tmr; - if (copy_from_user(&tempo, (void*)arg, sizeof(tempo))) + if (copy_from_user(&tempo, arg, sizeof(tempo))) return -EFAULT; queue = queueptr(tempo.queue); @@ -1654,19 +1654,19 @@ tempo.skew_base = tmr->skew_base; queuefree(queue); - if (copy_to_user((void*)arg, &tempo, sizeof(tempo))) + if (copy_to_user(arg, &tempo, sizeof(tempo))) return -EFAULT; return 0; } /* SET_QUEUE_TEMPO ioctl() */ -static int snd_seq_ioctl_set_queue_tempo(client_t * client, unsigned long arg) +static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg) { int result; snd_seq_queue_tempo_t tempo; - if (copy_from_user(&tempo, (void*)arg, sizeof(tempo))) + if (copy_from_user(&tempo, arg, sizeof(tempo))) return -EFAULT; if (snd_seq_queue_check_access(tempo.queue, client->number)) { @@ -1682,13 +1682,13 @@ /* GET_QUEUE_TIMER ioctl() */ -static int snd_seq_ioctl_get_queue_timer(client_t * client, unsigned long arg) +static int snd_seq_ioctl_get_queue_timer(client_t * client, void __user *arg) { snd_seq_queue_timer_t timer; queue_t *queue; seq_timer_t *tmr; - if (copy_from_user(&timer, (void*)arg, sizeof(timer))) + if (copy_from_user(&timer, arg, sizeof(timer))) return -EFAULT; queue = queueptr(timer.queue); @@ -1711,19 +1711,19 @@ up(&queue->timer_mutex); queuefree(queue); - if (copy_to_user((void*)arg, &timer, sizeof(timer))) + if (copy_to_user(arg, &timer, sizeof(timer))) return -EFAULT; return 0; } /* SET_QUEUE_TIMER ioctl() */ -static int snd_seq_ioctl_set_queue_timer(client_t * client, unsigned long arg) +static int snd_seq_ioctl_set_queue_timer(client_t * client, void __user *arg) { int result = 0; snd_seq_queue_timer_t timer; - if (copy_from_user(&timer, (void*)arg, sizeof(timer))) + if (copy_from_user(&timer, arg, sizeof(timer))) return -EFAULT; if (timer.type != SNDRV_SEQ_TIMER_ALSA) @@ -1759,12 +1759,12 @@ /* GET_QUEUE_CLIENT ioctl() */ -static int snd_seq_ioctl_get_queue_client(client_t * client, unsigned long arg) +static int snd_seq_ioctl_get_queue_client(client_t * client, void __user *arg) { snd_seq_queue_client_t info; int used; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; used = snd_seq_queue_is_used(info.queue, client->number); @@ -1773,19 +1773,19 @@ info.used = used; info.client = client->number; - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } /* SET_QUEUE_CLIENT ioctl() */ -static int snd_seq_ioctl_set_queue_client(client_t * client, unsigned long arg) +static int snd_seq_ioctl_set_queue_client(client_t * client, void __user *arg) { int err; snd_seq_queue_client_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (info.used >= 0) { @@ -1799,12 +1799,12 @@ /* GET_CLIENT_POOL ioctl() */ -static int snd_seq_ioctl_get_client_pool(client_t * client, unsigned long arg) +static int snd_seq_ioctl_get_client_pool(client_t * client, void __user *arg) { snd_seq_client_pool_t info; client_t *cptr; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; cptr = snd_seq_client_use_ptr(info.client); @@ -1827,18 +1827,18 @@ } snd_seq_client_unlock(cptr); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } /* SET_CLIENT_POOL ioctl() */ -static int snd_seq_ioctl_set_client_pool(client_t * client, unsigned long arg) +static int snd_seq_ioctl_set_client_pool(client_t * client, void __user *arg) { snd_seq_client_pool_t info; int rc; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (client->number != info.client) @@ -1877,11 +1877,11 @@ /* REMOVE_EVENTS ioctl() */ -static int snd_seq_ioctl_remove_events(client_t * client, unsigned long arg) +static int snd_seq_ioctl_remove_events(client_t * client, void __user *arg) { snd_seq_remove_events_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; /* @@ -1906,7 +1906,7 @@ /* * get subscription info */ -static int snd_seq_ioctl_get_subscription(client_t *client, unsigned long arg) +static int snd_seq_ioctl_get_subscription(client_t *client, void __user *arg) { int result; client_t *sender = NULL; @@ -1914,7 +1914,7 @@ snd_seq_port_subscribe_t subs; subscribers_t *p; - if (copy_from_user(&subs, (void*)arg, sizeof(subs))) + if (copy_from_user(&subs, arg, sizeof(subs))) return -EFAULT; result = -EINVAL; @@ -1935,7 +1935,7 @@ if (sender) snd_seq_client_unlock(sender); if (result >= 0) { - if (copy_to_user((void*)arg, &subs, sizeof(subs))) + if (copy_to_user(arg, &subs, sizeof(subs))) return -EFAULT; } return result; @@ -1945,7 +1945,7 @@ /* * get subscription info - check only its presence */ -static int snd_seq_ioctl_query_subs(client_t *client, unsigned long arg) +static int snd_seq_ioctl_query_subs(client_t *client, void __user *arg) { int result = -ENXIO; client_t *cptr = NULL; @@ -1955,7 +1955,7 @@ struct list_head *p; int i; - if (copy_from_user(&subs, (void*)arg, sizeof(subs))) + if (copy_from_user(&subs, arg, sizeof(subs))) return -EFAULT; if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL) @@ -2004,7 +2004,7 @@ if (cptr) snd_seq_client_unlock(cptr); if (result >= 0) { - if (copy_to_user((void*)arg, &subs, sizeof(subs))) + if (copy_to_user(arg, &subs, sizeof(subs))) return -EFAULT; } return result; @@ -2014,12 +2014,12 @@ /* * query next client */ -static int snd_seq_ioctl_query_next_client(client_t *client, unsigned long arg) +static int snd_seq_ioctl_query_next_client(client_t *client, void __user *arg) { client_t *cptr = NULL; snd_seq_client_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; /* search for next client */ @@ -2037,7 +2037,7 @@ get_client_info(cptr, &info); snd_seq_client_unlock(cptr); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } @@ -2045,13 +2045,13 @@ /* * query next port */ -static int snd_seq_ioctl_query_next_port(client_t *client, unsigned long arg) +static int snd_seq_ioctl_query_next_port(client_t *client, void __user *arg) { client_t *cptr; client_port_t *port = NULL; snd_seq_port_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) + if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; cptr = snd_seq_client_use_ptr(info.addr.client); if (cptr == NULL) @@ -2071,7 +2071,7 @@ snd_seq_port_unlock(port); snd_seq_client_unlock(cptr); - if (copy_to_user((void*)arg, &info, sizeof(info))) + if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0; } @@ -2080,7 +2080,7 @@ static struct seq_ioctl_table { unsigned int cmd; - int (*func)(client_t *client, unsigned long arg); + int (*func)(client_t *client, void __user * arg); } ioctl_tables[] = { { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode }, @@ -2114,7 +2114,7 @@ { 0, NULL }, }; -static int snd_seq_do_ioctl(client_t *client, unsigned int cmd, unsigned long arg) +static int snd_seq_do_ioctl(client_t *client, unsigned int cmd, void __user *arg) { struct seq_ioctl_table *p; @@ -2131,7 +2131,7 @@ return -EFAULT; for (p = ioctl_tables; p->cmd; p++) { if (p->cmd == cmd) - return p->func(client, arg); + return p->func(client, (void __user *) arg); } snd_printd("seq unknown ioctl() 0x%x (type='%c', number=0x%2x)\n", cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); @@ -2146,7 +2146,7 @@ snd_assert(client != NULL, return -ENXIO); - return snd_seq_do_ioctl(client, cmd, arg); + return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } @@ -2315,7 +2315,7 @@ * exported, called by kernel clients to perform same functions as with * userland ioctl() */ -int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) +int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void __user *arg) { client_t *client; mm_segment_t fs; @@ -2325,7 +2325,7 @@ if (client == NULL) return -ENXIO; fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, (unsigned long)arg); + result = snd_seq_do_ioctl(client, cmd, arg); snd_leave_user(fs); return result; }