## Automatically generated incremental diff ## From: linux-2.5.69-bk6 ## To: linux-2.5.69-bk7 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.69-bk6/Documentation/BK-usage/bk-kernel-howto.txt linux-2.5.69-bk7/Documentation/BK-usage/bk-kernel-howto.txt --- linux-2.5.69-bk6/Documentation/BK-usage/bk-kernel-howto.txt 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/Documentation/BK-usage/bk-kernel-howto.txt 2003-05-12 04:43:29.000000000 -0700 @@ -273,3 +273,11 @@ A tag is just an alias for a specific changeset... and since changesets are ordered, a tag is thus a marker for a specific point in time (or specific state of the tree). + + +3) Is there an easy way to generate One Big Patch versus mainline, + for my long-lived kernel branch? +A. Yes. This requires BK 3.x, though. + + bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ + diff -urN linux-2.5.69-bk6/Makefile linux-2.5.69-bk7/Makefile --- linux-2.5.69-bk6/Makefile 2003-05-12 04:43:25.000000000 -0700 +++ linux-2.5.69-bk7/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 69 -EXTRAVERSION = -bk6 +EXTRAVERSION = -bk7 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.69-bk6/arch/alpha/kernel/sys_titan.c linux-2.5.69-bk7/arch/alpha/kernel/sys_titan.c --- linux-2.5.69-bk6/arch/alpha/kernel/sys_titan.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/arch/alpha/kernel/sys_titan.c 2003-05-12 04:43:29.000000000 -0700 @@ -204,13 +204,14 @@ .set_affinity = titan_set_irq_affinity, }; -static void +static irqreturn_t titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs) { /* * This is a NOP interrupt handler for the purposes of * event counting -- just return. */ + return IRQ_HANDLED; } static void __init diff -urN linux-2.5.69-bk6/arch/i386/kernel/Makefile linux-2.5.69-bk7/arch/i386/kernel/Makefile --- linux-2.5.69-bk6/arch/i386/kernel/Makefile 2003-05-04 16:53:03.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -17,7 +17,7 @@ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_APM) += apm.o +obj-$(CONFIG_APM) += apm.o suspend.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o diff -urN linux-2.5.69-bk6/arch/i386/kernel/apm.c linux-2.5.69-bk7/arch/i386/kernel/apm.c --- linux-2.5.69-bk6/arch/i386/kernel/apm.c 2003-05-04 16:53:00.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/apm.c 2003-05-12 04:43:29.000000000 -0700 @@ -226,6 +226,7 @@ #include #include #include +#include #include "io_ports.h" @@ -1212,7 +1213,9 @@ spin_unlock(&i8253_lock); write_sequnlock_irq(&xtime_lock); + save_processor_state(); err = set_system_power_state(APM_STATE_SUSPEND); + restore_processor_state(); write_seqlock_irq(&xtime_lock); spin_lock(&i8253_lock); diff -urN linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2003-05-12 04:43:29.000000000 -0700 @@ -147,7 +147,7 @@ #ifdef SUSPMOD_DEBUG #define dprintk(msg...) printk(KERN_DEBUG "cpufreq:" msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif /** diff -urN linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/longhaul.c linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/longhaul.c --- linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/longhaul.c 2003-05-04 16:53:00.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/longhaul.c 2003-05-12 04:43:29.000000000 -0700 @@ -37,7 +37,7 @@ #ifdef DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif static unsigned int numscales=16, numvscales; diff -urN linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2003-05-12 04:43:29.000000000 -0700 @@ -32,7 +32,7 @@ #ifdef DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif #define PFX "powernow: " @@ -89,7 +89,7 @@ rdmsr (msr, l__, h__); \ val = l__; \ val |= ((u64)h__<<32); \ -} while(0); +} while(0) #endif #ifndef wrmsrl @@ -236,20 +236,24 @@ if (have_a0 == 1) /* A0 errata 5 */ __asm__("\tcli\n"); - rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); - fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */ - fidvidctl.bits.FID = fid; - fidvidctl.bits.FIDC = 1; + /* First change the frequency. */ + if (fidvidctl.bits.FID != fid) { + rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */ + fidvidctl.bits.FID = fid; + fidvidctl.bits.FIDC = 1; + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + } - /* Set the voltage lazily. Ie, only do voltage transition - if its changed since last time (Some speeds have the same voltage) */ + /* Now change voltage. */ if (fidvidctl.bits.VID != vid) { + rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); fidvidctl.bits.VID = vid; fidvidctl.bits.VIDC = 1; + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); } - wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); if (have_a0 == 1) __asm__("\tsti\n"); @@ -386,6 +390,10 @@ static int __init powernow_init (void) { + if (dmi_broken & BROKEN_CPUFREQ) { + printk (KERN_INFO PFX "Disabled at boot time by DMI,\n"); + return -ENODEV; + } if (check_powernow()==0) return -ENODEV; return cpufreq_register_driver(&powernow_driver); diff -urN linux-2.5.69-bk6/arch/i386/kernel/dmi_scan.c linux-2.5.69-bk7/arch/i386/kernel/dmi_scan.c --- linux-2.5.69-bk6/arch/i386/kernel/dmi_scan.c 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/dmi_scan.c 2003-05-12 04:43:29.000000000 -0700 @@ -511,6 +511,14 @@ return 0; } +static __init int acer_cpufreq_pst(struct dmi_blacklist *d) +{ + printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident); + printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n"); + printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n"); + dmi_broken |= BROKEN_CPUFREQ; + return 0; +} /* @@ -825,6 +833,17 @@ NO_MATCH, NO_MATCH, NO_MATCH } }, + /* + * Some Athlon laptops have really fucked PST tables. + * A BIOS update is all that can save them. + * Mention this, and disable cpufreq. + */ + { acer_cpufreq_pst, "Acer Aspire", { + MATCH(DMI_SYS_VENDOR, "Insyde Software"), + MATCH(DMI_BIOS_VERSION, "3A71"), + NO_MATCH, NO_MATCH, NO_MATCH + } }, + { NULL, } }; diff -urN linux-2.5.69-bk6/arch/i386/kernel/suspend.c linux-2.5.69-bk7/arch/i386/kernel/suspend.c --- linux-2.5.69-bk6/arch/i386/kernel/suspend.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/suspend.c 2003-05-12 04:43:29.000000000 -0700 @@ -27,9 +27,7 @@ #include static struct saved_context saved_context; -unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx; -unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi; -unsigned long saved_context_eflags; +static void fix_processor_context(void); extern void enable_sep_cpu(void *); @@ -107,7 +105,7 @@ do_fpu_end(); } -void fix_processor_context(void) +static void fix_processor_context(void) { int cpu = smp_processor_id(); struct tss_struct * t = init_tss + cpu; diff -urN linux-2.5.69-bk6/arch/i386/kernel/suspend_asm.S linux-2.5.69-bk7/arch/i386/kernel/suspend_asm.S --- linux-2.5.69-bk6/arch/i386/kernel/suspend_asm.S 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/arch/i386/kernel/suspend_asm.S 2003-05-12 04:43:29.000000000 -0700 @@ -6,6 +6,28 @@ #include #include + .data +saved_context_eax: + .long 0 +saved_context_ebx: + .long 0 +saved_context_ecx: + .long 0 +saved_context_edx: + .long 0 +saved_context_esp: + .long 0 +saved_context_ebp: + .long 0 +saved_context_esi: + .long 0 +saved_context_edi: + .long 0 +saved_context_eflags: + .long 0 + + .text + ENTRY(do_magic) pushl %ebx cmpl $0,8(%esp) diff -urN linux-2.5.69-bk6/arch/ia64/Kconfig linux-2.5.69-bk7/arch/ia64/Kconfig --- linux-2.5.69-bk6/arch/ia64/Kconfig 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/Kconfig 2003-05-12 04:43:29.000000000 -0700 @@ -381,6 +381,10 @@ depends on MCKINLEY bool "4GB" +config HUGETLB_PAGE_SIZE_1GB + depends on MCKINLEY + bool "1GB" + config HUGETLB_PAGE_SIZE_256MB bool "256MB" diff -urN linux-2.5.69-bk6/arch/ia64/Makefile linux-2.5.69-bk7/arch/ia64/Makefile --- linux-2.5.69-bk6/arch/ia64/Makefile 2003-05-04 16:52:59.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -23,6 +23,7 @@ CFLAGS_KERNEL := -mconstant-gp GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') +GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.') GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) @@ -35,7 +36,14 @@ endif ifneq ($(GCC_VERSION),2) - cflags-y += -frename-registers --param max-inline-insns=5000 + cflags-$(CONFIG_ITANIUM) += -frename-registers +endif + +ifeq ($(GCC_VERSION),3) + ifeq ($(GCC_MINOR_VERSION),4) + cflags-$(CONFIG_ITANIUM) += -mtune=merced + cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley + endif endif cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC) += -mb-step @@ -48,14 +56,14 @@ core-y += arch/ia64/kernel/ arch/ia64/mm/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ -core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ arch/ia64/hp/common/ arch/ia64/hp/zx1/ \ - arch/ia64/hp/sim/ +core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ boot := arch/ia64/boot tools := arch/ia64/tools diff -urN linux-2.5.69-bk6/arch/ia64/dig/machvec.c linux-2.5.69-bk7/arch/ia64/dig/machvec.c --- linux-2.5.69-bk6/arch/ia64/dig/machvec.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/dig/machvec.c 2003-05-12 04:43:29.000000000 -0700 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME dig +#define MACHVEC_PLATFORM_NAME dig +#define MACHVEC_PLATFORM_HEADER #include diff -urN linux-2.5.69-bk6/arch/ia64/hp/common/sba_iommu.c linux-2.5.69-bk7/arch/ia64/hp/common/sba_iommu.c --- linux-2.5.69-bk6/arch/ia64/hp/common/sba_iommu.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/common/sba_iommu.c 2003-05-12 04:43:29.000000000 -0700 @@ -1,9 +1,9 @@ /* ** IA64 System Bus Adapter (SBA) I/O MMU manager ** -** (c) Copyright 2002 Alex Williamson -** (c) Copyright 2002 Grant Grundler -** (c) Copyright 2002 Hewlett-Packard Company +** (c) Copyright 2002-2003 Alex Williamson +** (c) Copyright 2002-2003 Grant Grundler +** (c) Copyright 2002-2003 Hewlett-Packard Company ** ** Portions (c) 2000 Grant Grundler (from parisc I/O MMU code) ** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code) @@ -30,17 +30,39 @@ #include #include #include +#include +#include #include #include /* ia64_get_itc() */ #include #include /* PAGE_OFFSET */ +#include +#include /* wmb() */ +#include -#define DRIVER_NAME "SBA" +#define PFX "IOC: " +/* +** This option allows cards capable of 64bit DMA to bypass the IOMMU. If +** not defined, all DMA will be 32bit and go through the TLB. +*/ #define ALLOW_IOV_BYPASS + +/* +** If a device prefetches beyond the end of a valid pdir entry, it will cause +** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should +** disconnect on 4k boundaries and prevent such issues. If the device is +** particularly agressive, this option will keep the entire pdir valid such +** that prefetching will hit a valid address. This could severely impact +** error containment, and is therefore off by default. The page that is +** used for spill-over is poisoned, so that should help debugging somewhat. +*/ +#undef FULL_VALID_PDIR + #define ENABLE_MARK_CLEAN + /* ** The number of debug flags is a clue - this code is fragile. */ @@ -52,6 +74,10 @@ #undef DEBUG_LARGE_SG_ENTRIES #undef DEBUG_BYPASS +#if defined(FULL_VALID_PDIR) && defined(ASSERT_PDIR_SANITY) +#error FULL_VALID_PDIR and ASSERT_PDIR_SANITY are mutually exclusive +#endif + #define SBA_INLINE __inline__ /* #define SBA_INLINE */ @@ -96,12 +122,8 @@ #define ASSERT(expr) #endif -#define KB(x) ((x) * 1024) -#define MB(x) (KB (KB (x))) -#define GB(x) (MB (KB (x))) - /* -** The number of pdir entries to "free" before issueing +** The number of pdir entries to "free" before issuing ** a read to PCOM register to flush out PCOM writes. ** Interacts with allocation granularity (ie 4 or 8 entries ** allocated and free'd/purged at a time might make this @@ -109,30 +131,24 @@ */ #define DELAYED_RESOURCE_CNT 16 -#define DEFAULT_DMA_HINT_REG(d) 0 - -#define ZX1_FUNC_ID_VALUE ((PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP) -#define ZX1_MC_ID ((PCI_DEVICE_ID_HP_ZX1_MC << 16) | PCI_VENDOR_ID_HP) +#define DEFAULT_DMA_HINT_REG 0 -#define SBA_FUNC_ID 0x0000 /* function id */ -#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */ +#define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP) +#define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP) +#define SX1000_IOC_ID ((PCI_DEVICE_ID_HP_SX1000_IOC << 16) | PCI_VENDOR_ID_HP) -#define SBA_FUNC_SIZE 0x10000 /* SBA configuration function reg set */ - -unsigned int __initdata zx1_func_offsets[] = {0x1000, 0x4000, 0x8000, - 0x9000, 0xa000, -1}; - -#define SBA_IOC_OFFSET 0x1000 - -#define MAX_IOC 1 /* we only have 1 for now*/ +#define ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */ +#define IOC_FUNC_ID 0x000 +#define IOC_FCLASS 0x008 /* function class, bist, header, rev... */ #define IOC_IBASE 0x300 /* IO TLB */ #define IOC_IMASK 0x308 #define IOC_PCOM 0x310 #define IOC_TCNFG 0x318 #define IOC_PDIR_BASE 0x320 -#define IOC_IOVA_SPACE_BASE 0x40000000 /* IOVA ranges start at 1GB */ +/* AGP GART driver looks for this */ +#define ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL /* ** IOC supports 4/8/16/64KB page sizes (see TCNFG register) @@ -152,7 +168,7 @@ #define IOVP_MASK PAGE_MASK struct ioc { - unsigned long ioc_hpa; /* I/O MMU base address */ + void *ioc_hpa; /* I/O MMU base address */ char *res_map; /* resource map, bit == pdir entry */ u64 *pdir_base; /* physical base address */ unsigned long ibase; /* pdir IOV Space base */ @@ -193,37 +209,37 @@ #endif #endif - /* STUFF We don't need in performance path */ + /* Stuff we don't need in performance path */ + struct ioc *next; /* list of IOC's in system */ + acpi_handle handle; /* for multiple IOC's */ + const char *name; + unsigned int func_id; + unsigned int rev; /* HW revision of chip */ + u32 iov_size; unsigned int pdir_size; /* in bytes, determined by IOV Space size */ + struct pci_dev *sac_only_dev; }; -struct sba_device { - struct sba_device *next; /* list of SBA's in system */ - const char *name; - unsigned long sba_hpa; /* base address */ - spinlock_t sba_lock; - unsigned int flags; /* state/functionality enabled */ - unsigned int hw_rev; /* HW revision of chip */ - - unsigned int num_ioc; /* number of on-board IOC's */ - struct ioc ioc[MAX_IOC]; -}; +static struct ioc *ioc_list; +static int reserve_sba_gart = 1; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) +#else +#define sba_sg_address(sg) ((sg)->address ? (sg)->address : \ + page_address((sg)->page) + (sg)->offset) +#endif -static struct sba_device *sba_list; -static int sba_count; -static int reserve_sba_gart = 1; -static struct pci_dev sac_only_dev; +#ifdef FULL_VALID_PDIR +static u64 prefetch_spill_page; +#endif -#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) -#define sba_sg_len(sg) (sg->length) -#define sba_sg_iova(sg) (sg->dma_address) -#define sba_sg_iova_len(sg) (sg->dma_length) - -/* REVISIT - fix me for multiple SBAs/IOCs */ -#define GET_IOC(dev) (sba_list->ioc) -#define SBA_SET_AGP(sba_dev) (sba_dev->flags |= 0x1) -#define SBA_GET_AGP(sba_dev) (sba_dev->flags & 0x1) +#ifdef CONFIG_PCI +# define GET_IOC(dev) (((dev)->bus == &pci_bus_type) \ + ? ((struct ioc *) PCI_CONTROLLER(to_pci_dev(dev))->iommu) : NULL) +#else +# define GET_IOC(dev) NULL +#endif /* ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up @@ -232,10 +248,7 @@ ** rather than the HW. I/O MMU allocation alogorithms can be ** faster with smaller size is (to some degree). */ -#define DMA_CHUNK_SIZE (BITS_PER_LONG*IOVP_SIZE) - -/* Looks nice and keeps the compiler happy */ -#define SBA_DEV(d) ((struct sba_device *) (d)) +#define DMA_CHUNK_SIZE (BITS_PER_LONG*PAGE_SIZE) #define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) @@ -255,7 +268,7 @@ * sba_dump_tlb - debugging only - print IOMMU operating parameters * @hpa: base address of the IOMMU * - * Print the size/location of the IO MMU Pdir. + * Print the size/location of the IO MMU PDIR. */ static void sba_dump_tlb(char *hpa) @@ -273,19 +286,19 @@ #ifdef ASSERT_PDIR_SANITY /** - * sba_dump_pdir_entry - debugging only - print one IOMMU Pdir entry + * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry * @ioc: IO MMU structure which owns the pdir we are interested in. * @msg: text to print ont the output line. * @pide: pdir index. * - * Print one entry of the IO MMU Pdir in human readable form. + * Print one entry of the IO MMU PDIR in human readable form. */ static void sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide) { /* start printing from lowest pde in rval */ - u64 *ptr = &(ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)]); - unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]); + u64 *ptr = &ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)]; + unsigned long *rptr = (unsigned long *) &ioc->res_map[(pide >>3) & -sizeof(unsigned long)]; uint rcnt; printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n", @@ -296,7 +309,7 @@ printk(KERN_DEBUG "%s %2d %p %016Lx\n", (rcnt == (pide & (BITS_PER_LONG - 1))) ? " -->" : " ", - rcnt, ptr, *ptr ); + rcnt, ptr, (unsigned long long) *ptr ); rcnt++; ptr++; } @@ -359,17 +372,18 @@ * print the SG list so we can verify it's correct by hand. */ static void -sba_dump_sg(struct ioc *ioc, struct scatterlist *startsg, int nents) +sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { while (nents-- > 0) { printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents, - (unsigned long) sba_sg_iova(startsg), sba_sg_iova_len(startsg), + startsg->dma_address, startsg->dma_length, sba_sg_address(startsg)); startsg++; } } + static void -sba_check_sg(struct ioc *ioc, struct scatterlist *startsg, int nents) +sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { struct scatterlist *the_sg = startsg; int the_nents = nents; @@ -398,9 +412,11 @@ #define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ /* Convert from IOVP to IOVA and vice versa. */ -#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir))) +#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | \ + ((hint_reg)<<(ioc->hint_shift_pdir))) #define SBA_IOVP(ioc,iova) (((iova) & ioc->hint_mask_pdir) & ~(ioc->ibase)) +/* FIXME : review these macros to verify correctness and usage */ #define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) #define RESMAP_MASK(n) ~(~0UL << (n)) @@ -408,7 +424,7 @@ /** - * sba_search_bitmap - find free space in IO Pdir resource bitmap + * sba_search_bitmap - find free space in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @bits_wanted: number of entries we need. * @@ -445,7 +461,7 @@ ** We need the alignment to invalidate I/O TLB using ** SBA HW features in the unmap path. */ - unsigned long o = 1UL << get_order(bits_wanted << IOVP_SHIFT); + unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT); uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); unsigned long mask; @@ -491,7 +507,7 @@ /** - * sba_alloc_range - find free bits and mark them in IO Pdir resource bitmap + * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @size: number of bytes to create a mapping for * @@ -520,7 +536,8 @@ if (pide >= (ioc->res_size << 3)) { pide = sba_search_bitmap(ioc, pages_needed); if (pide >= (ioc->res_size << 3)) - panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa); + panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", + ioc->ioc_hpa); } #ifdef ASSERT_PDIR_SANITY @@ -553,7 +570,7 @@ /** - * sba_free_range - unmark bits in IO Pdir resource bitmap + * sba_free_range - unmark bits in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @iova: IO virtual address which was previously allocated. * @size: number of bytes to create a mapping for @@ -600,14 +617,14 @@ /** - * sba_io_pdir_entry - fill in one IO Pdir entry - * @pdir_ptr: pointer to IO Pdir entry - * @phys_page: phys CPU address of page to map + * sba_io_pdir_entry - fill in one IO PDIR entry + * @pdir_ptr: pointer to IO PDIR entry + * @vba: Virtual CPU address of buffer to map * * SBA Mapping Routine * - * Given a physical address (phys_page, arg1) sba_io_pdir_entry() - * loads the I/O Pdir entry pointed to by pdir_ptr (arg0). + * Given a virtual address (vba, arg1) sba_io_pdir_entry() + * loads the I/O PDIR entry pointed to by pdir_ptr (arg0). * Each IO Pdir entry consists of 8 bytes as shown below * (LSB == bit 0): * @@ -619,12 +636,21 @@ * V == Valid Bit * U == Unused * PPN == Physical Page Number + * + * The physical address fields are filled with the results of virt_to_phys() + * on the vba. */ -#define SBA_VALID_MASK 0x80000000000000FFULL -#define sba_io_pdir_entry(pdir_ptr, phys_page) *pdir_ptr = (phys_page | SBA_VALID_MASK) -#define sba_io_page(pdir_ptr) (*pdir_ptr & ~SBA_VALID_MASK) - +#if 1 +#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL) \ + | 0x8000000000000000ULL) +#else +void SBA_INLINE +sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba) +{ + *pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x80000000000000FFULL); +} +#endif #ifdef ENABLE_MARK_CLEAN /** @@ -640,7 +666,7 @@ pg_addr = PAGE_ALIGN((unsigned long) addr); end = (unsigned long) addr + size; while (pg_addr + PAGE_SIZE <= end) { - struct page *page = virt_to_page(pg_addr); + struct page *page = virt_to_page((void *)pg_addr); set_bit(PG_arch_1, &page->flags); pg_addr += PAGE_SIZE; } @@ -648,12 +674,12 @@ #endif /** - * sba_mark_invalid - invalidate one or more IO Pdir entries + * sba_mark_invalid - invalidate one or more IO PDIR entries * @ioc: IO MMU structure which owns the pdir we are interested in. * @iova: IO Virtual Address mapped earlier * @byte_cnt: number of bytes this mapping covers. * - * Marking the IO Pdir entry(ies) as Invalid and invalidate + * Marking the IO PDIR entry(ies) as Invalid and invalidate * corresponding IO TLB entry. The PCOM (Purge Command Register) * is to purge stale entries in the IO TLB when unmapping entries. * @@ -687,15 +713,24 @@ iovp |= IOVP_SHIFT; /* set "size" field for PCOM */ +#ifndef FULL_VALID_PDIR /* - ** clear I/O Pdir entry "valid" bit + ** clear I/O PDIR entry "valid" bit ** Do NOT clear the rest - save it for debugging. ** We should only clear bits that have previously ** been enabled. */ - ioc->pdir_base[off] &= ~SBA_VALID_MASK; + ioc->pdir_base[off] &= ~(0x80000000000000FFULL); +#else + /* + ** If we want to maintain the PDIR as valid, put in + ** the spill page so devices prefetching won't + ** cause a hard fail. + */ + ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); +#endif } else { - u32 t = get_order(byte_cnt) + IOVP_SHIFT; + u32 t = get_order(byte_cnt) + PAGE_SHIFT; iovp |= t; ASSERT(t <= 31); /* 2GB! Max value of "size" field */ @@ -703,14 +738,18 @@ do { /* verify this pdir entry is enabled */ ASSERT(ioc->pdir_base[off] >> 63); +#ifndef FULL_VALID_PDIR /* clear I/O Pdir entry "valid" bit first */ - ioc->pdir_base[off] &= ~SBA_VALID_MASK; + ioc->pdir_base[off] &= ~(0x80000000000000FFULL); +#else + ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); +#endif off++; byte_cnt -= IOVP_SIZE; } while (byte_cnt > 0); } - WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM); + WRITE_REG(iovp | ioc->ibase, ioc->ioc_hpa+IOC_PCOM); } /** @@ -718,26 +757,23 @@ * @dev: instance of PCI owned by the driver that's asking. * @addr: driver buffer to map. * @size: number of bytes to map in driver buffer. - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ dma_addr_t -sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) +sba_map_single(struct device *dev, void *addr, size_t size, int dir) { struct ioc *ioc; - unsigned long flags; + unsigned long flags; dma_addr_t iovp; dma_addr_t offset; u64 *pdir_start; int pide; #ifdef ALLOW_IOV_BYPASS - unsigned long phys_addr = virt_to_phys(addr); + unsigned long pci_addr = virt_to_phys(addr); #endif - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); - ioc = GET_IOC(dev); ASSERT(ioc); @@ -745,7 +781,7 @@ /* ** Check if the PCI device can DMA to ptr... if so, just return ptr */ - if ((phys_addr & ~dev->dma_mask) == 0) { + if (dev && dev->dma_mask && (pci_addr & ~*dev->dma_mask) == 0) { /* ** Device is bit capable of DMA'ing to the buffer... ** just return the PCI address of ptr @@ -756,8 +792,8 @@ spin_unlock_irqrestore(&ioc->res_lock, flags); #endif DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n", - dev->dma_mask, phys_addr); - return phys_addr; + *dev->dma_mask, pci_addr); + return pci_addr; } #endif @@ -790,8 +826,7 @@ while (size > 0) { ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */ - - sba_io_pdir_entry(pdir_start, virt_to_phys(addr)); + sba_io_pdir_entry(pdir_start, (unsigned long) addr); DBG_RUN(" pdir 0x%p %lx\n", pdir_start, *pdir_start); @@ -799,12 +834,15 @@ size -= IOVP_SIZE; pdir_start++; } + /* force pdir update */ + wmb(); + /* form complete address */ #ifdef ASSERT_PDIR_SANITY sba_check_pdir(ioc,"Check after sba_map_single()"); #endif spin_unlock_irqrestore(&ioc->res_lock, flags); - return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG(direction)); + return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG); } /** @@ -812,23 +850,19 @@ * @dev: instance of PCI owned by the driver that's asking. * @iova: IOVA of driver buffer previously mapped. * @size: number of bytes mapped in driver buffer. - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ -void sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, - int direction) +void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir) { struct ioc *ioc; #if DELAYED_RESOURCE_CNT > 0 struct sba_dma_pair *d; #endif - unsigned long flags; + unsigned long flags; dma_addr_t offset; - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); - ioc = GET_IOC(dev); ASSERT(ioc); @@ -845,7 +879,7 @@ DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova); #ifdef ENABLE_MARK_CLEAN - if (direction == PCI_DMA_FROMDEVICE) { + if (dir == DMA_FROM_DEVICE) { mark_clean(phys_to_virt(iova), size); } #endif @@ -861,29 +895,6 @@ size += offset; size = ROUNDUP(size, IOVP_SIZE); -#ifdef ENABLE_MARK_CLEAN - /* - ** Don't need to hold the spinlock while telling VM pages are "clean". - ** The pages are "busy" in the resource map until we mark them free. - ** But tell VM pages are clean *before* releasing the resource - ** in order to avoid race conditions. - */ - if (direction == PCI_DMA_FROMDEVICE) { - u32 iovp = (u32) SBA_IOVP(ioc,iova); - unsigned int pide = PDIR_INDEX(iovp); - u64 *pdirp = &(ioc->pdir_base[pide]); - size_t byte_cnt = size; - void *addr; - - do { - addr = phys_to_virt(sba_io_page(pdirp)); - mark_clean(addr, min(byte_cnt, IOVP_SIZE)); - pdirp++; - byte_cnt -= IOVP_SIZE; - } while (byte_cnt > 0); - } -#endif - spin_lock_irqsave(&ioc->res_lock, flags); #ifdef CONFIG_PROC_FS ioc->usingle_calls++; @@ -909,7 +920,40 @@ sba_free_range(ioc, iova, size); READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ #endif /* DELAYED_RESOURCE_CNT == 0 */ +#ifdef ENABLE_MARK_CLEAN + if (dir == DMA_FROM_DEVICE) { + u32 iovp = (u32) SBA_IOVP(ioc,iova); + int off = PDIR_INDEX(iovp); + void *addr; + + if (size <= IOVP_SIZE) { + addr = phys_to_virt(ioc->pdir_base[off] & + ~0xE000000000000FFFULL); + mark_clean(addr, size); + } else { + size_t byte_cnt = size; + + do { + addr = phys_to_virt(ioc->pdir_base[off] & + ~0xE000000000000FFFULL); + mark_clean(addr, min(byte_cnt, IOVP_SIZE)); + off++; + byte_cnt -= IOVP_SIZE; + + } while (byte_cnt > 0); + } + } +#endif spin_unlock_irqrestore(&ioc->res_lock, flags); + + /* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support. + ** For Astro based systems this isn't a big deal WRT performance. + ** As long as 2.4 kernels copyin/copyout data from/to userspace, + ** we don't need the syncdma. The issue here is I/O MMU cachelines + ** are *not* coherent in all cases. May be hwrev dependent. + ** Need to investigate more. + asm volatile("syncdma"); + */ } @@ -922,29 +966,25 @@ * See Documentation/DMA-mapping.txt */ void * -sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +sba_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flags) { - void *ret; - - if (!hwdev) { - /* only support PCI */ - *dma_handle = 0; - return 0; - } + struct ioc *ioc; + void *addr; - ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size)); + addr = (void *) __get_free_pages(flags, get_order(size)); + if (!addr) + return NULL; - if (ret) { - memset(ret, 0, size); - /* - * REVISIT: if sba_map_single starts needing more - * than dma_mask from the device, this needs to be - * updated. - */ - *dma_handle = sba_map_single(&sac_only_dev, ret, size, 0); - } + /* + * REVISIT: if sba_map_single starts needing more than dma_mask from the + * device, this needs to be updated. + */ + ioc = GET_IOC(hwdev); + ASSERT(ioc); + *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0); - return ret; + memset(addr, 0, size); + return addr; } @@ -957,117 +997,245 @@ * * See Documentation/DMA-mapping.txt */ -void sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, - dma_addr_t dma_handle) +void sba_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { sba_unmap_single(hwdev, dma_handle, size, 0); free_pages((unsigned long) vaddr, get_order(size)); } +/* +** Since 0 is a valid pdir_base index value, can't use that +** to determine if a value is valid or not. Use a flag to indicate +** the SG list entry contains a valid pdir index. +*/ +#define PIDE_FLAG 0x1UL + #ifdef DEBUG_LARGE_SG_ENTRIES int dump_run_sg = 0; #endif -#define SG_ENT_VIRT_PAGE(sg) page_address((sg)->page) -#define SG_ENT_PHYS_PAGE(SG) virt_to_phys(SG_ENT_VIRT_PAGE(SG)) - /** - * sba_coalesce_chunks - preprocess the SG list + * sba_fill_pdir - write allocated SG entries into IO PDIR * @ioc: IO MMU structure which owns the pdir we are interested in. - * @startsg: input=SG list output=DMA addr/len pairs filled in + * @startsg: list of IOVA/size pairs * @nents: number of entries in startsg list - * @direction: R/W or both. * - * Walk the SG list and determine where the breaks are in the DMA stream. - * Allocate IO Pdir resources and fill them in separate loop. - * Returns the number of DMA streams used for output IOVA list. - * Note each DMA stream can consume multiple IO Pdir entries. - * - * Code is written assuming some coalescing is possible. + * Take preprocessed SG list and write corresponding entries + * in the IO PDIR. */ + static SBA_INLINE int -sba_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, - int nents, int direction) +sba_fill_pdir( + struct ioc *ioc, + struct scatterlist *startsg, + int nents) { - struct scatterlist *dma_sg = startsg; /* return array */ + struct scatterlist *dma_sg = startsg; /* pointer to current DMA */ int n_mappings = 0; + u64 *pdirp = 0; + unsigned long dma_offset = 0; - ASSERT(nents > 1); + dma_sg--; + while (nents-- > 0) { + int cnt = startsg->dma_length; + startsg->dma_length = 0; - do { - unsigned int dma_cnt = 1; /* number of pages in DMA stream */ - unsigned int pide; /* index into IO Pdir array */ - u64 *pdirp; /* pointer into IO Pdir array */ - unsigned long dma_offset, dma_len; /* cumulative DMA stream */ +#ifdef DEBUG_LARGE_SG_ENTRIES + if (dump_run_sg) + printk(" %2d : %08lx/%05x %p\n", + nents, startsg->dma_address, cnt, + sba_sg_address(startsg)); +#else + DBG_RUN_SG(" %d : %08lx/%05x %p\n", + nents, startsg->dma_address, cnt, + sba_sg_address(startsg)); +#endif + /* + ** Look for the start of a new DMA stream + */ + if (startsg->dma_address & PIDE_FLAG) { + u32 pide = startsg->dma_address & ~PIDE_FLAG; + dma_offset = (unsigned long) pide & ~IOVP_MASK; + startsg->dma_address = 0; + dma_sg++; + dma_sg->dma_address = pide | ioc->ibase; + pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]); + n_mappings++; + } /* - ** Prepare for first/next DMA stream + ** Look for a VCONTIG chunk */ - dma_len = sba_sg_len(startsg); - dma_offset = (unsigned long) sba_sg_address(startsg); + if (cnt) { + unsigned long vaddr = (unsigned long) sba_sg_address(startsg); + ASSERT(pdirp); + + /* Since multiple Vcontig blocks could make up + ** one DMA stream, *add* cnt to dma_len. + */ + dma_sg->dma_length += cnt; + cnt += dma_offset; + dma_offset=0; /* only want offset on first chunk */ + cnt = ROUNDUP(cnt, IOVP_SIZE); +#ifdef CONFIG_PROC_FS + ioc->msg_pages += cnt >> IOVP_SHIFT; +#endif + do { + sba_io_pdir_entry(pdirp, vaddr); + vaddr += IOVP_SIZE; + cnt -= IOVP_SIZE; + pdirp++; + } while (cnt > 0); + } startsg++; - nents--; + } + /* force pdir update */ + wmb(); + +#ifdef DEBUG_LARGE_SG_ENTRIES + dump_run_sg = 0; +#endif + return(n_mappings); +} + + +/* +** Two address ranges are DMA contiguous *iff* "end of prev" and +** "start of next" are both on a page boundry. +** +** (shift left is a quick trick to mask off upper bits) +*/ +#define DMA_CONTIG(__X, __Y) \ + (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL) + + +/** + * sba_coalesce_chunks - preprocess the SG list + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @startsg: list of IOVA/size pairs + * @nents: number of entries in startsg list + * + * First pass is to walk the SG list and determine where the breaks are + * in the DMA stream. Allocates PDIR entries but does not fill them. + * Returns the number of DMA chunks. + * + * Doing the fill seperate from the coalescing/allocation keeps the + * code simpler. Future enhancement could make one pass through + * the sglist do both. + */ +static SBA_INLINE int +sba_coalesce_chunks( struct ioc *ioc, + struct scatterlist *startsg, + int nents) +{ + struct scatterlist *vcontig_sg; /* VCONTIG chunk head */ + unsigned long vcontig_len; /* len of VCONTIG chunk */ + unsigned long vcontig_end; + struct scatterlist *dma_sg; /* next DMA stream head */ + unsigned long dma_offset, dma_len; /* start/len of DMA stream */ + int n_mappings = 0; + + while (nents > 0) { + unsigned long vaddr = (unsigned long) sba_sg_address(startsg); /* - ** We want to know how many entries can be coalesced - ** before trying to allocate IO Pdir space. - ** IOVAs can then be allocated "naturally" aligned - ** to take advantage of the block IO TLB flush. + ** Prepare for first/next DMA stream */ - while (nents) { - unsigned long end_offset = dma_offset + dma_len; + dma_sg = vcontig_sg = startsg; + dma_len = vcontig_len = vcontig_end = startsg->length; + vcontig_end += vaddr; + dma_offset = vaddr & ~IOVP_MASK; - /* prev entry must end on a page boundary */ - if (end_offset & IOVP_MASK) - break; + /* PARANOID: clear entries */ + startsg->dma_address = startsg->dma_length = 0; - /* next entry start on a page boundary? */ - if (startsg->offset) - break; + /* + ** This loop terminates one iteration "early" since + ** it's always looking one "ahead". + */ + while (--nents > 0) { + unsigned long vaddr; /* tmp */ + + startsg++; + + /* PARANOID */ + startsg->dma_address = startsg->dma_length = 0; + + /* catch brokenness in SCSI layer */ + ASSERT(startsg->length <= DMA_CHUNK_SIZE); /* - ** make sure current dma stream won't exceed - ** DMA_CHUNK_SIZE if coalescing entries. + ** First make sure current dma stream won't + ** exceed DMA_CHUNK_SIZE if we coalesce the + ** next entry. */ - if (((end_offset + startsg->length + ~IOVP_MASK) - & IOVP_MASK) - > DMA_CHUNK_SIZE) + if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) + > DMA_CHUNK_SIZE) break; - dma_len += sba_sg_len(startsg); - startsg++; - nents--; - dma_cnt++; - } + /* + ** Then look for virtually contiguous blocks. + ** + ** append the next transaction? + */ + vaddr = (unsigned long) sba_sg_address(startsg); + if (vcontig_end == vaddr) + { + vcontig_len += startsg->length; + vcontig_end += startsg->length; + dma_len += startsg->length; + continue; + } - ASSERT(dma_len <= DMA_CHUNK_SIZE); +#ifdef DEBUG_LARGE_SG_ENTRIES + dump_run_sg = (vcontig_len > IOVP_SIZE); +#endif - /* allocate IO Pdir resource. - ** returns index into (u64) IO Pdir array. - ** IOVA is formed from this. - */ - pide = sba_alloc_range(ioc, dma_cnt << IOVP_SHIFT); - pdirp = &(ioc->pdir_base[pide]); + /* + ** Not virtually contigous. + ** Terminate prev chunk. + ** Start a new chunk. + ** + ** Once we start a new VCONTIG chunk, dma_offset + ** can't change. And we need the offset from the first + ** chunk - not the last one. Ergo Successive chunks + ** must start on page boundaries and dove tail + ** with it's predecessor. + */ + vcontig_sg->dma_length = vcontig_len; - /* fill_pdir: write stream into IO Pdir */ - while (dma_cnt--) { - sba_io_pdir_entry(pdirp, SG_ENT_PHYS_PAGE(startsg)); - startsg++; - pdirp++; - } + vcontig_sg = startsg; + vcontig_len = startsg->length; - /* "output" IOVA */ - sba_sg_iova(dma_sg) = SBA_IOVA(ioc, - ((dma_addr_t) pide << IOVP_SHIFT), - dma_offset, - DEFAULT_DMA_HINT_REG(direction)); - sba_sg_iova_len(dma_sg) = dma_len; + /* + ** 3) do the entries end/start on page boundaries? + ** Don't update vcontig_end until we've checked. + */ + if (DMA_CONTIG(vcontig_end, vaddr)) + { + vcontig_end = vcontig_len + vaddr; + dma_len += vcontig_len; + continue; + } else { + break; + } + } - dma_sg++; + /* + ** End of DMA Stream + ** Terminate last VCONTIG block. + ** Allocate space for DMA stream. + */ + vcontig_sg->dma_length = vcontig_len; + dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK; + ASSERT(dma_len <= DMA_CHUNK_SIZE); + dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG + | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT) + | dma_offset); n_mappings++; - } while (nents); + } return n_mappings; } @@ -1075,60 +1243,51 @@ /** * sba_map_sg - map Scatter/Gather list - * @dev: instance of PCI device owned by the driver that's asking. + * @dev: instance of PCI owned by the driver that's asking. * @sglist: array of buffer/length pairs * @nents: number of entries in list - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ -int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, - int direction) +int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int dir) { struct ioc *ioc; - int filled = 0; + int coalesced, filled = 0; unsigned long flags; #ifdef ALLOW_IOV_BYPASS struct scatterlist *sg; #endif - DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents, - sba_sg_address(sglist), sba_sg_len(sglist)); - - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); - + DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); ioc = GET_IOC(dev); ASSERT(ioc); #ifdef ALLOW_IOV_BYPASS - if (dev->dma_mask >= ioc->dma_mask) { - for (sg = sglist ; filled < nents ; filled++, sg++) { - sba_sg_iova(sg) = virt_to_phys(sba_sg_address(sg)); - sba_sg_iova_len(sg) = sba_sg_len(sg); + if (dev && dev->dma_mask && (ioc->dma_mask & ~*dev->dma_mask) == 0) { + for (sg = sglist ; filled < nents ; filled++, sg++){ + sg->dma_length = sg->length; + sg->dma_address = virt_to_phys(sba_sg_address(sg)); } #ifdef CONFIG_PROC_FS spin_lock_irqsave(&ioc->res_lock, flags); ioc->msg_bypass++; spin_unlock_irqrestore(&ioc->res_lock, flags); #endif - DBG_RUN_SG("%s() DONE %d mappings bypassed\n", __FUNCTION__, filled); return filled; } #endif /* Fast path single entry scatterlists. */ if (nents == 1) { - sba_sg_iova(sglist) = sba_map_single(dev, - (void *) sba_sg_iova(sglist), - sba_sg_len(sglist), direction); - sba_sg_iova_len(sglist) = sba_sg_len(sglist); + sglist->dma_length = sglist->length; + sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, + dir); #ifdef CONFIG_PROC_FS /* ** Should probably do some stats counting, but trying to ** be precise quickly starts wasting CPU time. */ #endif - DBG_RUN_SG("%s() DONE 1 mapping\n", __FUNCTION__); return 1; } @@ -1145,11 +1304,26 @@ #ifdef CONFIG_PROC_FS ioc->msg_calls++; #endif - + /* - ** coalesce and program the I/O Pdir + ** First coalesce the chunks and allocate I/O pdir space + ** + ** If this is one DMA stream, we can properly map using the + ** correct virtual address associated with each DMA page. + ** w/o this association, we wouldn't have coherent DMA! + ** Access to the virtual address is what forces a two pass algorithm. */ - filled = sba_coalesce_chunks(ioc, sglist, nents, direction); + coalesced = sba_coalesce_chunks(ioc, sglist, nents); + + /* + ** Program the I/O Pdir + ** + ** map the virtual addresses to the I/O Pdir + ** o dma_address will contain the pdir index + ** o dma_len will contain the number of bytes to map + ** o address contains the virtual address. + */ + filled = sba_fill_pdir(ioc, sglist, nents); #ifdef ASSERT_PDIR_SANITY if (sba_check_pdir(ioc,"Check after sba_map_sg()")) @@ -1161,6 +1335,7 @@ spin_unlock_irqrestore(&ioc->res_lock, flags); + ASSERT(coalesced == filled); DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); return filled; @@ -1172,23 +1347,19 @@ * @dev: instance of PCI owned by the driver that's asking. * @sglist: array of buffer/length pairs * @nents: number of entries in list - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ -void sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, - int direction) +void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) { struct ioc *ioc; #ifdef ASSERT_PDIR_SANITY unsigned long flags; #endif - DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", - __FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist)); - - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); + DBG_RUN_SG("%s() START %d entries, %p,%x\n", + __FUNCTION__, nents, sba_sg_address(sglist), sglist->length); ioc = GET_IOC(dev); ASSERT(ioc); @@ -1203,10 +1374,9 @@ spin_unlock_irqrestore(&ioc->res_lock, flags); #endif - while (sba_sg_len(sglist) && nents--) { + while (nents && sglist->dma_length) { - sba_unmap_single(dev, (dma_addr_t)sba_sg_iova(sglist), - sba_sg_iova_len(sglist), direction); + sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir); #ifdef CONFIG_PROC_FS /* ** This leaves inconsistent data in the stats, but we can't @@ -1214,9 +1384,11 @@ ** were coalesced to a single entry. The stats are fun, ** but speed is more important. */ - ioc->usg_pages += (((u64)sba_sg_iova(sglist) & ~IOVP_MASK) + sba_sg_len(sglist) + IOVP_SIZE - 1) >> IOVP_SHIFT; + ioc->usg_pages += ((sglist->dma_address & ~IOVP_MASK) + sglist->dma_length + + IOVP_SIZE - 1) >> PAGE_SHIFT; #endif - ++sglist; + sglist++; + nents--; } DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); @@ -1229,87 +1401,76 @@ } -unsigned long -sba_dma_address (struct scatterlist *sg) -{ - return ((unsigned long)sba_sg_iova(sg)); -} - -int -sba_dma_supported (struct pci_dev *dev, u64 mask) -{ - return 1; -} - /************************************************************** * * Initialization and claim * ***************************************************************/ - -static void -sba_ioc_init(struct sba_device *sba_dev, struct ioc *ioc, int ioc_num) +static void __init +ioc_iova_init(struct ioc *ioc) { - u32 iova_space_size, iova_space_mask; - void * pdir_base; - int pdir_size, iov_order, tcnfg; + u32 iova_space_mask; + int iov_order, tcnfg; + int agp_found = 0; + struct pci_dev *device; +#ifdef FULL_VALID_PDIR + unsigned long index; +#endif /* - ** Firmware programs the maximum IOV space size into the imask reg + ** Firmware programs the base and size of a "safe IOVA space" + ** (one that doesn't overlap memory or LMMIO space) in the + ** IBASE and IMASK registers. */ - iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; + ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1UL; + ioc->iov_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; /* ** iov_order is always based on a 1GB IOVA space since we want to ** turn on the other half for AGP GART. */ - iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT)); - ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); + iov_order = get_order(ioc->iov_size >> (IOVP_SHIFT - PAGE_SHIFT)); + ioc->pdir_size = (ioc->iov_size / IOVP_SIZE) * sizeof(u64); - DBG_INIT("%s() hpa 0x%lx IOV %dMB (%d bits) PDIR size 0x%0x\n", - __FUNCTION__, ioc->ioc_hpa, iova_space_size>>20, - iov_order + PAGE_SHIFT, ioc->pdir_size); + DBG_INIT("%s() hpa %p IOV %dMB (%d bits) PDIR size 0x%x\n", + __FUNCTION__, ioc->ioc_hpa, ioc->iov_size >> 20, + iov_order + PAGE_SHIFT, ioc->pdir_size); - /* XXX DMA HINTs not used */ + /* FIXME : DMA HINTs not used */ ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT)); - ioc->pdir_base = pdir_base = - (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size)); - if (NULL == pdir_base) - { - panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); - } - memset(pdir_base, 0, pdir_size); + ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL, + get_order(ioc->pdir_size)); + if (!ioc->pdir_base) + panic(PFX "Couldn't allocate I/O Page Table\n"); + + memset(ioc->pdir_base, 0, ioc->pdir_size); DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n", - __FUNCTION__, pdir_base, pdir_size, + __FUNCTION__, ioc->pdir_base, ioc->pdir_size, ioc->hint_shift_pdir, ioc->hint_mask_pdir); - ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base); - WRITE_REG(virt_to_phys(pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE); + ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base); + WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE); - DBG_INIT(" base %p\n", pdir_base); + DBG_INIT(" base %p\n", ioc->pdir_base); /* build IMASK for IOC and Elroy */ iova_space_mask = 0xffffffff; - iova_space_mask <<= (iov_order + IOVP_SHIFT); - - ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & 0xFFFFFFFEUL; - - ioc->imask = iova_space_mask; /* save it */ + iova_space_mask <<= (iov_order + PAGE_SHIFT); + ioc->imask = iova_space_mask; DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__, ioc->ibase, ioc->imask); /* - ** XXX DMA HINT registers are programmed with default hint + ** FIXME: Hint registers are programmed with default hint ** values during boot, so hints should be sane even if we ** can't reprogram them the way drivers want. */ - - WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK); + WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK); /* ** Setting the upper bits makes checking for bypass addresses @@ -1317,34 +1478,30 @@ */ ioc->imask |= 0xFFFFFFFF00000000UL; - /* Set I/O Pdir page size to system page size */ - switch (IOVP_SHIFT) { - case 12: /* 4K */ - tcnfg = 0; - break; - case 13: /* 8K */ - tcnfg = 1; - break; - case 14: /* 16K */ - tcnfg = 2; - break; - case 16: /* 64K */ - tcnfg = 3; + /* Set I/O PDIR Page size to system page size */ + switch (PAGE_SHIFT) { + case 12: tcnfg = 0; break; /* 4K */ + case 13: tcnfg = 1; break; /* 8K */ + case 14: tcnfg = 2; break; /* 16K */ + case 16: tcnfg = 3; break; /* 64K */ + default: + panic(PFX "Unsupported system page size %d", + 1 << PAGE_SHIFT); break; } - WRITE_REG(tcnfg, ioc->ioc_hpa+IOC_TCNFG); + WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG); /* ** Program the IOC's ibase and enable IOVA translation ** Bit zero == enable bit. */ - WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa+IOC_IBASE); + WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE); /* ** Clear I/O TLB of any possible entries. ** (Yes. This is a bit paranoid...but so what) */ - WRITE_REG(0 | 31, ioc->ioc_hpa+IOC_PCOM); + WRITE_REG(ioc->ibase | (iov_order+PAGE_SHIFT), ioc->ioc_hpa + IOC_PCOM); /* ** If an AGP device is present, only use half of the IOV space @@ -1354,346 +1511,468 @@ ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - if (SBA_GET_AGP(sba_dev)) { - DBG_INIT("%s() AGP Device found, reserving 512MB for GART support\n", __FUNCTION__); + pci_for_each_dev(device) + agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP); + + if (agp_found && reserve_sba_gart) { + DBG_INIT("%s: AGP device found, reserving half of IOVA for GART support\n", + __FUNCTION__); ioc->pdir_size /= 2; - ((u64 *)pdir_base)[PDIR_INDEX(iova_space_size/2)] = 0x0000badbadc0ffeeULL; + ((u64 *)ioc->pdir_base)[PDIR_INDEX(ioc->iov_size/2)] = ZX1_SBA_IOMMU_COOKIE; } +#ifdef FULL_VALID_PDIR + /* + ** Check to see if the spill page has been allocated, we don't need more than + ** one across multiple SBAs. + */ + if (!prefetch_spill_page) { + char *spill_poison = "SBAIOMMU POISON"; + int poison_size = 16; + void *poison_addr, *addr; + + addr = (void *)__get_free_pages(GFP_KERNEL, get_order(IOVP_SIZE)); + if (!addr) + panic(PFX "Couldn't allocate PDIR spill page\n"); + + poison_addr = addr; + for ( ; (u64) poison_addr < addr + IOVP_SIZE; poison_addr += poison_size) + memcpy(poison_addr, spill_poison, poison_size); + + prefetch_spill_page = virt_to_phys(addr); + + DBG_INIT("%s() prefetch spill addr: 0x%lx\n", __FUNCTION__, prefetch_spill_page); + } + /* + ** Set all the PDIR entries valid w/ the spill page as the target + */ + for (index = 0 ; index < (ioc->pdir_size / sizeof(u64)) ; index++) + ((u64 *)ioc->pdir_base)[index] = (0x80000000000000FF | prefetch_spill_page); +#endif - DBG_INIT("%s() DONE\n", __FUNCTION__); } +static void __init +ioc_resource_init(struct ioc *ioc) +{ + spin_lock_init(&ioc->res_lock); + /* resource map size dictated by pdir_size */ + ioc->res_size = ioc->pdir_size / sizeof(u64); /* entries */ + ioc->res_size >>= 3; /* convert bit count to byte count */ + DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size); -/************************************************************************** -** -** SBA initialization code (HW and SW) -** -** o identify SBA chip itself -** o FIXME: initialize DMA hints for reasonable defaults -** -**************************************************************************/ + ioc->res_map = (char *) __get_free_pages(GFP_KERNEL, + get_order(ioc->res_size)); + if (!ioc->res_map) + panic(PFX "Couldn't allocate resource map\n"); -static void -sba_hw_init(struct sba_device *sba_dev) -{ - int i; - int num_ioc; - u64 dma_mask; - u32 func_id; + memset(ioc->res_map, 0, ioc->res_size); + /* next available IOVP - circular search */ + ioc->res_hint = (unsigned long *) ioc->res_map; - /* - ** Identify the SBA so we can set the dma_mask. We can make a virtual - ** dma_mask of the memory subsystem such that devices not implmenting - ** a full 64bit mask might still be able to bypass efficiently. - */ - func_id = READ_REG(sba_dev->sba_hpa + SBA_FUNC_ID); +#ifdef ASSERT_PDIR_SANITY + /* Mark first bit busy - ie no IOVA 0 */ + ioc->res_map[0] = 0x1; + ioc->pdir_base[0] = 0x8000000000000000ULL | ZX1_SBA_IOMMU_COOKIE; +#endif +#ifdef FULL_VALID_PDIR + /* Mark the last resource used so we don't prefetch beyond IOVA space */ + ioc->res_map[ioc->res_size - 1] |= 0x80UL; /* res_map is chars */ + ioc->pdir_base[(ioc->pdir_size / sizeof(u64)) - 1] = (0x80000000000000FF + | prefetch_spill_page); +#endif - if (func_id == ZX1_FUNC_ID_VALUE) { - dma_mask = 0xFFFFFFFFFFUL; - } else { - dma_mask = 0xFFFFFFFFFFFFFFFFUL; - } + DBG_INIT("%s() res_map %x %p\n", __FUNCTION__, + ioc->res_size, (void *) ioc->res_map); +} + +static void __init +ioc_sac_init(struct ioc *ioc) +{ + struct pci_dev *sac = NULL; + struct pci_controller *controller = NULL; - DBG_INIT("%s(): ioc->dma_mask == 0x%lx\n", __FUNCTION__, dma_mask); - /* - ** Leaving in the multiple ioc code from parisc for the future, - ** currently there are no muli-ioc mckinley sbas - */ - sba_dev->ioc[0].ioc_hpa = SBA_IOC_OFFSET; - num_ioc = 1; + * pci_alloc_coherent() must return a DMA address which is + * SAC (single address cycle) addressable, so allocate a + * pseudo-device to enforce that. + */ + sac = kmalloc(sizeof(*sac), GFP_KERNEL); + if (!sac) + panic(PFX "Couldn't allocate struct pci_dev"); + memset(sac, 0, sizeof(*sac)); - sba_dev->num_ioc = num_ioc; - for (i = 0; i < num_ioc; i++) { - sba_dev->ioc[i].dma_mask = dma_mask; - sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa; - sba_ioc_init(sba_dev, &(sba_dev->ioc[i]), i); - } + controller = kmalloc(sizeof(*controller), GFP_KERNEL); + if (!controller) + panic(PFX "Couldn't allocate struct pci_controller"); + memset(controller, 0, sizeof(*controller)); + + controller->iommu = ioc; + sac->sysdata = controller; + sac->dma_mask = 0xFFFFFFFFUL; +#ifdef CONFIG_PCI + sac->dev.bus = &pci_bus_type; +#endif + ioc->sac_only_dev = sac; } -static void -sba_common_init(struct sba_device *sba_dev) +static void __init +ioc_zx1_init(struct ioc *ioc) { - int i; + if (ioc->rev < 0x20) + panic(PFX "IOC 2.0 or later required for IOMMU support\n"); - /* add this one to the head of the list (order doesn't matter) - ** This will be useful for debugging - especially if we get coredumps - */ - sba_dev->next = sba_list; - sba_list = sba_dev; - sba_count++; - - for(i=0; i< sba_dev->num_ioc; i++) { - int res_size; - - /* resource map size dictated by pdir_size */ - res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */ - res_size >>= 3; /* convert bit count to byte count */ - DBG_INIT("%s() res_size 0x%x\n", - __FUNCTION__, res_size); - - sba_dev->ioc[i].res_size = res_size; - sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); - - if (NULL == sba_dev->ioc[i].res_map) - { - panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ ); - } + ioc->dma_mask = 0xFFFFFFFFFFUL; +} - memset(sba_dev->ioc[i].res_map, 0, res_size); - /* next available IOVP - circular search */ - if ((sba_dev->hw_rev & 0xFF) >= 0x20) { - sba_dev->ioc[i].res_hint = (unsigned long *) - sba_dev->ioc[i].res_map; - } else { - u64 reserved_iov; +typedef void (initfunc)(struct ioc *); - /* Yet another 1.x hack */ - printk(KERN_DEBUG "zx1 1.x: Starting resource hint offset into " - "IOV space to avoid initial zero value IOVA\n"); - sba_dev->ioc[i].res_hint = (unsigned long *) - &(sba_dev->ioc[i].res_map[L1_CACHE_BYTES]); - - sba_dev->ioc[i].res_map[0] = 0x1; - sba_dev->ioc[i].pdir_base[0] = 0x8000badbadc0ffeeULL; - - for (reserved_iov = 0xA0000 ; reserved_iov < 0xC0000 ; reserved_iov += IOVP_SIZE) { - u64 *res_ptr = (u64 *) sba_dev->ioc[i].res_map; - int index = PDIR_INDEX(reserved_iov); - int res_word; - u64 mask; - - res_word = (int)(index / BITS_PER_LONG); - mask = 0x1UL << (index - (res_word * BITS_PER_LONG)); - res_ptr[res_word] |= mask; - sba_dev->ioc[i].pdir_base[PDIR_INDEX(reserved_iov)] = (SBA_VALID_MASK | reserved_iov); +struct ioc_iommu { + u32 func_id; + char *name; + initfunc *init; +}; - } - } +static struct ioc_iommu ioc_iommu_info[] __initdata = { + { ZX1_IOC_ID, "zx1", ioc_zx1_init }, + { REO_IOC_ID, "REO" }, + { SX1000_IOC_ID, "sx1000" }, +}; -#ifdef ASSERT_PDIR_SANITY - /* Mark first bit busy - ie no IOVA 0 */ - sba_dev->ioc[i].res_map[0] = 0x1; - sba_dev->ioc[i].pdir_base[0] = 0x8000badbadc0ffeeULL; -#endif +static struct ioc * __init +ioc_init(u64 hpa, void *handle) +{ + struct ioc *ioc; + struct ioc_iommu *info; + + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return NULL; + + memset(ioc, 0, sizeof(*ioc)); - DBG_INIT("%s() %d res_map %x %p\n", __FUNCTION__, - i, res_size, (void *)sba_dev->ioc[i].res_map); + ioc->next = ioc_list; + ioc_list = ioc; + + ioc->handle = handle; + ioc->ioc_hpa = ioremap(hpa, 0x1000); + + ioc->func_id = READ_REG(ioc->ioc_hpa + IOC_FUNC_ID); + ioc->rev = READ_REG(ioc->ioc_hpa + IOC_FCLASS) & 0xFFUL; + ioc->dma_mask = 0xFFFFFFFFFFFFFFFFUL; /* conservative */ + + for (info = ioc_iommu_info; info < ioc_iommu_info + ARRAY_SIZE(ioc_iommu_info); info++) { + if (ioc->func_id == info->func_id) { + ioc->name = info->name; + if (info->init) + (info->init)(ioc); + } } - sba_dev->sba_lock = SPIN_LOCK_UNLOCKED; + if (!ioc->name) { + ioc->name = kmalloc(24, GFP_KERNEL); + if (ioc->name) + sprintf((char *) ioc->name, "Unknown (%04x:%04x)", + ioc->func_id & 0xFFFF, (ioc->func_id >> 16) & 0xFFFF); + else + ioc->name = "Unknown"; + } + + ioc_iova_init(ioc); + ioc_resource_init(ioc); + ioc_sac_init(ioc); + + printk(KERN_INFO PFX + "%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n", + ioc->name, (ioc->rev >> 4) & 0xF, ioc->rev & 0xF, + hpa, ioc->iov_size >> 20, ioc->ibase); + + return ioc; } + + +/************************************************************************** +** +** SBA initialization code (HW and SW) +** +** o identify SBA chip itself +** o FIXME: initialize DMA hints for reasonable defaults +** +**************************************************************************/ + #ifdef CONFIG_PROC_FS -static int sba_proc_info(char *buf, char **start, off_t offset, int len) +static void * +ioc_start(struct seq_file *s, loff_t *pos) { - struct sba_device *sba_dev; struct ioc *ioc; - int total_pages; + loff_t n = *pos; + + for (ioc = ioc_list; ioc; ioc = ioc->next) + if (!n--) + return ioc; + + return NULL; +} + +static void * +ioc_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct ioc *ioc = v; + + ++*pos; + return ioc->next; +} + +static void +ioc_stop(struct seq_file *s, void *v) +{ +} + +static int +ioc_show(struct seq_file *s, void *v) +{ + struct ioc *ioc = v; + int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ unsigned long i = 0, avg = 0, min, max; - for (sba_dev = sba_list; sba_dev; sba_dev = sba_dev->next) { - ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ - total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ - - sprintf(buf, "%s rev %d.%d\n", "Hewlett-Packard zx1 SBA", - ((sba_dev->hw_rev >> 4) & 0xF), (sba_dev->hw_rev & 0xF)); - sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", buf, - (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages); - - sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, - total_pages - ioc->used_pages, ioc->used_pages, - (int) (ioc->used_pages * 100 / total_pages)); - - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ - - min = max = ioc->avg_search[0]; - for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { - avg += ioc->avg_search[i]; - if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; - if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; - } - avg /= SBA_SEARCH_SAMPLE; - sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - buf, min, avg, max); - - sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msingle_calls, ioc->msingle_pages, - (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); + seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", + ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); + seq_printf(s, "IO PDIR size : %d bytes (%d entries)\n", + (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ + total_pages); + + seq_printf(s, "IO PDIR entries : %ld free %ld used (%d%%)\n", + total_pages - ioc->used_pages, ioc->used_pages, + (int) (ioc->used_pages * 100 / total_pages)); + + seq_printf(s, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + + min = max = ioc->avg_search[0]; + for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { + avg += ioc->avg_search[i]; + if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; + if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; + } + avg /= SBA_SEARCH_SAMPLE; + seq_printf(s, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max); + + seq_printf(s, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, + (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_single(): %12ld bypasses\n", - buf, ioc->msingle_bypass); + seq_printf(s, "pci_map_single(): %12ld bypasses\n", ioc->msingle_bypass); #endif - sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usingle_calls, ioc->usingle_pages, - (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); + seq_printf(s, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usingle_calls, ioc->usingle_pages, + (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_unmap_single: %12ld bypasses\n", - buf, ioc->usingle_bypass); + seq_printf(s, "pci_unmap_single: %12ld bypasses\n", ioc->usingle_bypass); #endif - sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msg_calls, ioc->msg_pages, - (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); + seq_printf(s, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, + (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_sg() : %12ld bypasses\n", - buf, ioc->msg_bypass); + seq_printf(s, "pci_map_sg() : %12ld bypasses\n", ioc->msg_bypass); #endif - sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usg_calls, ioc->usg_pages, - (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); - } - return strlen(buf); + seq_printf(s, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); + + return 0; } +static struct seq_operations ioc_seq_ops = { + .start = ioc_start, + .next = ioc_next, + .stop = ioc_stop, + .show = ioc_show +}; + static int -sba_resource_map(char *buf, char **start, off_t offset, int len) +ioc_open(struct inode *inode, struct file *file) { - struct ioc *ioc = sba_list->ioc; /* FIXME: Multi-IOC support! */ - unsigned int *res_ptr; - int i; + return seq_open(file, &ioc_seq_ops); +} - if (!ioc) - return 0; +static struct file_operations ioc_fops = { + .open = ioc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; - res_ptr = (unsigned int *)ioc->res_map; - buf[0] = '\0'; - for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) { - if ((i & 7) == 0) - strcat(buf,"\n "); - sprintf(buf, "%s %08x", buf, *res_ptr); - } - strcat(buf, "\n"); +static int +ioc_map_show(struct seq_file *s, void *v) +{ + struct ioc *ioc = v; + unsigned int i, *res_ptr = (unsigned int *)ioc->res_map; - return strlen(buf); + for (i = 0; i < ioc->res_size / sizeof(unsigned int); ++i, ++res_ptr) + seq_printf(s, "%s%08x", (i & 7) ? " " : "\n ", *res_ptr); + seq_printf(s, "\n"); + + return 0; } -#endif -/* -** Determine if sba should claim this chip (return 0) or not (return 1). -** If so, initialize the chip and tell other partners in crime they -** have work to do. -*/ -void __init sba_init(void) +static struct seq_operations ioc_map_ops = { + .start = ioc_start, + .next = ioc_next, + .stop = ioc_stop, + .show = ioc_map_show +}; + +static int +ioc_map_open(struct inode *inode, struct file *file) { - struct sba_device *sba_dev; - u32 func_id, hw_rev; - u32 *func_offset = NULL; - int i, agp_found = 0; - static char sba_rev[6]; - struct pci_dev *device = NULL; - u64 hpa = 0; + return seq_open(file, &ioc_map_ops); +} - if (!(device = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_SBA, NULL))) - return; +static struct file_operations ioc_map_fops = { + .open = ioc_map_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (pci_resource_flags(device, i) == IORESOURCE_MEM) { - hpa = (u64) ioremap(pci_resource_start(device, i), - pci_resource_len(device, i)); - break; - } +static void __init +ioc_proc_init(void) +{ + if (ioc_list) { + struct proc_dir_entry *dir, *entry; + + dir = proc_mkdir("bus/mckinley", 0); + entry = create_proc_entry(ioc_list->name, 0, dir); + if (entry) + entry->proc_fops = &ioc_fops; + + entry = create_proc_entry("bitmap", 0, dir); + if (entry) + entry->proc_fops = &ioc_map_fops; } +} +#endif - func_id = READ_REG(hpa + SBA_FUNC_ID); - if (func_id != ZX1_FUNC_ID_VALUE) - return; +void +sba_connect_bus(struct pci_bus *bus) +{ + acpi_handle handle, parent; + acpi_status status; + struct ioc *ioc; - strcpy(sba_rev, "zx1"); - func_offset = zx1_func_offsets; + if (!PCI_CONTROLLER(bus)) + panic(PFX "no sysdata on bus %d!\n",bus->number); - /* Read HW Rev First */ - hw_rev = READ_REG(hpa + SBA_FCLASS) & 0xFFUL; + if (PCI_CONTROLLER(bus)->iommu) + return; + + handle = PCI_CONTROLLER(bus)->acpi_handle; + if (!handle) + return; /* - * Not all revision registers of the chipset are updated on every - * turn. Must scan through all functions looking for the highest rev + * The IOC scope encloses PCI root bridges in the ACPI + * namespace, so work our way out until we find an IOC we + * claimed previously. */ - if (func_offset) { - for (i = 0 ; func_offset[i] != -1 ; i++) { - u32 func_rev; - - func_rev = READ_REG(hpa + SBA_FCLASS + func_offset[i]) & 0xFFUL; - DBG_INIT("%s() func offset: 0x%x rev: 0x%x\n", - __FUNCTION__, func_offset[i], func_rev); - if (func_rev > hw_rev) - hw_rev = func_rev; - } - } - - printk(KERN_INFO "%s found %s %d.%d at %s, HPA 0x%lx\n", DRIVER_NAME, - sba_rev, ((hw_rev >> 4) & 0xF), (hw_rev & 0xF), - device->slot_name, hpa); + do { + for (ioc = ioc_list; ioc; ioc = ioc->next) + if (ioc->handle == handle) { + PCI_CONTROLLER(bus)->iommu = ioc; + return; + } - if ((hw_rev & 0xFF) < 0x20) { - printk(KERN_INFO "%s: SBA rev less than 2.0 not supported", DRIVER_NAME); - return; - } + status = acpi_get_parent(handle, &parent); + handle = parent; + } while (ACPI_SUCCESS(status)); - sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); - if (NULL == sba_dev) { - printk(KERN_ERR DRIVER_NAME " - couldn't alloc sba_device\n"); - return; - } + printk(KERN_WARNING "No IOC for PCI Bus %02x:%02x in ACPI\n", PCI_SEGMENT(bus), bus->number); +} - memset(sba_dev, 0, sizeof(struct sba_device)); +static int __init +acpi_sba_ioc_add(struct acpi_device *device) +{ + struct ioc *ioc; + acpi_status status; + u64 hpa, length; + struct acpi_device_info dev_info; - for(i=0; iioc[i].res_lock)); + status = hp_acpi_csr_space(device->handle, &hpa, &length); + if (ACPI_FAILURE(status)) + return 1; - sba_dev->hw_rev = hw_rev; - sba_dev->sba_hpa = hpa; + status = acpi_get_object_info(device->handle, &dev_info); + if (ACPI_FAILURE(status)) + return 1; /* - * We pass this fake device from alloc_consistent to ensure - * we only use SAC for alloc_consistent mappings. + * For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI + * root bridges, and its CSR space includes the IOC function. */ - sac_only_dev.dma_mask = 0xFFFFFFFFUL; + if (strncmp("HWP0001", dev_info.hardware_id, 7) == 0) + hpa += ZX1_IOC_OFFSET; - /* - * We need to check for an AGP device, if we find one, then only - * use part of the IOVA space for PCI DMA, the rest is for GART. - * REVISIT for multiple IOC. - */ - pci_for_each_dev(device) - agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP); + ioc = ioc_init(hpa, device->handle); + if (!ioc) + return 1; - if (agp_found && reserve_sba_gart) - SBA_SET_AGP(sba_dev); + return 0; +} - sba_hw_init(sba_dev); - sba_common_init(sba_dev); +static struct acpi_driver acpi_sba_ioc_driver = { + name: "IOC IOMMU Driver", + ids: "HWP0001,HWP0004", + ops: { + add: acpi_sba_ioc_add, + }, +}; -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry * proc_mckinley_root; +static int __init +sba_init(void) +{ + MAX_DMA_ADDRESS = ~0UL; + + acpi_bus_register_driver(&acpi_sba_ioc_driver); - proc_mckinley_root = proc_mkdir("bus/mckinley",0); - create_proc_info_entry(sba_rev, 0, proc_mckinley_root, sba_proc_info); - create_proc_info_entry("bitmap", 0, proc_mckinley_root, sba_resource_map); +#ifdef CONFIG_PCI + { + struct pci_bus *b; + pci_for_each_bus(b) + sba_connect_bus(b); } #endif + +#ifdef CONFIG_PROC_FS + ioc_proc_init(); +#endif + return 0; } +subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */ + static int __init -nosbagart (char *str) +nosbagart(char *str) { reserve_sba_gart = 0; return 1; } -__setup("nosbagart",nosbagart); +int +sba_dma_supported (struct device *dev, u64 mask) +{ + /* make sure it's at least 32bit capable */ + return ((mask & 0xFFFFFFFFUL) == 0xFFFFFFFFUL); +} + +__setup("nosbagart", nosbagart); -EXPORT_SYMBOL(sba_init); EXPORT_SYMBOL(sba_map_single); EXPORT_SYMBOL(sba_unmap_single); EXPORT_SYMBOL(sba_map_sg); EXPORT_SYMBOL(sba_unmap_sg); -EXPORT_SYMBOL(sba_dma_address); EXPORT_SYMBOL(sba_dma_supported); -EXPORT_SYMBOL(sba_alloc_consistent); -EXPORT_SYMBOL(sba_free_consistent); +EXPORT_SYMBOL(sba_alloc_coherent); +EXPORT_SYMBOL(sba_free_coherent); diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_console.c linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_console.c --- linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_console.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_console.c 2003-05-12 04:43:29.000000000 -0700 @@ -59,7 +59,7 @@ static struct tty_driver *simcons_console_device (struct console *c, int *index) { - extern struct tty_driver hp_serial_driver; + extern struct tty_driver hp_simserial_driver; *index = c->index; - return &hp_serial_driver; + return &hp_simserial_driver; } diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_machvec.c linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_machvec.c --- linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_machvec.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_machvec.c 2003-05-12 04:43:29.000000000 -0700 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME hpsim +#define MACHVEC_PLATFORM_NAME hpsim +#define MACHVEC_PLATFORM_HEADER #include diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/simeth.c linux-2.5.69-bk7/arch/ia64/hp/sim/simeth.c --- linux-2.5.69-bk6/arch/ia64/hp/sim/simeth.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/sim/simeth.c 2003-05-12 04:43:29.000000000 -0700 @@ -55,7 +55,7 @@ static int simeth_tx(struct sk_buff *skb, struct net_device *dev); static int simeth_rx(struct net_device *dev); static struct net_device_stats *simeth_get_stats(struct net_device *dev); -static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); static void set_multicast_list(struct net_device *dev); static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr); @@ -494,20 +494,21 @@ /* * Interrupt handler (Yes, we can do it too !!!) */ -static void +static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = dev_id; if ( dev == NULL ) { printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq); - return; + return IRQ_NONE; } /* - * very simple loop because we get interrupts only when receving + * very simple loop because we get interrupts only when receiving */ while (simeth_rx(dev)); + return IRQ_HANDLED; } static struct net_device_stats * diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/simserial.c linux-2.5.69-bk7/arch/ia64/hp/sim/simserial.c --- linux-2.5.69-bk6/arch/ia64/hp/sim/simserial.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/sim/simserial.c 2003-05-12 04:43:29.000000000 -0700 @@ -103,7 +103,8 @@ { 0, 0} }; -static struct tty_driver hp_serial_driver, callout_driver; +struct tty_driver hp_simserial_driver; +static struct tty_driver callout_driver; static int serial_refcount; static struct async_struct *IRQ_ports[NR_IRQS]; @@ -184,7 +185,7 @@ /* * This is the serial driver's interrupt routine for a single port */ -static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) { struct async_struct * info; @@ -195,13 +196,14 @@ info = IRQ_ports[irq]; if (!info || !info->tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); - return; + return IRQ_NONE; } /* * pretty simple in our case, because we only get interrupts * on inbound traffic */ receive_chars(info->tty, regs); + return IRQ_HANDLED; } /* @@ -768,7 +770,7 @@ { unsigned long flags; int retval=0; - void (*handler)(int, void *, struct pt_regs *); + irqreturn_t (*handler)(int, void *, struct pt_regs *); struct serial_state *state= info->state; unsigned long page; @@ -808,8 +810,7 @@ } else handler = rs_interrupt_single; - retval = request_irq(state->irq, handler, IRQ_T(info), - "simserial", NULL); + retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL); if (retval) { if (capable(CAP_SYS_ADMIN)) { if (info->tty) @@ -1028,43 +1029,43 @@ /* Initialize the tty_driver structure */ - memset(&hp_serial_driver, 0, sizeof(struct tty_driver)); - hp_serial_driver.magic = TTY_DRIVER_MAGIC; - hp_serial_driver.driver_name = "simserial"; - hp_serial_driver.name = "ttyS"; - hp_serial_driver.major = TTY_MAJOR; - hp_serial_driver.minor_start = 64; - hp_serial_driver.num = 1; - hp_serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - hp_serial_driver.subtype = SERIAL_TYPE_NORMAL; - hp_serial_driver.init_termios = tty_std_termios; - hp_serial_driver.init_termios.c_cflag = + memset(&hp_simserial_driver, 0, sizeof(struct tty_driver)); + hp_simserial_driver.magic = TTY_DRIVER_MAGIC; + hp_simserial_driver.driver_name = "simserial"; + hp_simserial_driver.name = "ttyS"; + hp_simserial_driver.major = TTY_MAJOR; + hp_simserial_driver.minor_start = 64; + hp_simserial_driver.num = 1; + hp_simserial_driver.type = TTY_DRIVER_TYPE_SERIAL; + hp_simserial_driver.subtype = SERIAL_TYPE_NORMAL; + hp_simserial_driver.init_termios = tty_std_termios; + hp_simserial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - hp_serial_driver.flags = TTY_DRIVER_REAL_RAW; - hp_serial_driver.refcount = &serial_refcount; - hp_serial_driver.table = serial_table; - hp_serial_driver.termios = serial_termios; - hp_serial_driver.termios_locked = serial_termios_locked; - - hp_serial_driver.open = rs_open; - hp_serial_driver.close = rs_close; - hp_serial_driver.write = rs_write; - hp_serial_driver.put_char = rs_put_char; - hp_serial_driver.flush_chars = rs_flush_chars; - hp_serial_driver.write_room = rs_write_room; - hp_serial_driver.chars_in_buffer = rs_chars_in_buffer; - hp_serial_driver.flush_buffer = rs_flush_buffer; - hp_serial_driver.ioctl = rs_ioctl; - hp_serial_driver.throttle = rs_throttle; - hp_serial_driver.unthrottle = rs_unthrottle; - hp_serial_driver.send_xchar = rs_send_xchar; - hp_serial_driver.set_termios = rs_set_termios; - hp_serial_driver.stop = rs_stop; - hp_serial_driver.start = rs_start; - hp_serial_driver.hangup = rs_hangup; - hp_serial_driver.break_ctl = rs_break; - hp_serial_driver.wait_until_sent = rs_wait_until_sent; - hp_serial_driver.read_proc = rs_read_proc; + hp_simserial_driver.flags = TTY_DRIVER_REAL_RAW; + hp_simserial_driver.refcount = &serial_refcount; + hp_simserial_driver.table = serial_table; + hp_simserial_driver.termios = serial_termios; + hp_simserial_driver.termios_locked = serial_termios_locked; + + hp_simserial_driver.open = rs_open; + hp_simserial_driver.close = rs_close; + hp_simserial_driver.write = rs_write; + hp_simserial_driver.put_char = rs_put_char; + hp_simserial_driver.flush_chars = rs_flush_chars; + hp_simserial_driver.write_room = rs_write_room; + hp_simserial_driver.chars_in_buffer = rs_chars_in_buffer; + hp_simserial_driver.flush_buffer = rs_flush_buffer; + hp_simserial_driver.ioctl = rs_ioctl; + hp_simserial_driver.throttle = rs_throttle; + hp_simserial_driver.unthrottle = rs_unthrottle; + hp_simserial_driver.send_xchar = rs_send_xchar; + hp_simserial_driver.set_termios = rs_set_termios; + hp_simserial_driver.stop = rs_stop; + hp_simserial_driver.start = rs_start; + hp_simserial_driver.hangup = rs_hangup; + hp_simserial_driver.break_ctl = rs_break; + hp_simserial_driver.wait_until_sent = rs_wait_until_sent; + hp_simserial_driver.read_proc = rs_read_proc; /* * Let's have a little bit of fun ! @@ -1087,14 +1088,14 @@ * The callout device is just like normal device except for * major number and the subtype code. */ - callout_driver = hp_serial_driver; + callout_driver = hp_simserial_driver; callout_driver.name = "cua"; callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; callout_driver.read_proc = 0; callout_driver.proc_entry = 0; - if (tty_register_driver(&hp_serial_driver)) + if (tty_register_driver(&hp_simserial_driver)) panic("Couldn't register simserial driver\n"); if (tty_register_driver(&callout_driver)) diff -urN linux-2.5.69-bk6/arch/ia64/hp/zx1/Makefile linux-2.5.69-bk7/arch/ia64/hp/zx1/Makefile --- linux-2.5.69-bk6/arch/ia64/hp/zx1/Makefile 2003-05-04 16:53:55.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/zx1/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -5,5 +5,4 @@ # Copyright (C) Alex Williamson (alex_williamson@hp.com) # -obj-y := hpzx1_misc.o obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o diff -urN linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_machvec.c linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_machvec.c --- linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_machvec.c 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_machvec.c 2003-05-12 04:43:29.000000000 -0700 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME hpzx1 +#define MACHVEC_PLATFORM_NAME hpzx1 +#define MACHVEC_PLATFORM_HEADER #include diff -urN linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_misc.c linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_misc.c --- linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_misc.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_misc.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,348 +0,0 @@ -/* - * Misc. support for HP zx1 chipset support - * - * Copyright (C) 2002-2003 Hewlett-Packard Co - * Alex Williamson - * Bjorn Helgaas - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include - -extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, struct acpi_object_list *, - unsigned long *); - -#define PFX "hpzx1: " - -static int hpzx1_devices; - -struct fake_pci_dev { - struct fake_pci_dev *next; - struct pci_dev *pci_dev; - unsigned long csr_base; - unsigned long csr_size; - unsigned long mapped_csrs; // ioremapped - int sizing; // in middle of BAR sizing operation? -} *fake_pci_dev_list; - -static struct pci_ops *orig_pci_ops; - -struct fake_pci_dev * -lookup_fake_dev (struct pci_bus *bus, unsigned int devfn) -{ - struct fake_pci_dev *fake_dev; - - for (fake_dev = fake_pci_dev_list; fake_dev; fake_dev = fake_dev->next) - if (fake_dev->pci_dev->bus == bus && fake_dev->pci_dev->devfn == devfn) - return fake_dev; - return NULL; -} - -static int -hp_cfg_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn); - - if (!fake_dev) - return (*orig_pci_ops->read)(bus, devfn, where, size, value); - - if (where == PCI_BASE_ADDRESS_0) { - if (fake_dev->sizing) - *value = ~(fake_dev->csr_size - 1); - else - *value = ((fake_dev->csr_base & PCI_BASE_ADDRESS_MEM_MASK) - | PCI_BASE_ADDRESS_SPACE_MEMORY); - fake_dev->sizing = 0; - return PCIBIOS_SUCCESSFUL; - } - switch (size) { - case 1: *value = readb(fake_dev->mapped_csrs + where); break; - case 2: *value = readw(fake_dev->mapped_csrs + where); break; - case 4: *value = readl(fake_dev->mapped_csrs + where); break; - default: - printk(KERN_WARNING"hp_cfg_read: bad size = %d bytes", size); - break; - } - if (where == PCI_COMMAND) - *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ - return PCIBIOS_SUCCESSFUL; -} - -static int -hp_cfg_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn); - - if (!fake_dev) - return (*orig_pci_ops->write)(bus, devfn, where, size, value); - - if (where == PCI_BASE_ADDRESS_0) { - if (value == ((1UL << 8*size) - 1)) - fake_dev->sizing = 1; - return PCIBIOS_SUCCESSFUL; - } - switch (size) { - case 1: writeb(value, fake_dev->mapped_csrs + where); break; - case 2: writew(value, fake_dev->mapped_csrs + where); break; - case 4: writel(value, fake_dev->mapped_csrs + where); break; - default: - printk(KERN_WARNING"hp_cfg_write: bad size = %d bytes", size); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops hp_pci_conf = { - .read = hp_cfg_read, - .write = hp_cfg_write -}; - -static void -hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size) -{ - struct fake_pci_dev *fake; - int slot, ret; - struct pci_dev *dev; - struct pci_bus *b, *bus = NULL; - u8 hdr; - - fake = kmalloc(sizeof(*fake), GFP_KERNEL); - if (!fake) { - printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name, (void *) addr); - return; - } - - memset(fake, 0, sizeof(*fake)); - fake->csr_base = addr; - fake->csr_size = size; - fake->mapped_csrs = (unsigned long) ioremap(addr, size); - fake->sizing = 0; - - pci_for_each_bus(b) - if (busnum == b->number) { - bus = b; - break; - } - - if (!bus) { - printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n", - busnum, name, (void *) addr); - kfree(fake); - return; - } - - for (slot = 0x1e; slot; slot--) - if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0))) - break; - - if (slot < 0) { - printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n", - name, (void *) addr, busnum); - kfree(fake); - return; - } - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name, (void *) addr); - kfree(fake); - return; - } - - bus->ops = &hp_pci_conf; // replace pci ops for this bus - - fake->pci_dev = dev; - fake->next = fake_pci_dev_list; - fake_pci_dev_list = fake; - - memset(dev, 0, sizeof(*dev)); - dev->bus = bus; - dev->sysdata = fake; - dev->dev.parent = bus->dev; - dev->dev.bus = &pci_bus_type; - dev->devfn = PCI_DEVFN(slot, 0); - pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor); - pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); - pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr); - dev->hdr_type = hdr & 0x7f; - - pci_setup_device(dev); - - // pci_insert_device() without running /sbin/hotplug - list_add_tail(&dev->bus_list, &bus->devices); - list_add_tail(&dev->global_list, &pci_devices); - - strcpy(dev->dev.bus_id, dev->slot_name); - ret = device_register(&dev->dev); - if (ret < 0) - printk(KERN_INFO PFX "fake device registration failed (%d)\n", ret); - - printk(KERN_INFO PFX "%s at 0x%lx; pci dev %s\n", name, addr, dev->slot_name); - - hpzx1_devices++; -} - -struct acpi_hp_vendor_long { - u8 guid_id; - u8 guid[16]; - u8 csr_base[8]; - u8 csr_length[8]; -}; - -#define HP_CCSR_LENGTH 0x21 -#define HP_CCSR_TYPE 0x2 -#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ - 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) - -extern acpi_status acpi_get_crs(acpi_handle, struct acpi_buffer *); -extern struct acpi_resource *acpi_get_crs_next(struct acpi_buffer *, int *); -extern union acpi_resource_data *acpi_get_crs_type(struct acpi_buffer *, int *, int); -extern void acpi_dispose_crs(struct acpi_buffer *); - -static acpi_status -hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) -{ - int i, offset = 0; - acpi_status status; - struct acpi_buffer buf; - struct acpi_resource_vendor *res; - struct acpi_hp_vendor_long *hp_res; - efi_guid_t vendor_guid; - - *csr_base = 0; - *csr_length = 0; - - status = acpi_get_crs(obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PFX "Unable to get _CRS data on object\n"); - return status; - } - - res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); - if (!res) { - printk(KERN_ERR PFX "Failed to find config space for device\n"); - acpi_dispose_crs(&buf); - return AE_NOT_FOUND; - } - - hp_res = (struct acpi_hp_vendor_long *)(res->reserved); - - if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { - printk(KERN_ERR PFX "Unknown Vendor data\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); - if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { - printk(KERN_ERR PFX "Vendor GUID does not match\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - for (i = 0 ; i < 8 ; i++) { - *csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8)); - *csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8)); - } - - acpi_dispose_crs(&buf); - - return AE_OK; -} - -static acpi_status -hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret) -{ - u64 csr_base = 0, csr_length = 0; - acpi_status status; - char *name = context; - char fullname[16]; - - status = hp_csr_space(obj, &csr_base, &csr_length); - if (ACPI_FAILURE(status)) - return status; - - /* - * Only SBA shows up in ACPI namespace, so its CSR space - * includes both SBA and IOC. Make SBA and IOC show up - * separately in PCI space. - */ - sprintf(fullname, "%s SBA", name); - hpzx1_fake_pci_dev(fullname, 0, csr_base, 0x1000); - sprintf(fullname, "%s IOC", name); - hpzx1_fake_pci_dev(fullname, 0, csr_base + 0x1000, 0x1000); - - return AE_OK; -} - -static acpi_status -hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret) -{ - u64 csr_base = 0, csr_length = 0; - acpi_status status; - acpi_native_uint busnum; - char *name = context; - char fullname[32]; - - status = hp_csr_space(obj, &csr_base, &csr_length); - if (ACPI_FAILURE(status)) - return status; - - status = acpi_evaluate_integer(obj, METHOD_NAME__BBN, NULL, &busnum); - if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PFX "evaluate _BBN fail=0x%x\n", status); - busnum = 0; // no _BBN; stick it on bus 0 - } - - sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum); - hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length); - - return AE_OK; -} - -static void -hpzx1_acpi_dev_init(void) -{ - extern struct pci_ops *pci_root_ops; - - orig_pci_ops = pci_root_ops; - - /* - * Make fake PCI devices for the following hardware in the - * ACPI namespace. This makes it more convenient for drivers - * because they can claim these devices based on PCI - * information, rather than needing to know about ACPI. The - * 64-bit "HPA" space for this hardware is available as BAR - * 0/1. - * - * HWP0001: Single IOC SBA w/o IOC in namespace - * HWP0002: LBA device - * HWP0003: AGP LBA device - */ - acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL); - acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL); - acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL); -} - -extern void sba_init(void); - -static int -hpzx1_init (void) -{ - /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */ - MAX_DMA_ADDRESS = ~0UL; - - hpzx1_acpi_dev_init(); - sba_init(); - return 0; -} - -subsys_initcall(hpzx1_init); diff -urN linux-2.5.69-bk6/arch/ia64/ia32/ia32_entry.S linux-2.5.69-bk7/arch/ia64/ia32/ia32_entry.S --- linux-2.5.69-bk6/arch/ia64/ia32/ia32_entry.S 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/ia32/ia32_entry.S 2003-05-12 04:43:29.000000000 -0700 @@ -273,9 +273,9 @@ data8 sys32_sigsuspend data8 compat_sys_sigpending data8 sys_sethostname - data8 sys32_setrlimit /* 75 */ - data8 sys32_old_getrlimit - data8 sys32_getrusage + data8 compat_sys_setrlimit /* 75 */ + data8 compat_sys_old_getrlimit + data8 compat_sys_getrusage data8 sys32_gettimeofday data8 sys32_settimeofday data8 sys32_getgroups16 /* 80 */ @@ -312,7 +312,7 @@ data8 sys_vhangup data8 sys32_ni_syscall /* used to be sys_idle */ data8 sys32_ni_syscall - data8 sys32_wait4 + data8 compat_sys_wait4 data8 sys_swapoff /* 115 */ data8 sys32_sysinfo data8 sys32_ipc @@ -389,7 +389,7 @@ data8 sys32_ni_syscall /* streams1 */ data8 sys32_ni_syscall /* streams2 */ data8 sys32_vfork /* 190 */ - data8 sys32_getrlimit + data8 compat_sys_getrlimit data8 sys32_mmap2 data8 sys32_truncate64 data8 sys32_ftruncate64 diff -urN linux-2.5.69-bk6/arch/ia64/ia32/ia32_ioctl.c linux-2.5.69-bk7/arch/ia64/ia32/ia32_ioctl.c --- linux-2.5.69-bk6/arch/ia64/ia32/ia32_ioctl.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/ia32/ia32_ioctl.c 2003-05-12 04:43:29.000000000 -0700 @@ -3,13 +3,16 @@ * * Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 Don Dugger - * Copyright (C) 2001-2002 Hewlett-Packard Co + * Copyright (C) 2001-2003 Hewlett-Packard Co * David Mosberger-Tang */ #include #include #include /* argh, msdos_fs.h isn't self-contained... */ +#include /* argh, msdos_fs.h isn't self-contained... */ + +#include #include #include @@ -33,8 +36,6 @@ #define __KERNEL__ #include -#include - #include <../drivers/char/drm/drm.h> #include <../drivers/char/drm/mga_drm.h> #include <../drivers/char/drm/i810_drm.h> diff -urN linux-2.5.69-bk6/arch/ia64/ia32/ia32_traps.c linux-2.5.69-bk7/arch/ia64/ia32/ia32_traps.c --- linux-2.5.69-bk6/arch/ia64/ia32/ia32_traps.c 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/ia32/ia32_traps.c 2003-05-12 04:43:29.000000000 -0700 @@ -103,7 +103,7 @@ * C1 reg you need in case of a stack fault, 0x040 is the stack * fault bit. We should only be taking one exception at a time, * so if this combination doesn't produce any single exception, - * then we have a bad program that isn't syncronizing its FPU usage + * then we have a bad program that isn't synchronizing its FPU usage * and it will suffer the consequences since we won't be able to * fully reproduce the context of the exception */ diff -urN linux-2.5.69-bk6/arch/ia64/ia32/sys_ia32.c linux-2.5.69-bk7/arch/ia64/ia32/sys_ia32.c --- linux-2.5.69-bk6/arch/ia64/ia32/sys_ia32.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/ia32/sys_ia32.c 2003-05-12 04:43:29.000000000 -0700 @@ -53,10 +53,10 @@ #include #include #include +#include #include #include -#include #define DEBUG 0 @@ -177,7 +177,7 @@ { int err; - if (stat->size > MAX_NON_LFS) + if ((u64) stat->size > MAX_NON_LFS) return -EOVERFLOW; if (clear_user(ubuf, sizeof(*ubuf))) @@ -243,8 +243,7 @@ return -ENOMEM; if (old_prot) - if (copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE)) - return -EFAULT; + copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE); down_write(¤t->mm->mmap_sem); { @@ -837,8 +836,9 @@ } } + size = FDS_BYTES(n); ret = -EINVAL; - if (n < 0) + if (n < 0 || size < n) goto out_nofds; if (n > current->files->max_fdset) @@ -850,7 +850,6 @@ * long-words. */ ret = -ENOMEM; - size = FDS_BYTES(n); bits = kmalloc(6 * size, GFP_KERNEL); if (!bits) goto out_nofds; @@ -928,8 +927,7 @@ static struct iovec * get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) { - int i; - u32 buf, len; + u32 i, buf, len; struct iovec *ivp, *iov; /* Get the "struct iovec" from user memory */ @@ -1005,77 +1003,6 @@ return ret; } -#define RLIM_INFINITY32 0x7fffffff -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - int rlim_cur; - int rlim_max; -}; - -extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim) -{ - mm_segment_t old_fs = get_fs(); - struct rlimit r; - int ret; - - set_fs(KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur); - ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max); - } - return ret; -} - -asmlinkage long -sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim) -{ - mm_segment_t old_fs = get_fs(); - struct rlimit r; - int ret; - - set_fs(KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - if (r.rlim_cur >= 0xffffffff) - r.rlim_cur = 0xffffffff; - if (r.rlim_max >= 0xffffffff) - r.rlim_max = 0xffffffff; - ret = put_user(r.rlim_cur, &rlim->rlim_cur); - ret |= put_user(r.rlim_max, &rlim->rlim_max); - } - return ret; -} - -extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs(); - - if (resource >= RLIM_NLIMITS) - return -EINVAL; - if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - if (r.rlim_cur == RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max == RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs(KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs(old_fs); - return ret; -} - /* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * @@ -1648,19 +1575,35 @@ return err; } +extern int sem_ctls[]; +#define sc_semopm (sem_ctls[2]) + static long -semtimedop32(int semid, struct sembuf *tsems, int nsems, - const struct compat_timespec *timeout32) +semtimedop32(int semid, struct sembuf *tsops, int nsops, + struct compat_timespec *timeout32) { struct timespec t; - if (get_user (t.tv_sec, &timeout32->tv_sec) || - get_user (t.tv_nsec, &timeout32->tv_nsec)) + mm_segment_t oldfs; + long ret; + + /* parameter checking precedence should mirror sys_semtimedop() */ + if (nsops < 1 || semid < 0) + return -EINVAL; + if (nsops > sc_semopm) + return -E2BIG; + if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) || + get_compat_timespec(&t, timeout32)) return -EFAULT; - return sys_semtimedop(semid, tsems, nsems, &t); + + oldfs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_semtimedop(semid, tsops, nsops, &t); + set_fs(oldfs); + return ret; } asmlinkage long -sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) +sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth) { int version; @@ -1668,12 +1611,15 @@ call &= 0xffff; switch (call) { + case SEMTIMEDOP: + if (fifth) + return semtimedop32(first, (struct sembuf *)AA(ptr), + second, (struct compat_timespec *)AA(fifth)); + /* else fall through for normal semop() */ case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL); - case SEMTIMEDOP: - return semtimedop32(first, (struct sembuf *)AA(ptr), second, - (const struct compat_timespec *)AA(fifth)); + return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, + NULL); case SEMGET: return sys_semget(first, second, third); case SEMCTL: @@ -1724,98 +1670,10 @@ return i; } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - int ru_maxrss; - int ru_ixrss; - int ru_idrss; - int ru_isrss; - int ru_minflt; - int ru_majflt; - int ru_nswap; - int ru_inblock; - int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; - int ru_nsignals; - int ru_nvcsw; - int ru_nivcsw; -}; - -static int -put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru))) - return -EFAULT; - - err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - -asmlinkage long -sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs(old_fs); - if (put_rusage(ru, &r)) - return -EFAULT; - if (stat_addr && put_user(status, stat_addr)) - return -EFAULT; - return ret; - } -} - asmlinkage long sys32_waitpid (int pid, unsigned int *stat_addr, int options) { - return sys32_wait4(pid, stat_addr, options, NULL); -} - - -extern asmlinkage long sys_getrusage (int who, struct rusage *ru); - -asmlinkage long -sys32_getrusage (int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs(old_fs); - if (put_rusage (ru, &r)) - return -EFAULT; - return ret; + return compat_sys_wait4(pid, stat_addr, options, NULL); } static unsigned int @@ -2211,7 +2069,7 @@ ret = -EIO; break; } - for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { put_user(getreg(child, i), (unsigned int *) A(data)); data += sizeof(int); } @@ -2223,7 +2081,7 @@ ret = -EIO; break; } - for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { get_user(tmp, (unsigned int *) A(data)); putreg(child, i, tmp); data += sizeof(int); @@ -2299,7 +2157,7 @@ return(-EINVAL); /* Trying to gain more privileges? */ asm volatile ("mov %0=ar.eflag ;;" : "=r"(old)); - if (level > ((old >> 12) & 3)) { + if ((unsigned int) level > ((old >> 12) & 3)) { if (!capable(CAP_SYS_RAWIO)) return -EPERM; } diff -urN linux-2.5.69-bk6/arch/ia64/kernel/Makefile linux-2.5.69-bk7/arch/ia64/kernel/Makefile --- linux-2.5.69-bk6/arch/ia64/kernel/Makefile 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -11,6 +11,8 @@ obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_FSYS) += fsys.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o +obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o +obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o diff -urN linux-2.5.69-bk6/arch/ia64/kernel/acpi-ext.c linux-2.5.69-bk7/arch/ia64/kernel/acpi-ext.c --- linux-2.5.69-bk6/arch/ia64/kernel/acpi-ext.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/acpi-ext.c 2003-05-12 04:43:29.000000000 -0700 @@ -3,69 +3,99 @@ * * Copyright (C) 2003 Hewlett-Packard * Copyright (C) Alex Williamson + * Copyright (C) Bjorn Helgaas * - * Vendor specific extensions to ACPI. These are used by both - * HP and NEC. + * Vendor specific extensions to ACPI. */ #include +#include #include #include #include #include -/* - * Note: Strictly speaking, this is only needed for HP and NEC machines. - * However, NEC machines identify themselves as DIG-compliant, so there is - * no easy way to #ifdef this out. - */ +struct acpi_vendor_descriptor { + u8 guid_id; + efi_guid_t guid; +}; + +struct acpi_vendor_info { + struct acpi_vendor_descriptor *descriptor; + u8 *data; + u32 length; +}; + acpi_status -hp_acpi_csr_space (acpi_handle obj, u64 *csr_base, u64 *csr_length) +acpi_vendor_resource_match(struct acpi_resource *resource, void *context) { - int i, offset = 0; - acpi_status status; - struct acpi_buffer buf; - struct acpi_resource_vendor *res; - struct acpi_hp_vendor_long *hp_res; - efi_guid_t vendor_guid; - - *csr_base = 0; - *csr_length = 0; - - status = acpi_get_crs(obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); - return status; - } - - res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); - if (!res) { - printk(KERN_ERR PREFIX "Failed to find config space for device\n"); - acpi_dispose_crs(&buf); + struct acpi_vendor_info *info = (struct acpi_vendor_info *) context; + struct acpi_resource_vendor *vendor; + struct acpi_vendor_descriptor *descriptor; + u32 length; + + if (resource->id != ACPI_RSTYPE_VENDOR) + return AE_OK; + + vendor = (struct acpi_resource_vendor *) &resource->data; + descriptor = (struct acpi_vendor_descriptor *) vendor->reserved; + if (vendor->length <= sizeof(*info->descriptor) || + descriptor->guid_id != info->descriptor->guid_id || + efi_guidcmp(descriptor->guid, info->descriptor->guid)) + return AE_OK; + + length = vendor->length - sizeof(struct acpi_vendor_descriptor); + info->data = acpi_os_allocate(length); + if (!info->data) + return AE_NO_MEMORY; + + memcpy(info->data, vendor->reserved + sizeof(struct acpi_vendor_descriptor), length); + info->length = length; + return AE_CTRL_TERMINATE; +} + +acpi_status +acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id, + u8 **data, u32 *length) +{ + struct acpi_vendor_info info; + + info.descriptor = id; + info.data = 0; + + acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info); + if (!info.data) return AE_NOT_FOUND; - } - hp_res = (struct acpi_hp_vendor_long *)(res->reserved); + *data = info.data; + *length = info.length; + return AE_OK; +} + +struct acpi_vendor_descriptor hp_ccsr_descriptor = { + .guid_id = 2, + .guid = EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) +}; + +acpi_status +hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) +{ + acpi_status status; + u8 *data; + u32 length; + int i; + + status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length); - if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { - printk(KERN_ERR PREFIX "Unknown Vendor data\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); - if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { - printk(KERN_ERR PREFIX "Vendor GUID does not match\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - for (i = 0 ; i < 8 ; i++) { - *csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8)); - *csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8)); - } + if (ACPI_FAILURE(status) || length != 16) + return AE_NOT_FOUND; + + memcpy(csr_base, data, sizeof(*csr_base)); + memcpy(csr_length, data + 8, sizeof(*csr_length)); + acpi_os_free(data); - acpi_dispose_crs(&buf); return AE_OK; } + +EXPORT_SYMBOL(hp_acpi_csr_space); diff -urN linux-2.5.69-bk6/arch/ia64/kernel/acpi.c linux-2.5.69-bk7/arch/ia64/kernel/acpi.c --- linux-2.5.69-bk6/arch/ia64/kernel/acpi.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/acpi.c 2003-05-12 04:43:29.000000000 -0700 @@ -115,134 +115,6 @@ #endif } -#ifdef CONFIG_ACPI - -/** - * acpi_get_crs - Return the current resource settings for a device - * obj: A handle for this device - * buf: A buffer to be populated by this call. - * - * Pass a valid handle, typically obtained by walking the namespace and a - * pointer to an allocated buffer, and this function will fill in the buffer - * with a list of acpi_resource structures. - */ -acpi_status -acpi_get_crs (acpi_handle obj, struct acpi_buffer *buf) -{ - acpi_status result; - buf->length = 0; - buf->pointer = NULL; - - result = acpi_get_current_resources(obj, buf); - if (result != AE_BUFFER_OVERFLOW) - return result; - buf->pointer = kmalloc(buf->length, GFP_KERNEL); - if (!buf->pointer) - return -ENOMEM; - - return acpi_get_current_resources(obj, buf); -} - -struct acpi_resource * -acpi_get_crs_next (struct acpi_buffer *buf, int *offset) -{ - struct acpi_resource *res; - - if (*offset >= buf->length) - return NULL; - - res = buf->pointer + *offset; - *offset += res->length; - return res; -} - -union acpi_resource_data * -acpi_get_crs_type (struct acpi_buffer *buf, int *offset, int type) -{ - for (;;) { - struct acpi_resource *res = acpi_get_crs_next(buf, offset); - if (!res) - return NULL; - if (res->id == type) - return &res->data; - } -} - -void -acpi_dispose_crs (struct acpi_buffer *buf) -{ - kfree(buf->pointer); -} - -void -acpi_get_crs_addr (struct acpi_buffer *buf, int type, u64 *base, u64 *size, u64 *tra) -{ - int offset = 0; - struct acpi_resource_address16 *addr16; - struct acpi_resource_address32 *addr32; - struct acpi_resource_address64 *addr64; - - for (;;) { - struct acpi_resource *res = acpi_get_crs_next(buf, &offset); - if (!res) - return; - switch (res->id) { - case ACPI_RSTYPE_ADDRESS16: - addr16 = (struct acpi_resource_address16 *) &res->data; - - if (type == addr16->resource_type) { - *base = addr16->min_address_range; - *size = addr16->address_length; - *tra = addr16->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_ADDRESS32: - addr32 = (struct acpi_resource_address32 *) &res->data; - if (type == addr32->resource_type) { - *base = addr32->min_address_range; - *size = addr32->address_length; - *tra = addr32->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_ADDRESS64: - addr64 = (struct acpi_resource_address64 *) &res->data; - if (type == addr64->resource_type) { - *base = addr64->min_address_range; - *size = addr64->address_length; - *tra = addr64->address_translation_offset; - return; - } - break; - } - } -} - -int -acpi_get_addr_space(void *obj, u8 type, u64 *base, u64 *length, u64 *tra) -{ - acpi_status status; - struct acpi_buffer buf; - - *base = 0; - *length = 0; - *tra = 0; - - status = acpi_get_crs((acpi_handle)obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); - return status; - } - - acpi_get_crs_addr(&buf, type, base, length, tra); - - acpi_dispose_crs(&buf); - - return AE_OK; -} -#endif /* CONFIG_ACPI */ - #ifdef CONFIG_ACPI_BOOT #define ACPI_MAX_PLATFORM_INTERRUPTS 256 @@ -324,7 +196,8 @@ printk(" enabled"); #ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid; - if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus]) + if (hard_smp_processor_id() + == (unsigned int) smp_boot_data.cpu_phys_id[total_cpus]) printk(" (BSP)"); #endif } @@ -918,8 +791,7 @@ return 0; /* Turn it on */ - vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL); + vector = iosapic_register_intr (gsi, polarity, trigger); return vector; } diff -urN linux-2.5.69-bk6/arch/ia64/kernel/brl_emu.c linux-2.5.69-bk7/arch/ia64/kernel/brl_emu.c --- linux-2.5.69-bk6/arch/ia64/kernel/brl_emu.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/brl_emu.c 2003-05-12 04:43:29.000000000 -0700 @@ -59,7 +59,7 @@ unsigned long next_ip; struct siginfo siginfo; struct illegal_op_return rv; - int tmp_taken, unimplemented_address; + long tmp_taken, unimplemented_address; rv.fkt = (unsigned long) -1; diff -urN linux-2.5.69-bk6/arch/ia64/kernel/efi.c linux-2.5.69-bk7/arch/ia64/kernel/efi.c --- linux-2.5.69-bk6/arch/ia64/kernel/efi.c 2003-05-04 16:52:59.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/efi.c 2003-05-12 04:43:29.000000000 -0700 @@ -203,16 +203,16 @@ STUB_RESET_SYSTEM(virt, ) void -efi_gettimeofday (struct timeval *tv) +efi_gettimeofday (struct timespec *ts) { efi_time_t tm; - memset(tv, 0, sizeof(tv)); + memset(ts, 0, sizeof(ts)); if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS) return; - tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); - tv->tv_usec = tm.nanosecond / 1000; + ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); + ts->tv_nsec = tm.nanosecond; } static int @@ -512,7 +512,7 @@ /* Show what we know for posterity */ c16 = __va(efi.systab->fw_vendor); if (c16) { - for (i = 0;i < sizeof(vendor) && *c16; ++i) + for (i = 0;i < (int) sizeof(vendor) && *c16; ++i) vendor[i] = *c16++; vendor[i] = '\0'; } @@ -520,7 +520,7 @@ printk(KERN_INFO "EFI v%u.%.02u by %s:", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - for (i = 0; i < efi.systab->nr_tables; i++) { + for (i = 0; i < (int) efi.systab->nr_tables; i++) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { efi.mps = __va(config_tables[i].table); printk(" MPS=0x%lx", config_tables[i].table); diff -urN linux-2.5.69-bk6/arch/ia64/kernel/efivars.c linux-2.5.69-bk7/arch/ia64/kernel/efivars.c --- linux-2.5.69-bk6/arch/ia64/kernel/efivars.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/efivars.c 2003-05-12 04:43:29.000000000 -0700 @@ -138,8 +138,7 @@ static inline unsigned long utf8_strsize(efi_char16_t *data, unsigned long maxlength) { - return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * - sizeof(efi_char16_t); + return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t); } @@ -170,8 +169,7 @@ efi_guid_t *vendor_guid) { - int i, short_name_size = variable_name_size / - sizeof(efi_char16_t) + 38; + int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; char *short_name; efivar_entry_t *new_efivar; @@ -192,7 +190,7 @@ /* Convert Unicode to normal chars (assume top bits are 0), ala UTF-8 */ - for (i=0; i EXPORT_SYMBOL_NOVERS(__down); @@ -56,6 +57,12 @@ #include EXPORT_SYMBOL(clear_page); +#ifdef CONFIG_VIRTUAL_MEM_MAP +#include +EXPORT_SYMBOL(vmalloc_end); +EXPORT_SYMBOL(ia64_pfn_valid); +#endif + #include EXPORT_SYMBOL(cpu_info__per_cpu); EXPORT_SYMBOL(kernel_thread); @@ -161,3 +168,11 @@ EXPORT_SYMBOL(unw_access_fr); EXPORT_SYMBOL(unw_access_ar); EXPORT_SYMBOL(unw_access_pr); + +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +extern void ia64_spinlock_contention_pre3_4 (void); +EXPORT_SYMBOL(ia64_spinlock_contention_pre3_4); +#else +extern void ia64_spinlock_contention (void); +EXPORT_SYMBOL(ia64_spinlock_contention); +#endif diff -urN linux-2.5.69-bk6/arch/ia64/kernel/iosapic.c linux-2.5.69-bk7/arch/ia64/kernel/iosapic.c --- linux-2.5.69-bk6/arch/ia64/kernel/iosapic.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/iosapic.c 2003-05-12 04:43:29.000000000 -0700 @@ -581,9 +581,8 @@ register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", - isa_irq, gsi, - polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level", - dest, vector); + isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low", + trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -635,7 +634,6 @@ (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); if ((gsi_base == 0) && pcat_compat) { - /* * Map the legacy ISA devices into the IOSAPIC data. Some of these may * get reprogrammed later on with data from the ACPI Interrupt Source @@ -646,20 +644,11 @@ } } -static void __init -fixup_vector (int vector, unsigned int gsi, const char *pci_id) +void +iosapic_enable_intr (unsigned int vector) { - struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; - irq_desc_t *idesc; unsigned int dest; - idesc = irq_desc(vector); - if (idesc->handler != irq_type) { - if (idesc->handler != &no_irq_type) - printk(KERN_INFO "IOSAPIC: changing vector %d from %s to %s\n", - vector, idesc->handler->typename, irq_type->typename); - idesc->handler = irq_type; - } #ifdef CONFIG_SMP /* * For platforms that do not support interrupt redirect via the XTP interface, we @@ -687,10 +676,12 @@ #endif set_rte(vector, dest); - printk(KERN_INFO "IOSAPIC: %s -> GSI 0x%x -> CPU 0x%04x vector %d\n", - pci_id, gsi, dest, vector); + printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n", + vector, dest); } +#ifdef CONFIG_ACPI_PCI + void __init iosapic_parse_prt (void) { @@ -699,6 +690,8 @@ unsigned int gsi; int vector; char pci_id[16]; + struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; + irq_desc_t *idesc; list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -711,6 +704,9 @@ vector = gsi_to_vector(gsi); if (vector < 0) { + if (find_iosapic(gsi) < 0) + continue; + /* allocate a vector for this interrupt line */ if (pcat_compat && (gsi < 16)) vector = isa_irq_to_vector(gsi); @@ -718,11 +714,22 @@ /* new GSI; allocate a vector for it */ vector = ia64_alloc_vector(); - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, + IOSAPIC_LEVEL); } snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); - fixup_vector(vector, gsi, pci_id); + /* + * If vector was previously initialized to a different + * handler, re-initialize. + */ + idesc = irq_desc(vector); + if (idesc->handler != irq_type) + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, + IOSAPIC_LEVEL); + } } + +#endif /* CONFIG_ACPI */ diff -urN linux-2.5.69-bk6/arch/ia64/kernel/irq.c linux-2.5.69-bk7/arch/ia64/kernel/irq.c --- linux-2.5.69-bk6/arch/ia64/kernel/irq.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/irq.c 2003-05-12 04:43:29.000000000 -0700 @@ -18,7 +18,6 @@ */ #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include @@ -50,7 +50,7 @@ * Linux has a controller-independent x86 interrupt architecture. * every controller has a 'controller-template', that is used * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate + * interrupt source is transparently wired to the appropriate * controller. Thus drivers need not be aware of the * interrupt-controller. * @@ -91,7 +91,8 @@ * Special irq handlers. */ -void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ return IRQ_NONE; } /* * Generic no controller code @@ -141,9 +142,11 @@ }; atomic_t irq_err_count; -#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) +#ifdef CONFIG_X86_IO_APIC +#ifdef APIC_MISMATCH_DEBUG atomic_t irq_mis_count; #endif +#endif /* * Generic, controller-independent functions: @@ -178,9 +181,10 @@ #endif seq_printf(p, " %14s", idesc->handler->typename); seq_printf(p, " %s", action->name); + for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); - + seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&idesc->lock, flags); @@ -190,17 +194,19 @@ if (cpu_online(j)) seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); -#if defined(CONFIG_SMP) && defined(CONFIG_X86) +#if CONFIG_X86_LOCAL_APIC seq_puts(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - seq_printf(p, "%10u ", apic_timer_irqs[j]); + seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); -#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) +#ifdef CONFIG_X86_IO_APIC +#ifdef APIC_MISMATCH_DEBUG seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); #endif +#endif return 0; } @@ -219,21 +225,46 @@ * waste of time and is not what some drivers would * prefer. */ -int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) +int handle_IRQ_event(unsigned int irq, + struct pt_regs *regs, struct irqaction *action) { int status = 1; /* Force the "do bottom halves" bit */ + int retval = 0; + struct irqaction *first_action = action; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; - action->handler(irq, action->dev_id, regs); + retval |= action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); + if (retval != 1) { + static int count = 100; + if (count) { + count--; + if (retval) { + printk("irq event %d: bogus retval mask %x\n", + irq, retval); + } else { + printk("irq %d: nobody cared!\n", irq); + } + dump_stack(); + printk("handlers:\n"); + action = first_action; + do { + printk("[<%p>]", action->handler); + print_symbol(" (%s)", + (unsigned long)action->handler); + printk("\n"); + action = action->next; + } while (action); + } + } return status; } @@ -455,7 +486,7 @@ */ int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) @@ -482,7 +513,7 @@ return -EINVAL; action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); + kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) return -ENOMEM; @@ -511,10 +542,7 @@ * does not return until any executing interrupts for this IRQ * have completed. * - * This function may be called from interrupt context. - * - * Bugs: Attempting to free an irq in a handler for the same irq hangs - * the machine. + * This function must not be called from interrupt context. */ void free_irq(unsigned int irq, void *dev_id) @@ -545,11 +573,8 @@ } spin_unlock_irqrestore(&desc->lock,flags); -#ifdef CONFIG_SMP /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - synchronize_irq(irq); -#endif + synchronize_irq(irq); kfree(action); return; } @@ -664,7 +689,6 @@ * only return ISA irq numbers - just so that we reset them * all to a known state. */ - unsigned int probe_irq_mask(unsigned long val) { int i; @@ -705,7 +729,7 @@ * The interrupt probe logic state is returned to its previous * value. * - * BUGS: When used in a module (which arguably shouldnt happen) + * BUGS: When used in a module (which arguably shouldn't happen) * nothing prevents two IRQ probe callers from overlapping. The * results of this are non-optimal. */ @@ -748,6 +772,8 @@ struct irqaction *old, **p; irq_desc_t *desc = irq_desc(irq); + if (desc->handler == &no_irq_type) + return -ENOSYS; /* * Some drivers like serial.c use request_irq() heavily, * so we have to be careful not to interfere with a @@ -808,11 +834,11 @@ #define HEX_DIGITS 8 -static int parse_hex_value (const char *buffer, unsigned long count, unsigned long *ret) +static unsigned int parse_hex_value (const char *buffer, + unsigned long count, unsigned long *ret) { unsigned char hexnum [HEX_DIGITS]; - unsigned long value; - int i; + unsigned long value, i; if (!count) return -EINVAL; @@ -950,12 +976,13 @@ #if CONFIG_SMP { struct proc_dir_entry *entry; + /* create /proc/irq/1234/smp_affinity */ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); if (entry) { entry->nlink = 1; - entry->data = (void *)(unsigned long)irq; + entry->data = (void *)(long)irq; entry->read_proc = irq_affinity_read_proc; entry->write_proc = irq_affinity_write_proc; } diff -urN linux-2.5.69-bk6/arch/ia64/kernel/irq_ia64.c linux-2.5.69-bk7/arch/ia64/kernel/irq_ia64.c --- linux-2.5.69-bk6/arch/ia64/kernel/irq_ia64.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/irq_ia64.c 2003-05-12 04:43:29.000000000 -0700 @@ -145,7 +145,7 @@ } #ifdef CONFIG_SMP -extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs); static struct irqaction ipi_irqaction = { .handler = handle_IPI, diff -urN linux-2.5.69-bk6/arch/ia64/kernel/machvec.c linux-2.5.69-bk7/arch/ia64/kernel/machvec.c --- linux-2.5.69-bk6/arch/ia64/kernel/machvec.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/machvec.c 2003-05-12 04:43:29.000000000 -0700 @@ -1,12 +1,14 @@ #include +#include + #ifdef CONFIG_IA64_GENERIC #include #include -#include #include +#include struct ia64_machine_vector ia64_mv; @@ -43,3 +45,9 @@ machvec_noop (void) { } + +void +machvec_memory_fence (void) +{ + mb(); +} diff -urN linux-2.5.69-bk6/arch/ia64/kernel/mca.c linux-2.5.69-bk7/arch/ia64/kernel/mca.c --- linux-2.5.69-bk6/arch/ia64/kernel/mca.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/mca.c 2003-05-12 04:43:29.000000000 -0700 @@ -3,6 +3,9 @@ * Purpose: Generic MCA handling layer * * Updated for latest kernel + * Copyright (C) 2003 Hewlett-Packard Co + * David Mosberger-Tang + * * Copyright (C) 2002 Dell Computer Corporation * Copyright (C) Matt Domsch (Matt_Domsch@dell.com) * @@ -18,6 +21,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * + * 03/04/15 D. Mosberger Added INIT backtrace support. * 02/03/25 M. Domsch GUID cleanups * * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU @@ -39,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +52,7 @@ #include #include +#include #include #include #include @@ -139,7 +145,7 @@ /* Get the MCA error record */ if (!ia64_log_get(sal_info_type, (prfunc_t)printk)) - return platform_err; // no record retrieved + return platform_err; /* no record retrieved */ /* TODO: * 1. analyze error logs to determine recoverability @@ -166,7 +172,7 @@ } -void +irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n", @@ -174,20 +180,186 @@ /* Get the CMC error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0); + return IRQ_HANDLED; +} + +static void +show_min_state (pal_min_state_area_t *minstate) +{ + u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri; + u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri; + + printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits); + printk("pr\t\t%016lx\n", minstate->pmsa_pr); + printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0); + printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc); + printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip); + printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr); + printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs); + printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip); + printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr); + printk("xfs\t\t%016lx\n", minstate->pmsa_xfs); + printk("b1\t\t%016lx ", minstate->pmsa_br1); + print_symbol("%s\n", minstate->pmsa_br1); + + printk("\nstatic registers r0-r15:\n"); + printk(" r0- 3 %016lx %016lx %016lx %016lx\n", + 0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]); + printk(" r4- 7 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[3], minstate->pmsa_gr[4], + minstate->pmsa_gr[5], minstate->pmsa_gr[6]); + printk(" r8-11 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[7], minstate->pmsa_gr[8], + minstate->pmsa_gr[9], minstate->pmsa_gr[10]); + printk("r12-15 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[11], minstate->pmsa_gr[12], + minstate->pmsa_gr[13], minstate->pmsa_gr[14]); + + printk("\nbank 0:\n"); + printk("r16-19 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1], + minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]); + printk("r20-23 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5], + minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]); + printk("r24-27 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9], + minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]); + printk("r28-31 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13], + minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]); + + printk("\nbank 1:\n"); + printk("r16-19 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1], + minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]); + printk("r20-23 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5], + minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]); + printk("r24-27 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9], + minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]); + printk("r28-31 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13], + minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]); +} + +static void +fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw) +{ + u64 *dst_banked, *src_banked, bit, shift, nat_bits; + int i; + + /* + * First, update the pt-regs and switch-stack structures with the contents stored + * in the min-state area: + */ + if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) { + pt->cr_ipsr = ms->pmsa_xpsr; + pt->cr_iip = ms->pmsa_xip; + pt->cr_ifs = ms->pmsa_xfs; + } else { + pt->cr_ipsr = ms->pmsa_ipsr; + pt->cr_iip = ms->pmsa_iip; + pt->cr_ifs = ms->pmsa_ifs; + } + pt->ar_rsc = ms->pmsa_rsc; + pt->pr = ms->pmsa_pr; + pt->r1 = ms->pmsa_gr[0]; + pt->r2 = ms->pmsa_gr[1]; + pt->r3 = ms->pmsa_gr[2]; + sw->r4 = ms->pmsa_gr[3]; + sw->r5 = ms->pmsa_gr[4]; + sw->r6 = ms->pmsa_gr[5]; + sw->r7 = ms->pmsa_gr[6]; + pt->r8 = ms->pmsa_gr[7]; + pt->r9 = ms->pmsa_gr[8]; + pt->r10 = ms->pmsa_gr[9]; + pt->r11 = ms->pmsa_gr[10]; + pt->r12 = ms->pmsa_gr[11]; + pt->r13 = ms->pmsa_gr[12]; + pt->r14 = ms->pmsa_gr[13]; + pt->r15 = ms->pmsa_gr[14]; + dst_banked = &pt->r16; /* r16-r31 are contiguous in struct pt_regs */ + src_banked = ms->pmsa_bank1_gr; + for (i = 0; i < 16; ++i) + dst_banked[i] = src_banked[i]; + pt->b0 = ms->pmsa_br0; + sw->b1 = ms->pmsa_br1; + + /* construct the NaT bits for the pt-regs structure: */ +# define PUT_NAT_BIT(dst, addr) \ + do { \ + bit = nat_bits & 1; nat_bits >>= 1; \ + shift = ((unsigned long) addr >> 3) & 0x3f; \ + dst = ((dst) & ~(1UL << shift)) | (bit << shift); \ + } while (0) + + /* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */ + shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f; + nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift)); + + PUT_NAT_BIT(sw->caller_unat, &pt->r1); + PUT_NAT_BIT(sw->caller_unat, &pt->r2); + PUT_NAT_BIT(sw->caller_unat, &pt->r3); + PUT_NAT_BIT(sw->ar_unat, &sw->r4); + PUT_NAT_BIT(sw->ar_unat, &sw->r5); + PUT_NAT_BIT(sw->ar_unat, &sw->r6); + PUT_NAT_BIT(sw->ar_unat, &sw->r7); + PUT_NAT_BIT(sw->caller_unat, &pt->r8); PUT_NAT_BIT(sw->caller_unat, &pt->r9); + PUT_NAT_BIT(sw->caller_unat, &pt->r10); PUT_NAT_BIT(sw->caller_unat, &pt->r11); + PUT_NAT_BIT(sw->caller_unat, &pt->r12); PUT_NAT_BIT(sw->caller_unat, &pt->r13); + PUT_NAT_BIT(sw->caller_unat, &pt->r14); PUT_NAT_BIT(sw->caller_unat, &pt->r15); + nat_bits >>= 16; /* skip over bank0 NaT bits */ + PUT_NAT_BIT(sw->caller_unat, &pt->r16); PUT_NAT_BIT(sw->caller_unat, &pt->r17); + PUT_NAT_BIT(sw->caller_unat, &pt->r18); PUT_NAT_BIT(sw->caller_unat, &pt->r19); + PUT_NAT_BIT(sw->caller_unat, &pt->r20); PUT_NAT_BIT(sw->caller_unat, &pt->r21); + PUT_NAT_BIT(sw->caller_unat, &pt->r22); PUT_NAT_BIT(sw->caller_unat, &pt->r23); + PUT_NAT_BIT(sw->caller_unat, &pt->r24); PUT_NAT_BIT(sw->caller_unat, &pt->r25); + PUT_NAT_BIT(sw->caller_unat, &pt->r26); PUT_NAT_BIT(sw->caller_unat, &pt->r27); + PUT_NAT_BIT(sw->caller_unat, &pt->r28); PUT_NAT_BIT(sw->caller_unat, &pt->r29); + PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31); } -/* - * This routine will be used to deal with platform specific handling - * of the init, i.e. drop into the kernel debugger on server machine, - * or if the processor is part of some parallel machine without a - * console, then we would call the appropriate debug hooks here. - */ void -init_handler_platform (struct pt_regs *regs) +init_handler_platform (sal_log_processor_info_t *proc_ptr, + struct pt_regs *pt, struct switch_stack *sw) { + struct unw_frame_info info; + /* if a kernel debugger is available call it here else just dump the registers */ - show_regs(regs); /* dump the state info */ + /* + * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be + * generated via the BMC's command-line interface, but since the console is on the + * same serial line, the user will need some time to switch out of the BMC before + * the dump begins. + */ + printk("Delaying for 5 seconds...\n"); + udelay(5*1000000); + show_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area); + + printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm); + fetch_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area, pt, sw); + unw_init_from_interruption(&info, current, pt, sw); + ia64_do_show_stack(&info, NULL); + + if (!tasklist_lock.write_lock) + read_lock(&tasklist_lock); + { + struct task_struct *g, *t; + do_each_thread (g, t) { + if (t == current) + continue; + + printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); + show_stack(t); + } while_each_thread (g, t); + } + if (!tasklist_lock.write_lock) + read_unlock(&tasklist_lock); + + printk("\nINIT dump complete. Please reboot now.\n"); while (1); /* hang city if no debugger */ } @@ -263,7 +435,6 @@ /* * routine to process and prepare to dump min_state_save * information for debugging purposes. - * */ void ia64_process_min_state_save (pal_min_state_area_t *pmss) @@ -272,8 +443,6 @@ u64 *tpmss_ptr = (u64 *)pmss; u64 *return_min_state_ptr = ia64_mca_min_state_save_info; - /* dump out the min_state_area information */ - for (i=0;i>=1; } p += sprintf(p, "\n\tLoad hints : "); for(k=0; k < 8; k++ ) { - if ( cci.pcci_ld_hints & 0x1) p += sprintf(p, "[%s]", cache_ld_hints[k]); + if (cci.pcci_ld_hints & 0x1) + p += sprintf(p, "[%s]", cache_ld_hints[k]); cci.pcci_ld_hints >>=1; } - p += sprintf(p, "\n\tAlias boundary : %d byte(s)\n" \ - "\tTag LSB : %d\n" \ - "\tTag MSB : %d\n", - 1<0 ; j--) { @@ -379,15 +380,14 @@ continue; } - p += sprintf(p, "\n%s Translation Cache Level %d:\n" \ - "\tHash sets : %d\n" \ - "\tAssociativity : %d\n" \ - "\tNumber of entries : %d\n" \ - "\tFlags : ", - cache_types[j+tc_info.tc_unified], i+1, - tc_info.tc_num_sets, - tc_info.tc_associativity, - tc_info.tc_num_entries); + p += sprintf(p, + "\n%s Translation Cache Level %d:\n" + "\tHash sets : %d\n" + "\tAssociativity : %d\n" + "\tNumber of entries : %d\n" + "\tFlags : ", + cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets, + tc_info.tc_associativity, tc_info.tc_num_entries); if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized "); if (tc_info.tc_unified) p += sprintf(p, "Unified "); @@ -436,17 +436,18 @@ if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0; - p += sprintf(p, "RSE stacked physical registers : %ld\n" \ - "RSE load/store hints : %ld (%s)\n", - phys_stacked, - hints.ph_data, - hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)"); - - if (ia64_pal_debug_info(&iregs, &dregs)) return 0; - - p += sprintf(p, "Instruction debug register pairs : %ld\n" \ - "Data debug register pairs : %ld\n", - iregs, dregs); + p += sprintf(p, + "RSE stacked physical registers : %ld\n" + "RSE load/store hints : %ld (%s)\n", + phys_stacked, hints.ph_data, + hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)"); + + if (ia64_pal_debug_info(&iregs, &dregs)) + return 0; + + p += sprintf(p, + "Instruction debug register pairs : %ld\n" + "Data debug register pairs : %ld\n", iregs, dregs); return p - page; } @@ -563,26 +564,21 @@ */ if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0; - p += sprintf(p, "PAL_vendor : 0x%02x (min=0x%02x)\n" \ - "PAL_A : %x.%x.%x (min=%x.%x.%x)\n" \ - "PAL_B : %x.%x.%x (min=%x.%x.%x)\n", - cur_ver.pal_version_s.pv_pal_vendor, - min_ver.pal_version_s.pv_pal_vendor, - - cur_ver.pal_version_s.pv_pal_a_model>>4, - cur_ver.pal_version_s.pv_pal_a_model&0xf, - cur_ver.pal_version_s.pv_pal_a_rev, - min_ver.pal_version_s.pv_pal_a_model>>4, - min_ver.pal_version_s.pv_pal_a_model&0xf, - min_ver.pal_version_s.pv_pal_a_rev, - - cur_ver.pal_version_s.pv_pal_b_model>>4, - cur_ver.pal_version_s.pv_pal_b_model&0xf, - cur_ver.pal_version_s.pv_pal_b_rev, - min_ver.pal_version_s.pv_pal_b_model>>4, - min_ver.pal_version_s.pv_pal_b_model&0xf, - min_ver.pal_version_s.pv_pal_b_rev); - + p += sprintf(p, + "PAL_vendor : 0x%02x (min=0x%02x)\n" + "PAL_A : %x.%x.%x (min=%x.%x.%x)\n" + "PAL_B : %x.%x.%x (min=%x.%x.%x)\n", + cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor, + + cur_ver.pal_version_s.pv_pal_a_model>>4, + cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev, + min_ver.pal_version_s.pv_pal_a_model>>4, + min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev, + + cur_ver.pal_version_s.pv_pal_b_model>>4, + cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev, + min_ver.pal_version_s.pv_pal_b_model>>4, + min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev); return p - page; } @@ -595,26 +591,20 @@ if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0; - p += sprintf(p, "PMC/PMD pairs : %d\n" \ - "Counter width : %d bits\n" \ - "Cycle event number : %d\n" \ - "Retired event number : %d\n" \ - "Implemented PMC : ", - pm_info.pal_perf_mon_info_s.generic, - pm_info.pal_perf_mon_info_s.width, - pm_info.pal_perf_mon_info_s.cycles, - pm_info.pal_perf_mon_info_s.retired); + p += sprintf(p, + "PMC/PMD pairs : %d\n" + "Counter width : %d bits\n" + "Cycle event number : %d\n" + "Retired event number : %d\n" + "Implemented PMC : ", + pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width, + pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired); p = bitregister_process(p, pm_buffer, 256); - p += sprintf(p, "\nImplemented PMD : "); - p = bitregister_process(p, pm_buffer+4, 256); - p += sprintf(p, "\nCycles count capable : "); - p = bitregister_process(p, pm_buffer+8, 256); - p += sprintf(p, "\nRetired bundles count capable : "); #ifdef CONFIG_ITANIUM @@ -646,12 +636,11 @@ if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; - p += sprintf(p, "Processor/Clock ratio : %ld/%ld\n" \ - "Bus/Clock ratio : %ld/%ld\n" \ - "ITC/Clock ratio : %ld/%ld\n", - proc.num, proc.den, - bus.num, bus.den, - itc.num, itc.den); + p += sprintf(p, + "Processor/Clock ratio : %ld/%ld\n" + "Bus/Clock ratio : %ld/%ld\n" + "ITC/Clock ratio : %ld/%ld\n", + proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); return p - page; } @@ -665,7 +654,7 @@ u64 tr_buffer[4]; pal_vm_info_1_u_t vm_info_1; pal_vm_info_2_u_t vm_info_2; - int i, j; + u64 i, j; u64 max[3], pgm; struct ifa_reg { u64 valid:1; @@ -711,7 +700,7 @@ status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid); if (status != 0) { - printk(KERN_ERR "palinfo: pal call failed on tr[%d:%d]=%ld\n", + printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n", i, j, status); continue; } @@ -725,34 +714,29 @@ rid_reg = (struct rid_reg *)&tr_buffer[3]; pgm = -1 << (itir_reg->ps - 12); - p += sprintf(p, "%cTR%d: av=%d pv=%d dv=%d mv=%d\n" \ - "\tppn : 0x%lx\n" \ - "\tvpn : 0x%lx\n" \ - "\tps : ", - - "ID"[i], - j, - tr_valid.pal_tr_valid_s.access_rights_valid, - tr_valid.pal_tr_valid_s.priv_level_valid, - tr_valid.pal_tr_valid_s.dirty_bit_valid, - tr_valid.pal_tr_valid_s.mem_attr_valid, - (gr_reg->ppn & pgm)<< 12, - (ifa_reg->vpn & pgm)<< 12); + p += sprintf(p, + "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n" + "\tppn : 0x%lx\n" + "\tvpn : 0x%lx\n" + "\tps : ", + "ID"[i], j, + tr_valid.pal_tr_valid_s.access_rights_valid, + tr_valid.pal_tr_valid_s.priv_level_valid, + tr_valid.pal_tr_valid_s.dirty_bit_valid, + tr_valid.pal_tr_valid_s.mem_attr_valid, + (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12); p = bitvector_process(p, 1<< itir_reg->ps); - p += sprintf(p, "\n\tpl : %d\n" \ - "\tar : %d\n" \ - "\trid : %x\n" \ - "\tp : %d\n" \ - "\tma : %d\n" \ - "\td : %d\n", - gr_reg->pl, - gr_reg->ar, - rid_reg->rid, - gr_reg->p, - gr_reg->ma, - gr_reg->d); + p += sprintf(p, + "\n\tpl : %d\n" + "\tar : %d\n" + "\trid : %x\n" + "\tp : %d\n" + "\tma : %d\n" + "\td : %d\n", + gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma, + gr_reg->d); } } return p - page; @@ -776,7 +760,7 @@ { "tr_info", tr_info, } }; -#define NR_PALINFO_ENTRIES (sizeof(palinfo_entries)/sizeof(palinfo_entry_t)) +#define NR_PALINFO_ENTRIES (int) ARRAY_SIZE(palinfo_entries) /* * this array is used to keep track of the proc entries we create. This is diff -urN linux-2.5.69-bk6/arch/ia64/kernel/perfmon.c linux-2.5.69-bk7/arch/ia64/kernel/perfmon.c --- linux-2.5.69-bk6/arch/ia64/kernel/perfmon.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/perfmon.c 2003-05-12 04:43:29.000000000 -0700 @@ -2,7 +2,7 @@ * This file implements the perfmon subsystem which is used * to program the IA-64 Performance Monitoring Unit (PMU). * - * Originaly Written by Ganesh Venkitachalam, IBM Corp. + * Originally Written by Ganesh Venkitachalam, IBM Corp. * Copyright (C) 1999 Ganesh Venkitachalam * * Modifications by Stephane Eranian, Hewlett-Packard Co. @@ -224,8 +224,9 @@ unsigned int protected:1; /* allow access to creator of context only */ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int excl_idle:1; /* exclude idle task in system wide session */ + unsigned int unsecure:1; /* sp = 0 for non self-monitored task */ unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */ - unsigned int reserved:21; + unsigned int reserved:20; } pfm_context_flags_t; #define PFM_TRAP_REASON_NONE 0x0 /* default value */ @@ -278,6 +279,7 @@ #define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_excl_idle ctx_flags.excl_idle #define ctx_fl_trap_reason ctx_flags.trap_reason +#define ctx_fl_unsecure ctx_flags.unsecure /* * global information about all sessions @@ -362,8 +364,9 @@ #define PFM_CMD_IDX(cmd) (cmd) -#define PFM_CMD_IS_VALID(cmd) ((PFM_CMD_IDX(cmd) >= 0) && (PFM_CMD_IDX(cmd) < PFM_CMD_COUNT) \ - && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL) +#define PFM_CMD_IS_VALID(cmd) ((PFM_CMD_IDX(cmd) >= 0) \ + && (PFM_CMD_IDX(cmd) < (int) PFM_CMD_COUNT) \ + && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL) #define PFM_CMD_USE_PID(cmd) ((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_PID) != 0) #define PFM_CMD_READ_ARG(cmd) ((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ) != 0) @@ -646,7 +649,7 @@ /* * This function is called from pfm_destroy_context() and also from pfm_inherit() - * to explicitely remove the sampling buffer mapping from the user level address space. + * to explicitly remove the sampling buffer mapping from the user level address space. */ static int pfm_remove_smpl_mapping(struct task_struct *task) @@ -724,8 +727,7 @@ static unsigned long pfm_smpl_entry_size(unsigned long *which, unsigned long size) { - unsigned long res = 0; - int i; + unsigned long i, res = 0; for (i=0; i < size; i++, which++) res += hweight64(*which); @@ -1076,10 +1078,15 @@ * and it must be a valid CPU */ cpu = ffz(~pfx->ctx_cpu_mask); +#ifdef CONFIG_SMP if (cpu_online(cpu) == 0) { +#else + if (cpu != 0) { +#endif DBprintk(("CPU%d is not online\n", cpu)); return -EINVAL; } + /* * check for pre-existing pinning, if conflicting reject */ @@ -1225,6 +1232,7 @@ ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; + ctx->ctx_fl_unsecure = (ctx_flags & PFM_FL_UNSECURE) ? 1: 0; ctx->ctx_fl_frozen = 0; ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; @@ -1251,9 +1259,11 @@ DBprintk(("context=%p, pid=%d notify_task=%p\n", (void *)ctx, task->pid, ctx->ctx_notify_task)); - DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d\n", + DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d unsecure=%d\n", (void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, - ctx->ctx_fl_block, ctx->ctx_fl_system, ctx->ctx_fl_excl_idle)); + ctx->ctx_fl_block, ctx->ctx_fl_system, + ctx->ctx_fl_excl_idle, + ctx->ctx_fl_unsecure)); /* * when no notification is required, we can make this visible at the last moment @@ -1659,7 +1669,7 @@ if (!PMD_IS_IMPL(cnum)) goto abort_mission; /* * we can only read the register that we use. That includes - * the one we explicitely initialize AND the one we want included + * the one we explicitly initialize AND the one we want included * in the sampling buffer (smpl_regs). * * Having this restriction allows optimization in the ctxsw routine @@ -1871,7 +1881,7 @@ * if blocking, then post the semaphore. * if non-blocking, then we ensure that the task will go into * pfm_overflow_must_block() before returning to user mode. - * We cannot explicitely reset another task, it MUST always + * We cannot explicitly reset another task, it MUST always * be done by the task itself. This works for system wide because * the tool that is controlling the session is doing "self-monitoring". * @@ -1882,7 +1892,10 @@ DBprintk(("unblocking %d \n", task->pid)); up(sem); } else { + struct thread_info *info = (struct thread_info *) ((char *) task + IA64_TASK_SIZE); task->thread.pfm_ovfl_block_reset = 1; + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_RESET; + set_bit(TIF_NOTIFY_RESUME, &info->flags); } #if 0 /* @@ -2051,7 +2064,7 @@ /* * reinforce secure monitoring: cannot toggle psr.up */ - ia64_psr(regs)->sp = 1; + if (ctx->ctx_fl_unsecure == 0) ia64_psr(regs)->sp = 1; return 0; } @@ -2159,11 +2172,11 @@ * never leaves the current CPU and the state * is shared by all processes running on it */ - for (i=0; i < pmu_conf.num_ibrs; i++) { + for (i=0; i < (int) pmu_conf.num_ibrs; i++) { ia64_set_ibr(i, 0UL); } ia64_srlz_i(); - for (i=0; i < pmu_conf.num_dbrs; i++) { + for (i=0; i < (int) pmu_conf.num_dbrs; i++) { ia64_set_dbr(i, 0UL); } ia64_srlz_d(); @@ -2505,7 +2518,7 @@ /* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)} #endif }; -#define PFM_CMD_COUNT (sizeof(pfm_cmd_tab)/sizeof(pfm_cmd_desc_t)) +#define PFM_CMD_COUNT ARRAY_SIZE(pfm_cmd_tab) static int check_task_state(struct task_struct *task) @@ -2732,12 +2745,13 @@ * again */ th->pfm_ovfl_block_reset = 0; + clear_thread_flag(TIF_NOTIFY_RESUME); /* * do some sanity checks first */ if (!ctx) { - printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid); + printk(KERN_ERR "perfmon: [%d] has no PFM context\n", current->pid); return; } /* @@ -2899,15 +2913,18 @@ /* * main overflow processing routine. - * it can be called from the interrupt path or explicitely during the context switch code + * it can be called from the interrupt path or explicitly during the context switch code + * Arguments: + * mode: 0=coming from PMU interrupt, 1=coming from ctxsw + * * Return: * new value of pmc[0]. if 0x0 then unfreeze, else keep frozen */ static unsigned long -pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) +pfm_overflow_handler(int mode, struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) { - unsigned long mask; struct thread_struct *t; + unsigned long mask; unsigned long old_val; unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; int i; @@ -2998,10 +3015,10 @@ /* * check for sampling buffer * - * if present, record sample. We propagate notification ONLY when buffer - * becomes full. + * if present, record sample only when a 64-bit counter has overflowed. + * We propagate notification ONLY when buffer becomes full. */ - if(CTX_HAS_SMPL(ctx)) { + if(CTX_HAS_SMPL(ctx) && ovfl_pmds) { ret = pfm_record_sample(task, ctx, ovfl_pmds, regs); if (ret == 1) { /* @@ -3046,12 +3063,55 @@ * ctx_notify_task could already be NULL, checked in pfm_notify_user() */ if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG; } else { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG; } + /* + * we cannot block in system wide mode and we do not go + * through the PMU ctxsw code. Therefore we can generate + * the notification here. In system wide mode, the current + * task maybe different from the task controlling the session + * on this CPU, therefore owner can be different from current. + * + * In per-process mode, this function gets called from + * the interrupt handler or pfm_load_regs(). The mode argument + * tells where we are coming from. When coming from the interrupt + * handler, it is safe to notify (send signal) right here because + * we do not hold any runqueue locks needed by send_sig_info(). + * + * However when coming from ctxsw, we cannot send the signal here. + * It must be deferred until we are sure we do not hold any runqueue + * related locks. The current task maybe different from the owner + * only in UP mode. The deferral is implemented using the + * TIF_NOTIFY_RESUME mechanism. In this case, the pending work + * is checked when the task is about to leave the kernel (see + * entry.S). As of this version of perfmon, a kernel only + * task cannot be monitored in per-process mode. Therefore, + * when this function gets called from pfm_load_regs(), we know + * we have a user level task which will eventually either exit + * or leave the kernel, and thereby go through the checkpoint + * for TIF_*. + */ + if (ctx->ctx_fl_system || mode == 0) { + pfm_notify_user(ctx); + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; + } else { + struct thread_info *info; + + /* + * given that TIF_NOTIFY_RESUME is not specific to + * perfmon, we need to have a second level check to + * verify the source of the notification. + */ + task->thread.pfm_ovfl_block_reset = 1; + /* + * when coming from ctxsw, current still points to the + * previous task, therefore we must work with task and not current. + */ + info = ((struct thread_info *) ((char *) task + IA64_TASK_SIZE)); + set_bit(TIF_NOTIFY_RESUME, &info->flags); + } /* * keep the PMU frozen until either pfm_restart() or @@ -3059,7 +3119,10 @@ */ ctx->ctx_fl_frozen = 1; - DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n", + DBprintk_ovfl(("current [%d] owner [%d] mode=%d return pmc0=0x%x must_block=%ld reason=%d\n", + current->pid, + PMU_OWNER() ? PMU_OWNER()->pid : -1, + mode, ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset, ctx->ctx_fl_trap_reason)); @@ -3068,7 +3131,7 @@ return 0x1UL; } -static void +static irqreturn_t pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) { u64 pmc0; @@ -3083,7 +3146,7 @@ if (pfm_alternate_intr_handler) { (*pfm_alternate_intr_handler->handler)(irq, arg, regs); put_cpu(); - return; + return IRQ_HANDLED; } /* @@ -3108,19 +3171,21 @@ printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has " "no PFM context\n", task->pid); put_cpu(); - return; + return IRQ_HANDLED; } /* * assume PMC[0].fr = 1 at this point */ - pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs); + pmc0 = pfm_overflow_handler(0, task, ctx, pmc0, regs); /* * we can only update pmc0 when the overflow - * is for the current context. In UP the current - * task may not be the one owning the PMU + * is for the current context or we are in system + * wide mode. In UP (per-task) the current + * task may not be the one owning the PMU, + * same thing for system-wide. */ - if (task == current) { + if (task == current || ctx->ctx_fl_system) { /* * We always clear the overflow status bits and either unfreeze * or keep the PMU frozen. @@ -3134,6 +3199,7 @@ pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++; } put_cpu_no_resched(); + return IRQ_HANDLED; } /* for debug only */ @@ -3387,11 +3453,11 @@ * in the next version of perfmon. */ if (ctx->ctx_fl_using_dbreg) { - for (i=0; i < pmu_conf.num_ibrs; i++) { + for (i=0; i < (int) pmu_conf.num_ibrs; i++) { ia64_set_ibr(i, t->ibr[i]); } ia64_srlz_i(); - for (i=0; i < pmu_conf.num_dbrs; i++) { + for (i=0; i < (int) pmu_conf.num_dbrs; i++) { ia64_set_dbr(i, t->dbr[i]); } ia64_srlz_d(); @@ -3402,7 +3468,7 @@ * this path cannot be used in SMP */ if (owner == task) { - if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) + if ((unsigned int) atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) DBprintk(("invalid last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); @@ -3454,7 +3520,7 @@ * Side effect on ctx_fl_frozen is possible. */ if (t->pmc[0] & ~0x1) { - t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL); + t->pmc[0] = pfm_overflow_handler(1, task, ctx, t->pmc[0], NULL); } /* @@ -3676,7 +3742,7 @@ * */ - if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) + if ((unsigned int) atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) printk(KERN_DEBUG "perfmon: [%d] last_cpu=%d\n", task->pid, atomic_read(&ctx->ctx_last_cpu)); @@ -3754,16 +3820,20 @@ preempt_disable(); /* - * make sure child cannot mess up the monitoring session + * for secure sessions, make sure child cannot mess up + * the monitoring session. */ - ia64_psr(regs)->sp = 1; - DBprintk(("enabling psr.sp for [%d]\n", task->pid)); - + if (ctx->ctx_fl_unsecure == 0) { + ia64_psr(regs)->sp = 1; + DBprintk(("enabling psr.sp for [%d]\n", task->pid)); + } else { + DBprintk(("psr.sp=%d [%d]\n", ia64_psr(regs)->sp, task->pid)); + } /* * if there was a virtual mapping for the sampling buffer * the mapping is NOT inherited across fork() (see VM_DONTCOPY), - * so we don't have to explicitely remove it here. + * so we don't have to explicitly remove it here. * * * Part of the clearing of fields is also done in diff -urN linux-2.5.69-bk6/arch/ia64/kernel/perfmon_mckinley.h linux-2.5.69-bk7/arch/ia64/kernel/perfmon_mckinley.h --- linux-2.5.69-bk6/arch/ia64/kernel/perfmon_mckinley.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/perfmon_mckinley.h 2003-05-12 04:43:29.000000000 -0700 @@ -25,8 +25,8 @@ /* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, @@ -143,11 +143,8 @@ case 8: val8 = *val; val13 = th->pmc[13]; val14 = th->pmc[14]; - *val |= 1UL << 2; /* bit 2 must always be 1 */ check_case1 = 1; break; - case 9: *val |= 1UL << 2; /* bit 2 must always be 1 */ - break; case 13: val8 = th->pmc[8]; val13 = *val; val14 = th->pmc[14]; diff -urN linux-2.5.69-bk6/arch/ia64/kernel/process.c linux-2.5.69-bk7/arch/ia64/kernel/process.c --- linux-2.5.69-bk6/arch/ia64/kernel/process.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/process.c 2003-05-12 04:43:29.000000000 -0700 @@ -43,8 +43,8 @@ #include "sigframe.h" -static void -do_show_stack (struct unw_frame_info *info, void *arg) +void +ia64_do_show_stack (struct unw_frame_info *info, void *arg) { unsigned long ip, sp, bsp; char buf[80]; /* don't make it so big that it overflows the stack! */ @@ -57,7 +57,7 @@ unw_get_sp(info, &sp); unw_get_bsp(info, &bsp); - snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n", + snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n", ip, sp, bsp); print_symbol(buf, ip); } while (unw_unwind(info) >= 0); @@ -73,12 +73,12 @@ show_stack (struct task_struct *task) { if (!task) - unw_init_running(do_show_stack, 0); + unw_init_running(ia64_do_show_stack, 0); else { struct unw_frame_info info; unw_init_from_blocked_task(&info, task); - do_show_stack(&info, 0); + ia64_do_show_stack(&info, 0); } } @@ -123,8 +123,8 @@ if (user_mode(regs)) { /* print the stacked registers */ - unsigned long val, sof, *bsp, ndirty; - int i, is_nat = 0; + unsigned long val, *bsp, ndirty; + int i, sof, is_nat = 0; sof = regs->cr_ifs & 0x7f; /* size of frame */ ndirty = (regs->loadrs >> 19); @@ -135,7 +135,7 @@ ((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); } } else - show_stack(0); + show_stack(NULL); } void @@ -379,6 +379,7 @@ # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); + p->thread.last_fph_cpu = -1; #ifdef CONFIG_IA32_SUPPORT /* * If we're cloning an IA32 task then save the IA32 extra diff -urN linux-2.5.69-bk6/arch/ia64/kernel/ptrace.c linux-2.5.69-bk7/arch/ia64/kernel/ptrace.c --- linux-2.5.69-bk6/arch/ia64/kernel/ptrace.c 2003-05-04 16:53:56.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/ptrace.c 2003-05-12 04:43:29.000000000 -0700 @@ -202,17 +202,16 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw, unsigned long *krbs, unsigned long *urnat_addr) { - unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, kmask = ~0UL; + unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0UL; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; long num_regs; kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; /* - * First, figure out which bit number slot 0 in user-land maps - * to in the kernel rnat. Do this by figuring out how many - * register slots we're beyond the user's backingstore and - * then computing the equivalent address in kernel space. + * First, figure out which bit number slot 0 in user-land maps to in the kernel + * rnat. Do this by figuring out how many register slots we're beyond the user's + * backingstore and then computing the equivalent address in kernel space. */ num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); @@ -222,8 +221,8 @@ if (ubspstore + 63 > urnat_addr) { /* some bits need to be merged in from pt->ar_rnat */ - kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); - urnat = (pt->ar_rnat & ~kmask); + umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1); + urnat = (pt->ar_rnat & umask); } if (rnat0_kaddr >= kbsp) { rnat0 = sw->ar_rnat; @@ -235,7 +234,7 @@ } else if (rnat1_kaddr > krbs) { rnat1 = *rnat1_kaddr; } - urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & kmask; + urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & ~umask; return urnat; } @@ -246,17 +245,19 @@ put_rnat (struct pt_regs *pt, struct switch_stack *sw, unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat) { - unsigned long rnat0 = 0, rnat1 = 0, rnat = 0, *slot0_kaddr, kmask = ~0UL, mask; - unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; - long num_regs; + unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m; + unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift, slot, ndirty; + long num_regs, nbits; + + ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); + nbits = ndirty % 63; kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; /* - * First, figure out which bit number slot 0 in user-land maps - * to in the kernel rnat. Do this by figuring out how many - * register slots we're beyond the user's backingstore and - * then computing the equivalent address in kernel space. + * First, figure out which bit number slot 0 in user-land maps to in the kernel + * rnat. Do this by figuring out how many register slots we're beyond the user's + * backingstore and then computing the equivalent address in kernel space. */ num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); @@ -264,29 +265,37 @@ rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr); rnat0_kaddr = rnat1_kaddr - 64; +printk("%s: ubspstore=%p urnat_addr=%p\n", __FUNCTION__, ubspstore, urnat_addr); if (ubspstore + 63 > urnat_addr) { /* some bits need to be place in pt->ar_rnat: */ - kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); - pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask); + slot = ia64_rse_slot_num(ubspstore); + umask = ((1UL << slot) - 1); + pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask); + nbits -= slot; + if (nbits <= 0) + return; } + mask = (1UL << nbits) - 1; /* * Note: Section 11.1 of the EAS guarantees that bit 63 of an * rnat slot is ignored. so we don't have to clear it here. */ rnat0 = (urnat << shift); - mask = ~0UL << shift; + m = mask << shift; +printk("%s: rnat0=%016lx, m=%016lx, rnat0_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat0, m, rnat0_kaddr, kbsp); if (rnat0_kaddr >= kbsp) { - sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat0 & mask); + sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m); } else if (rnat0_kaddr > krbs) { - *rnat0_kaddr = ((*rnat0_kaddr & ~mask) | (rnat0 & mask)); + *rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m)); } rnat1 = (urnat >> (63 - shift)); - mask = ~0UL >> (63 - shift); + m = mask >> (63 - shift); +printk("%s: rnat1=%016lx, m=%016lx, rnat1_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat1, m, rnat1_kaddr, kbsp); if (rnat1_kaddr >= kbsp) { - sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat1 & mask); + sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m); } else if (rnat1_kaddr > krbs) { - *rnat1_kaddr = ((*rnat1_kaddr & ~mask) | (rnat1 & mask)); + *rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m)); } } @@ -589,6 +598,7 @@ psr->mfh = 0; ia64_save_fpu(&task->thread.fph[0]); task->thread.flags |= IA64_THREAD_FPH_VALID; + task->thread.last_fph_cpu = smp_processor_id(); } } @@ -608,12 +618,11 @@ ia64_flush_fph(task); if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) { task->thread.flags |= IA64_THREAD_FPH_VALID; + task->thread.last_fph_cpu = -1; /* force reload */ memset(&task->thread.fph, 0, sizeof(task->thread.fph)); } -#ifndef CONFIG_SMP if (ia64_get_fpu_owner() == task) ia64_set_fpu_owner(0); -#endif psr->dfh = 1; } @@ -702,7 +711,9 @@ case PT_R4: case PT_R5: case PT_R6: case PT_R7: if (write_access) { /* read NaT bit first: */ - ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, data, &nat); + unsigned long dummy; + + ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, &dummy, &nat); if (ret < 0) return ret; } diff -urN linux-2.5.69-bk6/arch/ia64/kernel/sal.c linux-2.5.69-bk7/arch/ia64/kernel/sal.c --- linux-2.5.69-bk6/arch/ia64/kernel/sal.c 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/sal.c 2003-05-12 04:43:29.000000000 -0700 @@ -116,7 +116,7 @@ p = (char *) (systab + 1); for (i = 0; i < systab->entry_count; i++) { /* - * The first byte of each entry type contains the type desciptor. + * The first byte of each entry type contains the type descriptor. */ switch (*p) { case SAL_DESC_ENTRY_POINT: diff -urN linux-2.5.69-bk6/arch/ia64/kernel/salinfo.c linux-2.5.69-bk7/arch/ia64/kernel/salinfo.c --- linux-2.5.69-bk6/arch/ia64/kernel/salinfo.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/salinfo.c 2003-05-12 04:43:29.000000000 -0700 @@ -38,7 +38,7 @@ { "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, }, }; -#define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t)) +#define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries) /* * One for each feature and one more for the directory entry... diff -urN linux-2.5.69-bk6/arch/ia64/kernel/setup.c linux-2.5.69-bk7/arch/ia64/kernel/setup.c --- linux-2.5.69-bk6/arch/ia64/kernel/setup.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/setup.c 2003-05-12 04:43:29.000000000 -0700 @@ -59,7 +59,10 @@ struct ia64_boot_param *ia64_boot_param; struct screen_info screen_info; +unsigned long ia64_max_cacheline_size; unsigned long ia64_iobase; /* virtual address for I/O accesses */ +struct io_space io_space[MAX_IO_SPACES]; +unsigned int num_io_spaces; unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */ @@ -412,6 +415,11 @@ } ia64_iobase = (unsigned long) ioremap(phys_iobase, 0); + /* setup legacy IO port space */ + io_space[0].mmio_base = ia64_iobase; + io_space[0].sparse = 1; + num_io_spaces = 1; + #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); #endif @@ -421,7 +429,7 @@ #ifdef CONFIG_ACPI_BOOT acpi_boot_init(); #endif -#ifdef CONFIG_SERIAL_HCDP +#ifdef CONFIG_SERIAL_8250_HCDP if (efi.hcdp) { void setup_serial_hcdp(void *); @@ -494,7 +502,7 @@ memcpy(features, " standard", 10); cp = features; sep = 0; - for (i = 0; i < sizeof(feature_bits)/sizeof(feature_bits[0]); ++i) { + for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) { if (mask & feature_bits[i].mask) { if (sep) *cp++ = sep; @@ -625,6 +633,39 @@ /* start_kernel() requires this... */ } +static void +get_max_cacheline_size (void) +{ + unsigned long line_size, max = 1; + u64 l, levels, unique_caches; + pal_cache_config_info_t cci; + s64 status; + + status = ia64_pal_cache_summary(&levels, &unique_caches); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", + __FUNCTION__, status); + max = SMP_CACHE_BYTES; + goto out; + } + + for (l = 0; l < levels; ++l) { + status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, + &cci); + if (status != 0) { + printk(KERN_ERR + "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n", + __FUNCTION__, l, status); + max = SMP_CACHE_BYTES; + } + line_size = 1 << cci.pcci_line_size; + if (line_size > max) + max = line_size; + } + out: + if (max > ia64_max_cacheline_size) + ia64_max_cacheline_size = max; +} /* * cpu_init() initializes state that is per-CPU. This function acts @@ -668,6 +709,8 @@ cpu_info->node_data = get_node_data_ptr(); #endif + get_max_cacheline_size(); + /* * We can't pass "local_cpu_data" to identify_cpu() because we haven't called * ia64_mmu_init() yet. And we can't call ia64_mmu_init() first because it diff -urN linux-2.5.69-bk6/arch/ia64/kernel/signal.c linux-2.5.69-bk7/arch/ia64/kernel/signal.c --- linux-2.5.69-bk6/arch/ia64/kernel/signal.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/signal.c 2003-05-12 04:43:29.000000000 -0700 @@ -142,8 +142,13 @@ __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); psr->mfh = 0; /* drop signal handler's fph contents... */ - if (!psr->dfh) + if (psr->dfh) + current->thread.last_fph_cpu = -1; + else { __ia64_load_fpu(current->thread.fph); + ia64_set_fpu_owner(current); + current->thread.last_fph_cpu = smp_processor_id(); + } } return err; } @@ -523,7 +528,7 @@ else errno = -errno; } - } else if (scr->pt.r10 != -1) + } else if ((long) scr->pt.r10 != -1) /* * A system calls has to be restarted only if one of the error codes * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 diff -urN linux-2.5.69-bk6/arch/ia64/kernel/smp.c linux-2.5.69-bk7/arch/ia64/kernel/smp.c --- linux-2.5.69-bk6/arch/ia64/kernel/smp.c 2003-05-04 16:53:56.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/smp.c 2003-05-12 04:43:29.000000000 -0700 @@ -2,7 +2,7 @@ * SMP Support * * Copyright (C) 1999 Walt Drummond - * Copyright (C) 1999, 2001 David Mosberger-Tang + * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang * * Lots of stuff stolen from arch/alpha/kernel/smp.c * @@ -87,7 +87,7 @@ cpu_halt(); } -void +irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs) { int this_cpu = get_cpu(); @@ -147,10 +147,11 @@ mb(); /* Order data access and bit testing. */ } put_cpu(); + return IRQ_HANDLED; } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_single (int dest_cpu, int op) @@ -160,12 +161,12 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_allbutself (int op) { - int i; + unsigned int i; for (i = 0; i < NR_CPUS; i++) { if (cpu_online(i) && i != smp_processor_id()) @@ -174,7 +175,7 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_all (int op) @@ -187,7 +188,7 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_self (int op) @@ -196,7 +197,7 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ void smp_send_reschedule (int cpu) diff -urN linux-2.5.69-bk6/arch/ia64/kernel/smpboot.c linux-2.5.69-bk7/arch/ia64/kernel/smpboot.c --- linux-2.5.69-bk6/arch/ia64/kernel/smpboot.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/smpboot.c 2003-05-12 04:43:29.000000000 -0700 @@ -192,6 +192,7 @@ { long i, delta, adj, adjust_latency = 0, done = 0; unsigned long flags, rt, master_time_stamp, bound; + extern void ia64_cpu_local_tick (void); #if DEBUG_ITC_SYNC struct { long rt; /* roundtrip time */ @@ -246,6 +247,16 @@ printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, " "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt); + + /* + * Check whether we sync'd the itc ahead of the next timer interrupt. If so, just + * reset it. + */ + if (time_after(ia64_get_itc(), local_cpu_data->itm_next)) { + Dprintk("CPU %d: oops, jumped a timer tick; resetting timer.\n", + smp_processor_id()); + ia64_cpu_local_tick(); + } } /* @@ -279,15 +290,6 @@ smp_setup_percpu_timer(); - if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { - /* - * Synchronize the ITC with the BP - */ - Dprintk("Going to syncup ITC with BP.\n"); - - ia64_sync_itc(0); - } - /* * Get our bogomips. */ @@ -310,6 +312,18 @@ local_irq_enable(); calibrate_delay(); local_cpu_data->loops_per_jiffy = loops_per_jiffy; + + if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { + /* + * Synchronize the ITC with the BP. Need to do this after irqs are + * enabled because ia64_sync_itc() calls smp_call_function_single(), which + * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls + * local_bh_enable(), which bugs out if irqs are not enabled... + */ + Dprintk("Going to syncup ITC with BP.\n"); + ia64_sync_itc(0); + } + /* * Allow the master to continue. */ @@ -394,13 +408,26 @@ return 0; } -unsigned long cache_decay_ticks; /* # of ticks an idle task is considered cache-hot */ +static int __init +decay (char *str) +{ + int ticks; + get_option (&str, &ticks); + cache_decay_ticks = ticks; + return 1; +} + +__setup("decay=", decay); + +/* + * # of ticks an idle task is considered cache-hot. Highly application-dependent. There + * are apps out there which are known to suffer significantly with values >= 4. + */ +unsigned long cache_decay_ticks = 10; /* equal to MIN_TIMESLICE */ static void smp_tune_scheduling (void) { - cache_decay_ticks = 10; /* XXX base this on PAL info and cache-bandwidth estimate */ - printk(KERN_INFO "task migration cache decay timeout: %ld msecs.\n", (cache_decay_ticks + 1) * 1000 / HZ); } diff -urN linux-2.5.69-bk6/arch/ia64/kernel/time.c linux-2.5.69-bk7/arch/ia64/kernel/time.c --- linux-2.5.69-bk6/arch/ia64/kernel/time.c 2003-05-04 16:53:07.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/kernel/time.c 2003-05-12 04:43:29.000000000 -0700 @@ -83,11 +83,26 @@ return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT; } +static inline void +set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) +{ + while (nsec > NSEC_PER_SEC) { + nsec -= NSEC_PER_SEC; + ++sec; + } + while (nsec < 0) { + nsec += NSEC_PER_SEC; + --sec; + } + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + void do_settimeofday (struct timeval *tv) { - time_t sec = tv->tv_sec; - long nsec = tv->tv_usec * 1000; + time_t wtm_sec, sec = tv->tv_sec; + long wtm_nsec, nsec = tv->tv_usec * 1000; write_seqlock_irq(&xtime_lock); { @@ -99,13 +114,12 @@ */ nsec -= gettimeoffset(); - while (nsec < 0) { - nsec += 1000000000; - sec--; - } + wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); + wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); + + set_normalized_timespec(&xtime, sec, nsec); + set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - xtime.tv_sec = sec; - xtime.tv_nsec = nsec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -166,8 +180,8 @@ usec = (nsec + offset) / 1000; - while (unlikely(usec >= 1000000)) { - usec -= 1000000; + while (unlikely(usec >= USEC_PER_SEC)) { + usec -= USEC_PER_SEC; ++sec; } @@ -175,8 +189,8 @@ tv->tv_usec = usec; } -static void -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t +timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { unsigned long new_itm; @@ -221,7 +235,7 @@ do { /* * If we're too close to the next clock tick for comfort, we increase the - * saftey margin by intentionally dropping the next tick(s). We do NOT update + * safety margin by intentionally dropping the next tick(s). We do NOT update * itm.next because that would force us to call do_timer() which in turn would * let our clock run too fast (with the potentially devastating effect of * losing monotony of time). @@ -231,12 +245,13 @@ ia64_set_itm(new_itm); /* double check, in case we got hit by a (slow) PMI: */ } while (time_after_eq(ia64_get_itc(), new_itm)); + return IRQ_HANDLED; } /* * Encapsulate access to the itm structure for SMP. */ -void __init +void ia64_cpu_local_tick (void) { int cpu = smp_processor_id(); @@ -281,7 +296,7 @@ if (status != 0) { /* invent "random" values */ printk(KERN_ERR - "SAL/PAL failed to obtain frequency info---inventing reasonably values\n"); + "SAL/PAL failed to obtain frequency info---inventing reasonable values\n"); platform_base_freq = 100000000; itc_ratio.num = 3; itc_ratio.den = 1; @@ -305,8 +320,8 @@ local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; - local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000; - local_cpu_data->nsec_per_cyc = ((1000000000UL<cyc_per_usec = (itc_freq + USEC_PER_SEC/2) / USEC_PER_SEC; + local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<curr.reg + unw.save_order[i]; if (reg->where == UNW_WHERE_GR_SAVE) { reg->where = UNW_WHERE_GR; @@ -698,7 +698,7 @@ */ if (sr->imask) { unsigned char kind, mask = 0, *cp = sr->imask; - unsigned long t; + int t; static const unsigned char limit[3] = { UNW_REG_F31, UNW_REG_R7, UNW_REG_B5 }; @@ -1214,13 +1214,13 @@ spin_unlock(&unw.lock); /* - * XXX We'll deadlock here if we interrupt a thread that is - * holding a read lock on script->lock. A try_write_lock() - * might be mighty handy here... Alternatively, we could - * disable interrupts whenever we hold a read-lock, but that - * seems silly. + * We'd deadlock here if we interrupted a thread that is holding a read lock on + * script->lock. Thus, if the write_trylock() fails, we simply bail out. The + * alternative would be to disable interrupts whenever we hold a read-lock, but + * that seems silly. */ - write_lock(&script->lock); + if (!write_trylock(&script->lock)) + return NULL; spin_lock(&unw.lock); { @@ -1888,22 +1888,21 @@ return -1; } -void -unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw) +static void +init_frame_info (struct unw_frame_info *info, struct task_struct *t, + struct switch_stack *sw, unsigned long stktop) { - unsigned long rbslimit, rbstop, stklimit, stktop, sol; + unsigned long rbslimit, rbstop, stklimit; STAT(unsigned long start, flags;) STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc()); /* - * Subtle stuff here: we _could_ unwind through the - * switch_stack frame but we don't want to do that because it - * would be slow as each preserved register would have to be - * processed. Instead, what we do here is zero out the frame - * info and start the unwind process at the function that - * created the switch_stack frame. When a preserved value in - * switch_stack needs to be accessed, run_script() will + * Subtle stuff here: we _could_ unwind through the switch_stack frame but we + * don't want to do that because it would be slow as each preserved register would + * have to be processed. Instead, what we do here is zero out the frame info and + * start the unwind process at the function that created the switch_stack frame. + * When a preserved value in switch_stack needs to be accessed, run_script() will * initialize the appropriate pointer on demand. */ memset(info, 0, sizeof(*info)); @@ -1914,7 +1913,6 @@ rbstop = rbslimit; stklimit = (unsigned long) t + IA64_STK_OFFSET; - stktop = (unsigned long) sw - 16; if (stktop <= rbstop) stktop = rbstop; @@ -1924,34 +1922,58 @@ info->memstk.top = stktop; info->task = t; info->sw = sw; - info->sp = info->psp = (unsigned long) (sw + 1) - 16; - info->pt = 0; + info->sp = info->psp = stktop; + info->pr = sw->pr; + UNW_DPRINT(3, "unwind.%s:\n" + " task 0x%lx\n" + " rbs = [0x%lx-0x%lx)\n" + " stk = [0x%lx-0x%lx)\n" + " pr 0x%lx\n" + " sw 0x%lx\n" + " sp 0x%lx\n", + __FUNCTION__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit, + info->pr, (unsigned long) info->sw, info->sp); + STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); +} + +void +unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t, + struct pt_regs *pt, struct switch_stack *sw) +{ + unsigned long sof; + + init_frame_info(info, t, sw, pt->r12); + info->cfm_loc = &pt->cr_ifs; + info->unat_loc = &pt->ar_unat; + info->pfs_loc = &pt->ar_pfs; + sof = *info->cfm_loc & 0x7f; + info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof); + info->ip = pt->cr_iip + ia64_psr(pt)->ri; + info->pt = (unsigned long) pt; + UNW_DPRINT(3, "unwind.%s:\n" + " bsp 0x%lx\n" + " sof 0x%lx\n" + " ip 0x%lx\n", + __FUNCTION__, info->bsp, sof, info->ip); + find_save_locs(info); +} + +void +unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw) +{ + unsigned long sol; + + init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16); info->cfm_loc = &sw->ar_pfs; sol = (*info->cfm_loc >> 7) & 0x7f; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->ip = sw->b0; - info->pr = sw->pr; - UNW_DPRINT(3, - "unwind.%s\n" - " rbslimit 0x%lx\n" - " rbstop 0x%lx\n" - " stklimit 0x%lx\n" - " stktop 0x%lx\n" - " task 0x%lx\n" - " sw 0x%lx\n", - __FUNCTION__, rbslimit, rbstop, stklimit, stktop, - (unsigned long)(info->task), - (unsigned long)(info->sw)); - UNW_DPRINT(3, - " sp/psp 0x%lx\n" - " sol 0x%lx\n" - " bsp 0x%lx\n" - " ip 0x%lx\n" - " pr 0x%lx\n", - info->sp, sol, info->bsp, info->ip, info->pr); - + UNW_DPRINT(3, "unwind.%s:\n" + " bsp 0x%lx\n" + " sol 0x%lx\n" + " ip 0x%lx\n", + __FUNCTION__, info->bsp, sol, info->ip); find_save_locs(info); - STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); } void diff -urN linux-2.5.69-bk6/arch/ia64/lib/copy_user.S linux-2.5.69-bk7/arch/ia64/lib/copy_user.S --- linux-2.5.69-bk6/arch/ia64/lib/copy_user.S 2003-05-04 16:53:03.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/lib/copy_user.S 2003-05-12 04:43:29.000000000 -0700 @@ -316,7 +316,7 @@ // Beginning of long mempcy (i.e. > 16 bytes) // .long_copy_user: - tbit.nz p6,p7=src1,0 // odd alignement + tbit.nz p6,p7=src1,0 // odd alignment and tmp=7,tmp ;; cmp.eq p10,p8=r0,tmp diff -urN linux-2.5.69-bk6/arch/ia64/lib/do_csum.S linux-2.5.69-bk7/arch/ia64/lib/do_csum.S --- linux-2.5.69-bk6/arch/ia64/lib/do_csum.S 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/lib/do_csum.S 2003-05-12 04:43:29.000000000 -0700 @@ -137,7 +137,7 @@ mov saved_pr=pr // preserve predicates (rotation) (p6) br.ret.spnt.many rp // return if zero or negative length - mov hmask=-1 // intialize head mask + mov hmask=-1 // initialize head mask tbit.nz p15,p0=buf,0 // is buf an odd address? and first1=-8,buf // 8-byte align down address of first1 element diff -urN linux-2.5.69-bk6/arch/ia64/lib/io.c linux-2.5.69-bk7/arch/ia64/lib/io.c --- linux-2.5.69-bk6/arch/ia64/lib/io.c 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/lib/io.c 2003-05-12 04:43:29.000000000 -0700 @@ -51,84 +51,79 @@ #ifdef CONFIG_IA64_GENERIC +#undef __ia64_inb +#undef __ia64_inw +#undef __ia64_inl +#undef __ia64_outb +#undef __ia64_outw +#undef __ia64_outl +#undef __ia64_readb +#undef __ia64_readw +#undef __ia64_readl +#undef __ia64_readq +#undef __ia64_writeb +#undef __ia64_writew +#undef __ia64_writel +#undef __ia64_writeq + unsigned int -ia64_inb (unsigned long port) +__ia64_inb (unsigned long port) { - return __ia64_inb(port); + return ___ia64_inb(port); } unsigned int -ia64_inw (unsigned long port) +__ia64_inw (unsigned long port) { - return __ia64_inw(port); + return ___ia64_inw(port); } unsigned int -ia64_inl (unsigned long port) +__ia64_inl (unsigned long port) { - return __ia64_inl(port); + return ___ia64_inl(port); } void -ia64_outb (unsigned char val, unsigned long port) +__ia64_outb (unsigned char val, unsigned long port) { - __ia64_outb(val, port); + ___ia64_outb(val, port); } void -ia64_outw (unsigned short val, unsigned long port) +__ia64_outw (unsigned short val, unsigned long port) { - __ia64_outw(val, port); + ___ia64_outw(val, port); } void -ia64_outl (unsigned int val, unsigned long port) +__ia64_outl (unsigned int val, unsigned long port) { - __ia64_outl(val, port); + ___ia64_outl(val, port); } unsigned char -ia64_readb (void *addr) +__ia64_readb (void *addr) { - return __ia64_readb (addr); + return ___ia64_readb (addr); } unsigned short -ia64_readw (void *addr) +__ia64_readw (void *addr) { - return __ia64_readw (addr); + return ___ia64_readw (addr); } unsigned int -ia64_readl (void *addr) +__ia64_readl (void *addr) { - return __ia64_readl (addr); + return ___ia64_readl (addr); } unsigned long -ia64_readq (void *addr) +__ia64_readq (void *addr) { - return __ia64_readq (addr) + return ___ia64_readq (addr); } - -/* define aliases: */ - -asm (".global __ia64_inb, __ia64_inw, __ia64_inl"); -asm ("__ia64_inb = ia64_inb"); -asm ("__ia64_inw = ia64_inw"); -asm ("__ia64_inl = ia64_inl"); - -asm (".global __ia64_outb, __ia64_outw, __ia64_outl"); -asm ("__ia64_outb = ia64_outb"); -asm ("__ia64_outw = ia64_outw"); -asm ("__ia64_outl = ia64_outl"); - -asm (".global __ia64_readb, __ia64_readw, __ia64_readl, __ia64_readq"); -asm ("__ia64_readb = ia64_readb"); -asm ("__ia64_readw = ia64_readw"); -asm ("__ia64_readl = ia64_readl"); -asm ("__ia64_readq = ia64_readq"); - - #endif /* CONFIG_IA64_GENERIC */ diff -urN linux-2.5.69-bk6/arch/ia64/lib/swiotlb.c linux-2.5.69-bk7/arch/ia64/lib/swiotlb.c --- linux-2.5.69-bk6/arch/ia64/lib/swiotlb.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/lib/swiotlb.c 2003-05-12 04:43:29.000000000 -0700 @@ -5,7 +5,10 @@ * I/O TLBs (aka DMA address translation hardware). * Copyright (C) 2000 Asit Mallick * Copyright (C) 2000 Goutham Rao + * Copyright (C) 2000, 2003 Hewlett-Packard Co + * David Mosberger-Tang * + * 03/05/07 davidm Switch from PCI-DMA to generic device DMA API. * 00/12/13 davidm Rename to swiotlb.c and add mark_clean() to avoid * unnecessary i-cache flushing. */ @@ -92,7 +95,7 @@ void swiotlb_init (void) { - int i; + unsigned long i; /* * Get IO TLB memory from the low pages @@ -121,7 +124,7 @@ * Allocates bounce buffer and returns its kernel virtual address. */ static void * -map_single (struct pci_dev *hwdev, char *buffer, size_t size, int direction) +map_single (struct device *hwdev, char *buffer, size_t size, int dir) { unsigned long flags; char *dma_addr; @@ -161,7 +164,7 @@ if (io_tlb_list[index] >= nslots) { int count = 0; - for (i = index; i < index + nslots; i++) + for (i = index; i < (int) (index + nslots); i++) io_tlb_list[i] = 0; for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && io_tlb_list[i]; i--) @@ -195,7 +198,7 @@ * needed when we sync the memory. Then we sync the buffer if needed. */ io_tlb_orig_addr[index] = buffer; - if (direction == PCI_DMA_TODEVICE || direction == PCI_DMA_BIDIRECTIONAL) + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) memcpy(dma_addr, buffer, size); return dma_addr; @@ -205,7 +208,7 @@ * dma_addr is the kernel virtual address of the bounce buffer to unmap. */ static void -unmap_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction) +unmap_single (struct device *hwdev, char *dma_addr, size_t size, int dir) { unsigned long flags; int i, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; @@ -215,7 +218,7 @@ /* * First, sync the memory before unmapping the entry */ - if ((direction == PCI_DMA_FROMDEVICE) || (direction == PCI_DMA_BIDIRECTIONAL)) + if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) /* * bounce... copy the data back into the original buffer * and delete the * bounce buffer. @@ -239,7 +242,7 @@ for (i = index + nslots - 1; i >= index; i--) io_tlb_list[i] = ++count; /* - * Step 2: merge the returned slots with the preceeding slots, if + * Step 2: merge the returned slots with the preceding slots, if * available (non zero) */ for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && @@ -250,49 +253,46 @@ } static void -sync_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction) +sync_single (struct device *hwdev, char *dma_addr, size_t size, int dir) { int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; char *buffer = io_tlb_orig_addr[index]; /* * bounce... copy the data back into/from the original buffer - * XXX How do you handle PCI_DMA_BIDIRECTIONAL here ? + * XXX How do you handle DMA_BIDIRECTIONAL here ? */ - if (direction == PCI_DMA_FROMDEVICE) + if (dir == DMA_FROM_DEVICE) memcpy(buffer, dma_addr, size); - else if (direction == PCI_DMA_TODEVICE) + else if (dir == DMA_TO_DEVICE) memcpy(dma_addr, buffer, size); else BUG(); } void * -swiotlb_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flags) { - unsigned long pci_addr; - int gfp = GFP_ATOMIC; + unsigned long dev_addr; void *ret; - /* - * Alloc_consistent() is defined to return memory < 4GB, no matter what the DMA - * mask says. - */ - gfp |= GFP_DMA; /* XXX fix me: should change this to GFP_32BIT or ZONE_32BIT */ - ret = (void *)__get_free_pages(gfp, get_order(size)); + /* XXX fix me: the DMA API should pass us an explicit DMA mask instead: */ + flags |= GFP_DMA; + + ret = (void *)__get_free_pages(flags, get_order(size)); if (!ret) return NULL; memset(ret, 0, size); - pci_addr = virt_to_phys(ret); - if (hwdev && (pci_addr & ~hwdev->dma_mask) != 0) - panic("swiotlb_alloc_consistent: allocated memory is out of range for PCI device"); - *dma_handle = pci_addr; + dev_addr = virt_to_phys(ret); + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) + panic("swiotlb_alloc_consistent: allocated memory is out of range for device"); + *dma_handle = dev_addr; return ret; } void -swiotlb_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long) vaddr, get_order(size)); } @@ -305,34 +305,34 @@ * swiotlb_unmap_single or swiotlb_dma_sync_single is performed. */ dma_addr_t -swiotlb_map_single (struct pci_dev *hwdev, void *ptr, size_t size, int direction) +swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir) { - unsigned long pci_addr = virt_to_phys(ptr); + unsigned long dev_addr = virt_to_phys(ptr); - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); /* * Check if the PCI device can DMA to ptr... if so, just return ptr */ - if ((pci_addr & ~hwdev->dma_mask) == 0) + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0) /* * Device is bit capable of DMA'ing to the buffer... just return the PCI * address of ptr */ - return pci_addr; + return dev_addr; /* * get a bounce buffer: */ - pci_addr = virt_to_phys(map_single(hwdev, ptr, size, direction)); + dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir)); /* * Ensure that the address returned is DMA'ble: */ - if ((pci_addr & ~hwdev->dma_mask) != 0) + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) panic("map_single: bounce buffer is not DMA'ble"); - return pci_addr; + return dev_addr; } /* @@ -363,15 +363,15 @@ * device wrote there. */ void -swiotlb_unmap_single (struct pci_dev *hwdev, dma_addr_t pci_addr, size_t size, int direction) +swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - char *dma_addr = phys_to_virt(pci_addr); + char *dma_addr = phys_to_virt(dev_addr); - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) - unmap_single(hwdev, dma_addr, size, direction); - else if (direction == PCI_DMA_FROMDEVICE) + unmap_single(hwdev, dma_addr, size, dir); + else if (dir == DMA_FROM_DEVICE) mark_clean(dma_addr, size); } @@ -385,21 +385,21 @@ * again owns the buffer. */ void -swiotlb_sync_single (struct pci_dev *hwdev, dma_addr_t pci_addr, size_t size, int direction) +swiotlb_sync_single (struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - char *dma_addr = phys_to_virt(pci_addr); + char *dma_addr = phys_to_virt(dev_addr); - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) - sync_single(hwdev, dma_addr, size, direction); - else if (direction == PCI_DMA_FROMDEVICE) + sync_single(hwdev, dma_addr, size, dir); + else if (dir == DMA_FROM_DEVICE) mark_clean(dma_addr, size); } /* * Map a set of buffers described by scatterlist in streaming mode for DMA. This is the - * scather-gather version of the above swiotlb_map_single interface. Here the scatter + * scatter-gather version of the above swiotlb_map_single interface. Here the scatter * gather list elements are each tagged with the appropriate dma address and length. They * are obtained via sg_dma_{address,length}(SG). * @@ -412,23 +412,22 @@ * Device ownership issues as mentioned above for swiotlb_map_single are the same here. */ int -swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) +swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { void *addr; - unsigned long pci_addr; + unsigned long dev_addr; int i; - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); for (i = 0; i < nelems; i++, sg++) { addr = SG_ENT_VIRT_ADDRESS(sg); - pci_addr = virt_to_phys(addr); - if ((pci_addr & ~hwdev->dma_mask) != 0) - sg->dma_address = (dma_addr_t) - map_single(hwdev, addr, sg->length, direction); + dev_addr = virt_to_phys(addr); + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) + sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir); else - sg->dma_address = pci_addr; + sg->dma_address = dev_addr; sg->dma_length = sg->length; } return nelems; @@ -439,17 +438,17 @@ * here are the same as for swiotlb_unmap_single() above. */ void -swiotlb_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) +swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { int i; - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction); - else if (direction == PCI_DMA_FROMDEVICE) + unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir); + else if (dir == DMA_FROM_DEVICE) mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); } @@ -461,16 +460,16 @@ * usage. */ void -swiotlb_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) +swiotlb_sync_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { int i; - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction); + sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir); } /* @@ -479,7 +478,7 @@ * you would pass 0x00ffffff as the mask to this function. */ int -swiotlb_pci_dma_supported (struct pci_dev *hwdev, u64 mask) +swiotlb_dma_supported (struct device *hwdev, u64 mask) { return 1; } @@ -491,6 +490,6 @@ EXPORT_SYMBOL(swiotlb_unmap_sg); EXPORT_SYMBOL(swiotlb_sync_single); EXPORT_SYMBOL(swiotlb_sync_sg); -EXPORT_SYMBOL(swiotlb_alloc_consistent); -EXPORT_SYMBOL(swiotlb_free_consistent); -EXPORT_SYMBOL(swiotlb_pci_dma_supported); +EXPORT_SYMBOL(swiotlb_alloc_coherent); +EXPORT_SYMBOL(swiotlb_free_coherent); +EXPORT_SYMBOL(swiotlb_dma_supported); diff -urN linux-2.5.69-bk6/arch/ia64/mm/fault.c linux-2.5.69-bk7/arch/ia64/mm/fault.c --- linux-2.5.69-bk6/arch/ia64/mm/fault.c 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/mm/fault.c 2003-05-12 04:43:29.000000000 -0700 @@ -58,6 +58,18 @@ if (in_atomic() || !mm) goto no_context; +#ifdef CONFIG_VIRTUAL_MEM_MAP + /* + * If fault is in region 5 and we are in the kernel, we may already + * have the mmap_sem (pfn_valid macro is called during mmap). There + * is no vma for region 5 addr's anyway, so skip getting the semaphore + * and go directly to the exception handling code. + */ + + if ((REGION_NUMBER(address) == 5) && !user_mode(regs)) + goto bad_area_no_up; +#endif + down_read(&mm->mmap_sem); vma = find_vma_prev(mm, address, &prev_vma); @@ -139,6 +151,9 @@ bad_area: up_read(&mm->mmap_sem); +#ifdef CONFIG_VIRTUAL_MEM_MAP + bad_area_no_up: +#endif if ((isr & IA64_ISR_SP) || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) { diff -urN linux-2.5.69-bk6/arch/ia64/mm/init.c linux-2.5.69-bk7/arch/ia64/mm/init.c --- linux-2.5.69-bk6/arch/ia64/mm/init.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/mm/init.c 2003-05-12 04:43:29.000000000 -0700 @@ -38,6 +38,13 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; +#ifdef CONFIG_VIRTUAL_MEM_MAP +# define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ + unsigned long vmalloc_end = VMALLOC_END_INIT; + static struct page *vmem_map; + static unsigned long num_dma_physpages; +#endif + static int pgt_cache_water[2] = { 25, 50 }; void @@ -48,13 +55,13 @@ low = pgt_cache_water[0]; high = pgt_cache_water[1]; - if (pgtable_cache_size > high) { + if (pgtable_cache_size > (u64) high) { do { if (pgd_quicklist) free_page((unsigned long)pgd_alloc_one_fast(0)); if (pmd_quicklist) free_page((unsigned long)pmd_alloc_one_fast(0, 0)); - } while (pgtable_cache_size > low); + } while (pgtable_cache_size > (u64) low); } } @@ -337,6 +344,139 @@ ia64_tlb_init(); } +#ifdef CONFIG_VIRTUAL_MEM_MAP + +static int +create_mem_map_page_table (u64 start, u64 end, void *arg) +{ + unsigned long address, start_page, end_page; + struct page *map_start, *map_end; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + map_start = vmem_map + (__pa(start) >> PAGE_SHIFT); + map_end = vmem_map + (__pa(end) >> PAGE_SHIFT); + + start_page = (unsigned long) map_start & PAGE_MASK; + end_page = PAGE_ALIGN((unsigned long) map_end); + + for (address = start_page; address < end_page; address += PAGE_SIZE) { + pgd = pgd_offset_k(address); + if (pgd_none(*pgd)) + pgd_populate(&init_mm, pgd, alloc_bootmem_pages(PAGE_SIZE)); + pmd = pmd_offset(pgd, address); + + if (pmd_none(*pmd)) + pmd_populate_kernel(&init_mm, pmd, alloc_bootmem_pages(PAGE_SIZE)); + pte = pte_offset_kernel(pmd, address); + + if (pte_none(*pte)) + set_pte(pte, pfn_pte(__pa(alloc_bootmem_pages(PAGE_SIZE)) >> PAGE_SHIFT, + PAGE_KERNEL)); + } + return 0; +} + +struct memmap_init_callback_data { + struct page *start; + struct page *end; + int nid; + unsigned long zone; +}; + +static int +virtual_memmap_init (u64 start, u64 end, void *arg) +{ + struct memmap_init_callback_data *args; + struct page *map_start, *map_end; + + args = (struct memmap_init_callback_data *) arg; + + map_start = vmem_map + (__pa(start) >> PAGE_SHIFT); + map_end = vmem_map + (__pa(end) >> PAGE_SHIFT); + + if (map_start < args->start) + map_start = args->start; + if (map_end > args->end) + map_end = args->end; + + /* + * We have to initialize "out of bounds" struct page elements that fit completely + * on the same pages that were allocated for the "in bounds" elements because they + * may be referenced later (and found to be "reserved"). + */ + map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1)) / sizeof(struct page); + map_end += ((PAGE_ALIGN((unsigned long) map_end) - (unsigned long) map_end) + / sizeof(struct page)); + + if (map_start < map_end) + memmap_init_zone(map_start, (unsigned long) (map_end - map_start), + args->nid, args->zone, page_to_pfn(map_start)); + return 0; +} + +void +memmap_init (struct page *start, unsigned long size, int nid, + unsigned long zone, unsigned long start_pfn) +{ + if (!vmem_map) + memmap_init_zone(start, size, nid, zone, start_pfn); + else { + struct memmap_init_callback_data args; + + args.start = start; + args.end = start + size; + args.nid = nid; + args.zone = zone; + + efi_memmap_walk(virtual_memmap_init, &args); + } +} + +int +ia64_pfn_valid (unsigned long pfn) +{ + char byte; + + return __get_user(byte, (char *) pfn_to_page(pfn)) == 0; +} + +static int +count_dma_pages (u64 start, u64 end, void *arg) +{ + unsigned long *count = arg; + + if (end <= MAX_DMA_ADDRESS) + *count += (end - start) >> PAGE_SHIFT; + return 0; +} + +static int +find_largest_hole (u64 start, u64 end, void *arg) +{ + u64 *max_gap = arg; + + static u64 last_end = PAGE_OFFSET; + + /* NOTE: this algorithm assumes efi memmap table is ordered */ + + if (*max_gap < (start - last_end)) + *max_gap = start - last_end; + last_end = end; + return 0; +} +#endif /* CONFIG_VIRTUAL_MEM_MAP */ + +static int +count_pages (u64 start, u64 end, void *arg) +{ + unsigned long *count = arg; + + *count += (end - start) >> PAGE_SHIFT; + return 0; +} + /* * Set up the page tables. */ @@ -348,18 +488,70 @@ extern void discontig_paging_init(void); discontig_paging_init(); + efi_memmap_walk(count_pages, &num_physpages); } #else /* !CONFIG_DISCONTIGMEM */ void paging_init (void) { - unsigned long max_dma, zones_size[MAX_NR_ZONES]; + unsigned long max_dma; + unsigned long zones_size[MAX_NR_ZONES]; +# ifdef CONFIG_VIRTUAL_MEM_MAP + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long max_gap; +# endif /* initialize mem_map[] */ memset(zones_size, 0, sizeof(zones_size)); + num_physpages = 0; + efi_memmap_walk(count_pages, &num_physpages); + max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; + +# ifdef CONFIG_VIRTUAL_MEM_MAP + memset(zholes_size, 0, sizeof(zholes_size)); + + num_dma_physpages = 0; + efi_memmap_walk(count_dma_pages, &num_dma_physpages); + + if (max_low_pfn < max_dma) { + zones_size[ZONE_DMA] = max_low_pfn; + zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages; + } else { + zones_size[ZONE_DMA] = max_dma; + zholes_size[ZONE_DMA] = max_dma - num_dma_physpages; + if (num_physpages > num_dma_physpages) { + zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; + zholes_size[ZONE_NORMAL] = ((max_low_pfn - max_dma) + - (num_physpages - num_dma_physpages)); + } + } + + max_gap = 0; + efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); + if (max_gap < LARGE_GAP) { + vmem_map = (struct page *) 0; + free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, zholes_size); + mem_map = contig_page_data.node_mem_map; + } + else { + unsigned long map_size; + + /* allocate virtual_mem_map */ + + map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page)); + vmalloc_end -= map_size; + vmem_map = (struct page *) vmalloc_end; + efi_memmap_walk(create_mem_map_page_table, 0); + + free_area_init_node(0, &contig_page_data, vmem_map, zones_size, 0, zholes_size); + + mem_map = contig_page_data.node_mem_map; + printk("Virtual mem_map starts at 0x%p\n", mem_map); + } +# else /* !CONFIG_VIRTUAL_MEM_MAP */ if (max_low_pfn < max_dma) zones_size[ZONE_DMA] = max_low_pfn; else { @@ -367,19 +559,11 @@ zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; } free_area_init(zones_size); +# endif /* !CONFIG_VIRTUAL_MEM_MAP */ } #endif /* !CONFIG_DISCONTIGMEM */ static int -count_pages (u64 start, u64 end, void *arg) -{ - unsigned long *count = arg; - - *count += (end - start) >> PAGE_SHIFT; - return 0; -} - -static int count_reserved_pages (u64 start, u64 end, void *arg) { unsigned long num_reserved = 0; @@ -406,7 +590,7 @@ * any drivers that may need the PCI DMA interface are initialized or bootmem has * been freed. */ - platform_pci_dma_init(); + platform_dma_init(); #endif #ifndef CONFIG_DISCONTIGMEM @@ -415,9 +599,6 @@ max_mapnr = max_low_pfn; #endif - num_physpages = 0; - efi_memmap_walk(count_pages, &num_physpages); - high_memory = __va(max_low_pfn * PAGE_SIZE); for_each_pgdat(pgdat) @@ -445,7 +626,7 @@ num_pgt_pages = nr_free_pages() / PTRS_PER_PGD + NUM_TASKS; if (num_pgt_pages > nr_free_pages() / 10) num_pgt_pages = nr_free_pages() / 10; - if (num_pgt_pages > pgt_cache_water[1]) + if (num_pgt_pages > (u64) pgt_cache_water[1]) pgt_cache_water[1] = num_pgt_pages; /* install the gate page in the global page table: */ diff -urN linux-2.5.69-bk6/arch/ia64/pci/pci.c linux-2.5.69-bk7/arch/ia64/pci/pci.c --- linux-2.5.69-bk6/arch/ia64/pci/pci.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/pci/pci.c 2003-05-12 04:43:29.000000000 -0700 @@ -5,6 +5,7 @@ * * Copyright (C) 2002 Hewlett-Packard Co * David Mosberger-Tang + * Bjorn Helgaas * * Note: Above list of copyright holders is incomplete... */ @@ -116,31 +117,10 @@ subsys_initcall(pci_acpi_init); -static void __init -pcibios_fixup_resource(struct resource *res, u64 offset) -{ - res->start += offset; - res->end += offset; -} - -void __init -pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) -{ - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (!dev->resource[i].start) - continue; - if (dev->resource[i].flags & IORESOURCE_MEM) - pcibios_fixup_resource(&dev->resource[i], - PCI_CONTROLLER(dev)->mem_offset); - } -} - /* Called by ACPI when it finds a new root bus. */ static struct pci_controller * -alloc_pci_controller(int seg) +alloc_pci_controller (int seg) { struct pci_controller *controller; @@ -153,8 +133,8 @@ return controller; } -struct pci_bus * -scan_root_bus(int bus, struct pci_ops *ops, void *sysdata) +static struct pci_bus * +scan_root_bus (int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; @@ -184,23 +164,185 @@ return b; } +static int +alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags) +{ + struct resource *res; + + res = kmalloc(sizeof(*res), GFP_KERNEL); + if (!res) + return -ENOMEM; + + memset(res, 0, sizeof(*res)); + res->name = name; + res->start = start; + res->end = end; + res->flags = flags; + + if (request_resource(root, res)) + return -EBUSY; + + return 0; +} + +static u64 +add_io_space (struct acpi_resource_address64 *addr) +{ + u64 offset; + int sparse = 0; + int i; + + if (addr->address_translation_offset == 0) + return IO_SPACE_BASE(0); /* part of legacy IO space */ + + if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) + sparse = 1; + + offset = (u64) ioremap(addr->address_translation_offset, 0); + for (i = 0; i < num_io_spaces; i++) + if (io_space[i].mmio_base == offset && + io_space[i].sparse == sparse) + return IO_SPACE_BASE(i); + + if (num_io_spaces == MAX_IO_SPACES) { + printk("Too many IO port spaces\n"); + return ~0; + } + + i = num_io_spaces++; + io_space[i].mmio_base = offset; + io_space[i].sparse = sparse; + + return IO_SPACE_BASE(i); +} + +static acpi_status +count_window (struct acpi_resource *resource, void *data) +{ + unsigned int *windows = (unsigned int *) data; + struct acpi_resource_address64 addr; + acpi_status status; + + status = acpi_resource_to_address64(resource, &addr); + if (ACPI_SUCCESS(status)) + if (addr.resource_type == ACPI_MEMORY_RANGE || + addr.resource_type == ACPI_IO_RANGE) + (*windows)++; + + return AE_OK; +} + +struct pci_root_info { + struct pci_controller *controller; + char *name; +}; + +static acpi_status +add_window (struct acpi_resource *res, void *data) +{ + struct pci_root_info *info = (struct pci_root_info *) data; + struct pci_window *window; + struct acpi_resource_address64 addr; + acpi_status status; + unsigned long flags, offset = 0; + struct resource *root; + + status = acpi_resource_to_address64(res, &addr); + if (ACPI_SUCCESS(status)) { + if (addr.resource_type == ACPI_MEMORY_RANGE) { + flags = IORESOURCE_MEM; + root = &iomem_resource; + offset = addr.address_translation_offset; + } else if (addr.resource_type == ACPI_IO_RANGE) { + flags = IORESOURCE_IO; + root = &ioport_resource; + offset = add_io_space(&addr); + if (offset == ~0) + return AE_OK; + } else + return AE_OK; + + window = &info->controller->window[info->controller->windows++]; + window->resource.flags |= flags; + window->resource.start = addr.min_address_range; + window->resource.end = addr.max_address_range; + window->offset = offset; + + if (alloc_resource(info->name, root, addr.min_address_range + offset, + addr.max_address_range + offset, flags)) + printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", + addr.min_address_range + offset, addr.max_address_range + offset, + root->name, info->name); + } + + return AE_OK; +} + struct pci_bus * -pcibios_scan_root(void *handle, int seg, int bus) +pcibios_scan_root (void *handle, int seg, int bus) { + struct pci_root_info info; struct pci_controller *controller; - u64 base, size, offset; + unsigned int windows = 0; + char *name; printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus); controller = alloc_pci_controller(seg); if (!controller) - return NULL; + goto out1; controller->acpi_handle = handle; - acpi_get_addr_space(handle, ACPI_MEMORY_RANGE, &base, &size, &offset); - controller->mem_offset = offset; + acpi_walk_resources(handle, METHOD_NAME__CRS, count_window, &windows); + controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL); + if (!controller->window) + goto out2; + + name = kmalloc(16, GFP_KERNEL); + if (!name) + goto out3; + + sprintf(name, "PCI Bus %02x:%02x", seg, bus); + info.controller = controller; + info.name = name; + acpi_walk_resources(handle, METHOD_NAME__CRS, add_window, &info); return scan_root_bus(bus, pci_root_ops, controller); + +out3: + kfree(controller->window); +out2: + kfree(controller); +out1: + return NULL; +} + +void __init +pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus) +{ + struct pci_controller *controller = PCI_CONTROLLER(dev); + struct pci_window *window; + int i, j; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (!dev->resource[i].start) + continue; + +#define contains(win, res) ((res)->start >= (win)->start && \ + (res)->end <= (win)->end) + + for (j = 0; j < controller->windows; j++) { + window = &controller->window[j]; + if (((dev->resource[i].flags & IORESOURCE_MEM && + window->resource.flags & IORESOURCE_MEM) || + (dev->resource[i].flags & IORESOURCE_IO && + window->resource.flags & IORESOURCE_IO)) && + contains(&window->resource, &dev->resource[i])) { + dev->resource[i].start += window->offset; + dev->resource[i].end += window->offset; + } + } + } } /* diff -urN linux-2.5.69-bk6/arch/ia64/sn/kernel/machvec.c linux-2.5.69-bk7/arch/ia64/sn/kernel/machvec.c --- linux-2.5.69-bk6/arch/ia64/sn/kernel/machvec.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/sn/kernel/machvec.c 2003-05-12 04:43:29.000000000 -0700 @@ -33,9 +33,11 @@ #include #ifdef CONFIG_IA64_SGI_SN1 -#define MACHVEC_PLATFORM_NAME sn1 +#define MACHVEC_PLATFORM_NAME sn1 +#define MACHVEC_PLATFORM_HEADER #else CONFIG_IA64_SGI_SN1 -#define MACHVEC_PLATFORM_NAME sn2 +#define MACHVEC_PLATFORM_NAME sn2 +#define MACHVEC_PLATFORM_HEADER #else #error "unknown platform" #endif diff -urN linux-2.5.69-bk6/arch/ia64/tools/print_offsets.c linux-2.5.69-bk7/arch/ia64/tools/print_offsets.c --- linux-2.5.69-bk6/arch/ia64/tools/print_offsets.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/arch/ia64/tools/print_offsets.c 2003-05-12 04:43:29.000000000 -0700 @@ -193,7 +193,7 @@ printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by " "arch/ia64/tools/print_offsets.\n *\n */\n\n"); - for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i) + for (i = 0; i < (int) (sizeof (tab) / sizeof (tab[0])); ++i) { if (tab[i].name[0] == '\0') printf ("\n"); diff -urN linux-2.5.69-bk6/drivers/Makefile linux-2.5.69-bk7/drivers/Makefile --- linux-2.5.69-bk6/drivers/Makefile 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/drivers/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -37,6 +37,7 @@ obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_USB) += usb/ +obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_SERIO) += input/serio/ diff -urN linux-2.5.69-bk6/drivers/char/agp/Kconfig linux-2.5.69-bk7/drivers/char/agp/Kconfig --- linux-2.5.69-bk6/drivers/char/agp/Kconfig 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/Kconfig 2003-05-12 04:43:29.000000000 -0700 @@ -1,6 +1,6 @@ config AGP tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU - default AGP_GART if GART_IOMMU + default y if GART_IOMMU ---help--- AGP (Accelerated Graphics Port) is a bus system mainly used to connect graphics cards to the rest of the system. @@ -25,54 +25,66 @@ a module, say M here and read . The module will be called agpgart. -config AGP_GART - bool "/dev/agpgart (AGP Support)" - depends on GART_IOMMU - -config AGP_INTEL - tristate "Intel 440LX/BX/GX, I8xx and E7x05 support" - depends on AGP && !X86_64 - help +config AGP_ALI + tristate "ALI chipset support" + depends on AGP && X86 && !X86_64 + ---help--- This option gives you AGP support for the GLX component of the - XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860 - E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G, - 852GM, 855GM and 865G integrated graphics chipsets. + XFree86 4.x on the following ALi chipsets. The supported chipsets + include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. + For the ALi-chipset question, ALi suggests you refer to + . - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI, or if you have any Intel integrated graphics - chipsets. If unsure, say Y. + The M1541 chipset can do AGP 1x and 2x, but note that there is an + acknowledged incompatibility with Matrox G200 cards. Due to + timing issues, this chipset cannot do AGP 2x with the G200. + This is a hardware limitation. AGP 1x seems to be fine, though. -#config AGP_I810 -# tristate "Intel I810/I815/I830M (on-board) support" -# depends on AGP && !X86_64 -# help -# This option gives you AGP support for the Xserver on the Intel 810 -# 815 and 830m chipset boards for their on-board integrated graphics. This -# is required to do any useful video modes with these boards. + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. -config AGP_VIA - tristate "VIA chipset support" - depends on AGP && !X86_64 +config AGP_AMD + tristate "AMD Irongate, 761, and 762 chipset support" + depends on AGP && X86 && !X86_64 help This option gives you AGP support for the GLX component of the - XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + XFree86 4.x on AMD Irongate, 761, and 762 chipsets. You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. -config AGP_AMD - tristate "AMD Irongate, 761, and 762 support" - depends on AGP && !X86_64 +config AGP_AMD_8151 + tristate "AMD 8151 chipset support" + depends on AGP && X86 + default GART_IOMMU + help + Say Y here to support the AMD 8151 AGP bridge and the builtin + GART on the AMD Athlon64/Opteron ("Hammer") CPUs. + +config AGP_INTEL + tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support" + depends on AGP && X86 && !X86_64 help This option gives you AGP support for the GLX component of the - XFree86 4.x on AMD Irongate, 761, and 762 chipsets. + XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860 + E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G, + 852GM, 855GM and 865G integrated graphics chipsets. You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. + use GLX or DRI, or if you have any Intel integrated graphics + chipsets. If unsure, say Y. + +config AGP_NVIDIA + tristate "NVIDIA nForce/nForce2 chipset support" + depends on AGP && X86 && !X86_64 + help + This option gives you AGP support for the GLX component of the + XFree86 4.x on the following NVIDIA chipsets. The supported chipsets + include nForce and nForce2 config AGP_SIS - tristate "Generic SiS support" - depends on AGP && !X86_64 + tristate "SiS chipset support" + depends on AGP && X86 && !X86_64 help This option gives you AGP support for the GLX component of the "soon to be released" XFree86 4.x on Silicon Integrated Systems [SiS] @@ -83,55 +95,39 @@ You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. -config AGP_ALI - tristate "ALI chipset support" - depends on AGP && !X86_64 - ---help--- - This option gives you AGP support for the GLX component of the - XFree86 4.x on the following ALi chipsets. The supported chipsets - include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. - For the ALi-chipset question, ALi suggests you refer to - . - - The M1541 chipset can do AGP 1x and 2x, but note that there is an - acknowledged incompatibility with Matrox G200 cards. Due to - timing issues, this chipset cannot do AGP 2x with the G200. - This is a hardware limitation. AGP 1x seems to be fine, though. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. - config AGP_SWORKS - tristate "Serverworks LE/HE support" - depends on AGP && !X86_64 + tristate "Serverworks LE/HE chipset support" + depends on AGP && X86 && !X86_64 help Say Y here to support the Serverworks AGP card. See for product descriptions and images. -config AGP_AMD_8151 - tristate "AMD 8151 support" - depends on AGP - default GART_IOMMU +config AGP_VIA + tristate "VIA chipset support" + depends on AGP && X86 && !X86_64 help - Say Y here to support the AMD 8151 AGP bridge and the builtin - GART on the AMD Athlon64/Opteron ("Hammer") CPUs. + This option gives you AGP support for the GLX component of the + XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. config AGP_I460 - tristate "Intel 460GX support" + tristate "Intel 460GX chipset support" depends on AGP && IA64 help This option gives you AGP GART support for the Intel 460GX chipset for IA64 processors. config AGP_HP_ZX1 - tristate "HP ZX1 AGP support" + tristate "HP ZX1 chipset AGP support" depends on AGP && IA64 help This option gives you AGP GART support for the HP ZX1 chipset for IA64 processors. config AGP_ALPHA_CORE - tristate + tristate "Alpha AGP support" depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL) default AGP diff -urN linux-2.5.69-bk6/drivers/char/agp/Makefile linux-2.5.69-bk7/drivers/char/agp/Makefile --- linux-2.5.69-bk6/drivers/char/agp/Makefile 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/Makefile 2003-05-12 04:43:29.000000000 -0700 @@ -1,21 +1,15 @@ -# -# Makefile for the agpgart device driver. This driver adds a user -# space ioctl interface to use agp memory. It also adds a kernel interface -# that other drivers could use to manipulate agp memory. - agpgart-y := backend.o frontend.o generic.o generic-3.0.o -agpgart-objs := $(agpgart-y) -obj-$(CONFIG_AGP) += agpgart.o -obj-$(CONFIG_AGP_INTEL) += intel-agp.o -obj-$(CONFIG_AGP_VIA) += via-agp.o -obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o -obj-$(CONFIG_AGP_SIS) += sis-agp.o +obj-$(CONFIG_AGP) += agpgart.o obj-$(CONFIG_AGP_ALI) += ali-agp.o -obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o -obj-$(CONFIG_AGP_I460) += i460-agp.o -obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o +obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o obj-$(CONFIG_AGP_AMD_8151) += amd-k8-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o - +obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o +obj-$(CONFIG_AGP_I460) += i460-agp.o +obj-$(CONFIG_AGP_INTEL) += intel-agp.o +obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o +obj-$(CONFIG_AGP_SIS) += sis-agp.o +obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o +obj-$(CONFIG_AGP_VIA) += via-agp.o diff -urN linux-2.5.69-bk6/drivers/char/agp/agp.h linux-2.5.69-bk7/drivers/char/agp/agp.h --- linux-2.5.69-bk6/drivers/char/agp/agp.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/agp.h 2003-05-12 04:43:29.000000000 -0700 @@ -30,27 +30,16 @@ #include /* for flush_agp_cache() */ -extern struct agp_bridge_data *agp_bridge; - #define PFX "agpgart: " -#ifdef CONFIG_SMP -static void ipi_handler(void *null) -{ - flush_agp_cache(); -} - -static void __attribute__((unused)) global_cache_flush(void) -{ - if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0) - panic(PFX "timed out waiting for the other CPUs!\n"); -} +//#define AGP_DEBUG 1 +#ifdef AGP_DEBUG +#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __FUNCTION__ , ## y) #else -static void global_cache_flush(void) -{ - flush_agp_cache(); -} -#endif /* !CONFIG_SMP */ +#define DBG(x,y...) do { } while (0) +#endif + +extern struct agp_bridge_data *agp_bridge; enum aper_size_type { U8_APER_SIZE, @@ -101,14 +90,41 @@ int page_order; }; +struct agp_bridge_driver { + struct module *owner; + void *aperture_sizes; + int num_aperture_sizes; + enum aper_size_type size_type; + int cant_use_aperture; + int needs_scratch_page; + struct gatt_mask *masks; + int (*fetch_size)(void); + int (*configure)(void); + void (*agp_enable)(u32); + void (*cleanup)(void); + void (*tlb_flush)(agp_memory *); + unsigned long (*mask_memory)(unsigned long, int); + void (*cache_flush)(void); + int (*create_gatt_table)(void); + int (*free_gatt_table)(void); + int (*insert_memory)(agp_memory *, off_t, int); + int (*remove_memory)(agp_memory *, off_t, int); + agp_memory *(*alloc_by_type) (size_t, int); + void (*free_by_type)(agp_memory *); + void *(*agp_alloc_page)(void); + void (*agp_destroy_page)(void *); + int (*suspend)(void); + void (*resume)(void); +}; + struct agp_bridge_data { struct agp_version *version; - void *aperture_sizes; + struct agp_bridge_driver *driver; + struct vm_operations_struct *vm_ops; void *previous_size; void *current_size; void *dev_private_data; struct pci_dev *dev; - struct gatt_mask *masks; u32 *gatt_table; u32 *gatt_table_real; unsigned long scratch_page; @@ -117,38 +133,12 @@ unsigned long gatt_bus_addr; u32 mode; enum chipset_type type; - enum aper_size_type size_type; unsigned long *key_list; atomic_t current_memory_agp; atomic_t agp_in_use; int max_memory_agp; /* in number of pages */ - int needs_scratch_page; int aperture_size_idx; - int num_aperture_sizes; int capndx; - int cant_use_aperture; - struct vm_operations_struct *vm_ops; - - /* Links to driver specific functions */ - - int (*fetch_size) (void); - int (*configure) (void); - void (*agp_enable) (u32); - void (*cleanup) (void); - void (*tlb_flush) (agp_memory *); - unsigned long (*mask_memory) (unsigned long, int); - void (*cache_flush) (void); - int (*create_gatt_table) (void); - int (*free_gatt_table) (void); - int (*insert_memory) (agp_memory *, off_t, int); - int (*remove_memory) (agp_memory *, off_t, int); - agp_memory *(*alloc_by_type) (size_t, int); - void (*free_by_type) (agp_memory *); - void *(*agp_alloc_page) (void); - void (*agp_destroy_page) (void *); - int (*suspend)(void); - void (*resume)(void); - }; #define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr)) @@ -165,20 +155,17 @@ #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) -#define CACHE_FLUSH agp_bridge->cache_flush #define A_SIZE_8(x) ((struct aper_size_info_8 *) x) #define A_SIZE_16(x) ((struct aper_size_info_16 *) x) #define A_SIZE_32(x) ((struct aper_size_info_32 *) x) #define A_SIZE_LVL2(x) ((struct aper_size_info_lvl2 *) x) #define A_SIZE_FIX(x) ((struct aper_size_info_fixed *) x) -#define A_IDX8() (A_SIZE_8(agp_bridge->aperture_sizes) + i) -#define A_IDX16() (A_SIZE_16(agp_bridge->aperture_sizes) + i) -#define A_IDX32() (A_SIZE_32(agp_bridge->aperture_sizes) + i) -#define A_IDXLVL2() (A_SIZE_LVL2(agp_bridge->aperture_sizes) + i) -#define A_IDXFIX() (A_SIZE_FIX(agp_bridge->aperture_sizes) + i) +#define A_IDX8(bridge) (A_SIZE_8((bridge)->driver->aperture_sizes) + i) +#define A_IDX16(bridge) (A_SIZE_16((bridge)->driver->aperture_sizes) + i) +#define A_IDX32(bridge) (A_SIZE_32((bridge)->driver->aperture_sizes) + i) #define MAXKEY (4096 * 32) -#define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge->scratch_page) +#define PGE_EMPTY(b, p) (!(p) || (p) == (unsigned long) (b)->scratch_page) /* intel register */ #define INTEL_APBASE 0x10 @@ -374,11 +361,15 @@ int (*chipset_setup) (struct pci_dev *pdev); /* used to override generic */ }; -struct agp_driver { - struct module *owner; - struct pci_dev *dev; -}; - +/* Driver registration */ +struct agp_bridge_data *agp_alloc_bridge(void); +void agp_put_bridge(struct agp_bridge_data *bridge); +int agp_add_bridge(struct agp_bridge_data *bridge); +void agp_remove_bridge(struct agp_bridge_data *bridge); + +/* Frontend routines. */ +int agp_frontend_initialize(void); +void agp_frontend_cleanup(void); /* Generic routines. */ void agp_generic_enable(u32 mode); @@ -395,10 +386,29 @@ void agp_generic_resume(void); void agp_free_key(int key); int agp_num_entries(void); -int agp_register_driver (struct agp_driver *drv); -int agp_unregister_driver(struct agp_driver *drv); u32 agp_collect_device_status(u32 mode, u32 command); void agp_device_command(u32 command, int agp_v3); -int agp_3_0_node_enable(u32 mode, u32 minor); +int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor); +void global_cache_flush(void); + +/* Standard agp registers */ +#define AGPSTAT 0x4 +#define AGPCMD 0x8 +#define AGPNEPG 0x16 + +#define AGP_MAJOR_VERSION_SHIFT (20) +#define AGP_MINOR_VERSION_SHIFT (16) + +#define AGPSTAT_RQ_DEPTH (0xff000000) + +#define AGPSTAT_ARQSZ_SHIFT 13 + +#define AGPSTAT_AGP_ENABLE (1<<8) +#define AGPSTAT_SBA (1<<9) + +#define AGPSTAT2_1X (1<<0) +#define AGPSTAT2_2X (1<<1) +#define AGPSTAT2_4X (1<<2) +#define AGPSTAT_FW (1<<4) #endif /* _AGP_BACKEND_PRIV_H */ diff -urN linux-2.5.69-bk6/drivers/char/agp/ali-agp.c linux-2.5.69-bk7/drivers/char/agp/ali-agp.c --- linux-2.5.69-bk6/drivers/char/agp/ali-agp.c 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/ali-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -19,9 +19,9 @@ pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp); temp &= ~(0xfffffff0); - values = A_SIZE_32(agp_bridge->aperture_sizes); + values = A_SIZE_32(agp_bridge->driver->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -118,47 +118,51 @@ { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } -static void ali_cache_flush(void) +static void m1541_cache_flush(void) { - global_cache_flush(); + int i, page_count; + u32 temp; - if (agp_bridge->type == ALI_M1541) { - int i, page_count; - u32 temp; + global_cache_flush(); - page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order; - for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - (agp_bridge->gatt_bus_addr + i)) | - ALI_CACHE_FLUSH_EN)); - } + page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order; + for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + (agp_bridge->gatt_bus_addr + i)) | + ALI_CACHE_FLUSH_EN)); } } -static void *ali_alloc_page(void) +static void *m1541_alloc_page(void) { - void *adr = agp_generic_alloc_page(); + void *addr = agp_generic_alloc_page(); u32 temp; - if (adr == 0) - return 0; + if (!addr) + return NULL; + + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN )); + return addr; +} - if (agp_bridge->type == ALI_M1541) { - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(adr)) | - ALI_CACHE_FLUSH_EN )); +static void ali_destroy_page(void * addr) +{ + if (addr) { + global_cache_flush(); /* is this really needed? --hch */ + agp_generic_destroy_page(addr); } - return adr; } -static void ali_destroy_page(void * addr) +static void m1541_destroy_page(void * addr) { u32 temp; @@ -167,17 +171,14 @@ global_cache_flush(); - if (agp_bridge->type == ALI_M1541) { - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(addr)) | - ALI_CACHE_FLUSH_EN)); - } - + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN)); agp_generic_destroy_page(addr); } + /* Setup function */ static struct gatt_mask ali_generic_masks[] = { @@ -195,170 +196,185 @@ {4, 1024, 0, 3} }; -static int __init ali_generic_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = ali_generic_masks; - agp_bridge->aperture_sizes = (void *) ali_generic_sizes; - agp_bridge->size_type = U32_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = ali_configure; - agp_bridge->fetch_size = ali_fetch_size; - agp_bridge->cleanup = ali_cleanup; - agp_bridge->tlb_flush = ali_tlbflush; - agp_bridge->mask_memory = ali_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = ali_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = ali_alloc_page; - agp_bridge->agp_destroy_page = ali_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver ali_generic_bridge = { + .owner = THIS_MODULE, + .masks = ali_generic_masks, + .aperture_sizes = ali_generic_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = ali_configure, + .fetch_size = ali_fetch_size, + .cleanup = ali_cleanup, + .tlb_flush = ali_tlbflush, + .mask_memory = ali_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = ali_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +struct agp_bridge_driver ali_m1541_bridge = { + .owner = THIS_MODULE, + .masks = ali_generic_masks, + .aperture_sizes = ali_generic_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = ali_configure, + .fetch_size = ali_fetch_size, + .cleanup = ali_cleanup, + .tlb_flush = ali_tlbflush, + .mask_memory = ali_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = m1541_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = m1541_alloc_page, + .agp_destroy_page = m1541_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + struct agp_device_ids ali_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_AL_M1541, - .chipset = ALI_M1541, .chipset_name = "M1541", }, { .device_id = PCI_DEVICE_ID_AL_M1621, - .chipset = ALI_M1621, .chipset_name = "M1621", }, { .device_id = PCI_DEVICE_ID_AL_M1631, - .chipset = ALI_M1631, .chipset_name = "M1631", }, { .device_id = PCI_DEVICE_ID_AL_M1632, - .chipset = ALI_M1632, .chipset_name = "M1632", }, { .device_id = PCI_DEVICE_ID_AL_M1641, - .chipset = ALI_M1641, .chipset_name = "M1641", }, { .device_id = PCI_DEVICE_ID_AL_M1644, - .chipset = ALI_M1644, .chipset_name = "M1644", }, { .device_id = PCI_DEVICE_ID_AL_M1647, - .chipset = ALI_M1647, .chipset_name = "M1647", }, { .device_id = PCI_DEVICE_ID_AL_M1651, - .chipset = ALI_M1651, .chipset_name = "M1651", }, { .device_id = PCI_DEVICE_ID_AL_M1671, - .chipset = ALI_M1671, .chipset_name = "M1671", }, { }, /* dummy final entry, always present */ }; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_ali_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = ali_agp_device_ids; + struct agp_device_ids *devs = ali_agp_device_ids; + struct agp_bridge_data *bridge; + u8 hidden_1621_id, cap_ptr; + int j; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - if (pdev->device == PCI_DEVICE_ID_AL_M1621) { - u8 hidden_1621_id; - - pci_read_config_byte(pdev, 0xFB, &hidden_1621_id); - switch (hidden_1621_id) { - case 0x31: - devs[j].chipset_name="M1631"; - break; - case 0x32: - devs[j].chipset_name="M1632"; - break; - case 0x41: - devs[j].chipset_name="M1641"; - break; - case 0x43: - break; - case 0x47: - devs[j].chipset_name="M1647"; - break; - case 0x51: - devs[j].chipset_name="M1651"; - break; - default: - break; - } - } - - printk (KERN_INFO PFX "Detected ALi %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return ali_generic_setup(pdev); - } - j++; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name; j++) { + if (pdev->device == devs[j].device_id) + goto found; } - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic ALi routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = ALI_GENERIC; - return ali_generic_setup(pdev); + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported ALi chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic ALi routines" + " for device id: %04x\n", pdev->device); -static struct agp_driver ali_agp_driver = { - .owner = THIS_MODULE, -}; +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + switch (pdev->device) { + case PCI_DEVICE_ID_AL_M1541: + bridge->driver = &ali_m1541_bridge; + break; + case PCI_DEVICE_ID_AL_M1621: + pci_read_config_byte(pdev, 0xFB, &hidden_1621_id); + switch (hidden_1621_id) { + case 0x31: + devs[j].chipset_name = "M1631"; + break; + case 0x32: + devs[j].chipset_name = "M1632"; + break; + case 0x41: + devs[j].chipset_name = "M1641"; + break; + case 0x43: + break; + case 0x47: + devs[j].chipset_name = "M1647"; + break; + case 0x51: + devs[j].chipset_name = "M1651"; + break; + default: + break; + } + /*FALLTHROUGH*/ + default: + bridge->driver = &ali_generic_bridge; + } -static int __init agp_ali_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + printk(KERN_INFO PFX "Detected ALi %s chipset\n", + devs[j].chipset_name); - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); - /* probe for known chipsets */ - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - ali_agp_driver.dev = dev; - agp_register_driver(&ali_agp_driver); - return 0; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_ali_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_ali_pci_table[] __initdata = { @@ -379,22 +395,16 @@ .name = "agpgart-ali", .id_table = agp_ali_pci_table, .probe = agp_ali_probe, + .remove = agp_ali_remove, }; static int __init agp_ali_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_ali_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_ali_pci_driver); } static void __exit agp_ali_cleanup(void) { - agp_unregister_driver(&ali_agp_driver); pci_unregister_driver(&agp_ali_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/alpha-agp.c linux-2.5.69-bk7/drivers/char/agp/alpha-agp.c --- linux-2.5.69-bk6/drivers/char/agp/alpha-agp.c 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/alpha-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -81,7 +81,7 @@ static unsigned long alpha_core_agp_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static void alpha_core_agp_enable(u32 mode) @@ -109,7 +109,7 @@ status = agp->ops->bind(agp, pg_start, mem); mb(); - agp_bridge->tlb_flush(mem); + alpha_core_agp_tlbflush(mem); return status; } @@ -121,29 +121,57 @@ int status; status = agp->ops->unbind(agp, pg_start, mem); - agp_bridge->tlb_flush(mem); + alpha_core_agp_tlbflush(mem); return status; } - -static struct agp_driver alpha_core_agp_driver = { - .owner = THIS_MODULE, +struct agp_bridge_driver alpha_core_agp_driver = { + .owner = THIS_MODULE, + .masks = alpha_core_agp_masks, + .aperture_sizes = aper_size, + .current_size = aper_size, /* only one entry */ + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 1, + .configure = alpha_core_agp_configure, + .fetch_size = alpha_core_agp_fetch_size, + .cleanup = alpha_core_agp_cleanup, + .tlb_flush = alpha_core_agp_tlbflush, + .mask_memory = alpha_core_agp_mask_memory, + .agp_enable = alpha_core_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = alpha_core_agp_nop, + .free_gatt_table = alpha_core_agp_nop, + .insert_memory = alpha_core_agp_insert_memory, + .remove_memory = alpha_core_agp_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .mode = agp->capability.lw, + .cant_use_aperture = 1, + .vm_ops = &alpha_core_agp_vm_ops, }; +struct agp_bridge_data *alpha_bridge; + int __init alpha_core_agp_setup(void) { alpha_agp_info *agp = alpha_mv.agp_info(); + struct pci_dev *pdev; /* faked */ struct aper_size_info_fixed *aper_size; - if (!agp) return -ENODEV; - if (agp->ops->setup(agp)) return -ENODEV; + if (!agp) + return -ENODEV; + if (agp->ops->setup(agp)) + return -ENODEV; /* * Build the aperture size descriptor */ aper_size = alpha_core_agp_sizes; - if (!aper_size) return -ENOMEM; + if (!aper_size) + return -ENOMEM; aper_size->size = agp->aperture.size / (1024 * 1024); aper_size->num_entries = agp->aperture.size / PAGE_SIZE; aper_size->page_order = ffs(aper_size->num_entries / 1024) - 1; @@ -151,63 +179,40 @@ /* * Build a fake pci_dev struct */ - if (!(agp_bridge->dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL))) { + pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + if (!pdev) return -ENOMEM; - } - agp_bridge->dev->vendor = 0xffff; - agp_bridge->dev->device = 0xffff; - agp_bridge->dev->sysdata = agp->hose; - - /* - * Fill in the rest of the agp_bridge struct - */ - agp_bridge->masks = alpha_core_agp_masks; - agp_bridge->aperture_sizes = aper_size; - agp_bridge->current_size = aper_size; /* only one entry */ - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->num_aperture_sizes = 1; - agp_bridge->dev_private_data = agp; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = alpha_core_agp_configure; - agp_bridge->fetch_size = alpha_core_agp_fetch_size; - agp_bridge->cleanup = alpha_core_agp_cleanup; - agp_bridge->tlb_flush = alpha_core_agp_tlbflush; - agp_bridge->mask_memory = alpha_core_agp_mask_memory; - agp_bridge->agp_enable = alpha_core_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = alpha_core_agp_nop; - agp_bridge->free_gatt_table = alpha_core_agp_nop; - agp_bridge->insert_memory = alpha_core_agp_insert_memory; - agp_bridge->remove_memory = alpha_core_agp_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->mode = agp->capability.lw; - agp_bridge->cant_use_aperture = 1; - agp_bridge->vm_ops = &alpha_core_agp_vm_ops; + pdev->vendor = 0xffff; + pdev->device = 0xffff; + pdev->sysdata = agp->hose; + + alpha_bridge = agp_alloc_bridge(); + if (!alpha_bridge) + goto fail; + + alpha_bridge->driver = &alpha_core_agp_driver; + alpha_bridge->dev_private_data = agp; + alpha_bridge->dev = pdev; - alpha_core_agp_driver.dev = agp_bridge->dev; - agp_register_driver(&alpha_core_agp_driver); printk(KERN_INFO "Detected AGP on hose %d\n", agp->hose->index); - return 0; + return agp_add_bridge(alpha_bridge); + + fail: + kfree(pdev); + return -ENOMEM; } static int __init agp_alpha_core_init(void) { - int ret_val = -ENODEV; - if (alpha_mv.agp_info) { - agp_bridge->type = ALPHA_CORE_AGP; - ret_val = alpha_core_agp_setup(); - } - - return ret_val; + if (alpha_mv.agp_info) + return alpha_core_agp_setup(); + return -ENODEV; } static void __exit agp_alpha_core_cleanup(void) { - agp_unregister_driver(&alpha_core_agp_driver); - /* no pci driver for core */ + agp_remove_bridge(alpha_bridge); + agp_put_bridge(alpha_bridge); } module_init(agp_alpha_core_init); diff -urN linux-2.5.69-bk6/drivers/char/agp/amd-k7-agp.c linux-2.5.69-bk7/drivers/char/agp/amd-k7-agp.c --- linux-2.5.69-bk6/drivers/char/agp/amd-k7-agp.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/amd-k7-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -33,7 +33,7 @@ return -ENOMEM; } SetPageReserved(virt_to_page(page_map->real)); - CACHE_FLUSH(); + global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { @@ -42,7 +42,7 @@ page_map->real = NULL; return -ENOMEM; } - CACHE_FLUSH(); + global_cache_flush(); for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { page_map->remapped[i] = agp_bridge->scratch_page; @@ -75,6 +75,7 @@ } } kfree(tables); + amd_irongate_private.gatt_pages = NULL; } static int amd_create_gatt_pages(int nr_tables) @@ -184,8 +185,8 @@ pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp); temp = (temp & 0x0000000e); - values = A_SIZE_LVL2(agp_bridge->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -274,7 +275,7 @@ { /* Only type 0 is supported by the irongate */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static int amd_insert_memory(agp_memory * mem, @@ -297,14 +298,13 @@ while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) return -EBUSY; - } j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -312,9 +312,9 @@ addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); cur_gatt[GET_GATT_OFF(addr)] = - agp_bridge->mask_memory(mem->memory[i], mem->type); + amd_irongate_mask_memory(mem->memory[i], mem->type); } - agp_bridge->tlb_flush(mem); + amd_irongate_tlbflush(mem); return 0; } @@ -335,7 +335,7 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + amd_irongate_tlbflush(mem); return 0; } @@ -355,115 +355,104 @@ {.mask = 0x00000001, .type = 0} }; -static int __init amd_irongate_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = amd_irongate_masks; - agp_bridge->aperture_sizes = (void *) amd_irongate_sizes; - agp_bridge->size_type = LVL2_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = (void *) &amd_irongate_private; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = amd_irongate_configure; - agp_bridge->fetch_size = amd_irongate_fetch_size; - agp_bridge->cleanup = amd_irongate_cleanup; - agp_bridge->tlb_flush = amd_irongate_tlbflush; - agp_bridge->mask_memory = amd_irongate_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = amd_create_gatt_table; - agp_bridge->free_gatt_table = amd_free_gatt_table; - agp_bridge->insert_memory = amd_insert_memory; - agp_bridge->remove_memory = amd_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver amd_irongate_driver = { + .owner = THIS_MODULE, + .masks = amd_irongate_masks, + .aperture_sizes = amd_irongate_sizes, + .size_type = LVL2_APER_SIZE, + .num_aperture_sizes = 7, + .configure = amd_irongate_configure, + .fetch_size = amd_irongate_fetch_size, + .cleanup = amd_irongate_cleanup, + .tlb_flush = amd_irongate_tlbflush, + .mask_memory = amd_irongate_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = amd_create_gatt_table, + .free_gatt_table = amd_free_gatt_table, + .insert_memory = amd_insert_memory, + .remove_memory = amd_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; struct agp_device_ids amd_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006, - .chipset = AMD_IRONGATE, .chipset_name = "Irongate", }, { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_700E, - .chipset = AMD_761, .chipset_name = "761", }, { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_700C, - .chipset = AMD_762, .chipset_name = "760MP", }, { }, /* dummy final entry, always present */ }; - -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_amdk7_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = amd_agp_device_ids; + struct agp_device_ids *devs = amd_agp_device_ids; + struct agp_bridge_data *bridge; + u8 cap_ptr; + int j; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected AMD %s chipset\n", devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return amd_irongate_setup(pdev); + for (j = 0; devs[j].chipset_name; j++) { + if (pdev->device == devs[j].device_id) { + printk (KERN_INFO PFX "Detected AMD %s chipset\n", + devs[j].chipset_name); + goto found; } - j++; } - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic AMD routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = AMD_GENERIC; - return amd_irongate_setup(pdev); + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported AMD chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic AMD routines" + " for device id: %04x\n", pdev->device); +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; -static struct agp_driver amd_k7_agp_driver = { - .owner = THIS_MODULE, -}; + bridge->driver = &amd_irongate_driver; + bridge->dev_private_data = &amd_irongate_private, + bridge->dev = pdev; + bridge->capndx = cap_ptr; -/* Supported Device Scanning routine */ + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); -static int __init agp_amdk7_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; +static void __devexit agp_amdk7_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - amd_k7_agp_driver.dev = dev; - agp_register_driver(&amd_k7_agp_driver); - return 0; - } - return -ENODEV; + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_amdk7_pci_table[] __initdata = { @@ -484,22 +473,16 @@ .name = "agpgart-amdk7", .id_table = agp_amdk7_pci_table, .probe = agp_amdk7_probe, + .remove = agp_amdk7_remove, }; static int __init agp_amdk7_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_amdk7_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_amdk7_pci_driver); } static void __exit agp_amdk7_cleanup(void) { - agp_unregister_driver(&amd_k7_agp_driver); pci_unregister_driver(&agp_amdk7_pci_driver); } @@ -508,4 +491,3 @@ MODULE_PARM(agp_try_unsupported, "1i"); MODULE_LICENSE("GPL and additional rights"); - diff -urN linux-2.5.69-bk6/drivers/char/agp/amd-k8-agp.c linux-2.5.69-bk7/drivers/char/agp/amd-k8-agp.c --- linux-2.5.69-bk6/drivers/char/agp/amd-k8-agp.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/amd-k8-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -29,6 +29,21 @@ static int gart_iterator; #define for_each_nb() for(gart_iterator=0;gart_iteratorpage_count)) { - if (!PGE_EMPTY(agp_bridge->gatt_table[j])) + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) return -EBUSY; j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - addr = agp_bridge->mask_memory(mem->memory[i], mem->type); + addr = agp_bridge->driver->mask_memory(mem->memory[i], mem->type); tmp = addr; BUG_ON(tmp & 0xffffff0000000ffc); @@ -71,7 +86,7 @@ agp_bridge->gatt_table[j] = pte; } - agp_bridge->tlb_flush(mem); + amd_x86_64_tlbflush(mem); return 0; } @@ -113,7 +128,7 @@ temp = (temp & 0xe); values = A_SIZE_32(x86_64_aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -125,25 +140,6 @@ return 0; } - -static void flush_x86_64_tlb(struct pci_dev *dev) -{ - u32 tmp; - - pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp); - tmp |= 1<<0; - pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp); -} - - -static void amd_x86_64_tlbflush(agp_memory * temp) -{ - for_each_nb() { - flush_x86_64_tlb (hammers[gart_iterator]); - } -} - - /* * In a multiprocessor x86-64 system, this function gets * called once for each CPU. @@ -218,7 +214,7 @@ static unsigned long amd_8151_mask_memory(unsigned long addr, int type) { - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } @@ -227,130 +223,84 @@ {.mask = 0x00000001, .type = 0} }; +struct agp_bridge_driver amd_8151_driver = { + .owner = THIS_MODULE, + .masks = amd_8151_masks, + .aperture_sizes = amd_8151_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = amd_8151_configure, + .fetch_size = amd_x86_64_fetch_size, + .cleanup = amd_8151_cleanup, + .tlb_flush = amd_x86_64_tlbflush, + .mask_memory = amd_8151_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = x86_64_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -/* - * Try to configure an AGP v3 capable setup. - * If we fail (typically because we don't have an AGP v3 - * card in the system) we fall back to the generic AGP v2 - * routines. - */ -static void agp_x86_64_agp_enable(u32 mode) +static int __init agp_amdk8_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct pci_dev *device = NULL; - u32 command, scratch; + struct agp_bridge_data *bridge; + struct pci_dev *loop_dev; u8 cap_ptr; - u8 v3_devs=0; - - /* FIXME: If 'mode' is x1/x2/x4 should we call the AGPv2 routines directly ? - * Messy, as some AGPv3 cards can only do x4 as a minimum. - */ - - /* PASS1: Count # of devs capable of AGPv3 mode. */ - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) { - pci_read_config_dword(device, cap_ptr, &scratch); - scratch &= (1<<20|1<<21|1<<22|1<<23); - scratch = scratch>>20; - /* AGP v3 capable ? */ - if (scratch>=3) { - v3_devs++; - printk (KERN_INFO "AGP: Found AGPv3 capable device at %d:%d:%d\n", - device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn)); - } else { - printk (KERN_INFO "AGP: Meh. version %x AGP device found.\n", scratch); - } - } - } - /* If not enough, go to AGP v2 setup */ - if (v3_devs<2) { - printk (KERN_INFO "AGP: Only %d devices found, not enough, trying AGPv2\n", v3_devs); - return agp_generic_enable(mode); - } else { - printk (KERN_INFO "AGP: Enough AGPv3 devices found, setting up...\n"); - } - - - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &command); - - command = agp_collect_device_status(mode, command); - command |= 0x100; - - pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_COMMAND, command); - - agp_device_command(command, 1); -} + int i = 0; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; -static int __init amd_8151_setup (struct pci_dev *pdev) -{ - struct pci_dev *dev; - int i=0; + printk(KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n"); - agp_bridge->masks = amd_8151_masks; - agp_bridge->aperture_sizes = (void *) amd_8151_sizes; - agp_bridge->size_type = U32_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = amd_8151_configure; - agp_bridge->fetch_size = amd_x86_64_fetch_size; - agp_bridge->cleanup = amd_8151_cleanup; - agp_bridge->tlb_flush = amd_x86_64_tlbflush; - agp_bridge->mask_memory = amd_8151_mask_memory; - agp_bridge->agp_enable = agp_x86_64_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = x86_64_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + 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); /* cache pci_devs of northbridges. */ - pci_for_each_dev(dev) { - if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 && - (PCI_SLOT(dev->devfn) >=24) && (PCI_SLOT(dev->devfn) <=31)) { - - hammers[i++] = dev; + pci_for_each_dev(loop_dev) { + if (loop_dev->bus->number == 0 && + PCI_FUNC(loop_dev->devfn) == 3 && + PCI_SLOT(loop_dev->devfn) >=24 && + PCI_SLOT(loop_dev->devfn) <=31) { + hammers[i++] = loop_dev; nr_garts = i; - if (i==MAX_HAMMER_GARTS) - return 0; + if (i == MAX_HAMMER_GARTS) + goto out_free; } } - return 0; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); + out_free: + agp_put_bridge(bridge); + return -ENOMEM; } -static struct agp_driver amd_k8_agp_driver = { - .owner = THIS_MODULE, -}; - -static int __init agp_amdk8_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static void __devexit agp_amdk8_remove(struct pci_dev *pdev) { - u8 cap_ptr = 0; - - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - printk (KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n"); - - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - amd_8151_setup(dev); - amd_k8_agp_driver.dev = dev; - agp_register_driver(&amd_k8_agp_driver); - return 0; + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_amdk8_pci_table[] __initdata = { @@ -371,25 +321,17 @@ .name = "agpgart-amd-k8", .id_table = agp_amdk8_pci_table, .probe = agp_amdk8_probe, + .remove = agp_amdk8_remove, }; /* Not static due to IOMMU code calling it early. */ int __init agp_amdk8_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_amdk8_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - agp_bridge->type = AMD_8151; - - return ret_val; + return pci_module_init(&agp_amdk8_pci_driver); } static void __exit agp_amdk8_cleanup(void) { - agp_unregister_driver(&amd_k8_agp_driver); pci_unregister_driver(&agp_amdk8_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/backend.c linux-2.5.69-bk7/drivers/char/agp/backend.c --- linux-2.5.69-bk6/drivers/char/agp/backend.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/backend.c 2003-05-12 04:43:29.000000000 -0700 @@ -43,37 +43,54 @@ * past 0.99 at all due to some boolean logic error. */ #define AGPGART_VERSION_MAJOR 0 #define AGPGART_VERSION_MINOR 100 +static struct agp_version agp_current_version = +{ + .major = AGPGART_VERSION_MAJOR, + .minor = AGPGART_VERSION_MINOR, +}; + +static int agp_count=0; struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED }; struct agp_bridge_data *agp_bridge = &agp_bridge_dummy; +EXPORT_SYMBOL(agp_bridge); + +/** + * agp_backend_acquire - attempt to acquire the agp backend. + * + * returns -EBUSY if agp is in use, + * returns 0 if the caller owns the agp backend + */ int agp_backend_acquire(void) { if (agp_bridge->type == NOT_SUPPORTED) return -EINVAL; - - if (atomic_read(&agp_bridge->agp_in_use) != 0) + if (atomic_read(&agp_bridge->agp_in_use)) return -EBUSY; - atomic_inc(&agp_bridge->agp_in_use); return 0; } +EXPORT_SYMBOL(agp_backend_acquire); + +/** + * agp_backend_release - release the lock on the agp backend. + * + * The caller must insure that the graphics aperture translation table + * is read for use by another entity. + * + * (Ensure that all memory it bound is unbound.) + */ void agp_backend_release(void) { - if (agp_bridge->type == NOT_SUPPORTED) - return; - - atomic_dec(&agp_bridge->agp_in_use); + if (agp_bridge->type != NOT_SUPPORTED) + atomic_dec(&agp_bridge->agp_in_use); } +EXPORT_SYMBOL(agp_backend_release); -struct agp_max_table { - int mem; - int agp; -}; -static struct agp_max_table maxes_table[9] = -{ +struct { int mem, agp; } maxes_table[] = { {0, 0}, {32, 4}, {64, 28}, @@ -85,7 +102,7 @@ {4096, 3932} }; -static int agp_find_max (void) +static int agp_find_max(void) { long memory, index, result; @@ -105,48 +122,43 @@ return result; } -static struct agp_version agp_current_version = -{ - .major = AGPGART_VERSION_MAJOR, - .minor = AGPGART_VERSION_MINOR, -}; -static int agp_backend_initialize(struct pci_dev *dev) +static int agp_backend_initialize(struct agp_bridge_data *bridge) { int size_value, rc, got_gatt=0, got_keylist=0; - agp_bridge->max_memory_agp = agp_find_max(); - agp_bridge->version = &agp_current_version; + bridge->max_memory_agp = agp_find_max(); + bridge->version = &agp_current_version; - if (agp_bridge->needs_scratch_page == TRUE) { - void *addr; - addr = agp_bridge->agp_alloc_page(); + if (bridge->driver->needs_scratch_page) { + void *addr = bridge->driver->agp_alloc_page(); - if (addr == NULL) { + if (!addr) { printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); return -ENOMEM; } - agp_bridge->scratch_page_real = virt_to_phys(addr); - agp_bridge->scratch_page = - agp_bridge->mask_memory(agp_bridge->scratch_page_real, 0); - } - size_value = agp_bridge->fetch_size(); + bridge->scratch_page_real = virt_to_phys(addr); + bridge->scratch_page = + bridge->driver->mask_memory(bridge->scratch_page_real, 0); + } + size_value = bridge->driver->fetch_size(); if (size_value == 0) { printk(KERN_ERR PFX "unable to determine aperture size.\n"); rc = -EINVAL; goto err_out; } - if (agp_bridge->create_gatt_table()) { - printk(KERN_ERR PFX "unable to get memory for graphics translation table.\n"); + if (bridge->driver->create_gatt_table()) { + printk(KERN_ERR PFX + "unable to get memory for graphics translation table.\n"); rc = -ENOMEM; goto err_out; } got_gatt = 1; - agp_bridge->key_list = vmalloc(PAGE_SIZE * 4); - if (agp_bridge->key_list == NULL) { + bridge->key_list = vmalloc(PAGE_SIZE * 4); + if (bridge->key_list == NULL) { printk(KERN_ERR PFX "error allocating memory for key lists.\n"); rc = -ENOMEM; goto err_out; @@ -154,61 +166,62 @@ got_keylist = 1; /* FIXME vmalloc'd memory not guaranteed contiguous */ - memset(agp_bridge->key_list, 0, PAGE_SIZE * 4); + memset(bridge->key_list, 0, PAGE_SIZE * 4); - if (agp_bridge->configure()) { + if (bridge->driver->configure()) { printk(KERN_ERR PFX "error configuring host chipset.\n"); rc = -EINVAL; goto err_out; } printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n", - size_value, agp_bridge->gart_bus_addr); + size_value, bridge->gart_bus_addr); return 0; err_out: - if (agp_bridge->needs_scratch_page == TRUE) { - agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real)); - } + if (bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( + phys_to_virt(bridge->scratch_page_real)); if (got_gatt) - agp_bridge->free_gatt_table(); - if (got_keylist) - vfree(agp_bridge->key_list); + bridge->driver->free_gatt_table(); + if (got_keylist) { + vfree(bridge->key_list); + bridge->key_list = NULL; + } return rc; } - /* cannot be __exit b/c as it could be called from __init code */ -static void agp_backend_cleanup(void) +static void agp_backend_cleanup(struct agp_bridge_data *bridge) { - if (agp_bridge->cleanup != NULL) - agp_bridge->cleanup(); - if (agp_bridge->free_gatt_table != NULL) - agp_bridge->free_gatt_table(); - if (agp_bridge->key_list) - vfree(agp_bridge->key_list); - - if ((agp_bridge->agp_destroy_page!=NULL) && - (agp_bridge->needs_scratch_page == TRUE)) - agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real)); + if (bridge->driver->cleanup) + bridge->driver->cleanup(); + if (bridge->driver->free_gatt_table) + bridge->driver->free_gatt_table(); + if (bridge->key_list) { + vfree(bridge->key_list); + bridge->key_list = NULL; + } + + if (bridge->driver->agp_destroy_page && + bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( + phys_to_virt(bridge->scratch_page_real)); } static int agp_power(struct pm_dev *dev, pm_request_t rq, void *data) { - switch(rq) - { + switch(rq) { case PM_SUSPEND: - return agp_bridge->suspend(); + return agp_bridge->driver->suspend(); case PM_RESUME: - agp_bridge->resume(); + agp_bridge->driver->resume(); return 0; } return 0; } -extern int agp_frontend_initialize(void); -extern void agp_frontend_cleanup(void); static const drm_agp_t drm_agp = { &agp_free_memory, @@ -221,78 +234,81 @@ &agp_copy_info }; -static int agp_count=0; +/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */ +struct agp_bridge_data *agp_alloc_bridge(void) +{ + return agp_bridge; +} +EXPORT_SYMBOL(agp_alloc_bridge); + + +void agp_put_bridge(struct agp_bridge_data *bridge) +{ +} +EXPORT_SYMBOL(agp_put_bridge); -int agp_register_driver (struct agp_driver *drv) + +int agp_add_bridge(struct agp_bridge_data *bridge) { - int ret_val; + int error; - if (drv->dev == NULL) { - printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); + if (!bridge->dev) { + printk(KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); return -EINVAL; } - if (agp_count==1) { - printk (KERN_DEBUG PFX "Only one agpgart device currently supported.\n"); + if (agp_count) { + printk(KERN_DEBUG PFX + "Only one agpgart device currently supported.\n"); return -ENODEV; } /* Grab reference on the chipset driver. */ - if (!try_module_get(drv->owner)) + if (!try_module_get(bridge->driver->owner)) return -EINVAL; - ret_val = agp_backend_initialize(drv->dev); - if (ret_val) + bridge->type = SUPPORTED; + + error = agp_backend_initialize(agp_bridge); + if (error) goto err_out; - ret_val = agp_frontend_initialize(); - if (ret_val) + error = agp_frontend_initialize(); + if (error) goto frontend_err; /* FIXME: What to do with this? */ inter_module_register("drm_agp", THIS_MODULE, &drm_agp); - pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge->dev), agp_power); + pm_register(PM_PCI_DEV, PM_PCI_ID(bridge->dev), agp_power); agp_count++; return 0; frontend_err: - agp_backend_cleanup(); + agp_backend_cleanup(agp_bridge); err_out: - agp_bridge->type = NOT_SUPPORTED; - module_put(drv->owner); - drv->dev = NULL; - return ret_val; + bridge->type = NOT_SUPPORTED; + module_put(bridge->driver->owner); + return error; } +EXPORT_SYMBOL_GPL(agp_add_bridge); -int agp_unregister_driver(struct agp_driver *drv) -{ - if (drv->dev==NULL) - return -ENODEV; - agp_bridge->type = NOT_SUPPORTED; +void agp_remove_bridge(struct agp_bridge_data *bridge) +{ + bridge->type = NOT_SUPPORTED; pm_unregister_all(agp_power); agp_frontend_cleanup(); - agp_backend_cleanup(); + agp_backend_cleanup(bridge); inter_module_unregister("drm_agp"); agp_count--; - module_put(drv->owner); - return 0; + module_put(bridge->driver->owner); } +EXPORT_SYMBOL_GPL(agp_remove_bridge); -int __init agp_init(void) +static int __init agp_init(void) { - static int already_initialised=0; - - if (already_initialised!=0) - return 0; - - already_initialised = 1; - - memset(agp_bridge, 0, sizeof(struct agp_bridge_data)); - agp_bridge->type = NOT_SUPPORTED; - printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n", AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); return 0; @@ -300,19 +316,13 @@ void __exit agp_exit(void) { - if (agp_count!=0) - BUG(); } -#ifndef CONFIG_GART_IOMMU -module_init(agp_init); -module_exit(agp_exit); -#endif - -EXPORT_SYMBOL(agp_backend_acquire); -EXPORT_SYMBOL(agp_backend_release); -EXPORT_SYMBOL_GPL(agp_register_driver); -EXPORT_SYMBOL_GPL(agp_unregister_driver); MODULE_AUTHOR("Dave Jones "); +MODULE_DESCRIPTION("AGP GART driver"); MODULE_LICENSE("GPL and additional rights"); + +module_init(agp_init); +module_exit(agp_exit); + diff -urN linux-2.5.69-bk6/drivers/char/agp/frontend.c linux-2.5.69-bk7/drivers/char/agp/frontend.c --- linux-2.5.69-bk6/drivers/char/agp/frontend.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/frontend.c 2003-05-12 04:43:29.000000000 -0700 @@ -53,11 +53,12 @@ while (curr != NULL) { if (curr->key == key) - return curr; + break; curr = curr->next; } - return NULL; + DBG("key=%d -> mem=%p", key, curr); + return curr; } static void agp_remove_from_pool(agp_memory * temp) @@ -67,6 +68,7 @@ /* Check to see if this is even in the memory pool */ + DBG("mem=%p", temp); if (agp_find_mem_by_key(temp->key) != NULL) { next = temp->next; prev = temp->prev; @@ -92,11 +94,12 @@ * to each auth'ed client. */ -static agp_segment_priv *agp_find_seg_in_client(const agp_client * client, +static struct +agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client, unsigned long offset, int size, pgprot_t page_prot) { - agp_segment_priv *seg; + struct agp_segment_priv *seg; int num_segments, i; off_t pg_start; size_t pg_count; @@ -117,25 +120,32 @@ return NULL; } -static void agp_remove_seg_from_client(agp_client * client) +static void agp_remove_seg_from_client(struct agp_client *client) { + DBG("client=%p", client); + if (client->segments != NULL) { - if (*(client->segments) != NULL) + if (*(client->segments) != NULL) { + DBG("Freeing %p from client %p", *(client->segments), client); kfree(*(client->segments)); + } + DBG("Freeing %p from client %p", client->segments, client); kfree(client->segments); + client->segments = NULL; } } -static void agp_add_seg_to_client(agp_client * client, - agp_segment_priv ** seg, int num_segments) +static void agp_add_seg_to_client(struct agp_client *client, + struct agp_segment_priv ** seg, int num_segments) { - agp_segment_priv **prev_seg; + struct agp_segment_priv **prev_seg; prev_seg = client->segments; if (prev_seg != NULL) agp_remove_seg_from_client(client); + DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client); client->num_segments = num_segments; client->segments = seg; } @@ -171,19 +181,20 @@ return temp; } -static int agp_create_segment(agp_client * client, agp_region * region) +static int agp_create_segment(struct agp_client *client, struct agp_region *region) { - agp_segment_priv **ret_seg; - agp_segment_priv *seg; - agp_segment *user_seg; + struct agp_segment_priv **ret_seg; + struct agp_segment_priv *seg; + struct agp_segment *user_seg; size_t i; - seg = kmalloc((sizeof(agp_segment_priv) * region->seg_count), GFP_KERNEL); + seg = kmalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); if (seg == NULL) { kfree(region->seg_list); + region->seg_list = NULL; return -ENOMEM; } - memset(seg, 0, (sizeof(agp_segment_priv) * region->seg_count)); + memset(seg, 0, (sizeof(struct agp_segment_priv) * region->seg_count)); user_seg = region->seg_list; for (i = 0; i < region->seg_count; i++) { @@ -191,14 +202,15 @@ seg[i].pg_count = user_seg[i].pg_count; seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot); } + kfree(region->seg_list); + region->seg_list = NULL; + ret_seg = kmalloc(sizeof(void *), GFP_KERNEL); if (ret_seg == NULL) { - kfree(region->seg_list); kfree(seg); return -ENOMEM; } *ret_seg = seg; - kfree(region->seg_list); agp_add_seg_to_client(client, ret_seg, region->seg_count); return 0; } @@ -222,9 +234,9 @@ /* File private list routines */ -agp_file_private *agp_find_private(pid_t pid) +struct agp_file_private *agp_find_private(pid_t pid) { - agp_file_private *curr; + struct agp_file_private *curr; curr = agp_fe.file_priv_list; @@ -237,9 +249,9 @@ return NULL; } -void agp_insert_file_private(agp_file_private * priv) +void agp_insert_file_private(struct agp_file_private * priv) { - agp_file_private *prev; + struct agp_file_private *prev; prev = agp_fe.file_priv_list; @@ -249,10 +261,10 @@ agp_fe.file_priv_list = priv; } -void agp_remove_file_private(agp_file_private * priv) +void agp_remove_file_private(struct agp_file_private * priv) { - agp_file_private *next; - agp_file_private *prev; + struct agp_file_private *next; + struct agp_file_private *prev; next = priv->next; prev = priv->prev; @@ -301,9 +313,9 @@ * controllers */ -static agp_controller *agp_find_controller_by_pid(pid_t id) +static struct agp_controller *agp_find_controller_by_pid(pid_t id) { - agp_controller *controller; + struct agp_controller *controller; controller = agp_fe.controllers; @@ -316,24 +328,24 @@ return NULL; } -static agp_controller *agp_create_controller(pid_t id) +static struct agp_controller *agp_create_controller(pid_t id) { - agp_controller *controller; + struct agp_controller *controller; - controller = kmalloc(sizeof(agp_controller), GFP_KERNEL); + controller = kmalloc(sizeof(struct agp_controller), GFP_KERNEL); if (controller == NULL) return NULL; - memset(controller, 0, sizeof(agp_controller)); + memset(controller, 0, sizeof(struct agp_controller)); controller->pid = id; return controller; } -static int agp_insert_controller(agp_controller * controller) +static int agp_insert_controller(struct agp_controller *controller) { - agp_controller *prev_controller; + struct agp_controller *prev_controller; prev_controller = agp_fe.controllers; controller->next = prev_controller; @@ -346,15 +358,15 @@ return 0; } -static void agp_remove_all_clients(agp_controller * controller) +static void agp_remove_all_clients(struct agp_controller *controller) { - agp_client *client; - agp_client *temp; + struct agp_client *client; + struct agp_client *temp; client = controller->clients; while (client) { - agp_file_private *priv; + struct agp_file_private *priv; temp = client; agp_remove_seg_from_client(temp); @@ -369,7 +381,7 @@ } } -static void agp_remove_all_memory(agp_controller * controller) +static void agp_remove_all_memory(struct agp_controller *controller) { agp_memory *memory; agp_memory *temp; @@ -383,10 +395,10 @@ } } -static int agp_remove_controller(agp_controller * controller) +static int agp_remove_controller(struct agp_controller *controller) { - agp_controller *prev_controller; - agp_controller *next_controller; + struct agp_controller *prev_controller; + struct agp_controller *next_controller; prev_controller = controller->prev; next_controller = controller->next; @@ -415,14 +427,14 @@ return 0; } -static void agp_controller_make_current(agp_controller * controller) +static void agp_controller_make_current(struct agp_controller *controller) { - agp_client *clients; + struct agp_client *clients; clients = controller->clients; while (clients != NULL) { - agp_file_private *priv; + struct agp_file_private *priv; priv = agp_find_private(clients->pid); @@ -436,16 +448,16 @@ agp_fe.current_controller = controller; } -static void agp_controller_release_current(agp_controller * controller, - agp_file_private * controller_priv) +static void agp_controller_release_current(struct agp_controller *controller, + struct agp_file_private *controller_priv) { - agp_client *clients; + struct agp_client *clients; clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags); clients = controller->clients; while (clients != NULL) { - agp_file_private *priv; + struct agp_file_private *priv; priv = agp_find_private(clients->pid); @@ -465,10 +477,10 @@ * These routines are for managing the list of auth'ed clients. */ -static agp_client *agp_find_client_in_controller(agp_controller * controller, - pid_t id) +static struct agp_client +*agp_find_client_in_controller(struct agp_controller *controller, pid_t id) { - agp_client *client; + struct agp_client *client; if (controller == NULL) return NULL; @@ -484,9 +496,9 @@ return NULL; } -static agp_controller *agp_find_controller_for_client(pid_t id) +static struct agp_controller *agp_find_controller_for_client(pid_t id) { - agp_controller *controller; + struct agp_controller *controller; controller = agp_fe.controllers; @@ -499,9 +511,9 @@ return NULL; } -static agp_client *agp_find_client_by_pid(pid_t id) +static struct agp_client *agp_find_client_by_pid(pid_t id) { - agp_client *temp; + struct agp_client *temp; if (agp_fe.current_controller == NULL) return NULL; @@ -510,9 +522,9 @@ return temp; } -static void agp_insert_client(agp_client * client) +static void agp_insert_client(struct agp_client *client) { - agp_client *prev_client; + struct agp_client *prev_client; prev_client = agp_fe.current_controller->clients; client->next = prev_client; @@ -524,16 +536,16 @@ agp_fe.current_controller->num_clients++; } -static agp_client *agp_create_client(pid_t id) +static struct agp_client *agp_create_client(pid_t id) { - agp_client *new_client; + struct agp_client *new_client; - new_client = kmalloc(sizeof(agp_client), GFP_KERNEL); + new_client = kmalloc(sizeof(struct agp_client), GFP_KERNEL); if (new_client == NULL) return NULL; - memset(new_client, 0, sizeof(agp_client)); + memset(new_client, 0, sizeof(struct agp_client)); new_client->pid = id; agp_insert_client(new_client); return new_client; @@ -541,10 +553,10 @@ static int agp_remove_client(pid_t id) { - agp_client *client; - agp_client *prev_client; - agp_client *next_client; - agp_controller *controller; + struct agp_client *client; + struct agp_client *prev_client; + struct agp_client *next_client; + struct agp_controller *controller; controller = agp_find_controller_for_client(id); if (controller == NULL) @@ -582,11 +594,11 @@ { unsigned int size, current_size; unsigned long offset; - agp_client *client; - agp_file_private *priv = (agp_file_private *) file->private_data; + struct agp_client *client; + struct agp_file_private *priv = file->private_data; agp_kern_info kerninfo; - AGP_LOCK(); + down(&(agp_fe.agp_mutex)); if (agp_fe.backend_acquired != TRUE) goto out_eperm; @@ -599,6 +611,7 @@ current_size = kerninfo.aper_size; current_size = current_size * 0x100000; offset = vma->vm_pgoff << PAGE_SHIFT; + DBG("%lx:%lx", offset, offset+size); if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { if ((size + offset) > current_size) @@ -612,6 +625,7 @@ if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot)) goto out_inval; + DBG("client vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; } else if (remap_page_range(vma, vma->vm_start, @@ -619,7 +633,7 @@ size, vma->vm_page_prot)) { goto out_again; } - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return 0; } @@ -627,6 +641,7 @@ if (size != current_size) goto out_inval; + DBG("controller vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; } else if (remap_page_range(vma, vma->vm_start, @@ -634,68 +649,71 @@ size, vma->vm_page_prot)) { goto out_again; } - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return 0; } out_eperm: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return -EPERM; out_inval: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return -EINVAL; out_again: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return -EAGAIN; } static int agp_release(struct inode *inode, struct file *file) { - agp_file_private *priv = (agp_file_private *) file->private_data; + struct agp_file_private *priv = file->private_data; - AGP_LOCK(); + down(&(agp_fe.agp_mutex)); + + DBG("priv=%p", priv); if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { - agp_controller *controller; + struct agp_controller *controller; controller = agp_find_controller_by_pid(priv->my_pid); if (controller != NULL) { - if (controller == agp_fe.current_controller) { - agp_controller_release_current(controller, - priv); - } + if (controller == agp_fe.current_controller) + agp_controller_release_current(controller, priv); agp_remove_controller(controller); + controller = NULL; } } - if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { + + if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) agp_remove_client(priv->my_pid); - } + agp_remove_file_private(priv); kfree(priv); - AGP_UNLOCK(); + file->private_data = NULL; + up(&(agp_fe.agp_mutex)); return 0; } static int agp_open(struct inode *inode, struct file *file) { int minor = minor(inode->i_rdev); - agp_file_private *priv; - agp_client *client; + struct agp_file_private *priv; + struct agp_client *client; int rc = -ENXIO; - AGP_LOCK(); + down(&(agp_fe.agp_mutex)); if (minor != AGPGART_MINOR) goto err_out; - priv = kmalloc(sizeof(agp_file_private), GFP_KERNEL); + priv = kmalloc(sizeof(struct agp_file_private), GFP_KERNEL); if (priv == NULL) goto err_out_nomem; - memset(priv, 0, sizeof(agp_file_private)); + memset(priv, 0, sizeof(struct agp_file_private)); set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); priv->my_pid = current->pid; @@ -711,13 +729,14 @@ } file->private_data = (void *) priv; agp_insert_file_private(priv); - AGP_UNLOCK(); + DBG("private=%p, client=%p", priv, client); + up(&(agp_fe.agp_mutex)); return 0; err_out_nomem: rc = -ENOMEM; err_out: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return rc; } @@ -734,9 +753,9 @@ return -EINVAL; } -static int agpioc_info_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_info_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_info userinfo; + struct agp_info userinfo; agp_kern_info kerninfo; agp_copy_info(&kerninfo); @@ -751,17 +770,19 @@ userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; userinfo.pg_used = kerninfo.current_memory; - if (copy_to_user((void *) arg, &userinfo, sizeof(agp_info))) + if (copy_to_user((void *) arg, &userinfo, sizeof(struct agp_info))) return -EFAULT; return 0; } -static int agpioc_acquire_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_acquire_wrap(struct agp_file_private *priv, unsigned long arg) { int ret; + struct agp_controller *controller; + + DBG(""); - agp_controller *controller; if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags))) return -EPERM; @@ -795,33 +816,36 @@ return 0; } -static int agpioc_release_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_release_wrap(struct agp_file_private *priv, unsigned long arg) { + DBG(""); agp_controller_release_current(agp_fe.current_controller, priv); return 0; } -static int agpioc_setup_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_setup_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_setup mode; + struct agp_setup mode; - if (copy_from_user(&mode, (void *) arg, sizeof(agp_setup))) { + DBG(""); + if (copy_from_user(&mode, (void *) arg, sizeof(struct agp_setup))) return -EFAULT; - } + agp_enable(mode.agp_mode); return 0; } -static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_reserve_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_region reserve; - agp_client *client; - agp_file_private *client_priv; + struct agp_region reserve; + struct agp_client *client; + struct agp_file_private *client_priv; - if (copy_from_user(&reserve, (void *) arg, sizeof(agp_region))) + DBG(""); + if (copy_from_user(&reserve, (void *) arg, sizeof(struct agp_region))) return -EFAULT; - if ((unsigned) reserve.seg_count >= ~0U/sizeof(agp_segment)) + if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) return -EFAULT; client = agp_find_client_by_pid(reserve.pid); @@ -831,10 +855,8 @@ client_priv = agp_find_private(reserve.pid); if (client_priv != NULL) { - set_bit(AGP_FF_IS_CLIENT, - &client_priv->access_flags); - set_bit(AGP_FF_IS_VALID, - &client_priv->access_flags); + set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); + set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); } if (client == NULL) { /* client is already removed */ @@ -842,19 +864,19 @@ } return agp_remove_client(reserve.pid); } else { - agp_segment *segment; + struct agp_segment *segment; if (reserve.seg_count >= 16384) return -EINVAL; - - segment = kmalloc((sizeof(agp_segment) * reserve.seg_count), + + segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count), GFP_KERNEL); if (segment == NULL) return -ENOMEM; if (copy_from_user(segment, (void *) reserve.seg_list, - sizeof(agp_segment) * reserve.seg_count)) { + sizeof(struct agp_segment) * reserve.seg_count)) { kfree(segment); return -EFAULT; } @@ -871,32 +893,30 @@ client_priv = agp_find_private(reserve.pid); if (client_priv != NULL) { - set_bit(AGP_FF_IS_CLIENT, - &client_priv->access_flags); - set_bit(AGP_FF_IS_VALID, - &client_priv->access_flags); + set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); + set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); } - return agp_create_segment(client, &reserve); - } else { - return agp_create_segment(client, &reserve); } + return agp_create_segment(client, &reserve); } /* Will never really happen */ return -EINVAL; } -static int agpioc_protect_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_protect_wrap(struct agp_file_private *priv, unsigned long arg) { + DBG(""); /* This function is not currently implemented */ return -EINVAL; } -static int agpioc_allocate_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_allocate_wrap(struct agp_file_private *priv, unsigned long arg) { agp_memory *memory; - agp_allocate alloc; + struct agp_allocate alloc; - if (copy_from_user(&alloc, (void *) arg, sizeof(agp_allocate))) + DBG(""); + if (copy_from_user(&alloc, (void *) arg, sizeof(struct agp_allocate))) return -EFAULT; memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); @@ -907,17 +927,18 @@ alloc.key = memory->key; alloc.physical = memory->physical; - if (copy_to_user((void *) arg, &alloc, sizeof(agp_allocate))) { + if (copy_to_user((void *) arg, &alloc, sizeof(struct agp_allocate))) { agp_free_memory_wrap(memory); return -EFAULT; } return 0; } -static int agpioc_deallocate_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_deallocate_wrap(struct agp_file_private *priv, unsigned long arg) { agp_memory *memory; + DBG(""); memory = agp_find_mem_by_key((int) arg); if (memory == NULL) @@ -927,12 +948,13 @@ return 0; } -static int agpioc_bind_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_bind_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_bind bind_info; + struct agp_bind bind_info; agp_memory *memory; - if (copy_from_user(&bind_info, (void *) arg, sizeof(agp_bind))) + DBG(""); + if (copy_from_user(&bind_info, (void *) arg, sizeof(struct agp_bind))) return -EFAULT; memory = agp_find_mem_by_key(bind_info.key); @@ -943,12 +965,13 @@ return agp_bind_memory(memory, bind_info.pg_start); } -static int agpioc_unbind_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_unbind_wrap(struct agp_file_private *priv, unsigned long arg) { agp_memory *memory; - agp_unbind unbind; + struct agp_unbind unbind; - if (copy_from_user(&unbind, (void *) arg, sizeof(agp_unbind))) + DBG(""); + if (copy_from_user(&unbind, (void *) arg, sizeof(struct agp_unbind))) return -EFAULT; memory = agp_find_mem_by_key(unbind.key); @@ -962,10 +985,11 @@ static int agp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - agp_file_private *curr_priv = (agp_file_private *) file->private_data; + struct agp_file_private *curr_priv = file->private_data; int ret_val = -ENOTTY; - AGP_LOCK(); + DBG("priv=%p, cmd=%x", curr_priv, cmd); + down(&(agp_fe.agp_mutex)); if ((agp_fe.current_controller == NULL) && (cmd != AGPIOC_ACQUIRE)) { @@ -1034,7 +1058,8 @@ } ioctl_out: - AGP_UNLOCK(); + DBG("ioctl returns %d\n", ret_val); + up(&(agp_fe.agp_mutex)); return ret_val; } @@ -1060,7 +1085,7 @@ int agp_frontend_initialize(void) { memset(&agp_fe, 0, sizeof(struct agp_front_data)); - AGP_LOCK_INIT(); + sema_init(&(agp_fe.agp_mutex), 1); if (misc_register(&agp_miscdev)) { printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); diff -urN linux-2.5.69-bk6/drivers/char/agp/generic-3.0.c linux-2.5.69-bk7/drivers/char/agp/generic-3.0.c --- linux-2.5.69-bk6/drivers/char/agp/generic-3.0.c 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/generic-3.0.c 2003-05-12 04:43:29.000000000 -0700 @@ -18,7 +18,7 @@ struct pci_dev *dev; }; -static int agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new) +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; @@ -29,11 +29,9 @@ break; } list_add_tail(new, pos); - - return 0; } -static int agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs) +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; @@ -53,7 +51,6 @@ pos = pos->next; agp_3_0_dev_list_insert(head, tmp); } - return 0; } /* @@ -62,7 +59,8 @@ * lying behind it...) */ -static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs) +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 @@ -77,7 +75,7 @@ struct agp_3_0_dev *dev; }; - struct pci_dev *td = agp_bridge->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; @@ -114,11 +112,10 @@ * transfers are enabled and consequently whether maxbw will mean * anything. */ - if((ret = agp_3_0_dev_list_sort(dev_list, ndevs)) != 0) - goto free_and_exit; + agp_3_0_dev_list_sort(dev_list, ndevs); - pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat); - pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus); + 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; @@ -170,13 +167,13 @@ * 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, agp_bridge->capndx + 0x20, &tnicmd); + pci_read_config_word(td, bridge->capndx + 0x20, &tnicmd); tnicmd &= ~(0x3 << 6); tnicmd |= target.y << 6; - pci_write_config_word(td, agp_bridge->capndx + 0x20, tnicmd); + pci_write_config_word(td, bridge->capndx + 0x20, tnicmd); /* Reread the target's ISOCH_N */ - pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat); + pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat); target.n = (tnistat >> 8) & 0xff; /* Calculate the minimum ISOCH_N needed by each master */ @@ -260,7 +257,7 @@ ? (rem_async + rem_isoch) : step; pci_read_config_word(dev, cur->capndx + 0x20, &mnicmd); - pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd); + pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd); mnicmd &= ~(0xff << 8); mnicmd &= ~(0x3 << 6); @@ -270,7 +267,7 @@ mnicmd |= master[cdev].y << 6; mcmd |= master[cdev].rq << 24; - pci_write_config_dword(dev, cur->capndx + 0x08, mcmd); + pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd); pci_write_config_word(dev, cur->capndx + 0x20, mnicmd); } @@ -288,7 +285,8 @@ * 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 int agp_3_0_nonisochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs) +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; @@ -296,7 +294,7 @@ u32 trq, mrq, rem; unsigned int cdev = 0; - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x04, &tstatus); + pci_read_config_dword(bridge->dev, bridge->capndx + 0x04, &tstatus); trq = (tstatus >> 24) & 0xff; mrq = trq / ndevs; @@ -306,22 +304,20 @@ 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 + 0x08, &mcmd); + 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 + 0x08, mcmd); + pci_write_config_dword(cur->dev, cur->capndx+AGPCMD, mcmd); } - - return 0; } /* * Fully configure and enable an AGP 3.0 host bridge and all the devices * lying behind it. */ -int agp_3_0_node_enable(u32 mode, u32 minor) +int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor) { - struct pci_dev *td = agp_bridge->dev, *dev; + struct pci_dev *td = bridge->dev, *dev; u8 mcapndx; u32 isoch, arqsz, cal_cycle, tmp, rate; u32 tstatus, tcmd, mcmd, mstatus, ncapid; @@ -345,12 +341,22 @@ /* 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 */ - case 0x0600: /* Bridge */ - mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); if (mcapndx == 0) continue; @@ -371,7 +377,7 @@ } /* Extract some power-on defaults from the target */ - pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus); + pci_read_config_dword(td, bridge->capndx + 0x04, &tstatus); isoch = (tstatus >> 17) & 0x1; arqsz = (tstatus >> 13) & 0x7; cal_cycle = (tstatus >> 10) & 0x7; @@ -409,8 +415,8 @@ goto free_and_exit; } - mmajor = (ncapid >> 20) & 0xf; - mminor = (ncapid >> 16) & 0xf; + 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 " @@ -463,13 +469,15 @@ * masters. This process is dramatically different depending on * whether isochronous transfers are supported. */ - if(isoch != 0) { - if((ret = agp_3_0_isochronous_node_enable(dev_list, ndevs)) != 0) - goto free_and_exit; - } else { - if((ret = agp_3_0_nonisochronous_node_enable(dev_list,ndevs)) != 0) - goto free_and_exit; + 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 @@ -477,7 +485,7 @@ * 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, agp_bridge->capndx + 0x08, &tcmd); + pci_read_config_dword(td, bridge->capndx+AGPCMD, &tcmd); tcmd &= ~(0x7 << 10); tcmd &= ~0x7; @@ -486,7 +494,7 @@ tcmd |= 0x1 << 8; tcmd |= rate; - pci_write_config_dword(td, agp_bridge->capndx + 0x08, tcmd); + pci_write_config_dword(td, bridge->capndx+AGPCMD, tcmd); /* * Set the target's advertised arqsz value, the minimum supported @@ -499,16 +507,16 @@ mcapndx = cur->capndx; - pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd); + pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd); - mcmd &= ~(0x7 << 13); + mcmd &= ~(0x7 << AGPSTAT_ARQSZ_SHIFT); mcmd &= ~0x7; mcmd |= arqsz << 13; - mcmd |= 0x1 << 8; + mcmd |= AGPSTAT_AGP_ENABLE; mcmd |= rate; - pci_write_config_dword(dev, cur->capndx + 0x08, mcmd); + pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd); } free_and_exit: diff -urN linux-2.5.69-bk6/drivers/char/agp/generic.c linux-2.5.69-bk7/drivers/char/agp/generic.c --- linux-2.5.69-bk6/drivers/char/agp/generic.c 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/generic.c 2003-05-12 04:43:29.000000000 -0700 @@ -1,6 +1,6 @@ /* * AGPGART driver. - * Copyright (C) 2002 Dave Jones. + * Copyright (C) 2002-2003 Dave Jones. * Copyright (C) 1999 Jeff Hartmann. * Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Xi Graphics, Inc. @@ -42,19 +42,19 @@ /* * Generic routines for handling agp_memory structures - - * They use the basic page allocation routines to do the - * brunt of the work. + * They use the basic page allocation routines to do the brunt of the work. */ void agp_free_key(int key) { - if (key < 0) return; if (key < MAXKEY) clear_bit(key, agp_bridge->key_list); } +EXPORT_SYMBOL(agp_free_key); + static int agp_get_key(void) { @@ -68,6 +68,7 @@ return -1; } + agp_memory *agp_create_memory(int scratch_pages) { agp_memory *new; @@ -94,7 +95,16 @@ new->num_scratch_pages = scratch_pages; return new; } +EXPORT_SYMBOL(agp_create_memory); +/** + * agp_free_memory - free memory associated with an agp_memory pointer. + * + * @curr: agp_memory pointer to be freed. + * + * It is the only function that can be called when the backend is not owned + * by the caller. (So it can free memory on client death.) + */ void agp_free_memory(agp_memory * curr) { size_t i; @@ -106,21 +116,33 @@ agp_unbind_memory(curr); if (curr->type != 0) { - agp_bridge->free_by_type(curr); + agp_bridge->driver->free_by_type(curr); return; } if (curr->page_count != 0) { for (i = 0; i < curr->page_count; i++) { - agp_bridge->agp_destroy_page(phys_to_virt(curr->memory[i])); + agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); } } agp_free_key(curr->key); vfree(curr->memory); kfree(curr); } +EXPORT_SYMBOL(agp_free_memory); #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) +/** + * agp_allocate_memory - allocate a group of pages of a certain type. + * + * @page_count: size_t argument of the number of pages + * @type: u32 argument of the type of memory to be allocated. + * + * Every agp bridge device will allow you to allocate AGP_NORMAL_MEMORY which + * maps to physical ram. Any other type is device dependent. + * + * It returns NULL whenever memory is unavailable. + */ agp_memory *agp_allocate_memory(size_t page_count, u32 type) { int scratch_pages; @@ -134,7 +156,7 @@ return NULL; if (type != 0) { - new = agp_bridge->alloc_by_type(page_count, type); + new = agp_bridge->driver->alloc_by_type(page_count, type); return new; } @@ -146,7 +168,7 @@ return NULL; for (i = 0; i < page_count; i++) { - void *addr = agp_bridge->agp_alloc_page(); + void *addr = agp_bridge->driver->agp_alloc_page(); if (addr == NULL) { agp_free_memory(new); @@ -160,9 +182,12 @@ return new; } +EXPORT_SYMBOL(agp_allocate_memory); + /* End - Generic routines for handling agp_memory structures */ + static int agp_return_size(void) { int current_size; @@ -170,7 +195,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: current_size = A_SIZE_8(temp)->size; break; @@ -197,6 +222,7 @@ return current_size; } + int agp_num_entries(void) { int num_entries; @@ -204,7 +230,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: num_entries = A_SIZE_8(temp)->num_entries; break; @@ -230,9 +256,17 @@ num_entries = 0; return num_entries; } +EXPORT_SYMBOL_GPL(agp_num_entries); -/* Routine to copy over information structure */ +/** + * agp_copy_info - copy bridge state information + * + * @info: agp_kern_info pointer. The caller should insure that this pointer is valid. + * + * This function copies information about the agp bridge device and the state of + * the agp backend into an agp_kern_info pointer. + */ int agp_copy_info(agp_kern_info * info) { memset(info, 0, sizeof(agp_kern_info)); @@ -249,20 +283,32 @@ info->aper_size = agp_return_size(); info->max_memory = agp_bridge->max_memory_agp; info->current_memory = atomic_read(&agp_bridge->current_memory_agp); - info->cant_use_aperture = agp_bridge->cant_use_aperture; + info->cant_use_aperture = agp_bridge->driver->cant_use_aperture; info->vm_ops = agp_bridge->vm_ops; info->page_mask = ~0UL; return 0; } +EXPORT_SYMBOL(agp_copy_info); + /* End - Routine to copy over information structure */ + /* * Routines for handling swapping of agp_memory into the GATT - * These routines take agp_memory and insert them into the GATT. * They call device specific routines to actually write to the GATT. */ +/** + * agp_bind_memory - Bind an agp_memory structure into the GATT. + * + * @curr: agp_memory pointer + * @pg_start: an offset into the graphics aperture translation table + * + * It returns -EINVAL if the pointer == NULL. + * It returns -EBUSY if the area of the table requested is already in use. + */ int agp_bind_memory(agp_memory * curr, off_t pg_start) { int ret_val; @@ -272,10 +318,10 @@ return -EINVAL; } if (curr->is_flushed == FALSE) { - CACHE_FLUSH(); + agp_bridge->driver->cache_flush(); curr->is_flushed = TRUE; } - ret_val = agp_bridge->insert_memory(curr, pg_start, curr->type); + ret_val = agp_bridge->driver->insert_memory(curr, pg_start, curr->type); if (ret_val != 0) return ret_val; @@ -284,7 +330,17 @@ curr->pg_start = pg_start; return 0; } +EXPORT_SYMBOL(agp_bind_memory); + +/** + * agp_unbind_memory - Removes an agp_memory structure from the GATT + * + * @curr: agp_memory pointer to be removed from the GATT. + * + * It returns -EINVAL if this piece of agp_memory is not currently bound to + * the graphics aperture translation table or if the agp_memory pointer == NULL + */ int agp_unbind_memory(agp_memory * curr) { int ret_val; @@ -295,7 +351,7 @@ if (curr->is_bound != TRUE) return -EINVAL; - ret_val = agp_bridge->remove_memory(curr, curr->pg_start, curr->type); + ret_val = agp_bridge->driver->remove_memory(curr, curr->pg_start, curr->type); if (ret_val != 0) return ret_val; @@ -304,6 +360,7 @@ curr->pg_start = 0; return 0; } +EXPORT_SYMBOL(agp_unbind_memory); /* End - Routines for handling swapping of agp_memory into the GATT */ @@ -328,50 +385,44 @@ pci_read_config_dword(device, agp + PCI_AGP_STATUS, &scratch); /* adjust RQ depth */ - command = ((command & ~0xff000000) | - min_t(u32, (mode & 0xff000000), - min_t(u32, (command & 0xff000000), - (scratch & 0xff000000)))); + command = ((command & ~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 & 0x00000200) && - (scratch & 0x00000200) && - (mode & 0x00000200))) - command &= ~0x00000200; + if (!((command & AGPSTAT_SBA) && (scratch & AGPSTAT_SBA) && (mode & AGPSTAT_SBA))) + command &= ~AGPSTAT_SBA; /* disable FW if it's not supported */ - if (!((command & 0x00000010) && - (scratch & 0x00000010) && - (mode & 0x00000010))) - command &= ~0x00000010; - - if (!((command & 4) && - (scratch & 4) && - (mode & 4))) - command &= ~0x00000004; - - if (!((command & 2) && - (scratch & 2) && - (mode & 2))) - command &= ~0x00000002; - - if (!((command & 1) && - (scratch & 1) && - (mode & 1))) - command &= ~0x00000001; + 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; + + if (!((command & AGPSTAT2_1X) && (scratch & AGPSTAT2_1X) && (mode & AGPSTAT2_1X))) + command &= ~AGPSTAT2_1X; } - if (command & 4) - command &= ~3; /* 4X */ + /* 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 & 2) - command &= ~5; /* 2X (8X for AGP3.0) */ + if (command & AGPSTAT2_2X) + command &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ - if (command & 1) - command &= ~6; /* 1X (4X for AGP3.0) */ + if (command & AGPSTAT2_1X) + command &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1Xf */ return command; } +EXPORT_SYMBOL(agp_collect_device_status); + void agp_device_command(u32 command, int agp_v3) { @@ -392,6 +443,8 @@ pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); } } +EXPORT_SYMBOL(agp_device_command); + void agp_generic_enable(u32 mode) { @@ -408,7 +461,7 @@ 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(mode, minor); + 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"); @@ -420,12 +473,14 @@ agp_bridge->capndx + PCI_AGP_STATUS, &command); command = agp_collect_device_status(mode, command); - command |= 0x100; + command |= AGPSTAT_AGP_ENABLE; pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_COMMAND, command); agp_device_command(command, 0); } +EXPORT_SYMBOL(agp_generic_enable); + int agp_generic_create_gatt_table(void) { @@ -439,7 +494,7 @@ struct page *page; /* The generic routines can't handle 2 level gatt's */ - if (agp_bridge->size_type == LVL2_APER_SIZE) + if (agp_bridge->driver->size_type == LVL2_APER_SIZE) return -EINVAL; table = NULL; @@ -447,9 +502,9 @@ temp = agp_bridge->current_size; size = page_order = num_entries = 0; - if (agp_bridge->size_type != FIXED_APER_SIZE) { + if (agp_bridge->driver->size_type != FIXED_APER_SIZE) { do { - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: size = A_SIZE_8(temp)->size; page_order = @@ -480,19 +535,17 @@ if (table == NULL) { i++; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: - agp_bridge->current_size = A_IDX8(); + agp_bridge->current_size = A_IDX8(agp_bridge); break; case U16_APER_SIZE: - agp_bridge->current_size = A_IDX16(); + agp_bridge->current_size = A_IDX16(agp_bridge); break; case U32_APER_SIZE: - agp_bridge->current_size = A_IDX32(); + agp_bridge->current_size = A_IDX32(agp_bridge); break; - /* This case will never really - * happen. - */ + /* This case will never really happen. */ case FIXED_APER_SIZE: case LVL2_APER_SIZE: default: @@ -504,7 +557,7 @@ } else { agp_bridge->aperture_size_idx = i; } - } while ((table == NULL) && (i < agp_bridge->num_aperture_sizes)); + } while (!table && (i < agp_bridge->driver->num_aperture_sizes)); } else { size = ((struct aper_size_info_fixed *) temp)->size; page_order = ((struct aper_size_info_fixed *) temp)->page_order; @@ -522,10 +575,11 @@ agp_bridge->gatt_table_real = (u32 *) table; agp_gatt_table = (void *)table; - CACHE_FLUSH(); + + agp_bridge->driver->cache_flush(); agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table), (PAGE_SIZE * (1 << page_order))); - CACHE_FLUSH(); + agp_bridge->driver->cache_flush(); if (agp_bridge->gatt_table == NULL) { for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) @@ -543,16 +597,21 @@ return 0; } +EXPORT_SYMBOL(agp_generic_create_gatt_table); int agp_generic_suspend(void) { return 0; } +EXPORT_SYMBOL(agp_generic_suspend); + void agp_generic_resume(void) { return; } +EXPORT_SYMBOL(agp_generic_resume); + int agp_generic_free_gatt_table(void) { @@ -563,7 +622,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: page_order = A_SIZE_8(temp)->page_order; break; @@ -587,8 +646,7 @@ /* Do not worry about freeing memory, because if this is * called, then all agp memory is deallocated and removed - * from the table. - */ + * from the table. */ iounmap(agp_bridge->gatt_table); table = (char *) agp_bridge->gatt_table_real; @@ -598,8 +656,16 @@ ClearPageReserved(page); free_pages((unsigned long) agp_bridge->gatt_table_real, page_order); + + agp_gatt_table = NULL; + agp_bridge->gatt_table = NULL; + agp_bridge->gatt_table_real = NULL; + agp_bridge->gatt_bus_addr = 0; + return 0; } +EXPORT_SYMBOL(agp_generic_free_gatt_table); + int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type) { @@ -610,7 +676,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: num_entries = A_SIZE_8(temp)->num_entries; break; @@ -647,24 +713,27 @@ j = pg_start; while (j < (pg_start + mem->page_count)) { - if (!PGE_EMPTY(agp_bridge->gatt_table[j])) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) { return -EBUSY; } j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + agp_bridge->driver->cache_flush(); mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) agp_bridge->gatt_table[j] = - agp_bridge->mask_memory(mem->memory[i], mem->type); + agp_bridge->driver->mask_memory( + mem->memory[i], mem->type); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } +EXPORT_SYMBOL(agp_generic_insert_memory); + int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type) { @@ -681,14 +750,18 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } +EXPORT_SYMBOL(agp_generic_remove_memory); + agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) { return NULL; } +EXPORT_SYMBOL(agp_generic_alloc_by_type); + void agp_generic_free_by_type(agp_memory * curr) { @@ -698,13 +771,13 @@ agp_free_key(curr->key); kfree(curr); } +EXPORT_SYMBOL(agp_generic_free_by_type); + /* * Basic Page Allocation Routines - - * These routines handle page allocation - * and by default they reserve the allocated - * memory. They also handle incrementing the - * current_memory_agp value, Which is checked + * These routines handle page allocation and by default they reserve the allocated + * memory. They also handle incrementing the current_memory_agp value, Which is checked * against a maximum value. */ @@ -723,6 +796,8 @@ atomic_inc(&agp_bridge->current_memory_agp); return page_address(page); } +EXPORT_SYMBOL(agp_generic_alloc_page); + void agp_generic_destroy_page(void *addr) { @@ -738,41 +813,39 @@ free_page((unsigned long)addr); atomic_dec(&agp_bridge->current_memory_agp); } +EXPORT_SYMBOL(agp_generic_destroy_page); /* End Basic Page Allocation Routines */ + +/** + * agp_enable - initialise the agp point-to-point connection. + * + * @mode: agp mode register value to configure with. + */ void agp_enable(u32 mode) { if (agp_bridge->type == NOT_SUPPORTED) return; - agp_bridge->agp_enable(mode); + agp_bridge->driver->agp_enable(mode); } - -EXPORT_SYMBOL(agp_free_memory); -EXPORT_SYMBOL(agp_allocate_memory); -EXPORT_SYMBOL(agp_copy_info); -EXPORT_SYMBOL(agp_create_memory); -EXPORT_SYMBOL(agp_bind_memory); -EXPORT_SYMBOL(agp_unbind_memory); -EXPORT_SYMBOL(agp_free_key); EXPORT_SYMBOL(agp_enable); -EXPORT_SYMBOL(agp_bridge); - -EXPORT_SYMBOL(agp_generic_alloc_page); -EXPORT_SYMBOL(agp_generic_destroy_page); -EXPORT_SYMBOL(agp_generic_suspend); -EXPORT_SYMBOL(agp_generic_resume); -EXPORT_SYMBOL(agp_generic_enable); -EXPORT_SYMBOL(agp_generic_create_gatt_table); -EXPORT_SYMBOL(agp_generic_free_gatt_table); -EXPORT_SYMBOL(agp_generic_insert_memory); -EXPORT_SYMBOL(agp_generic_remove_memory); -EXPORT_SYMBOL(agp_generic_alloc_by_type); -EXPORT_SYMBOL(agp_generic_free_by_type); -EXPORT_SYMBOL(global_cache_flush); -EXPORT_SYMBOL(agp_device_command); -EXPORT_SYMBOL(agp_collect_device_status); +#ifdef CONFIG_SMP +static void ipi_handler(void *null) +{ + flush_agp_cache(); +} +#endif -EXPORT_SYMBOL_GPL(agp_num_entries); +void global_cache_flush(void) +{ +#ifdef CONFIG_SMP + if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0) + panic(PFX "timed out waiting for the other CPUs!\n"); +#else + flush_agp_cache(); +#endif +} +EXPORT_SYMBOL(global_cache_flush); diff -urN linux-2.5.69-bk6/drivers/char/agp/hp-agp.c linux-2.5.69-bk7/drivers/char/agp/hp-agp.c --- linux-2.5.69-bk6/drivers/char/agp/hp-agp.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/hp-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -285,7 +285,7 @@ } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -296,11 +296,11 @@ for (k = 0; k < hp->io_pages_per_kpage; k++, j++, paddr += hp->io_page_size) { - hp->gatt[j] = agp_bridge->mask_memory(paddr, type); + hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type); } } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } @@ -319,7 +319,7 @@ hp->gatt[i] = agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } @@ -328,58 +328,62 @@ return HP_ZX1_PDIR_VALID_BIT | addr; } -static int __init hp_zx1_setup (struct pci_dev *pdev __attribute__((unused))) -{ - agp_bridge->masks = hp_zx1_masks; - agp_bridge->dev_private_data = NULL; - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = hp_zx1_configure; - agp_bridge->fetch_size = hp_zx1_fetch_size; - agp_bridge->cleanup = hp_zx1_cleanup; - agp_bridge->tlb_flush = hp_zx1_tlbflush; - agp_bridge->mask_memory = hp_zx1_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = hp_zx1_create_gatt_table; - agp_bridge->free_gatt_table = hp_zx1_free_gatt_table; - agp_bridge->insert_memory = hp_zx1_insert_memory; - agp_bridge->remove_memory = hp_zx1_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->cant_use_aperture = 1; - return hp_zx1_ioc_init(); -} +struct agp_bridge_driver hp_zx1_driver = { + .owner = THIS_MODULE, + .masks = hp_zx1_masks, + .size_type = FIXED_APER_SIZE, + .configure = hp_zx1_configure, + .fetch_size = hp_zx1_fetch_size, + .cleanup = hp_zx1_cleanup, + .tlb_flush = hp_zx1_tlbflush, + .mask_memory = hp_zx1_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = hp_zx1_create_gatt_table, + .free_gatt_table = hp_zx1_free_gatt_table, + .insert_memory = hp_zx1_insert_memory, + .remove_memory = hp_zx1_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .cant_use_aperture = 1, +}; -static int __init agp_find_supported_device(struct pci_dev *dev) +static int __init agp_hp_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - agp_bridge->dev = dev; + struct agp_bridge_data *bridge; + int error; /* ZX1 LBAs can be either PCI or AGP bridges */ - if (pci_find_capability(dev, PCI_CAP_ID_AGP)) { - printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n", - dev->slot_name); - agp_bridge->type = HP_ZX1; - agp_bridge->dev = dev; - return hp_zx1_setup(dev); - } - return -ENODEV; -} + if (!pci_find_capability(pdev, PCI_CAP_ID_AGP)) + return -ENODEV; -static struct agp_driver hp_agp_driver = { - .owner = THIS_MODULE, -}; + printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n", + pdev->slot_name); + + error = hp_zx1_ioc_init(); + if (error) + return error; + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; -static int __init agp_hp_probe (struct pci_dev *dev, const struct pci_device_id *ent) + bridge->driver = &hp_zx1_driver; + bridge->dev = pdev; + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_hp_remove(struct pci_dev *pdev) { - if (agp_find_supported_device(dev) == 0) { - hp_agp_driver.dev = dev; - agp_register_driver(&hp_agp_driver); - return 0; - } - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_hp_pci_table[] __initdata = { @@ -400,22 +404,16 @@ .name = "agpgart-hp", .id_table = agp_hp_pci_table, .probe = agp_hp_probe, + .remove = agp_hp_remove, }; static int __init agp_hp_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_hp_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_hp_pci_driver); } static void __exit agp_hp_cleanup(void) { - agp_unregister_driver(&hp_agp_driver); pci_unregister_driver(&agp_hp_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/i460-agp.c linux-2.5.69-bk7/drivers/char/agp/i460-agp.c --- linux-2.5.69-bk6/drivers/char/agp/i460-agp.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/i460-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -69,7 +69,7 @@ } *lp_desc; } i460; -static const struct aper_size_info_8 i460_sizes[3] = +static struct aper_size_info_8 i460_sizes[3] = { /* * The 32GB aperture is only available with a 4M GART page size. Due to the @@ -107,7 +107,7 @@ return 0; } - values = A_SIZE_8(agp_bridge->aperture_sizes); + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp); @@ -130,7 +130,7 @@ else i460.dynamic_apbase = INTEL_I460_APBASE; - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { /* * Dynamically calculate the proper num_entries and page_order values for * the define aperture sizes. Take care not to shift off the end of @@ -140,7 +140,7 @@ values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT); } - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { /* Neglect control bits when matching up size_value */ if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -294,7 +294,7 @@ j = io_pg_start; while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) { - if (!PGE_EMPTY(RD_GATT(j))) { + if (!PGE_EMPTY(agp_bridge, RD_GATT(j))) { pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n", j, RD_GATT(j)); return -EBUSY; @@ -306,7 +306,7 @@ for (i = 0, j = io_pg_start; i < mem->page_count; i++) { paddr = mem->memory[i]; for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size) - WR_GATT(j, agp_bridge->mask_memory(paddr, mem->type)); + WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type)); } WR_FLUSH_GATT(j - 1); return 0; @@ -417,7 +417,7 @@ if (i460_alloc_large_page(lp) < 0) return -ENOMEM; pg = lp - i460.lp_desc; - WR_GATT(pg, agp_bridge->mask_memory(lp->paddr, 0)); + WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0)); WR_FLUSH_GATT(pg); } @@ -439,7 +439,7 @@ struct lp_desc *start, *end, *lp; void *temp; - temp = agp_bridge->current_size; + temp = agp_bridge->driver->current_size; num_entries = A_SIZE_8(temp)->num_entries; /* Figure out what pg_start means in terms of our large GART pages */ @@ -519,64 +519,71 @@ static unsigned long i460_mask_memory (unsigned long addr, int type) { /* Make sure the returned address is a valid GATT entry */ - return (agp_bridge->masks[0].mask + return (agp_bridge->driver->masks[0].mask | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12)); } -static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))) -{ - agp_bridge->masks = i460_masks; - agp_bridge->aperture_sizes = (void *) i460_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 3; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = i460_configure; - agp_bridge->fetch_size = i460_fetch_size; - agp_bridge->cleanup = i460_cleanup; - agp_bridge->tlb_flush = i460_tlb_flush; - agp_bridge->mask_memory = i460_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = i460_create_gatt_table; - agp_bridge->free_gatt_table = i460_free_gatt_table; +struct agp_bridge_driver intel_i460_driver = { + .owner = THIS_MODULE, + .masks = i460_masks, + .aperture_sizes = i460_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 3, + .configure = i460_configure, + .fetch_size = i460_fetch_size, + .cleanup = i460_cleanup, + .tlb_flush = i460_tlb_flush, + .mask_memory = i460_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = i460_create_gatt_table, + .free_gatt_table = i460_free_gatt_table, #if I460_LARGE_IO_PAGES - agp_bridge->insert_memory = i460_insert_memory; - agp_bridge->remove_memory = i460_remove_memory; - agp_bridge->agp_alloc_page = i460_alloc_page; - agp_bridge->agp_destroy_page = i460_destroy_page; + .insert_memory = i460_insert_memory, + .remove_memory = i460_remove_memory, + .agp_alloc_page = i460_alloc_page, + .agp_destroy_page = i460_destroy_page, #else - agp_bridge->insert_memory = i460_insert_memory_small_io_page; - agp_bridge->remove_memory = i460_remove_memory_small_io_page; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; + .insert_memory = i460_insert_memory_small_io_page, + .remove_memory = i460_remove_memory_small_io_page, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, #endif - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 1; - return 0; -} - -static struct agp_driver i460_agp_driver = { - .owner = THIS_MODULE, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, + .cant_use_aperture = 1, }; -static int __init agp_intel_i460_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static int __init agp_intel_i460_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - u8 cap_ptr = 0; + struct agp_bridge_data *bridge; + u8 cap_ptr; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) return -ENODEV; - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - intel_i460_setup(dev); - i460_agp_driver.dev = dev; - agp_register_driver(&i460_agp_driver); - return 0; + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &intel_i460_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_intel_i460_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_intel_i460_pci_table[] __initdata = { @@ -597,22 +604,16 @@ .name = "agpgart-intel-i460", .id_table = agp_intel_i460_pci_table, .probe = agp_intel_i460_probe, + .remove = agp_intel_i460_remove, }; static int __init agp_intel_i460_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_intel_i460_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_intel_i460_pci_driver); } static void __exit agp_intel_i460_cleanup(void) { - agp_unregister_driver(&i460_agp_driver); pci_unregister_driver(&agp_intel_i460_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/intel-agp.c linux-2.5.69-bk7/drivers/char/agp/intel-agp.c --- linux-2.5.69-bk6/drivers/char/agp/intel-agp.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/intel-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -45,7 +45,7 @@ struct aper_size_info_fixed *values; pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc); - values = A_SIZE_FIX(agp_bridge->aperture_sizes); + values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { printk(KERN_WARNING PFX "i810 is disabled\n"); @@ -89,9 +89,9 @@ agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED); - CACHE_FLUSH(); + global_cache_flush(); - if (agp_bridge->needs_scratch_page == TRUE) { + if (agp_bridge->driver->needs_scratch_page) { for (i = 0; i < current_size->num_entries; i++) { OUTREG32(intel_i810_private.registers, I810_PTE_BASE + (i * 4), @@ -130,23 +130,22 @@ return -EINVAL; } for (j = pg_start; j < (pg_start + mem->page_count); j++) { - if (!PGE_EMPTY(agp_bridge->gatt_table[j])) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) return -EBUSY; - } } if (type != 0 || mem->type != 0) { if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { /* special insert */ - CACHE_FLUSH(); + global_cache_flush(); for (i = pg_start; i < (pg_start + mem->page_count); i++) { OUTREG32(intel_i810_private.registers, I810_PTE_BASE + (i * 4), (i * 4096) | I810_PTE_LOCAL | I810_PTE_VALID); } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + agp_bridge->driver->tlb_flush(mem); return 0; } if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY)) @@ -155,15 +154,15 @@ } insert: - CACHE_FLUSH(); + global_cache_flush(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { OUTREG32(intel_i810_private.registers, I810_PTE_BASE + (j * 4), - agp_bridge->mask_memory(mem->memory[i], mem->type)); + agp_bridge->driver->mask_memory(mem->memory[i], mem->type)); } - CACHE_FLUSH(); + global_cache_flush(); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } @@ -178,58 +177,61 @@ agp_bridge->scratch_page); } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + agp_bridge->driver->tlb_flush(mem); return 0; } +/* + * The i810/i830 requires a physical address to program its mouse + * pointer into hardware. + * However the Xserver still writes to it through the agp aperture. + */ +static agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) +{ + agp_memory *new; + void *addr; + + if (pg_count != 1) + return NULL; + + addr = agp_bridge->driver->agp_alloc_page(); + if (addr == NULL) + return NULL; + + new = agp_create_memory(1); + if (new == NULL) + return NULL; + + new->memory[0] = virt_to_phys(addr); + new->page_count = 1; + new->num_scratch_pages = 1; + new->type = AGP_PHYS_MEMORY; + new->physical = new->memory[0]; + return new; +} + static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) { agp_memory *new; if (type == AGP_DCACHE_MEMORY) { - if (pg_count != intel_i810_private.num_dcache_entries) { + if (pg_count != intel_i810_private.num_dcache_entries) return NULL; - } - new = agp_create_memory(1); - if (new == NULL) { + new = agp_create_memory(1); + if (new == NULL) return NULL; - } + new->type = AGP_DCACHE_MEMORY; new->page_count = pg_count; new->num_scratch_pages = 0; vfree(new->memory); return new; } - if(type == AGP_PHYS_MEMORY) { - void *addr; - /* The I810 requires a physical address to program - * it's mouse pointer into hardware. However the - * Xserver still writes to it through the agp - * aperture - */ - if (pg_count != 1) - return NULL; - - new = agp_create_memory(1); - if (new == NULL) - return NULL; - - addr = agp_bridge->agp_alloc_page(); + if (type == AGP_PHYS_MEMORY) + return(alloc_agpphysmem_i8xx(pg_count, type)); - if (addr == NULL) { - /* Free this structure */ - agp_free_memory(new); - return NULL; - } - new->memory[0] = virt_to_phys(addr); - new->page_count = 1; - new->num_scratch_pages = 1; - new->type = AGP_PHYS_MEMORY; - new->physical = new->memory[0]; - return new; - } return NULL; } @@ -237,7 +239,7 @@ { agp_free_key(curr->key); if(curr->type == AGP_PHYS_MEMORY) { - agp_bridge->agp_destroy_page(phys_to_virt(curr->memory[0])); + agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0])); vfree(curr->memory); } kfree(curr); @@ -246,39 +248,7 @@ static unsigned long intel_i810_mask_memory(unsigned long addr, int type) { /* Type checking must be done elsewhere */ - return addr | agp_bridge->masks[type].mask; -} - -static int __init intel_i810_setup(struct pci_dev *i810_dev) -{ - intel_i810_private.i810_dev = i810_dev; - - agp_bridge->masks = intel_i810_masks; - agp_bridge->aperture_sizes = (void *) intel_i810_sizes; - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->num_aperture_sizes = 2; - agp_bridge->dev_private_data = (void *) &intel_i810_private; - agp_bridge->needs_scratch_page = TRUE; - agp_bridge->configure = intel_i810_configure; - agp_bridge->fetch_size = intel_i810_fetch_size; - agp_bridge->cleanup = intel_i810_cleanup; - agp_bridge->tlb_flush = intel_i810_tlbflush; - agp_bridge->mask_memory = intel_i810_mask_memory; - agp_bridge->agp_enable = intel_i810_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = intel_i810_insert_entries; - agp_bridge->remove_memory = intel_i810_remove_entries; - agp_bridge->alloc_by_type = intel_i810_alloc_by_type; - agp_bridge->free_by_type = intel_i810_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - return 0; + return addr | agp_bridge->driver->masks[type].mask; } static struct aper_size_info_fixed intel_i830_sizes[] = @@ -379,10 +349,11 @@ temp &= 0xfff80000; intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) return (-ENOMEM); + if (!intel_i830_private.registers) + return (-ENOMEM); temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000; - CACHE_FLUSH(); + global_cache_flush(); /* we have to call this as early as possible after the MMIO base address is known */ intel_i830_init_gtt_entries(); @@ -407,7 +378,7 @@ u16 gmch_ctrl; struct aper_size_info_fixed *values; - values = A_SIZE_FIX(agp_bridge->aperture_sizes); + values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB && agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) { @@ -449,9 +420,9 @@ pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl); OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED); - CACHE_FLUSH(); + global_cache_flush(); - if (agp_bridge->needs_scratch_page == TRUE) + if (agp_bridge->driver->needs_scratch_page) for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page); @@ -490,15 +461,15 @@ (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) return (-EINVAL); - CACHE_FLUSH(); + global_cache_flush(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4), - agp_bridge->mask_memory(mem->memory[i], mem->type)); + agp_bridge->driver->mask_memory(mem->memory[i], mem->type)); - CACHE_FLUSH(); + global_cache_flush(); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return(0); } @@ -507,7 +478,7 @@ { int i; - CACHE_FLUSH (); + global_cache_flush(); if (pg_start < intel_i830_private.gtt_entries) { printk ("Trying to disable local/stolen memory\n"); @@ -517,90 +488,22 @@ for (i = pg_start; i < (mem->page_count + pg_start); i++) OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page); - CACHE_FLUSH(); + global_cache_flush(); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return (0); } static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type) { - agp_memory *nw; - - /* always return NULL for now */ - if (type == AGP_DCACHE_MEMORY) return(NULL); - - if (type == AGP_PHYS_MEMORY) { - void *addr; - - /* The i830 requires a physical address to program - * it's mouse pointer into hardware. However the - * Xserver still writes to it through the agp - * aperture - */ - - if (pg_count != 1) return(NULL); - - nw = agp_create_memory(1); - - if (nw == NULL) return(NULL); - - addr = agp_bridge->agp_alloc_page(); - if (addr == NULL) { - /* free this structure */ - agp_free_memory(nw); - return(NULL); - } - - nw->memory[0] = virt_to_phys(addr); - nw->page_count = 1; - nw->num_scratch_pages = 1; - nw->type = AGP_PHYS_MEMORY; - nw->physical = nw->memory[0]; - return(nw); - } + if (type == AGP_PHYS_MEMORY) + return(alloc_agpphysmem_i8xx(pg_count, type)); + /* always return NULL for other allocation types for now */ return(NULL); } -static int __init intel_i830_setup(struct pci_dev *i830_dev) -{ - intel_i830_private.i830_dev = i830_dev; - - agp_bridge->masks = intel_i810_masks; - agp_bridge->aperture_sizes = (void *) intel_i830_sizes; - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->num_aperture_sizes = 2; - - agp_bridge->dev_private_data = (void *) &intel_i830_private; - agp_bridge->needs_scratch_page = TRUE; - - agp_bridge->configure = intel_i830_configure; - agp_bridge->fetch_size = intel_i830_fetch_size; - agp_bridge->cleanup = intel_i830_cleanup; - agp_bridge->tlb_flush = intel_i810_tlbflush; - agp_bridge->mask_memory = intel_i810_mask_memory; - agp_bridge->agp_enable = intel_i810_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - - agp_bridge->create_gatt_table = intel_i830_create_gatt_table; - agp_bridge->free_gatt_table = intel_i830_free_gatt_table; - - agp_bridge->insert_memory = intel_i830_insert_entries; - agp_bridge->remove_memory = intel_i830_remove_entries; - agp_bridge->alloc_by_type = intel_i830_alloc_by_type; - agp_bridge->free_by_type = intel_i810_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - return(0); -} - static int intel_fetch_size(void) { int i; @@ -608,9 +511,9 @@ struct aper_size_info_16 *values; pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp); - values = A_SIZE_16(agp_bridge->aperture_sizes); + values = A_SIZE_16(agp_bridge->driver->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); agp_bridge->aperture_size_idx = i; @@ -621,22 +524,14 @@ return 0; } -static int intel_8xx_fetch_size(void) +static int __intel_8xx_fetch_size(u8 temp) { int i; - u8 temp; struct aper_size_info_8 *values; - pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); - - /* Intel 815 chipsets have a _weird_ APSIZE register with only - * one non-reserved bit, so mask the others out ... */ - if (agp_bridge->type == INTEL_I815) - temp &= (1 << 3); + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); - values = A_SIZE_8(agp_bridge->aperture_sizes); - - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -647,6 +542,25 @@ return 0; } +static int intel_8xx_fetch_size(void) +{ + u8 temp; + + pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); + return __intel_8xx_fetch_size(temp); +} + +static int intel_815_fetch_size(void) +{ + u8 temp; + + /* Intel 815 chipsets have a _weird_ APSIZE register with only + * one non-reserved bit, so mask the others out ... */ + pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); + temp &= (1 << 3); + + return __intel_8xx_fetch_size(temp); +} static void intel_tlbflush(agp_memory * mem) { @@ -991,7 +905,7 @@ static unsigned long intel_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static void intel_resume(void) @@ -1041,584 +955,485 @@ {32, 8192, 3, 56} }; -static int __init intel_generic_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_generic_sizes; - agp_bridge->size_type = U16_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_configure; - agp_bridge->fetch_size = intel_fetch_size; - agp_bridge->cleanup = intel_cleanup; - agp_bridge->tlb_flush = intel_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = intel_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_generic_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_generic_sizes, + .size_type = U16_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_configure, + .fetch_size = intel_fetch_size, + .cleanup = intel_cleanup, + .tlb_flush = intel_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = intel_resume, +}; -static int __init intel_815_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_815_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 2; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_815_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_810_driver = { + .owner = THIS_MODULE, + .masks = intel_i810_masks, + .aperture_sizes = intel_i810_sizes, + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 2, + .needs_scratch_page = TRUE, + .configure = intel_i810_configure, + .fetch_size = intel_i810_fetch_size, + .cleanup = intel_i810_cleanup, + .tlb_flush = intel_i810_tlbflush, + .mask_memory = intel_i810_mask_memory, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = intel_i810_insert_entries, + .remove_memory = intel_i810_remove_entries, + .alloc_by_type = intel_i810_alloc_by_type, + .free_by_type = intel_i810_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init intel_820_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_820_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_820_cleanup; - agp_bridge->tlb_flush = intel_820_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_815_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_815_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 2, + .configure = intel_815_configure, + .fetch_size = intel_815_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init intel_830mp_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_830mp_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 4; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_830mp_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_830_driver = { + .owner = THIS_MODULE, + .masks = intel_i810_masks, + .aperture_sizes = intel_i830_sizes, + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 2, + .needs_scratch_page = TRUE, + .configure = intel_i830_configure, + .fetch_size = intel_i830_fetch_size, + .cleanup = intel_i830_cleanup, + .tlb_flush = intel_i810_tlbflush, + .mask_memory = intel_i810_mask_memory, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = intel_i830_create_gatt_table, + .free_gatt_table = intel_i830_free_gatt_table, + .insert_memory = intel_i830_insert_entries, + .remove_memory = intel_i830_remove_entries, + .alloc_by_type = intel_i830_alloc_by_type, + .free_by_type = intel_i810_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init intel_840_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_840_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} -static int __init intel_845_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_845_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = intel_845_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_820_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_820_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_820_cleanup, + .tlb_flush = intel_820_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init intel_850_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_850_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_830mp_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_830mp_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 4, + .configure = intel_830mp_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init intel_860_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_860_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_840_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_840_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init intel_7505_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_7505_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} -struct agp_device_ids intel_agp_device_ids[] __initdata = -{ - { - .device_id = PCI_DEVICE_ID_INTEL_82443LX_0, - .chipset = INTEL_LX, - .chipset_name = "440LX", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82443BX_0, - .chipset = INTEL_BX, - .chipset_name = "440BX", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82443GX_0, - .chipset = INTEL_GX, - .chipset_name = "440GX", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82815_MC, - .chipset = INTEL_I815, - .chipset_name = "i815", - .chipset_setup = intel_815_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82820_HB, - .chipset = INTEL_I820, - .chipset_name = "i820", - .chipset_setup = intel_820_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82820_UP_HB, - .chipset = INTEL_I820, - .chipset_name = "i820", - .chipset_setup = intel_820_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82830_HB, - .chipset = INTEL_I830_M, - .chipset_name = "830M", - .chipset_setup = intel_830mp_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82840_HB, - .chipset = INTEL_I840, - .chipset_name = "i840", - .chipset_setup = intel_840_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82845_HB, - .chipset = INTEL_I845, - .chipset_name = "i845", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82845G_HB, - .chipset = INTEL_I845_G, - .chipset_name = "845G", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82850_HB, - .chipset = INTEL_I850, - .chipset_name = "i850", - .chipset_setup = intel_850_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82855_HB, - .chipset = INTEL_I855_PM, - .chipset_name = "855PM", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82860_HB, - .chipset = INTEL_I860, - .chipset_name = "i860", - .chipset_setup = intel_860_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82865_HB, - .chipset = INTEL_I865_G, - .chipset_name = "865G", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_7505_0, - .chipset = INTEL_E7505, - .chipset_name = "E7505", - .chipset_setup = intel_7505_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_7205_0, - .chipset = INTEL_E7505, - .chipset_name = "E7205", - .chipset_setup = intel_7505_setup - }, - { }, /* dummy final entry, always present */ +struct agp_bridge_driver intel_845_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_845_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = intel_845_resume, }; +struct agp_bridge_driver intel_850_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_850_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +struct agp_bridge_driver intel_860_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_860_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +struct agp_bridge_driver intel_7505_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_7505_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = intel_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +static int find_i810(u16 device, const char *name) { - int j=0; - struct agp_device_ids *devs; - - devs = intel_agp_device_ids; + struct pci_dev *i810_dev; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected Intel %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return intel_generic_setup(pdev); - } - j++; + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL); + if (!i810_dev) { + printk(KERN_ERR PFX "Detected an Intel %s Chipset, " + "but could not find the secondary device.\n", + name); + return 0; } - j--; + + intel_i810_private.i810_dev = i810_dev; + return 1; +} - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic Intel routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = INTEL_GENERIC; - return intel_generic_setup(pdev); - } +static int find_i830(u16 device) +{ + struct pci_dev *i830_dev; - printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL); + if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) { + i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + device, i830_dev); + } + if (!i830_dev) + return 0; -/* Supported Device Scanning routine */ + intel_i830_private.i830_dev = i830_dev; + return 1; +} -static int __init agp_find_supported_device(struct pci_dev *dev) +static int __init agp_intel_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct pci_dev *i810_dev; + struct agp_bridge_data *bridge; + char *name = "(unknown)"; u8 cap_ptr = 0; - agp_bridge->dev = dev; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; - /* This shit needs moving into tables/init-routines. */ - switch (dev->device) { + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_82443LX_0: + bridge->driver = &intel_generic_driver; + name = "440LX"; + break; + case PCI_DEVICE_ID_INTEL_82443BX_0: + bridge->driver = &intel_generic_driver; + name = "440BX"; + break; + case PCI_DEVICE_ID_INTEL_82443GX_0: + bridge->driver = &intel_generic_driver; + name = "440GX"; + break; case PCI_DEVICE_ID_INTEL_82810_MC1: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "Detected an Intel i810," - " but could not find the secondary device.\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected an Intel i810 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup (i810_dev); - + if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1, "i810")) + goto fail; + bridge->driver = &intel_810_driver; + name = "i810"; + break; case PCI_DEVICE_ID_INTEL_82810_MC3: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "Detected an Intel i810 DC100, but could not find the " - "secondary device.\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected an Intel i810 DC100 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - + if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3, "i810 DC100")) + goto fail; + bridge->driver = &intel_810_driver; + name = "i810 DC100"; + break; case PCI_DEVICE_ID_INTEL_82810E_MC: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "Detected an Intel i810 E" - ", but could not find the secondary device.\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected an Intel i810 E Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - + if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG, "i810 E")) + goto fail; + bridge->driver = &intel_810_driver; + name = "i810 E"; + break; case PCI_DEVICE_ID_INTEL_82815_MC: - /* The i815 can operate either as an i810 style + /* + * The i815 can operate either as an i810 style * integrated device, or as an AGP4X motherboard. - * - * This only addresses the first mode: */ - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "agpgart: Detected an " - "Intel i815, but could not find the" - " secondary device. Assuming a " - "non-integrated video card.\n"); - break; - } - printk(KERN_INFO PFX "agpgart: Detected an Intel i815 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - - case PCI_DEVICE_ID_INTEL_82845G_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82845G_IG, NULL); - if (i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82845G_IG, i810_dev); - } - - if (i810_dev == NULL) { - /* - * We probably have a I845G chipset with an external graphics - * card. It will be initialized later - */ - agp_bridge->type = INTEL_I845_G; - break; - } - printk(KERN_INFO PFX "Detected an Intel(R) 845G Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - + if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC, "i815")) + bridge->driver = &intel_810_driver; + else + bridge->driver = &intel_815_driver; + name = "i815"; + break; + case PCI_DEVICE_ID_INTEL_82820_HB: + case PCI_DEVICE_ID_INTEL_82820_UP_HB: + bridge->driver = &intel_820_driver; + name = "i820"; + break; case PCI_DEVICE_ID_INTEL_82830_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC, NULL); - if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC, i810_dev); - - if (i810_dev == NULL) { - /* Intel 830MP with external graphic card */ - /* It will be initialized later */ - agp_bridge->type = INTEL_I830_M; - break; + if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_830mp_driver; } - printk(KERN_INFO PFX "Detected an Intel(R) 830M Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - - case PCI_DEVICE_ID_INTEL_82855_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855_IG, NULL); - if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855_IG, i810_dev); - - if (i810_dev == NULL) { - /* Intel 855PM with external graphic card */ - /* It will be initialized later */ - agp_bridge->type = INTEL_I855_PM; - break; + name = "830M"; + break; + case PCI_DEVICE_ID_INTEL_82840_HB: + bridge->driver = &intel_840_driver; + name = "i840"; + break; + case PCI_DEVICE_ID_INTEL_82845_HB: + bridge->driver = &intel_845_driver; + name = "i845"; + break; + case PCI_DEVICE_ID_INTEL_82845G_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_845_driver; } - { - u32 capval = 0; - const char *name = "855GM/852GM"; - pci_read_config_dword(dev, I85X_CAPID, &capval); - switch ((capval >> I85X_VARIANT_SHIFT) & - I85X_VARIANT_MASK) { - case I855_GME: - name = "855GME"; - break; - case I855_GM: - name = "855GM"; - break; - case I852_GME: - name = "852GME"; - break; - case I852_GM: - name = "852GM"; - break; - } - printk(KERN_INFO PFX - "Detected an Intel(R) %s Chipset.\n", name); + name = "845G"; + break; + case PCI_DEVICE_ID_INTEL_82850_HB: + bridge->driver = &intel_850_driver; + name = "i850"; + break; + case PCI_DEVICE_ID_INTEL_82855PM_HB: + bridge->driver = &intel_845_driver; + name = "855PM"; + break; + case PCI_DEVICE_ID_INTEL_82855GM_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) { + bridge->driver = &intel_830_driver; + name = "855"; + } else { + bridge->driver = &intel_845_driver; + name = "855GM"; } - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - + break; + case PCI_DEVICE_ID_INTEL_82860_HB: + bridge->driver = &intel_860_driver; + name = "i860"; + break; case PCI_DEVICE_ID_INTEL_82865_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82865_IG, NULL); - if (i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82865_IG, i810_dev); - } - - if (i810_dev == NULL) { - /* - * We probably have a 865G chipset with an external graphics - * card. It will be initialized later - */ - agp_bridge->type = INTEL_I865_G; - break; + if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_845_driver; } - printk(KERN_INFO PFX "Detected an Intel(R) 865G Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - + name = "865"; + break; + case PCI_DEVICE_ID_INTEL_82875_HB: + bridge->driver = &intel_845_driver; + name = "i875"; + break; + case PCI_DEVICE_ID_INTEL_7505_0: + bridge->driver = &intel_7505_driver; + name = "E7505"; + break; + case PCI_DEVICE_ID_INTEL_7205_0: + bridge->driver = &intel_7505_driver; + name = "E7205"; + break; default: + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported Intel chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; + } + bridge->driver = &intel_generic_driver; break; - } + }; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; - agp_bridge->capndx = cap_ptr; + bridge->dev = pdev; + bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); + if (bridge->driver == &intel_810_driver) + bridge->dev_private_data = &intel_i810_private; + else if (bridge->driver == &intel_830_driver) + bridge->dev_private_data = &intel_i830_private; - /* probe for known chipsets */ - return agp_lookup_host_bridge(dev); -} + printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name); -static struct agp_driver intel_agp_driver = { - .owner = THIS_MODULE, -}; + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); + fail: + agp_put_bridge(bridge); + return -ENODEV; +} -static int __init agp_intel_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static void __devexit agp_intel_remove(struct pci_dev *pdev) { - if (agp_find_supported_device(dev) == 0) { - intel_agp_driver.dev = dev; - agp_register_driver(&intel_agp_driver); - return 0; - } - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_intel_pci_table[] __initdata = { @@ -1639,29 +1454,24 @@ .name = "agpgart-intel", .id_table = agp_intel_pci_table, .probe = agp_intel_probe, + .remove = agp_intel_remove, }; /* intel_agp_init() must not be declared static for explicit early initialization to work (ie i810fb) */ int __init agp_intel_init(void) { - int ret_val; static int agp_initialised=0; - if (agp_initialised==1) + if (agp_initialised == 1) return 0; agp_initialised=1; - ret_val = pci_module_init(&agp_intel_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_intel_pci_driver); } static void __exit agp_intel_cleanup(void) { - agp_unregister_driver(&intel_agp_driver); pci_unregister_driver(&agp_intel_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/nvidia-agp.c linux-2.5.69-bk7/drivers/char/agp/nvidia-agp.c --- linux-2.5.69-bk6/drivers/char/agp/nvidia-agp.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.69-bk7/drivers/char/agp/nvidia-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -0,0 +1,380 @@ +/* + * Nvidia AGPGART routines. + * Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up + * to work in 2.5 by Dave Jones + */ + +#include +#include +#include +#include +#include +#include +#include +#include "agp.h" + + +/* registers */ +#define NVIDIA_0_APBASE 0x10 +#define NVIDIA_0_APSIZE 0x80 +#define NVIDIA_1_WBC 0xf0 +#define NVIDIA_2_GARTCTRL 0xd0 +#define NVIDIA_2_APBASE 0xd8 +#define NVIDIA_2_APLIMIT 0xdc +#define NVIDIA_2_ATTBASE(i) (0xe0 + (i) * 4) +#define NVIDIA_3_APBASE 0x50 +#define NVIDIA_3_APLIMIT 0x54 + + +static int agp_try_unsupported __initdata = 0; + +static struct _nvidia_private { + struct pci_dev *dev_1; + struct pci_dev *dev_2; + struct pci_dev *dev_3; + volatile u32 *aperture; + int num_active_entries; + off_t pg_offset; + u32 wbc_mask; +} nvidia_private; + + +static int nvidia_fetch_size(void) +{ + int i; + u8 size_value; + struct aper_size_info_8 *values; + + pci_read_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, &size_value); + size_value &= 0x0f; + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { + if (size_value == values[i].size_value) { + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + i); + agp_bridge->aperture_size_idx = i; + return values[i].size; + } + } + + return 0; +} + + +static int nvidia_configure(void) +{ + int i, num_dirs; + u32 apbase, aplimit; + struct aper_size_info_8 *current_size; + u32 temp; + + current_size = A_SIZE_8(agp_bridge->current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APBASE, &apbase); + apbase &= PCI_BASE_ADDRESS_MEM_MASK; + agp_bridge->gart_bus_addr = apbase; + aplimit = apbase + (current_size->size * 1024 * 1024) - 1; + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APBASE, apbase); + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APLIMIT, aplimit); + pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APBASE, apbase); + pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APLIMIT, aplimit); + + /* directory size is 64k */ + num_dirs = current_size->size / 64; + nvidia_private.num_active_entries = current_size->num_entries; + nvidia_private.pg_offset = 0; + if (num_dirs == 0) { + num_dirs = 1; + nvidia_private.num_active_entries /= (64 / current_size->size); + nvidia_private.pg_offset = (apbase & (64 * 1024 * 1024 - 1) & + ~(current_size->size * 1024 * 1024 - 1)) / PAGE_SIZE; + } + + /* attbase */ + for(i = 0; i < 8; i++) { + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i), + (agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1); + } + + /* gtlb control */ + pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp); + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp | 0x11); + + /* gart control */ + pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp); + pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp | 0x100); + + /* map aperture */ + nvidia_private.aperture = + (volatile u32 *) ioremap(apbase, 33 * PAGE_SIZE); + + return 0; +} + +static void nvidia_cleanup(void) +{ + struct aper_size_info_8 *previous_size; + u32 temp; + + /* gart control */ + pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp); + pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp & ~(0x100)); + + /* gtlb control */ + pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp); + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11)); + + /* unmap aperture */ + iounmap((void *) nvidia_private.aperture); + + /* restore previous aperture size */ + previous_size = A_SIZE_8(agp_bridge->previous_size); + pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, + previous_size->size_value); +} + + +static unsigned long nvidia_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + return addr | agp_bridge->driver->masks[0].mask; +} + +#if 0 +extern int agp_memory_reserved; + +static int nvidia_insert_memory(agp_memory * mem, off_t pg_start, int type) +{ + int i, j; + + if ((type != 0) || (mem->type != 0)) + return -EINVAL; + + if ((pg_start + mem->page_count) > + (nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE)) + return -EINVAL; + + for(j = pg_start; j < (pg_start + mem->page_count); j++) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[nvidia_private.pg_offset + j])) + return -EBUSY; + } + + if (mem->is_flushed == FALSE) { + global_cache_flush(); + mem->is_flushed = TRUE; + } + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) + agp_bridge->gatt_table[nvidia_private.pg_offset + j] = mem->memory[i]; + + agp_bridge->tlb_flush(mem); + return 0; +} + +static int nvidia_remove_memory(agp_memory * mem, off_t pg_start, int type) +{ + int i; + + if ((type != 0) || (mem->type != 0)) + return -EINVAL; + + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + agp_bridge->gatt_table[nvidia_private.pg_offset + i] = + (unsigned long) agp_bridge->scratch_page; + } + + agp_bridge->tlb_flush(mem); + return 0; +} +#endif + + +static void nvidia_tlbflush(agp_memory * mem) +{ + unsigned long end; + u32 wbc_reg, temp; + int i; + + /* flush chipset */ + if (nvidia_private.wbc_mask) { + pci_read_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, &wbc_reg); + wbc_reg |= nvidia_private.wbc_mask; + pci_write_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, wbc_reg); + + end = jiffies + 3*HZ; + do { + pci_read_config_dword(nvidia_private.dev_1, + NVIDIA_1_WBC, &wbc_reg); + if ((signed)(end - jiffies) <= 0) { + printk(KERN_ERR + "TLB flush took more than 3 seconds.\n"); + } + } while (wbc_reg & nvidia_private.wbc_mask); + } + + /* flush TLB entries */ + for(i = 0; i < 32 + 1; i++) + temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)]; + for(i = 0; i < 32 + 1; i++) + temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)]; +} + + +static struct aper_size_info_8 nvidia_generic_sizes[5] = +{ + {512, 131072, 7, 0}, + {256, 65536, 6, 8}, + {128, 32768, 5, 12}, + {64, 16384, 4, 14}, + /* The 32M mode still requires a 64k gatt */ + {32, 16384, 4, 15} +}; + + +static struct gatt_mask nvidia_generic_masks[] = +{ + {0x00000001, 0} +}; + + +struct agp_bridge_driver nvidia_driver = { + .owner = THIS_MODULE, + .masks = nvidia_generic_masks, + .aperture_sizes = nvidia_generic_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 5, + .configure = nvidia_configure, + .fetch_size = nvidia_fetch_size, + .cleanup = nvidia_cleanup, + .tlb_flush = nvidia_tlbflush, + .mask_memory = nvidia_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +static int __init agp_nvidia_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct agp_bridge_data *bridge; + u8 cap_ptr; + + nvidia_private.dev_1 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); + nvidia_private.dev_2 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); + nvidia_private.dev_3 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); + + if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { + printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " + "nForce/nForce2 chipset, but could not find " + "the secondary devices.\n"); + return -ENODEV; + } + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + switch (pdev->device) { + case PCI_DEVICE_ID_NVIDIA_NFORCE: + printk(KERN_INFO PFX "Detected NVIDIA nForce chipset\n"); + nvidia_private.wbc_mask = 0x00010000; + break; + case PCI_DEVICE_ID_NVIDIA_NFORCE2: + printk(KERN_INFO PFX "Detected NVIDIA nForce2 chipset\n"); + nvidia_private.wbc_mask = 0x80000000; + break; + default: + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported NVIDIA chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; + } + printk(KERN_WARNING PFX + "Trying generic NVIDIA routines for device id: %04x\n", + pdev->device); + break; + } + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &nvidia_driver; + bridge->dev_private_data = &nvidia_private, + 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_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_nvidia_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} + +static struct pci_device_id agp_nvidia_pci_table[] __initdata = { + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); + +static struct __initdata pci_driver agp_nvidia_pci_driver = { + .name = "agpgart-nvidia", + .id_table = agp_nvidia_pci_table, + .probe = agp_nvidia_probe, + .remove = agp_nvidia_remove, +}; + +static int __init agp_nvidia_init(void) +{ + return pci_module_init(&agp_nvidia_pci_driver); +} + +static void __exit agp_nvidia_cleanup(void) +{ + pci_unregister_driver(&agp_nvidia_pci_driver); +} + +module_init(agp_nvidia_init); +module_exit(agp_nvidia_cleanup); + +MODULE_PARM(agp_try_unsupported, "1i"); +MODULE_LICENSE("GPL and additional rights"); +MODULE_AUTHOR("NVIDIA Corporation"); + diff -urN linux-2.5.69-bk6/drivers/char/agp/sis-agp.c linux-2.5.69-bk7/drivers/char/agp/sis-agp.c --- linux-2.5.69-bk6/drivers/char/agp/sis-agp.c 2003-05-04 16:53:00.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/sis-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -17,8 +17,8 @@ struct aper_size_info_8 *values; pci_read_config_byte(agp_bridge->dev, SIS_APSIZE, &temp_size); - values = A_SIZE_8(agp_bridge->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if ((temp_size == values[i].size_value) || ((temp_size & ~(0x03)) == (values[i].size_value & ~(0x03)))) { @@ -67,7 +67,7 @@ { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static struct aper_size_info_8 sis_generic_sizes[7] = @@ -86,164 +86,144 @@ {.mask = 0x00000000, .type = 0} }; -static int __init sis_generic_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = sis_generic_masks; - agp_bridge->aperture_sizes = (void *) sis_generic_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = sis_configure; - agp_bridge->fetch_size = sis_fetch_size; - agp_bridge->cleanup = sis_cleanup; - agp_bridge->tlb_flush = sis_tlbflush; - agp_bridge->mask_memory = sis_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - return 0; -} +struct agp_bridge_driver sis_driver = { + .owner = THIS_MODULE, + .masks = sis_generic_masks, + .aperture_sizes = sis_generic_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = sis_configure, + .fetch_size = sis_fetch_size, + .cleanup = sis_cleanup, + .tlb_flush = sis_tlbflush, + .mask_memory = sis_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; struct agp_device_ids sis_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_SI_740, - .chipset = SIS_GENERIC, .chipset_name = "740", }, { .device_id = PCI_DEVICE_ID_SI_650, - .chipset = SIS_GENERIC, .chipset_name = "650", }, { .device_id = PCI_DEVICE_ID_SI_651, - .chipset = SIS_GENERIC, .chipset_name = "651", }, { .device_id = PCI_DEVICE_ID_SI_645, - .chipset = SIS_GENERIC, .chipset_name = "645", }, { .device_id = PCI_DEVICE_ID_SI_646, - .chipset = SIS_GENERIC, .chipset_name = "646", }, { .device_id = PCI_DEVICE_ID_SI_735, - .chipset = SIS_GENERIC, .chipset_name = "735", }, { .device_id = PCI_DEVICE_ID_SI_745, - .chipset = SIS_GENERIC, .chipset_name = "745", }, { .device_id = PCI_DEVICE_ID_SI_730, - .chipset = SIS_GENERIC, .chipset_name = "730", }, { .device_id = PCI_DEVICE_ID_SI_630, - .chipset = SIS_GENERIC, .chipset_name = "630", }, { .device_id = PCI_DEVICE_ID_SI_540, - .chipset = SIS_GENERIC, .chipset_name = "540", }, { .device_id = PCI_DEVICE_ID_SI_620, - .chipset = SIS_GENERIC, .chipset_name = "620", }, { .device_id = PCI_DEVICE_ID_SI_530, - .chipset = SIS_GENERIC, .chipset_name = "530", }, { .device_id = PCI_DEVICE_ID_SI_550, - .chipset = SIS_GENERIC, .chipset_name = "550", }, { }, /* dummy final entry, always present */ }; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_sis_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = sis_agp_device_ids; + struct agp_device_ids *devs = sis_agp_device_ids; + struct agp_bridge_data *bridge; + u8 cap_ptr; + int j; - while (devs[j].chipset_name != NULL) { + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name; j++) { if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected SiS %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return sis_generic_setup(pdev); + printk(KERN_INFO PFX "Detected SiS %s chipset\n", + devs[j].chipset_name); + goto found; } - j++; } - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic SiS routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = SIS_GENERIC; - return sis_generic_setup(pdev); + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported SiS chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic SiS routines" + " for device id: %04x\n", pdev->device); -static struct agp_driver sis_agp_driver = { - .owner = THIS_MODULE, -}; +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; -static int __init agp_sis_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + bridge->driver = &sis_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); - /* probe for known chipsets */ - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - sis_agp_driver.dev = dev; - agp_register_driver(&sis_agp_driver); - return 0; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_sis_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_sis_pci_table[] __initdata = { @@ -264,22 +244,16 @@ .name = "agpgart-sis", .id_table = agp_sis_pci_table, .probe = agp_sis_probe, + .remove = agp_sis_remove, }; static int __init agp_sis_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_sis_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_sis_pci_driver); } static void __exit agp_sis_cleanup(void) { - agp_unregister_driver(&sis_agp_driver); pci_unregister_driver(&agp_sis_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/sworks-agp.c linux-2.5.69-bk7/drivers/char/agp/sworks-agp.c --- linux-2.5.69-bk6/drivers/char/agp/sworks-agp.c 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/sworks-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -35,7 +35,7 @@ return -ENOMEM; } SetPageReserved(virt_to_page(page_map->real)); - CACHE_FLUSH(); + global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { @@ -44,7 +44,7 @@ page_map->real = NULL; return -ENOMEM; } - CACHE_FLUSH(); + global_cache_flush(); for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { page_map->remapped[i] = agp_bridge->scratch_page; @@ -203,7 +203,7 @@ u32 temp2; struct aper_size_info_lvl2 *values; - values = A_SIZE_LVL2(agp_bridge->aperture_sizes); + values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp); pci_write_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs, SVWRKS_SIZE_MASK); @@ -211,7 +211,7 @@ pci_write_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,temp); temp2 &= SVWRKS_SIZE_MASK; - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp2 == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -224,6 +224,37 @@ return 0; } +/* + * This routine could be implemented by taking the addresses + * written to the GATT, and flushing them individually. However + * currently it just flushes the whole table. Which is probably + * more efficent, since agp_memory blocks can be a large number of + * entries. + */ +static void serverworks_tlbflush(agp_memory * temp) +{ + unsigned long end; + + OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); + end = jiffies + 3*HZ; + while(INREG8(serverworks_private.registers, + SVWRKS_POSTFLUSH) == 0x01) { + if((signed)(end - jiffies) <= 0) { + printk(KERN_ERR "Posted write buffer flush took more" + "then 3 seconds\n"); + } + } + OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); + end = jiffies + 3*HZ; + while(INREG32(serverworks_private.registers, + SVWRKS_DIRFLUSH) == 0x00000001) { + if((signed)(end - jiffies) <= 0) { + printk(KERN_ERR "TLB flush took more" + "then 3 seconds\n"); + } + } +} + static int serverworks_configure(void) { struct aper_size_info_lvl2 *current_size; @@ -253,7 +284,7 @@ enable_reg |= 0x1; /* Agp Enable bit */ pci_write_config_byte(serverworks_private.svrwrks_dev, SVWRKS_AGP_ENABLE, enable_reg); - agp_bridge->tlb_flush(NULL); + serverworks_tlbflush(NULL); agp_bridge->capndx = pci_find_capability(serverworks_private.svrwrks_dev, PCI_CAP_ID_AGP); @@ -277,43 +308,11 @@ iounmap((void *) serverworks_private.registers); } -/* - * This routine could be implemented by taking the addresses - * written to the GATT, and flushing them individually. However - * currently it just flushes the whole table. Which is probably - * more efficent, since agp_memory blocks can be a large number of - * entries. - */ - -static void serverworks_tlbflush(agp_memory * temp) -{ - unsigned long end; - - OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); - end = jiffies + 3*HZ; - while(INREG8(serverworks_private.registers, - SVWRKS_POSTFLUSH) == 0x01) { - if((signed)(end - jiffies) <= 0) { - printk(KERN_ERR "Posted write buffer flush took more" - "then 3 seconds\n"); - } - } - OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); - end = jiffies + 3*HZ; - while(INREG32(serverworks_private.registers, - SVWRKS_DIRFLUSH) == 0x00000001) { - if((signed)(end - jiffies) <= 0) { - printk(KERN_ERR "TLB flush took more" - "then 3 seconds\n"); - } - } -} - static unsigned long serverworks_mask_memory(unsigned long addr, int type) { /* Only type 0 is supported by the serverworks chipsets */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static int serverworks_insert_memory(agp_memory * mem, @@ -336,14 +335,14 @@ while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); - if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) { return -EBUSY; } j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -351,9 +350,9 @@ addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); cur_gatt[GET_GATT_OFF(addr)] = - agp_bridge->mask_memory(mem->memory[i], mem->type); + agp_bridge->driver->mask_memory(mem->memory[i], mem->type); } - agp_bridge->tlb_flush(mem); + serverworks_tlbflush(mem); return 0; } @@ -368,8 +367,8 @@ return -EINVAL; } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + serverworks_tlbflush(mem); for (i = pg_start; i < (mem->page_count + pg_start); i++) { addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; @@ -378,7 +377,7 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + serverworks_tlbflush(mem); return 0; } @@ -420,123 +419,103 @@ agp_device_command(command, 0); } -static int __init serverworks_setup (struct pci_dev *pdev) +struct agp_bridge_driver sworks_driver = { + .owner = THIS_MODULE, + .masks = serverworks_masks, + .aperture_sizes = serverworks_sizes, + .size_type = LVL2_APER_SIZE, + .num_aperture_sizes = 7, + .configure = serverworks_configure, + .fetch_size = serverworks_fetch_size, + .cleanup = serverworks_cleanup, + .tlb_flush = serverworks_tlbflush, + .mask_memory = serverworks_mask_memory, + .agp_enable = serverworks_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = serverworks_create_gatt_table, + .free_gatt_table = serverworks_free_gatt_table, + .insert_memory = serverworks_insert_memory, + .remove_memory = serverworks_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +static int __init agp_serverworks_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - u32 temp; - u32 temp2; + struct agp_bridge_data *bridge; + struct pci_dev *bridge_dev; + u32 temp, temp2; - serverworks_private.svrwrks_dev = pdev; + /* Everything is on func 1 here so we are hardcoding function one */ + bridge_dev = pci_find_slot((unsigned int)pdev->bus->number, + PCI_DEVFN(0, 1)); + if (!bridge_dev) { + printk(KERN_INFO PFX "agpgart: Detected a Serverworks " + "Chipset, but could not find the secondary " + "device.\n"); + return -ENODEV; + } - agp_bridge->masks = serverworks_masks; - agp_bridge->aperture_sizes = (void *) serverworks_sizes; - agp_bridge->size_type = LVL2_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = (void *) &serverworks_private; - agp_bridge->needs_scratch_page = TRUE; - agp_bridge->configure = serverworks_configure; - agp_bridge->fetch_size = serverworks_fetch_size; - agp_bridge->cleanup = serverworks_cleanup; - agp_bridge->tlb_flush = serverworks_tlbflush; - agp_bridge->mask_memory = serverworks_mask_memory; - agp_bridge->agp_enable = serverworks_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = serverworks_create_gatt_table; - agp_bridge->free_gatt_table = serverworks_free_gatt_table; - agp_bridge->insert_memory = serverworks_insert_memory; - agp_bridge->remove_memory = serverworks_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - pci_read_config_dword(agp_bridge->dev, - SVWRKS_APSIZE, - &temp); + switch (pdev->device) { + case PCI_DEVICE_ID_SERVERWORKS_HE: + case PCI_DEVICE_ID_SERVERWORKS_LE: + case 0x0007: + break; + default: + if (!agp_try_unsupported) + return -ENODEV; + break; + } + serverworks_private.svrwrks_dev = bridge_dev; serverworks_private.gart_addr_ofs = 0x10; - - if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(agp_bridge->dev, - SVWRKS_APSIZE + 4, - &temp2); - if(temp2 != 0) { + + pci_read_config_dword(pdev, SVWRKS_APSIZE, &temp); + if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2); + if (temp2 != 0) { printk("Detected 64 bit aperture address, but top " "bits are not zero. Disabling agp\n"); return -ENODEV; } serverworks_private.mm_addr_ofs = 0x18; - } else { + } else serverworks_private.mm_addr_ofs = 0x14; - } - pci_read_config_dword(agp_bridge->dev, - serverworks_private.mm_addr_ofs, - &temp); - if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(agp_bridge->dev, - serverworks_private.mm_addr_ofs + 4, - &temp2); - if(temp2 != 0) { + pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs, &temp); + if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(pdev, + serverworks_private.mm_addr_ofs + 4, &temp2); + if (temp2 != 0) { printk("Detected 64 bit MMIO address, but top " "bits are not zero. Disabling agp\n"); return -ENODEV; } } - return 0; -} - - -static int __init agp_find_supported_device(struct pci_dev *dev) -{ - struct pci_dev *bridge_dev; - - /* Everything is on func 1 here so we are hardcoding function one */ - bridge_dev = pci_find_slot ((unsigned int)dev->bus->number, PCI_DEVFN(0, 1)); - if(bridge_dev == NULL) { - printk(KERN_INFO PFX "agpgart: Detected a Serverworks " - "Chipset, but could not find the secondary " - "device.\n"); - return -ENODEV; - } - - agp_bridge->dev = dev; - - switch (dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_HE: - agp_bridge->type = SVWRKS_HE; - return serverworks_setup(bridge_dev); + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; - case PCI_DEVICE_ID_SERVERWORKS_LE: - case 0x0007: - agp_bridge->type = SVWRKS_LE; - return serverworks_setup(bridge_dev); + bridge->driver = &sworks_driver; + bridge->dev_private_data = &serverworks_private, + bridge->dev = pdev; - default: - if(agp_try_unsupported) { - agp_bridge->type = SVWRKS_GENERIC; - return serverworks_setup(bridge_dev); - } - break; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); } -static struct agp_driver serverworks_agp_driver = { - .owner = THIS_MODULE, -}; - -static int __init agp_serverworks_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static void __devexit agp_serverworks_remove(struct pci_dev *pdev) { - if (agp_find_supported_device(dev) == 0) { - serverworks_agp_driver.dev = dev; - agp_register_driver(&serverworks_agp_driver); - return 0; - } - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_serverworks_pci_table[] __initdata = { @@ -557,22 +536,16 @@ .name = "agpgart-serverworks", .id_table = agp_serverworks_pci_table, .probe = agp_serverworks_probe, + .remove = agp_serverworks_remove, }; static int __init agp_serverworks_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_serverworks_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_serverworks_pci_driver); } static void __exit agp_serverworks_cleanup(void) { - agp_unregister_driver(&serverworks_agp_driver); pci_unregister_driver(&agp_serverworks_pci_driver); } diff -urN linux-2.5.69-bk6/drivers/char/agp/via-agp.c linux-2.5.69-bk7/drivers/char/agp/via-agp.c --- linux-2.5.69-bk6/drivers/char/agp/via-agp.c 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk7/drivers/char/agp/via-agp.c 2003-05-12 04:43:29.000000000 -0700 @@ -18,9 +18,9 @@ u8 temp; struct aper_size_info_8 *values; - values = A_SIZE_8(agp_bridge->aperture_sizes); + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); pci_read_config_byte(agp_bridge->dev, VIA_APSIZE, &temp); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -79,7 +79,7 @@ { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } @@ -107,11 +107,11 @@ u16 temp; struct aper_size_info_16 *values; - values = A_SIZE_16(agp_bridge->aperture_sizes); + values = A_SIZE_16(agp_bridge->driver->aperture_sizes); pci_read_config_word(agp_bridge->dev, VIA_AGP3_APSIZE, &temp); temp &= 0xfff; - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -174,99 +174,55 @@ { 2048, 524288, 9, 1<<11} /* 2GB <- Max supported */ }; +struct agp_bridge_driver via_agp3_driver = { + .owner = THIS_MODULE, + .masks = via_generic_masks, + .aperture_sizes = via_generic_agp3_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 10, + .configure = via_configure_agp3, + .fetch_size = via_fetch_size_agp3, + .cleanup = via_cleanup_agp3, + .tlb_flush = via_tlbflush_agp3, + .mask_memory = via_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init via_generic_agp3_setup (struct pci_dev *pdev) -{ - agp_bridge->dev = pdev; - agp_bridge->type = VIA_GENERIC; - agp_bridge->masks = via_generic_masks; - agp_bridge->aperture_sizes = (void *) via_generic_agp3_sizes; - agp_bridge->size_type = U16_APER_SIZE; - agp_bridge->num_aperture_sizes = 10; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->configure = via_configure_agp3; - agp_bridge->fetch_size = via_fetch_size_agp3; - agp_bridge->cleanup = via_cleanup_agp3; - agp_bridge->tlb_flush = via_tlbflush_agp3; - agp_bridge->mask_memory = via_mask_memory; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} - - -static int __init via_generic_setup (struct pci_dev *pdev) -{ - /* Garg, there are KT400s with KT266 IDs. */ - if (pdev->device == PCI_DEVICE_ID_VIA_8367_0) { - - /* Is there a KT400 subsystem ? */ - if (pdev->subsystem_device==PCI_DEVICE_ID_VIA_8377_0) { - u8 reg; - - printk (KERN_INFO PFX "Found KT400 in disguise as a KT266.\n"); - - /* Check AGP compatibility mode. */ - pci_read_config_byte(pdev, VIA_AGPSEL, ®); - if ((reg & (1<<1))==0) - return via_generic_agp3_setup(pdev); - - /* Its in 2.0 mode, drop through. */ - } - } - - agp_bridge->masks = via_generic_masks; - agp_bridge->aperture_sizes = (void *) via_generic_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = via_configure; - agp_bridge->fetch_size = via_fetch_size; - agp_bridge->cleanup = via_cleanup; - agp_bridge->tlb_flush = via_tlbflush; - agp_bridge->mask_memory = via_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} - - -/* The KT400 does magick to put the AGP bridge compliant with the same - * standards version as the graphics card. */ -static int __init via_kt400_setup(struct pci_dev *pdev) -{ - u8 reg; - pci_read_config_byte(pdev, VIA_AGPSEL, ®); - /* Check AGP 2.0 compatibility mode. */ - if ((reg & (1<<1))==0) - return via_generic_agp3_setup(pdev); - return via_generic_setup(pdev); -} - +struct agp_bridge_driver via_driver = { + .owner = THIS_MODULE, + .masks = via_generic_masks, + .aperture_sizes = via_generic_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = via_configure, + .fetch_size = via_fetch_size, + .cleanup = via_cleanup, + .tlb_flush = via_tlbflush, + .mask_memory = via_mask_memory, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; static struct agp_device_ids via_agp_device_ids[] __initdata = { @@ -310,7 +266,7 @@ /* VT8361 */ { - .device_id = PCI_DEVICE_ID_VIA_8361, // 0x3112 + .device_id = PCI_DEVICE_ID_VIA_8361, .chipset_name = "Apollo KLE133", }, @@ -353,7 +309,6 @@ { .device_id = PCI_DEVICE_ID_VIA_8377_0, .chipset_name = "Apollo Pro KT400", - .chipset_setup = via_kt400_setup, }, /* VT8604 / VT8605 / VT8603 / TwisterT @@ -402,74 +357,99 @@ /* P4M400 */ { .device_id = PCI_DEVICE_ID_VIA_P4M400, - .chipset_name = "PM400", + .chipset_name = "P4M400", }, { }, /* dummy final entry, always present */ }; - -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_via_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = via_agp_device_ids; + struct agp_device_ids *devs = via_agp_device_ids; + struct agp_bridge_data *bridge; + int j = 0; + u8 cap_ptr, reg; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name); - agp_bridge->type = VIA_GENERIC; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return via_generic_setup(pdev); + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name; j++) { + if (pdev->device == devs[j].device_id) { + printk (KERN_INFO PFX "Detected VIA %s chipset\n", + devs[j].chipset_name); + goto found; } - j++; } - /* try init anyway, if user requests it */ if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic VIA routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = VIA_GENERIC; - return via_generic_setup(pdev); + printk(KERN_ERR PFX + "Unsupported VIA chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic VIA routines" + " for device id: %04x\n", pdev->device); - -static struct agp_driver via_agp_driver = { - .owner = THIS_MODULE, -}; +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + switch (pdev->device) { + case PCI_DEVICE_ID_VIA_8367_0: + /* + * Garg, there are KT400s with KT266 IDs. + */ + /* Is there a KT400 subsystem ? */ + if (pdev->subsystem_device != PCI_DEVICE_ID_VIA_8377_0) + break; + + printk(KERN_INFO PFX "Found KT400 in disguise as a KT266.\n"); + /*FALLTHROUGH*/ + case PCI_DEVICE_ID_VIA_8377_0: + /* + * The KT400 does magick to put the AGP bridge compliant + * with the same standards version as the graphics card. + */ + pci_read_config_byte(pdev, VIA_AGPSEL, ®); + /* Check AGP 2.0 compatibility mode. */ + if ((reg & (1<<1))==0) { + bridge->driver = &via_agp3_driver; + break; + } + /*FALLTHROUGH*/ + default: + bridge->driver = &via_driver; + break; + } -static int __init agp_via_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + bridge->dev = pdev; + bridge->capndx = cap_ptr; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, &bridge->mode); - /* probe for known chipsets */ - if (agp_lookup_host_bridge (dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - via_agp_driver.dev = dev; - agp_register_driver(&via_agp_driver); - return 0; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); } +static void __devexit agp_via_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} static struct pci_device_id agp_via_pci_table[] __initdata = { { @@ -490,28 +470,20 @@ .name = "agpgart-via", .id_table = agp_via_pci_table, .probe = agp_via_probe, + .remove = agp_via_remove, }; static int __init agp_via_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_via_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_via_pci_driver); } - static void __exit agp_via_cleanup(void) { - agp_unregister_driver(&via_agp_driver); pci_unregister_driver(&agp_via_pci_driver); } - module_init(agp_via_init); module_exit(agp_via_cleanup); diff -urN linux-2.5.69-bk6/drivers/ide/ide-io.c linux-2.5.69-bk7/drivers/ide/ide-io.c --- linux-2.5.69-bk6/drivers/ide/ide-io.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/drivers/ide/ide-io.c 2003-05-12 04:43:29.000000000 -0700 @@ -850,14 +850,14 @@ * happens anyway when any interrupt comes in, IDE or otherwise * -- the kernel masks the IRQ while it is being handled. */ - if (hwif->irq != masked_irq) + if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&ide_lock); local_irq_enable(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&ide_lock); - if (hwif->irq != masked_irq) + if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_released) goto queue_next; diff -urN linux-2.5.69-bk6/drivers/net/Kconfig linux-2.5.69-bk7/drivers/net/Kconfig --- linux-2.5.69-bk6/drivers/net/Kconfig 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/Kconfig 2003-05-12 04:43:29.000000000 -0700 @@ -158,7 +158,7 @@ config NET_SB1000 tristate "General Instruments Surfboard 1000" - depends on NETDEVICES && ISAPNP + depends on NETDEVICES && PNP ---help--- This is a driver for the General Instrument (also known as NextLevel) SURFboard 1000 internal diff -urN linux-2.5.69-bk6/drivers/net/bmac.c linux-2.5.69-bk7/drivers/net/bmac.c --- linux-2.5.69-bk6/drivers/net/bmac.c 2003-05-04 16:52:50.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/bmac.c 2003-05-12 04:43:29.000000000 -0700 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,7 @@ int opened; unsigned short hash_use_count[64]; unsigned short hash_table_mask[4]; + spinlock_t lock; struct net_device *next_bmac; }; @@ -159,9 +161,9 @@ static void bmac_init_registers(struct net_device *dev); static void bmac_enable_and_reset_chip(struct net_device *dev); static int bmac_set_address(struct net_device *dev, void *addr); -static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs); -static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); -static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); static void bmac_set_timeout(struct net_device *dev); static void bmac_tx_timeout(unsigned long data); static int bmac_proc_info ( char *buffer, char **start, off_t offset, int length); @@ -485,7 +487,7 @@ case PBOOK_SLEEP_NOW: netif_device_detach(dev); /* prolly should wait for dma to finish & turn off the chip */ - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); if (bp->timeout_active) { del_timer(&bp->tx_timeout); bp->timeout_active = 0; @@ -494,7 +496,7 @@ disable_irq(bp->tx_dma_intr); disable_irq(bp->rx_dma_intr); bp->sleeping = 1; - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); if (bp->opened) { volatile struct dbdma_regs *rd = bp->rx_dma; volatile struct dbdma_regs *td = bp->tx_dma; @@ -539,13 +541,14 @@ static int bmac_set_address(struct net_device *dev, void *addr) { + struct bmac_data *bp = (struct bmac_data *) dev->priv; unsigned char *p = addr; unsigned short *pWord16; unsigned long flags; int i; XXDEBUG(("bmac: enter set_address\n")); - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); for (i = 0; i < 6; ++i) { dev->dev_addr[i] = p[i]; @@ -556,7 +559,7 @@ bmwrite(dev, MADD1, *pWord16++); bmwrite(dev, MADD2, *pWord16); - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); XXDEBUG(("bmac: exit set_address\n")); return 0; } @@ -566,8 +569,7 @@ struct bmac_data *bp = (struct bmac_data *) dev->priv; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&bp->lock, flags); if (bp->timeout_active) del_timer(&bp->tx_timeout); bp->tx_timeout.expires = jiffies + TX_TIMEOUT; @@ -575,7 +577,7 @@ bp->tx_timeout.data = (unsigned long) dev; add_timer(&bp->tx_timeout); bp->timeout_active = 1; - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } static void @@ -703,7 +705,7 @@ static int rxintcount; -static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct bmac_data *bp = (struct bmac_data *) dev->priv; @@ -715,7 +717,7 @@ int last; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); if (++rxintcount < 10) { XXDEBUG(("bmac_rxdma_intr\n")); @@ -769,18 +771,18 @@ bp->rx_empty = i; } - restore_flags(flags); - dbdma_continue(rd); + spin_unlock_irqrestore(&bp->lock, flags); if (rxintcount < 10) { XXDEBUG(("bmac_rxdma_intr done\n")); } + return IRQ_HANDLED; } static int txintcount; -static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct bmac_data *bp = (struct bmac_data *) dev->priv; @@ -788,7 +790,7 @@ int stat; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); if (txintcount++ < 10) { XXDEBUG(("bmac_txdma_intr\n")); @@ -824,13 +826,14 @@ break; } - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); if (txintcount < 10) { XXDEBUG(("bmac_txdma_intr done->bmac_start\n")); } bmac_start(dev); + return IRQ_HANDLED; } static struct net_device_stats *bmac_stats(struct net_device *dev) @@ -1096,7 +1099,7 @@ static int miscintcount; -static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct bmac_data *bp = (struct bmac_data *)dev->priv; @@ -1117,6 +1120,7 @@ if (status & TxErrorMask) bp->stats.tx_errors++; if (status & TxUnderrun) bp->stats.tx_fifo_errors++; if (status & TxNormalCollExp) bp->stats.collisions++; + return IRQ_HANDLED; } /* @@ -1249,7 +1253,7 @@ struct sk_buff *skb; unsigned char *data; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); bmac_enable_and_reset_chip(dev); bmac_init_tx_ring(bp); bmac_init_rx_ring(bp); @@ -1270,7 +1274,7 @@ memcpy(data+6, dev->dev_addr, 6); bmac_transmit_packet(skb, dev); } - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } static int __init bmac_probe(void) @@ -1336,6 +1340,7 @@ bp = (struct bmac_data *) dev->priv; SET_MODULE_OWNER(dev); bp->node = bmac; + spin_lock_init(&bp->lock); if (!request_OF_resource(bmac, 0, " (bmac)")) { printk(KERN_ERR "BMAC: can't request IO resource !\n"); @@ -1522,7 +1527,7 @@ if (bp->sleeping) return; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); while (1) { i = bp->tx_fill + 1; if (i >= N_TX_RING) @@ -1534,7 +1539,7 @@ break; bmac_transmit_packet(skb, dev); } - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } static int @@ -1558,7 +1563,7 @@ int i; XXDEBUG(("bmac: tx_timeout called\n")); - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); bp->timeout_active = 0; /* update various counters */ @@ -1614,7 +1619,7 @@ oldConfig = bmread(dev, TXCFG); bmwrite(dev, TXCFG, oldConfig | TxMACEnable ); - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } #if 0 diff -urN linux-2.5.69-bk6/drivers/net/depca.c linux-2.5.69-bk7/drivers/net/depca.c --- linux-2.5.69-bk6/drivers/net/depca.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/depca.c 2003-05-12 04:43:29.000000000 -0700 @@ -230,6 +230,7 @@ by acme@conectiva.com.br 0.54 08-Nov-01 use library crc32 functions by Matt_Domsch@dell.com + 0.55 01-Mar-03 Use EISA/sysfs framework ========================================================================= */ @@ -263,6 +264,11 @@ #include #endif +#ifdef CONFIG_EISA +#include +#include +#endif + #include "depca.h" static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n"; @@ -328,6 +334,25 @@ DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown } adapter; +#ifdef CONFIG_EISA +struct eisa_device_id depca_eisa_ids[] = { + { "DEC4220" }, + { "" } +}; + +static int depca_eisa_probe (struct device *device); +static int depca_eisa_remove (struct device *device); + +struct eisa_driver depca_eisa_driver = { + .id_table = depca_eisa_ids, + .driver = { + .name = "depca", + .probe = depca_eisa_probe, + .remove = __devexit_p (depca_eisa_remove) + } +}; +#endif + /* ** Miscellaneous info... */ @@ -388,6 +413,8 @@ void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ void *sh_mem; /* CPU mapped virt address of device RAM */ + u_long mem_start; /* Bus address of device RAM (before remap) */ + u_long mem_len; /* device memory size */ /* Device address space fields */ u_long device_ram_start; /* Start of RAM in device addr space */ /* Offsets used in both address spaces */ @@ -450,10 +477,8 @@ static void DepcaSignature(char *name, u_long paddr); static int DevicePresent(u_long ioaddr); static int get_hw_addr(struct net_device *dev); -static int EISA_signature(char *name, s32 eisa_id); static void SetMulticastFilter(struct net_device *dev); static void isa_probe(struct net_device *dev, u_long iobase); -static void eisa_probe(struct net_device *dev, u_long iobase); #ifdef CONFIG_MCA static void mca_probe(struct net_device *dev, u_long iobase); #endif @@ -503,7 +528,9 @@ mca_probe(dev, iobase); #endif isa_probe(dev, iobase); - eisa_probe(dev, iobase); +#ifdef CONFIG_EISA + eisa_driver_register (&depca_eisa_driver); +#endif if ((tmp == num_depcas) && (iobase != 0) && loading_module) { printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase); @@ -530,6 +557,7 @@ int i, j, offset, netRAM, mem_len, status = 0; s16 nicsr; u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; + int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS); STOP_DEPCA; @@ -555,7 +583,7 @@ if (mca_slot != -1) { printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot); - } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ + } else if (is_eisa) { /* EISA slot address */ printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f)); } else { /* ISA port address */ printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); @@ -600,9 +628,11 @@ } /* Define the device private memory */ - dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (!is_eisa) { + dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + } lp = (struct depca_private *) dev->priv; memset((char *) dev->priv, 0, sizeof(struct depca_private)); lp->adapter = adapter; @@ -610,18 +640,23 @@ lp->lock = SPIN_LOCK_UNLOCKED; sprintf(lp->adapter_name, "%s (%s)", name, dev->name); status = -EBUSY; - if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) { - printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr); - goto out_priv; - } /* Initialisation Block */ - lp->sh_mem = ioremap(mem_start, mem_len); + if (!request_mem_region (mem_start, mem_len, lp->adapter_name)) { + printk(KERN_ERR "depca: cannot request ISA memory, aborting\n"); + goto out_priv; + } + status = -EIO; + lp->sh_mem = ioremap(mem_start, mem_len); if (lp->sh_mem == NULL) { printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n"); - goto out_region; + release_mem_region (mem_start, mem_len); + goto out_priv; } + + lp->mem_start = mem_start; + lp->mem_len = mem_len; lp->device_ram_start = mem_start & LA_MASK; offset = 0; @@ -703,7 +738,7 @@ status = -ENXIO; if (!irqnum) { printk(" and failed to detect IRQ line.\n"); - goto out_region; + goto out_priv; } else { for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++) if (irqnum == depca_irq[i]) { @@ -714,7 +749,7 @@ status = -ENXIO; if (!dev->irq) { printk(" but incorrect IRQ line detected.\n"); - goto out_region; + goto out_priv; } } #endif /* MODULE */ @@ -739,13 +774,16 @@ dev->mem_start = 0; /* Fill in the generic field of the device structure. */ - ether_setup(dev); + if (!is_eisa) + ether_setup(dev); return 0; - out_region: - release_region(ioaddr, DEPCA_TOTAL_SIZE); out_priv: - kfree(dev->priv); - dev->priv = NULL; + if (!is_eisa) { + kfree(dev->priv); + dev->priv = NULL; + } else { + unregister_netdev (dev); + } return status; } @@ -1351,31 +1389,35 @@ ** Get everything allocated and initialized... (almost just ** like the ISA and EISA probes) */ + if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) { + if (autoprobed) + printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + goto next; + } if (DevicePresent(iobase) != 0) { /* ** If the MCA configuration says the card should be here, ** it really should be here. */ printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase); + goto release_next; } - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - dev->irq = irq; - if (depca_hw_init(dev, iobase, slot) == 0) { - /* - ** Adapter initialized correctly: Name it in - ** /proc/mca. - */ - mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); - mca_mark_as_used(slot); - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } + if (!(dev = alloc_device(dev, iobase))) + goto release_next; + + num_eth++; + dev->irq = irq; + if (depca_hw_init(dev, iobase, slot)) + goto release_next; + + /* + ** Adapter initialized correctly: Name it in + ** /proc/mca. + */ + mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); + mca_mark_as_used(slot); + num_depcas++; /* ** If this is a probe by a module, return after setting up the @@ -1385,9 +1427,15 @@ return; /* - ** Set up to check the next slot and loop. + ** Set up to check the next slot and loop. */ slot++; + continue; + + release_next: + release_region (iobase, DEPCA_TOTAL_SIZE); + next: + slot++; } } @@ -1418,69 +1466,100 @@ } for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { - if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { - if (DevicePresent(ports[i]) == 0) { - if ((dev = alloc_device(dev, ports[i])) != NULL) { - if (depca_hw_init(dev, ports[i], -1) == 0) { - num_depcas++; - } - num_eth++; - } - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) { + if (autoprobed) + printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + continue; } + + if (DevicePresent(ports[i])) { + release_region (ports[i], DEPCA_TOTAL_SIZE); + continue; + } + + if (!(dev = alloc_device(dev, ports[i]))) { + release_region (ports[i], DEPCA_TOTAL_SIZE); + continue; + } + + num_eth++; + + if (depca_hw_init(dev, ports[i], -1)) { + release_region (ports[i], DEPCA_TOTAL_SIZE); + continue; + } + + num_depcas++; } return; } /* -** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually -** the motherboard. Upto 15 EISA devices are supported. +** EISA callbacks from sysfs. */ -static void __init eisa_probe(struct net_device *dev, u_long ioaddr) + +#ifdef CONFIG_EISA +static int __init depca_eisa_probe (struct device *device) { - int i, maxSlots; + struct eisa_device *edev; + struct net_device *dev; u_long iobase; - char name[DEPCA_STRLEN]; + int status = 0; - if (!ioaddr && autoprobed) - return; /* Been here before ! */ - if ((ioaddr < 0x400) && (ioaddr > 0)) - return; /* ISA Address */ + edev = to_eisa_device (device); + iobase = edev->base_addr + DEPCA_EISA_IO_PORTS; - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; + if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) { + status = -EBUSY; + goto out; + } + + if (DevicePresent(iobase)) { + status = -ENODEV; + goto out_release; } - if ((iobase & 0x0fff) == 0) - iobase += DEPCA_EISA_IO_PORTS; - for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if (EISA_signature(name, EISA_ID)) { - if (DevicePresent(iobase) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if (depca_hw_init(dev, iobase, -1) == 0) { - num_depcas++; - } - num_eth++; - } - } - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } + if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) { + status = -ENOMEM; + goto out_release; } + + eisa_set_drvdata (edev, dev); - return; + if ((status = depca_hw_init(dev, iobase, -1))) + goto out_free; + + num_depcas++; + return 0; + + out_free: + kfree (dev); + out_release: + release_region (iobase, DEPCA_TOTAL_SIZE); + out: + return status; +} + +static int __devexit depca_eisa_remove (struct device *device) +{ + struct net_device *dev; + struct eisa_device *edev; + struct depca_private *lp; + + edev = to_eisa_device (device); + dev = eisa_get_drvdata (edev); + lp = dev->priv; + + unregister_netdev (dev); + iounmap (lp->sh_mem); + release_mem_region (lp->mem_start, lp->mem_len); + release_region (dev->base_addr, DEPCA_TOTAL_SIZE); + kfree (dev); + + return 0; } +#endif /* ** Search the entire 'eth' device list for a fixed probe. If a match isn't @@ -1781,40 +1860,6 @@ return status; } -/* -** Look for a particular board name in the EISA configuration space -*/ -static int __init EISA_signature(char *name, s32 eisa_id) -{ - u_int i; - const char *signatures[] = DEPCA_SIGNATURE; - char ManCode[DEPCA_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); - ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); - ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); - ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); - ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); - ManCode[5] = '\0'; - - for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name, ManCode); - status = 1; - } - } - - return status; -} - static void depca_dbg_open(struct net_device *dev) { struct depca_private *lp = (struct depca_private *) dev->priv; @@ -2067,6 +2112,7 @@ unregister_netdev(&thisDepca); if (lp) { iounmap(lp->sh_mem); + release_mem_region (lp->mem_start, lp->mem_len); #ifdef CONFIG_MCA if (lp->mca_slot != -1) mca_mark_as_unused(lp->mca_slot); diff -urN linux-2.5.69-bk6/drivers/net/mace.c linux-2.5.69-bk7/drivers/net/mace.c --- linux-2.5.69-bk6/drivers/net/mace.c 2003-05-04 16:53:08.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/mace.c 2003-05-12 04:43:29.000000000 -0700 @@ -86,9 +86,9 @@ static void mace_set_multicast(struct net_device *dev); static void mace_reset(struct net_device *dev); static int mace_set_address(struct net_device *dev, void *addr); -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); -static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); static void mace_set_timeout(struct net_device *dev); static void mace_tx_timeout(unsigned long data); static inline void dbdma_reset(volatile struct dbdma_regs *dma); @@ -622,7 +622,7 @@ printk(KERN_DEBUG "mace: jabbering transceiver\n"); } -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct mace_data *mp = (struct mace_data *) dev->priv; @@ -765,6 +765,7 @@ mace_set_timeout(dev); } spin_unlock_irqrestore(&mp->lock, flags); + return IRQ_HANDLED; } static void mace_tx_timeout(unsigned long data) @@ -833,11 +834,12 @@ spin_unlock_irqrestore(&mp->lock, flags); } -static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_HANDLED; } -static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct mace_data *mp = (struct mace_data *) dev->priv; @@ -947,6 +949,7 @@ mp->rx_fill = i; } spin_unlock_irqrestore(&mp->lock, flags); + return IRQ_HANDLED; } MODULE_AUTHOR("Paul Mackerras"); diff -urN linux-2.5.69-bk6/drivers/net/sb1000.c linux-2.5.69-bk7/drivers/net/sb1000.c --- linux-2.5.69-bk6/drivers/net/sb1000.c 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/sb1000.c 2003-05-12 04:43:29.000000000 -0700 @@ -49,7 +49,7 @@ #include #include /* for udelay() */ #include -#include +#include #include #include @@ -131,146 +131,122 @@ static inline int sb1000_rx(struct net_device *dev); static inline void sb1000_error_dpc(struct net_device *dev); -static struct isapnp_device_id id_table[] = { - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('G','I','C'), ISAPNP_FUNCTION(0x1000), 0 }, - {0} +static const struct pnp_device_id sb1000_pnp_ids[] = { + { "GIC1000", 0 }, + { "", 0 } }; +MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids); -MODULE_DEVICE_TABLE(isapnp, id_table); - -/* probe for SB1000 using Plug-n-Play mechanism */ -int -sb1000_probe(struct net_device *dev) +static void +sb1000_setup(struct net_device *dev) { + dev->type = ARPHRD_ETHER; + dev->mtu = 1500; + dev->addr_len = ETH_ALEN; + + /* New-style flags. */ + dev->flags = IFF_POINTOPOINT|IFF_NOARP; +} +static int +sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id) +{ + struct net_device *dev; unsigned short ioaddr[2], irq; - struct pnp_dev *idev=NULL; unsigned int serial_number; + int error = -ENODEV; - while(1) - { - /* - * Find the card - */ - - idev=pnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'), - ISAPNP_FUNCTION(0x1000), idev); - - /* - * No card - */ - - if(idev==NULL || idev->card == NULL) - return -ENODEV; - - /* - * Bring it online - */ - - if (pnp_device_attach(idev) < 0) - continue; - if (pnp_activate_dev(idev) < 0) { - __again: - pnp_device_detach(idev); - continue; - } - - /* - * Ports free ? - */ - - if(!pnp_port_valid(idev, 0) || !pnp_port_valid(idev, 1) || !pnp_irq_valid(idev, 0)) - goto __again; + if (pnp_device_attach(pdev) < 0) + return -ENODEV; + if (pnp_activate_dev(pdev) < 0) + goto out_detach; + + if (!pnp_port_valid(pdev, 0) || !pnp_port_valid(pdev, 1)) + goto out_disable; + if (!pnp_irq_valid(pdev, 0)) + goto out_disable; - serial_number = idev->card->serial; + serial_number = pdev->card->serial; - ioaddr[0]=pnp_port_start(idev, 0); - ioaddr[1]=pnp_port_start(idev, 0); + ioaddr[0] = pnp_port_start(pdev, 0); + ioaddr[1] = pnp_port_start(pdev, 0); - irq = pnp_irq(idev, 0); + irq = pnp_irq(pdev, 0); - /* check I/O base and IRQ */ - if (dev->base_addr != 0 && dev->base_addr != ioaddr[0]) - goto __again; - if (dev->mem_start != 0 && dev->mem_start != ioaddr[1]) - goto __again; - if (dev->irq != 0 && dev->irq != irq) - goto __again; - - /* - * Ok set it up. - */ - if (!request_region(ioaddr[0], 16, dev->name)) - goto __again; - if (!request_region(ioaddr[1], 16, dev->name)) { - release_region(ioaddr[0], 16); - goto __again; - } + if (!request_region(ioaddr[0], 16, dev->name)) + goto out_disable; + if (!request_region(ioaddr[1], 16, dev->name)) + goto out_release_region0; - dev->base_addr = ioaddr[0]; - /* mem_start holds the second I/O address */ - dev->mem_start = ioaddr[1]; - dev->irq = irq; - - if (sb1000_debug > 0) - printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), " - "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr, - dev->mem_start, serial_number, dev->irq); - - dev = init_etherdev(dev, 0); - if (!dev) { - pnp_device_detach(idev); - release_region(ioaddr[1], 16); - release_region(ioaddr[0], 16); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - - /* Make up a SB1000-specific-data structure. */ - dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct sb1000_private)); - - if (sb1000_debug > 0) - printk(KERN_NOTICE "%s", version); - - /* The SB1000-specific entries in the device structure. */ - dev->open = sb1000_open; - dev->do_ioctl = sb1000_dev_ioctl; - dev->hard_start_xmit = sb1000_start_xmit; - dev->stop = sb1000_close; - dev->get_stats = sb1000_stats; - - /* Fill in the generic fields of the device structure. */ - dev->change_mtu = NULL; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = NULL; - dev->header_cache_update= NULL; - - dev->type = ARPHRD_ETHER; - dev->hard_header_len = 0; - dev->mtu = 1500; - dev->addr_len = ETH_ALEN; - /* hardware address is 0:0:serial_number */ - dev->dev_addr[0] = 0; - dev->dev_addr[1] = 0; - dev->dev_addr[2] = serial_number >> 24 & 0xff; - dev->dev_addr[3] = serial_number >> 16 & 0xff; - dev->dev_addr[4] = serial_number >> 8 & 0xff; - dev->dev_addr[5] = serial_number >> 0 & 0xff; - dev->tx_queue_len = 0; - - /* New-style flags. */ - dev->flags = IFF_POINTOPOINT|IFF_NOARP; + dev->base_addr = ioaddr[0]; + /* mem_start holds the second I/O address */ + dev->mem_start = ioaddr[1]; + dev->irq = irq; - /* Lock resources */ + if (sb1000_debug > 0) + printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), " + "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr, + dev->mem_start, serial_number, dev->irq); + + dev = alloc_netdev(sizeof(struct sb1000_private), "cm%d", sb1000_setup); + if (!dev) { + error = -ENOMEM; + goto out_release_regions; + } + SET_MODULE_OWNER(dev); + + if (sb1000_debug > 0) + printk(KERN_NOTICE "%s", version); + + /* The SB1000-specific entries in the device structure. */ + dev->open = sb1000_open; + dev->do_ioctl = sb1000_dev_ioctl; + dev->hard_start_xmit = sb1000_start_xmit; + dev->stop = sb1000_close; + dev->get_stats = sb1000_stats; + + /* hardware address is 0:0:serial_number */ + dev->dev_addr[2] = serial_number >> 24 & 0xff; + dev->dev_addr[3] = serial_number >> 16 & 0xff; + dev->dev_addr[4] = serial_number >> 8 & 0xff; + dev->dev_addr[5] = serial_number >> 0 & 0xff; + + pnp_set_drvdata(pdev, dev); + + error = register_netdev(dev); + if (error) + goto out_unregister; + return 0; - return 0; - } -} + out_unregister: + unregister_netdev(dev); + out_release_regions: + release_region(ioaddr[1], 16); + out_release_region0: + release_region(ioaddr[0], 16); + out_disable: + pnp_disable_dev(pdev); + out_detach: + pnp_device_detach(pdev); + return error; +} + +static void +sb1000_remove_one(struct pnp_dev *pdev) +{ + struct net_device *dev = pnp_get_drvdata(pdev); + + unregister_netdev(dev); + release_region(dev->base_addr, 16); + release_region(dev->mem_start, 16); +} + +static struct pnp_driver sb1000_driver = { + .name = "sb1000", + .id_table = sb1000_pnp_ids, + .probe = sb1000_probe_one, + .remove = sb1000_remove_one, +}; /* @@ -1207,60 +1183,21 @@ return 0; } -#ifdef MODULE MODULE_AUTHOR("Franco Venturi "); MODULE_DESCRIPTION("General Instruments SB1000 driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(io, "1-2i"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(io, "SB1000 I/O base addresses"); -MODULE_PARM_DESC(irq, "SB1000 IRQ number"); - -static struct net_device dev_sb1000; -static int io[2]; -static int irq; - -int -init_module(void) +static int __init +sb1000_init(void) { - int i; - for (i = 0; i < 100; i++) { - sprintf(dev_sb1000.name, "cm%d", i); - if (dev_get(dev_sb1000.name) == 0) break; - } - if (i == 100) { - printk(KERN_ERR "sb1000: can't register any device cm\n"); - return -ENFILE; - } - dev_sb1000.init = sb1000_probe; - dev_sb1000.base_addr = io[0]; - /* mem_start holds the second I/O address */ - dev_sb1000.mem_start = io[1]; - dev_sb1000.irq = irq; - if (register_netdev(&dev_sb1000) != 0) { - printk(KERN_ERR "sb1000: failed to register device (io: %03x,%03x " - "irq: %d)\n", io[0], io[1], irq); - return -EIO; - } - return 0; + return pnp_register_driver(&sb1000_driver); } -void cleanup_module(void) +static void __exit +sb1000_exit(void) { - unregister_netdev(&dev_sb1000); - release_region(dev_sb1000.base_addr, 16); - release_region(dev_sb1000.mem_start, 16); - kfree(dev_sb1000.priv); - dev_sb1000.priv = NULL; + pnp_unregister_driver(&sb1000_driver); } -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -DMODULE -Wall -Wstrict-prototypes -O -m486 -c sb1000.c" - * version-control: t - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ + +module_init(sb1000_init); +module_exit(sb1000_exit); diff -urN linux-2.5.69-bk6/drivers/net/setup.c linux-2.5.69-bk7/drivers/net/setup.c --- linux-2.5.69-bk6/drivers/net/setup.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/setup.c 2003-05-12 04:43:29.000000000 -0700 @@ -21,14 +21,6 @@ extern int madgemc_probe(void); -/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ -#define __PAD6 "\0\0\0\0\0\0\0\0\0" -#define __PAD5 __PAD6 "\0" -#define __PAD4 __PAD5 "\0" -#define __PAD3 __PAD4 "\0" -#define __PAD2 __PAD3 "\0" - - /* * Devices in this list must do new style probing. That is they must * allocate their own device objects and do their own bus scans. @@ -84,7 +76,7 @@ * into them. */ -static void __init network_probe(void) +void __init net_device_init(void) { struct net_probe *p = pci_probes; @@ -94,28 +86,3 @@ p++; } } - -static void __init special_device_init(void) -{ -#ifdef CONFIG_NET_SB1000 - extern int sb1000_probe(struct net_device *dev); - - static struct net_device sb1000_dev = { - .name = "cm0" __PAD3, - .init = sb1000_probe, - }; - register_netdev(&sb1000_dev); -#endif -} - -/* - * Initialise network devices - */ - -void __init net_device_init(void) -{ - /* Devices supporting the new^H^H^Hold probing API */ - network_probe(); - /* Special devices */ - special_device_init(); -} diff -urN linux-2.5.69-bk6/drivers/net/tulip/tulip_core.c linux-2.5.69-bk7/drivers/net/tulip/tulip_core.c --- linux-2.5.69-bk6/drivers/net/tulip/tulip_core.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/tulip/tulip_core.c 2003-05-12 04:43:29.000000000 -0700 @@ -223,6 +223,7 @@ { 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, /* ALi 1563 integrated ethernet */ { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); @@ -1325,12 +1326,14 @@ csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */ /* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */ - if (pdev->vendor == 0x1282 && pdev->device == 0x9102) + if ((pdev->vendor == 0x1282 && pdev->device == 0x9102) + || (pdev->vendor == 0x10b9 && pdev->device == 0x5261)) csr0 &= ~0x01f100ff; #if defined(__sparc__) /* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */ - if (pdev->vendor == 0x1282 && pdev->device == 0x9102) + if ((pdev->vendor == 0x1282 && pdev->device == 0x9102) + || (pdev->vendor == 0x10b9 && pdev->device == 0x5261)) csr0 = (csr0 & ~0xff00) | 0xe000; #endif diff -urN linux-2.5.69-bk6/drivers/net/wireless/netwave_cs.c linux-2.5.69-bk7/drivers/net/wireless/netwave_cs.c --- linux-2.5.69-bk6/drivers/net/wireless/netwave_cs.c 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/wireless/netwave_cs.c 2003-05-12 04:43:29.000000000 -0700 @@ -227,7 +227,7 @@ static int netwave_rx( struct net_device *dev); /* Interrupt routines */ -static void netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void netwave_watchdog(struct net_device *); /* Statistics */ @@ -1456,7 +1456,7 @@ * ready to transmit another packet. * 3. A command has completed execution. */ -static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { +static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { ioaddr_t iobase; u_char *ramBase; struct net_device *dev = (struct net_device *)dev_id; @@ -1465,7 +1465,7 @@ int i; if (!netif_device_present(dev)) - return; + return IRQ_NONE; iobase = dev->base_addr; ramBase = priv->ramBase; @@ -1476,7 +1476,7 @@ wait_WOC(iobase); if (!(inb(iobase+NETWAVE_REG_CCSR) & 0x02)) - break; /* None of the interrupt sources asserted */ + break; /* None of the interrupt sources asserted (normal exit) */ status = inb(iobase + NETWAVE_REG_ASR); @@ -1569,6 +1569,8 @@ } */ } + /* Handled if we looped at least one time - Jean II */ + return IRQ_RETVAL(i); } /* netwave_interrupt */ /* diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan.c linux-2.5.69-bk7/drivers/net/wireless/wavelan.c --- linux-2.5.69-bk6/drivers/net/wireless/wavelan.c 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/wireless/wavelan.c 2003-05-12 04:43:29.000000000 -0700 @@ -1717,31 +1717,28 @@ return (i); } -#ifdef WIRELESS_SPY +#ifdef IW_WIRELESS_SPY /*------------------------------------------------------------------*/ /* * Gather wireless spy statistics: for each packet, compare the source * address with our list, and if they match, get the statistics. * Sorry, but this function really needs the wireless extensions. */ -static inline void wl_spy_gather(device * dev, u8 * mac, /* MAC address */ - u8 * stats) -{ /* Statistics to gather */ - net_local *lp = (net_local *) dev->priv; - int i; +static inline void wl_spy_gather(device * dev, + u8 * mac, /* MAC address */ + u8 * stats) /* Statistics to gather */ +{ + struct iw_quality wstats; - /* Check all addresses. */ - for (i = 0; i < lp->spy_number; i++) - /* If match */ - if (!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) { - /* Update statistics */ - lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL; - lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL; - lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL; - lp->spy_stat[i].updated = 0x7; - } + wstats.qual = stats[2] & MMR_SGNL_QUAL; + wstats.level = stats[0] & MMR_SIGNAL_LVL; + wstats.noise = stats[1] & MMR_SILENCE_LVL; + wstats.updated = 0x7; + + /* Update spy records */ + wireless_spy_update(dev, mac, &wstats); } -#endif /* WIRELESS_SPY */ +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM /*------------------------------------------------------------------*/ @@ -1767,7 +1764,7 @@ /* Increment interval counter. */ (lp->his_sum[i])++; } -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ /*------------------------------------------------------------------*/ /* @@ -2203,93 +2200,6 @@ return ret; } -#ifdef WIRELESS_SPY -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set spy list - */ -static int wavelan_set_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - int ret = 0; - - /* Disable spy while we copy the addresses. - * As we don't disable interrupts, we need to do this */ - lp->spy_number = 0; - - /* Are there are addresses to copy? */ - if (wrqu->data.length > 0) { - /* Copy addresses to the lp structure. */ - for (i = 0; i < wrqu->data.length; i++) { - memcpy(lp->spy_address[i], address[i].sa_data, - WAVELAN_ADDR_SIZE); - } - - /* Reset structure. */ - memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG - "SetSpy: set of new addresses is: \n"); - for (i = 0; i < wrqu->data.length; i++) - printk(KERN_DEBUG - "%02X:%02X:%02X:%02X:%02X:%02X \n", - lp->spy_address[i][0], - lp->spy_address[i][1], - lp->spy_address[i][2], - lp->spy_address[i][3], - lp->spy_address[i][4], - lp->spy_address[i][5]); -#endif /* DEBUG_IOCTL_INFO */ - } - - /* Now we can set the number of addresses */ - lp->spy_number = wrqu->data.length; - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get spy list - */ -static int wavelan_get_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - - /* Set the number of addresses */ - wrqu->data.length = lp->spy_number; - - /* Copy addresses from the lp structure. */ - for (i = 0; i < lp->spy_number; i++) { - memcpy(address[i].sa_data, - lp->spy_address[i], - WAVELAN_ADDR_SIZE); - address[i].sa_family = AF_UNIX; - } - /* Copy stats to the user buffer (just after). */ - if(lp->spy_number > 0) - memcpy(extra + (sizeof(struct sockaddr) * lp->spy_number), - lp->spy_stat, sizeof(iw_qual) * lp->spy_number); - - /* Reset updated flags. */ - for (i = 0; i < lp->spy_number; i++) - lp->spy_stat[i].updated = 0x0; - - return(0); -} -#endif /* WIRELESS_SPY */ - /*------------------------------------------------------------------*/ /* * Wireless Private Handler : set quality threshold @@ -2439,15 +2349,10 @@ NULL, /* SIOCGIWPRIV */ NULL, /* SIOCSIWSTATS */ NULL, /* SIOCGIWSTATS */ -#ifdef WIRELESS_SPY - wavelan_set_spy, /* SIOCSIWSPY */ - wavelan_get_spy, /* SIOCGIWSPY */ -#else /* WIRELESS_SPY */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ -#endif /* WIRELESS_SPY */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ NULL, /* SIOCSIWAP */ NULL, /* SIOCGIWAP */ NULL, /* -- hole -- */ @@ -2501,6 +2406,8 @@ .standard = (iw_handler *) wavelan_handler, .private = (iw_handler *) wavelan_private_handler, .private_args = (struct iw_priv_args *) wavelan_private_args, + .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - + (void *) NULL), }; /*------------------------------------------------------------------*/ @@ -2618,22 +2525,23 @@ #endif /* DEBUG_RX_INFO */ /* Statistics-gathering and associated stuff. - * It seem a bit messy with all the define, but it's really simple... */ -#if defined(WIRELESS_SPY) || defined(HISTOGRAM) + * It seem a bit messy with all the define, but it's really + * simple... */ if ( -#ifdef WIRELESS_SPY - (lp->spy_number > 0) || -#endif /* WIRELESS_SPY */ +#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ + (lp->spy_data.spy_number > 0) || +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM (lp->his_number > 0) || -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ 0) { u8 stats[3]; /* signal level, noise level, signal quality */ - /* Read signal level, silence level and signal quality bytes. */ - /* Note: in the PCMCIA hardware, these are part of the frame. It seems - * that for the ISA hardware, it's nowhere to be found in the frame, - * so I'm obliged to do this (it has a side effect on /proc/net/wireless). + /* Read signal level, silence level and signal quality bytes */ + /* Note: in the PCMCIA hardware, these are part of the frame. + * It seems that for the ISA hardware, it's nowhere to be + * found in the frame, so I'm obliged to do this (it has a + * side effect on /proc/net/wireless). * Any ideas? */ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); @@ -2648,15 +2556,14 @@ #endif /* Spying stuff */ -#ifdef WIRELESS_SPY +#ifdef IW_WIRELESS_SPY wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats); -#endif /* WIRELESS_SPY */ +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM wl_his_gather(dev, stats); -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ } -#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */ /* * Hand the packet to the network module. @@ -2884,10 +2791,6 @@ length); #endif - /* Do we need some padding? */ - if (clen < ETH_ZLEN) - clen = ETH_ZLEN; - spin_lock_irqsave(&lp->spinlock, flags); /* Check nothing bad has happened */ @@ -3008,12 +2911,6 @@ (unsigned) skb); #endif - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } - /* * Block a timer-based transmit from overlapping. * In other words, prevent reentering this routine. @@ -3036,6 +2933,17 @@ printk(KERN_INFO "skb has next\n"); #endif + /* Do we need some padding? */ + /* Note : on wireless the propagation time is in the order of 1us, + * and we don't have the Ethernet specific requirement of beeing + * able to detect collisions, therefore in theory we don't really + * need to pad. Jean II */ + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } + /* Write packet on the card */ if(wv_packet_write(dev, skb->data, skb->len)) return 1; /* We failed */ diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan.p.h linux-2.5.69-bk7/drivers/net/wireless/wavelan.p.h --- linux-2.5.69-bk6/drivers/net/wireless/wavelan.p.h 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/wireless/wavelan.p.h 2003-05-12 04:43:29.000000000 -0700 @@ -509,13 +509,9 @@ #ifdef WIRELESS_EXT iw_stats wstats; /* Wireless-specific statistics */ -#endif -#ifdef WIRELESS_SPY - int spy_number; /* number of addresses to spy */ - mac_addr spy_address[IW_MAX_SPY]; /* the addresses to spy */ - iw_qual spy_stat[IW_MAX_SPY]; /* statistics gathered */ -#endif /* WIRELESS_SPY */ + struct iw_spy_data spy_data; +#endif #ifdef HISTOGRAM int his_number; /* number of intervals */ diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.c linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.c --- linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.c 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.c 2003-05-12 04:43:29.000000000 -0700 @@ -1757,10 +1757,8 @@ u_short table[10]; /* Authorized frequency table */ long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */ int i; /* index in the table */ -#if WIRELESS_EXT > 7 const int BAND_NUM = 10; /* Number of bands */ int c = 0; /* Channel number */ -#endif /* WIRELESS_EXT */ /* Read the frequency table */ fee_read(base, 0x71 /* frequency table */, @@ -1772,13 +1770,11 @@ /* Look in the table if the frequency is allowed */ if(table[9 - (freq / 16)] & (1 << (freq % 16))) { -#if WIRELESS_EXT > 7 /* Compute approximate channel number */ while((((channel_bands[c] >> 1) - 24) < freq) && (c < BAND_NUM)) c++; list[i].i = c; /* Set the list index */ -#endif /* WIRELESS_EXT */ /* put in the list */ list[i].m = (((freq + 24) * 5) + 24000L) * 10000; @@ -1792,7 +1788,7 @@ return(i); } -#ifdef WIRELESS_SPY +#ifdef IW_WIRELESS_SPY /*------------------------------------------------------------------*/ /* * Gather wireless spy statistics : for each packet, compare the source @@ -1804,22 +1800,17 @@ u_char * mac, /* MAC address */ u_char * stats) /* Statistics to gather */ { - net_local * lp = (net_local *) dev->priv; - int i; + struct iw_quality wstats; - /* Look all addresses */ - for(i = 0; i < lp->spy_number; i++) - /* If match */ - if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) - { - /* Update statistics */ - lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL; - lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL; - lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL; - lp->spy_stat[i].updated = 0x7; - } + wstats.qual = stats[2] & MMR_SGNL_QUAL; + wstats.level = stats[0] & MMR_SIGNAL_LVL; + wstats.noise = stats[1] & MMR_SILENCE_LVL; + wstats.updated = 0x7; + + /* Update spy records */ + wireless_spy_update(dev, mac, &wstats); } -#endif /* WIRELESS_SPY */ +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM /*------------------------------------------------------------------*/ @@ -1904,17 +1895,10 @@ spin_lock_irqsave(&lp->spinlock, flags); /* Set NWID in WaveLAN. */ -#if WIRELESS_EXT > 8 if (!wrqu->nwid.disabled) { /* Set NWID in psa */ psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8; psa.psa_nwid[1] = wrqu->nwid.value & 0xFF; -#else /* WIRELESS_EXT > 8 */ - if(wrq->u.nwid.on) { - /* Set NWID in psa */ - psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8; - psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF; -#endif /* WIRELESS_EXT > 8 */ psa.psa_nwid_select = 0x01; psa_write(dev, (char *) psa.psa_nwid - (char *) &psa, @@ -1971,14 +1955,9 @@ psa_read(dev, (char *) psa.psa_nwid - (char *) &psa, (unsigned char *) psa.psa_nwid, 3); -#if WIRELESS_EXT > 8 wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; wrqu->nwid.disabled = !(psa.psa_nwid_select); wrqu->nwid.fixed = 1; /* Superfluous */ -#else /* WIRELESS_EXT > 8 */ - wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; - wrq->u.nwid.on = psa.psa_nwid_select; -#endif /* WIRELESS_EXT > 8 */ /* Enable interrupts and restore flags. */ spin_unlock_irqrestore(&lp->spinlock, flags); @@ -2081,13 +2060,9 @@ spin_lock_irqsave(&lp->spinlock, flags); /* Set the level threshold. */ -#if WIRELESS_EXT > 7 /* We should complain loudly if wrqu->sens.fixed = 0, because we * can't set auto mode... */ psa.psa_thr_pre_set = wrqu->sens.value & 0x3F; -#else /* WIRELESS_EXT > 7 */ - psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F; -#endif /* WIRELESS_EXT > 7 */ psa_write(dev, (char *) &psa.psa_thr_pre_set - (char *) &psa, (unsigned char *) &psa.psa_thr_pre_set, 1); @@ -2123,12 +2098,8 @@ psa_read(dev, (char *) &psa.psa_thr_pre_set - (char *) &psa, (unsigned char *) &psa.psa_thr_pre_set, 1); -#if WIRELESS_EXT > 7 wrqu->sens.value = psa.psa_thr_pre_set & 0x3F; wrqu->sens.fixed = 1; -#else /* WIRELESS_EXT > 7 */ - wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F; -#endif /* WIRELESS_EXT > 7 */ /* Enable interrupts and restore flags. */ spin_unlock_irqrestore(&lp->spinlock, flags); @@ -2136,7 +2107,6 @@ return ret; } -#if WIRELESS_EXT > 8 /*------------------------------------------------------------------*/ /* * Wireless Handler : set encryption key @@ -2253,10 +2223,8 @@ return ret; } -#endif /* WIRELESS_EXT > 8 */ #ifdef WAVELAN_ROAMING_EXT -#if WIRELESS_EXT > 5 /*------------------------------------------------------------------*/ /* * Wireless Handler : set ESSID (domain) @@ -2367,10 +2335,8 @@ return -EOPNOTSUPP; } -#endif /* WIRELESS_EXT > 5 */ #endif /* WAVELAN_ROAMING_EXT */ -#if WIRELESS_EXT > 8 #ifdef WAVELAN_ROAMING /*------------------------------------------------------------------*/ /* @@ -2429,7 +2395,6 @@ return 0; } #endif /* WAVELAN_ROAMING */ -#endif /* WIRELESS_EXT > 8 */ /*------------------------------------------------------------------*/ /* @@ -2452,11 +2417,9 @@ /* Set all the info we don't care or don't know about to zero */ memset(range, 0, sizeof(struct iw_range)); -#if WIRELESS_EXT > 10 /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 9; -#endif /* WIRELESS_EXT > 10 */ /* Set information in the range struct. */ range->throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */ @@ -2467,17 +2430,13 @@ range->max_qual.qual = MMR_SGNL_QUAL; range->max_qual.level = MMR_SIGNAL_LVL; range->max_qual.noise = MMR_SILENCE_LVL; -#if WIRELESS_EXT > 11 range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */ /* Need to get better values for those two */ range->avg_qual.level = 30; range->avg_qual.noise = 8; -#endif /* WIRELESS_EXT > 11 */ -#if WIRELESS_EXT > 7 range->num_bitrates = 1; range->bitrate[0] = 2000000; /* 2 Mb/s */ -#endif /* WIRELESS_EXT > 7 */ /* Disable interrupts and save flags. */ spin_lock_irqsave(&lp->spinlock, flags); @@ -2491,7 +2450,6 @@ } else range->num_channels = range->num_frequency = 0; -#if WIRELESS_EXT > 8 /* Encryption supported ? */ if (mmc_encr(base)) { range->encoding_size[0] = 8; /* DES = 64 bits key */ @@ -2501,7 +2459,6 @@ range->num_encoding_sizes = 0; range->max_encoding_tokens = 0; } -#endif /* WIRELESS_EXT > 8 */ /* Enable interrupts and restore flags. */ spin_unlock_irqrestore(&lp->spinlock, flags); @@ -2509,93 +2466,6 @@ return ret; } -#ifdef WIRELESS_SPY -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set spy list - */ -static int wavelan_set_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - int ret = 0; - - /* Disable spy while we copy the addresses. - * As we don't disable interrupts, we need to do this */ - lp->spy_number = 0; - - /* Are there are addresses to copy? */ - if (wrqu->data.length > 0) { - /* Copy addresses to the lp structure. */ - for (i = 0; i < wrqu->data.length; i++) { - memcpy(lp->spy_address[i], address[i].sa_data, - WAVELAN_ADDR_SIZE); - } - - /* Reset structure. */ - memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG - "SetSpy: set of new addresses is: \n"); - for (i = 0; i < wrqu->data.length; i++) - printk(KERN_DEBUG - "%02X:%02X:%02X:%02X:%02X:%02X \n", - lp->spy_address[i][0], - lp->spy_address[i][1], - lp->spy_address[i][2], - lp->spy_address[i][3], - lp->spy_address[i][4], - lp->spy_address[i][5]); -#endif /* DEBUG_IOCTL_INFO */ - } - - /* Now we can set the number of addresses */ - lp->spy_number = wrqu->data.length; - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get spy list - */ -static int wavelan_get_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - - /* Set the number of addresses */ - wrqu->data.length = lp->spy_number; - - /* Copy addresses from the lp structure. */ - for (i = 0; i < lp->spy_number; i++) { - memcpy(address[i].sa_data, - lp->spy_address[i], - WAVELAN_ADDR_SIZE); - address[i].sa_family = AF_UNIX; - } - /* Copy stats to the user buffer (just after). */ - if(lp->spy_number > 0) - memcpy(extra + (sizeof(struct sockaddr) * lp->spy_number), - lp->spy_stat, sizeof(iw_qual) * lp->spy_number); - - /* Reset updated flags. */ - for (i = 0; i < lp->spy_number; i++) - lp->spy_stat[i].updated = 0x0; - - return(0); -} -#endif /* WIRELESS_SPY */ - /*------------------------------------------------------------------*/ /* * Wireless Private Handler : set quality threshold @@ -2781,8 +2651,6 @@ { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, }; -#if WIRELESS_EXT > 12 - static const iw_handler wavelan_handler[] = { NULL, /* SIOCSIWNAME */ @@ -2806,15 +2674,10 @@ NULL, /* SIOCGIWPRIV */ NULL, /* SIOCSIWSTATS */ NULL, /* SIOCGIWSTATS */ -#ifdef WIRELESS_SPY - wavelan_set_spy, /* SIOCSIWSPY */ - wavelan_get_spy, /* SIOCGIWSPY */ -#else /* WIRELESS_SPY */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ -#endif /* WIRELESS_SPY */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ #ifdef WAVELAN_ROAMING_EXT wavelan_set_wap, /* SIOCSIWAP */ wavelan_get_wap, /* SIOCGIWAP */ @@ -2834,7 +2697,6 @@ NULL, /* SIOCSIWESSID */ NULL, /* SIOCGIWESSID */ #endif /* WAVELAN_ROAMING_EXT */ -#if WIRELESS_EXT > 8 NULL, /* SIOCSIWNICKN */ NULL, /* SIOCGIWNICKN */ NULL, /* -- hole -- */ @@ -2851,7 +2713,6 @@ NULL, /* SIOCGIWRETRY */ wavelan_set_encode, /* SIOCSIWENCODE */ wavelan_get_encode, /* SIOCGIWENCODE */ -#endif /* WIRELESS_EXT > 8 */ }; static const iw_handler wavelan_private_handler[] = @@ -2879,8 +2740,9 @@ .standard = (iw_handler *) wavelan_handler, .private = (iw_handler *) wavelan_private_handler, .private_args = (struct iw_priv_args *) wavelan_private_args, + .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - + (void *) NULL), }; -#endif /* WIRELESS_EXT > 12 */ /*------------------------------------------------------------------*/ /* @@ -2892,9 +2754,6 @@ struct ifreq * rq, /* Data passed */ int cmd) /* Ioctl number */ { -#if WIRELESS_EXT <= 12 - struct iwreq * wrq = (struct iwreq *) rq; -#endif int ret = 0; #ifdef DEBUG_IOCTL_TRACE @@ -2908,284 +2767,6 @@ ret = wl_netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); break; -#if WIRELESS_EXT <= 12 - /* --------------- WIRELESS EXTENSIONS --------------- */ - /* Now done as iw_handler - Jean II */ - case SIOCGIWNAME: - wavelan_get_name(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCSIWNWID: - ret = wavelan_set_nwid(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWNWID: - ret = wavelan_get_nwid(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCSIWFREQ: - ret = wavelan_set_freq(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWFREQ: - ret = wavelan_get_freq(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCSIWSENS: - ret = wavelan_set_sens(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWSENS: - ret = wavelan_get_sens(dev, NULL, &(wrq->u), NULL); - break; - -#if WIRELESS_EXT > 8 - case SIOCSIWENCODE: - { - char keybuf[8]; - if (wrq->u.encoding.pointer) { - /* We actually have a key to set */ - if (wrq->u.encoding.length != 8) { - ret = -EINVAL; - break; - } - if (copy_from_user(keybuf, - wrq->u.encoding.pointer, - wrq->u.encoding.length)) { - ret = -EFAULT; - break; - } - } else if (wrq->u.encoding.length != 0) { - ret = -EINVAL; - break; - } - ret = wavelan_set_encode(dev, NULL, &(wrq->u), keybuf); - } - break; - - case SIOCGIWENCODE: - if (! capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - { - char keybuf[8]; - ret = wavelan_get_encode(dev, NULL, - &(wrq->u), - keybuf); - if (wrq->u.encoding.pointer) { - if (copy_to_user(wrq->u.encoding.pointer, - keybuf, - wrq->u.encoding.length)) - ret = -EFAULT; - } - } - break; -#endif /* WIRELESS_EXT > 8 */ - -#ifdef WAVELAN_ROAMING_EXT -#if WIRELESS_EXT > 5 - case SIOCSIWESSID: - { - char essidbuf[IW_ESSID_MAX_SIZE+1]; - if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - break; - } - if (copy_from_user(essidbuf, wrq->u.essid.pointer, - wrq->u.essid.length)) { - ret = -EFAULT; - break; - } - ret = wavelan_set_essid(dev, NULL, - &(wrq->u), - essidbuf); - } - break; - - case SIOCGIWESSID: - { - char essidbuf[IW_ESSID_MAX_SIZE+1]; - ret = wavelan_get_essid(dev, NULL, - &(wrq->u), - essidbuf); - if (wrq->u.essid.pointer) - if ( copy_to_user(wrq->u.essid.pointer, - essidbuf, - wrq->u.essid.length) ) - ret = -EFAULT; - } - break; - - case SIOCSIWAP: - ret = wavelan_set_wap(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWAP: - ret = wavelan_get_wap(dev, NULL, &(wrq->u), NULL); - break; -#endif /* WIRELESS_EXT > 5 */ -#endif /* WAVELAN_ROAMING_EXT */ - -#if WIRELESS_EXT > 8 -#ifdef WAVELAN_ROAMING - case SIOCSIWMODE: - ret = wavelan_set_mode(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWMODE: - ret = wavelan_get_mode(dev, NULL, &(wrq->u), NULL); - break; -#endif /* WAVELAN_ROAMING */ -#endif /* WIRELESS_EXT > 8 */ - - case SIOCGIWRANGE: - { - struct iw_range range; - ret = wavelan_get_range(dev, NULL, - &(wrq->u), - (char *) &range); - if (copy_to_user(wrq->u.data.pointer, &range, - sizeof(struct iw_range))) - ret = -EFAULT; - } - break; - - case SIOCGIWPRIV: - /* Basic checking... */ - if(wrq->u.data.pointer != (caddr_t) 0) - { - /* Set the number of ioctl available */ - wrq->u.data.length = sizeof(wavelan_private_args) / sizeof(wavelan_private_args[0]); - - /* Copy structure to the user buffer */ - if(copy_to_user(wrq->u.data.pointer, (u_char *) wavelan_private_args, - sizeof(wavelan_private_args))) - ret = -EFAULT; - } - break; - -#ifdef WIRELESS_SPY - case SIOCSIWSPY: - { - struct sockaddr address[IW_MAX_SPY]; - /* Check the number of addresses */ - if (wrq->u.data.length > IW_MAX_SPY) { - ret = -E2BIG; - break; - } - /* Get the data in the driver */ - if (wrq->u.data.pointer) { - if (copy_from_user((char *) address, - wrq->u.data.pointer, - sizeof(struct sockaddr) * - wrq->u.data.length)) { - ret = -EFAULT; - break; - } - } else if (wrq->u.data.length != 0) { - ret = -EINVAL; - break; - } - ret = wavelan_set_spy(dev, NULL, &(wrq->u), - (char *) address); - } - break; - - case SIOCGIWSPY: - { - char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) + - sizeof(struct iw_quality))]; - ret = wavelan_get_spy(dev, NULL, &(wrq->u), - buffer); - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, - buffer, - (wrq->u.data.length * - (sizeof(struct sockaddr) + - sizeof(struct iw_quality))) - )) - ret = -EFAULT; - } - } - break; -#endif /* WIRELESS_SPY */ - - /* ------------------ PRIVATE IOCTL ------------------ */ - - case SIOCSIPQTHR: - if(!capable(CAP_NET_ADMIN)) - { - ret = -EPERM; - break; - } - ret = wavelan_set_qthr(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIPQTHR: - ret = wavelan_get_qthr(dev, NULL, &(wrq->u), NULL); - break; - -#ifdef WAVELAN_ROAMING - case SIOCSIPROAM: - /* Note : should check if user == root */ - ret = wavelan_set_roam(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIPROAM: - ret = wavelan_get_roam(dev, NULL, &(wrq->u), NULL); - break; -#endif /* WAVELAN_ROAMING */ - -#ifdef HISTOGRAM - case SIOCSIPHISTO: - /* Verif if the user is root */ - if(!capable(CAP_NET_ADMIN)) - { - ret = -EPERM; - } - { - char buffer[16]; - /* Check the number of intervals */ - if(wrq->u.data.length > 16) - { - ret = -E2BIG; - break; - } - /* Get the data in the driver */ - if (wrq->u.data.pointer) { - if (copy_from_user(buffer, - wrq->u.data.pointer, - sizeof(struct sockaddr) * - wrq->u.data.length)) { - ret = -EFAULT; - break; - } - } else if (wrq->u.data.length != 0) { - ret = -EINVAL; - break; - } - ret = wavelan_set_histo(dev, NULL, &(wrq->u), - buffer); - } - break; - - case SIOCGIPHISTO: - { - long buffer[16]; - ret = wavelan_get_histo(dev, NULL, &(wrq->u), - (char *) buffer); - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, - buffer, - (wrq->u.data.length * sizeof(long)))) - ret = -EFAULT; - } - } - break; -#endif /* HISTOGRAM */ -#endif /* WIRELESS_EXT <= 12 */ - /* ------------------- OTHER IOCTL ------------------- */ default: @@ -3368,9 +2949,9 @@ /* Statistics gathering & stuff associated. * It seem a bit messy with all the define, but it's really simple... */ if( -#ifdef WIRELESS_SPY - (lp->spy_number > 0) || -#endif /* WIRELESS_SPY */ +#ifdef IW_WIRELESS_SPY + (lp->spy_data.spy_number > 0) || +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM (lp->his_number > 0) || #endif /* HISTOGRAM */ @@ -3581,10 +3162,6 @@ spin_lock_irqsave(&lp->spinlock, flags); - /* Check if we need some padding */ - if(clen < ETH_ZLEN) - clen = ETH_ZLEN; - /* Write the length of data buffer followed by the buffer */ outb(xmtdata_base & 0xff, PIORL(base)); outb(((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); @@ -3664,6 +3241,17 @@ printk(KERN_INFO "skb has next\n"); #endif + /* Check if we need some padding */ + /* Note : on wireless the propagation time is in the order of 1us, + * and we don't have the Ethernet specific requirement of beeing + * able to detect collisions, therefore in theory we don't really + * need to pad. Jean II */ + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } + wv_packet_write(dev, skb->data, skb->len); dev_kfree_skb(skb); @@ -4644,7 +4232,7 @@ * ready to transmit another packet. * 3. A command has completed execution. */ -static void +static irqreturn_t wavelan_interrupt(int irq, void * dev_id, struct pt_regs * regs) @@ -4661,7 +4249,7 @@ printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n", irq); #endif - return; + return IRQ_NONE; } #ifdef DEBUG_INTERRUPT_TRACE @@ -4883,6 +4471,24 @@ #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); #endif + + /* We always return IRQ_HANDLED, because we will receive empty + * interrupts under normal operations. Anyway, it doesn't matter + * as we are dealing with an ISA interrupt that can't be shared. + * + * Explanation : under heavy receive, the following happens : + * ->wavelan_interrupt() + * (status0 & SR0_INTERRUPT) != 0 + * ->wv_packet_rcv() + * (status0 & SR0_INTERRUPT) != 0 + * ->wv_packet_rcv() + * (status0 & SR0_INTERRUPT) == 0 // i.e. no more event + * <-wavelan_interrupt() + * ->wavelan_interrupt() + * (status0 & SR0_INTERRUPT) == 0 // i.e. empty interrupt + * <-wavelan_interrupt() + * Jean II */ + return IRQ_HANDLED; } /* wv_interrupt */ /*------------------------------------------------------------------*/ @@ -5189,9 +4795,7 @@ dev->watchdog_timeo = WATCHDOG_JIFFIES; #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ -#if WIRELESS_EXT > 12 dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; -#endif /* WIRELESS_EXT > 12 */ dev->do_ioctl = wavelan_ioctl; /* old wireless extensions */ dev->get_wireless_stats = wavelan_get_wireless_stats; #endif diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.p.h linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.p.h --- linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.p.h 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.p.h 2003-05-12 04:43:29.000000000 -0700 @@ -443,9 +443,7 @@ #ifdef CONFIG_NET_RADIO #include /* Wireless extensions */ -#if WIRELESS_EXT > 12 -#include -#endif /* WIRELESS_EXT > 12 */ +#include /* New driver API */ #endif /* Pcmcia headers that we need */ @@ -527,13 +525,6 @@ /* ------------------------ PRIVATE IOCTL ------------------------ */ -/* Wireless Extension Backward compatibility - Jean II - * If the new wireless device private ioctl range is not defined, - * default to standard device private ioctl range */ -#ifndef SIOCIWFIRSTPRIV -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif /* SIOCIWFIRSTPRIV */ - #define SIOCSIPQTHR SIOCIWFIRSTPRIV /* Set quality threshold */ #define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1 /* Get quality threshold */ #define SIOCSIPROAM SIOCIWFIRSTPRIV + 2 /* Set roaming state */ @@ -605,16 +596,6 @@ typedef struct net_local net_local; typedef struct timer_list timer_list; -#if WIRELESS_EXT <= 12 -/* Wireless extensions backward compatibility */ -/* Part of iw_handler prototype we need */ -struct iw_request_info -{ - __u16 cmd; /* Wireless Extension command */ - __u16 flags; /* More to come ;-) */ -}; -#endif /* WIRELESS_EXT <= 12 */ - /* Basic types */ typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ @@ -647,13 +628,10 @@ #ifdef WIRELESS_EXT iw_stats wstats; /* Wireless specific stats */ + + struct iw_spy_data spy_data; #endif -#ifdef WIRELESS_SPY - int spy_number; /* Number of addresses to spy */ - mac_addr spy_address[IW_MAX_SPY]; /* The addresses to spy */ - iw_qual spy_stat[IW_MAX_SPY]; /* Statistics gathered */ -#endif /* WIRELESS_SPY */ #ifdef HISTOGRAM int his_number; /* Number of intervals */ u_char his_range[16]; /* Boundaries of interval ]n-1; n] */ @@ -686,11 +664,6 @@ void wv_roam_cleanup(struct net_device *dev); #endif /* WAVELAN_ROAMING */ -/* ----------------------- MISC SUBROUTINES ------------------------ */ -static void - cs_error(client_handle_t, /* Report error to cardmgr */ - int, - int); /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ static inline u_char /* data */ hasr_read(u_long); /* Read the host interface : base address */ @@ -791,7 +764,7 @@ wv_pcmcia_release(u_long), /* Remove a device */ wv_flush_stale_links(void); /* "detach" all possible devices */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ -static void +static irqreturn_t wavelan_interrupt(int, /* Interrupt handler */ void *, struct pt_regs *); diff -urN linux-2.5.69-bk6/drivers/usb/Makefile linux-2.5.69-bk7/drivers/usb/Makefile --- linux-2.5.69-bk6/drivers/usb/Makefile 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/drivers/usb/Makefile 2003-05-12 04:43:30.000000000 -0700 @@ -59,6 +59,3 @@ obj-$(CONFIG_USB_TIGL) += misc/ obj-$(CONFIG_USB_USS720) += misc/ -obj-$(CONFIG_USB_NET2280) += gadget/ -obj-$(CONFIG_USB_ZERO) += gadget/ -obj-$(CONFIG_USB_ETH) += gadget/ diff -urN linux-2.5.69-bk6/drivers/usb/gadget/Kconfig linux-2.5.69-bk7/drivers/usb/gadget/Kconfig --- linux-2.5.69-bk6/drivers/usb/gadget/Kconfig 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/drivers/usb/gadget/Kconfig 2003-05-12 04:43:30.000000000 -0700 @@ -10,7 +10,7 @@ tristate "Support for USB Gadgets" depends on EXPERIMENTAL help - USB is a master/slave protocol, organized with with one master + USB is a master/slave protocol, organized with one master host (such as a PC) controlling up to 127 peripheral devices. The USB hardware is asymmetric, which makes it easier to set up: you can't connect two "to-the-host" connectors to each other. diff -urN linux-2.5.69-bk6/drivers/usb/gadget/ether.c linux-2.5.69-bk7/drivers/usb/gadget/ether.c --- linux-2.5.69-bk6/drivers/usb/gadget/ether.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/drivers/usb/gadget/ether.c 2003-05-12 04:43:30.000000000 -0700 @@ -168,7 +168,7 @@ */ #ifdef CONFIG_USB_ETH_NET2280 #define CHIP "net2280" -#define DRIVER_VERSION_NUM cpu_to_le16(0x0101) +#define DRIVER_VERSION_NUM 0x0101 #define EP0_MAXPACKET 64 static const char EP_OUT_NAME [] = "ep-a"; #define EP_OUT_NUM 2 @@ -201,7 +201,7 @@ */ #ifdef CONFIG_USB_ETH_PXA250 #define CHIP "pxa250" -#define DRIVER_VERSION_NUM cpu_to_le16(0x0103) +#define DRIVER_VERSION_NUM 0x0103 #define EP0_MAXPACKET 16 static const char EP_OUT_NAME [] = "ep12out-bulk"; #define EP_OUT_NUM 12 @@ -225,7 +225,7 @@ */ #ifdef CONFIG_USB_ETH_SA1100 #define CHIP "sa1100" -#define DRIVER_VERSION_NUM cpu_to_le16(0x0105) +#define DRIVER_VERSION_NUM 0x0105 #define EP0_MAXPACKET 8 static const char EP_OUT_NAME [] = "ep1out-bulk"; #define EP_OUT_NUM 1 @@ -329,15 +329,15 @@ .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = cpu_to_le16 (0x0200), + .bcdUSB = __constant_cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = EP0_MAXPACKET, - .idVendor = cpu_to_le16 (DRIVER_VENDOR_NUM), - .idProduct = cpu_to_le16 (DRIVER_PRODUCT_NUM), - .bcdDevice = cpu_to_le16 (DRIVER_VERSION_NUM), + .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), + .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), + .bcdDevice = __constant_cpu_to_le16 (DRIVER_VERSION_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .bNumConfigurations = 1, @@ -389,7 +389,7 @@ .bDescriptorType = 0x24, .bDescriptorSubType = 0, - .bcdCDC = cpu_to_le16 (0x0110), + .bcdCDC = __constant_cpu_to_le16 (0x0110), }; /* "Union Functional Descriptor" from CDC spec 5.2.3.X */ @@ -432,9 +432,9 @@ /* this descriptor actually adds value, surprise! */ .iMACAddress = STRING_ETHADDR, - .bmEthernetStatistics = cpu_to_le32 (0), /* no statistics */ - .wMaxSegmentSize = cpu_to_le16 (MAX_PACKET + ETH_HLEN), - .wNumberMCFilters = cpu_to_le16 (0), + .bmEthernetStatistics = __constant_cpu_to_le32 (0), /* no statistics */ + .wMaxSegmentSize = __constant_cpu_to_le16 (MAX_PACKET + ETH_HLEN), + .wNumberMCFilters = __constant_cpu_to_le16 (0), .bNumberPowerFilters = 0, }; @@ -457,7 +457,7 @@ .bEndpointAddress = EP_STATUS_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16 (STATUS_BYTECOUNT), + .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; #endif @@ -501,7 +501,7 @@ .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (64), + .wMaxPacketSize = __constant_cpu_to_le16 (64), }; static const struct usb_endpoint_descriptor @@ -511,7 +511,7 @@ .bEndpointAddress = EP_OUT_NUM, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (64), + .wMaxPacketSize = __constant_cpu_to_le16 (64), }; #ifdef HIGHSPEED @@ -529,7 +529,7 @@ .bEndpointAddress = EP_STATUS_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16 (STATUS_BYTECOUNT), + .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 3, }; #endif @@ -541,7 +541,7 @@ .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (512), + .wMaxPacketSize = __constant_cpu_to_le16 (512), .bInterval = 1, }; @@ -552,7 +552,7 @@ .bEndpointAddress = EP_OUT_NUM, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (512), + .wMaxPacketSize = __constant_cpu_to_le16 (512), .bInterval = 1, }; @@ -561,7 +561,7 @@ .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = cpu_to_le16 (0x0200), + .bcdUSB = __constant_cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, /* assumes ep0 uses the same value for both speeds ... */ @@ -627,7 +627,7 @@ memcpy (buf, ð_config, USB_DT_CONFIG_SIZE); buf [1] = type; ((struct usb_config_descriptor *) buf)->wTotalLength - = cpu_to_le16 (config_len); + = __constant_cpu_to_le16 (config_len); buf += USB_DT_CONFIG_SIZE; #ifdef HIGHSPEED hs = (speed == USB_SPEED_HIGH); @@ -858,9 +858,9 @@ && value == 0) { event->bmRequestType = 0xA1; event->bNotificationType = CDC_NOTIFY_SPEED_CHANGE; - event->wValue = cpu_to_le16 (0); - event->wIndex = cpu_to_le16 (1); - event->wLength = cpu_to_le16 (8); + event->wValue = __constant_cpu_to_le16 (0); + event->wIndex = __constant_cpu_to_le16 (1); + event->wLength = __constant_cpu_to_le16 (8); /* SPEED_CHANGE data is up/down speeds in bits/sec */ event->data [0] = event->data [1] = @@ -920,8 +920,8 @@ event = req->buf; event->bmRequestType = 0xA1; event->bNotificationType = CDC_NOTIFY_NETWORK_CONNECTION; - event->wValue = cpu_to_le16 (1); /* connected */ - event->wIndex = cpu_to_le16 (1); + event->wValue = __constant_cpu_to_le16 (1); /* connected */ + event->wIndex = __constant_cpu_to_le16 (1); event->wLength = 0; req->length = 8; diff -urN linux-2.5.69-bk6/drivers/usb/gadget/net2280.c linux-2.5.69-bk7/drivers/usb/gadget/net2280.c --- linux-2.5.69-bk6/drivers/usb/gadget/net2280.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/drivers/usb/gadget/net2280.c 2003-05-12 04:43:30.000000000 -0700 @@ -114,8 +114,8 @@ #include "net2280.h" -#define valid_bit cpu_to_le32 (1 << VALID_BIT) -#define dma_done_ie cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) +#define valid_bit __constant_cpu_to_le32 (1 << VALID_BIT) +#define dma_done_ie __constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) /*-------------------------------------------------------------------------*/ @@ -371,7 +371,7 @@ return 0; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); req->td = td; } return &req->req; @@ -756,7 +756,7 @@ | (ep->is_in << DMA_DIRECTION) | 0, &dma->dmacount); #else - req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN); + req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); #endif writel (req->td_dma, &dma->dmadesc); @@ -2157,9 +2157,9 @@ if (readl (&e->regs->ep_rsp) & (1 << SET_ENDPOINT_HALT)) - status = cpu_to_le16 (1); + status = __constant_cpu_to_le16 (1); else - status = cpu_to_le16 (0); + status = __constant_cpu_to_le16 (0); /* don't bother with a request object! */ writel (0, &dev->epregs [0].ep_irqenb); @@ -2574,7 +2574,7 @@ goto done; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); dev->ep [i].dummy = td; } diff -urN linux-2.5.69-bk6/drivers/usb/gadget/zero.c linux-2.5.69-bk7/drivers/usb/gadget/zero.c --- linux-2.5.69-bk6/drivers/usb/gadget/zero.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/drivers/usb/gadget/zero.c 2003-05-12 04:43:30.000000000 -0700 @@ -137,7 +137,7 @@ */ #ifdef CONFIG_USB_ZERO_NET2280 #define CHIP "net2280" -#define DRIVER_VERSION_NUM cpu_to_le16(0x0101) +#define DRIVER_VERSION_NUM 0x0101 #define EP0_MAXPACKET 64 static const char EP_OUT_NAME [] = "ep-a"; #define EP_OUT_NUM 2 @@ -172,7 +172,7 @@ */ #ifdef CONFIG_USB_ZERO_PXA250 #define CHIP "pxa250" -#define DRIVER_VERSION_NUM cpu_to_le16(0x0103) +#define DRIVER_VERSION_NUM 0x0103 #define EP0_MAXPACKET 16 static const char EP_OUT_NAME [] = "ep12out-bulk"; #define EP_OUT_NUM 12 @@ -199,7 +199,7 @@ */ #ifdef CONFIG_USB_ZERO_SA1100 #define CHIP "sa1100" -#define DRIVER_VERSION_NUM cpu_to_le16(0x0105) +#define DRIVER_VERSION_NUM 0x0105 #define EP0_MAXPACKET 8 static const char EP_OUT_NAME [] = "ep1out-bulk"; #define EP_OUT_NUM 1 @@ -340,13 +340,13 @@ .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = cpu_to_le16 (0x0200), + .bcdUSB = __constant_cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, .bMaxPacketSize0 = EP0_MAXPACKET, - .idVendor = cpu_to_le16 (DRIVER_VENDOR_NUM), - .idProduct = cpu_to_le16 (DRIVER_PRODUCT_NUM), - .bcdDevice = cpu_to_le16 (DRIVER_VERSION_NUM), + .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), + .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), + .bcdDevice = __constant_cpu_to_le16 (DRIVER_VERSION_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .iSerialNumber = STRING_SERIAL, @@ -410,7 +410,7 @@ .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (64), + .wMaxPacketSize = __constant_cpu_to_le16 (64), }; static const struct usb_endpoint_descriptor @@ -420,7 +420,7 @@ .bEndpointAddress = EP_OUT_NUM, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (64), + .wMaxPacketSize = __constant_cpu_to_le16 (64), }; #ifdef HIGHSPEED @@ -441,7 +441,7 @@ .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (512), + .wMaxPacketSize = __constant_cpu_to_le16 (512), }; static const struct usb_endpoint_descriptor @@ -451,7 +451,7 @@ .bEndpointAddress = EP_OUT_NUM, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16 (512), + .wMaxPacketSize = __constant_cpu_to_le16 (512), }; static const struct usb_qualifier_descriptor @@ -459,7 +459,7 @@ .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = cpu_to_le16 (0x0200), + .bcdUSB = __constant_cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, /* assumes ep0 uses the same value for both speeds ... */ @@ -538,7 +538,7 @@ memcpy (buf, &loopback_config, USB_DT_CONFIG_SIZE); buf [1] = type; ((struct usb_config_descriptor *) buf)->wTotalLength - = cpu_to_le16 (config_len); + = __constant_cpu_to_le16 (config_len); buf += USB_DT_CONFIG_SIZE; /* one interface */ diff -urN linux-2.5.69-bk6/fs/fs-writeback.c linux-2.5.69-bk7/fs/fs-writeback.c --- linux-2.5.69-bk6/fs/fs-writeback.c 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk7/fs/fs-writeback.c 2003-05-12 04:43:30.000000000 -0700 @@ -367,7 +367,8 @@ }; get_page_state(&ps); - wbc.nr_to_write = ps.nr_dirty + ps.nr_dirty / 4; + wbc.nr_to_write = ps.nr_dirty + ps.nr_unstable + + (ps.nr_dirty + ps.nr_unstable) / 4; spin_lock(&inode_lock); sync_sb_inodes(sb, &wbc); spin_unlock(&inode_lock); diff -urN linux-2.5.69-bk6/fs/lockd/host.c linux-2.5.69-bk7/fs/lockd/host.c --- linux-2.5.69-bk6/fs/lockd/host.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/fs/lockd/host.c 2003-05-12 04:43:30.000000000 -0700 @@ -187,15 +187,7 @@ host->h_nextrebind - jiffies); } } else { - uid_t saved_fsuid = current->fsuid; - kernel_cap_t saved_cap = current->cap_effective; - - /* Create RPC socket as root user so we get a priv port */ - current->fsuid = 0; - cap_raise (current->cap_effective, CAP_NET_BIND_SERVICE); xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); - current->fsuid = saved_fsuid; - current->cap_effective = saved_cap; if (xprt == NULL) goto forgetit; @@ -209,6 +201,7 @@ } clnt->cl_autobind = 1; /* turn on pmap queries */ xprt->nocong = 1; /* No congestion control for NLM */ + xprt->resvport = 1; /* NLM requires a reserved port */ host->h_rpcclnt = clnt; } @@ -276,7 +269,7 @@ dprintk("lockd: nuking all hosts...\n"); for (i = 0; i < NLM_HOST_NRHASH; i++) { for (host = nlm_hosts[i]; host; host = host->h_next) - host->h_expires = 0; + host->h_expires = jiffies - 1; } /* Then, perform a garbage collection pass */ @@ -323,6 +316,9 @@ while ((host = *q) != NULL) { if (host->h_count || host->h_inuse || time_before(jiffies, host->h_expires)) { + dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", + host->h_name, host->h_count, + host->h_inuse, host->h_expires); q = &host->h_next; continue; } diff -urN linux-2.5.69-bk6/fs/lockd/mon.c linux-2.5.69-bk7/fs/lockd/mon.c --- linux-2.5.69-bk6/fs/lockd/mon.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/fs/lockd/mon.c 2003-05-12 04:43:30.000000000 -0700 @@ -123,6 +123,7 @@ clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; + xprt->resvport = 1; /* NSM requires a reserved port */ out: return clnt; diff -urN linux-2.5.69-bk6/fs/nfs/dir.c linux-2.5.69-bk7/fs/nfs/dir.c --- linux-2.5.69-bk6/fs/nfs/dir.c 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/fs/nfs/dir.c 2003-05-12 04:43:30.000000000 -0700 @@ -83,7 +83,7 @@ lock_kernel(); /* Do cto revalidation */ - if (server->flags & NFS_MOUNT_NOCTO) + if (!(server->flags & NFS_MOUNT_NOCTO)) res = __nfs_revalidate_inode(server, inode); /* Call generic open code in order to cache credentials */ if (!res) diff -urN linux-2.5.69-bk6/fs/nfs/file.c linux-2.5.69-bk7/fs/nfs/file.c --- linux-2.5.69-bk6/fs/nfs/file.c 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk7/fs/nfs/file.c 2003-05-12 04:43:30.000000000 -0700 @@ -83,7 +83,7 @@ if ((open = server->rpc_ops->file_open) != NULL) res = open(inode, filp); /* Do cto revalidation */ - else if (server->flags & NFS_MOUNT_NOCTO) + else if (!(server->flags & NFS_MOUNT_NOCTO)) res = __nfs_revalidate_inode(server, inode); /* Call generic open code in order to cache credentials */ if (!res) diff -urN linux-2.5.69-bk6/fs/nfs/write.c linux-2.5.69-bk7/fs/nfs/write.c --- linux-2.5.69-bk6/fs/nfs/write.c 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/fs/nfs/write.c 2003-05-12 04:43:30.000000000 -0700 @@ -280,8 +280,6 @@ err = nfs_wb_all(inode); } else nfs_commit_file(inode, NULL, 0, 0, 0); - /* Avoid races. Tell upstream we've done all we were told to do */ - wbc->nr_to_write = 0; out: return err; } @@ -490,7 +488,6 @@ int res; res = nfs_scan_list(&nfsi->commit, dst, file, idx_start, npages); nfsi->ncommit -= res; - sub_page_state(nr_unstable,res); if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); return res; @@ -1009,6 +1006,7 @@ { struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata; struct nfs_page *req; + int res = 0; dprintk("NFS: %4d nfs_commit_done (status %d)\n", task->tk_pid, task->tk_status); @@ -1043,7 +1041,9 @@ nfs_mark_request_dirty(req); next: nfs_unlock_request(req); + res++; } + sub_page_state(nr_unstable,res); } #endif diff -urN linux-2.5.69-bk6/include/asm-i386/suspend.h linux-2.5.69-bk7/include/asm-i386/suspend.h --- linux-2.5.69-bk6/include/asm-i386/suspend.h 2003-05-04 16:53:40.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-i386/suspend.h 2003-05-12 04:43:30.000000000 -0700 @@ -30,18 +30,14 @@ unsigned long return_address; } __attribute__((packed)); -/* We'll access these from assembly, so we'd better have them outside struct */ -extern unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx; -extern unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi; -extern unsigned long saved_context_eflags; - - #define loaddebug(thread,register) \ __asm__("movl %0,%%db" #register \ : /* no output */ \ :"r" ((thread)->debugreg[register])) -extern void fix_processor_context(void); +extern void save_processor_state(void); +extern void restore_processor_state(void); + extern void do_magic(int resume); #ifdef CONFIG_ACPI_SLEEP diff -urN linux-2.5.69-bk6/include/asm-i386/system.h linux-2.5.69-bk7/include/asm-i386/system.h --- linux-2.5.69-bk6/include/asm-i386/system.h 2003-05-04 16:52:48.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-i386/system.h 2003-05-12 04:43:30.000000000 -0700 @@ -474,5 +474,6 @@ #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002 #define BROKEN_PNP_BIOS 0x0004 +#define BROKEN_CPUFREQ 0x0008 #endif diff -urN linux-2.5.69-bk6/include/asm-ia64/acpi-ext.h linux-2.5.69-bk7/include/asm-ia64/acpi-ext.h --- linux-2.5.69-bk6/include/asm-ia64/acpi-ext.h 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/acpi-ext.h 2003-05-12 04:43:30.000000000 -0700 @@ -3,30 +3,15 @@ * * Copyright (C) 2003 Hewlett-Packard * Copyright (C) Alex Williamson + * Copyright (C) Bjorn Helgaas * - * Vendor specific extensions to ACPI. The HP-specific extensiosn are also used by NEC. + * Vendor specific extensions to ACPI. */ #ifndef _ASM_IA64_ACPI_EXT_H #define _ASM_IA64_ACPI_EXT_H #include -#define HP_CCSR_LENGTH 0x21 -#define HP_CCSR_TYPE 0x2 -#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ - 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) - -struct acpi_hp_vendor_long { - u8 guid_id; - u8 guid[16]; - u8 csr_base[8]; - u8 csr_length[8]; -}; - extern acpi_status hp_acpi_csr_space (acpi_handle, u64 *base, u64 *length); -extern acpi_status acpi_get_crs (acpi_handle, struct acpi_buffer *); -extern struct acpi_resource *acpi_get_crs_next (struct acpi_buffer *, int *); -extern union acpi_resource_data *acpi_get_crs_type (struct acpi_buffer *, int *, int); -extern void acpi_dispose_crs (struct acpi_buffer *); #endif /* _ASM_IA64_ACPI_EXT_H */ diff -urN linux-2.5.69-bk6/include/asm-ia64/atomic.h linux-2.5.69-bk7/include/asm-ia64/atomic.h --- linux-2.5.69-bk6/include/asm-ia64/atomic.h 2003-05-04 16:53:06.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/atomic.h 2003-05-12 04:43:30.000000000 -0700 @@ -56,11 +56,16 @@ } #define atomic_add_return(i,v) \ - ((__builtin_constant_p(i) && \ - ( (i == 1) || (i == 4) || (i == 8) || (i == 16) \ - || (i == -1) || (i == -4) || (i == -8) || (i == -16))) \ - ? ia64_fetch_and_add(i, &(v)->counter) \ - : ia64_atomic_add(i, v)) +({ \ + int __ia64_aar_i = (i); \ + (__builtin_constant_p(i) \ + && ( (__ia64_aar_i == 1) || (__ia64_aar_i == 4) \ + || (__ia64_aar_i == 8) || (__ia64_aar_i == 16) \ + || (__ia64_aar_i == -1) || (__ia64_aar_i == -4) \ + || (__ia64_aar_i == -8) || (__ia64_aar_i == -16))) \ + ? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \ + : ia64_atomic_add(__ia64_aar_i, v); \ +}) /* * Atomically add I to V and return TRUE if the resulting value is @@ -72,13 +77,17 @@ return atomic_add_return(i, v) < 0; } - #define atomic_sub_return(i,v) \ - ((__builtin_constant_p(i) && \ - ( (i == 1) || (i == 4) || (i == 8) || (i == 16) \ - || (i == -1) || (i == -4) || (i == -8) || (i == -16))) \ - ? ia64_fetch_and_add(-(i), &(v)->counter) \ - : ia64_atomic_sub(i, v)) +({ \ + int __ia64_asr_i = (i); \ + (__builtin_constant_p(i) \ + && ( (__ia64_asr_i == 1) || (__ia64_asr_i == 4) \ + || (__ia64_asr_i == 8) || (__ia64_asr_i == 16) \ + || (__ia64_asr_i == -1) || (__ia64_asr_i == -4) \ + || (__ia64_asr_i == -8) || (__ia64_asr_i == -16))) \ + ? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \ + : ia64_atomic_sub(__ia64_asr_i, v); \ +}) #define atomic_dec_return(v) atomic_sub_return(1, (v)) #define atomic_inc_return(v) atomic_add_return(1, (v)) diff -urN linux-2.5.69-bk6/include/asm-ia64/bitops.h linux-2.5.69-bk7/include/asm-ia64/bitops.h --- linux-2.5.69-bk6/include/asm-ia64/bitops.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/bitops.h 2003-05-12 04:43:30.000000000 -0700 @@ -450,15 +450,15 @@ #ifdef __KERNEL__ -#define __clear_bit(nr, addr) clear_bit(nr, addr) +#define __clear_bit(nr, addr) clear_bit(nr, addr) -#define ext2_set_bit test_and_set_bit -#define ext2_set_atomic(l,n,a) test_and_set_bit(n,a) -#define ext2_clear_bit test_and_clear_bit -#define ext2_clear_atomic(l,n,a) test_and_clear_bit(n,a) -#define ext2_test_bit test_bit -#define ext2_find_first_zero_bit find_first_zero_bit -#define ext2_find_next_zero_bit find_next_zero_bit +#define ext2_set_bit test_and_set_bit +#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a) +#define ext2_clear_bit test_and_clear_bit +#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a) +#define ext2_test_bit test_bit +#define ext2_find_first_zero_bit find_first_zero_bit +#define ext2_find_next_zero_bit find_next_zero_bit /* Bitmap functions for the minix filesystem. */ #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) diff -urN linux-2.5.69-bk6/include/asm-ia64/compat.h linux-2.5.69-bk7/include/asm-ia64/compat.h --- linux-2.5.69-bk6/include/asm-ia64/compat.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/compat.h 2003-05-12 04:43:30.000000000 -0700 @@ -102,6 +102,9 @@ int f_spare[6]; }; +#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff +#define COMPAT_RLIM_INFINITY 0xffffffff + typedef u32 compat_old_sigset_t; /* at least 32 bits */ #define _COMPAT_NSIG 64 diff -urN linux-2.5.69-bk6/include/asm-ia64/dma-mapping.h linux-2.5.69-bk7/include/asm-ia64/dma-mapping.h --- linux-2.5.69-bk6/include/asm-ia64/dma-mapping.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/dma-mapping.h 2003-05-12 04:43:30.000000000 -0700 @@ -1 +1,63 @@ -#include +#ifndef _ASM_IA64_DMA_MAPPING_H +#define _ASM_IA64_DMA_MAPPING_H + +/* + * Copyright (C) 2003 Hewlett-Packard Co + * David Mosberger-Tang + */ + +#define dma_alloc_coherent platform_dma_alloc_coherent +#define dma_alloc_noncoherent platform_dma_alloc_coherent /* coherent mem. is cheap */ +#define dma_free_coherent platform_dma_free_coherent +#define dma_free_noncoherent platform_dma_free_coherent +#define dma_map_single platform_dma_map_single +#define dma_map_sg platform_dma_map_sg +#define dma_unmap_single platform_dma_unmap_single +#define dma_unmap_sg platform_dma_unmap_sg +#define dma_sync_single platform_dma_sync_single +#define dma_sync_sg platform_dma_sync_sg + +#define dma_map_page(dev, pg, off, size, dir) \ + dma_map_single(dev, page_address(pg) + (off), (size), (dir)) +#define dma_unmap_page(dev, dma_addr, size, dir) \ + dma_unmap_single(dev, dma_addr, size, dir) + +/* + * Rest of this file is part of the "Advanced DMA API". Use at your own risk. + * See Documentation/DMA-API.txt for details. + */ + +#define dma_sync_single_range(dev, dma_handle, offset, size, dir) \ + dma_sync_single(dev, dma_handle, size, dir) + +#define dma_supported platform_dma_supported + +static inline int +dma_set_mask (struct device *dev, u64 mask) +{ + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + *dev->dma_mask = mask; + return 0; +} + +static inline int +dma_get_cache_alignment (void) +{ + extern int ia64_max_cacheline_size; + return ia64_max_cacheline_size; +} + +static inline void +dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir) +{ + /* + * IA-64 is cache-coherent, so this is mostly a no-op. However, we do need to + * ensure that dma_cache_sync() enforces order, hence the mb(). + */ + mb(); +} + +#define dma_is_consistent(dma_handle) (1) /* all we do is coherent memory... */ + +#endif /* _ASM_IA64_DMA_MAPPING_H */ diff -urN linux-2.5.69-bk6/include/asm-ia64/ia32.h linux-2.5.69-bk7/include/asm-ia64/ia32.h --- linux-2.5.69-bk6/include/asm-ia64/ia32.h 2003-05-04 16:53:56.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/ia32.h 2003-05-12 04:43:30.000000000 -0700 @@ -453,8 +453,6 @@ struct linux_binprm; extern void ia32_gdt_init (void); -extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs); extern void ia32_init_addr_space (struct pt_regs *regs); extern int ia32_setup_arg_pages (struct linux_binprm *bprm); extern int ia32_exception (struct pt_regs *regs, unsigned long isr); @@ -476,4 +474,8 @@ #endif /* !CONFIG_IA32_SUPPORT */ +/* Declare this uncondiontally, so we don't get warnings for unreachable code. */ +extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs); + #endif /* _ASM_IA64_IA32_H */ diff -urN linux-2.5.69-bk6/include/asm-ia64/intrinsics.h linux-2.5.69-bk7/include/asm-ia64/intrinsics.h --- linux-2.5.69-bk6/include/asm-ia64/intrinsics.h 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/intrinsics.h 2003-05-12 04:43:30.000000000 -0700 @@ -17,16 +17,16 @@ extern unsigned long __bad_size_for_ia64_fetch_and_add (void); extern unsigned long __bad_increment_for_ia64_fetch_and_add (void); -#define IA64_FETCHADD(tmp,v,n,sz) \ +#define IA64_FETCHADD(tmp,v,n,sz,sem) \ ({ \ switch (sz) { \ case 4: \ - __asm__ __volatile__ ("fetchadd4.rel %0=[%1],%2" \ + __asm__ __volatile__ ("fetchadd4."sem" %0=[%1],%2" \ : "=r"(tmp) : "r"(v), "i"(n) : "memory"); \ break; \ \ case 8: \ - __asm__ __volatile__ ("fetchadd8.rel %0=[%1],%2" \ + __asm__ __volatile__ ("fetchadd8."sem" %0=[%1],%2" \ : "=r"(tmp) : "r"(v), "i"(n) : "memory"); \ break; \ \ @@ -35,32 +35,34 @@ } \ }) -#define ia64_fetch_and_add(i,v) \ +#define ia64_fetchadd(i,v,sem) \ ({ \ __u64 _tmp; \ volatile __typeof__(*(v)) *_v = (v); \ /* Can't use a switch () here: gcc isn't always smart enough for that... */ \ if ((i) == -16) \ - IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)), sem); \ else if ((i) == -8) \ - IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)), sem); \ else if ((i) == -4) \ - IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)), sem); \ else if ((i) == -1) \ - IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)), sem); \ else if ((i) == 1) \ - IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)), sem); \ else if ((i) == 4) \ - IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)), sem); \ else if ((i) == 8) \ - IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)), sem); \ else if ((i) == 16) \ - IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v))); \ + IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)), sem); \ else \ _tmp = __bad_increment_for_ia64_fetch_and_add(); \ - (__typeof__(*(v))) (_tmp + (i)); /* return new value */ \ + (__typeof__(*(v))) (_tmp); /* return old value */ \ }) +#define ia64_fetch_and_add(i,v) (ia64_fetchadd(i, v, "rel") + (i)) /* return new value */ + /* * This function doesn't exist, so you'll get a linker error if * something tries to do an invalid xchg(). @@ -127,7 +129,7 @@ case 8: _o_ = (__u64) (long) (old); break; \ default: break; \ } \ - __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ + __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \ switch (size) { \ case 1: \ __asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv" \ diff -urN linux-2.5.69-bk6/include/asm-ia64/io.h linux-2.5.69-bk7/include/asm-ia64/io.h --- linux-2.5.69-bk6/include/asm-ia64/io.h 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/io.h 2003-05-12 04:43:30.000000000 -0700 @@ -13,7 +13,7 @@ * over and over again with slight variations and possibly making a * mistake somewhere. * - * Copyright (C) 1998-2002 Hewlett-Packard Co + * Copyright (C) 1998-2003 Hewlett-Packard Co * David Mosberger-Tang * Copyright (C) 1999 Asit Mallick * Copyright (C) 1999 Don Dugger @@ -32,6 +32,24 @@ */ #define IO_SPACE_LIMIT 0xffffffffffffffffUL +#define MAX_IO_SPACES 16 +#define IO_SPACE_BITS 24 +#define IO_SPACE_SIZE (1UL << IO_SPACE_BITS) + +#define IO_SPACE_NR(port) ((port) >> IO_SPACE_BITS) +#define IO_SPACE_BASE(space) ((space) << IO_SPACE_BITS) +#define IO_SPACE_PORT(port) ((port) & (IO_SPACE_SIZE - 1)) + +#define IO_SPACE_SPARSE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff)) + +struct io_space { + unsigned long mmio_base; /* base in MMIO space */ + int sparse; +}; + +extern struct io_space io_space[]; +extern unsigned int num_io_spaces; + # ifdef __KERNEL__ #include @@ -80,12 +98,33 @@ static inline void* __ia64_mk_io_addr (unsigned long port) { - const unsigned long io_base = __ia64_get_io_port_base(); - unsigned long addr; + struct io_space *space; + unsigned long offset; - addr = io_base | ((port >> 2) << 12) | (port & 0xfff); - return (void *) addr; -} + space = &io_space[IO_SPACE_NR(port)]; + port = IO_SPACE_PORT(port); + if (space->sparse) + offset = IO_SPACE_SPARSE_ENCODING(port); + else + offset = port; + + return (void *) (space->mmio_base | offset); +} + +#define __ia64_inb ___ia64_inb +#define __ia64_inw ___ia64_inw +#define __ia64_inl ___ia64_inl +#define __ia64_outb ___ia64_outb +#define __ia64_outw ___ia64_outw +#define __ia64_outl ___ia64_outl +#define __ia64_readb ___ia64_readb +#define __ia64_readw ___ia64_readw +#define __ia64_readl ___ia64_readl +#define __ia64_readq ___ia64_readq +#define __ia64_writeb ___ia64_writeb +#define __ia64_writew ___ia64_writew +#define __ia64_writel ___ia64_writel +#define __ia64_writeq ___ia64_writeq /* * For the in/out routines, we need to do "mf.a" _after_ doing the I/O access to ensure @@ -96,7 +135,7 @@ */ static inline unsigned int -__ia64_inb (unsigned long port) +___ia64_inb (unsigned long port) { volatile unsigned char *addr = __ia64_mk_io_addr(port); unsigned char ret; @@ -107,7 +146,7 @@ } static inline unsigned int -__ia64_inw (unsigned long port) +___ia64_inw (unsigned long port) { volatile unsigned short *addr = __ia64_mk_io_addr(port); unsigned short ret; @@ -118,7 +157,7 @@ } static inline unsigned int -__ia64_inl (unsigned long port) +___ia64_inl (unsigned long port) { volatile unsigned int *addr = __ia64_mk_io_addr(port); unsigned int ret; @@ -129,7 +168,7 @@ } static inline void -__ia64_outb (unsigned char val, unsigned long port) +___ia64_outb (unsigned char val, unsigned long port) { volatile unsigned char *addr = __ia64_mk_io_addr(port); @@ -138,7 +177,7 @@ } static inline void -__ia64_outw (unsigned short val, unsigned long port) +___ia64_outw (unsigned short val, unsigned long port) { volatile unsigned short *addr = __ia64_mk_io_addr(port); @@ -147,7 +186,7 @@ } static inline void -__ia64_outl (unsigned int val, unsigned long port) +___ia64_outl (unsigned int val, unsigned long port) { volatile unsigned int *addr = __ia64_mk_io_addr(port); @@ -160,17 +199,8 @@ { unsigned char *dp = dst; - if (platform_inb == __ia64_inb) { - volatile unsigned char *addr = __ia64_mk_io_addr(port); - - __ia64_mf_a(); - while (count--) - *dp++ = *addr; - __ia64_mf_a(); - } else - while (count--) - *dp++ = platform_inb(port); - return; + while (count--) + *dp++ = platform_inb(port); } static inline void @@ -178,17 +208,8 @@ { unsigned short *dp = dst; - if (platform_inw == __ia64_inw) { - volatile unsigned short *addr = __ia64_mk_io_addr(port); - - __ia64_mf_a(); - while (count--) - *dp++ = *addr; - __ia64_mf_a(); - } else - while (count--) - *dp++ = platform_inw(port); - return; + while (count--) + *dp++ = platform_inw(port); } static inline void @@ -196,17 +217,8 @@ { unsigned int *dp = dst; - if (platform_inl == __ia64_inl) { - volatile unsigned int *addr = __ia64_mk_io_addr(port); - - __ia64_mf_a(); - while (count--) - *dp++ = *addr; - __ia64_mf_a(); - } else - while (count--) - *dp++ = platform_inl(port); - return; + while (count--) + *dp++ = platform_inl(port); } static inline void @@ -214,16 +226,8 @@ { const unsigned char *sp = src; - if (platform_outb == __ia64_outb) { - volatile unsigned char *addr = __ia64_mk_io_addr(port); - - while (count--) - *addr = *sp++; - __ia64_mf_a(); - } else - while (count--) - platform_outb(*sp++, port); - return; + while (count--) + platform_outb(*sp++, port); } static inline void @@ -231,16 +235,8 @@ { const unsigned short *sp = src; - if (platform_outw == __ia64_outw) { - volatile unsigned short *addr = __ia64_mk_io_addr(port); - - while (count--) - *addr = *sp++; - __ia64_mf_a(); - } else - while (count--) - platform_outw(*sp++, port); - return; + while (count--) + platform_outw(*sp++, port); } static inline void @@ -248,16 +244,8 @@ { const unsigned int *sp = src; - if (platform_outl == __ia64_outl) { - volatile unsigned int *addr = __ia64_mk_io_addr(port); - - while (count--) - *addr = *sp++; - __ia64_mf_a(); - } else - while (count--) - platform_outl(*sp++, port); - return; + while (count--) + platform_outl(*sp++, port); } /* @@ -294,25 +282,25 @@ * hopefully it'll stay that way). */ static inline unsigned char -__ia64_readb (void *addr) +___ia64_readb (void *addr) { return *(volatile unsigned char *)addr; } static inline unsigned short -__ia64_readw (void *addr) +___ia64_readw (void *addr) { return *(volatile unsigned short *)addr; } static inline unsigned int -__ia64_readl (void *addr) +___ia64_readl (void *addr) { return *(volatile unsigned int *) addr; } static inline unsigned long -__ia64_readq (void *addr) +___ia64_readq (void *addr) { return *(volatile unsigned long *) addr; } diff -urN linux-2.5.69-bk6/include/asm-ia64/iosapic.h linux-2.5.69-bk7/include/asm-ia64/iosapic.h --- linux-2.5.69-bk6/include/asm-ia64/iosapic.h 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/iosapic.h 2003-05-12 04:43:30.000000000 -0700 @@ -57,6 +57,7 @@ extern int gsi_to_vector (unsigned int gsi); extern int gsi_to_irq (unsigned int gsi); extern void __init iosapic_parse_prt (void); +extern void iosapic_enable_intr (unsigned int vector); extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger); extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec.h linux-2.5.69-bk7/include/asm-ia64/machvec.h --- linux-2.5.69-bk6/include/asm-ia64/machvec.h 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/machvec.h 2003-05-12 04:43:30.000000000 -0700 @@ -4,7 +4,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Srinivasa Thirumalachar * Copyright (C) Vijay Chander - * Copyright (C) 1999-2001 Hewlett-Packard Co. + * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co. * David Mosberger-Tang */ #ifndef _ASM_IA64_MACHVEC_H @@ -14,7 +14,7 @@ #include /* forward declarations: */ -struct pci_dev; +struct device; struct pt_regs; struct scatterlist; struct irq_desc; @@ -33,17 +33,17 @@ typedef u8 ia64_mv_irq_to_vector (u8); typedef unsigned int ia64_mv_local_vector_to_irq (u8 vector); -/* PCI-DMA interface: */ -typedef void ia64_mv_pci_dma_init (void); -typedef void *ia64_mv_pci_alloc_consistent (struct pci_dev *, size_t, dma_addr_t *); -typedef void ia64_mv_pci_free_consistent (struct pci_dev *, size_t, void *, dma_addr_t); -typedef dma_addr_t ia64_mv_pci_map_single (struct pci_dev *, void *, size_t, int); -typedef void ia64_mv_pci_unmap_single (struct pci_dev *, dma_addr_t, size_t, int); -typedef int ia64_mv_pci_map_sg (struct pci_dev *, struct scatterlist *, int, int); -typedef void ia64_mv_pci_unmap_sg (struct pci_dev *, struct scatterlist *, int, int); -typedef void ia64_mv_pci_dma_sync_single (struct pci_dev *, dma_addr_t, size_t, int); -typedef void ia64_mv_pci_dma_sync_sg (struct pci_dev *, struct scatterlist *, int, int); -typedef int ia64_mv_pci_dma_supported (struct pci_dev *, u64); +/* DMA-mapping interface: */ +typedef void ia64_mv_dma_init (void); +typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, int); +typedef void ia64_mv_dma_free_coherent (struct device *, size_t, void *, dma_addr_t); +typedef dma_addr_t ia64_mv_dma_map_single (struct device *, void *, size_t, int); +typedef void ia64_mv_dma_unmap_single (struct device *, dma_addr_t, size_t, int); +typedef int ia64_mv_dma_map_sg (struct device *, struct scatterlist *, int, int); +typedef void ia64_mv_dma_unmap_sg (struct device *, struct scatterlist *, int, int); +typedef void ia64_mv_dma_sync_single (struct device *, dma_addr_t, size_t, int); +typedef void ia64_mv_dma_sync_sg (struct device *, struct scatterlist *, int, int); +typedef int ia64_mv_dma_supported (struct device *, u64); /* * WARNING: The legacy I/O space is _architected_. Platforms are @@ -66,6 +66,7 @@ typedef unsigned long ia64_mv_readq_t (void *); extern void machvec_noop (void); +extern void machvec_memory_fence (void); # if defined (CONFIG_IA64_HP_SIM) # include @@ -92,16 +93,16 @@ # define platform_log_print ia64_mv.log_print # define platform_send_ipi ia64_mv.send_ipi # define platform_global_tlb_purge ia64_mv.global_tlb_purge -# define platform_pci_dma_init ia64_mv.dma_init -# define platform_pci_alloc_consistent ia64_mv.alloc_consistent -# define platform_pci_free_consistent ia64_mv.free_consistent -# define platform_pci_map_single ia64_mv.map_single -# define platform_pci_unmap_single ia64_mv.unmap_single -# define platform_pci_map_sg ia64_mv.map_sg -# define platform_pci_unmap_sg ia64_mv.unmap_sg -# define platform_pci_dma_sync_single ia64_mv.sync_single -# define platform_pci_dma_sync_sg ia64_mv.sync_sg -# define platform_pci_dma_supported ia64_mv.dma_supported +# define platform_dma_init ia64_mv.dma_init +# define platform_dma_alloc_coherent ia64_mv.dma_alloc_coherent +# define platform_dma_free_coherent ia64_mv.dma_free_coherent +# define platform_dma_map_single ia64_mv.dma_map_single +# define platform_dma_unmap_single ia64_mv.dma_unmap_single +# define platform_dma_map_sg ia64_mv.dma_map_sg +# define platform_dma_unmap_sg ia64_mv.dma_unmap_sg +# define platform_dma_sync_single ia64_mv.dma_sync_single +# define platform_dma_sync_sg ia64_mv.dma_sync_sg +# define platform_dma_supported ia64_mv.dma_supported # define platform_irq_desc ia64_mv.irq_desc # define platform_irq_to_vector ia64_mv.irq_to_vector # define platform_local_vector_to_irq ia64_mv.local_vector_to_irq @@ -119,7 +120,7 @@ /* __attribute__((__aligned__(16))) is required to make size of the * structure multiple of 16 bytes. - * This will fillup the holes created because of section 3.3.1 in + * This will fillup the holes created because of section 3.3.1 in * Software Conventions guide. */ struct ia64_machine_vector { @@ -133,16 +134,16 @@ ia64_mv_log_print_t *log_print; ia64_mv_send_ipi_t *send_ipi; ia64_mv_global_tlb_purge_t *global_tlb_purge; - ia64_mv_pci_dma_init *dma_init; - ia64_mv_pci_alloc_consistent *alloc_consistent; - ia64_mv_pci_free_consistent *free_consistent; - ia64_mv_pci_map_single *map_single; - ia64_mv_pci_unmap_single *unmap_single; - ia64_mv_pci_map_sg *map_sg; - ia64_mv_pci_unmap_sg *unmap_sg; - ia64_mv_pci_dma_sync_single *sync_single; - ia64_mv_pci_dma_sync_sg *sync_sg; - ia64_mv_pci_dma_supported *dma_supported; + ia64_mv_dma_init *dma_init; + ia64_mv_dma_alloc_coherent *dma_alloc_coherent; + ia64_mv_dma_free_coherent *dma_free_coherent; + ia64_mv_dma_map_single *dma_map_single; + ia64_mv_dma_unmap_single *dma_unmap_single; + ia64_mv_dma_map_sg *dma_map_sg; + ia64_mv_dma_unmap_sg *dma_unmap_sg; + ia64_mv_dma_sync_single *dma_sync_single; + ia64_mv_dma_sync_sg *dma_sync_sg; + ia64_mv_dma_supported *dma_supported; ia64_mv_irq_desc *irq_desc; ia64_mv_irq_to_vector *irq_to_vector; ia64_mv_local_vector_to_irq *local_vector_to_irq; @@ -170,16 +171,16 @@ platform_log_print, \ platform_send_ipi, \ platform_global_tlb_purge, \ - platform_pci_dma_init, \ - platform_pci_alloc_consistent, \ - platform_pci_free_consistent, \ - platform_pci_map_single, \ - platform_pci_unmap_single, \ - platform_pci_map_sg, \ - platform_pci_unmap_sg, \ - platform_pci_dma_sync_single, \ - platform_pci_dma_sync_sg, \ - platform_pci_dma_supported, \ + platform_dma_init, \ + platform_dma_alloc_coherent, \ + platform_dma_free_coherent, \ + platform_dma_map_single, \ + platform_dma_unmap_single, \ + platform_dma_map_sg, \ + platform_dma_unmap_sg, \ + platform_dma_sync_single, \ + platform_dma_sync_sg, \ + platform_dma_supported, \ platform_irq_desc, \ platform_irq_to_vector, \ platform_local_vector_to_irq, \ @@ -205,16 +206,16 @@ /* * Declare default routines which aren't declared anywhere else: */ -extern ia64_mv_pci_dma_init swiotlb_init; -extern ia64_mv_pci_alloc_consistent swiotlb_alloc_consistent; -extern ia64_mv_pci_free_consistent swiotlb_free_consistent; -extern ia64_mv_pci_map_single swiotlb_map_single; -extern ia64_mv_pci_unmap_single swiotlb_unmap_single; -extern ia64_mv_pci_map_sg swiotlb_map_sg; -extern ia64_mv_pci_unmap_sg swiotlb_unmap_sg; -extern ia64_mv_pci_dma_sync_single swiotlb_sync_single; -extern ia64_mv_pci_dma_sync_sg swiotlb_sync_sg; -extern ia64_mv_pci_dma_supported swiotlb_pci_dma_supported; +extern ia64_mv_dma_init swiotlb_init; +extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent; +extern ia64_mv_dma_free_coherent swiotlb_free_coherent; +extern ia64_mv_dma_map_single swiotlb_map_single; +extern ia64_mv_dma_unmap_single swiotlb_unmap_single; +extern ia64_mv_dma_map_sg swiotlb_map_sg; +extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg; +extern ia64_mv_dma_sync_single swiotlb_sync_single; +extern ia64_mv_dma_sync_sg swiotlb_sync_sg; +extern ia64_mv_dma_supported swiotlb_dma_supported; /* * Define default versions so we can extend machvec for new platforms without having @@ -247,35 +248,35 @@ #ifndef platform_global_tlb_purge # define platform_global_tlb_purge ia64_global_tlb_purge /* default to architected version */ #endif -#ifndef platform_pci_dma_init -# define platform_pci_dma_init swiotlb_init +#ifndef platform_dma_init +# define platform_dma_init swiotlb_init #endif -#ifndef platform_pci_alloc_consistent -# define platform_pci_alloc_consistent swiotlb_alloc_consistent +#ifndef platform_dma_alloc_coherent +# define platform_dma_alloc_coherent swiotlb_alloc_coherent #endif -#ifndef platform_pci_free_consistent -# define platform_pci_free_consistent swiotlb_free_consistent +#ifndef platform_dma_free_coherent +# define platform_dma_free_coherent swiotlb_free_coherent #endif -#ifndef platform_pci_map_single -# define platform_pci_map_single swiotlb_map_single +#ifndef platform_dma_map_single +# define platform_dma_map_single swiotlb_map_single #endif -#ifndef platform_pci_unmap_single -# define platform_pci_unmap_single swiotlb_unmap_single +#ifndef platform_dma_unmap_single +# define platform_dma_unmap_single swiotlb_unmap_single #endif -#ifndef platform_pci_map_sg -# define platform_pci_map_sg swiotlb_map_sg +#ifndef platform_dma_map_sg +# define platform_dma_map_sg swiotlb_map_sg #endif -#ifndef platform_pci_unmap_sg -# define platform_pci_unmap_sg swiotlb_unmap_sg +#ifndef platform_dma_unmap_sg +# define platform_dma_unmap_sg swiotlb_unmap_sg #endif -#ifndef platform_pci_dma_sync_single -# define platform_pci_dma_sync_single swiotlb_sync_single +#ifndef platform_dma_sync_single +# define platform_dma_sync_single swiotlb_sync_single #endif -#ifndef platform_pci_dma_sync_sg -# define platform_pci_dma_sync_sg swiotlb_sync_sg +#ifndef platform_dma_sync_sg +# define platform_dma_sync_sg swiotlb_sync_sg #endif -#ifndef platform_pci_dma_supported -# define platform_pci_dma_supported swiotlb_pci_dma_supported +#ifndef platform_dma_supported +# define platform_dma_supported swiotlb_dma_supported #endif #ifndef platform_irq_desc # define platform_irq_desc __ia64_irq_desc diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_hpzx1.h linux-2.5.69-bk7/include/asm-ia64/machvec_hpzx1.h --- linux-2.5.69-bk6/include/asm-ia64/machvec_hpzx1.h 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/machvec_hpzx1.h 2003-05-12 04:43:30.000000000 -0700 @@ -2,13 +2,13 @@ #define _ASM_IA64_MACHVEC_HPZX1_h extern ia64_mv_setup_t dig_setup; -extern ia64_mv_pci_alloc_consistent sba_alloc_consistent; -extern ia64_mv_pci_free_consistent sba_free_consistent; -extern ia64_mv_pci_map_single sba_map_single; -extern ia64_mv_pci_unmap_single sba_unmap_single; -extern ia64_mv_pci_map_sg sba_map_sg; -extern ia64_mv_pci_unmap_sg sba_unmap_sg; -extern ia64_mv_pci_dma_supported sba_dma_supported; +extern ia64_mv_dma_alloc_coherent sba_alloc_coherent; +extern ia64_mv_dma_free_coherent sba_free_coherent; +extern ia64_mv_dma_map_single sba_map_single; +extern ia64_mv_dma_unmap_single sba_unmap_single; +extern ia64_mv_dma_map_sg sba_map_sg; +extern ia64_mv_dma_unmap_sg sba_unmap_sg; +extern ia64_mv_dma_supported sba_dma_supported; /* * This stuff has dual use! @@ -19,15 +19,15 @@ */ #define platform_name "hpzx1" #define platform_setup dig_setup -#define platform_pci_dma_init ((ia64_mv_pci_dma_init *) machvec_noop) -#define platform_pci_alloc_consistent sba_alloc_consistent -#define platform_pci_free_consistent sba_free_consistent -#define platform_pci_map_single sba_map_single -#define platform_pci_unmap_single sba_unmap_single -#define platform_pci_map_sg sba_map_sg -#define platform_pci_unmap_sg sba_unmap_sg -#define platform_pci_dma_sync_single ((ia64_mv_pci_dma_sync_single *) machvec_noop) -#define platform_pci_dma_sync_sg ((ia64_mv_pci_dma_sync_sg *) machvec_noop) -#define platform_pci_dma_supported sba_dma_supported +#define platform_dma_init ((ia64_mv_dma_init *) machvec_noop) +#define platform_dma_alloc_coherent sba_alloc_coherent +#define platform_dma_free_coherent sba_free_coherent +#define platform_dma_map_single sba_map_single +#define platform_dma_unmap_single sba_unmap_single +#define platform_dma_map_sg sba_map_sg +#define platform_dma_unmap_sg sba_unmap_sg +#define platform_dma_sync_single ((ia64_mv_dma_sync_single *) machvec_memory_fence) +#define platform_dma_sync_sg ((ia64_mv_dma_sync_sg *) machvec_memory_fence) +#define platform_dma_supported sba_dma_supported #endif /* _ASM_IA64_MACHVEC_HPZX1_h */ diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_init.h linux-2.5.69-bk7/include/asm-ia64/machvec_init.h --- linux-2.5.69-bk6/include/asm-ia64/machvec_init.h 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/machvec_init.h 2003-05-12 04:43:30.000000000 -0700 @@ -1,7 +1,3 @@ -#define __MACHVEC_HDR(n) -#define __MACHVEC_EXPAND(n) __MACHVEC_HDR(n) -#define MACHVEC_PLATFORM_HEADER __MACHVEC_EXPAND(MACHVEC_PLATFORM_NAME) - #include extern ia64_mv_send_ipi_t ia64_send_ipi; @@ -16,6 +12,10 @@ extern ia64_mv_outb_t __ia64_outb; extern ia64_mv_outw_t __ia64_outw; extern ia64_mv_outl_t __ia64_outl; +extern ia64_mv_readb_t __ia64_readb; +extern ia64_mv_readw_t __ia64_readw; +extern ia64_mv_readl_t __ia64_readl; +extern ia64_mv_readq_t __ia64_readq; #define MACHVEC_HELPER(name) \ struct ia64_machine_vector machvec_##name __attribute__ ((unused, __section__ (".machvec"))) \ diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_sn1.h linux-2.5.69-bk7/include/asm-ia64/machvec_sn1.h --- linux-2.5.69-bk6/include/asm-ia64/machvec_sn1.h 2003-05-04 16:53:34.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/machvec_sn1.h 2003-05-12 04:43:30.000000000 -0700 @@ -44,14 +44,14 @@ extern ia64_mv_outb_t sn1_outb; extern ia64_mv_outw_t sn1_outw; extern ia64_mv_outl_t sn1_outl; -extern ia64_mv_pci_alloc_consistent sn1_pci_alloc_consistent; -extern ia64_mv_pci_free_consistent sn1_pci_free_consistent; -extern ia64_mv_pci_map_single sn1_pci_map_single; -extern ia64_mv_pci_unmap_single sn1_pci_unmap_single; -extern ia64_mv_pci_map_sg sn1_pci_map_sg; -extern ia64_mv_pci_unmap_sg sn1_pci_unmap_sg; -extern ia64_mv_pci_dma_sync_single sn1_pci_dma_sync_single; -extern ia64_mv_pci_dma_sync_sg sn1_pci_dma_sync_sg; +extern ia64_mv_dma_alloc_coherent sn1_dma_alloc_coherent; +extern ia64_mv_dma_free_coherent sn1_dma_free_coherent; +extern ia64_mv_dma_map_single sn1_dma_map_single; +extern ia64_mv_dma_unmap_single sn1_dma_unmap_single; +extern ia64_mv_dma_map_sg sn1_dma_map_sg; +extern ia64_mv_dma_unmap_sg sn1_dma_unmap_sg; +extern ia64_mv_dma_sync_single sn1_dma_sync_single; +extern ia64_mv_dma_sync_sg sn1_dma_sync_sg; /* * This stuff has dual use! @@ -72,14 +72,14 @@ #define platform_outb sn1_outb #define platform_outw sn1_outw #define platform_outl sn1_outl -#define platform_pci_dma_init machvec_noop -#define platform_pci_alloc_consistent sn1_pci_alloc_consistent -#define platform_pci_free_consistent sn1_pci_free_consistent -#define platform_pci_map_single sn1_pci_map_single -#define platform_pci_unmap_single sn1_pci_unmap_single -#define platform_pci_map_sg sn1_pci_map_sg -#define platform_pci_unmap_sg sn1_pci_unmap_sg -#define platform_pci_dma_sync_single sn1_pci_dma_sync_single -#define platform_pci_dma_sync_sg sn1_pci_dma_sync_sg +#define platform_dma_init machvec_noop +#define platform_dma_alloc_coherent sn1_dma_alloc_coherent +#define platform_dma_free_coherent sn1_dma_free_coherent +#define platform_dma_map_single sn1_dma_map_single +#define platform_dma_unmap_single sn1_dma_unmap_single +#define platform_dma_map_sg sn1_dma_map_sg +#define platform_dma_unmap_sg sn1_dma_unmap_sg +#define platform_dma_sync_single sn1_dma_sync_single +#define platform_dma_sync_sg sn1_dma_sync_sg #endif /* _ASM_IA64_MACHVEC_SN1_h */ diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_sn2.h linux-2.5.69-bk7/include/asm-ia64/machvec_sn2.h --- linux-2.5.69-bk6/include/asm-ia64/machvec_sn2.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/machvec_sn2.h 2003-05-12 04:43:30.000000000 -0700 @@ -51,15 +51,15 @@ extern ia64_mv_readw_t __sn_readw; extern ia64_mv_readl_t __sn_readl; extern ia64_mv_readq_t __sn_readq; -extern ia64_mv_pci_alloc_consistent sn_pci_alloc_consistent; -extern ia64_mv_pci_free_consistent sn_pci_free_consistent; -extern ia64_mv_pci_map_single sn_pci_map_single; -extern ia64_mv_pci_unmap_single sn_pci_unmap_single; -extern ia64_mv_pci_map_sg sn_pci_map_sg; -extern ia64_mv_pci_unmap_sg sn_pci_unmap_sg; -extern ia64_mv_pci_dma_sync_single sn_pci_dma_sync_single; -extern ia64_mv_pci_dma_sync_sg sn_pci_dma_sync_sg; -extern ia64_mv_pci_dma_supported sn_pci_dma_supported; +extern ia64_mv_dma_alloc_coherent sn_dma_alloc_coherent; +extern ia64_mv_dma_free_coherent sn_dma_free_coherent; +extern ia64_mv_dma_map_single sn_dma_map_single; +extern ia64_mv_dma_unmap_single sn_dma_unmap_single; +extern ia64_mv_dma_map_sg sn_dma_map_sg; +extern ia64_mv_dma_unmap_sg sn_dma_unmap_sg; +extern ia64_mv_dma_sync_single sn_dma_sync_single; +extern ia64_mv_dma_sync_sg sn_dma_sync_sg; +extern ia64_mv_dma_supported sn_dma_supported; /* * This stuff has dual use! @@ -88,15 +88,15 @@ #define platform_irq_desc sn_irq_desc #define platform_irq_to_vector sn_irq_to_vector #define platform_local_vector_to_irq sn_local_vector_to_irq -#define platform_pci_dma_init machvec_noop -#define platform_pci_alloc_consistent sn_pci_alloc_consistent -#define platform_pci_free_consistent sn_pci_free_consistent -#define platform_pci_map_single sn_pci_map_single -#define platform_pci_unmap_single sn_pci_unmap_single -#define platform_pci_map_sg sn_pci_map_sg -#define platform_pci_unmap_sg sn_pci_unmap_sg -#define platform_pci_dma_sync_single sn_pci_dma_sync_single -#define platform_pci_dma_sync_sg sn_pci_dma_sync_sg -#define platform_pci_dma_supported sn_pci_dma_supported +#define platform_dma_init machvec_noop +#define platform_dma_alloc_coherent sn_dma_alloc_coherent +#define platform_dma_free_coherent sn_dma_free_coherent +#define platform_dma_map_single sn_dma_map_single +#define platform_dma_unmap_single sn_dma_unmap_single +#define platform_dma_map_sg sn_dma_map_sg +#define platform_dma_unmap_sg sn_dma_unmap_sg +#define platform_dma_sync_single sn_dma_sync_single +#define platform_dma_sync_sg sn_dma_sync_sg +#define platform_dma_supported sn_dma_supported #endif /* _ASM_IA64_MACHVEC_SN2_H */ diff -urN linux-2.5.69-bk6/include/asm-ia64/mca.h linux-2.5.69-bk7/include/asm-ia64/mca.h --- linux-2.5.69-bk6/include/asm-ia64/mca.h 2003-05-04 16:53:07.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/mca.h 2003-05-12 04:43:30.000000000 -0700 @@ -11,7 +11,10 @@ #define _ASM_IA64_MCA_H #if !defined(__ASSEMBLY__) + +#include #include + #include #include #include @@ -129,10 +132,10 @@ extern void ia64_mca_ucmc_handler(void); extern void ia64_monarch_init_handler(void); extern void ia64_slave_init_handler(void); -extern void ia64_mca_rendez_int_handler(int,void *,struct pt_regs *); -extern void ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *); -extern void ia64_mca_cmc_int_handler(int,void *,struct pt_regs *); -extern void ia64_mca_cpe_int_handler(int,void *,struct pt_regs *); +extern irqreturn_t ia64_mca_rendez_int_handler(int,void *,struct pt_regs *); +extern irqreturn_t ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *); +extern irqreturn_t ia64_mca_cmc_int_handler(int,void *,struct pt_regs *); +extern irqreturn_t ia64_mca_cpe_int_handler(int,void *,struct pt_regs *); extern int ia64_log_print(int,prfunc_t); extern void ia64_mca_cmc_vector_setup(void); extern int ia64_mca_check_errors(void); diff -urN linux-2.5.69-bk6/include/asm-ia64/page.h linux-2.5.69-bk7/include/asm-ia64/page.h --- linux-2.5.69-bk6/include/asm-ia64/page.h 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/page.h 2003-05-12 04:43:30.000000000 -0700 @@ -37,6 +37,8 @@ # if defined(CONFIG_HUGETLB_PAGE_SIZE_4GB) # define HPAGE_SHIFT 32 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1GB) +# define HPAGE_SHIFT 30 # elif defined(CONFIG_HUGETLB_PAGE_SIZE_256MB) # define HPAGE_SHIFT 28 # elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) @@ -89,7 +91,12 @@ #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #ifndef CONFIG_DISCONTIGMEM -#define pfn_valid(pfn) ((pfn) < max_mapnr) +# ifdef CONFIG_VIRTUAL_MEM_MAP + extern int ia64_pfn_valid (unsigned long pfn); +# define pfn_valid(pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) +# else +# define pfn_valid(pfn) ((pfn) < max_mapnr) +# endif #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define page_to_pfn(page) ((unsigned long) (page - mem_map)) #define pfn_to_page(pfn) (mem_map + (pfn)) diff -urN linux-2.5.69-bk6/include/asm-ia64/pal.h linux-2.5.69-bk7/include/asm-ia64/pal.h --- linux-2.5.69-bk6/include/asm-ia64/pal.h 2003-05-04 16:53:34.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/pal.h 2003-05-12 04:43:30.000000000 -0700 @@ -622,7 +622,8 @@ u64 pmsa_xip; /* previous iip */ u64 pmsa_xpsr; /* previous psr */ u64 pmsa_xfs; /* previous ifs */ - u64 pmsa_reserved[71]; /* pal_min_state_area should total to 1KB */ + u64 pmsa_br1; /* branch register 1 */ + u64 pmsa_reserved[70]; /* pal_min_state_area should total to 1KB */ } pal_min_state_area_t; diff -urN linux-2.5.69-bk6/include/asm-ia64/pci.h linux-2.5.69-bk7/include/asm-ia64/pci.h --- linux-2.5.69-bk6/include/asm-ia64/pci.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/pci.h 2003-05-12 04:43:30.000000000 -0700 @@ -47,18 +47,7 @@ #define HAVE_ARCH_PCI_MWI 1 extern int pcibios_prep_mwi (struct pci_dev *); -/* - * Dynamic DMA mapping API. See Documentation/DMA-mapping.txt for details. - */ -#define pci_alloc_consistent platform_pci_alloc_consistent -#define pci_free_consistent platform_pci_free_consistent -#define pci_map_single platform_pci_map_single -#define pci_unmap_single platform_pci_unmap_single -#define pci_map_sg platform_pci_map_sg -#define pci_unmap_sg platform_pci_unmap_sg -#define pci_dma_sync_single platform_pci_dma_sync_single -#define pci_dma_sync_sg platform_pci_dma_sync_sg -#define pci_dma_supported platform_pci_dma_supported +#include /* pci_unmap_{single,page} is not a nop, thus... */ #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ @@ -74,18 +63,12 @@ #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ (((PTR)->LEN_NAME) = (VAL)) -#define pci_map_page(dev,pg,off,size,dir) \ - pci_map_single((dev), page_address(pg) + (off), (size), (dir)) -#define pci_unmap_page(dev,dma_addr,size,dir) \ - pci_unmap_single((dev), (dma_addr), (size), (dir)) - /* The ia64 platform always supports 64-bit addressing. */ -#define pci_dac_dma_supported(pci_dev, mask) (1) - -#define pci_dac_page_to_dma(dev,pg,off,dir) ((dma_addr_t) page_to_bus(pg) + (off)) -#define pci_dac_dma_to_page(dev,dma_addr) (virt_to_page(bus_to_virt(dma_addr))) -#define pci_dac_dma_to_offset(dev,dma_addr) ((dma_addr) & ~PAGE_MASK) -#define pci_dac_dma_sync_single(dev,dma_addr,len,dir) do { /* nothing */ } while (0) +#define pci_dac_dma_supported(pci_dev, mask) (1) +#define pci_dac_page_to_dma(dev,pg,off,dir) ((dma_addr_t) page_to_bus(pg) + (off)) +#define pci_dac_dma_to_page(dev,dma_addr) (virt_to_page(bus_to_virt(dma_addr))) +#define pci_dac_dma_to_offset(dev,dma_addr) ((dma_addr) & ~PAGE_MASK) +#define pci_dac_dma_sync_single(dev,dma_addr,len,dir) do { mb(); } while (0) /* Return the index of the PCI controller for device PDEV. */ #define pci_controller_num(PDEV) (0) @@ -97,12 +80,18 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); +struct pci_window { + struct resource resource; + u64 offset; +}; + struct pci_controller { void *acpi_handle; void *iommu; int segment; - u64 mem_offset; + unsigned int windows; + struct pci_window *window; }; #define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata) diff -urN linux-2.5.69-bk6/include/asm-ia64/percpu.h linux-2.5.69-bk7/include/asm-ia64/percpu.h --- linux-2.5.69-bk6/include/asm-ia64/percpu.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/percpu.h 2003-05-12 04:43:30.000000000 -0700 @@ -5,7 +5,7 @@ #include /* - * Copyright (C) 2002 Hewlett-Packard Co + * Copyright (C) 2002-2003 Hewlett-Packard Co * David Mosberger-Tang */ @@ -35,6 +35,8 @@ #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu) #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu) +extern void setup_per_cpu_areas (void); + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_PERCPU_H */ diff -urN linux-2.5.69-bk6/include/asm-ia64/perfmon.h linux-2.5.69-bk7/include/asm-ia64/perfmon.h --- linux-2.5.69-bk6/include/asm-ia64/perfmon.h 2003-05-04 16:53:32.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/perfmon.h 2003-05-12 04:43:30.000000000 -0700 @@ -41,6 +41,7 @@ #define PFM_FL_NOTIFY_BLOCK 0x04 /* block task on user level notifications */ #define PFM_FL_SYSTEM_WIDE 0x08 /* create a system wide context */ #define PFM_FL_EXCL_IDLE 0x20 /* exclude idle task from system wide session */ +#define PFM_FL_UNSECURE 0x40 /* allow unsecure monitoring for non self-monitoring task */ /* * PMC flags @@ -125,7 +126,7 @@ * Define the version numbers for both perfmon as a whole and the sampling buffer format. */ #define PFM_VERSION_MAJ 1U -#define PFM_VERSION_MIN 3U +#define PFM_VERSION_MIN 4U #define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff)) #define PFM_SMPL_VERSION_MAJ 1U diff -urN linux-2.5.69-bk6/include/asm-ia64/processor.h linux-2.5.69-bk7/include/asm-ia64/processor.h --- linux-2.5.69-bk6/include/asm-ia64/processor.h 2003-05-04 16:53:12.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/processor.h 2003-05-12 04:43:30.000000000 -0700 @@ -39,6 +39,14 @@ #define TASK_SIZE (current->thread.task_size) /* + * MM_VM_SIZE(mm) gives the maximum address (plus 1) which may contain a mapping for + * address-space MM. Note that with 32-bit tasks, this is still DEFAULT_TASK_SIZE, + * because the kernel may have installed helper-mappings above TASK_SIZE. For example, + * for x86 emulation, the LDT and GDT are mapped above TASK_SIZE. + */ +#define MM_VM_SIZE(mm) DEFAULT_TASK_SIZE + +/* * This decides where the kernel will search for a free chunk of vm * space during mmap's. */ @@ -291,7 +299,7 @@ #define start_thread(regs,new_ip,new_sp) do { \ set_fs(USER_DS); \ - regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL | IA64_PSR_SP)) \ + regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL)) \ & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS)); \ regs->cr_iip = new_ip; \ regs->ar_rsc = 0xf; /* eager mode, privilege level 3 */ \ diff -urN linux-2.5.69-bk6/include/asm-ia64/ptrace.h linux-2.5.69-bk7/include/asm-ia64/ptrace.h --- linux-2.5.69-bk6/include/asm-ia64/ptrace.h 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/ptrace.h 2003-05-12 04:43:30.000000000 -0700 @@ -227,8 +227,10 @@ }) struct task_struct; /* forward decl */ + struct unw_frame_info; /* forward decl */ extern void show_regs (struct pt_regs *); + extern void ia64_do_show_stack (struct unw_frame_info *, void *); extern unsigned long ia64_get_user_rbs_end (struct task_struct *, struct pt_regs *, unsigned long *); extern long ia64_peek (struct task_struct *, struct switch_stack *, unsigned long, diff -urN linux-2.5.69-bk6/include/asm-ia64/sal.h linux-2.5.69-bk7/include/asm-ia64/sal.h --- linux-2.5.69-bk6/include/asm-ia64/sal.h 2003-05-04 16:53:42.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/sal.h 2003-05-12 04:43:30.000000000 -0700 @@ -226,7 +226,7 @@ /* Encodings for machine check parameter types */ enum { - SAL_MC_PARAM_RENDEZ_INT = 1, /* Rendezevous interrupt */ + SAL_MC_PARAM_RENDEZ_INT = 1, /* Rendezvous interrupt */ SAL_MC_PARAM_RENDEZ_WAKEUP = 2, /* Wakeup */ SAL_MC_PARAM_CPE_INT = 3 /* Corrected Platform Error Int */ }; diff -urN linux-2.5.69-bk6/include/asm-ia64/serial.h linux-2.5.69-bk7/include/asm-ia64/serial.h --- linux-2.5.69-bk6/include/asm-ia64/serial.h 2003-05-04 16:53:14.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/serial.h 2003-05-12 04:43:30.000000000 -0700 @@ -59,7 +59,6 @@ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ - #ifdef CONFIG_SERIAL_MANY_PORTS #define EXTRA_SERIAL_PORT_DEFNS \ { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \ diff -urN linux-2.5.69-bk6/include/asm-ia64/spinlock.h linux-2.5.69-bk7/include/asm-ia64/spinlock.h --- linux-2.5.69-bk6/include/asm-ia64/spinlock.h 2003-05-04 16:53:01.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/spinlock.h 2003-05-12 04:43:30.000000000 -0700 @@ -22,26 +22,72 @@ #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #define spin_lock_init(x) ((x)->lock = 0) -#define DEBUG_SPIN_LOCK 0 +#define NEW_LOCK +#ifdef NEW_LOCK -#if DEBUG_SPIN_LOCK +/* + * Try to get the lock. If we fail to get the lock, make a non-standard call to + * ia64_spinlock_contention(). We do not use a normal call because that would force all + * callers of spin_lock() to be non-leaf routines. Instead, ia64_spinlock_contention() is + * carefully coded to touch only those registers that spin_lock() marks "clobbered". + */ -#include - -#define _raw_spin_lock(x) \ -do { \ - unsigned long _timeout = 1000000000; \ - volatile unsigned int _old = 0, _new = 1, *_ptr = &((x)->lock); \ - do { \ - if (_timeout-- == 0) { \ - extern void dump_stack (void); \ - printk("kernel DEADLOCK at %s:%d?\n", __FILE__, __LINE__); \ - dump_stack(); \ - } \ - } while (__sync_val_compare_and_swap(_ptr, _old, _new) != _old); \ -} while (0) +#define IA64_SPINLOCK_CLOBBERS "ar.pfs", "p14", "r28", "r29", "r30", "b6", "memory" +static inline void +_raw_spin_lock (spinlock_t *lock) +{ + register volatile unsigned int *ptr asm ("r31") = &lock->lock; + +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +# ifdef CONFIG_ITANIUM + /* don't use brl on Itanium... */ + asm volatile ("{\n\t" + " mov ar.ccv = r0\n\t" + " mov r28 = ip\n\t" + " mov r30 = 1;;\n\t" + "}\n\t" + "cmpxchg4.acq r30 = [%1], r30, ar.ccv\n\t" + "movl r29 = ia64_spinlock_contention_pre3_4;;\n\t" + "cmp4.ne p14, p0 = r30, r0\n\t" + "mov b6 = r29;;\n" + "(p14) br.cond.spnt.many b6" + : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS); +# else + asm volatile ("{\n\t" + " mov ar.ccv = r0\n\t" + " mov r28 = ip\n\t" + " mov r30 = 1;;\n\t" + "}\n\t" + "cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t" + "cmp4.ne p14, p0 = r30, r0\n" + "(p14) brl.cond.spnt.many ia64_spinlock_contention_pre3_4" + : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS); +# endif /* CONFIG_MCKINLEY */ #else +# ifdef CONFIG_ITANIUM + /* don't use brl on Itanium... */ + /* mis-declare, so we get the entry-point, not it's function descriptor: */ + asm volatile ("mov r30 = 1\n\t" + "mov ar.ccv = r0;;\n\t" + "cmpxchg4.acq r30 = [%0], r30, ar.ccv\n\t" + "movl r29 = ia64_spinlock_contention;;\n\t" + "cmp4.ne p14, p0 = r30, r0\n\t" + "mov b6 = r29;;\n" + "(p14) br.call.spnt.many b6 = b6" + : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS); +# else + asm volatile ("mov r30 = 1\n\t" + "mov ar.ccv = r0;;\n\t" + "cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t" + "cmp4.ne p14, p0 = r30, r0\n\t" + "(p14) brl.call.spnt.many b6=ia64_spinlock_contention" + : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS); +# endif /* CONFIG_MCKINLEY */ +#endif +} + +#else /* !NEW_LOCK */ /* * Streamlined test_and_set_bit(0, (x)). We use test-and-test-and-set @@ -64,7 +110,7 @@ ";;\n" \ :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory") -#endif /* !DEBUG_SPIN_LOCK */ +#endif /* !NEW_LOCK */ #define spin_is_locked(x) ((x)->lock != 0) #define _raw_spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) @@ -72,43 +118,31 @@ #define spin_unlock_wait(x) do { barrier(); } while ((x)->lock) typedef struct { - volatile int read_counter:31; - volatile int write_lock:1; + volatile int read_counter : 31; + volatile int write_lock : 1; } rwlock_t; #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) #define rwlock_is_locked(x) (*(volatile int *) (x) != 0) -#define _raw_read_lock(rw) \ -do { \ - int __read_lock_tmp = 0; \ - __asm__ __volatile__ ("1:\tfetchadd4.acq %0 = [%1], 1\n" \ - ";;\n" \ - "tbit.nz p6,p0 = %0, 31\n" \ - "(p6) br.cond.sptk.few 2f\n" \ - ".section .text.lock,\"ax\"\n" \ - "2:\tfetchadd4.rel %0 = [%1], -1\n" \ - ";;\n" \ - "3:\tld4.acq %0 = [%1]\n" \ - ";;\n" \ - "tbit.nz p6,p0 = %0, 31\n" \ - "(p6) br.cond.sptk.few 3b\n" \ - "br.cond.sptk.few 1b\n" \ - ";;\n" \ - ".previous\n" \ - : "=&r" (__read_lock_tmp) \ - : "r" (rw) : "p6", "memory"); \ -} while(0) +#define _raw_read_lock(rw) \ +do { \ + rwlock_t *__read_lock_ptr = (rw); \ + \ + while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, "acq") < 0)) { \ + ia64_fetchadd(-1, (int *) __read_lock_ptr, "rel"); \ + while (*(volatile int *)__read_lock_ptr < 0) \ + barrier(); \ + \ + } \ +} while (0) -#define _raw_read_unlock(rw) \ -do { \ - int __read_unlock_tmp = 0; \ - __asm__ __volatile__ ("fetchadd4.rel %0 = [%1], -1\n" \ - : "=r" (__read_unlock_tmp) \ - : "r" (rw) \ - : "memory"); \ -} while(0) +#define _raw_read_unlock(rw) \ +do { \ + rwlock_t *__read_lock_ptr = (rw); \ + ia64_fetchadd(-1, (int *) __read_lock_ptr, "rel"); \ +} while (0) #define _raw_write_lock(rw) \ do { \ diff -urN linux-2.5.69-bk6/include/asm-ia64/system.h linux-2.5.69-bk7/include/asm-ia64/system.h --- linux-2.5.69-bk6/include/asm-ia64/system.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/system.h 2003-05-12 04:43:30.000000000 -0700 @@ -212,48 +212,39 @@ # define PERFMON_IS_SYSWIDE() (0) #endif -#define __switch_to(prev,next,last) do { \ - if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)) \ - || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE()) \ - ia64_save_extra(prev); \ - if (((next)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)) \ - || IS_IA32_PROCESS(ia64_task_regs(next)) || PERFMON_IS_SYSWIDE()) \ - ia64_load_extra(next); \ - (last) = ia64_switch_to((next)); \ +#define IA64_HAS_EXTRA_STATE(t) \ + ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID) \ + || IS_IA32_PROCESS(ia64_task_regs(t)) || PERFMON_IS_SYSWIDE()) + +#define __switch_to(prev,next,last) do { \ + struct task_struct *__fpu_owner = ia64_get_fpu_owner(); \ + if (IA64_HAS_EXTRA_STATE(prev)) \ + ia64_save_extra(prev); \ + if (IA64_HAS_EXTRA_STATE(next)) \ + ia64_load_extra(next); \ + ia64_psr(ia64_task_regs(next))->dfh = \ + !(__fpu_owner == (next) && ((next)->thread.last_fph_cpu == smp_processor_id())); \ + (last) = ia64_switch_to((next)); \ } while (0) #ifdef CONFIG_SMP - /* - * In the SMP case, we save the fph state when context-switching - * away from a thread that modified fph. This way, when the thread - * gets scheduled on another CPU, the CPU can pick up the state from - * task->thread.fph, avoiding the complication of having to fetch - * the latest fph state from another CPU. + * In the SMP case, we save the fph state when context-switching away from a thread that + * modified fph. This way, when the thread gets scheduled on another CPU, the CPU can + * pick up the state from task->thread.fph, avoiding the complication of having to fetch + * the latest fph state from another CPU. In other words: eager save, lazy restore. */ -# define switch_to(prev,next,last) do { \ - if (ia64_psr(ia64_task_regs(prev))->mfh) { \ - ia64_psr(ia64_task_regs(prev))->mfh = 0; \ - (prev)->thread.flags |= IA64_THREAD_FPH_VALID; \ - __ia64_save_fpu((prev)->thread.fph); \ - (prev)->thread.last_fph_cpu = smp_processor_id(); \ - } \ - if ((next)->thread.flags & IA64_THREAD_FPH_VALID) { \ - if (((next)->thread.last_fph_cpu == smp_processor_id()) \ - && (ia64_get_fpu_owner() == next)) \ - { \ - ia64_psr(ia64_task_regs(next))->dfh = 0; \ - ia64_psr(ia64_task_regs(next))->mfh = 0; \ - } else \ - ia64_psr(ia64_task_regs(next))->dfh = 1; \ - } \ - __switch_to(prev,next,last); \ - } while (0) -#else # define switch_to(prev,next,last) do { \ - ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next)); \ - __switch_to(prev,next,last); \ + if (ia64_psr(ia64_task_regs(prev))->mfh) { \ + ia64_psr(ia64_task_regs(prev))->mfh = 0; \ + (prev)->thread.flags |= IA64_THREAD_FPH_VALID; \ + __ia64_save_fpu((prev)->thread.fph); \ + (prev)->thread.last_fph_cpu = smp_processor_id(); \ + } \ + __switch_to(prev, next, last); \ } while (0) +#else +# define switch_to(prev,next,last) __switch_to(prev, next, last) #endif /* diff -urN linux-2.5.69-bk6/include/asm-ia64/uaccess.h linux-2.5.69-bk7/include/asm-ia64/uaccess.h --- linux-2.5.69-bk6/include/asm-ia64/uaccess.h 2003-05-04 16:53:09.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/uaccess.h 2003-05-12 04:43:30.000000000 -0700 @@ -8,7 +8,7 @@ * addresses. Thus, we need to be careful not to let the user to * trick us into accessing kernel memory that would normally be * inaccessible. This code is also fairly performance sensitive, - * so we want to spend as little time doing saftey checks as + * so we want to spend as little time doing safety checks as * possible. * * To make matters a bit more interesting, these macros sometimes also diff -urN linux-2.5.69-bk6/include/asm-ia64/unwind.h linux-2.5.69-bk7/include/asm-ia64/unwind.h --- linux-2.5.69-bk6/include/asm-ia64/unwind.h 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/include/asm-ia64/unwind.h 2003-05-12 04:43:30.000000000 -0700 @@ -2,8 +2,8 @@ #define _ASM_IA64_UNWIND_H /* - * Copyright (C) 1999-2000 Hewlett-Packard Co - * Copyright (C) 1999-2000 David Mosberger-Tang + * Copyright (C) 1999-2000, 2003 Hewlett-Packard Co + * David Mosberger-Tang * * A simple API for unwinding kernel stacks. This is used for * debugging and error reporting purposes. The kernel doesn't need @@ -107,6 +107,13 @@ */ extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t); +/* + * Prepare to unwind from interruption. The pt-regs and switch-stack structures must have + * be "adjacent" (no state modifications between pt-regs and switch-stack). + */ +extern void unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t, + struct pt_regs *pt, struct switch_stack *sw); + extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw); diff -urN linux-2.5.69-bk6/include/linux/agp_backend.h linux-2.5.69-bk7/include/linux/agp_backend.h --- linux-2.5.69-bk6/include/linux/agp_backend.h 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/agp_backend.h 2003-05-12 04:43:30.000000000 -0700 @@ -1,5 +1,6 @@ /* - * AGPGART module version 0.99 + * AGPGART module version 0.100 + * Copyright (C) 2002-2003 Dave Jones * Copyright (C) 1999 Jeff Hartmann * Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Xi Graphics, Inc. @@ -37,45 +38,7 @@ enum chipset_type { NOT_SUPPORTED, - INTEL_GENERIC, - INTEL_LX, - INTEL_BX, - INTEL_GX, - INTEL_I810, - INTEL_I815, - INTEL_I820, - INTEL_I830_M, - INTEL_I845_G, - INTEL_I855_PM, - INTEL_I865_G, - INTEL_I840, - INTEL_I845, - INTEL_I850, - INTEL_I860, - INTEL_460GX, - INTEL_E7505, - VIA_GENERIC, - SIS_GENERIC, - AMD_GENERIC, - AMD_IRONGATE, - AMD_761, - AMD_762, - AMD_8151, - ALI_M1541, - ALI_M1621, - ALI_M1631, - ALI_M1632, - ALI_M1641, - ALI_M1644, - ALI_M1647, - ALI_M1651, - ALI_M1671, - ALI_GENERIC, - SVWRKS_HE, - SVWRKS_LE, - SVWRKS_GENERIC, - HP_ZX1, - ALPHA_CORE_AGP, + SUPPORTED, }; struct agp_version { @@ -98,16 +61,11 @@ } agp_kern_info; /* - * The agp_memory structure has information - * about the block of agp memory allocated. - * A caller may manipulate the next and prev - * pointers to link each allocated item into - * a list. These pointers are ignored by the - * backend. Everything else should never be - * written to, but the caller may read any of - * the items to detrimine the status of this - * block of agp memory. - * + * The agp_memory structure has information about the block of agp memory + * allocated. A caller may manipulate the next and prev pointers to link + * each allocated item into a list. These pointers are ignored by the backend. + * Everything else should never be written to, but the caller may read any of + * the items to detrimine the status of this block of agp memory. */ typedef struct _agp_memory { @@ -127,126 +85,19 @@ #define AGP_NORMAL_MEMORY 0 extern void agp_free_memory(agp_memory *); - -/* - * agp_free_memory : - * - * This function frees memory associated with - * an agp_memory pointer. It is the only function - * that can be called when the backend is not owned - * by the caller. (So it can free memory on client - * death.) - * - * It takes an agp_memory pointer as an argument. - * - */ - extern agp_memory *agp_allocate_memory(size_t, u32); - -/* - * agp_allocate_memory : - * - * This function allocates a group of pages of - * a certain type. - * - * It takes a size_t argument of the number of pages, and - * an u32 argument of the type of memory to be allocated. - * Every agp bridge device will allow you to allocate - * AGP_NORMAL_MEMORY which maps to physical ram. Any other - * type is device dependent. - * - * It returns NULL whenever memory is unavailable. - * - */ - extern int agp_copy_info(agp_kern_info *); - -/* - * agp_copy_info : - * - * This function copies information about the - * agp bridge device and the state of the agp - * backend into an agp_kern_info pointer. - * - * It takes an agp_kern_info pointer as an - * argument. The caller should insure that - * this pointer is valid. - * - */ - extern int agp_bind_memory(agp_memory *, off_t); - -/* - * agp_bind_memory : - * - * This function binds an agp_memory structure - * into the graphics aperture translation table. - * - * It takes an agp_memory pointer and an offset into - * the graphics aperture translation table as arguments - * - * It returns -EINVAL if the pointer == NULL. - * It returns -EBUSY if the area of the table - * requested is already in use. - * - */ - extern int agp_unbind_memory(agp_memory *); - -/* - * agp_unbind_memory : - * - * This function removes an agp_memory structure - * from the graphics aperture translation table. - * - * It takes an agp_memory pointer as an argument. - * - * It returns -EINVAL if this piece of agp_memory - * is not currently bound to the graphics aperture - * translation table or if the agp_memory - * pointer == NULL - * - */ - extern void agp_enable(u32); - -/* - * agp_enable : - * - * This function initializes the agp point-to-point - * connection. - * - * It takes an agp mode register as an argument - * - */ - extern int agp_backend_acquire(void); - -/* - * agp_backend_acquire : - * - * This Function attempts to acquire the agp - * backend. - * - * returns -EBUSY if agp is in use, - * returns 0 if the caller owns the agp backend - */ - extern void agp_backend_release(void); /* - * agp_backend_release : - * - * This Function releases the lock on the agp - * backend. - * - * The caller must insure that the graphics - * aperture translation table is read for use - * by another entity. (Ensure that all memory - * it bound is unbound.) - * + * Interface between drm and agp code. When agp initializes, it makes + * the below structure available via inter_module_register(), drm might + * use it. Keith Owens 28 Oct 2000. */ - typedef struct { void (*free_memory)(agp_memory *); agp_memory *(*allocate_memory)(size_t, u32); @@ -260,10 +111,4 @@ extern const drm_agp_t *drm_agp_p; -/* - * Interface between drm and agp code. When agp initializes, it makes - * the above structure available via inter_module_register(), drm might - * use it. Keith Owens 28 Oct 2000. - */ - #endif /* _AGP_BACKEND_H */ diff -urN linux-2.5.69-bk6/include/linux/agpgart.h linux-2.5.69-bk7/include/linux/agpgart.h --- linux-2.5.69-bk6/include/linux/agpgart.h 2003-05-04 16:52:49.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/agpgart.h 2003-05-12 04:43:30.000000000 -0700 @@ -27,17 +27,19 @@ #ifndef _AGP_H #define _AGP_H 1 +#include + #define AGPIOC_BASE 'A' -#define AGPIOC_INFO _IOR (AGPIOC_BASE, 0, agp_info*) +#define AGPIOC_INFO _IOR (AGPIOC_BASE, 0, struct agp_info*) #define AGPIOC_ACQUIRE _IO (AGPIOC_BASE, 1) #define AGPIOC_RELEASE _IO (AGPIOC_BASE, 2) -#define AGPIOC_SETUP _IOW (AGPIOC_BASE, 3, agp_setup*) -#define AGPIOC_RESERVE _IOW (AGPIOC_BASE, 4, agp_region*) -#define AGPIOC_PROTECT _IOW (AGPIOC_BASE, 5, agp_region*) -#define AGPIOC_ALLOCATE _IOWR(AGPIOC_BASE, 6, agp_allocate*) +#define AGPIOC_SETUP _IOW (AGPIOC_BASE, 3, struct agp_setup*) +#define AGPIOC_RESERVE _IOW (AGPIOC_BASE, 4, struct agp_region*) +#define AGPIOC_PROTECT _IOW (AGPIOC_BASE, 5, struct agp_region*) +#define AGPIOC_ALLOCATE _IOWR(AGPIOC_BASE, 6, struct agp_allocate*) #define AGPIOC_DEALLOCATE _IOW (AGPIOC_BASE, 7, int) -#define AGPIOC_BIND _IOW (AGPIOC_BASE, 8, agp_bind*) -#define AGPIOC_UNBIND _IOW (AGPIOC_BASE, 9, agp_unbind*) +#define AGPIOC_BIND _IOW (AGPIOC_BASE, 8, struct agp_bind*) +#define AGPIOC_UNBIND _IOW (AGPIOC_BASE, 9, struct agp_unbind*) #define AGP_DEVICE "/dev/agpgart" @@ -112,19 +114,7 @@ #define AGPGART_MINOR 175 -#define AGP_UNLOCK() up(&(agp_fe.agp_mutex)); -#define AGP_LOCK() down(&(agp_fe.agp_mutex)); -#define AGP_LOCK_INIT() sema_init(&(agp_fe.agp_mutex), 1) - -#ifndef _AGP_BACKEND_H -struct _agp_version { - u16 major; - u16 minor; -} agp_version; - -#endif - -typedef struct _agp_info { +struct agp_info { struct agp_version version; /* version of the driver */ u32 bridge_id; /* bridge vendor/device */ u32 agp_mode; /* mode info of bridge */ @@ -133,34 +123,34 @@ size_t pg_total; /* max pages (swap + system) */ size_t pg_system; /* max pages (system) */ size_t pg_used; /* current pages used */ -} agp_info; +}; -typedef struct _agp_setup { +struct agp_setup { u32 agp_mode; /* mode info of bridge */ -} agp_setup; +}; /* * The "prot" down below needs still a "sleep" flag somehow ... */ -typedef struct _agp_segment { +struct agp_segment { off_t pg_start; /* starting page to populate */ size_t pg_count; /* number of pages */ int prot; /* prot flags for mmap */ -} agp_segment; +}; -typedef struct _agp_segment_priv { +struct agp_segment_priv { off_t pg_start; size_t pg_count; pgprot_t prot; -} agp_segment_priv; +}; -typedef struct _agp_region { +struct agp_region { pid_t pid; /* pid of process */ size_t seg_count; /* number of segments */ - struct _agp_segment *seg_list; -} agp_region; + struct agp_segment *seg_list; +}; -typedef struct _agp_allocate { +struct agp_allocate { int key; /* tag of allocation */ size_t pg_count; /* number of pages */ u32 type; /* 0 == normal, other devspec */ @@ -168,34 +158,34 @@ * need a phys address of the * actual page behind the gatt * table) */ -} agp_allocate; +}; -typedef struct _agp_bind { +struct agp_bind { int key; /* tag of allocation */ off_t pg_start; /* starting page to populate */ -} agp_bind; +}; -typedef struct _agp_unbind { +struct agp_unbind { int key; /* tag of allocation */ u32 priority; /* priority for paging out */ -} agp_unbind; +}; -typedef struct _agp_client { - struct _agp_client *next; - struct _agp_client *prev; +struct agp_client { + struct agp_client *next; + struct agp_client *prev; pid_t pid; int num_segments; - agp_segment_priv **segments; -} agp_client; + struct agp_segment_priv **segments; +}; -typedef struct _agp_controller { - struct _agp_controller *next; - struct _agp_controller *prev; +struct agp_controller { + struct agp_controller *next; + struct agp_controller *prev; pid_t pid; int num_clients; agp_memory *pool; - agp_client *clients; -} agp_controller; + struct agp_client *clients; +}; #define AGP_FF_ALLOW_CLIENT 0 #define AGP_FF_ALLOW_CONTROLLER 1 @@ -203,18 +193,18 @@ #define AGP_FF_IS_CONTROLLER 3 #define AGP_FF_IS_VALID 4 -typedef struct _agp_file_private { - struct _agp_file_private *next; - struct _agp_file_private *prev; +struct agp_file_private { + struct agp_file_private *next; + struct agp_file_private *prev; pid_t my_pid; long access_flags; /* long req'd for set_bit --RR */ -} agp_file_private; +}; struct agp_front_data { struct semaphore agp_mutex; - agp_controller *current_controller; - agp_controller *controllers; - agp_file_private *file_priv_list; + struct agp_controller *current_controller; + struct agp_controller *controllers; + struct agp_file_private *file_priv_list; u8 used_by_controller; u8 backend_acquired; }; diff -urN linux-2.5.69-bk6/include/linux/efi.h linux-2.5.69-bk7/include/linux/efi.h --- linux-2.5.69-bk6/include/linux/efi.h 2003-05-04 16:53:41.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/efi.h 2003-05-12 04:43:30.000000000 -0700 @@ -7,7 +7,7 @@ * * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond - * Copyright (C) 1999, 2002 Hewlett-Packard Co. + * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. * David Mosberger-Tang * Stephane Eranian */ @@ -21,12 +21,12 @@ #include #define EFI_SUCCESS 0 -#define EFI_LOAD_ERROR (1L | (1L << 63)) -#define EFI_INVALID_PARAMETER (2L | (1L << 63)) -#define EFI_UNSUPPORTED (3L | (1L << 63)) -#define EFI_BAD_BUFFER_SIZE (4L | (1L << 63)) -#define EFI_BUFFER_TOO_SMALL (5L | (1L << 63)) -#define EFI_NOT_FOUND (14L | (1L << 63)) +#define EFI_LOAD_ERROR ( 1 | (1UL << 63)) +#define EFI_INVALID_PARAMETER ( 2 | (1UL << 63)) +#define EFI_UNSUPPORTED ( 3 | (1UL << 63)) +#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << 63)) +#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << 63)) +#define EFI_NOT_FOUND (14 | (1UL << 63)) typedef unsigned long efi_status_t; typedef u8 efi_bool_t; @@ -260,7 +260,7 @@ extern void efi_init (void); extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); -extern void efi_gettimeofday (struct timeval *tv); +extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); diff -urN linux-2.5.69-bk6/include/linux/pci_ids.h linux-2.5.69-bk7/include/linux/pci_ids.h --- linux-2.5.69-bk6/include/linux/pci_ids.h 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/pci_ids.h 2003-05-12 04:43:30.000000000 -0700 @@ -605,6 +605,7 @@ #define PCI_DEVICE_ID_HP_ZX1_SBA 0x1229 #define PCI_DEVICE_ID_HP_ZX1_IOC 0x122a #define PCI_DEVICE_ID_HP_ZX1_LBA 0x122e +#define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c #define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 #define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 @@ -1007,7 +1008,9 @@ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL 0x017B #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL 0x017C #define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0 +#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4 #define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc +#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2 0x0202 @@ -1902,10 +1905,13 @@ #define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 #define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 #define PCI_DEVICE_ID_INTEL_82865_IG 0x2572 +#define PCI_DEVICE_ID_INTEL_82875_HB 0x2578 +#define PCI_DEVICE_ID_INTEL_82875_IG 0x257b +#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 -#define PCI_DEVICE_ID_INTEL_82855_HB 0x3580 -#define PCI_DEVICE_ID_INTEL_82855_IG 0x3582 +#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 +#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 #define PCI_DEVICE_ID_INTEL_80310 0x530d #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 #define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010 diff -urN linux-2.5.69-bk6/include/linux/sunrpc/xdr.h linux-2.5.69-bk7/include/linux/sunrpc/xdr.h --- linux-2.5.69-bk6/include/linux/sunrpc/xdr.h 2003-05-04 16:53:57.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/sunrpc/xdr.h 2003-05-12 04:43:30.000000000 -0700 @@ -157,6 +157,11 @@ extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int, skb_reader_t *, skb_read_actor_t); +struct socket; +struct sockaddr; +extern int xdr_sendpages(struct socket *, struct sockaddr *, int, + struct xdr_buf *, unsigned int, int); + /* * Provide some simple tools for XDR buffer overflow-checking etc. */ diff -urN linux-2.5.69-bk6/include/linux/sunrpc/xprt.h linux-2.5.69-bk7/include/linux/sunrpc/xprt.h --- linux-2.5.69-bk6/include/linux/sunrpc/xprt.h 2003-05-04 16:53:36.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/sunrpc/xprt.h 2003-05-12 04:43:30.000000000 -0700 @@ -198,7 +198,7 @@ #define XPRT_CONNECT 0 -#define xprt_connected(xp) (!(xp)->stream || test_bit(XPRT_CONNECT, &(xp)->sockstate)) +#define xprt_connected(xp) (test_bit(XPRT_CONNECT, &(xp)->sockstate)) #define xprt_set_connected(xp) (set_bit(XPRT_CONNECT, &(xp)->sockstate)) #define xprt_test_and_set_connected(xp) (test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate)) #define xprt_clear_connected(xp) (clear_bit(XPRT_CONNECT, &(xp)->sockstate)) diff -urN linux-2.5.69-bk6/include/linux/wireless.h linux-2.5.69-bk7/include/linux/wireless.h --- linux-2.5.69-bk6/include/linux/wireless.h 2003-05-04 16:53:33.000000000 -0700 +++ linux-2.5.69-bk7/include/linux/wireless.h 2003-05-12 04:43:30.000000000 -0700 @@ -1,7 +1,7 @@ /* * This file define a set of standard wireless extensions * - * Version : 15 12.7.02 + * Version : 16 2.4.03 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. @@ -69,6 +69,8 @@ /***************************** INCLUDES *****************************/ +/* To minimise problems in user space, I might remove those headers + * at some point. Jean II */ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ @@ -80,7 +82,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 15 +#define WIRELESS_EXT 16 /* * Changes : @@ -163,6 +165,16 @@ * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor + * + * V15 to V16 + * ---------- + * - Increase the number of bitrates in iw_range to 32 (for 802.11g) + * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) + * - Reshuffle struct iw_range for increases, add filler + * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses + * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support + * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" + * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index */ /**************************** CONSTANTS ****************************/ @@ -196,9 +208,11 @@ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ -/* Mobile IP support (statistics per MAC address) */ +/* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ +#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ +#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ @@ -306,13 +320,13 @@ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ -#define IW_MAX_FREQUENCIES 16 +#define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ -#define IW_MAX_BITRATES 8 +#define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 @@ -320,12 +334,11 @@ * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ -#define IW_MAX_SPY 8 /* set */ -#define IW_MAX_GET_SPY 64 /* get */ +#define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ -#define IW_MAX_AP 8 +#define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 @@ -354,7 +367,8 @@ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ +#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ +#define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ @@ -482,6 +496,17 @@ __u32 beacon; /* Missed beacons/superframe */ }; +/* + * Quality range (for spy threshold) + */ +struct iw_thrspy +{ + struct sockaddr addr; /* Source address (hw/mac) */ + struct iw_quality qual; /* Quality of the link */ + struct iw_quality low; /* Low threshold */ + struct iw_quality high; /* High threshold */ +}; + /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) @@ -534,7 +559,7 @@ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ - struct sockaddr addr; /* Destination address (hw) */ + struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ @@ -582,17 +607,31 @@ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ - /* Frequency */ - __u16 num_channels; /* Number of channels [0; num - 1] */ - __u8 num_frequency; /* Number of entry in the list */ - struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ - /* Note : this frequency list doesn't need to fit channel numbers */ + /* Old Frequency (backward compat - moved lower ) */ + __u16 old_num_channels; + __u8 old_num_frequency; + /* Filler to keep "version" at the same offset */ + __s32 old_freq[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ + /* Quality range (link, level, noise) + * If the quality is absolute, it will be in the range [0 ; max_qual], + * if the quality is dBm, it will be in the range [max_qual ; 0]. + * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ + /* This should contain the average/typical values of the quality + * indicator. This should be the threshold between a "good" and + * a "bad" link (example : monitor going from green to orange). + * Currently, user space apps like quality monitors don't have any + * way to calibrate the measurement. With this, they can split + * the range between 0 and max_qual in different quality level + * (using a geometric subdivision centered on the average). + * I expect that people doing the user space apps will feedback + * us on which value we need to put in each driver... */ + struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ @@ -619,6 +658,8 @@ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ + /* For drivers that need a "login/passwd" form */ + __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ @@ -638,18 +679,12 @@ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ - /* Average quality of link & SNR */ - struct iw_quality avg_qual; /* Quality of the link */ - /* This should contain the average/typical values of the quality - * indicator. This should be the threshold between a "good" and - * a "bad" link (example : monitor going from green to orange). - * Currently, user space apps like quality monitors don't have any - * way to calibrate the measurement. With this, they can split - * the range between 0 and max_qual in different quality level - * (using a geometric subdivision centered on the average). - * I expect that people doing the user space apps will feedback - * us on which value we need to put in each driver... - */ + /* Frequency */ + __u16 num_channels; /* Number of channels [0; num - 1] */ + __u8 num_frequency; /* Number of entry in the list */ + struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ + /* Note : this frequency list doesn't need to fit channel numbers, + * because each entry contain its channel index */ }; /* diff -urN linux-2.5.69-bk6/include/net/iw_handler.h linux-2.5.69-bk7/include/net/iw_handler.h --- linux-2.5.69-bk6/include/net/iw_handler.h 2003-05-04 16:53:02.000000000 -0700 +++ linux-2.5.69-bk7/include/net/iw_handler.h 2003-05-12 04:43:30.000000000 -0700 @@ -1,7 +1,7 @@ /* * This file define the new driver API for Wireless Extensions * - * Version : 4 21.6.02 + * Version : 5 4.12.02 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. @@ -206,7 +206,7 @@ * will be needed... * I just plan to increment with each new version. */ -#define IW_HANDLER_VERSION 4 +#define IW_HANDLER_VERSION 5 /* * Changes : @@ -220,10 +220,18 @@ * V3 to V4 * -------- * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes + * + * V4 to V5 + * -------- + * - Add new spy support : struct iw_spy_data & prototypes */ /**************************** CONSTANTS ****************************/ +/* Enable enhanced spy support. Disable to reduce footprint */ +#define IW_WIRELESS_SPY +#define IW_WIRELESS_THRSPY + /* Special error message for the driver to indicate that we * should do a commit after return from the iw_handler */ #define EIWCOMMIT EINPROGRESS @@ -315,6 +323,9 @@ * We will automatically export that to user space... */ struct iw_priv_args * private_args; + /* Driver enhanced spy support */ + long spy_offset; /* Spy data offset */ + /* In the long term, get_wireless_stats will move from * 'struct net_device' to here, to minimise bloat. */ }; @@ -350,6 +361,33 @@ /* Need to think of short header translation table. Later. */ +/* --------------------- ENHANCED SPY SUPPORT --------------------- */ +/* + * In the old days, the driver was handling spy support all by itself. + * Now, the driver can delegate this task to Wireless Extensions. + * It needs to include this struct in its private part and use the + * standard spy iw_handler. + */ + +/* + * Instance specific spy data, i.e. addresses spied and quality for them. + */ +struct iw_spy_data +{ +#ifdef IW_WIRELESS_SPY + /* --- Standard spy support --- */ + int spy_number; + u_char spy_address[IW_MAX_SPY][ETH_ALEN]; + struct iw_quality spy_stat[IW_MAX_SPY]; +#ifdef IW_WIRELESS_THRSPY + /* --- Enhanced spy support (event) */ + struct iw_quality spy_thr_low; /* Low threshold */ + struct iw_quality spy_thr_high; /* High threshold */ + u_char spy_thr_under[IW_MAX_SPY]; +#endif /* IW_WIRELESS_THRSPY */ +#endif /* IW_WIRELESS_SPY */ +}; + /**************************** PROTOTYPES ****************************/ /* * Functions part of the Wireless Extensions (defined in net/core/wireless.c). @@ -376,6 +414,31 @@ /* We may need a function to send a stream of events to user space. * More on that later... */ +/* Standard handler for SIOCSIWSPY */ +extern int iw_handler_set_spy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra); +/* Standard handler for SIOCGIWSPY */ +extern int iw_handler_get_spy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra); +/* Standard handler for SIOCSIWTHRSPY */ +extern int iw_handler_set_thrspy(struct net_device * dev, + struct iw_request_info *info, + union iwreq_data * wrqu, + char * extra); +/* Standard handler for SIOCGIWTHRSPY */ +extern int iw_handler_get_thrspy(struct net_device * dev, + struct iw_request_info *info, + union iwreq_data * wrqu, + char * extra); +/* Driver call to update spy records */ +extern void wireless_spy_update(struct net_device * dev, + unsigned char * address, + struct iw_quality * wstats); + /************************* INLINE FUNTIONS *************************/ /* * Function that are so simple that it's more efficient inlining them diff -urN linux-2.5.69-bk6/mm/page-writeback.c linux-2.5.69-bk7/mm/page-writeback.c --- linux-2.5.69-bk6/mm/page-writeback.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/mm/page-writeback.c 2003-05-12 04:43:30.000000000 -0700 @@ -270,7 +270,7 @@ struct page_state ps; get_page_state(&ps); - nr_pages = ps.nr_dirty; + nr_pages = ps.nr_dirty + ps.nr_unstable; } return pdflush_operation(background_writeout, nr_pages); } diff -urN linux-2.5.69-bk6/net/core/wireless.c linux-2.5.69-bk7/net/core/wireless.c --- linux-2.5.69-bk6/net/core/wireless.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/net/core/wireless.c 2003-05-12 04:43:31.000000000 -0700 @@ -2,7 +2,7 @@ * This file implement the Wireless Extensions APIs. * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) */ @@ -43,6 +43,11 @@ * o Turn on WE_STRICT_WRITE by default + kernel warning * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) * o Fix off-by-one in test (extra_size <= IFNAMSIZ) + * + * v6 - 9.01.03 - Jean II + * o Add common spy support : iw_handler_set_spy(), wireless_spy_update() + * o Add enhanced spy support : iw_handler_set_thrspy() and event. + * o Add WIRELESS_EXT version display in /proc/net/wireless */ /***************************** INCLUDES *****************************/ @@ -53,9 +58,10 @@ #include #include /* rtnetlink stuff */ #include -#include /* Pretty obvious */ #include /* for __init */ +#include /* ARPHRD_ETHER */ +#include /* Pretty obvious */ #include /* New driver API */ #include /* copy_to_user() */ @@ -69,6 +75,7 @@ /* Debugging stuff */ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ +#undef WE_SPY_DEBUG /* Debug enhanced spy support */ /* Options */ #define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ @@ -76,7 +83,7 @@ /************************* GLOBAL VARIABLES *************************/ /* - * You should not use global variables, because or re-entrancy. + * You should not use global variables, because of re-entrancy. * On our case, it's only const, so it's OK... */ /* @@ -152,7 +159,19 @@ .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), - .max_tokens = IW_MAX_GET_SPY, + .max_tokens = IW_MAX_SPY, + }, + [SIOCSIWTHRSPY - SIOCIWFIRST] = { + .header_type = IW_HEADER_TYPE_POINT, + .token_size = sizeof(struct iw_thrspy), + .min_tokens = 1, + .max_tokens = 1, + }, + [SIOCGIWTHRSPY - SIOCIWFIRST] = { + .header_type = IW_HEADER_TYPE_POINT, + .token_size = sizeof(struct iw_thrspy), + .min_tokens = 1, + .max_tokens = 1, }, [SIOCSIWAP - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, @@ -440,9 +459,10 @@ { if (v == (void *)1) seq_printf(seq, "Inter-| sta-| Quality | Discarded " - "packets | Missed\n" + "packets | Missed | WE\n" " face | tus | link level noise | nwid " - "crypt frag retry misc | beacon\n"); + "crypt frag retry misc | beacon | %d\n", + WIRELESS_EXT); else wireless_seq_printf_stats(seq, v); return 0; @@ -1100,3 +1120,252 @@ return; /* Always success, I guess ;-) */ } + +/********************** ENHANCED IWSPY SUPPORT **********************/ +/* + * In the old days, the driver was handling spy support all by itself. + * Now, the driver can delegate this task to Wireless Extensions. + * It needs to use those standard spy iw_handler in struct iw_handler_def, + * push data to us via wireless_spy_update() and include struct iw_spy_data + * in its private part (and advertise it in iw_handler_def->spy_offset). + * One of the main advantage of centralising spy support here is that + * it becomes much easier to improve and extend it without having to touch + * the drivers. One example is the addition of the Spy-Threshold events. + * Note : IW_WIRELESS_SPY is defined in iw_handler.h + */ + +/*------------------------------------------------------------------*/ +/* + * Standard Wireless Handler : set Spy List + */ +int iw_handler_set_spy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ +#ifdef IW_WIRELESS_SPY + struct iw_spy_data * spydata = (dev->priv + + dev->wireless_handlers->spy_offset); + struct sockaddr * address = (struct sockaddr *) extra; + + /* Disable spy collection while we copy the addresses. + * As we don't disable interrupts, we need to do this to avoid races. + * As we are the only writer, this is good enough. */ + spydata->spy_number = 0; + + /* Are there are addresses to copy? */ + if(wrqu->data.length > 0) { + int i; + + /* Copy addresses */ + for(i = 0; i < wrqu->data.length; i++) + memcpy(spydata->spy_address[i], address[i].sa_data, + ETH_ALEN); + /* Reset stats */ + memset(spydata->spy_stat, 0, + sizeof(struct iw_quality) * IW_MAX_SPY); + +#ifdef WE_SPY_DEBUG + printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length); + for (i = 0; i < wrqu->data.length; i++) + printk(KERN_DEBUG + "%02X:%02X:%02X:%02X:%02X:%02X \n", + spydata->spy_address[i][0], + spydata->spy_address[i][1], + spydata->spy_address[i][2], + spydata->spy_address[i][3], + spydata->spy_address[i][4], + spydata->spy_address[i][5]); +#endif /* WE_SPY_DEBUG */ + } + /* Enable addresses */ + spydata->spy_number = wrqu->data.length; + + return 0; +#else /* IW_WIRELESS_SPY */ + return -EOPNOTSUPP; +#endif /* IW_WIRELESS_SPY */ +} + +/*------------------------------------------------------------------*/ +/* + * Standard Wireless Handler : get Spy List + */ +int iw_handler_get_spy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) +{ +#ifdef IW_WIRELESS_SPY + struct iw_spy_data * spydata = (dev->priv + + dev->wireless_handlers->spy_offset); + struct sockaddr * address = (struct sockaddr *) extra; + int i; + + wrqu->data.length = spydata->spy_number; + + /* Copy addresses. */ + for(i = 0; i < spydata->spy_number; i++) { + memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN); + address[i].sa_family = AF_UNIX; + } + /* Copy stats to the user buffer (just after). */ + if(spydata->spy_number > 0) + memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number), + spydata->spy_stat, + sizeof(struct iw_quality) * spydata->spy_number); + /* Reset updated flags. */ + for(i = 0; i < spydata->spy_number; i++) + spydata->spy_stat[i].updated = 0; + return 0; +#else /* IW_WIRELESS_SPY */ + return -EOPNOTSUPP; +#endif /* IW_WIRELESS_SPY */ +} + +/*------------------------------------------------------------------*/ +/* + * Standard Wireless Handler : set spy threshold + */ +int iw_handler_set_thrspy(struct net_device * dev, + struct iw_request_info *info, + union iwreq_data * wrqu, + char * extra) +{ +#ifdef IW_WIRELESS_THRSPY + struct iw_spy_data * spydata = (dev->priv + + dev->wireless_handlers->spy_offset); + struct iw_thrspy * threshold = (struct iw_thrspy *) extra; + + /* Just do it */ + memcpy(&(spydata->spy_thr_low), &(threshold->low), + 2 * sizeof(struct iw_quality)); + + /* Clear flag */ + memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); + +#ifdef WE_SPY_DEBUG + printk(KERN_DEBUG "iw_handler_set_thrspy() : low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level); +#endif /* WE_SPY_DEBUG */ + + return 0; +#else /* IW_WIRELESS_THRSPY */ + return -EOPNOTSUPP; +#endif /* IW_WIRELESS_THRSPY */ +} + +/*------------------------------------------------------------------*/ +/* + * Standard Wireless Handler : get spy threshold + */ +int iw_handler_get_thrspy(struct net_device * dev, + struct iw_request_info *info, + union iwreq_data * wrqu, + char * extra) +{ +#ifdef IW_WIRELESS_THRSPY + struct iw_spy_data * spydata = (dev->priv + + dev->wireless_handlers->spy_offset); + struct iw_thrspy * threshold = (struct iw_thrspy *) extra; + + /* Just do it */ + memcpy(&(threshold->low), &(spydata->spy_thr_low), + 2 * sizeof(struct iw_quality)); + + return 0; +#else /* IW_WIRELESS_THRSPY */ + return -EOPNOTSUPP; +#endif /* IW_WIRELESS_THRSPY */ +} + +#ifdef IW_WIRELESS_THRSPY +/*------------------------------------------------------------------*/ +/* + * Prepare and send a Spy Threshold event + */ +static void iw_send_thrspy_event(struct net_device * dev, + struct iw_spy_data * spydata, + unsigned char * address, + struct iw_quality * wstats) +{ + union iwreq_data wrqu; + struct iw_thrspy threshold; + + /* Init */ + wrqu.data.length = 1; + wrqu.data.flags = 0; + /* Copy address */ + memcpy(threshold.addr.sa_data, address, ETH_ALEN); + threshold.addr.sa_family = ARPHRD_ETHER; + /* Copy stats */ + memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); + /* Copy also thresholds */ + memcpy(&(threshold.low), &(spydata->spy_thr_low), + 2 * sizeof(struct iw_quality)); + +#ifdef WE_SPY_DEBUG + printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n", + threshold.addr.sa_data[0], + threshold.addr.sa_data[1], + threshold.addr.sa_data[2], + threshold.addr.sa_data[3], + threshold.addr.sa_data[4], + threshold.addr.sa_data[5], threshold.qual.level); +#endif /* WE_SPY_DEBUG */ + + /* Send event to user space */ + wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); +} +#endif /* IW_WIRELESS_THRSPY */ + +/* ---------------------------------------------------------------- */ +/* + * Call for the driver to update the spy data. + * For now, the spy data is a simple array. As the size of the array is + * small, this is good enough. If we wanted to support larger number of + * spy addresses, we should use something more efficient... + */ +void wireless_spy_update(struct net_device * dev, + unsigned char * address, + struct iw_quality * wstats) +{ +#ifdef IW_WIRELESS_SPY + struct iw_spy_data * spydata = (dev->priv + + dev->wireless_handlers->spy_offset); + int i; + int match = -1; + +#ifdef WE_SPY_DEBUG + printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]); +#endif /* WE_SPY_DEBUG */ + + /* Update all records that match */ + for(i = 0; i < spydata->spy_number; i++) + if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) { + memcpy(&(spydata->spy_stat[i]), wstats, + sizeof(struct iw_quality)); + match = i; + } +#ifdef IW_WIRELESS_THRSPY + /* Generate an event if we cross the spy threshold. + * To avoid event storms, we have a simple hysteresis : we generate + * event only when we go under the low threshold or above the + * high threshold. */ + if(match >= 0) { + if(spydata->spy_thr_under[match]) { + if(wstats->level > spydata->spy_thr_high.level) { + spydata->spy_thr_under[match] = 0; + iw_send_thrspy_event(dev, spydata, + address, wstats); + } + } else { + if(wstats->level < spydata->spy_thr_low.level) { + spydata->spy_thr_under[match] = 1; + iw_send_thrspy_event(dev, spydata, + address, wstats); + } + } + } +#endif /* IW_WIRELESS_THRSPY */ +#endif /* IW_WIRELESS_SPY */ +} diff -urN linux-2.5.69-bk6/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.5.69-bk7/net/ipv4/netfilter/ip_fw_compat_masq.c --- linux-2.5.69-bk6/net/ipv4/netfilter/ip_fw_compat_masq.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/net/ipv4/netfilter/ip_fw_compat_masq.c 2003-05-12 04:43:31.000000000 -0700 @@ -35,16 +35,15 @@ unsigned int do_masquerade(struct sk_buff **pskb, const struct net_device *dev) { - struct iphdr *iph = (*pskb)->nh.iph; struct ip_nat_info *info; enum ip_conntrack_info ctinfo; struct ip_conntrack *ct; unsigned int ret; /* Sorry, only ICMP, TCP and UDP. */ - if (iph->protocol != IPPROTO_ICMP - && iph->protocol != IPPROTO_TCP - && iph->protocol != IPPROTO_UDP) + if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP + && (*pskb)->nh.iph->protocol != IPPROTO_TCP + && (*pskb)->nh.iph->protocol != IPPROTO_UDP) return NF_DROP; /* Feed it to connection tracking; in fact we're in NF_IP_FORWARD, @@ -68,7 +67,7 @@ /* Setup the masquerade, if not already */ if (!info->initialized) { u_int32_t newsrc; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->daddr } } }; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = (*pskb)->nh.iph->daddr } } }; struct rtable *rt; struct ip_nat_multi_range range; @@ -124,19 +123,18 @@ check_for_demasq(struct sk_buff **pskb) { struct ip_conntrack_tuple tuple; - struct iphdr *iph = (*pskb)->nh.iph; struct ip_conntrack_protocol *protocol; struct ip_conntrack_tuple_hash *h; enum ip_conntrack_info ctinfo; struct ip_conntrack *ct; int ret; - protocol = ip_ct_find_proto(iph->protocol); + protocol = ip_ct_find_proto((*pskb)->nh.iph->protocol); /* We don't feed packets to conntrack system unless we know they're part of an connection already established by an explicit masq command. */ - switch (iph->protocol) { + switch ((*pskb)->nh.iph->protocol) { case IPPROTO_ICMP: /* ICMP errors. */ ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING); @@ -146,12 +144,6 @@ server here (== DNAT). Do SNAT icmp manips in POST_ROUTING handling. */ if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { - /* FIXME: Remove once NAT handled non-linear. - */ - if (skb_is_nonlinear(*pskb) - && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - icmp_reply_translation(pskb, ct, NF_IP_PRE_ROUTING, CTINFO2DIR(ctinfo)); @@ -166,7 +158,7 @@ case IPPROTO_UDP: IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0); - if (!get_tuple(iph, *pskb, iph->ihl*4, &tuple, protocol)) { + if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) { if (net_ratelimit()) printk("ip_fw_compat_masq: Can't get tuple\n"); return NF_ACCEPT; diff -urN linux-2.5.69-bk6/net/ipv4/netfilter/ip_nat_core.c linux-2.5.69-bk7/net/ipv4/netfilter/ip_nat_core.c --- linux-2.5.69-bk6/net/ipv4/netfilter/ip_nat_core.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/net/ipv4/netfilter/ip_nat_core.c 2003-05-12 04:43:31.000000000 -0700 @@ -717,10 +717,13 @@ iph = (void *)(*pskb)->data + iphdroff; /* Manipulate protcol part. */ - if (!find_nat_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4, + if (!find_nat_proto(proto)->manip_pkt(pskb, + iphdroff + iph->ihl*4, manip, maniptype)) return 0; + iph = (void *)(*pskb)->data + iphdroff; + if (maniptype == IP_NAT_MANIP_SRC) { iph->check = ip_nat_cheat_check(~iph->saddr, manip->ip, iph->check); @@ -953,6 +956,8 @@ hdrlen = (*pskb)->nh.iph->ihl * 4; + inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; + inside->icmp.checksum = 0; inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen, (*pskb)->len - hdrlen, diff -urN linux-2.5.69-bk6/net/ipv4/protocol.c linux-2.5.69-bk7/net/ipv4/protocol.c --- linux-2.5.69-bk6/net/ipv4/protocol.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/net/ipv4/protocol.c 2003-05-12 04:43:31.000000000 -0700 @@ -91,6 +91,7 @@ } spin_unlock_bh(&inet_proto_lock); + synchronize_net(); return ret; } diff -urN linux-2.5.69-bk6/net/ipv6/protocol.c linux-2.5.69-bk7/net/ipv6/protocol.c --- linux-2.5.69-bk6/net/ipv6/protocol.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/net/ipv6/protocol.c 2003-05-12 04:43:31.000000000 -0700 @@ -80,5 +80,7 @@ spin_unlock_bh(&inet6_proto_lock); + synchronize_net(); + return ret; } diff -urN linux-2.5.69-bk6/net/ipv6/udp.c linux-2.5.69-bk7/net/ipv6/udp.c --- linux-2.5.69-bk6/net/ipv6/udp.c 2003-05-04 16:53:37.000000000 -0700 +++ linux-2.5.69-bk7/net/ipv6/udp.c 2003-05-12 04:43:31.000000000 -0700 @@ -575,7 +575,7 @@ for(; s; s = s->next) { struct inet_opt *inet = inet_sk(s); - if (inet->num == num) { + if (inet->num == num && sk->family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(s); if (inet->dport) { if (inet->dport != rmt_port) diff -urN linux-2.5.69-bk6/net/netsyms.c linux-2.5.69-bk7/net/netsyms.c --- linux-2.5.69-bk6/net/netsyms.c 2003-05-12 04:43:26.000000000 -0700 +++ linux-2.5.69-bk7/net/netsyms.c 2003-05-12 04:43:31.000000000 -0700 @@ -666,10 +666,13 @@ EXPORT_SYMBOL(softnet_data); #ifdef CONFIG_NET_RADIO -/* Don't include the whole header mess for a single function */ -union iwreq_data; -extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra); +#include /* Wireless Extensions driver API */ EXPORT_SYMBOL(wireless_send_event); +EXPORT_SYMBOL(iw_handler_set_spy); +EXPORT_SYMBOL(iw_handler_get_spy); +EXPORT_SYMBOL(iw_handler_set_thrspy); +EXPORT_SYMBOL(iw_handler_get_thrspy); +EXPORT_SYMBOL(wireless_spy_update); #endif /* CONFIG_NET_RADIO */ EXPORT_SYMBOL(linkwatch_fire_event); diff -urN linux-2.5.69-bk6/net/sunrpc/clnt.c linux-2.5.69-bk7/net/sunrpc/clnt.c --- linux-2.5.69-bk6/net/sunrpc/clnt.c 2003-05-04 16:53:13.000000000 -0700 +++ linux-2.5.69-bk7/net/sunrpc/clnt.c 2003-05-12 04:43:31.000000000 -0700 @@ -57,8 +57,7 @@ static void call_refreshresult(struct rpc_task *task); static void call_timeout(struct rpc_task *task); static void call_connect(struct rpc_task *task); -static void child_connect(struct rpc_task *task); -static void child_connect_status(struct rpc_task *task); +static void call_connect_status(struct rpc_task *task); static u32 * call_header(struct rpc_task *task); static u32 * call_verify(struct rpc_task *task); @@ -602,40 +601,48 @@ call_connect(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; - struct rpc_task *child; dprintk("RPC: %4d call_connect status %d\n", task->tk_pid, task->tk_status); - task->tk_action = call_transmit; - if (task->tk_status < 0 || !clnt->cl_xprt->stream) + if (xprt_connected(clnt->cl_xprt)) { + task->tk_action = call_transmit; return; - - /* Run as a child to ensure it runs as an rpciod task. Rpciod - * guarantees we have the correct capabilities for socket bind - * to succeed. */ - child = rpc_new_child(clnt, task); - if (child) { - child->tk_action = child_connect; - rpc_run_child(task, child, NULL); } + task->tk_action = call_connect_status; + if (task->tk_status < 0) + return; + xprt_connect(task); } +/* + * 4b. Sort out connect result + */ static void -child_connect(struct rpc_task *task) +call_connect_status(struct rpc_task *task) { + struct rpc_clnt *clnt = task->tk_client; + int status = task->tk_status; + task->tk_status = 0; - task->tk_action = child_connect_status; - xprt_connect(task); -} + if (status >= 0) { + clnt->cl_stats->netreconn++; + task->tk_action = call_transmit; + return; + } -static void -child_connect_status(struct rpc_task *task) -{ - if (task->tk_status == -EAGAIN) - task->tk_action = child_connect; - else - task->tk_action = NULL; + /* Something failed: we may have to rebind */ + if (clnt->cl_autobind) + clnt->cl_port = 0; + switch (status) { + case -ENOTCONN: + case -ETIMEDOUT: + case -EAGAIN: + task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect; + break; + default: + rpc_exit(task, -EIO); + } } /* @@ -696,6 +703,7 @@ break; case -ECONNREFUSED: case -ENOTCONN: + req->rq_bytes_sent = 0; if (clnt->cl_autobind) clnt->cl_port = 0; task->tk_action = call_bind; diff -urN linux-2.5.69-bk6/net/sunrpc/sched.c linux-2.5.69-bk7/net/sunrpc/sched.c --- linux-2.5.69-bk6/net/sunrpc/sched.c 2003-05-04 16:53:31.000000000 -0700 +++ linux-2.5.69-bk7/net/sunrpc/sched.c 2003-05-12 04:43:31.000000000 -0700 @@ -1110,9 +1110,10 @@ alltask_for_each(t, le, &all_tasks) printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n", t->tk_pid, - (t->tk_msg.rpc_proc->p_proc ? t->tk_msg.rpc_proc->p_proc : -1), + (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), t->tk_flags, t->tk_status, - t->tk_client, t->tk_client->cl_prog, + t->tk_client, + (t->tk_client ? t->tk_client->cl_prog : 0), t->tk_rqstp, t->tk_timeout, rpc_qname(t->tk_rpcwait), t->tk_action, t->tk_exit); diff -urN linux-2.5.69-bk6/net/sunrpc/xdr.c linux-2.5.69-bk7/net/sunrpc/xdr.c --- linux-2.5.69-bk6/net/sunrpc/xdr.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk7/net/sunrpc/xdr.c 2003-05-12 04:43:31.000000000 -0700 @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -314,8 +316,113 @@ } while ((pglen -= len) != 0); copy_tail: len = xdr->tail[0].iov_len; - if (len) - copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len); + if (base < len) + copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base); +} + + +int +xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, + struct xdr_buf *xdr, unsigned int base, int msgflags) +{ + struct page **ppage = xdr->pages; + unsigned int len, pglen = xdr->page_len; + int err, ret = 0; + ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); + mm_segment_t oldfs; + + len = xdr->head[0].iov_len; + if (base < len || (addr != NULL && base == 0)) { + struct iovec iov = { + .iov_base = xdr->head[0].iov_base + base, + .iov_len = len - base, + }; + struct msghdr msg = { + .msg_name = addr, + .msg_namelen = addrlen, + .msg_flags = msgflags, + }; + + if (iov.iov_len != 0) { + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + } + if (xdr->len > len) + msg.msg_flags |= MSG_MORE; + oldfs = get_fs(); set_fs(get_ds()); + err = sock_sendmsg(sock, &msg, iov.iov_len); + set_fs(oldfs); + if (ret == 0) + ret = err; + else if (err > 0) + ret += err; + if (err != iov.iov_len) + goto out; + base = 0; + } else + base -= len; + + if (pglen == 0) + goto copy_tail; + if (base >= pglen) { + base -= pglen; + goto copy_tail; + } + if (base || xdr->page_base) { + pglen -= base; + base += xdr->page_base; + ppage += base >> PAGE_CACHE_SHIFT; + base &= ~PAGE_CACHE_MASK; + } + + sendpage = sock->ops->sendpage ? : sock_no_sendpage; + do { + int flags = msgflags; + + len = PAGE_CACHE_SIZE; + if (base) + len -= base; + if (pglen < len) + len = pglen; + + if (pglen != len || xdr->tail[0].iov_len != 0) + flags |= MSG_MORE; + + /* Hmm... We might be dealing with highmem pages */ + if (PageHighMem(*ppage)) + sendpage = sock_no_sendpage; + err = sendpage(sock, *ppage, base, len, flags); + if (ret == 0) + ret = err; + else if (err > 0) + ret += err; + if (err != len) + goto out; + base = 0; + ppage++; + } while ((pglen -= len) != 0); +copy_tail: + len = xdr->tail[0].iov_len; + if (base < len) { + struct iovec iov = { + .iov_base = xdr->tail[0].iov_base + base, + .iov_len = len - base, + }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_flags = msgflags, + }; + oldfs = get_fs(); set_fs(get_ds()); + err = sock_sendmsg(sock, &msg, iov.iov_len); + set_fs(oldfs); + if (ret == 0) + ret = err; + else if (err > 0) + ret += err; + } +out: + return ret; } diff -urN linux-2.5.69-bk6/net/sunrpc/xprt.c linux-2.5.69-bk7/net/sunrpc/xprt.c --- linux-2.5.69-bk6/net/sunrpc/xprt.c 2003-05-04 16:53:35.000000000 -0700 +++ linux-2.5.69-bk7/net/sunrpc/xprt.c 2003-05-12 04:43:31.000000000 -0700 @@ -85,7 +85,7 @@ static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); static inline void do_xprt_reserve(struct rpc_task *); static void xprt_disconnect(struct rpc_xprt *); -static void xprt_conn_status(struct rpc_task *task); +static void xprt_connect_status(struct rpc_task *task); static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to); static struct socket *xprt_create_socket(int, struct rpc_timeout *, int); @@ -213,11 +213,10 @@ xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req) { struct socket *sock = xprt->sock; - struct msghdr msg; struct xdr_buf *xdr = &req->rq_snd_buf; - struct iovec niv[MAX_IOVEC]; - unsigned int niov, slen, skip; - mm_segment_t oldfs; + struct sockaddr *addr = NULL; + int addrlen = 0; + unsigned int skip; int result; if (!sock) @@ -227,27 +226,18 @@ req->rq_svec->iov_base, req->rq_svec->iov_len); + /* For UDP, we need to provide an address */ + if (!xprt->stream) { + addr = (struct sockaddr *) &xprt->addr; + addrlen = sizeof(xprt->addr); + } /* Dont repeat bytes */ skip = req->rq_bytes_sent; - slen = xdr->len - skip; - niov = xdr_kmap(niv, xdr, skip); - - msg.msg_flags = MSG_DONTWAIT|MSG_NOSIGNAL; - msg.msg_iov = niv; - msg.msg_iovlen = niov; - msg.msg_name = (struct sockaddr *) &xprt->addr; - msg.msg_namelen = sizeof(xprt->addr); - msg.msg_control = NULL; - msg.msg_controllen = 0; - oldfs = get_fs(); set_fs(get_ds()); clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); - result = sock_sendmsg(sock, &msg, slen); - set_fs(oldfs); + result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT); - xdr_kunmap(xdr, skip); - - dprintk("RPC: xprt_sendmsg(%d) = %d\n", slen, result); + dprintk("RPC: xprt_sendmsg(%d) = %d\n", xdr->len - skip, result); if (result >= 0) return result; @@ -259,6 +249,7 @@ */ case -EAGAIN: break; + case -ECONNRESET: case -ENOTCONN: case -EPIPE: /* connection broken */ @@ -376,6 +367,7 @@ if (!sk) return; + write_lock_bh(&sk->callback_lock); xprt->inet = NULL; xprt->sock = NULL; @@ -383,6 +375,7 @@ sk->data_ready = xprt->old_data_ready; sk->state_change = xprt->old_state_change; sk->write_space = xprt->old_write_space; + write_unlock_bh(&sk->callback_lock); xprt_disconnect(xprt); sk->no_check = 0; @@ -397,14 +390,15 @@ xprt_disconnect(struct rpc_xprt *xprt) { dprintk("RPC: disconnected transport %p\n", xprt); + spin_lock_bh(&xprt->sock_lock); xprt_clear_connected(xprt); rpc_wake_up_status(&xprt->pending, -ENOTCONN); + spin_unlock_bh(&xprt->sock_lock); } /* * Attempt to connect a TCP socket. * - * NB: This never collides with TCP reads, as both run from rpciod */ void xprt_connect(struct rpc_task *task) @@ -442,6 +436,10 @@ goto out_write; } xprt_bind_socket(xprt, sock); + + if (!xprt->stream) + goto out_write; + inet = sock->sk; /* @@ -452,6 +450,9 @@ dprintk("RPC: %4d connect status %d connected %d sock state %d\n", task->tk_pid, -status, xprt_connected(xprt), inet->state); + if (status >= 0) + return; + switch (status) { case -EINPROGRESS: case -EALREADY: @@ -464,53 +465,37 @@ /* if the socket is already closing, delay briefly */ if ((1 << inet->state) & ~(TCPF_SYN_SENT|TCPF_SYN_RECV)) task->tk_timeout = RPC_REESTABLISH_TIMEOUT; - rpc_sleep_on(&xprt->pending, task, xprt_conn_status, + rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL); - release_sock(inet); - /* task status set when task wakes up again */ - return; } release_sock(inet); - task->tk_status = 0; break; - - case 0: - case -EISCONN: /* not likely, but just in case */ - /* Half closed state. No race -- this socket is dead. */ - if (inet->state != TCP_ESTABLISHED) { - xprt_close(xprt); - task->tk_status = -EAGAIN; - goto out_write; + case -ECONNREFUSED: + case -ECONNRESET: + case -ENOTCONN: + if (!task->tk_client->cl_softrtry) { + rpc_delay(task, RPC_REESTABLISH_TIMEOUT); + task->tk_status = -ENOTCONN; + break; } - - /* Otherwise, the connection is already established. */ - task->tk_status = 0; - break; - - case -EPIPE: - xprt_close(xprt); - task->tk_status = -ENOTCONN; - goto out_write; - default: /* Report myriad other possible returns. If this file * system is soft mounted, just error out, like Solaris. */ - xprt_close(xprt); if (task->tk_client->cl_softrtry) { printk(KERN_WARNING "RPC: error %d connecting to server %s, exiting\n", -status, task->tk_client->cl_server); task->tk_status = -EIO; - } else { - printk(KERN_WARNING - "RPC: error %d connecting to server %s\n", - -status, task->tk_client->cl_server); - rpc_delay(task, RPC_REESTABLISH_TIMEOUT); - task->tk_status = status; + goto out_write; } + printk(KERN_WARNING "RPC: error %d connecting to server %s\n", + -status, task->tk_client->cl_server); + /* This will prevent anybody else from reconnecting */ + rpc_delay(task, RPC_REESTABLISH_TIMEOUT); + task->tk_status = status; break; } - + return; out_write: xprt_release_write(xprt, task); } @@ -519,33 +504,32 @@ * We arrive here when awoken from waiting on connection establishment. */ static void -xprt_conn_status(struct rpc_task *task) +xprt_connect_status(struct rpc_task *task) { struct rpc_xprt *xprt = task->tk_xprt; - switch (task->tk_status) { - case 0: - dprintk("RPC: %4d xprt_conn_status: connection established\n", + if (task->tk_status >= 0) { + dprintk("RPC: %4d xprt_connect_status: connection established\n", task->tk_pid); - goto out; + return; + } + + /* if soft mounted, just cause this RPC to fail */ + if (task->tk_client->cl_softrtry) + task->tk_status = -EIO; + + switch (task->tk_status) { + case -ENOTCONN: + rpc_delay(task, RPC_REESTABLISH_TIMEOUT); + return; case -ETIMEDOUT: - dprintk("RPC: %4d xprt_conn_status: timed out\n", + dprintk("RPC: %4d xprt_connect_status: timed out\n", task->tk_pid); - /* prevent TCP from continuing to retry SYNs */ - xprt_close(xprt); break; default: printk(KERN_ERR "RPC: error %d connecting to server %s\n", -task->tk_status, task->tk_client->cl_server); - xprt_close(xprt); - rpc_delay(task, RPC_REESTABLISH_TIMEOUT); - break; } - /* if soft mounted, cause this RPC to fail */ - if (task->tk_client->cl_softrtry) - task->tk_status = -EIO; - - out: xprt_release_write(xprt, task); } @@ -695,6 +679,7 @@ struct sk_buff *skb; int err, repsize, copied; + read_lock(&sk->callback_lock); dprintk("RPC: udp_data_ready...\n"); if (!(xprt = xprt_from_sock(sk))) { printk("RPC: udp_data_ready request not found!\n"); @@ -745,6 +730,7 @@ out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); + read_unlock(&sk->callback_lock); } /* @@ -939,7 +925,7 @@ } /* Skip over any trailing bytes on short reads */ tcp_read_discard(xprt, &desc); - } while (desc.count && xprt_connected(xprt)); + } while (desc.count); dprintk("RPC: tcp_data_recv done\n"); return len - desc.count; } @@ -949,18 +935,21 @@ struct rpc_xprt *xprt; read_descriptor_t rd_desc; + read_lock(&sk->callback_lock); dprintk("RPC: tcp_data_ready...\n"); if (!(xprt = xprt_from_sock(sk))) { printk("RPC: tcp_data_ready socket info not found!\n"); - return; + goto out; } if (xprt->shutdown) - return; + goto out; /* We use rd_desc to pass struct xprt to tcp_data_recv */ rd_desc.buf = (char *)xprt; rd_desc.count = 65536; tcp_read_sock(sk, &rd_desc, tcp_data_recv); +out: + read_unlock(&sk->callback_lock); } static void @@ -968,6 +957,7 @@ { struct rpc_xprt *xprt; + read_lock(&sk->callback_lock); if (!(xprt = xprt_from_sock(sk))) goto out; dprintk("RPC: tcp_state_change client %p...\n", xprt); @@ -977,19 +967,19 @@ switch (sk->state) { case TCP_ESTABLISHED: - if (xprt_test_and_set_connected(xprt)) - break; + spin_lock_bh(&xprt->sock_lock); + if (!xprt_test_and_set_connected(xprt)) { + /* Reset TCP record info */ + xprt->tcp_offset = 0; + xprt->tcp_reclen = 0; + xprt->tcp_copied = 0; + xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID; - /* Reset TCP record info */ - xprt->tcp_offset = 0; - xprt->tcp_reclen = 0; - xprt->tcp_copied = 0; - xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID; - - spin_lock(&xprt->sock_lock); - if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending) - rpc_wake_up_task(xprt->snd_task); - spin_unlock(&xprt->sock_lock); + if (xprt->snd_task) + rpc_wake_up_task(xprt->snd_task); + rpc_wake_up(&xprt->pending); + } + spin_unlock_bh(&xprt->sock_lock); break; case TCP_SYN_SENT: case TCP_SYN_RECV: @@ -1001,6 +991,7 @@ out: if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible_all(sk->sleep); + read_unlock(&sk->callback_lock); } /* @@ -1015,24 +1006,25 @@ struct rpc_xprt *xprt; struct socket *sock; + read_lock(&sk->callback_lock); if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->socket)) - return; + goto out; if (xprt->shutdown) - return; + goto out; /* Wait until we have enough socket memory */ if (xprt->stream) { /* from net/ipv4/tcp.c:tcp_write_space */ if (tcp_wspace(sk) < tcp_min_write_space(sk)) - return; + goto out; } else { /* from net/core/sock.c:sock_def_write_space */ if (!sock_writeable(sk)) - return; + goto out; } if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)) - return; + goto out; spin_lock_bh(&xprt->sock_lock); if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending) @@ -1040,6 +1032,8 @@ spin_unlock_bh(&xprt->sock_lock); if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); +out: + read_unlock(&sk->callback_lock); } /* @@ -1107,9 +1101,6 @@ if (xprt->shutdown) return -EIO; - if (!xprt_connected(xprt)) - return -ENOTCONN; - if (task->tk_rpcwait) rpc_remove_wait_queue(task); @@ -1118,6 +1109,12 @@ err = -EAGAIN; goto out_unlock; } + + if (!xprt_connected(xprt)) { + err = -ENOTCONN; + goto out_unlock; + } + if (list_empty(&req->rq_list)) { list_add_tail(&req->rq_list, &xprt->recv); req->rq_received = 0; @@ -1192,7 +1189,10 @@ if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) { /* Protect against races with xprt_write_space */ spin_lock_bh(&xprt->sock_lock); - if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) { + /* Don't race with disconnect */ + if (!xprt_connected(xprt)) + task->tk_status = -ENOTCONN; + else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) { task->tk_timeout = req->rq_timeout.to_current; rpc_sleep_on(&xprt->pending, task, NULL, NULL); } @@ -1203,20 +1203,17 @@ rpc_delay(task, HZ>>4); return; case -ECONNREFUSED: + task->tk_timeout = RPC_REESTABLISH_TIMEOUT; + rpc_sleep_on(&xprt->sending, task, NULL, NULL); case -ENOTCONN: - if (!xprt->stream) { - task->tk_timeout = RPC_REESTABLISH_TIMEOUT; - rpc_sleep_on(&xprt->sending, task, NULL, NULL); - return; - } - /* fall through */ + return; default: if (xprt->stream) xprt_disconnect(xprt); - req->rq_bytes_sent = 0; } out_release: xprt_release_write(xprt, task); + req->rq_bytes_sent = 0; return; out_receive: dprintk("RPC: %4d xmit complete\n", task->tk_pid); @@ -1230,10 +1227,14 @@ } else task->tk_timeout = req->rq_timeout.to_current; spin_lock_bh(&xprt->sock_lock); - if (!req->rq_received) + /* Don't race with disconnect */ + if (!xprt_connected(xprt)) + task->tk_status = -ENOTCONN; + else if (!req->rq_received) rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); __xprt_release_write(xprt, task); spin_unlock_bh(&xprt->sock_lock); + req->rq_bytes_sent = 0; } /* @@ -1417,6 +1418,9 @@ req->rq_next = NULL; xprt->free = xprt->slot; + /* Check whether we want to use a reserved port */ + xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; + dprintk("RPC: created transport %p\n", xprt); return xprt; @@ -1430,6 +1434,12 @@ { struct sockaddr_in myaddr; int err, port; + kernel_cap_t saved_cap = current->cap_effective; + + /* Override capabilities. + * They were checked in xprt_create_proto i.e. at mount time + */ + cap_raise(current->cap_effective, CAP_NET_BIND_SERVICE); memset(&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; @@ -1439,6 +1449,7 @@ err = sock->ops->bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)); } while (err == -EADDRINUSE && --port > 0); + current->cap_effective = saved_cap; if (err < 0) printk("RPC: Can't bind to reserved port (%d).\n", -err); @@ -1454,6 +1465,7 @@ if (xprt->inet) return; + write_lock_bh(&sk->callback_lock); sk->user_data = xprt; xprt->old_data_ready = sk->data_ready; xprt->old_state_change = sk->state_change; @@ -1474,6 +1486,7 @@ /* Reset to new socket */ xprt->sock = sock; xprt->inet = sk; + write_unlock_bh(&sk->callback_lock); return; } @@ -1544,16 +1557,6 @@ if (!xprt) goto out_bad; - xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; - if (!xprt->stream) { - struct socket *sock; - - sock = xprt_create_socket(proto, to, xprt->resvport); - if (!sock) - goto out_bad; - xprt_bind_socket(xprt, sock); - } - dprintk("RPC: xprt_create_proto created xprt %p\n", xprt); return xprt; out_bad: