diff options
189 files changed, 4628 insertions, 5436 deletions
@@ -1988,7 +1988,7 @@ S: Halifax, Nova Scotia S: Canada B3J 3C8 N: Kai Mäkisara -E: Kai.Makisara@metla.fi +E: Kai.Makisara@kolumbus.fi D: SCSI Tape Driver N: Asit Mallick diff --git a/Documentation/BK-usage/bk-kernel-howto.txt b/Documentation/BK-usage/bk-kernel-howto.txt index 996249fe9fdc..b7b9075d2910 100644 --- a/Documentation/BK-usage/bk-kernel-howto.txt +++ b/Documentation/BK-usage/bk-kernel-howto.txt @@ -216,7 +216,7 @@ changes. 3) Include a summary and "diffstat -p1" of each changeset that will be downloaded, when Linus issues a "bk pull". The author auto-generates -these summaries using "bk push -nl <parent> 2>&1", to obtain a listing +these summaries using "bk changes -L <parent>", to obtain a listing of all the pending-to-send changesets, and their commit messages. It is important to show Linus what he will be downloading when he issues diff --git a/Documentation/binfmt_misc.txt b/Documentation/binfmt_misc.txt index e8e2d7f8d960..e679460447f7 100644 --- a/Documentation/binfmt_misc.txt +++ b/Documentation/binfmt_misc.txt @@ -11,6 +11,9 @@ at the beginning of the file with a magic byte sequence (masking out specified bits) you have supplied. Binfmt_misc can also recognise a filename extension aka '.com' or '.exe'. +First you must mount binfmt_misc: + mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc + To actually register a new binary type, you have to set up a string looking like :name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register. diff --git a/MAINTAINERS b/MAINTAINERS index 7e98b242ae60..4d0577b47afd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1636,13 +1636,13 @@ S: Maintained SCSI SUBSYSTEM P: James E.J. Bottomley -M: James.Bottomley@HansenPartnership.com +M: James.Bottomley@SteelEye.com L: linux-scsi@vger.kernel.org S: Maintained SCSI TAPE DRIVER P: Kai Mäkisara -M: Kai.Makisara@metla.fi +M: Kai.Makisara@kolumbus.fi L: linux-scsi@vger.kernel.org S: Maintained diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 01a3caaa0dfe..2ebf4fff0be9 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -276,9 +276,9 @@ config MWINCHIP3D help Select this for an IDT Winchip-2A or 3. Linux and GCC treat this chip as a 586TSC with some extended instructions - and alignment reqirements. Development kernels also enable - out of order memory stores for this CPU, which can increase - performance of some operations. + and alignment reqirements. Also enable out of order memory + stores for this CPU, which can increase performance of some + operations. config MCYRIXIII bool "CyrixIII/VIA-C3" diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 01f4853083a3..c49b4749cf95 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -38,12 +38,14 @@ cflags-$(CONFIG_MPENTIUMII) += $(call check_gcc,-march=pentium2,-march=i686) cflags-$(CONFIG_MPENTIUMIII) += $(call check_gcc,-march=pentium3,-march=i686) cflags-$(CONFIG_MPENTIUM4) += $(call check_gcc,-march=pentium4,-march=i686) cflags-$(CONFIG_MK6) += $(call check_gcc,-march=k6,-march=i586) +# Please note, that patches that add -march=athlon-xp and friends are pointless. +# They make zero difference whatsosever to performance at this time. cflags-$(CONFIG_MK7) += $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4) cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,$(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4)) cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MWINCHIPC6) += $(call check_gcc,-march=winchip-c6,-march=i586) cflags-$(CONFIG_MWINCHIP2) += $(call check_gcc,-march=winchip2,-march=i586) -cflags-$(CONFIG_MWINCHIP3D) += -march=i586 +cflags-$(CONFIG_MWINCHIP3D) += $(call check_gcc,-march=winchip2,-march=i586) cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MVIAC3_2) += $(call check_gcc,-march=c3-2,-march=i686) diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index b660653dde76..a0b074a52ac7 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -61,6 +61,8 @@ static DEFINE_PER_CPU(int, prof_multiplier) = 1; static DEFINE_PER_CPU(int, prof_old_multiplier) = 1; static DEFINE_PER_CPU(int, prof_counter) = 1; +static int enabled_via_apicbase; + void enable_NMI_through_LVT0 (void * dummy) { unsigned int v, ver; @@ -190,6 +192,13 @@ void disable_local_APIC(void) value = apic_read(APIC_SPIV); value &= ~APIC_SPIV_APIC_ENABLED; apic_write_around(APIC_SPIV, value); + + if (enabled_via_apicbase) { + unsigned int l, h; + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_ENABLE; + wrmsr(MSR_IA32_APICBASE, l, h); + } } /* @@ -485,7 +494,6 @@ static struct { static int lapic_suspend(struct sys_device *dev, u32 state) { - unsigned int l, h; unsigned long flags; if (!apic_pm_state.active) @@ -507,9 +515,6 @@ static int lapic_suspend(struct sys_device *dev, u32 state) local_irq_save(flags); disable_local_APIC(); - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_ENABLE; - wrmsr(MSR_IA32_APICBASE, l, h); local_irq_restore(flags); return 0; } @@ -636,6 +641,7 @@ static int __init detect_init_APIC (void) l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; wrmsr(MSR_IA32_APICBASE, l, h); + enabled_via_apicbase = 1; } } /* diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index a09e70fa105a..a03beb5f6642 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -109,7 +109,6 @@ static void __init check_cx686_slop(struct cpuinfo_x86 *c) static void __init set_cx86_reorder(void) { -#ifdef CONFIG_OOSTORE u8 ccr3; printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n"); @@ -118,12 +117,9 @@ static void __init set_cx86_reorder(void) /* Load/Store Serialize to mem access disable (=reorder it) */ setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80); -#ifdef CONFIG_NOHIGHMEM /* set load/store serialize from 1GB to 4GB */ ccr3 |= 0xe0; -#endif setCx86(CX86_CCR3, ccr3); -#endif } static void __init set_cx86_memwb(void) diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 55d072c7eb0f..a58ad2a9f4d2 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -89,15 +89,6 @@ MODULE_LICENSE("GPL"); #define printf(x...) #endif -/* VFS interface */ -static int microcode_open(struct inode *, struct file *); -static ssize_t microcode_read(struct file *, char *, size_t, loff_t *); -static ssize_t microcode_write(struct file *, const char *, size_t, loff_t *); -static int microcode_ioctl(struct inode *, struct file *, unsigned int, unsigned long); - -static int do_microcode_update(void); -static void do_update_one(void *); - /* read()/write()/ioctl() are serialized on this */ static DECLARE_RWSEM(microcode_rwsem); @@ -106,46 +97,6 @@ static unsigned int microcode_num; /* number of chunks in microcode */ static char *mc_applied; /* array of applied microcode blocks */ static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */ -static struct file_operations microcode_fops = { - .owner = THIS_MODULE, - .read = microcode_read, - .write = microcode_write, - .ioctl = microcode_ioctl, - .open = microcode_open, -}; - -static struct miscdevice microcode_dev = { - .minor = MICROCODE_MINOR, - .name = "microcode", - .devfs_name = "cpu/microcode", - .fops = µcode_fops, -}; - -static int __init microcode_init(void) -{ - int error; - - error = misc_register(µcode_dev); - if (error) - return error; - - printk(KERN_INFO - "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", - MICROCODE_VERSION); - return 0; -} - -static void __exit microcode_exit(void) -{ - misc_deregister(µcode_dev); - kfree(mc_applied); - printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", - MICROCODE_VERSION); -} - -module_init(microcode_init) -module_exit(microcode_exit) - static int microcode_open(struct inode *unused1, struct file *unused2) { return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; @@ -160,27 +111,6 @@ struct update_req { int slot; } update_req[NR_CPUS]; -static int do_microcode_update(void) -{ - int i, error = 0, err; - struct microcode *m; - - if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { - printk(KERN_ERR "microcode: IPI timeout, giving up\n"); - return -EIO; - } - - for (i=0; i<NR_CPUS; i++) { - err = update_req[i].err; - error += err; - if (!err) { - m = (struct microcode *)mc_applied + i; - memcpy(m, µcode[update_req[i].slot], sizeof(struct microcode)); - } - } - return error; -} - static void do_update_one(void *unused) { int cpu_num = smp_processor_id(); @@ -291,7 +221,28 @@ static void do_update_one(void *unused) } -static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos) +static int do_microcode_update(void) +{ + int i, error = 0, err; + struct microcode *m; + + if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { + printk(KERN_ERR "microcode: IPI timeout, giving up\n"); + return -EIO; + } + + for (i=0; i<NR_CPUS; i++) { + err = update_req[i].err; + error += err; + if (!err) { + m = (struct microcode *)mc_applied + i; + memcpy(m, µcode[update_req[i].slot], sizeof(struct microcode)); + } + } + return error; +} + +static ssize_t microcode_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { ssize_t ret = 0; @@ -310,7 +261,7 @@ out: return ret; } -static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos) +static ssize_t microcode_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { ssize_t ret; @@ -384,3 +335,44 @@ static int microcode_ioctl(struct inode *inode, struct file *file, } return -EINVAL; } + +static struct file_operations microcode_fops = { + .owner = THIS_MODULE, + .read = microcode_read, + .write = microcode_write, + .ioctl = microcode_ioctl, + .open = microcode_open, +}; + +static struct miscdevice microcode_dev = { + .minor = MICROCODE_MINOR, + .name = "microcode", + .devfs_name = "cpu/microcode", + .fops = µcode_fops, +}; + +static int __init microcode_init(void) +{ + int error; + + error = misc_register(µcode_dev); + if (error) + return error; + + printk(KERN_INFO + "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", + MICROCODE_VERSION); + return 0; +} + +static void __exit microcode_exit(void) +{ + misc_deregister(µcode_dev); + kfree(mc_applied); + printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", + MICROCODE_VERSION); +} + +module_init(microcode_init) +module_exit(microcode_exit) + diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index 9524fea9d035..40a237769f3e 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -187,7 +187,7 @@ static loff_t msr_seek(struct file *file, loff_t offset, int orig) return ret; } -static ssize_t msr_read(struct file * file, char * buf, +static ssize_t msr_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { u32 *tmp = (u32 *)buf; @@ -212,7 +212,7 @@ static ssize_t msr_read(struct file * file, char * buf, return ((char *)tmp) - buf; } -static ssize_t msr_write(struct file * file, const char * buf, +static ssize_t msr_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { const u32 *tmp = (const u32 *)buf; diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 77d0daefb75e..4cca4f96cb36 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -8,6 +8,7 @@ #include <linux/interrupt.h> #include <linux/mc146818rtc.h> #include <asm/uaccess.h> +#include <asm/apic.h> #include "mach_reboot.h" /* @@ -249,6 +250,14 @@ void machine_restart(char * __unused) * other OSs see a clean IRQ state. */ smp_send_stop(); +#elif CONFIG_X86_LOCAL_APIC + if (cpu_has_apic) { + local_irq_disable(); + disable_local_APIC(); + local_irq_enable(); + } +#endif +#ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); #endif diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 8759fa4758ff..2edd55db64d0 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -629,9 +629,10 @@ void math_error(void *eip) default: break; case 0x001: /* Invalid Op */ - case 0x040: /* Stack Fault */ - case 0x240: /* Stack Fault | Direction */ + case 0x041: /* Stack Fault */ + case 0x241: /* Stack Fault | Direction */ info.si_code = FPE_FLTINV; + /* Should we clear the SF or let user space do it ???? */ break; case 0x002: /* Denormalize */ case 0x010: /* Underflow */ diff --git a/arch/i386/math-emu/fpu_trig.c b/arch/i386/math-emu/fpu_trig.c index f6ceae26cf8d..403cbde1d425 100644 --- a/arch/i386/math-emu/fpu_trig.c +++ b/arch/i386/math-emu/fpu_trig.c @@ -1058,7 +1058,7 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round) return; goto fprem_valid; } - else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) ) + else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) ) { FPU_stack_underflow(); return; diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c index 188900c1d71b..1b81fc4299cd 100644 --- a/arch/i386/oprofile/op_model_p4.c +++ b/arch/i386/oprofile/op_model_p4.c @@ -355,8 +355,8 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1)) #define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25)) #define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9)) -#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0); -#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0); +#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) +#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) #define CCCR_RESERVED_BITS 0x38030FFF #define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS) @@ -366,13 +366,13 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27)) #define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12)) #define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12)) -#define CCCR_READ(low, high, i) do {rdmsr (p4_counters[(i)].cccr_address, (low), (high));} while (0); -#define CCCR_WRITE(low, high, i) do {wrmsr (p4_counters[(i)].cccr_address, (low), (high));} while (0); +#define CCCR_READ(low, high, i) do {rdmsr (p4_counters[(i)].cccr_address, (low), (high));} while (0) +#define CCCR_WRITE(low, high, i) do {wrmsr (p4_counters[(i)].cccr_address, (low), (high));} while (0) #define CCCR_OVF_P(cccr) ((cccr) & (1U<<31)) #define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31))) -#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0); -#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0); +#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0) +#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0) #define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000)) diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 4117285dcd97..759a88325c4a 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -70,16 +70,16 @@ config NP405H depends on ASH default y -# All 405-based cores have this errata. This leaves out the 403GCX +# All 405-based cores up until the 405GPR and 405EP have this errata. config IBM405_ERR77 bool - depends on 40x && !403GCX + depends on 40x && !403GCX && !405GPR default y -# All 40x-based cores have this errata. +# All 40x-based cores, up until the 405GPR and 405EP have this errata. config IBM405_ERR51 bool - depends on 40x + depends on 40x && !405GPR default y config IBM_OCP diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 82ca1cfa9330..3018aafd56fd 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -22,7 +22,7 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=16 +CONFIG_LOG_BUF_SHIFT=18 # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_FUTEX=y @@ -149,17 +149,12 @@ CONFIG_LBD=y # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_IDEDISK_STROKE is not set @@ -174,15 +169,16 @@ CONFIG_BLK_DEV_IDECD=y # # CONFIG_BLK_DEV_CMD640 is not set CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_BLK_DEV_GENERIC is not set # CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDE_TCQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set @@ -192,23 +188,25 @@ CONFIG_BLK_DEV_AMD74XX=y # CONFIG_BLK_DEV_TRIFLEX is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set # CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIIMAGE is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set -CONFIG_IDEDMA_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -251,7 +249,7 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_IPS is not set +CONFIG_SCSI_IPS=m # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set @@ -301,7 +299,6 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -317,12 +314,10 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -CONFIG_IPV6=y -CONFIG_IPV6_PRIVACY=y -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set # CONFIG_XFRM_USER is not set # @@ -333,8 +328,6 @@ CONFIG_IPV6_SCTP__=y # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set # CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -546,11 +539,7 @@ CONFIG_UNIX98_PTY_COUNT=256 # # IPMI # -CONFIG_IPMI_HANDLER=y -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_DEVICE_INTERFACE=y -CONFIG_IPMI_KCS=y -CONFIG_IPMI_WATCHDOG=y +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards @@ -570,12 +559,7 @@ CONFIG_RTC=y # CONFIG_FTAPE is not set CONFIG_AGP=y CONFIG_AGP_AMD_8151=y -CONFIG_DRM=y -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_GAMMA is not set -# CONFIG_DRM_R128 is not set -CONFIG_DRM_RADEON=y -# CONFIG_DRM_MGA is not set +# CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y CONFIG_HANGCHECK_TIMER=y @@ -598,19 +582,25 @@ CONFIG_HANGCHECK_TIMER=y # File systems # CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_JFS_FS is not set -CONFIG_XFS_FS=m -# CONFIG_XFS_RT is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set +CONFIG_JFS_FS=y +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set @@ -684,6 +674,49 @@ CONFIG_SUNRPC=y # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set # # Graphics support @@ -759,8 +792,10 @@ CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_INIT_DEBUG is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_FRAME_POINTER is not set -# CONFIG_IOMMU_DEBUG is not set +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_LEAK=y CONFIG_MCE_DEBUG=y # @@ -771,21 +806,7 @@ CONFIG_MCE_DEBUG=y # # Cryptographic options # -CONFIG_CRYPTO=y -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO is not set # # Library routines diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index b7f3dcb7e3bf..7b102b1e89ae 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -204,10 +204,9 @@ static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* } static inline int -elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *xregs, elf_fpregset_t *fpu) +elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu) { struct _fpstate_ia32 *fpstate = (void*)fpu; - struct pt_regs *regs = (struct pt_regs *)(tsk->thread.rsp0); mm_segment_t oldfs = get_fs(); if (!tsk->used_math) diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 128cd3867de8..0f560efe9ef6 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o head64.o init_task.o EXTRA_AFLAGS := -traditional obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ - pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \ + x8664_ksyms.o i387.o syscall.o vsyscall.o \ setup64.o bluesmoke.o bootflag.o e820.o reboot.o warmreboot.o obj-$(CONFIG_MTRR) += mtrr/ @@ -19,7 +19,8 @@ obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o suspend_asm.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o -obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o +obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o + obj-$(CONFIG_MODULES) += module.o $(obj)/bootflag.c: diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index aedd584b7ae0..36242d20c492 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -1,14 +1,14 @@ /* * Firmware replacement code. * - * Work around broken BIOSes that don't set an aperture. - * The IOMMU code needs an aperture even who no AGP is present in the system. - * Map the aperture over some low memory. This is cheaper than doing bounce - * buffering. The memory is lost. This is done at early boot because only - * the bootmem allocator can allocate 32+MB. + * Work around broken BIOSes that don't set an aperture or only set the + * aperture in the AGP bridge. + * If all fails map the aperture over some low memory. This is cheaper than + * doing bounce buffering. The memory is lost. This is done at early boot + * because only the bootmem allocator can allocate 32+MB. * * Copyright 2002 Andi Kleen, SuSE Labs. - * $Id: aperture.c,v 1.2 2002/09/19 19:25:32 ak Exp $ + * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $ */ #include <linux/config.h> #include <linux/kernel.h> @@ -17,6 +17,8 @@ #include <linux/bootmem.h> #include <linux/mmzone.h> #include <linux/pci_ids.h> +#include <linux/pci.h> +#include <linux/bitops.h> #include <asm/e820.h> #include <asm/io.h> #include <asm/proto.h> @@ -45,10 +47,10 @@ static u32 __init allocate_aperture(void) aper_size = (32 * 1024 * 1024) << fallback_aper_order; /* - * Aperture has to be naturally aligned it seems. This means an - * 2GB aperture won't have much changes to succeed in the lower 4GB of - * memory. Unfortunately we cannot move it up because that would make - * the IOMMU useless. + * Aperture has to be naturally aligned. This means an 2GB aperture won't + * have much chances to find a place in the lower 4GB of memory. + * Unfortunately we cannot move it up because that would make the + * IOMMU useless. */ p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0); if (!p || __pa(p)+aper_size > 0xffffffff) { @@ -63,21 +65,136 @@ static u32 __init allocate_aperture(void) return (u32)__pa(p); } +static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size) +{ + if (!aper_base) + return 0; + if (aper_size < 64*1024*1024) { + printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20); + return 0; + } + if (aper_base + aper_size >= 0xffffffff) { + printk("Aperture from %s beyond 4GB. Ignoring.\n",name); + return 0; + } + if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) { + printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name); + return 0; + } + return 1; +} + +/* Find a PCI capability */ +static __u32 __init find_cap(int num, int slot, int func, int cap) +{ + if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST)) + return 0; + u8 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST); + int bytes; + for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { + pos &= ~3; + u8 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID); + if (id == 0xff) + break; + if (id == cap) + return pos; + pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT); + } + return 0; +} + +/* Read a standard AGPv3 bridge header */ +static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) +{ + printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func); + u32 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14); + + if (apsizereg == 0xffffffff) { + printk("APSIZE in AGP bridge unreadable\n"); + return 0; + } + + u32 apsize = apsizereg & 0xfff; + /* Some BIOS use weird encodings not in the AGPv3 table. */ + if (apsize & 0xff) + apsize |= 0xf00; + int nbits = hweight16(apsize); + *order = 7 - nbits; + if ((int)*order < 0) /* < 32MB */ + *order = 0; + + u32 aper_low = read_pci_config(num,slot,func, 0x10); + u32 aper_hi = read_pci_config(num,slot,func,0x14); + u64 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); + + printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", + aper, 32 << *order, apsizereg); + + if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order)) + return 0; + return (u32)aper; +} + +/* Look for an AGP bridge. Windows only expects the aperture in the + AGP bridge and some BIOS forget to initialize the Northbridge too. + Work around this here. + + Do an PCI bus scan by hand because we're running before the PCI + subsystem. + + All K8 AGP bridges are AGPv3 compliant, so we can do this scan + generically. It's probably overkill to always scan all slots because + the AGP bridges should be always an own bus on the HT hierarchy, + but do it here for future safety. */ +static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) +{ + int num, slot, func; + + /* Poor man's PCI discovery */ + for (num = 0; num < 32; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class, cap; + class = read_pci_config(num,slot,func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + switch (class >> 16) { + case PCI_CLASS_BRIDGE_HOST: + case PCI_CLASS_BRIDGE_OTHER: /* needed? */ + /* AGP bridge? */ + cap = find_cap(num,slot,func,PCI_CAP_ID_AGP); + if (!cap) + break; + *valid_agp = 1; + return read_agp(num,slot,func,cap,order); + } + + /* No multi-function device? */ + u8 type = read_pci_config_byte(num,slot,func, + PCI_HEADER_TYPE); + if (!(type & 0x80)) + break; + } + } + } + printk("No AGP bridge found\n"); + return 0; +} + void __init iommu_hole_init(void) { int fix, num; - u32 aper_size, aper_alloc, aper_order; + u32 aper_size, aper_alloc = 0, aper_order; u64 aper_base; - - if (no_iommu) - return; - if (end_pfn < (0xffffffff>>PAGE_SHIFT) && !force_mmu) - return; + int valid_agp = 0; printk("Checking aperture...\n"); fix = 0; for (num = 24; num < 32; num++) { + char name[30]; if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) continue; @@ -86,15 +203,12 @@ void __init iommu_hole_init(void) aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; aper_base <<= 25; - printk("CPU %d: aperture @ %Lx size %u KB\n", num-24, - aper_base, aper_size>>10); - if (!aper_base || aper_base + aper_size >= 0xffffffff) { - fix = 1; - break; - } + printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, + aper_base, aper_size>>20); - if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) { - printk("Aperture pointing to e820 RAM. Ignoring.\n"); + sprintf(name, "northbridge cpu %d", num-24); + + if (!aperture_valid(name, aper_base, aper_size)) { fix = 1; break; } @@ -103,12 +217,40 @@ void __init iommu_hole_init(void) if (!fix && !fallback_aper_force) return; + if (!fallback_aper_force) + aper_alloc = search_agp_bridge(&aper_order, &valid_agp); + + if (aper_alloc) { + /* Got the aperture from the AGP bridge */ + } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) || + force_iommu || + valid_agp || + fallback_aper_force) { + /* When there is a AGP bridge in the system assume the + user wants to use the AGP driver too and needs an + aperture. However this case (AGP but no good + aperture) should only happen with a more broken than + usual BIOS, because it would even break Windows. */ + printk("Your BIOS doesn't leave a aperture memory hole\n"); printk("Please enable the IOMMU option in the BIOS setup\n"); + printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order); + + aper_order = fallback_aper_order; aper_alloc = allocate_aperture(); - if (!aper_alloc) + if (!aper_alloc) { + /* Could disable AGP and IOMMU here, but it's probably + not worth it. But the later users cannot deal with + bad apertures and turning on the aperture over memory + causes very strange problems, so it's better to + panic early. */ + panic("Not enough memory for aperture"); + } + } else { return; + } + /* Fix up the north bridges */ for (num = 24; num < 32; num++) { if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) continue; @@ -116,7 +258,7 @@ void __init iommu_hole_init(void) /* Don't enable translation yet. That is done later. Assume this BIOS didn't initialise the GART so just overwrite all previous bits */ - write_pci_config(0, num, 3, 0x90, fallback_aper_order<<1); + write_pci_config(0, num, 3, 0x90, aper_order<<1); write_pci_config(0, num, 3, 0x94, aper_alloc>>25); } } diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index aa7a1868c1f3..12e28ccedbc1 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -40,6 +40,7 @@ * -1: the lapic NMI watchdog is disabled, but can be enabled */ static int nmi_active; +static int panic_on_timeout; unsigned int nmi_watchdog = NMI_IO_APIC; static unsigned int nmi_hz = HZ; @@ -115,6 +116,14 @@ static int __init setup_nmi_watchdog(char *str) { int nmi; + if (!strncmp(str,"panic",5)) { + panic_on_timeout = 1; + str = strchr(str, ','); + if (!str) + return 1; + ++str; + } + get_option(&str, &nmi); if (nmi >= NMI_INVALID) @@ -327,6 +336,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) bust_spinlocks(1); printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu); show_registers(regs); + if (panic_on_timeout) + panic("nmi watchdog"); printk("console shuts up ...\n"); console_silent(); spin_unlock(&nmi_print_lock); @@ -374,3 +385,4 @@ EXPORT_SYMBOL(disable_lapic_nmi_watchdog); EXPORT_SYMBOL(enable_lapic_nmi_watchdog); EXPORT_SYMBOL(disable_timer_nmi_watchdog); EXPORT_SYMBOL(enable_timer_nmi_watchdog); +EXPORT_SYMBOL(touch_nmi_watchdog); diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c index 67a07a9db3b1..43ff84bc076f 100644 --- a/arch/x86_64/kernel/pci-dma.c +++ b/arch/x86_64/kernel/pci-dma.c @@ -9,8 +9,6 @@ #include <linux/module.h> #include <asm/io.h> -dma_addr_t bad_dma_address = -1UL; - /* Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scatter-gather version of the * above pci_map_single interface. Here the scatter gather list @@ -34,16 +32,9 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, BUG_ON(direction == PCI_DMA_NONE); for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; - BUG_ON(!s->page); - s->dma_address = pci_map_page(hwdev, s->page, s->offset, s->length, direction); - - if (unlikely(s->dma_address == bad_dma_address)) { - pci_unmap_sg(hwdev, sg, i, direction); - return 0; - } } return nents; } diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 336989a14a92..b9951a64bab3 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -8,20 +8,8 @@ * See Documentation/DMA-mapping.txt for the interface specification. * * Copyright 2002 Andi Kleen, SuSE Labs. - * $Id: pci-gart.c,v 1.20 2003/03/12 08:23:29 ak Exp $ */ -/* - * Notebook: - -possible future tuning: - fast path for sg streaming mappings - only take the locks once. - more intelligent flush strategy - flush only the NB of the CPU directly - connected to the device? - move boundary between IOMMU and AGP in GART dynamically - -*/ - #include <linux/config.h> #include <linux/types.h> #include <linux/ctype.h> @@ -32,6 +20,8 @@ possible future tuning: #include <linux/spinlock.h> #include <linux/pci.h> #include <linux/module.h> +#include <linux/topology.h> +#include <asm/atomic.h> #include <asm/io.h> #include <asm/mtrr.h> #include <asm/bitops.h> @@ -41,6 +31,8 @@ possible future tuning: #include <asm/kdebug.h> #include <asm/proto.h> +dma_addr_t bad_dma_address; + unsigned long iommu_bus_base; /* GART remapping area (physical) */ static unsigned long iommu_size; /* size of remapping area bytes */ static unsigned long iommu_pages; /* .. and in pages */ @@ -50,9 +42,13 @@ u32 *iommu_gatt_base; /* Remapping table */ int no_iommu; static int no_agp; #ifdef CONFIG_IOMMU_DEBUG -int force_mmu = 1; +int panic_on_overflow = 1; +int force_iommu = 1; +int sac_force_size = 0; #else -int force_mmu = 0; +int panic_on_overflow = 1; /* for testing */ +int force_iommu = 0; +int sac_force_size = 256*1024*1024; #endif /* Allocation bitmap for the remapping area */ @@ -65,12 +61,18 @@ static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) +#define to_pages(addr,size) \ + (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT) + #define for_all_nb(dev) \ - dev=NULL; \ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) \ - if (dev->bus->number == 0 && PCI_FUNC(dev->devfn) == 3 && \ + dev = NULL; \ + while ((dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)\ + if (dev->bus->number == 0 && \ (PCI_SLOT(dev->devfn) >= 24) && (PCI_SLOT(dev->devfn) <= 31)) +static struct pci_dev *northbridges[NR_CPUS + 1]; +static u32 northbridge_flush_word[NR_CPUS + 1]; + #define EMERGENCY_PAGES 32 /* = 128KB */ #ifdef CONFIG_AGP @@ -85,15 +87,16 @@ AGPEXTERN int agp_memory_reserved; AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ +static int need_flush; /* global flush state. set for each gart wrap */ -static unsigned long alloc_iommu(int size, int *flush) +static unsigned long alloc_iommu(int size) { unsigned long offset, flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size); if (offset == -1) { - *flush = 1; + need_flush = 1; offset = find_next_zero_string(iommu_gart_bitmap,0,next_bit,size); } if (offset != -1) { @@ -101,7 +104,7 @@ static unsigned long alloc_iommu(int size, int *flush) next_bit = offset+size; if (next_bit >= iommu_pages) { next_bit = 0; - *flush = 1; + need_flush = 1; } } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); @@ -110,32 +113,59 @@ static unsigned long alloc_iommu(int size, int *flush) static void free_iommu(unsigned long offset, int size) { + if (size == 1) { + clear_bit(offset, iommu_gart_bitmap); + return; + } unsigned long flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); - clear_bit_string(iommu_gart_bitmap, offset, size); + __clear_bit_string(iommu_gart_bitmap, offset, size); spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } -static inline void flush_gart(void) +/* + * Use global flush state to avoid races with multiple flushers. + */ +static void __flush_gart(struct pci_dev *dev) { - struct pci_dev *nb; - for_all_nb(nb) { - u32 flag; - pci_read_config_dword(nb, 0x9c, &flag); /* could cache this */ - /* could complain for PTE walk errors here (bit 1 of flag) */ - flag |= 1; - pci_write_config_dword(nb, 0x9c, flag); + unsigned long flags; + int bus = dev ? dev->bus->number : -1; + int flushed = 0; + int i; + + spin_lock_irqsave(&iommu_bitmap_lock, flags); + /* recheck flush count inside lock */ + if (need_flush) { + for (i = 0; northbridges[i]; i++) { + if (bus >= 0 && !(pcibus_to_cpumask(bus) & (1UL << i))) + continue; + pci_write_config_dword(northbridges[i], 0x9c, + northbridge_flush_word[i] | 1); + flushed++; + } + if (!flushed) + printk("nothing to flush? %d\n", bus); + need_flush = 0; } + spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } +static inline void flush_gart(struct pci_dev *dev) +{ + if (need_flush) + __flush_gart(dev); +} + +/* + * Allocate memory for a consistent mapping. + * All mappings are consistent here, so this is just a wrapper around + * pci_map_single. + */ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) { void *memory; int gfp = GFP_ATOMIC; - int i; - int flush = 0; - unsigned long iommu_page; unsigned long dma_mask; if (hwdev == NULL) { @@ -149,20 +179,14 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, if (dma_mask < 0xffffffff || no_iommu) gfp |= GFP_DMA; - /* - * First try to allocate continuous and use directly if already - * in lowmem. - */ - size = round_up(size, PAGE_SIZE); memory = (void *)__get_free_pages(gfp, get_order(size)); if (memory == NULL) { return NULL; } else { - int high = 0, mmu; - if (((unsigned long)virt_to_bus(memory) + size) > dma_mask) - high = 1; - mmu = 1; - if (force_mmu && !(gfp & GFP_DMA)) + int high, mmu; + high = ((unsigned long)virt_to_bus(memory) + size) >= dma_mask; + mmu = high; + if (force_iommu && !(gfp & GFP_DMA)) mmu = 1; if (no_iommu) { if (high) goto error; @@ -175,27 +199,15 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, } } - size >>= PAGE_SHIFT; - - iommu_page = alloc_iommu(size, &flush); - if (iommu_page == -1) + *dma_handle = pci_map_single(hwdev, memory, size, 0); + if (*dma_handle == bad_dma_address) goto error; - /* Fill in the GATT */ - for (i = 0; i < size; i++) { - unsigned long phys_mem; - void *mem = memory + i*PAGE_SIZE; - phys_mem = virt_to_phys(mem); - BUG_ON(phys_mem & ~PHYSICAL_PAGE_MASK); - iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem); - } - - if (flush) - flush_gart(); - *dma_handle = iommu_bus_base + (iommu_page << PAGE_SHIFT); return memory; - error: +error: + if (panic_on_overflow) + panic("pci_map_single: overflow %lu bytes\n", size); free_pages((unsigned long)memory, get_order(size)); return NULL; } @@ -207,25 +219,17 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t bus) { - unsigned long iommu_page; - - size = round_up(size, PAGE_SIZE); - if (bus >= iommu_bus_base && bus <= iommu_bus_base + iommu_size) { - unsigned pages = size >> PAGE_SHIFT; - int i; - iommu_page = (bus - iommu_bus_base) >> PAGE_SHIFT; - vaddr = __va(GPTE_DECODE(iommu_gatt_base[iommu_page])); - for (i = 0; i < pages; i++) { - u64 pte = iommu_gatt_base[iommu_page + i]; - BUG_ON((pte & GPTE_VALID) == 0); - iommu_gatt_base[iommu_page + i] = 0; - } - free_iommu(iommu_page, pages); - } + pci_unmap_single(hwdev, bus, size, 0); free_pages((unsigned long)vaddr, get_order(size)); } #ifdef CONFIG_IOMMU_LEAK + +#define SET_LEAK(x) if (iommu_leak_tab) \ + iommu_leak_tab[x] = __builtin_return_address(0); +#define CLEAR_LEAK(x) if (iommu_leak_tab) \ + iommu_leak_tab[x] = 0; + /* Debugging aid for drivers that don't free their IOMMU tables */ static void **iommu_leak_tab; static int leak_trace; @@ -246,9 +250,12 @@ void dump_leak(void) } printk("\n"); } +#else +#define SET_LEAK(x) +#define CLEAR_LEAK(x) #endif -static void iommu_full(struct pci_dev *dev, void *addr, size_t size, int dir) +static void iommu_full(struct pci_dev *dev, size_t size, int dir) { /* * Ran out of IOMMU space for this operation. This is very bad. @@ -261,8 +268,8 @@ static void iommu_full(struct pci_dev *dev, void *addr, size_t size, int dir) */ printk(KERN_ERR - "PCI-DMA: Out of IOMMU space for %p size %lu at device %s[%s]\n", - addr,size, dev ? dev->dev.name : "?", dev ? pci_name(dev) : "?"); + "PCI-DMA: Out of IOMMU space for %lu bytes at device %s[%s]\n", + size, dev ? dev->dev.name : "?", dev ? dev->slot_name : "?"); if (size > PAGE_SIZE*EMERGENCY_PAGES) { if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) @@ -279,24 +286,61 @@ static void iommu_full(struct pci_dev *dev, void *addr, size_t size, int dir) static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t size) { u64 mask = dev ? dev->dma_mask : 0xffffffff; - int high = (~mask & (unsigned long)(addr + size)) != 0; + int high = addr + size >= mask; int mmu = high; - if (force_mmu) + if (force_iommu) mmu = 1; if (no_iommu) { if (high) - panic("pci_map_single: high address but no IOMMU.\n"); + panic("PCI-DMA: high address but no IOMMU.\n"); mmu = 0; } return mmu; } +static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_t size) +{ + u64 mask = dev ? dev->dma_mask : 0xffffffff; + int high = addr + size >= mask; + int mmu = high; + if (no_iommu) { + if (high) + panic("PCI-DMA: high address but no IOMMU.\n"); + mmu = 0; + } + return mmu; +} + +/* Map a single continuous physical area into the IOMMU. + * Caller needs to check if the iommu is needed and flush. + */ +static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, + size_t size, int dir) +{ + unsigned long npages = to_pages(phys_mem, size); + unsigned long iommu_page = alloc_iommu(npages); + if (iommu_page == -1) { + if (!nonforced_iommu(dev, phys_mem, size)) + return phys_mem; + if (panic_on_overflow) + panic("pci_map_area overflow %lu bytes\n", size); + iommu_full(dev, size, dir); + return bad_dma_address; + } + + int i; + for (i = 0; i < npages; i++) { + iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem); + SET_LEAK(iommu_page + i); + phys_mem += PAGE_SIZE; + } + return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK); +} + +/* Map a single area into the IOMMU */ dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir) { - unsigned long iommu_page; unsigned long phys_mem, bus; - int i, npages; - int flush = 0; BUG_ON(dir == PCI_DMA_NONE); @@ -304,39 +348,158 @@ dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir) if (!need_iommu(dev, phys_mem, size)) return phys_mem; - npages = round_up(size + ((u64)addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT; + bus = pci_map_area(dev, phys_mem, size, dir); + flush_gart(dev); + return bus; +} - iommu_page = alloc_iommu(npages, &flush); - if (iommu_page == -1) { - iommu_full(dev, addr, size, dir); - return iommu_bus_base; +/* Fallback for pci_map_sg in case of overflow */ +static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg, + int nents, int dir) +{ + int i; + +#ifdef CONFIG_IOMMU_DEBUG + printk(KERN_DEBUG "pci_map_sg overflow\n"); +#endif + + for (i = 0; i < nents; i++ ) { + struct scatterlist *s = &sg[i]; + unsigned long addr = page_to_phys(s->page) + s->offset; + if (nonforced_iommu(dev, addr, s->length)) { + addr = pci_map_area(dev, addr, s->length, dir); + if (addr == bad_dma_address) { + if (i > 0) + pci_unmap_sg(dev, sg, i, dir); + nents = 0; + break; + } + } + s->dma_address = addr; + } + flush_gart(dev); + return nents; +} + +/* Map multiple scatterlist entries continuous into the first. */ +static int __pci_map_cont(struct scatterlist *sg, int start, int stopat, + struct scatterlist *sout, unsigned long pages) +{ + unsigned long iommu_start = alloc_iommu(pages); + if (iommu_start == -1) + return -1; + + unsigned long iommu_page = iommu_start; + int i; + + for (i = start; i < stopat; i++) { + struct scatterlist *s = &sg[i]; + unsigned long start_addr = s->dma_address; + BUG_ON(i > 0 && s->offset); + if (i == start) { + *sout = *s; + sout->dma_address = iommu_bus_base; + sout->dma_address += iommu_page*PAGE_SIZE + s->offset; + } else { + sout->length += s->length; + } + unsigned long addr = start_addr; + while (addr < start_addr + s->length) { + iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); + SET_LEAK(iommu_page); + addr += PAGE_SIZE; + iommu_page++; } + BUG_ON(i > 0 && addr % PAGE_SIZE); + } + BUG_ON(iommu_page - iommu_start != pages); + return 0; +} - phys_mem &= PAGE_MASK; - for (i = 0; i < npages; i++, phys_mem += PAGE_SIZE) { - BUG_ON(phys_mem & ~PHYSICAL_PAGE_MASK); +static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat, + struct scatterlist *sout, + unsigned long pages, int need) +{ + if (!need) { + BUG_ON(stopat - start != 1); + *sout = sg[start]; + return 0; + } + return __pci_map_cont(sg, start, stopat, sout, pages); +} + +#define PCI_NO_MERGE 0 - /* - * Set coherent mapping here to avoid needing to flush - * the caches on mapping. +/* + * DMA map all entries in a scatterlist. + * Merge chunks that have page aligned sizes into a continuous mapping. */ - iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem); +int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) +{ + int i; + int out; + int start; + unsigned long pages = 0; + int need = 0; -#ifdef CONFIG_IOMMU_LEAK - /* XXX need eventually caller of pci_map_sg */ - if (iommu_leak_tab) - iommu_leak_tab[iommu_page + i] = __builtin_return_address(0); -#endif + unsigned long size = 0; + + BUG_ON(dir == PCI_DMA_NONE); + if (nents == 0) + return 0; + out = 0; + start = 0; + for (i = 0; i < nents; i++) { + struct scatterlist *s = &sg[i]; + dma_addr_t addr = page_to_phys(s->page) + s->offset; + s->dma_address = addr; + BUG_ON(s->length == 0); + + size += s->length; + + /* Handle the previous not yet processed entries */ + if (i > start) { + struct scatterlist *ps = &sg[i-1]; + /* Can only merge when the last chunk ends on a page + boundary. */ + if (PCI_NO_MERGE || !need || (i-1 > start && ps->offset) || + (ps->offset + ps->length) % PAGE_SIZE) { + if (pci_map_cont(sg, start, i, sg+out, pages, + need) < 0) + goto error; + out++; + pages = 0; + start = i; + } } - if (flush) - flush_gart(); - bus = iommu_bus_base + iommu_page*PAGE_SIZE; - return bus + ((unsigned long)addr & ~PAGE_MASK); + need = need_iommu(dev, addr, s->length); + pages += to_pages(s->offset, s->length); + } + if (pci_map_cont(sg, start, i, sg+out, pages, need) < 0) + goto error; + out++; + flush_gart(dev); + if (out < nents) + sg[out].length = 0; + return out; + +error: + flush_gart(NULL); + pci_unmap_sg(dev, sg, nents, dir); + /* When it was forced try again unforced */ + if (force_iommu) + return pci_map_sg_nonforce(dev, sg, nents, dir); + if (panic_on_overflow) + panic("pci_map_sg: overflow on %lu pages\n", pages); + iommu_full(dev, pages << PAGE_SHIFT, dir); + for (i = 0; i < nents; i++) + sg[i].dma_address = bad_dma_address; + return 0; } /* - * Free a temporary PCI mapping. + * Free a PCI mapping. */ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction) @@ -347,20 +510,68 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, dma_addr > iommu_bus_base + iommu_size) return; iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; - npages = round_up(size + (dma_addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT; + npages = to_pages(dma_addr, size); int i; for (i = 0; i < npages; i++) { iommu_gatt_base[iommu_page + i] = 0; -#ifdef CONFIG_IOMMU_LEAK - if (iommu_leak_tab) - iommu_leak_tab[iommu_page + i] = 0; -#endif + CLEAR_LEAK(iommu_page + i); } free_iommu(iommu_page, npages); } +/* + * Wrapper for pci_unmap_single working with scatterlists. + */ +void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, + int dir) +{ + int i; + for (i = 0; i < nents; i++) { + struct scatterlist *s = &sg[i]; + if (!s->length) + break; + pci_unmap_single(dev, s->dma_address, s->length, dir); + } +} + +int pci_dma_supported(struct pci_dev *dev, u64 mask) +{ + /* Copied from i386. Doesn't make much sense, because it will + only work for pci_alloc_consistent. + The caller just has to use GFP_DMA in this case. */ + if (mask < 0x00ffffff) + return 0; + + /* Tell the device to use SAC when IOMMU force is on. + This allows the driver to use cheaper accesses in some cases. + + Problem with this is that if we overflow the IOMMU area + and return DAC as fallback address the device may not handle it correctly. + As a compromise we only do this if the IOMMU area is >= 256MB + which should make overflow unlikely enough. + + As a special case some controllers have a 39bit address mode + that is as efficient as 32bit (aic79xx). Don't force SAC for these. + Assume all masks <= 40 bits are of this type. Normally this doesn't + make any difference, but gives more gentle handling of IOMMU overflow. */ + if (force_iommu && (mask > 0xffffffffffULL) && (iommu_size >= sac_force_size)){ + printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->slot_name,mask); + return 0; + } + + if (no_iommu && (mask < (end_pfn << PAGE_SHIFT))) + return 0; + + return 1; +} + +EXPORT_SYMBOL(pci_unmap_sg); +EXPORT_SYMBOL(pci_map_sg); EXPORT_SYMBOL(pci_map_single); EXPORT_SYMBOL(pci_unmap_single); +EXPORT_SYMBOL(pci_dma_supported); +EXPORT_SYMBOL(no_iommu); +EXPORT_SYMBOL(force_iommu); static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) { @@ -452,13 +663,12 @@ static __init int init_k8_gatt(struct agp_kern_info *info) pci_write_config_dword(dev, 0x90, ctl); } - flush_gart(); + flush_gart(NULL); - printk("PCI-DMA: aperture base @ %x size %u KB\n", aper_base, aper_size>>10); + printk("PCI-DMA: aperture base @ %x size %u KB\n",aper_base, aper_size>>10); return 0; nommu: - /* XXX: reject 0xffffffff mask now in pci mapping functions */ printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n" KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction."); return -1; @@ -466,11 +676,12 @@ static __init int init_k8_gatt(struct agp_kern_info *info) extern int agp_amdk8_init(void); -int __init pci_iommu_init(void) +static int __init pci_iommu_init(void) { struct agp_kern_info info; unsigned long aper_size; unsigned long iommu_start; + struct pci_dev *dev; #ifndef CONFIG_AGP_AMD_8151 no_agp = 1; @@ -482,7 +693,7 @@ int __init pci_iommu_init(void) (agp_copy_info(&info) < 0); #endif - if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { + if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); no_iommu = 1; return -1; @@ -492,7 +703,7 @@ int __init pci_iommu_init(void) int err = -1; printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); no_agp = 1; - if (force_mmu || end_pfn >= 0xffffffff>>PAGE_SHIFT) + if (force_iommu || end_pfn >= 0xffffffff>>PAGE_SHIFT) err = init_k8_gatt(&info); if (err < 0) { printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); @@ -529,25 +740,38 @@ int __init pci_iommu_init(void) set_bit_string(iommu_gart_bitmap, 0, EMERGENCY_PAGES); agp_memory_reserved = iommu_size; - printk(KERN_INFO"PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n", + printk(KERN_INFO + "PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n", iommu_size>>20); iommu_start = aper_size - iommu_size; iommu_bus_base = info.aper_base + iommu_start; - iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT); bad_dma_address = iommu_bus_base; + iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT); /* - * Unmap the IOMMU part of the GART. The alias of the page is always mapped - * with cache enabled and there is no full cache coherency across the GART - * remapping. The unmapping avoids automatic prefetches from the CPU - * allocating cache lines in there. All CPU accesses are done via the - * direct mapping to the backing memory. The GART address is only used by PCI + * Unmap the IOMMU part of the GART. The alias of the page is + * always mapped with cache enabled and there is no full cache + * coherency across the GART remapping. The unmapping avoids + * automatic prefetches from the CPU allocating cache lines in + * there. All CPU accesses are done via the direct mapping to + * the backing memory. The GART address is only used by PCI * devices. */ clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size); - flush_gart(); + for_all_nb(dev) { + u32 flag; + int cpu = PCI_SLOT(dev->devfn) - 24; + if (cpu >= NR_CPUS) + continue; + northbridges[cpu] = dev; + + pci_read_config_dword(dev, 0x9c, &flag); /* cache flush word */ + northbridge_flush_word[cpu] = flag; + } + + flush_gart(NULL); return 0; } @@ -561,8 +785,8 @@ fs_initcall(pci_iommu_init); off don't use the IOMMU leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) memaper[=order] allocate an own aperture over RAM with size 32MB^order. - noforce don't force IOMMU usage. Should be fastest. - force Force IOMMU and turn on unmap debugging. + noforce don't force IOMMU usage. Default. + force Force IOMMU. */ __init int iommu_setup(char *opt) { @@ -575,15 +799,19 @@ __init int iommu_setup(char *opt) if (!memcmp(p,"off", 3)) no_iommu = 1; if (!memcmp(p,"force", 5)) - force_mmu = 1; + force_iommu = 1; if (!memcmp(p,"noforce", 7)) - force_mmu = 0; + force_iommu = 0; if (!memcmp(p, "memaper", 7)) { fallback_aper_force = 1; p += 7; if (*p == '=' && get_option(&p, &arg)) fallback_aper_order = arg; } + if (!memcmp(p, "panic", 5)) + panic_on_overflow = 1; + if (!memcmp(p, "nopanic", 7)) + panic_on_overflow = 0; #ifdef CONFIG_IOMMU_LEAK if (!memcmp(p,"leak", 4)) { leak_trace = 1; diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c index 8240e5557f89..69bd270513e1 100644 --- a/arch/x86_64/kernel/pci-nommu.c +++ b/arch/x86_64/kernel/pci-nommu.c @@ -33,15 +33,30 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, free_pages((unsigned long)vaddr, get_order(size)); } +int pci_dma_supported(struct pci_dev *hwdev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + * RED-PEN this won't work for pci_map_single. Caller has to + * use GFP_DMA in the first place. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} -static void __init check_ram(void) +EXPORT_SYMBOL(pci_dma_supported); + +static int __init check_ram(void) { if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { printk(KERN_ERR "WARNING more than 4GB of memory but no IOMMU.\n" KERN_ERR "WARNING 32bit PCI may malfunction.\n"); - /* Could play with highmem_start_page here to trick some subsystems - into bounce buffers. Unfortunately that would require setting - CONFIG_HIGHMEM too. - */ } + return 0; } +__initcall(check_ram); + diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index eff0bf79748b..b192e8c08a83 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -131,14 +131,16 @@ void __init setup_per_cpu_areas(void) size = PERCPU_ENOUGH_ROOM; #endif - /* We don't support CPU hotplug, so only allocate as much as needed here */ - - int maxi = max_t(unsigned, numnodes, num_online_cpus()); - - for (i = 0; i < maxi; i++) { + for (i = 0; i < NR_CPUS; i++) { + unsigned char *ptr; /* If possible allocate on the node of the CPU. In case it doesn't exist round-robin nodes. */ - unsigned char *ptr = alloc_bootmem_node(NODE_DATA(i % numnodes), size); + if (!NODE_DATA(i % numnodes)) { + printk("cpu with no node %d, numnodes %d\n", i, numnodes); + ptr = alloc_bootmem(size); + } else { + ptr = alloc_bootmem_node(NODE_DATA(i % numnodes), size); + } if (!ptr) panic("Cannot allocate cpu data for CPU %d\n", i); cpu_pda[i].data_offset = ptr - __per_cpu_start; @@ -158,7 +160,6 @@ void pda_init(int cpu) pda->me = pda; pda->cpunumber = cpu; pda->irqcount = -1; - pda->data_offset = 0; pda->kernelstack = (unsigned long)stack_thread_info() - PDA_STACKOFFSET + THREAD_SIZE; pda->active_mm = &init_mm; @@ -170,14 +171,14 @@ void pda_init(int cpu) pda->irqstackptr = boot_cpu_stack; level4 = init_level4_pgt; } else { + level4 = (pml4_t *)__get_free_pages(GFP_ATOMIC, 0); + if (!level4) + panic("Cannot allocate top level page for cpu %d", cpu); pda->irqstackptr = (char *) __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); if (!pda->irqstackptr) - panic("cannot allocate irqstack for cpu %d\n", cpu); - level4 = (pml4_t *)__get_free_pages(GFP_ATOMIC, 0); + panic("cannot allocate irqstack for cpu %d", cpu); } - if (!level4) - panic("Cannot allocate top level page for cpu %d", cpu); pda->level4_pgt = (unsigned long *)level4; if (level4 != init_level4_pgt) diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c index 9e0ffdfd9031..1e3e5941fd69 100644 --- a/arch/x86_64/kernel/sys_x86_64.c +++ b/arch/x86_64/kernel/sys_x86_64.c @@ -122,3 +122,17 @@ asmlinkage long wrap_sys_shmat(int shmid, char *shmaddr, int shmflg) unsigned long raddr; return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; } + +asmlinkage long sys_time64(long * tloc) +{ + struct timeval now; + int i; + + do_gettimeofday(&now); + i = now.tv_sec; + if (tloc) { + if (put_user(i,tloc)) + i = -EFAULT; + } + return i; +} diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 4297388cd1cc..2042d9295796 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -121,6 +121,7 @@ EXPORT_SYMBOL_NOVERS(__read_lock_failed); EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(smp_call_function); +EXPORT_SYMBOL(cpu_callout_map); #endif #ifdef CONFIG_VT diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 04d716c22552..43df86e4f3ca 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c @@ -47,6 +47,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) struct node nodes[MAXNODE]; int nodeid, i, nb; int found = 0; + int nmax; nb = find_northbridge(); if (nb < 0) @@ -54,22 +55,28 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb); - numnodes = (1 << ((read_pci_config(0, nb, 0, 0x60 ) >> 4) & 3)); - - printk(KERN_INFO "Assuming %d nodes\n", numnodes - 1); + nmax = (1 << ((read_pci_config(0, nb, 0, 0x60 ) >> 4) & 3)); + numnodes = nmax; memset(&nodes,0,sizeof(nodes)); prevbase = 0; - for (i = 0; i < numnodes; i++) { + for (i = 0; i < 8; i++) { unsigned long base,limit; base = read_pci_config(0, nb, 1, 0x40 + i*8); limit = read_pci_config(0, nb, 1, 0x44 + i*8); nodeid = limit & 3; + if ((base & 3) == 0) { + if (i < nmax) + printk("Skipping disabled node %d\n", i); + continue; + } + if (!limit) { - printk(KERN_ERR "Skipping node entry %d (base %lx)\n", i, base); - return -1; + printk(KERN_INFO "Skipping node entry %d (base %lx)\n", i, + base); + continue; } if ((base >> 8) & 3 || (limit >> 8) & 3) { printk(KERN_ERR "Node %d using interleaving mode %lx/%lx\n", @@ -77,7 +84,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) return -1; } if ((1UL << nodeid) & nodes_present) { - printk(KERN_INFO "Node %d already present. Skipping\n", nodeid); + printk(KERN_INFO "Node %d already present. Skipping\n", + nodeid); continue; } @@ -104,7 +112,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) if (limit < base) { printk(KERN_ERR "Node %d bogus settings %lx-%lx.\n", nodeid, base, limit); - return -1; + continue; } /* Could sort here, but pun for now. Should not happen anyroads. */ @@ -135,11 +143,26 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) } printk(KERN_INFO "Using node hash shift of %d\n", memnode_shift); - for (i = 0; i < numnodes; i++) { + for (i = 0; i < MAXNODE; i++) { if (nodes[i].start != nodes[i].end) setup_node_bootmem(i, nodes[i].start, nodes[i].end); } + /* There are unfortunately some poorly designed mainboards around + that only connect memory to a single CPU. This breaks the 1:1 cpu->node + mapping. To avoid this fill in the mapping for all possible + CPUs, as the number of CPUs is not known yet. + We round robin the existing nodes. */ + int rr = 0; + for (i = 0; i < MAXNODE; i++) { + if (nodes_present & (1UL<<i)) + continue; + if ((nodes_present >> rr) == 0) + rr = 0; + rr = ffz(~nodes_present >> rr); + node_data[i] = node_data[rr]; + rr++; + } + return 0; } - diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 851d1f4afd1d..c9ee3ee2b491 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -26,8 +26,6 @@ static int numa_off __initdata; unsigned long nodes_present; -static int emunodes __initdata; - int __init compute_hash_shift(struct node *nodes) { int i; @@ -103,11 +101,8 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT); - if (nodeid + 1 > numnodes) { + if (nodeid + 1 > numnodes) numnodes = nodeid + 1; - printk(KERN_INFO - "setup_node_bootmem: enlarging numnodes to %d\n", numnodes); - } nodes_present |= (1UL << nodeid); } @@ -149,26 +144,6 @@ int __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) printk(KERN_INFO "%s\n", numa_off ? "NUMA turned off" : "No NUMA configuration found"); - if (!numa_off && emunodes > 0) { - struct node nodes[MAXNODE]; - unsigned long nodesize = (end_pfn << PAGE_SHIFT) / emunodes; - int i; - if (emunodes > MAXNODE) - emunodes = MAXNODE; - memset(&nodes, 0, sizeof(nodes)); - printk(KERN_INFO "Faking %d nodes of size %ld MB\n", emunodes, nodesize>>20); - for (i = 0; i < emunodes; i++) { - unsigned long end = (i+1)*nodesize; - if (i == emunodes-1) - end = end_pfn << PAGE_SHIFT; - nodes[i].start = i * nodesize; - nodes[i].end = end; - setup_node_bootmem(i, nodes[i].start, nodes[i].end); - } - memnode_shift = compute_hash_shift(nodes); - return 0; - } - printk(KERN_INFO "Faking a node at %016lx-%016lx\n", start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); @@ -176,6 +151,7 @@ int __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) fake_node = 1; memnode_shift = 63; memnodemap[0] = 0; + numnodes = 1; setup_node_bootmem(0, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); return -1; } @@ -199,13 +175,10 @@ void __init paging_init(void) } /* [numa=off] */ -/* [numa=emunodes] */ __init int numa_setup(char *opt) { if (!strncmp(opt,"off",3)) numa_off = 1; - if (isdigit(opt[0])) - emunodes = simple_strtoul(opt, NULL, 10); return 1; } diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index b3e7d4ef2024..7eb20b3e2627 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -65,7 +65,7 @@ */ #define DAC690_V1_PciDmaMask 0xffffffff -#define DAC690_V2_PciDmaMask 0xffffffffffffffff +#define DAC690_V2_PciDmaMask 0xffffffffffffffffULL /* Define a Boolean data type. diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c211537bb529..e16a993f539b 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2457,7 +2457,7 @@ static int __init cciss_init_one(struct pci_dev *pdev, hba[i]->pdev = pdev; /* configure PCI DMA stuff */ - if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) + if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) printk("cciss: using DAC cycles\n"); else if (!pci_set_dma_mask(pdev, 0xffffffff)) printk("cciss: not using DAC cycles\n"); diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 6951231d4ed5..e3136c14ef4b 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -896,13 +896,14 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags); cp = scsi_cmd_alloc(c); spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags); - ei = cp->err_info; if (cp == NULL) { /* trouble... */ printk("cmd_alloc returned NULL!\n"); return -1; } + ei = cp->err_info; + cdb[0] = CISS_INQUIRY; cdb[1] = 0; cdb[2] = 0; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 0735bd7375f3..5c254cbc322e 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -654,7 +654,7 @@ static int pd_probe_drive(struct pd_unit *disk) return pd_identify(disk); } -static struct request_queue pd_queue; +static struct request_queue *pd_queue; static int pd_detect(void) { @@ -704,7 +704,7 @@ static int pd_detect(void) set_capacity(p, disk->capacity); disk->gd = p; p->private_data = disk; - p->queue = &pd_queue; + p->queue = pd_queue; add_disk(p); } } @@ -782,7 +782,7 @@ static inline void next_request(int success) spin_lock_irqsave(&pd_lock, saved_flags); end_request(pd_req, success); pd_busy = 0; - do_pd_request(&pd_queue); + do_pd_request(pd_queue); spin_unlock_irqrestore(&pd_lock, saved_flags); } @@ -890,20 +890,30 @@ static int __init pd_init(void) { if (disable) return -1; - if (register_blkdev(major, name)) - return -1; - blk_init_queue(&pd_queue, do_pd_request, &pd_lock); - blk_queue_max_sectors(&pd_queue, cluster); + pd_queue = blk_init_queue(do_pd_request, &pd_lock); + if (!pd_queue) + goto out1; + + blk_queue_max_sectors(pd_queue, cluster); + + if (register_blkdev(major, name)) + goto out2; printk("%s: %s version %s, major %d, cluster %d, nice %d\n", name, name, PD_VERSION, major, cluster, nice); pd_init_units(); - if (!pd_detect()) { - unregister_blkdev(major, name); - return -1; - } + if (!pd_detect()) + goto out3; + return 0; + +out3: + unregister_blkdev(major, name); +out2: + blk_cleanup_queue(pd_queue); +out1: + return -1; } static void __exit pd_exit(void) @@ -920,7 +930,7 @@ static void __exit pd_exit(void) pi_release(disk->pi); } } - blk_cleanup_queue(&pd_queue); + blk_cleanup_queue(pd_queue); } MODULE_LICENSE("GPL"); diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index aa9ee0ef61a4..f17fd51b5d35 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -395,6 +395,7 @@ unsigned long agp_generic_mask_memory(unsigned long addr, int type); #define AGPSTAT 0x4 #define AGPCMD 0x8 #define AGPNISTAT 0xc +#define AGPCTRL 0x10 #define AGPNEPG 0x16 #define AGPNICMD 0x20 diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 0f3934f803bc..9f3032bfb990 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -9,8 +9,6 @@ #include <linux/agp_backend.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - static int ali_fetch_size(void) { int i; @@ -292,16 +290,10 @@ static int __init agp_ali_probe(struct pci_dev *pdev, goto found; } - 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)\n", + pdev->device); + return -ENODEV; - printk(KERN_WARNING PFX "Trying generic ALi routines" - " for device id: %04x\n", pdev->device); found: bridge = agp_alloc_bridge(); @@ -328,6 +320,7 @@ found: devs[j].chipset_name = "M1641"; break; case 0x43: + devs[j].chipset_name = "M????"; break; case 0x47: devs[j].chipset_name = "M1647"; @@ -397,7 +390,6 @@ static void __exit agp_ali_cleanup(void) module_init(agp_ali_init); module_exit(agp_ali_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 84790a7df555..51aaf5d4f811 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -11,8 +11,6 @@ #include <linux/mm.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - struct amd_page_map { unsigned long *real; unsigned long *remapped; @@ -404,16 +402,9 @@ static int __init agp_amdk7_probe(struct pci_dev *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", + printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)\n", pdev->device); - return -ENODEV; - } - - printk(KERN_WARNING PFX "Trying generic AMD routines" - " for device id: %04x\n", pdev->device); + return -ENODEV; found: bridge = agp_alloc_bridge(); @@ -476,5 +467,4 @@ static void __exit agp_amdk7_cleanup(void) module_init(agp_amdk7_init); module_exit(agp_amdk7_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index e26057c14e2a..9502d803d230 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -106,7 +106,11 @@ static int agp_find_max(void) { long memory, index, result; - memory = (num_physpages << PAGE_SHIFT) >> 20; +#if PAGE_SHIFT < 20 + memory = num_physpages >> (20 - PAGE_SHIFT); +#else + memory = num_physpages << (PAGE_SHIFT - 20); +#endif index = 1; while ((memory > maxes_table[index].mem) && (index < 8)) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index ed6cdb26e52d..50e74f6d4754 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -459,9 +459,9 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp) /* Clear out unwanted bits. */ if (*cmd & AGPSTAT3_8X) - *cmd = ~(AGPSTAT3_4X | AGPSTAT3_RSVD); + *cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); if (*cmd & AGPSTAT3_4X) - *cmd = ~(AGPSTAT3_8X | AGPSTAT3_RSVD); + *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); } //FIXME: This doesn't smell right. @@ -545,7 +545,7 @@ EXPORT_SYMBOL(get_agp_version); void agp_generic_enable(u32 mode) { - u32 command; + u32 command, temp; u32 agp3; get_agp_version(agp_bridge); @@ -577,7 +577,13 @@ void agp_generic_enable(u32 mode) agp_device_command(command, TRUE); return; } else { - printk (KERN_INFO PFX "Device is in legacy mode," + /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/ + command &= ~(7<<10) ; + pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp); + temp |= (1<<9); + pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp); + + printk (KERN_INFO PFX "Device is in legacy mode," " falling back to 2.x\n"); } } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index f99aafb56de5..d908c004990b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -13,9 +13,6 @@ #include <linux/agp_backend.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - - static struct aper_size_info_fixed intel_i810_sizes[] = { {64, 16384, 4}, @@ -1358,15 +1355,9 @@ static int __init agp_intel_probe(struct pci_dev *pdev, 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", + printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n", pdev->device); - return -ENODEV; - } - bridge->driver = &intel_generic_driver; - break; + return -ENODEV; }; bridge->dev = pdev; @@ -1485,6 +1476,5 @@ static void __exit agp_intel_cleanup(void) module_init(agp_intel_init); module_exit(agp_intel_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index ed34f4ffc982..cf76ee9c4090 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -25,9 +25,6 @@ #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; @@ -299,17 +296,9 @@ static int __init agp_nvidia_probe(struct pci_dev *pdev, 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", + printk(KERN_ERR PFX "Unsupported NVIDIA chipset (device id: %04x)\n", pdev->device); - return -ENODEV; - } - printk(KERN_WARNING PFX - "Trying generic NVIDIA routines for device id: %04x\n", - pdev->device); - break; + return -ENODEV; } bridge = agp_alloc_bridge(); @@ -372,7 +361,6 @@ static void __exit agp_nvidia_cleanup(void) 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 --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 7ebe1e362f3f..567b0d511add 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -8,8 +8,6 @@ #include <linux/agp_backend.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - static int sis_fetch_size(void) { u8 temp_size; @@ -187,16 +185,9 @@ static int __init agp_sis_probe(struct pci_dev *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", + printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n", pdev->device); - return -ENODEV; - } - - printk(KERN_WARNING PFX "Trying generic SiS routines" - " for device id: %04x\n", pdev->device); + return -ENODEV; found: bridge = agp_alloc_bridge(); @@ -258,5 +249,4 @@ static void __exit agp_sis_cleanup(void) module_init(agp_sis_init); module_exit(agp_sis_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 6ad6cd5ff57b..5e9ff6f2107a 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -8,8 +8,6 @@ #include <linux/agp_backend.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - struct serverworks_page_map { unsigned long *real; unsigned long *remapped; @@ -457,9 +455,9 @@ static int __init agp_serverworks_probe(struct pci_dev *pdev, case 0x0007: break; default: - if (!agp_try_unsupported) - return -ENODEV; - break; + printk(KERN_ERR PFX "Unsupported Serverworks chipset " + "(device id: %04x)\n", pdev->device); + return -ENODEV; } serverworks_private.svrwrks_dev = bridge_dev; @@ -542,6 +540,5 @@ static void __exit agp_serverworks_cleanup(void) module_init(agp_serverworks_init); module_exit(agp_serverworks_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index e4192313d73e..c75ec0120bd5 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -10,8 +10,6 @@ #include <asm/pci-bridge.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - static int uninorth_fetch_size(void) { int i; @@ -324,15 +322,9 @@ static int __init agp_uninorth_probe(struct pci_dev *pdev, } } - if (!agp_try_unsupported) { - printk(KERN_ERR PFX "Unsupported Apple chipset" - " (device id: %04x).\n", pdev->device); - printk(KERN_ERR PFX "You might want to try" - " agp_try_unsupported=1\n"); - return -ENODEV; - } - printk(KERN_ERR PFX "Trying generic Uninorth routines" - " for device id %04x\n", pdev->device); + printk(KERN_ERR PFX "Unsupported Apple chipset (device id: %04x).\n", + pdev->device); + return -ENODEV; found: bridge = agp_alloc_bridge(); @@ -392,6 +384,5 @@ static void __exit agp_uninorth_cleanup(void) module_init(agp_uninorth_init); module_exit(agp_uninorth_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index f421458432a3..8726826adbc9 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -9,9 +9,6 @@ #include <linux/agp_backend.h> #include "agp.h" -static int agp_try_unsupported __initdata = 0; - - static int via_fetch_size(void) { int i; @@ -123,6 +120,14 @@ static int via_configure_agp3(void) /* attbase - aperture GATT base */ pci_write_config_dword(agp_bridge->dev, VIA_AGP3_ATTBASE, agp_bridge->gatt_bus_addr & 0xfffff000); + + /* 1. Enable GTLB in RX90<7>, all AGP aperture access needs to fetch + * translation table first. + * 2. Enable AGP aperture in RX91<0>. This bit controls the enabling of the + * graphics AGP aperture for the AGP3.0 port. + */ + pci_read_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, &temp); + pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp | (3<<7)); return 0; } @@ -382,16 +387,9 @@ static int __init agp_via_probe(struct pci_dev *pdev, } } - if (!agp_try_unsupported) { - printk(KERN_ERR PFX - "Unsupported VIA chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", + printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)\n", pdev->device); - return -ENODEV; - } - - printk(KERN_WARNING PFX "Trying generic VIA routines" - " for device id: %04x\n", pdev->device); + return -ENODEV; found: bridge = agp_alloc_bridge(); @@ -470,6 +468,5 @@ static void __exit agp_via_cleanup(void) module_init(agp_via_init); module_exit(agp_via_cleanup); -MODULE_PARM(agp_try_unsupported, "1i"); MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); diff --git a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h index 67e91b6e5aa0..12c41a051c11 100644 --- a/drivers/char/drm/drm_agpsupport.h +++ b/drivers/char/drm/drm_agpsupport.h @@ -105,7 +105,8 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp, if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) return -EINVAL; - if ((retcode = drm_agp->acquire())) return retcode; + if ((retcode = drm_agp->acquire())) + return retcode; dev->agp->acquired = 1; return 0; } @@ -142,7 +143,8 @@ int DRM(agp_release)(struct inode *inode, struct file *filp, */ void DRM(agp_do_release)(void) { - if (drm_agp->release) drm_agp->release(); + if (drm_agp->release) + drm_agp->release(); } /** @@ -200,7 +202,8 @@ int DRM(agp_alloc)(struct inode *inode, struct file *filp, unsigned long pages; u32 type; - if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (!dev->agp || !dev->agp->acquired) + return -EINVAL; if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) return -EFAULT; if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS))) @@ -222,11 +225,12 @@ int DRM(agp_alloc)(struct inode *inode, struct file *filp, entry->pages = pages; entry->prev = NULL; entry->next = dev->agp->memory; - if (dev->agp->memory) dev->agp->memory->prev = entry; + if (dev->agp->memory) + dev->agp->memory->prev = entry; dev->agp->memory = entry; request.handle = entry->handle; - request.physical = memory->physical; + request.physical = memory->physical; if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) { dev->agp->memory = entry->next; @@ -253,7 +257,8 @@ static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev, drm_agp_mem_t *entry; for (entry = dev->agp->memory; entry; entry = entry->next) { - if (entry->handle == handle) return entry; + if (entry->handle == handle) + return entry; } return NULL; } @@ -279,12 +284,14 @@ int DRM(agp_unbind)(struct inode *inode, struct file *filp, drm_agp_mem_t *entry; int ret; - if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (!dev->agp || !dev->agp->acquired) + return -EINVAL; if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) return -EFAULT; if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) return -EINVAL; - if (!entry->bound) return -EINVAL; + if (!entry->bound) + return -EINVAL; ret = DRM(unbind_agp)(entry->memory); if (ret == 0) entry->bound = 0; @@ -320,9 +327,11 @@ int DRM(agp_bind)(struct inode *inode, struct file *filp, return -EFAULT; if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) return -EINVAL; - if (entry->bound) return -EINVAL; + if (entry->bound) + return -EINVAL; page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; - if ((retcode = DRM(bind_agp)(entry->memory, page))) return retcode; + if ((retcode = DRM(bind_agp)(entry->memory, page))) + return retcode; entry->bound = dev->agp->base + (page << PAGE_SHIFT); DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", dev->agp->base, entry->bound); @@ -351,16 +360,23 @@ int DRM(agp_free)(struct inode *inode, struct file *filp, drm_agp_buffer_t request; drm_agp_mem_t *entry; - if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (!dev->agp || !dev->agp->acquired) + return -EINVAL; if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) return -EFAULT; if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) return -EINVAL; - if (entry->bound) DRM(unbind_agp)(entry->memory); + if (entry->bound) + DRM(unbind_agp)(entry->memory); + + if (entry->prev) + entry->prev->next = entry->next; + else + dev->agp->memory = entry->next; + + if (entry->next) + entry->next->prev = entry->prev; - if (entry->prev) entry->prev->next = entry->next; - else dev->agp->memory = entry->next; - if (entry->next) entry->next->prev = entry->prev; DRM(free_agp)(entry->memory, entry->pages); DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); return 0; @@ -415,14 +431,16 @@ void DRM(agp_uninit)(void) /** Calls drm_agp->allocate_memory() */ struct agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type) { - if (!drm_agp->allocate_memory) return NULL; + if (!drm_agp->allocate_memory) + return NULL; return drm_agp->allocate_memory(pages, type); } /** Calls drm_agp->free_memory() */ int DRM(agp_free_memory)(struct agp_memory *handle) { - if (!handle || !drm_agp->free_memory) return 0; + if (!handle || !drm_agp->free_memory) + return 0; drm_agp->free_memory(handle); return 1; } @@ -430,14 +448,16 @@ int DRM(agp_free_memory)(struct agp_memory *handle) /** Calls drm_agp->bind_memory() */ int DRM(agp_bind_memory)(struct agp_memory *handle, off_t start) { - if (!handle || !drm_agp->bind_memory) return -EINVAL; + if (!handle || !drm_agp->bind_memory) + return -EINVAL; return drm_agp->bind_memory(handle, start); } /** Calls drm_agp->unbind_memory() */ int DRM(agp_unbind_memory)(struct agp_memory *handle) { - if (!handle || !drm_agp->unbind_memory) return -EINVAL; + if (!handle || !drm_agp->unbind_memory) + return -EINVAL; return drm_agp->unbind_memory(handle); } diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c index 9608c37a1b77..9a8eba82b9dc 100644 --- a/drivers/char/drm/gamma_dma.c +++ b/drivers/char/drm/gamma_dma.c @@ -44,9 +44,14 @@ static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address, drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; mb(); - while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2); + while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2) + cpu_relax(); + GAMMA_WRITE(GAMMA_DMAADDRESS, address); - while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4); + + while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4) + cpu_relax(); + GAMMA_WRITE(GAMMA_DMACOUNT, length / 4); } @@ -54,16 +59,18 @@ void gamma_dma_quiescent_single(drm_device_t *dev) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; - while (GAMMA_READ(GAMMA_DMACOUNT)); + while (GAMMA_READ(GAMMA_DMACOUNT)) + cpu_relax(); - while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2); + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2) + cpu_relax(); GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); GAMMA_WRITE(GAMMA_SYNC, 0); do { while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) - ; + cpu_relax(); } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); } @@ -71,9 +78,11 @@ void gamma_dma_quiescent_dual(drm_device_t *dev) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; - while (GAMMA_READ(GAMMA_DMACOUNT)); + while (GAMMA_READ(GAMMA_DMACOUNT)) + cpu_relax(); - while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3); + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) + cpu_relax(); GAMMA_WRITE(GAMMA_BROADCASTMASK, 3); GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); @@ -81,12 +90,14 @@ void gamma_dma_quiescent_dual(drm_device_t *dev) /* Read from first MX */ do { - while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)); + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) + cpu_relax(); } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); /* Read from second MX */ do { - while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)); + while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)) + cpu_relax(); } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG); } @@ -94,14 +105,15 @@ void gamma_dma_ready(drm_device_t *dev) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; - while (GAMMA_READ(GAMMA_DMACOUNT)); + while (GAMMA_READ(GAMMA_DMACOUNT)) + cpu_relax(); } static inline int gamma_dma_is_ready(drm_device_t *dev) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; - return(!GAMMA_READ(GAMMA_DMACOUNT)); + return (!GAMMA_READ(GAMMA_DMACOUNT)); } irqreturn_t gamma_dma_service(int irq, void *device, struct pt_regs *regs) @@ -113,7 +125,9 @@ irqreturn_t gamma_dma_service(int irq, void *device, struct pt_regs *regs) atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */ - while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3); + while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) + cpu_relax(); + GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */ GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8); GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001); @@ -824,7 +838,8 @@ void DRM(driver_irq_preinstall)( drm_device_t *dev ) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; - while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2); + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2) + cpu_relax(); GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000004 ); GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 ); @@ -834,7 +849,8 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; - while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3); + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3) + cpu_relax(); GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 ); GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 ); @@ -847,7 +863,8 @@ void DRM(driver_irq_uninstall)( drm_device_t *dev ) { if (!dev_priv) return; - while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3); + while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3) + cpu_relax(); GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 ); GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 ); diff --git a/drivers/char/ipmi/ipmi_kcs_intf.c b/drivers/char/ipmi/ipmi_kcs_intf.c index e47ab34a809f..c28cdfc7bfd0 100644 --- a/drivers/char/ipmi/ipmi_kcs_intf.c +++ b/drivers/char/ipmi/ipmi_kcs_intf.c @@ -1018,52 +1018,81 @@ static int init_one_kcs(int kcs_port, #ifdef CONFIG_ACPI_INTERPRETER -/* Retrieve the base physical address from ACPI tables. Originally - from Hewlett-Packard simple bmc.c, a GPL KCS driver. */ - #include <linux/acpi.h> struct SPMITable { - s8 Signature[4]; - u32 Length; - u8 Revision; - u8 Checksum; - s8 OEMID[6]; - s8 OEMTableID[8]; - s8 OEMRevision[4]; - s8 CreatorID[4]; - s8 CreatorRevision[4]; - s16 InterfaceType; - s16 SpecificationRevision; - u8 InterruptType; - u8 GPE; - s16 Reserved; - u64 GlobalSystemInterrupt; - u8 BaseAddress[12]; - u8 UID[4]; -} __attribute__ ((packed)); - -static unsigned long acpi_find_bmc(void) -{ - acpi_status status; - struct acpi_table_header *spmi; - static unsigned long io_base = 0; - - if (io_base != 0) - return io_base; + s8 Signature[4]; + u32 Length; + u8 Revision; + u8 Checksum; + s8 OEMID[6]; + s8 OEMTableID[8]; + s8 OEMRevision[4]; + s8 CreatorID[4]; + s8 CreatorRevision[4]; + u8 InterfaceType[2]; + s16 SpecificationRevision; + + /* + * Bit 0 - SCI interrupt supported + * Bit 1 - I/O APIC/SAPIC + */ + u8 InterruptType; + + /* If bit 0 of InterruptType is set, then this is the SCI + interrupt in the GPEx_STS register. */ + u8 GPE; + + s16 Reserved; + + /* If bit 1 of InterruptType is set, then this is the I/O + APIC/SAPIC interrupt. */ + u32 GlobalSystemInterrupt; + + /* The actual register address. */ + struct acpi_generic_address addr; + + u8 UID[4]; + + s8 spmi_id[1]; /* A '\0' terminated array starts here. */ +}; +static int acpi_find_bmc(unsigned long *physaddr, int *port) +{ + acpi_status status; + struct SPMITable *spmi; + status = acpi_get_firmware_table("SPMI", 1, - ACPI_LOGICAL_ADDRESSING, &spmi); + ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) &spmi); + if (status != AE_OK) + goto not_found; + + if (spmi->InterfaceType[0] != 1) + /* Not IPMI. */ + goto not_found; + + if (spmi->InterfaceType[1] != 1) + /* Not KCS. */ + goto not_found; + + if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + *physaddr = spmi->addr.address; + printk("ipmi_kcs_intf: Found ACPI-specified state machine" + " at memory address 0x%lx\n", + (unsigned long) spmi->addr.address); + } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { + *port = spmi->addr.address; + printk("ipmi_kcs_intf: Found ACPI-specified state machine" + " at I/O address 0x%lx\n", + (int) spmi->addr.address); + } else + goto not_found; /* Not an address type we recognise. */ - if (status != AE_OK) { - printk(KERN_ERR "ipmi_kcs: SPMI table not found.\n"); - return 0; - } + return 0; - memcpy(&io_base, ((struct SPMITable *)spmi)->BaseAddress, - sizeof(io_base)); - - return io_base; + not_found: + return -ENODEV; } #endif @@ -1074,6 +1103,7 @@ static __init int init_ipmi_kcs(void) int i = 0; #ifdef CONFIG_ACPI_INTERPRETER unsigned long physaddr = 0; + int port = 0; #endif if (initialized) @@ -1101,20 +1131,19 @@ static __init int init_ipmi_kcs(void) /* Only try the defaults if enabled and resources are available (because they weren't already specified above). */ - if (kcs_trydefaults) { + if (kcs_trydefaults && (pos == 0)) { + rv = -EINVAL; #ifdef CONFIG_ACPI_INTERPRETER - if ((physaddr = acpi_find_bmc())) { - if (!check_mem_region(physaddr, 2)) { - rv = init_one_kcs(0, - 0, - physaddr, - &(kcs_infos[pos])); - if (rv == 0) - pos++; - } + if (rv && (physaddr = acpi_find_bmc(&physaddr, &port) == 0)) { + rv = init_one_kcs(port, + 0, + physaddr, + &(kcs_infos[pos])); + if (rv == 0) + pos++; } #endif - if (!check_region(DEFAULT_IO_PORT, 2)) { + if (rv) { rv = init_one_kcs(DEFAULT_IO_PORT, 0, 0, diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 4eab8908181e..185ed6ade2a2 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -559,7 +559,10 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, case WDIOC_GETSTATUS: val = 0; - return copy_to_user((void *) arg, &val, sizeof(val)); + i = copy_to_user((void *) arg, &val, sizeof(val)); + if (i) + return -EFAULT; + return 0; default: return -ENOIOCTLCMD; diff --git a/drivers/char/random.c b/drivers/char/random.c index 86db1af9e2f0..d7d8f909f3e4 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1850,27 +1850,62 @@ static int uuid_strategy(ctl_table *table, int *name, int nlen, } ctl_table random_table[] = { - {RANDOM_POOLSIZE, "poolsize", - &sysctl_poolsize, sizeof(int), 0644, NULL, - &proc_do_poolsize, &poolsize_strategy}, - {RANDOM_ENTROPY_COUNT, "entropy_avail", - NULL, sizeof(int), 0444, NULL, - &proc_dointvec}, - {RANDOM_READ_THRESH, "read_wakeup_threshold", - &random_read_wakeup_thresh, sizeof(int), 0644, NULL, - &proc_dointvec_minmax, &sysctl_intvec, 0, - &min_read_thresh, &max_read_thresh}, - {RANDOM_WRITE_THRESH, "write_wakeup_threshold", - &random_write_wakeup_thresh, sizeof(int), 0644, NULL, - &proc_dointvec_minmax, &sysctl_intvec, 0, - &min_write_thresh, &max_write_thresh}, - {RANDOM_BOOT_ID, "boot_id", - &sysctl_bootid, 16, 0444, NULL, - &proc_do_uuid, &uuid_strategy}, - {RANDOM_UUID, "uuid", - NULL, 16, 0444, NULL, - &proc_do_uuid, &uuid_strategy}, - {0} + { + .ctl_name = RANDOM_POOLSIZE, + .procname = "poolsize", + .data = &sysctl_poolsize, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_do_poolsize, + .strategy = &poolsize_strategy, + }, + { + .ctl_name = RANDOM_ENTROPY_COUNT, + .procname = "entropy_avail", + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = RANDOM_READ_THRESH, + .procname = "read_wakeup_threshold", + .data = &random_read_wakeup_thresh, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &min_read_thresh, + .extra2 = &max_read_thresh, + }, + { + .ctl_name = RANDOM_WRITE_THRESH, + .procname = "write_wakeup_threshold", + .data = &random_write_wakeup_thresh, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &min_write_thresh, + .extra2 = &max_write_thresh, + }, + { + .ctl_name = RANDOM_BOOT_ID, + .procname = "boot_id", + .data = &sysctl_bootid, + .maxlen = 16, + .mode = 0444, + .proc_handler = &proc_do_uuid, + .strategy = &uuid_strategy, + }, + { + .ctl_name = RANDOM_UUID, + .procname = "uuid", + .maxlen = 16, + .mode = 0444, + .proc_handler = &proc_do_uuid, + .strategy = &uuid_strategy, + }, + { .ctl_name = 0 } }; static void sysctl_init_random(struct entropy_store *random_state) diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index e98826092f8c..323fc2019e2a 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c @@ -1,26 +1,11 @@ /* - * ALi M7101 PMU Computer Watchdog Timer driver for Linux 2.4.x + * ALi M7101 PMU Computer Watchdog Timer driver * - * Based on w83877f_wdt.c by Scott Jennings <management@oro.net> + * Based on w83877f_wdt.c by Scott Jennings <linuxdrivers@oro.net> * and the Cobalt kernel WDT timer driver by Tim Hockin * <thockin@cobaltnet.com> * * (c)2002 Steve Hill <steve@navaho.co.uk> - * - * Theory of operation: - * A Watchdog Timer (WDT) is a hardware circuit that can - * reset the computer system in case of a software fault. - * You probably knew that already. - * - * Usually a userspace daemon will notify the kernel WDT driver - * via the /proc/watchdog special device file that userspace is - * still alive, at regular intervals. When such a notification - * occurs, the driver will usually tell the hardware watchdog - * that everything is in order, and that the watchdog should wait - * for yet another little while to reset the system. - * If userspace fails (RAM error, kernel bug, whatever), the - * notifications cease to occur, and the hardware watchdog will - * reset the system (causing a reboot) after the timeout occurs. * * This WDT driver is different from most other Linux WDT * drivers in that the driver will ping the watchdog by itself, @@ -30,6 +15,7 @@ */ #include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/types.h> #include <linux/timer.h> #include <linux/miscdevice.h> @@ -38,7 +24,6 @@ #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> -#include <linux/moduleparam.h> #include <linux/pci.h> #include <asm/io.h> @@ -46,6 +31,7 @@ #include <asm/system.h> #define OUR_NAME "alim7101_wdt" +#define PFX OUR_NAME ": " #define WDT_ENABLE 0x9C #define WDT_DISABLE 0x8C @@ -65,13 +51,16 @@ * char to /dev/watchdog every 30 seconds. */ -#define WDT_HEARTBEAT (HZ * 30) +#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ +static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); static void wdt_timer_ping(unsigned long); static struct timer_list timer; static unsigned long next_heartbeat; static unsigned long wdt_is_open; -static int wdt_expect_close; +static char wdt_expect_close; static struct pci_dev *alim7101_pmu; #ifdef CONFIG_WATCHDOG_NOWAYOUT @@ -79,7 +68,7 @@ static int nowayout = 1; #else static int nowayout = 0; #endif - + module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); @@ -90,25 +79,25 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON static void wdt_timer_ping(unsigned long data) { /* If we got a heartbeat pulse within the WDT_US_INTERVAL - * we agree to ping the WDT + * we agree to ping the WDT */ char tmp; - if(time_before(jiffies, next_heartbeat)) + if(time_before(jiffies, next_heartbeat)) { /* Ping the WDT (this is actually a disarm/arm sequence) */ pci_read_config_byte(alim7101_pmu, 0x92, &tmp); pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM)); } else { - printk(KERN_INFO OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); + printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } /* Re-set the timer interval */ timer.expires = jiffies + WDT_INTERVAL; add_timer(&timer); } -/* +/* * Utility routines */ @@ -125,7 +114,7 @@ static void wdt_change(int writeval) static void wdt_startup(void) { - next_heartbeat = jiffies + WDT_HEARTBEAT; + next_heartbeat = jiffies + (timeout * HZ); /* We must enable before we kick off the timer in case the timer occurs as we ping it */ @@ -133,11 +122,11 @@ static void wdt_startup(void) wdt_change(WDT_ENABLE); /* Start the timer */ - timer.expires = jiffies + WDT_INTERVAL; + timer.expires = jiffies + WDT_INTERVAL; add_timer(&timer); - printk(KERN_INFO OUR_NAME ": Watchdog timer is now enabled.\n"); + printk(KERN_INFO PFX "Watchdog timer is now enabled.\n"); } static void wdt_turnoff(void) @@ -145,7 +134,13 @@ static void wdt_turnoff(void) /* Stop the timer */ del_timer_sync(&timer); wdt_change(WDT_DISABLE); - printk(KERN_INFO OUR_NAME ": Watchdog timer is now disabled...\n"); + printk(KERN_INFO PFX "Watchdog timer is now disabled...\n"); +} + +static void wdt_keepalive(void) +{ + /* user land ping */ + next_heartbeat = jiffies + (timeout * HZ); } /* @@ -158,7 +153,7 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof if(ppos != &file->f_pos) return -ESPIPE; - /* See if we got the magic character */ + /* See if we got the magic character 'V' and reload the timer */ if(count) { if (!nowayout) { size_t ofs; @@ -173,14 +168,13 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof if (get_user(c, buf+ofs)) return -EFAULT; if (c == 'V') - wdt_expect_close = 1; + wdt_expect_close = 42; } } /* someone wrote to us, we should restart timer */ - next_heartbeat = jiffies + WDT_HEARTBEAT; - return 1; - }; - return 0; + wdt_keepalive(); + } + return count; } static int fop_open(struct inode * inode, struct file * file) @@ -195,12 +189,14 @@ static int fop_open(struct inode * inode, struct file * file) static int fop_close(struct inode * inode, struct file * file) { - if(wdt_expect_close) + if(wdt_expect_close == 42) wdt_turnoff(); - else - printk(KERN_INFO OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); - + else { + /* wim: shouldn't there be a: del_timer(&timer); */ + printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); + } clear_bit(0, &wdt_is_open); + wdt_expect_close = 0; return 0; } @@ -208,20 +204,58 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u { static struct watchdog_info ident = { - .options = WDIOF_MAGICCLOSE, + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, - .identity = "ALiM7101" + .identity = "ALiM7101", }; - + switch(cmd) { case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: - next_heartbeat = jiffies + WDT_HEARTBEAT; + wdt_keepalive(); return 0; + case WDIOC_SETOPTIONS: + { + int new_options, retval = -EINVAL; + + if(get_user(new_options, (int *)arg)) + return -EFAULT; + + if(new_options & WDIOS_DISABLECARD) { + wdt_turnoff(); + retval = 0; + } + + if(new_options & WDIOS_ENABLECARD) { + wdt_startup(); + retval = 0; + } + + return retval; + } + case WDIOC_SETTIMEOUT: + { + int new_timeout; + + if(get_user(new_timeout, (int *)arg)) + return -EFAULT; + + if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ + return -EINVAL; + + timeout = new_timeout; + wdt_keepalive(); + /* Fall through */ + } + case WDIOC_GETTIMEOUT: + return put_user(timeout, (int *)arg); default: - return -ENOTTY; + return -ENOIOCTLCMD; } } @@ -231,13 +265,13 @@ static struct file_operations wdt_fops = { .write= fop_write, .open= fop_open, .release= fop_close, - .ioctl= fop_ioctl + .ioctl= fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor=WATCHDOG_MINOR, .name="watchdog", - .fops=&wdt_fops + .fops=&wdt_fops, }; /* @@ -256,21 +290,21 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void * reboot with no heartbeat */ wdt_change(WDT_ENABLE); - printk(KERN_INFO OUR_NAME ": Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n"); + printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n"); } return NOTIFY_DONE; } - + /* * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. + * turn the timebomb registers off. */ - + static struct notifier_block wdt_notifier= { .notifier_call = wdt_notify_sys, .next = 0, - .priority = 0 + .priority = 0, }; static void __exit alim7101_wdt_unload(void) @@ -287,10 +321,10 @@ static int __init alim7101_wdt_init(void) struct pci_dev *ali1543_south; char tmp; - printk(KERN_INFO OUR_NAME ": Steve Hill <steve@navaho.co.uk>.\n"); + printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n"); alim7101_pmu = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,NULL); if (!alim7101_pmu) { - printk(KERN_INFO OUR_NAME ": ALi M7101 PMU not present - WDT not set\n"); + printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n"); return -EBUSY; } @@ -299,35 +333,53 @@ static int __init alim7101_wdt_init(void) ali1543_south = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!ali1543_south) { - printk(KERN_INFO OUR_NAME ": ALi 1543 South-Bridge not present - WDT not set\n"); + printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); return -EBUSY; } pci_read_config_byte(ali1543_south, 0x5e, &tmp); if ((tmp & 0x1e) != 0x12) { - printk(KERN_INFO OUR_NAME ": ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); + printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); return -EBUSY; } + if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ + { + timeout = WATCHDOG_TIMEOUT; + printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", + timeout); + } + init_timer(&timer); timer.function = wdt_timer_ping; timer.data = 1; rc = misc_register(&wdt_miscdev); - if (rc) - return rc; + if (rc) { + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + wdt_miscdev.minor, rc); + goto err_out; + } rc = register_reboot_notifier(&wdt_notifier); if (rc) { - misc_deregister(&wdt_miscdev); - return rc; + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + rc); + goto err_out_miscdev; } - printk(KERN_INFO OUR_NAME ": WDT driver for ALi M7101 initialised.\n"); + printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n", + timeout, nowayout); return 0; + +err_out_miscdev: + misc_deregister(&wdt_miscdev); +err_out: + return rc; } module_init(alim7101_wdt_init); module_exit(alim7101_wdt_unload); MODULE_AUTHOR("Steve Hill"); +MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 19979dfe0185..a2ca29f6a896 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -1,21 +1,21 @@ /* - * AMD Elan SC520 processor Watchdog Timer driver for Linux 2.4.x + * AMD Elan SC520 processor Watchdog Timer driver * * Based on acquirewdt.c by Alan Cox, - * and sbc60xxwdt.c by Jakob Oestergaard <jakob@ostenfeld.dk> - * + * and sbc60xxwdt.c by Jakob Oestergaard <jakob@unthought.net> + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * The authors do NOT admit liability nor provide warranty for - * any of this software. This material is provided "AS-IS" in + * + * The authors do NOT admit liability nor provide warranty for + * any of this software. This material is provided "AS-IS" in * the hope that it may be useful for others. * * (c) Copyright 2001 Scott Jennings <linuxdrivers@oro.net> * 9/27 - 2001 [Initial release] - * + * * Additional fixes Alan Cox * - Fixed formatting * - Removed debug printks @@ -24,20 +24,21 @@ * - Used ioremap/writew/readw * - Added NOWAYOUT support * - * Theory of operation: - * A Watchdog Timer (WDT) is a hardware circuit that can - * reset the computer system in case of a software fault. - * You probably knew that already. - * - * Usually a userspace daemon will notify the kernel WDT driver - * via the /proc/watchdog special device file that userspace is - * still alive, at regular intervals. When such a notification - * occurs, the driver will usually tell the hardware watchdog - * that everything is in order, and that the watchdog should wait - * for yet another little while to reset the system. - * If userspace fails (RAM error, kernel bug, whatever), the - * notifications cease to occur, and the hardware watchdog will - * reset the system (causing a reboot) after the timeout occurs. + * 4/12 - 2002 Changes by Rob Radez <rob@osinvestor.com> + * - Change comments + * - Eliminate fop_llseek + * - Change CONFIG_WATCHDOG_NOWAYOUT semantics + * - Add KERN_* tags to printks + * - fix possible wdt_is_open race + * - Report proper capabilities in watchdog_info + * - Add WDIOC_{GETSTATUS, GETBOOTSTATUS, SETTIMEOUT, + * GETTIMEOUT, SETOPTIONS} ioctls + * 09/8 - 2003 Changes by Wim Van Sebroeck <wim@iguana.be> + * - cleanup of trailing spaces + * - added extra printk's for startup problems + * - use module_param + * - made timeout (the emulated heartbeat) a module_param + * - made the keepalive ping an internal subroutine * * This WDT driver is different from most other Linux WDT * drivers in that the driver will ping the watchdog by itself, @@ -77,7 +78,10 @@ * char to /dev/watchdog every 30 seconds. */ -#define WDT_HEARTBEAT (HZ * 30) +#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ +static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); /* * AMD Elan SC520 timeout value is 492us times a power of 2 (0-7) @@ -95,6 +99,7 @@ #define WDT_WRST_ENB 0x4000 /* [14] Watchdog Timer Reset Enable */ #define OUR_NAME "sc520_wdt" +#define PFX OUR_NAME ": " #define WRT_DOG(data) *wdtmrctl=data @@ -104,7 +109,8 @@ static void wdt_timer_ping(unsigned long); static struct timer_list timer; static unsigned long next_heartbeat; static unsigned long wdt_is_open; -static int wdt_expect_close; +static char wdt_expect_close; +static spinlock_t wdt_spinlock; #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -115,7 +121,6 @@ static int nowayout = 0; module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -static spinlock_t wdt_spinlock; /* * Whack the dog */ @@ -123,9 +128,9 @@ static spinlock_t wdt_spinlock; static void wdt_timer_ping(unsigned long data) { /* If we got a heartbeat pulse within the WDT_US_INTERVAL - * we agree to ping the WDT + * we agree to ping the WDT */ - if(time_before(jiffies, next_heartbeat)) + if(time_before(jiffies, next_heartbeat)) { /* Ping the WDT */ spin_lock(&wdt_spinlock); @@ -137,11 +142,11 @@ static void wdt_timer_ping(unsigned long data) timer.expires = jiffies + WDT_INTERVAL; add_timer(&timer); } else { - printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n"); + printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } } -/* +/* * Utility routines */ @@ -165,14 +170,14 @@ static void wdt_config(int writeval) static void wdt_startup(void) { - next_heartbeat = jiffies + WDT_HEARTBEAT; + next_heartbeat = jiffies + (timeout * HZ); /* Start the timer */ - timer.expires = jiffies + WDT_INTERVAL; + timer.expires = jiffies + WDT_INTERVAL; add_timer(&timer); wdt_config(WDT_ENB | WDT_WRST_ENB | TIMEOUT_EXPONENT); - printk(OUR_NAME ": Watchdog timer is now enabled.\n"); + printk(KERN_INFO PFX "Watchdog timer is now enabled.\n"); } static void wdt_turnoff(void) @@ -181,10 +186,15 @@ static void wdt_turnoff(void) /* Stop the timer */ del_timer(&timer); wdt_config(0); - printk(OUR_NAME ": Watchdog timer is now disabled...\n"); + printk(KERN_INFO PFX "Watchdog timer is now disabled...\n"); } } +static void wdt_keepalive(void) +{ + /* user land ping */ + next_heartbeat = jiffies + (timeout * HZ); +} /* * /dev/watchdog handling @@ -196,62 +206,56 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof if(ppos != &file->f_pos) return -ESPIPE; - /* See if we got the magic character */ - if(count) + /* See if we got the magic character 'V' and reload the timer */ + if(count) { - size_t ofs; - - /* note: just in case someone wrote the magic character - * five months ago... */ - wdt_expect_close = 0; - - /* now scan */ - for(ofs = 0; ofs != count; ofs++) { - char c; - if (get_user(c, buf + ofs)) - return -EFAULT; - if(c == 'V') - wdt_expect_close = 1; + if (!nowayout) + { + size_t ofs; + + /* note: just in case someone wrote the magic character + * five months ago... */ + wdt_expect_close = 0; + + /* now scan */ + for(ofs = 0; ofs != count; ofs++) { + char c; + if (get_user(c, buf + ofs)) + return -EFAULT; + if(c == 'V') + wdt_expect_close = 42; + } } /* Well, anyhow someone wrote to us, we should return that favour */ - next_heartbeat = jiffies + WDT_HEARTBEAT; - return 1; + wdt_keepalive(); } - return 0; + return count; } static int fop_open(struct inode * inode, struct file * file) { - switch(minor(inode->i_rdev)) - { - case WATCHDOG_MINOR: - /* Just in case we're already talking to someone... */ - if(test_and_set_bit(0, &wdt_is_open)) - return -EBUSY; - /* Good, fire up the show */ - wdt_startup(); - if (nowayout) - __module_get(THIS_MODULE); - - return 0; - default: - return -ENODEV; - } + /* Just in case we're already talking to someone... */ + if(test_and_set_bit(0, &wdt_is_open)) + return -EBUSY; + if (nowayout) + __module_get(THIS_MODULE); + + /* Good, fire up the show */ + wdt_startup(); + return 0; } static int fop_close(struct inode * inode, struct file * file) { - if(minor(inode->i_rdev) == WATCHDOG_MINOR) - { - if(wdt_expect_close) - wdt_turnoff(); - else { - del_timer(&timer); - printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n"); - } + if(wdt_expect_close == 42) + wdt_turnoff(); + else { + del_timer(&timer); + printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); } clear_bit(0, &wdt_is_open); + wdt_expect_close = 0; return 0; } @@ -260,20 +264,58 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, { static struct watchdog_info ident= { - .options = WDIOF_MAGICCLOSE, + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, - .identity = "SC520" + .identity = "SC520", }; - + switch(cmd) { default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: - next_heartbeat = jiffies + WDT_HEARTBEAT; + wdt_keepalive(); return 0; + case WDIOC_SETOPTIONS: + { + int new_options, retval = -EINVAL; + + if(get_user(new_options, (int *)arg)) + return -EFAULT; + + if(new_options & WDIOS_DISABLECARD) { + wdt_turnoff(); + retval = 0; + } + + if(new_options & WDIOS_ENABLECARD) { + wdt_startup(); + retval = 0; + } + + return retval; + } + case WDIOC_SETTIMEOUT: + { + int new_timeout; + + if(get_user(new_timeout, (int *)arg)) + return -EFAULT; + + if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ + return -EINVAL; + + timeout = new_timeout; + wdt_keepalive(); + /* Fall through */ + } + case WDIOC_GETTIMEOUT: + return put_user(timeout, (int *)arg); } } @@ -283,13 +325,13 @@ static struct file_operations wdt_fops = { .write = fop_write, .open = fop_open, .release = fop_close, - .ioctl = fop_ioctl + .ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", - .fops = &wdt_fops + .fops = &wdt_fops, }; /* @@ -299,21 +341,21 @@ static struct miscdevice wdt_miscdev = { static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { - if(code==SYS_DOWN || code==SYS_HALT) + if(code==SYS_DOWN || code==SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } - + /* * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. + * turn the timebomb registers off. */ - + static struct notifier_block wdt_notifier= { .notifier_call = wdt_notify_sys, .next = NULL, - .priority = 0 + .priority = 0, }; static void __exit sc520_wdt_unload(void) @@ -333,27 +375,42 @@ static int __init sc520_wdt_init(void) spin_lock_init(&wdt_spinlock); + if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ + { + timeout = WATCHDOG_TIMEOUT; + printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", + timeout); + } + init_timer(&timer); timer.function = wdt_timer_ping; timer.data = 0; rc = misc_register(&wdt_miscdev); if (rc) + { + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + wdt_miscdev.minor, rc); goto err_out_region2; + } rc = register_reboot_notifier(&wdt_notifier); if (rc) + { + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + rc); goto err_out_miscdev; + } /* get the Base Address Register */ cbar = inl_p(0xfffc); - printk(OUR_NAME ": CBAR: 0x%08lx\n", cbar); + printk(KERN_INFO PFX "CBAR: 0x%08lx\n", cbar); /* check if MMCR aliasing bit is set */ if (cbar & 0x80000000) { - printk(OUR_NAME ": MMCR Aliasing enabled.\n"); + printk(KERN_INFO PFX "MMCR Aliasing enabled.\n"); wdtmrctl = (__u16 *)(cbar & 0x3fffffff); } else { - printk(OUR_NAME "!!! WARNING !!!\n" + printk(KERN_INFO PFX "!!! WARNING !!!\n" "\t MMCR Aliasing found NOT enabled!\n" "\t Using default value of: %p\n" "\t This has not been tested!\n" @@ -366,7 +423,8 @@ static int __init sc520_wdt_init(void) wdtmrctl = (__u16 *)((char *)wdtmrctl + OFFS_WDTMRCTL); wdtmrctl = ioremap((unsigned long)wdtmrctl, 2); - printk(KERN_INFO OUR_NAME ": WDT driver for SC520 initialised.\n"); + printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n", + timeout,nowayout); return 0; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 226236ffc39c..ecbb7a9f6299 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -440,7 +440,7 @@ static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) { - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode(drive, 255, pio, NULL); (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index e109169af1a2..fb86f80c0326 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1002,8 +1002,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); /* Remove it from the scsi layer now */ - if (sdev && scsi_remove_device(sdev)) - SBP2_ERR("scsi_remove_device failed"); + if (sdev) { + scsi_remove_device(sdev); + } sbp2util_remove_command_orb_pool(scsi_id); @@ -2890,7 +2891,6 @@ static Scsi_Host_Template scsi_driver_template = { .cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, .can_queue = SBP2_MAX_SCSI_QUEUE, .emulated = 1, - .highmem_io = 1, }; static int sbp2_module_init(void) diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index f694a2d75acb..3d59eb2e05a7 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h @@ -103,11 +103,11 @@ #ifdef DEBUG static unsigned long i8042_start; -#define dbg_init() do { i8042_start = jiffies; } while (0); +#define dbg_init() do { i8042_start = jiffies; } while (0) #define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" ,\ ## arg, (int) (jiffies - i8042_start)) #else -#define dbg_init() do { } while (0); +#define dbg_init() do { } while (0) #define dbg(format, arg...) do {} while (0) #endif diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 7ce28244068a..5995ee02775e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1326,7 +1326,7 @@ static int make_request (request_queue_t *q, struct bio * bi) (unsigned long long)new_sector, (unsigned long long)logical_sector); - sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); + sh = get_active_stripe(conf, new_sector, pd_idx, 0/*(bi->bi_rw&RWA_MASK)*/); if (sh) { add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK)); diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 7cbfb45bff2d..038ee943a749 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -1211,7 +1211,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .pll = PLL_28, .muxsel = { 2 }, - gpiomask: 0 + .gpiomask = 0 },{ /* Tomasz Pyra <hellfire@sedez.iq.pl> */ .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", @@ -1298,7 +1298,7 @@ struct tvcard bttv_tvcards[] = { },{ .name = "Powercolor MTV878/ MTV878R/ MTV878F", .video_inputs = 3, - audio_inputs: 2, + .audio_inputs = 2, .tuner = 0, .svhs = 2, .gpiomask = 0x1C800F, // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset @@ -1338,7 +1338,7 @@ struct tvcard bttv_tvcards[] = { },{ .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", .video_inputs = 4, - audio_inputs: 3, + .audio_inputs = 3, .tuner = 0, .svhs = 2, .gpiomask = 7, diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index a7f672037ac7..b670fe42d4b4 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -2873,8 +2873,8 @@ static struct file_operations bttv_fops = static struct video_device bttv_video_template = { .name = "UNSET", - type: VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, .minor = -1, diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 5e18bad1fba3..731356b65e3c 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -24,7 +24,7 @@ #ifndef _BTTVP_H_ #define _BTTVP_H_ -#include <linux/version.h> + #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,11) #include <linux/types.h> diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 4728ee8a0a78..6b1cc1d2a164 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1279,7 +1279,7 @@ mpt_adapter_install(struct pci_dev *pdev) u32 psize; int ii; int r = -ENODEV; - u64 mask = 0xffffffffffffffff; + u64 mask = 0xffffffffffffffffULL; if (pci_enable_device(pdev)) return r; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index b50219c8d5d4..a5a449a4a7d9 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1458,7 +1458,6 @@ mptscsih_detect(Scsi_Host_Template *tpnt) sh->max_lun = MPT_LAST_LUN + 1; sh->max_sectors = MPT_SCSI_MAX_SECTORS; - sh->highmem_io = 1; sh->this_id = this->pfacts[portnum].PortSCSIID; /* Required entry. diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index 46fc46934743..60a953401c02 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -287,13 +287,10 @@ static int blkmtd_readpage(mtd_raw_dev_data_t *rawdevice, struct page *page) return 0; } - static struct address_space_operations blkmtd_aops = { - writepage: blkmtd_writepage, - readpage: NULL, + .writepage = blkmtd_writepage, }; - /* This is the kernel thread that empties the write queue to disk */ static int write_queue_task(void *data) { diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index de4ebe6d6504..dfd0ed0c486c 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -449,18 +449,18 @@ static int send_pcb(struct net_device *dev, pcb_struct * pcb) case ASF_PCB_ACK: adapter->send_pcb_semaphore = 0; return TRUE; - break; + case ASF_PCB_NAK: #ifdef ELP_DEBUG printk(KERN_DEBUG "%s: send_pcb got NAK\n", dev->name); #endif goto abort; - break; } } if (elp_debug >= 1) printk(KERN_DEBUG "%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr)); + goto abort; sti_abort: spin_unlock_irqrestore(&adapter->lock, flags); diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 48650bbc6337..7c245f7dd66b 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1940,12 +1940,12 @@ err_disable_pdev: } static struct pci_driver amd8111e_driver = { - name: MODULE_NAME, - id_table: amd8111e_pci_tbl, - probe: amd8111e_probe_one, - remove: __devexit_p(amd8111e_remove_one), - suspend: amd8111e_suspend, - resume: amd8111e_resume + .name = MODULE_NAME, + .id_table = amd8111e_pci_tbl, + .probe = amd8111e_probe_one, + .remove = __devexit_p(amd8111e_remove_one), + .suspend = amd8111e_suspend, + .resume = amd8111e_resume }; static int __init amd8111e_init(void) diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index db091f95f553..4668ca870292 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -132,9 +132,9 @@ static int __init arcrimi_found(struct net_device *dev) u_long first_mirror, last_mirror, shmem; int mirror_size; - /* reserve the irq */ { - if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + /* reserve the irq */ + if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet (RIM I)", dev)) { + BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } diff --git a/drivers/net/meth.c b/drivers/net/meth.c index eca8974e91df..3a253f16cb88 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -844,9 +844,6 @@ int meth_init_module(void) printk("meth: error %i registering device \"%s\"\n", result, meth_devs->name); else device_present++; -#ifndef METH_DEBUG - EXPORT_NO_SYMBOLS; -#endif return device_present ? 0 : -ENODEV; } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 606d7bf9842d..f022276d7aba 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2073,7 +2073,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) case CCP_CONFACK: if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN) break; - if (!pskb_may_pull(skb, len = CCP_LENGTH(dp)) + 2) + len = CCP_LENGTH(dp); + if (!pskb_may_pull(skb, len + 2)) return; /* too short */ dp += CCP_HDRLEN; len -= CCP_HDRLEN; diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index e9e9012bd251..6ca8dda68f26 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -1641,13 +1641,13 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) spin_lock_irqsave(&rrpriv->lock, flags); i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES); + spin_unlock_irqrestore(&rrpriv->lock, flags); if (i != EEPROM_BYTES){ printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name); error = -EFAULT; goto gf_out; } - spin_unlock_irqrestore(&rrpriv->lock, flags); error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES); if (error) error = -EFAULT; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 470ac0908e58..cff9fec672f6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -51,6 +51,8 @@ static int debug; /* Network device part of the driver */ +static LIST_HEAD(tun_dev_list); + /* Net device open. */ static int tun_net_open(struct net_device *dev) { @@ -70,7 +72,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) { struct tun_struct *tun = (struct tun_struct *)dev->priv; - DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->name, skb->len); + DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len); /* Drop packet if interface is not attached */ if (!tun->attached) @@ -120,7 +122,7 @@ int tun_net_init(struct net_device *dev) { struct tun_struct *tun = (struct tun_struct *)dev->priv; - DBG(KERN_INFO "%s: tun_net_init\n", tun->name); + DBG(KERN_INFO "%s: tun_net_init\n", tun->dev->name); switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: @@ -161,7 +163,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) if (!tun) return -EBADFD; - DBG(KERN_INFO "%s: tun_chr_poll\n", tun->name); + DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); poll_wait(file, &tun->read_wait, wait); @@ -226,7 +228,7 @@ static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv, if (!tun) return -EBADFD; - DBG(KERN_INFO "%s: tun_chr_write %d\n", tun->name, count); + DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); for (i = 0, len = 0; i < count; i++) { if (verify_area(VERIFY_READ, iv[i].iov_base, iv[i].iov_len)) @@ -290,7 +292,7 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv, if (!tun) return -EBADFD; - DBG(KERN_INFO "%s: tun_chr_read\n", tun->name); + DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name); for (i = 0, len = 0; i < count; i++) { if (verify_area(VERIFY_WRITE, iv[i].iov_base, iv[i].iov_len)) @@ -350,7 +352,7 @@ static void tun_setup(struct net_device *dev) tun->owner = -1; dev->init = tun_net_init; - tun->name = dev->name; + SET_MODULE_OWNER(dev); dev->open = tun_net_open; dev->hard_start_xmit = tun_net_xmit; @@ -359,27 +361,40 @@ static void tun_setup(struct net_device *dev) dev->destructor = (void (*)(struct net_device *))kfree; } +static struct tun_struct *tun_get_by_name(const char *name) +{ + struct tun_struct *tun; + + ASSERT_RTNL(); + list_for_each_entry(tun, &tun_dev_list, list) { + if (!strncmp(tun->dev->name, name, IFNAMSIZ)) + return tun; + } + + return NULL; +} + static int tun_set_iff(struct file *file, struct ifreq *ifr) { struct tun_struct *tun; - struct net_device *dev; int err; - dev = __dev_get_by_name(ifr->ifr_name); - if (dev) { - /* Device exist */ - tun = dev->priv; - - if (dev->init != tun_net_init || tun->attached) + tun = tun_get_by_name(ifr->ifr_name); + if (tun) { + if (tun->attached) return -EBUSY; /* Check permissions */ - if (tun->owner != -1) - if (current->euid != tun->owner && !capable(CAP_NET_ADMIN)) - return -EPERM; - } else { + if (tun->owner != -1 && + current->euid != tun->owner && !capable(CAP_NET_ADMIN)) + return -EPERM; + } + else if (__dev_get_by_name(ifr->ifr_name)) + return -EINVAL; + else { char *name; unsigned long flags = 0; + struct net_device *dev; err = -EINVAL; @@ -420,9 +435,10 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) goto failed; } + list_add(&tun->list, &tun_dev_list); } - DBG(KERN_INFO "%s: tun_set_iff\n", tun->name); + DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); if (ifr->ifr_flags & IFF_NO_PI) tun->flags |= TUN_NO_PI; @@ -433,7 +449,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) file->private_data = tun; tun->attached = 1; - strcpy(ifr->ifr_name, tun->name); + strcpy(ifr->ifr_name, tun->dev->name); return 0; failed: return err; @@ -459,14 +475,15 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, if (err) return err; - copy_to_user((void *)arg, &ifr, sizeof(ifr)); + if (copy_to_user((void *)arg, &ifr, sizeof(ifr))) + return -EFAULT; return 0; } if (!tun) return -EBADFD; - DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->name, cmd); + DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); switch (cmd) { case TUNSETNOCSUM: @@ -477,7 +494,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, tun->flags &= ~TUN_NOCHECKSUM; DBG(KERN_INFO "%s: checksum %s\n", - tun->name, arg ? "disabled" : "enabled"); + tun->dev->name, arg ? "disabled" : "enabled"); break; case TUNSETPERSIST: @@ -488,14 +505,14 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, tun->flags &= ~TUN_PERSIST; DBG(KERN_INFO "%s: persist %s\n", - tun->name, arg ? "disabled" : "enabled"); + tun->dev->name, arg ? "disabled" : "enabled"); break; case TUNSETOWNER: /* Set owner of the device */ tun->owner = (uid_t) arg; - DBG(KERN_INFO "%s: owner set to %d\n", tun->owner); + DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner); break; #ifdef TUN_DEBUG @@ -519,7 +536,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on) if (!tun) return -EBADFD; - DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->name, on); + DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on); if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0) return ret; @@ -549,7 +566,7 @@ static int tun_chr_close(struct inode *inode, struct file *file) if (!tun) return 0; - DBG(KERN_INFO "%s: tun_chr_close\n", tun->name); + DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); tun_chr_fasync(-1, file, 0); @@ -562,8 +579,10 @@ static int tun_chr_close(struct inode *inode, struct file *file) /* Drop read queue */ skb_queue_purge(&tun->readq); - if (!(tun->flags & TUN_PERSIST)) + if (!(tun->flags & TUN_PERSIST)) { + list_del(&tun->list); unregister_netdevice(tun->dev); + } rtnl_unlock(); @@ -605,7 +624,17 @@ int __init tun_init(void) void tun_cleanup(void) { + struct tun_struct *tun, *nxt; + misc_deregister(&tun_miscdev); + + rtnl_lock(); + list_for_each_entry_safe(tun, nxt, &tun_dev_list, list) { + DBG(KERN_INFO "%s cleaned up\n", tun->dev->name); + unregister_netdevice(tun->dev); + } + rtnl_unlock(); + } module_init(tun_init); diff --git a/drivers/net/wan/comx-hw-locomx.c b/drivers/net/wan/comx-hw-locomx.c index 320f15874171..45bf7f870848 100644 --- a/drivers/net/wan/comx-hw-locomx.c +++ b/drivers/net/wan/comx-hw-locomx.c @@ -339,7 +339,10 @@ static int locomx_write_proc(struct file *file, const char *buffer, return -ENOMEM; } - copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE)); + if (copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EBADF; + } if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } diff --git a/drivers/net/wan/comx-hw-mixcom.c b/drivers/net/wan/comx-hw-mixcom.c index 3b5c7388163e..0881f7e17563 100644 --- a/drivers/net/wan/comx-hw-mixcom.c +++ b/drivers/net/wan/comx-hw-mixcom.c @@ -763,7 +763,10 @@ static int mixcom_write_proc(struct file *file, const char *buffer, return -ENOMEM; } - copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE)); + if (copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } diff --git a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c index 24d62f203b49..911862ed940a 100644 --- a/drivers/net/wan/comx-hw-munich.c +++ b/drivers/net/wan/comx-hw-munich.c @@ -2414,7 +2414,10 @@ static int munich_write_proc(struct file *file, const char *buffer, return -ENOMEM; /* Copy user data and cut trailing \n */ - copy_from_user(page, buffer, count = min(count, PAGE_SIZE)); + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } if (*(page + count - 1) == '\n') *(page + count - 1) = 0; *(page + PAGE_SIZE - 1) = 0; diff --git a/drivers/net/wan/comx-proto-fr.c b/drivers/net/wan/comx-proto-fr.c index 3eb97644d3d4..e1c83300548d 100644 --- a/drivers/net/wan/comx-proto-fr.c +++ b/drivers/net/wan/comx-proto-fr.c @@ -657,7 +657,10 @@ static int fr_write_proc(struct file *file, const char *buffer, return -ENOMEM; } - copy_from_user(page, buffer, count); + if (copy_from_user(page, buffer, count)) { + free_page((unsigned long)page); + return -EFAULT; + } if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } diff --git a/drivers/net/wan/comx-proto-lapb.c b/drivers/net/wan/comx-proto-lapb.c index 0d57623e868f..ae0f5fde7519 100644 --- a/drivers/net/wan/comx-proto-lapb.c +++ b/drivers/net/wan/comx-proto-lapb.c @@ -232,7 +232,10 @@ static int comxlapb_write_proc(struct file *file, const char *buffer, return -ENOMEM; } - copy_from_user(page, buffer, count); + if (copy_from_user(page, buffer, count)) { + free_page((unsigned long)page); + return -EFAULT; + } if (*(page + count - 1) == '\n') { *(page + count - 1) = 0; } diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index f8a2b3e7c06b..21d1deffca33 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -2623,7 +2623,8 @@ int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) sizeof(struct net_device_stats)); if (card->hw.type == PC300_TE) memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t)); - copy_to_user(arg, &pc300stats, sizeof(pc300stats_t)); + if (copy_to_user(arg, &pc300stats, sizeof(pc300stats_t))) + return -EFAULT; } return 0; } diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index df78c1517e4f..362f28421c01 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -1287,8 +1287,9 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) error = verify_area( VERIFY_WRITE, ifr->ifr_data, sizeof(struct sbni_in_stats) ); if( !error ) - copy_to_user( ifr->ifr_data, &nl->in_stats, - sizeof(struct sbni_in_stats) ); + if (copy_to_user( ifr->ifr_data, &nl->in_stats, + sizeof(struct sbni_in_stats) )) + return -EFAULT; break; case SIOCDEVRESINSTATS : @@ -1307,7 +1308,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) error = verify_area( VERIFY_WRITE, ifr->ifr_data, sizeof flags ); if( !error ) - copy_to_user( ifr->ifr_data, &flags, sizeof flags ); + if (copy_to_user( ifr->ifr_data, &flags, sizeof flags )) + return -EFAULT; break; case SIOCDEVSHWSTATE : @@ -1339,7 +1341,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) sizeof slave_name )) != 0 ) return error; - copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name ); + if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name )) + return -EFAULT; slave_dev = dev_get_by_name( slave_name ); if( !slave_dev || !(slave_dev->flags & IFF_UP) ) { printk( KERN_ERR "%s: trying to enslave non-active " diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 5a05ccdb6aa9..31d89c588ec1 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -689,7 +689,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, err = ret = 0; - if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); + if (cmd & IOC_IN) __copy_from_user((char *)&buf, (char *)arg, size); switch (cmd) { case DS_ADJUST_RESOURCE_INFO: @@ -803,9 +803,9 @@ static int ds_ioctl(struct inode * inode, struct file * file, err = -EIO; break; } } - - if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size); - + + if (cmd & IOC_OUT) __copy_to_user((char *)arg, (char *)&buf, size); + return err; } /* ds_ioctl */ diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c index acaa214163e1..f34c4a9dee0f 100644 --- a/drivers/sbus/char/riowatchdog.c +++ b/drivers/sbus/char/riowatchdog.c @@ -194,17 +194,11 @@ static ssize_t riowd_write(struct file *file, const char *buf, size_t count, lof return 0; } -static ssize_t riowd_read(struct file *file, char *buffer, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - static struct file_operations riowd_fops = { .owner = THIS_MODULE, .ioctl = riowd_ioctl, .open = riowd_open, .write = riowd_write, - .read = riowd_read, .release = riowd_release, }; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 811f4c95578a..05e491e7a278 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -3451,7 +3451,6 @@ static Scsi_Host_Template driver_template = { .cmd_per_lun = TW_MAX_CMDS_PER_LUN, .use_clustering = ENABLE_CLUSTERING, .emulated = 1, - .highmem_io = 1, }; #include "scsi_module.c" diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index c2fce462e847..60bb81d4649b 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -282,7 +282,6 @@ NCR_700_detect(Scsi_Host_Template *tpnt, tpnt->slave_configure = NCR_700_slave_configure; tpnt->slave_destroy = NCR_700_slave_destroy; tpnt->use_blk_tcq = 1; - tpnt->highmem_io = 1; if(tpnt->name == NULL) tpnt->name = "53c700"; diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 9583fda4c924..be58e5a9edb3 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -450,6 +450,7 @@ static __inline__ int NCR53c406a_pio_write(unsigned char *request, unsigned int static int __init NCR53c406a_detect(Scsi_Host_Template * tpnt) { + int present = 0; struct Scsi_Host *shpnt = NULL; #ifndef PORT_BASE int i; @@ -522,7 +523,7 @@ static int __init NCR53c406a_detect(Scsi_Host_Template * tpnt) DEB(printk("NCR53c406a: using port_base 0x%x\n", port_base)); - tpnt->present = 1; + present = 1; tpnt->proc_name = "NCR53c406a"; shpnt = scsi_register(tpnt, 0); @@ -576,7 +577,7 @@ static int __init NCR53c406a_detect(Scsi_Host_Template * tpnt) sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", port_base, irq_level, fast_pio ? "fast" : "slow"); #endif - return (tpnt->present); + return (present); #if USE_DMA err_free_irq: diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 1328bbcbc402..89f88dbf4cf4 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -295,7 +295,6 @@ static int aac_detect(Scsi_Host_Template *template) printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n"); } - template->present = aac_count; /* # of cards of this type found */ return aac_count; } diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 49a424007ac4..0f4c25439217 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -1868,12 +1868,31 @@ static void run(void) static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs) { struct Scsi_Host *shpnt = lookup_irq(irqno); + unsigned char rev, dmacntrl0; if (!shpnt) { printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno); return IRQ_NONE; } + /* + * Read a couple of registers that are known to not be all 1's. If + * we read all 1's (-1), that means that either: + * + * a. The host adapter chip has gone bad, and we cannot control it, + * OR + * b. The host adapter is a PCMCIA card that has been ejected + * + * In either case, we cannot do anything with the host adapter at + * this point in time. So just ignore the interrupt and return. + * In the latter case, the interrupt might actually be meant for + * someone else sharing this IRQ, and that driver will handle it. + */ + rev = GETPORT(REV); + dmacntrl0 = GETPORT(DMACNTRL0); + if ((rev == 0xFF) && (dmacntrl0 == 0xFF)) + return IRQ_NONE; + /* no more interrupts from the controller, while we're busy. INTEN is restored by the BH handler */ CLRBITS(DMACNTRL0, INTEN); diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 1b87b2aac104..3857ed2508b8 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1681,33 +1681,9 @@ Scsi_Host_Template aic79xx_driver_template = { .this_id = -1, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - .max_sectors = 8192, -#endif -#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -/* Assume RedHat Distribution with its different HIGHIO conventions. */ - .can_dma_32 = 1, - .single_sg_okay = 1, -#else - .highmem_io = 1, -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) .slave_alloc = ahd_linux_slave_alloc, .slave_configure = ahd_linux_slave_configure, .slave_destroy = ahd_linux_slave_destroy, -#else - .detect = ahd_linux_detect, - .release = ahd_linux_release, - .select_queue_depths = ahd_linux_select_queue_depth, - .use_new_eh_code = 1, -#endif }; /**************************** Tasklet Handler *********************************/ diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 8c1e4086a808..599f0e306629 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1307,33 +1307,9 @@ Scsi_Host_Template aic7xxx_driver_template = { .this_id = -1, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - /* - * We can only map 16MB per-SG - * so create a sector limit of - * "16MB" in 2K sectors. - */ - .max_sectors = 8192, -#endif -#if defined CONFIG_HIGHIO || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) -/* Assume RedHat Distribution with its different HIGHIO conventions. */ - .can_dma_32 = 1, - .single_sg_okay = 1, -#else - .highmem_io = 1, -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) .slave_alloc = ahc_linux_slave_alloc, .slave_configure = ahc_linux_slave_configure, .slave_destroy = ahc_linux_slave_destroy, -#else - .detect = ahc_linux_detect, - .release = ahc_linux_release, - .select_queue_depths = ahc_linux_select_queue_depth, - .use_new_eh_code = 1, -#endif }; /**************************** Tasklet Handler *********************************/ diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c index 9a519af985ce..943778cca0eb 100644 --- a/drivers/scsi/cpqfcTSinit.c +++ b/drivers/scsi/cpqfcTSinit.c @@ -549,14 +549,14 @@ void cpqfc_free_private_data(CPQFCHBA *hba, cpqfc_passthru_private_t *data) hba->private_data_bits+(i/BITS_PER_LONG)); } -int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg) +int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg) { int result = 0; struct Scsi_Host *HostAdapter = ScsiDev->host; CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; PTACHYON fcChip = &cpqfcHBAdata->fcChip; PFC_LOGGEDIN_PORT pLoggedInPort = NULL; - Scsi_Cmnd DumCmnd; + struct scsi_cmnd *DumCmnd; int i, j; VENDOR_IOCTL_REQ ioc; cpqfc_passthru_t *vendor_cmd; @@ -723,13 +723,16 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg) /* DumCmnd.target = ScsiDev->id; */ /* DumCmnd.lun = ScsiDev->lun; */ - DumCmnd.device = ScsiDev; + DumCmnd = scsi_get_command (ScsiDev, GFP_KERNEL); + if (!DumCmnd) + return -ENOMEM; pLoggedInPort = fcFindLoggedInPort( fcChip, - &DumCmnd, // search Scsi Nexus + DumCmnd, // search Scsi Nexus 0, // DON'T search linked list for FC port id NULL, // DON'T search linked list for FC WWN NULL); // DON'T care about end of list + scsi_put_command (DumCmnd); if (pLoggedInPort == NULL) { result = -ENXIO; break; @@ -918,7 +921,8 @@ static int copy_info(struct info_str *info, char *fmt, ...) int cpqfcTS_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout) { - Scsi_Cmnd DumCmnd; + struct scsi_cmnd *DumCmnd; + struct scsi_device *ScsiDev; int Chan, Targ, i; struct info_str info; CPQFCHBA *cpqfcHBA; @@ -946,13 +950,21 @@ int cpqfcTS_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t #define DISPLAY_WWN_INFO #ifdef DISPLAY_WWN_INFO + ScsiDev = scsi_get_host_dev (host); + if (!ScsiDev) + return -ENOMEM; + DumCmnd = scsi_get_command (ScsiDev, GFP_KERNEL); + if (!DumCmnd) { + scsi_free_host_dev (ScsiDev); + return -ENOMEM; + } copy_info(&info, "WWN database: (\"port_id: 000000\" means disconnected)\n"); for ( Chan=0; Chan <= host->max_channel; Chan++) { - DumCmnd.channel = Chan; + DumCmnd->device->channel = Chan; for (Targ=0; Targ <= host->max_id; Targ++) { - DumCmnd.target = Targ; + DumCmnd->device->id = Targ; if ((pLoggedInPort = fcFindLoggedInPort( fcChip, - &DumCmnd, // search Scsi Nexus + DumCmnd, // search Scsi Nexus 0, // DON'T search list for FC port id NULL, // DON'T search list for FC WWN NULL))){ // DON'T care about end of list @@ -966,6 +978,9 @@ int cpqfcTS_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t } } } + + scsi_put_command (DumCmnd); + scsi_free_host_dev (ScsiDev); #endif @@ -1578,7 +1593,7 @@ int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, // Scsi_Request, etc. // For now, so people don't fall into a hole... return -ENOTSUPP; - +/* // printk(" ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags); if (ScsiDev->host->eh_active) return FAILED; @@ -1600,7 +1615,7 @@ return -ENOTSUPP; SCpnt->request->CPQFC_WAITING = NULL; } -/* + if(driver_byte(SCpnt->result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: diff --git a/drivers/scsi/cpqfcTSstructs.h b/drivers/scsi/cpqfcTSstructs.h index c208b98323ef..0bae3298c44b 100644 --- a/drivers/scsi/cpqfcTSstructs.h +++ b/drivers/scsi/cpqfcTSstructs.h @@ -696,7 +696,6 @@ typedef struct ULONG port_id; // a FC 24-bit address of port (lower 8 bits = al_pa) - Scsi_Cmnd ScsiCmnd; // command buffer for Report Luns #define REPORT_LUNS_PL 256 UCHAR ReportLunsPayload[REPORT_LUNS_PL]; diff --git a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c index 553d01543437..b41038baa394 100644 --- a/drivers/scsi/cpqfcTSworker.c +++ b/drivers/scsi/cpqfcTSworker.c @@ -30,6 +30,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/smp_lock.h> +#include <linux/pci.h> #define __KERNEL_SYSCALLS__ @@ -1196,9 +1197,9 @@ void cpqfcTSTerminateExchange( // have to terminate by SCSI target, NOT port_id. if( Exchanges->fcExchange[x_ID].Cmnd) // Cmnd in progress? { - if( (Exchanges->fcExchange[x_ID].Cmnd->target == ScsiNexus->target) + if( (Exchanges->fcExchange[x_ID].Cmnd->device->id == ScsiNexus->target) && - (Exchanges->fcExchange[x_ID].Cmnd->channel == ScsiNexus->channel)) + (Exchanges->fcExchange[x_ID].Cmnd->device->channel == ScsiNexus->channel)) { Exchanges->fcExchange[x_ID].status = TerminateStatus; cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID ); // timed-out @@ -2681,7 +2682,7 @@ static void SendLogins( CPQFCHBA *cpqfcHBAdata, __u32 *FabricPortIds ) // D. Deming, 1994, pg 7-19 (ISBN 1-879936-08-9) static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd) { - struct Scsi_Host *HostAdapter = Cmnd->host; + struct Scsi_Host *HostAdapter = Cmnd->device->host; CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; PTACHYON fcChip = &cpqfcHBAdata->fcChip; FC_EXCHANGES *Exchanges = fcChip->Exchanges; @@ -2887,11 +2888,11 @@ static void call_scsi_done(Scsi_Cmnd *Cmnd) { CPQFCHBA *hba; - hba = (CPQFCHBA *) Cmnd->host->hostdata; + hba = (CPQFCHBA *) Cmnd->device->host->hostdata; // Was this command a cpqfc passthru ioctl ? - if (Cmnd->sc_request != NULL && Cmnd->host != NULL && - Cmnd->host->hostdata != NULL && - is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->host->hostdata, + if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL && + Cmnd->device->host->hostdata != NULL && + is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->device->host->hostdata, Cmnd->sc_request->upper_private_data)) { cpqfc_free_private_data(hba, Cmnd->sc_request->upper_private_data); @@ -2918,7 +2919,8 @@ static void IssueReportLunsCommand( { PTACHYON fcChip = &cpqfcHBAdata->fcChip; PFC_LOGGEDIN_PORT pLoggedInPort; - Scsi_Cmnd *Cmnd; + struct scsi_cmnd *Cmnd = NULL; + struct scsi_device *ScsiDev = NULL; LONG x_ID; ULONG ulStatus; UCHAR *ucBuff; @@ -2942,17 +2944,20 @@ static void IssueReportLunsCommand( if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) ) goto Done; // forget it - FC device not a "target" - // now use the port's Scsi Command buffer for the - // Report Luns Command - Cmnd = &pLoggedInPort->ScsiCmnd; + ScsiDev = scsi_get_host_dev (cpqfcHBAdata->HostAdapter); + if (!ScsiDev) + goto Done; + + Cmnd = scsi_get_command (ScsiDev, GFP_KERNEL); + if (!Cmnd) + goto Done; + ucBuff = pLoggedInPort->ReportLunsPayload; - memset( Cmnd, 0, sizeof(Scsi_Cmnd)); memset( ucBuff, 0, REPORT_LUNS_PL); Cmnd->scsi_done = ScsiReportLunsDone; - Cmnd->host = cpqfcHBAdata->HostAdapter; Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload; Cmnd->request_bufflen = REPORT_LUNS_PL; @@ -2962,8 +2967,8 @@ static void IssueReportLunsCommand( Cmnd->cmnd[9] = (UCHAR)REPORT_LUNS_PL; Cmnd->cmd_len = 12; - Cmnd->channel = pLoggedInPort->ScsiNexus.channel; - Cmnd->target = pLoggedInPort->ScsiNexus.target; + Cmnd->device->channel = pLoggedInPort->ScsiNexus.channel; + Cmnd->device->id = pLoggedInPort->ScsiNexus.target; ulStatus = cpqfcTSBuildExchange( @@ -3003,6 +3008,10 @@ static void IssueReportLunsCommand( Done: + if (Cmnd) + scsi_put_command (Cmnd); + if (ScsiDev) + scsi_free_host_dev (ScsiDev); } @@ -3361,22 +3370,22 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( { // check Linux Scsi Cmnd for channel/target Nexus match // (all luns are accessed through matching "pLoggedInPort") - if( (pLoggedInPort->ScsiNexus.target == Cmnd->target) + if( (pLoggedInPort->ScsiNexus.target == Cmnd->device->id) && - (pLoggedInPort->ScsiNexus.channel == Cmnd->channel)) + (pLoggedInPort->ScsiNexus.channel == Cmnd->device->channel)) { // For "passthru" modes, the IOCTL caller is responsible // for setting the FCP-LUN addressing - if (Cmnd->sc_request != NULL && Cmnd->host != NULL && - Cmnd->host->hostdata != NULL && - is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->host->hostdata, + if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL && + Cmnd->device->host->hostdata != NULL && + is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->device->host->hostdata, Cmnd->sc_request->upper_private_data)) { /* This is a passthru... */ cpqfc_passthru_private_t *pd; pd = Cmnd->sc_request->upper_private_data; Cmnd->SCp.phase = pd->bus; // Cmnd->SCp.have_data_in = pd->pdrive; - Cmnd->SCp.have_data_in = Cmnd->lun; + Cmnd->SCp.have_data_in = Cmnd->device->lun; } else { /* This is not a passthru... */ @@ -3391,17 +3400,17 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( // Report Luns command if( pLoggedInPort->ScsiNexus.LunMasking == 1) { - if (Cmnd->lun > sizeof(pLoggedInPort->ScsiNexus.lun)) + if (Cmnd->device->lun > sizeof(pLoggedInPort->ScsiNexus.lun)) return NULL; // we KNOW all the valid LUNs... 0xFF is invalid! - Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun]; - if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF) + Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->device->lun]; + if (pLoggedInPort->ScsiNexus.lun[Cmnd->device->lun] == 0xFF) return NULL; // printk("xlating lun %d to 0x%02x\n", Cmnd->lun, // pLoggedInPort->ScsiNexus.lun[Cmnd->lun]); } else - Cmnd->SCp.have_data_in = Cmnd->lun; // Linux & target luns match + Cmnd->SCp.have_data_in = Cmnd->device->lun; // Linux & target luns match } break; // found it! } @@ -3507,9 +3516,9 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, // Are there any Q'd commands for this target? - if( (Cmnd->target == pLoggedInPort->ScsiNexus.target) + if( (Cmnd->device->id == pLoggedInPort->ScsiNexus.target) && - (Cmnd->channel == pLoggedInPort->ScsiNexus.channel) ) + (Cmnd->device->channel == pLoggedInPort->ScsiNexus.channel) ) { Cmnd->result = (DID_SOFT_ERROR <<16); // force retry if( Cmnd->scsi_done == NULL) diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 45050fc1505c..0714ea4b8736 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -264,6 +264,44 @@ struct SGentry { }; +/* + * The SEEPROM structure for TRM_S1040 + */ +struct NVRamTarget { + u8 cfg0; /* Target configuration byte 0 */ + u8 period; /* Target period */ + u8 cfg2; /* Target configuration byte 2 */ + u8 cfg3; /* Target configuration byte 3 */ +}; + + +struct NvRamType { + u8 sub_vendor_id[2]; /* 0,1 Sub Vendor ID */ + u8 sub_sys_id[2]; /* 2,3 Sub System ID */ + u8 sub_class; /* 4 Sub Class */ + u8 vendor_id[2]; /* 5,6 Vendor ID */ + u8 device_id[2]; /* 7,8 Device ID */ + u8 reserved; /* 9 Reserved */ + struct NVRamTarget target[DC395x_MAX_SCSI_ID]; + /** 10,11,12,13 + ** 14,15,16,17 + ** .... + ** .... + ** 70,71,72,73 + */ + u8 scsi_id; /* 74 Host Adapter SCSI ID */ + u8 channel_cfg; /* 75 Channel configuration */ + u8 delay_time; /* 76 Power on delay time */ + u8 max_tag; /* 77 Maximum tags */ + u8 reserved0; /* 78 */ + u8 boot_target; /* 79 */ + u8 boot_lun; /* 80 */ + u8 reserved1; /* 81 */ + u16 reserved2[22]; /* 82,..125 */ + u16 cksum; /* 126,127 */ +}; + + /*----------------------------------------------------------------------- SCSI Request Block -----------------------------------------------------------------------*/ @@ -349,7 +387,6 @@ struct DeviceCtlBlk { -----------------------------------------------------------------------*/ struct AdapterCtlBlk { struct Scsi_Host *scsi_host; - struct AdapterCtlBlk *next_acb; u16 IOPortBase; @@ -365,7 +402,6 @@ struct AdapterCtlBlk { struct timer_list selto_timer; u16 srb_count; - u16 adapter_index; /* nth Adapter this driver */ u8 dcb_count; u8 sel_timeout; @@ -389,45 +425,11 @@ struct AdapterCtlBlk { struct ScsiReqBlk srb_array[DC395x_MAX_SRB_CNT]; struct ScsiReqBlk srb; -}; - -/* - * The SEEPROM structure for TRM_S1040 - */ -struct NVRamTarget { - u8 cfg0; /* Target configuration byte 0 */ - u8 period; /* Target period */ - u8 cfg2; /* Target configuration byte 2 */ - u8 cfg3; /* Target configuration byte 3 */ + struct NvRamType eeprom; /* eeprom settings for this adapter */ }; -struct NvRamType { - u8 sub_vendor_id[2]; /* 0,1 Sub Vendor ID */ - u8 sub_sys_id[2]; /* 2,3 Sub System ID */ - u8 sub_class; /* 4 Sub Class */ - u8 vendor_id[2]; /* 5,6 Vendor ID */ - u8 device_id[2]; /* 7,8 Device ID */ - u8 reserved; /* 9 Reserved */ - struct NVRamTarget target[DC395x_MAX_SCSI_ID]; - /** 10,11,12,13 - ** 14,15,16,17 - ** .... - ** .... - ** 70,71,72,73 - */ - u8 scsi_id; /* 74 Host Adapter SCSI ID */ - u8 channel_cfg; /* 75 Channel configuration */ - u8 delay_time; /* 76 Power on delay time */ - u8 max_tag; /* 77 Maximum tags */ - u8 reserved0; /* 78 */ - u8 boot_target; /* 79 */ - u8 boot_lun; /* 80 */ - u8 reserved1; /* 81 */ - u16 reserved2[22]; /* 82,..125 */ - u16 cksum; /* 126,127 */ -}; /*--------------------------------------------------------------------------- @@ -512,9 +514,6 @@ static void waiting_timeout(unsigned long ptr); /*--------------------------------------------------------------------------- Static Data ---------------------------------------------------------------------------*/ -static struct AdapterCtlBlk *acb_list_head = NULL; -static struct AdapterCtlBlk *acb_list_tail = NULL; -static u16 adapter_count = 0; static u16 current_sync_offset = 0; static char monitor_next_irq = 0; @@ -546,7 +545,6 @@ static void *dc395x_scsi_phase1[] = { msgin_phase1, /* phase:7 */ }; -struct NvRamType eeprom_buf[DC395x_MAX_ADAPTER_NUM]; /* *Fast20: 000 50ns, 20.0 MHz * 001 75ns, 13.3 MHz @@ -1611,14 +1609,12 @@ static inline void clear_fifo(struct AdapterCtlBlk *acb, char *txt) */ static void reset_dev_param(struct AdapterCtlBlk *acb) { - struct DeviceCtlBlk *dcb; + struct DeviceCtlBlk *dcb = acb->link_dcb; struct DeviceCtlBlk *dcb_temp; - struct NvRamType *eeprom; + struct NvRamType *eeprom = &acb->eeprom; u8 period_index; - u16 index; dprintkdbg(DBG_0, "reset_dev_param..............\n"); - dcb = acb->link_dcb; if (dcb == NULL) return; @@ -1627,8 +1623,6 @@ static void reset_dev_param(struct AdapterCtlBlk *acb) dcb->sync_mode &= ~(SYNC_NEGO_DONE + WIDE_NEGO_DONE); dcb->sync_period = 0; dcb->sync_offset = 0; - index = acb->adapter_index; - eeprom = &eeprom_buf[index]; dcb->dev_mode = eeprom->target[dcb->target_id].cfg0; /*dcb->AdpMode = eeprom->channel_cfg; */ @@ -1679,7 +1673,7 @@ static int dc395x_eh_bus_reset(Scsi_Cmnd * cmd) /* We may be in serious trouble. Wait some seconds */ acb->scsi_host->last_reset = jiffies + 3 * HZ / 2 + - HZ * eeprom_buf[acb->adapter_index].delay_time; + HZ * acb->eeprom.delay_time; /* * re-enable interrupt @@ -3832,9 +3826,7 @@ static void disconnect(struct AdapterCtlBlk *acb) /* Suspend queue for a while */ acb->scsi_host->last_reset = jiffies + HZ / 2 + - HZ * - eeprom_buf[acb->adapter_index]. - delay_time; + HZ * acb->eeprom.delay_time; clear_fifo(acb, "DiscEx"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); return; @@ -4640,7 +4632,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb) /* Maybe we locked up the bus? Then lets wait even longer ... */ acb->scsi_host->last_reset = jiffies + 5 * HZ / 2 + - HZ * eeprom_buf[acb->adapter_index].delay_time; + HZ * acb->eeprom.delay_time; clear_fifo(acb, "RstDet"); set_basic_config(acb); @@ -4731,9 +4723,8 @@ static void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, u8 target, u8 lun) { - struct NvRamType *eeprom; + struct NvRamType *eeprom = &acb->eeprom; u8 period_index; - u16 index; struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb2; @@ -4771,8 +4762,6 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb, dcb->flag = 0; dcb->max_command = 1; /* $$$$$$$ */ - index = acb->adapter_index; - eeprom = &eeprom_buf[index]; dcb->dev_mode = eeprom->target[target].cfg0; /*dcb->AdpMode = eeprom->channel_cfg; */ dcb->inquiry7 = 0; @@ -4951,13 +4940,12 @@ static void __init link_srb(struct AdapterCtlBlk *acb) *********************************************************************** */ static -int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq, u16 index) +int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq) { - struct NvRamType *eeprom; - struct AdapterCtlBlk *acb; + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; + struct NvRamType *eeprom = &acb->eeprom; u16 i; - eeprom = &eeprom_buf[index]; host->max_cmd_len = 24; host->can_queue = DC395x_MAX_CMD_QUEUE; host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN; @@ -4969,7 +4957,6 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq, u16 index) host->irq = irq; host->last_reset = jiffies; - acb = (struct AdapterCtlBlk *) host->hostdata; host->max_id = 16; if (host->max_id - 1 == eeprom->scsi_id) @@ -4991,7 +4978,6 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq, u16 index) acb->dcb_run_robin = NULL; acb->active_dcb = NULL; acb->srb_count = DC395x_MAX_SRB_CNT; - acb->adapter_index = index; acb->scsi_host->this_id = eeprom->scsi_id; acb->hostid_bit = (1 << acb->scsi_host->this_id); /*acb->scsi_host->this_lun = 0; */ @@ -5050,16 +5036,14 @@ int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq, u16 index) * @host: This hosts adapter strcuture * @io_port: The base I/O port * @irq: IRQ - * @index: Card instance number * * Returns 0 if the initialization succeeds, any other value on failure. **/ static -int __init init_adapter(struct Scsi_Host *host, u32 io_port, - u8 irq, u16 index) +int __init init_adapter(struct Scsi_Host *host, u32 io_port, u8 irq) { - struct NvRamType *eeprom = &eeprom_buf[index]; struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; + struct NvRamType *eeprom = &acb->eeprom; if (!request_region(io_port, host->n_io_port, DC395X_NAME)) { dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); @@ -5106,9 +5090,7 @@ int __init init_adapter(struct Scsi_Host *host, u32 io_port, acb->scsi_host->last_reset = jiffies + HZ / 2 + - HZ * - eeprom_buf[acb->adapter_index]. - delay_time; + HZ * acb->eeprom.delay_time; /*spin_lock_irq (&io_request_lock); */ } @@ -5465,22 +5447,22 @@ void __init print_config(struct AdapterCtlBlk *acb) * print_eeprom_settings - output the eeprom settings * to the kernel log so people can see what they were. * - * @index: Adapter number + * @eeprom: The eeprom data strucutre to show details for. **/ static -void __init print_eeprom_settings(u16 index) +void __init print_eeprom_settings(struct NvRamType *eeprom) { dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n", - eeprom_buf[index].scsi_id, - eeprom_buf[index].target[0].period, - clock_speed[eeprom_buf[index].target[0].period] / 10, - clock_speed[eeprom_buf[index].target[0].period] % 10, - eeprom_buf[index].target[0].cfg0); + eeprom->scsi_id, + eeprom->target[0].period, + clock_speed[eeprom->target[0].period] / 10, + clock_speed[eeprom->target[0].period] % 10, + eeprom->target[0].cfg0); dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n", - eeprom_buf[index].channel_cfg, - eeprom_buf[index].max_tag, - 1 << eeprom_buf[index].max_tag, - eeprom_buf[index].delay_time); + eeprom->channel_cfg, + eeprom->max_tag, + 1 << eeprom->max_tag, + eeprom->delay_time); } @@ -5497,52 +5479,37 @@ void __init print_eeprom_settings(u16 index) */ static struct Scsi_Host *__init host_init(Scsi_Host_Template * host_template, - u32 io_port, u8 irq, - u16 index) + u32 io_port, u8 irq) { struct Scsi_Host *host; struct AdapterCtlBlk *acb; - /* - * Read the eeprom contents info the buffer we supply. Use - * defaults is eeprom checksum is wrong. - */ - check_eeprom(&eeprom_buf[index], (u16) io_port); - - /* - *$$$$$$$$$$$ MEMORY ALLOCATE FOR ADAPTER CONTROL BLOCK $$$$$$$$$$$$ - */ host = scsi_host_alloc(host_template, sizeof(struct AdapterCtlBlk)); if (!host) { - dprintkl(KERN_INFO, "pSH scsi_host_alloc ERROR\n"); - return 0; + dprintkl(KERN_INFO, "scsi_host_alloc failed\n"); + goto failed; } - print_eeprom_settings(index); + acb = (struct AdapterCtlBlk *)host->hostdata; - acb = (struct AdapterCtlBlk *) host->hostdata; - if (init_acb(host, io_port, irq, index)) { - scsi_host_put(host); - return 0; + check_eeprom(&acb->eeprom, (u16)io_port); + print_eeprom_settings(&acb->eeprom); + + if (init_acb(host, io_port, irq)) { + goto failed; } print_config(acb); - /* - *$$$$$$$$$$$$$$$$$ INITIAL ADAPTER $$$$$$$$$$$$$$$$$ - */ - if (!init_adapter(host, io_port, irq, index)) { - if (!acb_list_head) { - acb_list_head = acb; - } else { - acb_list_tail->next_acb = acb; - } - acb_list_tail = acb; - acb->next_acb = NULL; - } else { + if (init_adapter(host, io_port, irq)) { dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n"); - scsi_host_put(host); - host = NULL; + goto failed; } + return host; + +failed: + if (host) + scsi_host_put(host); + return NULL; } #undef SEARCH @@ -5579,25 +5546,15 @@ struct Scsi_Host *__init host_init(Scsi_Host_Template * host_template, else SPRINTF(" No ") static -int dc395x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, +int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout) { + struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata; int dev, spd, spd1; char *pos = buffer; - struct AdapterCtlBlk *acb; struct DeviceCtlBlk *dcb; unsigned long flags; - acb = acb_list_head; - - while (acb) { - if (acb->scsi_host == shpnt) - break; - acb = acb->next_acb; - } - if (!acb) - return -ESRCH; - if (inout) /* Has data been written to the file ? */ return -EPERM; @@ -5606,23 +5563,21 @@ int dc395x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t DC395x_LOCK_IO(acb->scsi_host, flags); - SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); - SPRINTF("DC395U/UW/F DC315/U %s Adapter Nr %i\n", - (acb->config & HCC_WIDE_CARD) ? "Wide" : "", - acb->adapter_index); + SPRINTF("SCSI Host Nr %i, ", host->host_no); + SPRINTF("DC395U/UW/F DC315/U %s\n", + (acb->config & HCC_WIDE_CARD) ? "Wide" : ""); SPRINTF("IOPortBase 0x%04x, ", acb->IOPortBase); SPRINTF("irq_level 0x%02x, ", acb->irq_level); SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000); - SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun); - SPRINTF("AdapterID %i\n", shpnt->this_id); + SPRINTF("MaxID %i, MaxLUN %i, ", host->max_id, host->max_lun); + SPRINTF("AdapterID %i\n", host->this_id); SPRINTF("tag_max_num %i", acb->tag_max_num); /*SPRINTF(", DMA_Status %i\n", DC395x_read8(acb, TRM_S1040_DMA_STATUS)); */ SPRINTF(", FilterCfg 0x%02x", DC395x_read8(acb, TRM_S1040_SCSI_CONFIG1)); - SPRINTF(", DelayReset %is\n", - eeprom_buf[acb->adapter_index].delay_time); + SPRINTF(", DelayReset %is\n", acb->eeprom.delay_time); /*SPRINTF("\n"); */ SPRINTF("Nr of DCBs: %i\n", acb->dcb_count); @@ -5852,6 +5807,7 @@ int __devinit dc395x_init_one(struct pci_dev *dev, u8 irq; struct Scsi_Host *scsi_host; static int banner_done = 0; + int error = 0; dprintkdbg(DBG_0, "Init one instance of the dc395x\n"); if (!banner_done) @@ -5871,29 +5827,27 @@ int __devinit dc395x_init_one(struct pci_dev *dev, irq = dev->irq; dprintkdbg(DBG_0, "IO_PORT=%04x,IRQ=%x\n", (unsigned int) io_port, irq); - scsi_host = host_init(&dc395x_driver_template, io_port, irq, adapter_count); + scsi_host = host_init(&dc395x_driver_template, io_port, irq); if (!scsi_host) { dprintkdbg(DBG_0, "host_init failed\n"); return -ENOMEM; } - - pci_set_master(dev); - - /* store pci devices in out host data object. */ ((struct AdapterCtlBlk *)(scsi_host->hostdata))->dev = dev; - - /* increment adaptor count */ - adapter_count++; - - /* store ptr to scsi host in the PCI device structure */ + pci_set_master(dev); pci_set_drvdata(dev, scsi_host); /* get the scsi mid level to scan for new devices on the bus */ - scsi_add_host(scsi_host, &dev->dev); /* XXX handle failure */ - scsi_scan_host(scsi_host); - - return 0; + error = scsi_add_host(scsi_host, &dev->dev); + if (error) { + dprintkl(KERN_ERR, "scsi_add_host failed\n"); + error = -ENODEV; + host_release(scsi_host); + scsi_host_put(scsi_host); + } else + scsi_scan_host(scsi_host); + + return error; } @@ -5906,9 +5860,18 @@ int __devinit dc395x_init_one(struct pci_dev *dev, static void __devexit dc395x_remove_one(struct pci_dev *dev) { struct Scsi_Host *host = pci_get_drvdata(dev); + dprintkdbg(DBG_0, "Removing instance\n"); - scsi_remove_host(host); + if (!host) { + dprintkl(KERN_ERR, "no host allocated\n"); + return; + } + if (scsi_remove_host(host)) { + dprintkl(KERN_ERR, "scsi_remove_host failed\n"); + return; + } host_release(host); + scsi_host_put(host); pci_set_drvdata(dev, NULL); } diff --git a/drivers/scsi/dc395x.h b/drivers/scsi/dc395x.h index ae1e57330ccb..031306f2d24f 100644 --- a/drivers/scsi/dc395x.h +++ b/drivers/scsi/dc395x.h @@ -28,7 +28,6 @@ #define DC395x_MAX_CMD_QUEUE 32 /* #define DC395x_MAX_QTAGS 32 */ #define DC395x_MAX_QTAGS 16 -#define DC395x_MAX_ADAPTER_NUM 4 #define DC395x_MAX_SCSI_ID 16 #define DC395x_MAX_CMD_PER_LUN DC395x_MAX_QTAGS #define DC395x_MAX_SG_TABLESIZE 64 /* HW limitation */ diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c index 9b78b350a495..ee7efe46e242 100644 --- a/drivers/scsi/esp.c +++ b/drivers/scsi/esp.c @@ -4392,7 +4392,6 @@ static Scsi_Host_Template driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, - .highmem_io = 1, }; #include "scsi_module.c" diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f4f69bf1e148..642c398d294a 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -39,30 +39,35 @@ static int scsi_host_next_hn; /* host_no for next new host */ + /** - * scsi_remove_host - check a scsi host for release and release - * @shost: a pointer to a scsi host to release - * - * Return value: - * 0 on Success / 1 on Failure + * scsi_host_cancel - cancel outstanding IO to this host + * @shost: pointer to struct Scsi_Host + * recovery: recovery requested to run. **/ -int scsi_remove_host(struct Scsi_Host *shost) +void scsi_host_cancel(struct Scsi_Host *shost, int recovery) { - struct scsi_device *sdev; - - /* - * FIXME Do ref counting. We force all of the devices offline to - * help prevent race conditions where other hosts/processors could - * try and get in and queue a command. - */ - list_for_each_entry(sdev, &shost->my_devices, siblings) - sdev->online = FALSE; + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + set_bit(SHOST_CANCEL, &shost->shost_state); + spin_unlock_irqrestore(shost->host_lock, flags); + device_for_each_child(&shost->shost_gendev, &recovery, + scsi_device_cancel_cb); + wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY, + &shost->shost_state))); +} +/** + * scsi_remove_host - remove a scsi host + * @shost: a pointer to a scsi host to remove + **/ +void scsi_remove_host(struct Scsi_Host *shost) +{ + scsi_host_cancel(shost, 0); scsi_proc_host_rm(shost); scsi_forget_host(shost); scsi_sysfs_remove_host(shost); - - return 0; } /** @@ -108,7 +113,7 @@ void scsi_free_shost(struct Scsi_Host *shost) shost->eh_notify = NULL; } - shost->hostt->present--; + scsi_proc_hostdir_rm(shost->hostt); scsi_destroy_command_freelist(shost); kfree(shost); } @@ -182,7 +187,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->unchecked_isa_dma = sht->unchecked_isa_dma; shost->use_clustering = sht->use_clustering; shost->use_blk_tcq = sht->use_blk_tcq; - shost->highmem_io = sht->highmem_io; if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; @@ -198,6 +202,14 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) else shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS; + /* + * assume a 4GB boundary, if not set + */ + if (sht->dma_boundary) + shost->dma_boundary = sht->dma_boundary; + else + shost->dma_boundary = 0xffffffff; + rval = scsi_setup_command_freelist(shost); if (rval) goto fail; @@ -209,7 +221,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) kernel_thread((int (*)(void *))scsi_error_handler, shost, 0); wait_for_completion(&complete); shost->eh_notify = NULL; - shost->hostt->present++; + scsi_proc_hostdir_add(shost->hostt); return shost; fail: kfree(shost); @@ -249,21 +261,21 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) { struct class *class = class_get(&shost_class); struct class_device *cdev; - struct Scsi_Host *shost = NULL, *p; + struct Scsi_Host *shost = ERR_PTR(-ENXIO), *p; if (class) { down_read(&class->subsys.rwsem); list_for_each_entry(cdev, &class->children, node) { p = class_to_shost(cdev); if (p->host_no == hostnum) { - scsi_host_get(p); - shost = p; + shost = scsi_host_get(p); break; } } up_read(&class->subsys.rwsem); } + class_put(&shost_class); return shost; } @@ -271,10 +283,12 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) * *scsi_host_get - inc a Scsi_Host ref count * @shost: Pointer to Scsi_Host to inc. **/ -void scsi_host_get(struct Scsi_Host *shost) +struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) { - get_device(&shost->shost_gendev); - class_device_get(&shost->shost_classdev); + if (test_bit(SHOST_DEL, &shost->shost_state) || + !get_device(&shost->shost_gendev)) + return NULL; + return shost; } /** @@ -283,6 +297,5 @@ void scsi_host_get(struct Scsi_Host *shost) **/ void scsi_host_put(struct Scsi_Host *shost) { - class_device_put(&shost->shost_classdev); put_device(&shost->shost_gendev); } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index e6cdee3e9611..e7c504d6a53e 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -268,9 +268,6 @@ static Scsi_Host_Template ips_driver_template = { .sg_tablesize = IPS_MAX_SG, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || (defined CONFIG_HIGHIO) - .highmem_io = 1, -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) .use_new_eh_code = 1, #endif diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 6dfaf6bacf38..de60f4f54b95 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -5361,7 +5361,6 @@ static Scsi_Host_Template driver_template = { .eh_device_reset_handler = megaraid_reset, .eh_bus_reset_handler = megaraid_reset, .eh_host_reset_handler = megaraid_reset, - .highmem_io = 1, }; #include "scsi_module.c" diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index af999e9509b6..0e381b816734 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -40,7 +40,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/timer.h> #include <linux/ioport.h> #include <scsi/scsi.h> #include <linux/major.h> @@ -102,7 +101,7 @@ typedef struct scsi_info_t { struct Scsi_Host *host; } scsi_info_t; -static void aha152x_release_cs(u_long arg); +static void aha152x_release_cs(dev_link_t *link); static int aha152x_event(event_t event, int priority, event_callback_args_t *args); @@ -126,9 +125,6 @@ static dev_link_t *aha152x_attach(void) if (!info) return NULL; memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; - init_timer(&link->release); - link->release.function = &aha152x_release_cs; - link->release.data = (u_long)link; link->io.NumPorts1 = 0x20; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -181,9 +177,8 @@ static void aha152x_detach(dev_link_t *link) if (*linkp == NULL) return; - del_timer(&link->release); if (link->state & DEV_CONFIG) { - aha152x_release_cs((u_long)link); + aha152x_release_cs(link); if (link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; @@ -290,13 +285,12 @@ static void aha152x_config_cs(dev_link_t *link) cs_failed: cs_error(link->handle, last_fn, last_ret); - aha152x_release_cs((u_long)link); + aha152x_release_cs(link); return; } -static void aha152x_release_cs(u_long arg) +static void aha152x_release_cs(dev_link_t *link) { - dev_link_t *link = (dev_link_t *)arg; scsi_info_t *info = link->priv; scsi_remove_host(info->host); @@ -325,7 +319,7 @@ static int aha152x_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ/20); + aha152x_release_cs(link); break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index e91187dca450..09ef39d759e7 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -37,7 +37,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/timer.h> #include <linux/ioport.h> #include <scsi/scsi.h> #include <linux/major.h> @@ -90,7 +89,7 @@ extern void fdomain_setup(char *str, int *ints); extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt ); extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt); -static void fdomain_release(u_long arg); +static void fdomain_release(dev_link_t *link); static int fdomain_event(event_t event, int priority, event_callback_args_t *args); @@ -116,10 +115,6 @@ static dev_link_t *fdomain_attach(void) if (!info) return NULL; memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; - init_timer(&link->release); - link->release.function = &fdomain_release; - link->release.data = (u_long)link; - link->io.NumPorts1 = 0x10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.IOAddrLines = 10; @@ -171,9 +166,8 @@ static void fdomain_detach(dev_link_t *link) if (*linkp == NULL) return; - del_timer(&link->release); if (link->state & DEV_CONFIG) { - fdomain_release((u_long)link); + fdomain_release(link); if (link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; @@ -266,16 +260,15 @@ static void fdomain_config(dev_link_t *link) cs_failed: cs_error(link->handle, last_fn, last_ret); - fdomain_release((u_long)link); + fdomain_release(link); return; } /* fdomain_config */ /*====================================================================*/ -static void fdomain_release(u_long arg) +static void fdomain_release(dev_link_t *link) { - dev_link_t *link = (dev_link_t *)arg; scsi_info_t *info = link->priv; DEBUG(0, "fdomain_release(0x%p)\n", link); @@ -307,7 +300,7 @@ static int fdomain_event(event_t event, int priority, case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ/20); + fdomain_release(link); break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 5165af63b6b5..01c56a591d9e 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -38,7 +38,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/timer.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/interrupt.h> @@ -1477,10 +1476,6 @@ static dev_link_t *nsp_cs_attach(void) link = &info->link; link->priv = info; - /* Initialize the dev_link_t structure */ - link->release.function = &nsp_cs_release; - link->release.data = (u_long)link; - /* The io structure describes IO port mapping */ link->io.NumPorts1 = 0x10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -1558,9 +1553,8 @@ static void nsp_cs_detach(dev_link_t *link) return; } - del_timer(&link->release); if (link->state & DEV_CONFIG) { - nsp_cs_release((u_long)link); + nsp_cs_release(link); if (link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; @@ -1780,7 +1774,7 @@ static void nsp_cs_config(dev_link_t *link) cs_failed: cs_error(link->handle, last_fn, last_ret); - nsp_cs_release((u_long)link); + nsp_cs_release(link); return; } /* nsp_cs_config */ @@ -1792,9 +1786,8 @@ cs_failed: device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. ======================================================================*/ -static void nsp_cs_release(u_long arg) +static void nsp_cs_release(dev_link_t *link) { - dev_link_t *link = (dev_link_t *)arg; scsi_info_t *info = link->priv; DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link); @@ -1866,7 +1859,7 @@ static int nsp_cs_event(event_t event, link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { ((scsi_info_t *)link->priv)->stop = 1; - mod_timer(&link->release, jiffies + HZ/20); + nsp_cs_release(link); } break; @@ -1933,7 +1926,7 @@ static void __exit nsp_cs_exit(void) /* XXX: this really needs to move into generic code.. */ while (dev_list != NULL) { if (dev_list->state & DEV_CONFIG) { - nsp_cs_release((u_long)dev_list); + nsp_cs_release(dev_list); } nsp_cs_detach(dev_list); } diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index af862b66840c..905e799e91fc 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -272,7 +272,7 @@ typedef struct _nsp_hw_data { -static void nsp_cs_release(u_long arg); +static void nsp_cs_release(dev_link_t *link); static int nsp_cs_event(event_t event, int priority, event_callback_args_t *args); static dev_link_t *nsp_cs_attach(void); static void nsp_cs_detach(dev_link_t *); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 503a5fd05d96..8cee766334ec 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -37,7 +37,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/timer.h> #include <linux/ioport.h> #include <asm/io.h> #include <scsi/scsi.h> @@ -90,7 +89,7 @@ typedef struct scsi_info_t { unsigned short manf_id; } scsi_info_t; -static void qlogic_release(u_long arg); +static void qlogic_release(dev_link_t *link); static int qlogic_event(event_t event, int priority, event_callback_args_t * args); static dev_link_t *qlogic_attach(void); @@ -117,10 +116,6 @@ static dev_link_t *qlogic_attach(void) memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; - init_timer(&link->release); - link->release.function = &qlogic_release; - link->release.data = (u_long) link; - link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.IOAddrLines = 10; @@ -170,9 +165,8 @@ static void qlogic_detach(dev_link_t * link) if (*linkp == NULL) return; - del_timer_sync(&link->release); if (link->state & DEV_CONFIG) { - qlogic_release((u_long) link); + qlogic_release(link); if (link->state & DEV_STALE_CONFIG) { link->state |= DEV_STALE_LINK; return; @@ -279,16 +273,15 @@ out: cs_failed: cs_error(link->handle, last_fn, last_ret); - qlogic_release((u_long) link); + qlogic_release(link); return; } /* qlogic_config */ /*====================================================================*/ -static void qlogic_release(u_long arg) +static void qlogic_release(dev_link_t *link) { - dev_link_t *link = (dev_link_t *) arg; scsi_info_t *info = link->priv; DEBUG(0, "qlogic_release(0x%p)\n", link); @@ -319,7 +312,7 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ / 20); + qlogic_release(link); break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 25e031649be9..72ca360a950a 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -3,7 +3,7 @@ * * QLogic QLA1280 (Ultra2) and QLA12160 (Ultra3) SCSI driver * Copyright (C) 2000 Qlogic Corporation (www.qlogic.com) -* Copyright (C) 2001-2002 Jes Sorensen, Wild Open Source Inc. +* Copyright (C) 2001-2003 Jes Sorensen, Wild Open Source Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,9 +16,52 @@ * General Public License for more details. * ******************************************************************************/ -#define QLA1280_VERSION "3.23.19 Beta" -/****************************************************************************** +#define QLA1280_VERSION "3.23.34" +/***************************************************************************** Revision History: + Rev 3.23.34 July 23, 2003, Jes Sorensen + - Remove pointless TRUE/FALSE macros + - Clean up vchan handling + Rev 3.23.33 July 3, 2003, Jes Sorensen + - Don't define register access macros before define determining MMIO. + This just happend to work out on ia64 but not elsewhere. + - Don't try and read from the card while it is in reset as + it won't respond and causes an MCA + Rev 3.23.32 June 23, 2003, Jes Sorensen + - Basic support for boot time arguments + Rev 3.23.31 June 8, 2003, Jes Sorensen + - Reduce boot time messages + Rev 3.23.30 June 6, 2003, Jes Sorensen + - Do not enable sync/wide/ppr before it has been determined + that the target device actually supports it + - Enable DMA arbitration for multi channel controllers + Rev 3.23.29 June 3, 2003, Jes Sorensen + - Port to 2.5.69 + Rev 3.23.28 June 3, 2003, Jes Sorensen + - Eliminate duplicate marker commands on bus resets + - Handle outstanding commands appropriately on bus/device resets + Rev 3.23.27 May 28, 2003, Jes Sorensen + - Remove bogus input queue code, let the Linux SCSI layer do the work + - Clean up NVRAM handling, only read it once from the card + - Add a number of missing default nvram parameters + Rev 3.23.26 Beta May 28, 2003, Jes Sorensen + - Use completion queue for mailbox commands instead of busy wait + Rev 3.23.25 Beta May 27, 2003, James Bottomley + - Migrate to use new error handling code + Rev 3.23.24 Beta May 21, 2003, James Bottomley + - Big endian support + - Cleanup data direction code + Rev 3.23.23 Beta May 12, 2003, Jes Sorensen + - Switch to using MMIO instead of PIO + Rev 3.23.22 Beta April 15, 2003, Jes Sorensen + - Fix PCI parity problem with 12160 during reset. + Rev 3.23.21 Beta April 14, 2003, Jes Sorensen + - Use pci_map_page()/pci_unmap_page() instead of map_single version. + Rev 3.23.20 Beta April 9, 2003, Jes Sorensen + - Remove < 2.4.x support + - Introduce HOST_LOCK to make the spin lock changes portable. + - Remove a bunch of idiotic and unnecessary typedef's + - Kill all leftovers of target-mode support which never worked anyway Rev 3.23.19 Beta April 11, 2002, Linus Torvalds - Do qla1280_pci_config() before calling request_irq() and request_region() @@ -107,8 +150,8 @@ - Provide compat macros for pci_enable_device(), pci_find_subsys() and scsi_set_pci_device() - Call scsi_set_pci_device() for all devices - - Reduce size of kernel version dependent device probe code - - Move duplicate probe/init code to separate function + - Reduce size of kernel version dependant device probe code + - Move duplicate probe/init code to seperate function - Handle error if qla1280_mem_alloc() fails - Kill OFFSET() macro and use Linux's PCI definitions instead - Kill private structure defining PCI config space (struct config_reg) @@ -131,14 +174,14 @@ - Added check of device_id when handling non QLA12160s during detect(). Rev 3.22 Beta January 5, 2001 BN Qlogic - - Changed queue_task() to schedule_work() + - Changed queue_task() to schedule_task() for kernels 2.4.0 and higher. Note: 2.4.0-testxx kernels released prior to the actual 2.4.0 kernel release on January 2001 - will get compile/link errors with schedule_work(). + will get compile/link errors with schedule_task(). Please update your kernel to released 2.4.0 level, or comment lines in this file flagged with 3.22 - to resolve compile/link error of schedule_work(). + to resolve compile/link error of schedule_task(). - Added -DCONFIG_SMP in addition to -D__SMP__ in Makefile for 2.4.0 builds of driver as module. Rev 3.21 Beta January 4, 2001 BN Qlogic @@ -238,6 +281,7 @@ - Initial Beta Release. *****************************************************************************/ + #include <linux/config.h> #include <linux/module.h> @@ -246,56 +290,54 @@ #include <linux/string.h> #include <linux/errno.h> #include <linux/kernel.h> -#include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/timer.h> +#include <linux/sched.h> #include <linux/pci.h> #include <linux/proc_fs.h> -#include <linux/blkdev.h> -#include <linux/workqueue.h> +#include <linux/blk.h> #include <linux/stat.h> #include <linux/slab.h> +#include <linux/pci_ids.h> +#include <linux/interrupt.h> +#include <linux/init.h> + #include <asm/io.h> #include <asm/irq.h> #include <asm/byteorder.h> #include <asm/processor.h> +#include <asm/types.h> +#include <asm/system.h> -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#if LINUX_VERSION_CODE < 0x020545 +#include "sd.h" #endif +#include "scsi.h" +#include "hosts.h" -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) -#include <linux/pci_ids.h> +#if LINUX_VERSION_CODE < 0x020407 +#error "Kernels older than 2.4.7 are no longer supported" #endif -#include "scsi.h" -#include "hosts.h" -#define UNIQUE_FW_NAME -#include "qla1280.h" -#include "ql12160_fw.h" /* ISP RISC codes */ -#include "ql1280_fw.h" /* * Compile time Options: * 0 - Disable and 1 - Enable */ -#define QL1280_TARGET_MODE_SUPPORT 0 /* Target mode support */ -#define QL1280_LUN_SUPPORT 0 -#define WATCHDOGTIMER 0 -#define MEMORY_MAPPED_IO 0 -#define DEBUG_QLA1280_INTR 0 -#define USE_NVRAM_DEFAULTS 0 -#define DEBUG_PRINT_NVRAM 0 -#define LOADING_RISC_ACTIVITY 0 -#define AUTO_ESCALATE_RESET 0 /* Automatically escalate resets */ -#define AUTO_ESCALATE_ABORT 0 /* Automatically escalate aborts */ -#define STOP_ON_ERROR 0 /* Stop on aborts and resets */ -#define STOP_ON_RESET 0 -#define STOP_ON_ABORT 0 -#define QLA1280_PROFILE 1 /* 3.20 */ -#define DEBUG_QLA1280 0 +#define QL1280_LUN_SUPPORT 0 +#define WATCHDOGTIMER 0 +#define MEMORY_MAPPED_IO 1 +#define DEBUG_QLA1280_INTR 0 +#define DEBUG_PRINT_NVRAM 0 +#define DEBUG_QLA1280 0 + +#define UNIQUE_FW_NAME +#include "qla1280.h" +#include "ql12160_fw.h" /* ISP RISC codes */ +#include "ql1280_fw.h" + /* * Missing PCI ID's @@ -320,97 +362,65 @@ #define PCI_VENDOR_ID_AMI 0x101e #endif +#ifndef BITS_PER_LONG +#error "BITS_PER_LONG not defined!" +#endif #if (BITS_PER_LONG == 64) || defined CONFIG_HIGHMEM #define QLA_64BIT_PTR 1 #endif -/* 3.16 */ -#ifdef QLA_64BIT_PTR -#define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) ((a >> 16)>>16) -#else -#define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) 0 +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) +#include <asm/sn/pci/pciio.h> +/* Ugly hack needed for the virtual channel fix on SN2 */ +extern int snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, + int *count_vchan0, int *count_vchan1); #endif -/* MACROS for managing the endian addresses */ -static inline uint16_t qla1280_addr0_15(dma_addr_t dma) -{ - return ((uint16_t)(dma & 0xffff)); -} -static inline uint16_t qla1280_addr16_31(dma_addr_t dma) -{ - return ((uint16_t)((dma >> 16) & 0xffff)); -} -static inline uint16_t qla1280_addr32_47(dma_addr_t dma) -{ - return ((uint16_t)(pci_dma_hi32(dma) & 0xffff)); -} -static inline uint16_t qla1280_addr48_63(dma_addr_t dma) -{ - return ((uint16_t)((pci_dma_hi32(dma) >> 16) & 0xffff)); -} - -#define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */ -#define CACHE_FLUSH(a) RD_REG_WORD(a) -#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 1) - -/* - * Compat macros - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -#define pci_set_dma_mask(dev, mask) dev->dma_mask = mask; -#define pci_enable_device(pdev) 0 -#define pci_find_subsys(id, dev, sid, sdev, pdev) pci_find_device(id,dev,pdev) -#define scsi_set_pci_device(host, pdev) +#ifdef QLA_64BIT_PTR +#define pci_dma_hi32(a) ((a >> 16) >> 16) +#else +#define pci_dma_hi32(a) 0 #endif +#define pci_dma_lo32(a) (a & 0xffffffff) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) -typedef unsigned long dma_addr_t; +#define NVRAM_DELAY() udelay(500) /* 2 microseconds */ -static inline void * -pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) +#if LINUX_VERSION_CODE < 0x020500 +#define HOST_LOCK &io_request_lock +#define irqreturn_t void +#define IRQ_RETVAL(foo) +#define MSG_ORDERED_TAG 1 +static inline void +scsi_adjust_queue_depth(Scsi_Device *device, int tag, int depth) { - void *virt_ptr; - - virt_ptr = kmalloc(size, GFP_KERNEL); - if (!virt_ptr) - return NULL; - *dma_handle = virt_to_bus(virt_ptr); - return virt_ptr; + if (tag) { + device->tagged_queue = tag; + device->current_tag = 0; + } + device->queue_depth = depth; } - -#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr) -#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) -#define pci_map_sg(cookie, scatter, ents, dir) ents -#define pci_unmap_single(cookie, address, size, dir) -#define pci_unmap_sg(cookie, scatter, ents, dir) - -#define pci_resource_start(dev, i) dev->base_address[i] +#else +#define HOST_LOCK ha->host->host_lock +#endif +#if defined(__ia64__) && !defined(ia64_platform_is) +#define ia64_platform_is(foo) (!strcmp(x, platform_name)) #endif /* * QLogic Driver Support Function Prototypes. */ -static void qla1280_done(struct scsi_qla_host *, srb_t **, srb_t **); -static void qla1280_next(struct scsi_qla_host *, scsi_lu_t *, int); -static void qla1280_putq_t(scsi_lu_t *, srb_t *); -static void qla1280_done_q_put(srb_t *, srb_t **, srb_t **); +static void qla1280_done(struct scsi_qla_host *, struct srb **, struct srb **); +static void qla1280_done_q_put(struct srb *, struct srb **, struct srb **); static int qla1280_slave_configure(Scsi_Device *); -#if STOP_ON_ERROR -static void qla1280_panic(char *, struct Scsi_Host *host); +#if LINUX_VERSION_CODE < 0x020545 +static void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *); +void qla1280_get_target_options(struct scsi_cmnd *, struct scsi_qla_host *); #endif -static void qla1280_abort_queue_single(struct scsi_qla_host *, int, int, - int, uint32_t); -static int qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp); -static void qla1280_removeq(scsi_lu_t * q, srb_t * sp); +static int qla1280_return_status(struct response * sts, Scsi_Cmnd * cp); static void qla1280_mem_free(struct scsi_qla_host *ha); void qla1280_do_dpc(void *p); -#ifdef MODULE -static char *qla1280_get_token(char *, char *); -#endif +static int qla1280_get_token(char *); static inline void qla1280_enable_intrs(struct scsi_qla_host *); static inline void qla1280_disable_intrs(struct scsi_qla_host *); @@ -418,7 +428,6 @@ static inline void qla1280_disable_intrs(struct scsi_qla_host *); * QLogic ISP1280 Hardware Support Function Prototypes. */ static int qla1280_initialize_adapter(struct scsi_qla_host *ha); -static int qla1280_enable_tgt(struct scsi_qla_host *, int); static int qla1280_isp_firmware(struct scsi_qla_host *); static int qla1280_pci_config(struct scsi_qla_host *); static int qla1280_chip_diag(struct scsi_qla_host *); @@ -430,23 +439,22 @@ static int qla1280_mailbox_command(struct scsi_qla_host *, static int qla1280_bus_reset(struct scsi_qla_host *, int); static int qla1280_device_reset(struct scsi_qla_host *, int, int); static int qla1280_abort_device(struct scsi_qla_host *, int, int, int); -static int qla1280_abort_command(struct scsi_qla_host *, srb_t *); +static int qla1280_abort_command(struct scsi_qla_host *, struct srb *, int); static int qla1280_abort_isp(struct scsi_qla_host *); -static int qla1280_64bit_start_scsi(struct scsi_qla_host *, srb_t *); -static int qla1280_32bit_start_scsi(struct scsi_qla_host *, srb_t *); +static int qla1280_64bit_start_scsi(struct scsi_qla_host *, struct srb *); +static int qla1280_32bit_start_scsi(struct scsi_qla_host *, struct srb *); static void qla1280_nv_write(struct scsi_qla_host *, uint16_t); static void qla1280_poll(struct scsi_qla_host *); static void qla1280_reset_adapter(struct scsi_qla_host *); static void qla1280_marker(struct scsi_qla_host *, int, int, int, u8); static void qla1280_isp_cmd(struct scsi_qla_host *); -static void qla1280_isr(struct scsi_qla_host *, srb_t **, srb_t **); +irqreturn_t qla1280_intr_handler(int, void *, struct pt_regs *); +static void qla1280_isr(struct scsi_qla_host *, struct srb **, struct srb **); static void qla1280_rst_aen(struct scsi_qla_host *); -static void qla1280_status_entry(struct scsi_qla_host *, sts_entry_t *, - srb_t **, srb_t **); -static void qla1280_error_entry(struct scsi_qla_host *, response_t *, - srb_t **, srb_t **); -static void qla1280_restart_queues(struct scsi_qla_host *); -static void qla1280_abort_queues(struct scsi_qla_host *); +static void qla1280_status_entry(struct scsi_qla_host *, struct response *, + struct srb **, struct srb **); +static void qla1280_error_entry(struct scsi_qla_host *, struct response *, + struct srb **, struct srb **); static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t); static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t); static uint16_t qla1280_debounce_register(volatile uint16_t *); @@ -456,9 +464,14 @@ static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *, static int qla1280_mem_alloc(struct scsi_qla_host *ha); static void qla12160_get_target_parameters(struct scsi_qla_host *, - uint32_t, uint32_t, uint32_t); + Scsi_Device *); +static int qla12160_set_target_parameters(struct scsi_qla_host *, int, int); + -/* convert scsi data direction to request_t control flags +static struct qla_driver_setup driver_setup __initdata; + +/* + * convert scsi data direction to request_t control flags */ static inline uint16_t qla1280_data_direction(struct scsi_cmnd *cmnd) @@ -491,58 +504,26 @@ qla1280_data_direction(struct scsi_cmnd *cmnd) static void qla1280_enable_lun(struct scsi_qla_host *, int, int); #endif -#if QL1280_TARGET_MODE_SUPPORT -static void qla1280_notify_ack(struct scsi_qla_host *, notify_entry_t *); -static void qla1280_immed_notify(struct scsi_qla_host *, notify_entry_t *); -static void qla1280_accept_io(struct scsi_qla_host *, ctio_ret_entry_t *); -static void qla1280_64bit_continue_io(struct scsi_qla_host *, atio_entry_t *, - uint32_t, paddr32_t *); -static void qla1280_32bit_continue_io(struct scsi_qla_host *, atio_entry_t *, - uint32_t, paddr32_t *); -static void qla1280_atio_entry(struct scsi_qla_host *, atio_entry_t *); -static void qla1280_notify_entry(struct scsi_qla_host *, notify_entry_t *); -#endif /* QLA1280_TARGET_MODE_SUPPORT */ - -#ifdef QL_DEBUG_ROUTINES -/* - * Driver Debug Function Prototypes. - */ -static u8 qla1280_getbyte(u8 *); -static u16 qla1280_getword(u16 *); -static u32 qla1280_getdword(u32 *); -static void qla1280_putbyte(u8 *, u8); -static void qla1280_putword(u16 *, u8); -static void qla1280_putdword(u32 *, u32); +#if DEBUG_QLA1280 static void __qla1280_print_scsi_cmd(Scsi_Cmnd * cmd); -static void __qla1280_dump_buffer(char *, u32); +static void __qla1280_dump_buffer(char *, int); #endif + /* * insmod needs to find the variable and make it point to something */ #ifdef MODULE -static char *options = NULL; +static char *qla1280; /* insmod qla1280 options=verbose" */ -MODULE_PARM(options, "s"); +MODULE_PARM(qla1280, "s"); +#else +__setup("qla1280=", qla1280_setup); #endif MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) -/* - * Our directory Entry in /proc/scsi for the user to - * access the driver. - */ -/* Need to add in proc_fs.h PROC_SCSI_QL1280 */ -#define PROC_SCSI_QL1280 PROC_SCSI_QLOGICISP - -struct proc_dir_entry proc_scsi_qla1280 = { - PROC_SCSI_QL1280, 7, "qla1280", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif /* We use the Scsi_Pointer structure that's included with each command * SCSI_Cmnd as a scratchpad for our SRB. @@ -565,6 +546,19 @@ struct proc_dir_entry proc_scsi_qla1280 = { #define CMD_SNSLEN(Cmnd) sizeof(Cmnd->sense_buffer) #define CMD_RESULT(Cmnd) Cmnd->result #define CMD_HANDLE(Cmnd) Cmnd->host_scribble +#if LINUX_VERSION_CODE < 0x020545 +#define CMD_HOST(Cmnd) Cmnd->host +#define CMD_REQUEST(Cmnd) Cmnd->request.cmd +#define SCSI_BUS_32(Cmnd) Cmnd->channel +#define SCSI_TCN_32(Cmnd) Cmnd->target +#define SCSI_LUN_32(Cmnd) Cmnd->lun +#else +#define CMD_HOST(Cmnd) Cmnd->device->host +#define CMD_REQUEST(Cmnd) Cmnd->request->cmd +#define SCSI_BUS_32(Cmnd) Cmnd->device->channel +#define SCSI_TCN_32(Cmnd) Cmnd->device->id +#define SCSI_LUN_32(Cmnd) Cmnd->device->lun +#endif /*****************************************/ /* ISP Boards supported by this driver */ @@ -573,7 +567,7 @@ struct proc_dir_entry proc_scsi_qla1280 = { #define NUM_OF_ISP_DEVICES 6 struct qla_boards { - unsigned char bdName[9]; /* Board ID String */ + unsigned char name[9]; /* Board ID String */ unsigned long device_id; /* Device PCI ID */ int numPorts; /* Number of SCSI ports */ unsigned short *fwcode; /* pointer to FW array */ @@ -584,44 +578,38 @@ struct qla_boards { struct qla_boards ql1280_board_tbl[NUM_OF_ISP_DEVICES] = { /* Name , Board PCI Device ID, Number of ports */ - {"QLA12160 ", PCI_DEVICE_ID_QLOGIC_ISP12160, 2, + {"QLA12160", PCI_DEVICE_ID_QLOGIC_ISP12160, 2, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, - {"QLA1080 ", PCI_DEVICE_ID_QLOGIC_ISP1080, 1, + {"QLA1080", PCI_DEVICE_ID_QLOGIC_ISP1080, 1, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, - {"QLA1240 ", PCI_DEVICE_ID_QLOGIC_ISP1240, 2, + {"QLA1240", PCI_DEVICE_ID_QLOGIC_ISP1240, 2, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, - {"QLA1280 ", PCI_DEVICE_ID_QLOGIC_ISP1280, 2, + {"QLA1280", PCI_DEVICE_ID_QLOGIC_ISP1280, 2, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, - {"QLA10160 ", PCI_DEVICE_ID_QLOGIC_ISP10160, 1, + {"QLA10160", PCI_DEVICE_ID_QLOGIC_ISP10160, 1, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, {" ", 0, 0} }; static int qla1280_verbose = 1; -static struct scsi_qla_host *qla1280_hostlist = NULL; -#if QLA1280_PROFILE -static int qla1280_buffer_size = 0; -static char *qla1280_buffer = NULL; -#endif +static struct scsi_qla_host *qla1280_hostlist; +static int qla1280_buffer_size; +static char *qla1280_buffer; #if DEBUG_QLA1280 -static int ql_debug_print = 1; -char debug_buff[80]; -#define DEBUG(x) x -static int ql_debug_level = 0; +static int ql_debug_level = 1; #define dprintk(level, format, a...) \ - if ((ql_debug_level >= level) && ql_debug_print) printk(KERN_DEBUG format, ##a) + do { if (ql_debug_level >= level) printk(KERN_ERR format, ##a); } while(0) #define qla1280_dump_buffer(level, buf, size) \ if (ql_debug_level >= level) __qla1280_dump_buffer(buf, size) -#define qla1280_dump_print_cmd(level, cmd) \ +#define qla1280_print_scsi_cmd(level, cmd) \ if (ql_debug_level >= level) __qla1280_print_scsi_cmd(cmd) #else -#define DEBUG(x) #define ql_debug_level 0 #define dprintk(level, format, a...) do{}while(0) #define qla1280_dump_buffer(a, b, c) do{}while(0) @@ -630,30 +618,9 @@ static int ql_debug_level = 0; #define ENTER(x) dprintk(3, "qla1280 : Entering %s()\n", x); #define LEAVE(x) dprintk(3, "qla1280 : Leaving %s()\n", x); -#define ENTER_INTR(x) dprintk(3, "qla1280 : Entering %s()\n", x); -#define LEAVE_INTR(x) dprintk(3, "qla1280 : Leaving %s()\n", x); - -#define SCSI_BUS_32(scp) scp->device->channel -#define SCSI_TCN_32(scp) scp->device->id -#define SCSI_LUN_32(scp) scp->device->lun - -/****************************************************************************/ -/* LINUX - Loadable Module Functions. */ -/****************************************************************************/ +#define ENTER_INTR(x) dprintk(4, "qla1280 : Entering %s()\n", x); +#define LEAVE_INTR(x) dprintk(4, "qla1280 : Leaving %s()\n", x); -/************************************************************************* - * qla1280_set_info - * - * Description: - * Set parameters for the driver from the /proc filesystem. - * - * Returns: - *************************************************************************/ -int -qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) -{ - return -ENOSYS; /* Currently this is a no-op */ -} /************************************************************************* * qla1280_proc_info @@ -668,28 +635,39 @@ qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) #define PROC_BUF &qla1280_buffer[len] int -qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, - int inout) +qla1280_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout) { -#if QLA1280_PROFILE + struct Scsi_Host *host; struct scsi_qla_host *ha; int size = 0; - scsi_lu_t *up; int len = 0; struct qla_boards *bdp; +#ifdef BOGUS_QUEUE + struct scsi_lu *up; uint32_t b, t, l; - host = NULL; +#endif /* Find the host that was specified */ - for (ha = qla1280_hostlist; (ha != NULL) && ha->host != host; - ha = ha->next) ; - - if (inout == TRUE) { /* Has data been written to the file? */ - printk(KERN_INFO - "qla1280_proc: has data been written to the file.\n"); - return qla1280_set_info(buffer, length, host); + for (ha = qla1280_hostlist; (ha != NULL) + && ha->host->host_no != hostno; ha = ha->next) ; + + /* if host wasn't found then exit */ + if (!ha) { + size = sprintf(buffer, "Can't find adapter for host " + "number %d\n", hostno); + if (size > length) { + return size; + } else { + return 0; + } } + host = ha->host; + + if (inout) + return -ENOSYS; + /* * if our old buffer is the right size use it otherwise * allocate a new one. @@ -724,10 +702,7 @@ qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offs len += size; size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", - bdp->bdName); - len += size; - size = sprintf(PROC_BUF, "Request Queue = 0x%p, Response Queue = 0x%p\n", - (void *)ha->request_dma, (void *)ha->response_dma); + bdp->name); len += size; size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response " "Queue count= 0x%x\n", @@ -736,9 +711,6 @@ qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offs size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n", ha->actthreads); len += size; - size = sprintf(PROC_BUF, "Number of queued commands = 0x%lx\n", - ha->qthreads); - len += size; size = sprintf(PROC_BUF, "Number of free request entries = %d\n", ha->req_q_cnt); len += size; @@ -747,6 +719,7 @@ qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offs size = sprintf(PROC_BUF, "SCSI device Information:\n"); len += size; +#ifdef BOGUS_QUEUE /* scan for all equipment stats */ for (b = 0; b < MAX_BUSES; b++) for (t = 0; t < MAX_TARGETS; t++) { @@ -787,6 +760,7 @@ qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offs if (len >= qla1280_buffer_size) break; } +#endif if (len >= qla1280_buffer_size) { printk(KERN_WARNING @@ -805,11 +779,67 @@ qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offs } } return length; -#else - return 0; -#endif } + +static int qla1280_read_nvram(struct scsi_qla_host *ha) +{ + uint16_t *wptr; + uint8_t chksum; + int cnt; + struct nvram *nv; + + ENTER("qla1280_read_nvram"); + + if (driver_setup.no_nvram) + return 1; + + printk(KERN_INFO "scsi(%ld): Reading NVRAM\n", ha->host_no); + + wptr = (uint16_t *)&ha->nvram; + nv = &ha->nvram; + chksum = 0; + for (cnt = 0; cnt < 3; cnt++) { + *wptr = qla1280_get_nvram_word(ha, cnt); + chksum += *wptr & 0xff; + chksum += (*wptr >> 8) & 0xff; + wptr++; + } + + if (nv->id0 != 'I' || nv->id1 != 'S' || + nv->id2 != 'P' || nv->id3 != ' ' || nv->version < 1) { + dprintk(2, "Invalid nvram ID or version!\n"); + chksum = 1; + } else { + for (; cnt < sizeof(struct nvram); cnt++) { + *wptr = qla1280_get_nvram_word(ha, cnt); + chksum += *wptr & 0xff; + chksum += (*wptr >> 8) & 0xff; + wptr++; + } + } + + dprintk(3, "qla1280_read_nvram: NVRAM Magic ID= %c %c %c %02x" + " version %i\n", nv->id0, nv->id1, nv->id2, nv->id3, + nv->version); + + + if (chksum) { + if (!driver_setup.no_nvram) + printk(KERN_WARNING "scsi(%ld): Unable to identify or " + "validate NVRAM checksum, using default " + "settings\n", ha->host_no); + ha->nvram_valid = 0; + } else + ha->nvram_valid = 1; + + dprintk(1, "qla1280_read_nvram: Completed Reading NVRAM\n"); + LEAVE("qla1280_read_nvram"); + + return chksum; +} + + /************************************************************************** * qla1280_do_device_init * This routine will register the device with the SCSI subsystem, @@ -827,17 +857,18 @@ qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offs * host - pointer to SCSI host structure **************************************************************************/ struct Scsi_Host * -qla1280_do_device_init(struct pci_dev *pdev, - Scsi_Host_Template * template, +qla1280_do_device_init(struct pci_dev *pdev, Scsi_Host_Template * template, int devnum, struct qla_boards *bdp, int num_hosts) { struct Scsi_Host *host; struct scsi_qla_host *ha; - struct device_reg *reg; - printk("qla1x160: Initializing ISP12160 on PCI bus %i, dev %i, irq %i\n", - pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->irq); + printk(KERN_INFO "qla1280: %s found on PCI bus %i, dev %i\n", + bdp->name, pdev->bus->number, PCI_SLOT(pdev->devfn)); +#if LINUX_VERSION_CODE >= 0x020545 + template->slave_configure = qla1280_slave_configure; +#endif host = scsi_register(template, sizeof(struct scsi_qla_host)); if (!host) { printk(KERN_WARNING @@ -845,7 +876,11 @@ qla1280_do_device_init(struct pci_dev *pdev, goto error; } +#if LINUX_VERSION_CODE < 0x020545 + scsi_set_pci_device(host, pdev); +#else scsi_set_device(host, &pdev->dev); +#endif ha = (struct scsi_qla_host *)host->hostdata; /* Clear our data area */ memset(ha, 0, sizeof(struct scsi_qla_host)); @@ -869,16 +904,13 @@ qla1280_do_device_init(struct pci_dev *pdev, host->can_queue = 0xfffff; /* unlimited */ host->cmd_per_lun = 1; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) - host->base = (unsigned char *)ha->mmpbase; -#else host->base = (unsigned long)ha->mmpbase; -#endif host->max_channel = bdp->numPorts - 1; host->max_lun = MAX_LUNS - 1; host->max_id = MAX_TARGETS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) host->max_sectors = 1024; +#if LINUX_VERSION_CODE < 0x020545 + host->select_queue_depths = qla1280_select_queue_depth; #endif ha->instance = num_hosts; @@ -897,25 +929,25 @@ qla1280_do_device_init(struct pci_dev *pdev, "qla1280", ha)) { printk("qla1280 : Failed to reserve interrupt %d already " "in use\n", host->irq); - goto error_unmap; + goto error_mem_alloced; } #if !MEMORY_MAPPED_IO /* Register the I/O space with Linux */ - if (!request_region(host->io_port, 0xff, "qla1280")) { - printk("qla1280 : Failed to reserve i/o region 0x%04lx-0x%04lx" + if (check_region(host->io_port, 0xff)) { + printk("qla1280: Failed to reserve i/o region 0x%04lx-0x%04lx" " already in use\n", host->io_port, host->io_port + 0xff); - goto error_irq; + free_irq(host->irq, ha); + goto error_mem_alloced; } + request_region(host->io_port, 0xff, "qla1280"); #endif - reg = ha->iobase; - /* load the F/W, read paramaters, and init the H/W */ if (qla1280_initialize_adapter(ha)) { - printk(KERN_INFO "qla1x160:Failed to initialize adapter\n"); - goto error_region; + printk(KERN_INFO "qla1x160: Failed to initialize adapter\n"); + goto error_mem_alloced; } /* set our host ID (need to do something about our two IDs) */ @@ -923,21 +955,6 @@ qla1280_do_device_init(struct pci_dev *pdev, return host; - error_region: -#if !MEMORY_MAPPED_IO - release_region(host->io_port, 0xff); -#endif - - error_irq: - free_irq(host->irq, ha); - - error_unmap: -#if MEMORY_MAPPED_IO - if (ha->mmpbase) - iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK)); -#endif - - error_mem_alloced: qla1280_mem_free(ha); @@ -975,14 +992,12 @@ qla1280_detect(Scsi_Host_Template * template) ENTER("qla1280_detect"); - if (sizeof(srb_t) > sizeof(Scsi_Pointer)) { + if (sizeof(struct srb) > sizeof(Scsi_Pointer)) { printk(KERN_WARNING - "qla1280_detect: [WARNING] srb_t too big\n"); + "qla1280_detect: [WARNING] struct srb too big\n"); return 0; } #ifdef MODULE - dprintk(1, "DEBUG: qla1280_detect starts at address = %p\n", - qla1280_detect); /* * If we are called as a module, the qla1280 pointer may not be null * and it would point to our bootup string, just like on the lilo @@ -995,28 +1010,14 @@ qla1280_detect(Scsi_Host_Template * template) * which will result in the first four devices on the first two * controllers being set to a tagged queue depth of 32. */ - if (options) - qla1280_setup(options, NULL); - - printk(KERN_WARNING - "qla1280: Please read the file /usr/src/linux/Documentation" - "/scsi/qla1280.txt\n" - "qla1280: to see the proper way to specify options to the qla1280 " - "module\n" - "qla1280: Specifically, don't use any commas when passing " - "arguments to\n" - "qla1280: insmod or else it might trash certain memory areas.\n"); + if (qla1280) + qla1280_setup(qla1280); #endif bdp = &ql1280_board_tbl[0]; qla1280_hostlist = NULL; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) - template->proc_dir = &proc_scsi_qla1280; -#else template->proc_name = "qla1280"; -#endif - /* 3.20 */ /* First Initialize QLA12160 on PCI Bus 1 Dev 2 */ while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, bdp->device_id, PCI_ANY_ID, PCI_ANY_ID, pdev))) { @@ -1059,15 +1060,9 @@ qla1280_detect(Scsi_Host_Template * template) if (pci_enable_device(pdev)) continue; /* found an adapter */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) subsys_vendor = pdev->subsystem_vendor; subsys_device = pdev->subsystem_device; -#else - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, - &subsys_vendor); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, - &subsys_device); -#endif + /* * skip QLA12160 already initialized on * PCI Bus 1 Dev 2 since we already initialized @@ -1084,8 +1079,7 @@ qla1280_detect(Scsi_Host_Template * template) "qla1x160: Skip AMI SubSys Vendor ID Chip\n"); continue; } - printk(KERN_INFO - "qla1x160: Supported Device Found VID=%x " + dprintk(1, "qla1x160: Supported Device Found VID=%x " "DID=%x SSVID=%x SSDID=%x\n", pdev->vendor, pdev->device, subsys_vendor, subsys_device); @@ -1135,7 +1129,7 @@ qla1280_release(struct Scsi_Host *host) #if MEMORY_MAPPED_IO if (ha->mmpbase) - iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK)); + iounmap(ha->mmpbase); #else /* release io space registers */ if (host->io_port) @@ -1167,7 +1161,7 @@ qla1280_info(struct Scsi_Host *host) sprintf (bp, "QLogic %s PCI to SCSI Host Adapter: bus %d device %d irq %d\n" " Firmware version: %2d.%02d.%02d, Driver version %s", - &bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, + &bdp->name[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], QLA1280_VERSION); return bp; @@ -1188,19 +1182,20 @@ int qla1280_queuecommand(Scsi_Cmnd * cmd, void (*fn) (Scsi_Cmnd *)) { struct scsi_qla_host *ha; - srb_t *sp; + struct srb *sp; struct Scsi_Host *host; int bus, target, lun; - scsi_lu_t *q; + int status; /*ENTER("qla1280_queuecommand"); */ + dprintk(2, "qla1280_queuecommand(): jiffies %li\n", jiffies); - host = cmd->device->host; + host = CMD_HOST(cmd); ha = (struct scsi_qla_host *)host->hostdata; /* send command to adapter */ - sp = (srb_t *)CMD_SP(cmd); + sp = (struct srb *)CMD_SP(cmd); sp->cmd = cmd; cmd->scsi_done = fn; if (cmd->flags == 0) { /* new command */ @@ -1213,63 +1208,46 @@ qla1280_queuecommand(Scsi_Cmnd * cmd, void (*fn) (Scsi_Cmnd *)) bus = SCSI_BUS_32(cmd); target = SCSI_TCN_32(cmd); lun = SCSI_LUN_32(cmd); - if ((q = LU_Q(ha, bus, target, lun)) == NULL) { - if ((q = (scsi_lu_t *)kmalloc(sizeof(struct scsi_lu), - GFP_ATOMIC))) { - LU_Q(ha, bus, target, lun) = q; - memset(q, 0, sizeof(struct scsi_lu)); - dprintk(1, "Allocate new device queue 0x%p\n", - (void *)q); - } else { - CMD_RESULT(cmd) = DID_BUS_BUSY << 16; - qla1280_done_q_put(sp, &ha->done_q_first, - &ha->done_q_last); -/* 3.22 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 3.22 */ - schedule_work(&ha->run_qla_bh); -#else /* 3.22 */ - schedule_work(&ha->run_qla_bh); /* 3.22 */ -#endif /* 3.22 */ - return 0; - } - } - /* Set an invalid handle until we issue the command to ISP */ - /* then we will set the real handle value. */ - CMD_HANDLE(cmd) = (unsigned char *)INVALID_HANDLE; - - /* add the command to our queue */ - ha->qthreads++; - qla1280_putq_t(q, sp); - - dprintk(1, "qla1280_QC: t=%x CDB=%x I/OSize=0x%x haQueueCount=0x%lx\n", - target, cmd->cmnd[0], cmd->request_bufflen, ha->qthreads); - - /* send command to adapter */ - if (q->q_outcnt == 0) - qla1280_restart_queues(ha); + if (ha->flags.enable_64bit_addressing) + status = qla1280_64bit_start_scsi(ha, sp); + else + status = qla1280_32bit_start_scsi(ha, sp); /*LEAVE("qla1280_queuecommand"); */ - return 0; + return status; } -typedef enum { +enum action { ABORT_COMMAND, ABORT_DEVICE, DEVICE_RESET, BUS_RESET, ADAPTER_RESET, FAIL -} action_t; +}; /* timer action for error action processor */ static void qla1280_error_wait_timeout(unsigned long __data) { struct scsi_cmnd *cmd = (struct scsi_cmnd *)__data; - srb_t *sp = (srb_t *)CMD_SP(cmd); + struct srb *sp = (struct srb *)CMD_SP(cmd); complete(sp->wait); } +static void qla1280_mailbox_timeout(unsigned long __data) +{ + struct scsi_qla_host *ha = (struct scsi_qla_host *)__data; + struct device_reg *reg; + reg = ha->iobase; + + ha->mailbox_out[0] = RD_REG_WORD(®->mailbox0); + printk(KERN_ERR "scsi(%ld): mailbox timed out, mailbox0 %04x, " + "ictrl %04x, istatus %04x\n", ha->host_no, ha->mailbox_out[0], + RD_REG_WORD(®->ictrl), RD_REG_WORD(®->istatus)); + complete(ha->mailbox_wait); +} + /************************************************************************** * qla1200_error_action * The function will attempt to perform a specified error action and @@ -1281,7 +1259,7 @@ static void qla1280_error_wait_timeout(unsigned long __data) * action = error action to take (see action_t) * * Returns: - * SUCCESS or FAIL + * SUCCESS or FAILED * * Note: * Resetting the bus always succeeds - is has to, otherwise the @@ -1290,39 +1268,43 @@ static void qla1280_error_wait_timeout(unsigned long __data) * the SCSI bus reset line. **************************************************************************/ int -qla1280_error_action(Scsi_Cmnd * cmd, action_t action) +qla1280_error_action(Scsi_Cmnd * cmd, enum action action) { struct scsi_qla_host *ha; int bus, target, lun; - srb_t *sp; + struct srb *sp; uint16_t data; unsigned char *handle; - scsi_lu_t *q; - int result; + int result, i; DECLARE_COMPLETION(wait); struct timer_list timer; + ha = (struct scsi_qla_host *)(CMD_HOST(cmd)->hostdata); + + dprintk(4, "error_action %i, istatus 0x%04x\n", action, + RD_REG_WORD(&ha->iobase->istatus)); + + dprintk(4, "host_cmd 0x%04x, ictrl 0x%04x, jiffies %li\n", + RD_REG_WORD(&ha->iobase->host_cmd), + RD_REG_WORD(&ha->iobase->ictrl), jiffies); + ENTER("qla1280_error_action"); if (qla1280_verbose) - printk(KERN_INFO "scsi(): Resetting Cmnd=0x%p, Handle=0x%p, " - "action=0x%x\n", cmd, CMD_HANDLE(cmd), action); + printk(KERN_INFO "scsi(%li): Resetting Cmnd=0x%p, " + "Handle=0x%p, action=0x%x\n", + ha->host_no, cmd, CMD_HANDLE(cmd), action); if (cmd == NULL) { - printk(KERN_WARNING - "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd " - "pointer, failing.\n"); + printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL " + "si_Cmnd pointer, failing.\n"); LEAVE("qla1280_error_action"); - return FAIL; + return FAILED; } ha = (struct scsi_qla_host *)cmd->device->host->hostdata; - sp = (srb_t *)CMD_SP(cmd); + sp = (struct srb *)CMD_SP(cmd); handle = CMD_HANDLE(cmd); -#if STOP_ON_RESET - qla1280_panic("qla1280_reset", ha->host); -#endif - /* Check for pending interrupts. */ data = qla1280_debounce_register(&ha->iobase->istatus); /* @@ -1337,7 +1319,7 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) * Determine the suggested action that the mid-level driver wants * us to perform. */ - if (handle == NULL) { + if (handle == (unsigned char *)INVALID_HANDLE || handle == NULL) { if(action == ABORT_COMMAND) { /* we never got this command */ printk(KERN_INFO "qla1280: Aborting a NULL handle\n"); @@ -1350,23 +1332,16 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) bus = SCSI_BUS_32(cmd); target = SCSI_TCN_32(cmd); lun = SCSI_LUN_32(cmd); - q = LU_Q(ha, bus, target, lun); /* Overloading result. Here it means the success or fail of the * *issue* of the action. When we return from the routine, it must * mean the actual success or fail of the action */ - result = FAIL; + result = FAILED; switch (action) { case FAIL: break; case ABORT_COMMAND: - if (q == NULL) { - /* No lun queue -- command must not be active */ - printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the " - "specified device\n", bus, target, lun); - break; - } if ((sp->flags & SRB_ABORT_PENDING)) { printk(KERN_WARNING "scsi(): Command has a pending abort " @@ -1376,50 +1351,35 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) break; } - /* - * Normally, would would need to search our queue for - * the specified command but; since our sp contains - * the cmd ptr, we can just remove it from our LUN - * queue. - */ - if (!(sp->flags & SRB_SENT)) { - if (qla1280_verbose) - printk(KERN_WARNING - "scsi(): Command returned from queue " - "aborted.\n"); - - /* Remove srb from SCSI LU queue. */ - qla1280_removeq(q, sp); - sp->flags |= SRB_ABORTED; - CMD_RESULT(cmd) = DID_ABORT << 16; - qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last); - if (ha->done_q_first) - qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); - - qla1280_restart_queues(ha); - - } else { /* find the command in our active list */ - int i; - - for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { - if (sp == ha->outstanding_cmds[i]) { - dprintk(1, - "qla1280: RISC aborting command.\n"); - qla1280_abort_command(ha, sp); + for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) { + if (sp == ha->outstanding_cmds[i]) { + dprintk(1, "qla1280: RISC aborting command\n"); + if (qla1280_abort_command(ha, sp, i) == 0) + result = SUCCESS; + else { + /* + * Since we don't know what might + * have happend to the command, it + * is unsafe to remove it from the + * device's queue at this point. + * Wait and let the escalation + * process take care of it. + */ + printk(KERN_WARNING + "scsi(%li:%i:%i:%i): Unable" + " to abort command!\n", + ha->host_no, bus, target, lun); } } } break; - - case ABORT_DEVICE: - ha->flags.in_reset = TRUE; + ha->flags.in_reset = 1; if (qla1280_verbose) printk(KERN_INFO "scsi(%ld:%d:%d:%d): Queueing abort device " "command.\n", ha->host_no, bus, target, lun); - qla1280_abort_queue_single(ha, bus, target, lun, DID_ABORT); if (qla1280_abort_device(ha, bus, target, lun) == 0) result = SUCCESS; break; @@ -1429,31 +1389,18 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) printk(KERN_INFO "scsi(%ld:%d:%d:%d): Queueing device reset " "command.\n", ha->host_no, bus, target, lun); - ha->flags.in_reset = TRUE; - for (lun = 0; lun < MAX_LUNS; lun++) - qla1280_abort_queue_single(ha, bus, target, lun, - DID_ABORT); + ha->flags.in_reset = 1; if (qla1280_device_reset(ha, bus, target) == 0) result = SUCCESS; - q->q_flag |= QLA1280_QRESET; break; case BUS_RESET: if (qla1280_verbose) - printk(KERN_INFO "qla1280(%ld:%d:%d:%d): Issuing BUS " - "DEVICE RESET.\n", ha->host_no, bus, target, - lun); - ha->flags.in_reset = TRUE; - for (target = 0; target < MAX_TARGETS; target++) - for (lun = 0; lun < MAX_LUNS; lun++) - qla1280_abort_queue_single(ha, bus, target, - lun, DID_RESET); - qla1280_bus_reset(ha, bus); - - /* wait 4 seconds */ - schedule_timeout(4*HZ); - - result = SUCCESS; + printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS " + "DEVICE RESET\n", ha->host_no, bus); + ha->flags.in_reset = 1; + if (qla1280_bus_reset(ha, bus == 0)) + result = SUCCESS; break; @@ -1461,14 +1408,12 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) default: if (qla1280_verbose) { printk(KERN_INFO - "scsi(%ld:%d:%d:%d): Issued an ADAPTER " - "RESET.\n", ha->host_no, bus, target, lun); - printk(KERN_INFO - "scsi(%ld:%d:%d:%d): I/O processing will " - "continue automatically.\n", ha->host_no, bus, - target, lun); + "scsi(%ld): Issued ADAPTER RESET\n", + ha->host_no); + printk(KERN_INFO "scsi(%ld): I/O processing will " + "continue automatically\n", ha->host_no); } - ha->flags.reset_active = TRUE; + ha->flags.reset_active = 1; /* * We restarted all of the commands automatically, so the * mid-level code can expect completions momentitarily. @@ -1476,17 +1421,17 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) if (qla1280_abort_isp(ha) == 0) result = SUCCESS; - ha->flags.reset_active = FALSE; + ha->flags.reset_active = 0; } if (ha->done_q_first) qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); - qla1280_restart_queues(ha); - ha->flags.in_reset = FALSE; + ha->flags.in_reset = 0; /* If we didn't manage to issue the action, or we have no * command to wait for, exit here */ - if(result == FAIL || handle == NULL) + if (result == FAILED || handle == NULL || + handle == (unsigned char *)INVALID_HANDLE) goto leave; /* set up a timer just in case we're really jammed */ @@ -1497,14 +1442,14 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) add_timer(&timer); /* wait for the action to complete (or the timer to expire) */ - spin_unlock_irq(ha->host->host_lock); + spin_unlock_irq(HOST_LOCK); wait_for_completion(&wait); del_timer_sync(&timer); - spin_lock_irq(ha->host->host_lock); + spin_lock_irq(HOST_LOCK); sp->wait = NULL; - + /* the only action we might get a fail for is abort */ - if(action == ABORT_COMMAND) { + if (action == ABORT_COMMAND) { if(sp->flags & SRB_ABORTED) result = SUCCESS; else @@ -1519,7 +1464,7 @@ qla1280_error_action(Scsi_Cmnd * cmd, action_t action) } /************************************************************************** - * qla1200_abort + * qla1280_abort * Abort the specified SCSI command(s). **************************************************************************/ int @@ -1529,7 +1474,7 @@ qla1280_eh_abort(struct scsi_cmnd * cmd) } /************************************************************************** - * qla1200_device_reset + * qla1280_device_reset * Reset the specified SCSI device **************************************************************************/ int @@ -1539,7 +1484,7 @@ qla1280_eh_device_reset(struct scsi_cmnd *cmd) } /************************************************************************** - * qla1200_bus_reset + * qla1280_bus_reset * Reset the specified bus. **************************************************************************/ int @@ -1549,7 +1494,7 @@ qla1280_eh_bus_reset(struct scsi_cmnd *cmd) } /************************************************************************** - * qla1200_adapter_reset + * qla1280_adapter_reset * Reset the specified adapter (both channels) **************************************************************************/ int @@ -1563,10 +1508,17 @@ qla1280_eh_adapter_reset(struct scsi_cmnd *cmd) * Return the disk geometry for the given SCSI device. **************************************************************************/ int +#if LINUX_VERSION_CODE < 0x020545 +qla1280_biosparam(Disk * disk, kdev_t dev, int geom[]) +#else qla1280_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) + sector_t capacity, int geom[]) +#endif { int heads, sectors, cylinders; +#if LINUX_VERSION_CODE < 0x020545 + unsigned long capacity = disk->capacity; +#endif heads = 64; sectors = 32; @@ -1595,13 +1547,13 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { struct scsi_qla_host *ha; struct device_reg *reg; - int handled = 0; u16 data; + int handled = 0; ENTER_INTR ("qla1280_intr_handler"); ha = (struct scsi_qla_host *)dev_id; - spin_lock(ha->host->host_lock); + spin_lock(HOST_LOCK); ha->isr_count++; reg = ha->iobase; @@ -1613,16 +1565,11 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) if (data & RISC_INT) { qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last); handled = 1; - } else { - /* spurious interrupts can happen legally */ - dprintk(1, "scsi(%ld): Spurious interrupt - ignoring\n", - ha->host_no); } - if (ha->done_q_first) qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); - spin_unlock(ha->host->host_lock); + spin_unlock(HOST_LOCK); /* enable our interrupt. */ WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); @@ -1649,10 +1596,7 @@ qla1280_do_dpc(void *p) struct scsi_qla_host *ha = (struct scsi_qla_host *) p; unsigned long cpu_flags; - spin_lock_irqsave(ha->host->host_lock, cpu_flags); - - if (ha->flags.isp_abort_needed) - qla1280_abort_isp(ha); + spin_lock_irqsave(HOST_LOCK, cpu_flags); if (ha->flags.reset_marker) qla1280_rst_aen(ha); @@ -1660,9 +1604,58 @@ qla1280_do_dpc(void *p) if (ha->done_q_first) qla1280_done(ha, &ha->done_q_first, &ha->done_q_last); - spin_unlock_irqrestore(ha->host->host_lock, cpu_flags); + spin_unlock_irqrestore(HOST_LOCK, cpu_flags); +} + + +static int +qla12160_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) +{ + uint8_t mr; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + struct nvram *nv; + int is1x160, status; + + nv = &ha->nvram; + + if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) + is1x160 = 1; + else + is1x160 = 0; + + mr = BIT_3 | BIT_2 | BIT_1 | BIT_0; + + /* Set Target Parameters. */ + mb[0] = MBC_SET_TARGET_PARAMETERS; + mb[1] = (uint16_t) (bus ? target | BIT_7 : target); + mb[1] <<= 8; + + mb[2] = (nv->bus[bus].target[target].parameter.c << 8); + + if (is1x160) + mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; + else + mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; + mb[3] |= nv->bus[bus].target[target].sync_period; + + if (is1x160) { + mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; + mb[6] = nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8; + mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; + mr |= BIT_6; + } + + status = qla1280_mailbox_command(ha, mr, &mb[0]); + + if (status) + printk(KERN_WARNING "scsi(%ld:%i:%i): " + "qla1280_set_target_parameters() failed\n", + ha->host_no, bus, target); + return status; } + /************************************************************************** * qla1280_slave_configure * @@ -1675,29 +1668,95 @@ qla1280_do_dpc(void *p) * default queue depth (dependent on the number of hardware SCBs). **************************************************************************/ static int -qla1280_slave_configure(Scsi_Device * device) +qla1280_slave_configure(Scsi_Device *device) { - struct scsi_qla_host *p = (struct scsi_qla_host *)device->host->hostdata; + struct scsi_qla_host *ha; + int default_depth = 3; int bus = device->channel; int target = device->id; + int status = 0; + struct nvram *nv; +#if LINUX_VERSION_CODE < 0x020500 + unsigned long flags; +#endif + + ha = (struct scsi_qla_host *)device->host->hostdata; + nv = &ha->nvram; - if (qla1280_check_for_dead_scsi_bus(p, bus)) + if (qla1280_check_for_dead_scsi_bus(ha, bus)) return 1; + if (device->tagged_supported && - (p->bus_settings[bus].qtag_enables & (BIT_0 << target))) { + (ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) { scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - p->bus_settings[bus].hiwat); - /* device->queue_depth = 20; */ - printk(KERN_INFO "scsi(%li:%d:%d:%d): Enabled tagged queuing, " - "queue depth %d.\n", p->host_no, device->channel, - device->id, device->lun, device->queue_depth); + ha->bus_settings[bus].hiwat); } else { - scsi_adjust_queue_depth(device, 0 /* TCQ off */, 3); + scsi_adjust_queue_depth(device, 0, default_depth); } - qla12160_get_target_parameters(p, bus, target, device->lun); - return 0; + +#if LINUX_VERSION_CODE > 0x020500 + nv->bus[bus].target[target].parameter.f.enable_sync = device->sdtr; + nv->bus[bus].target[target].parameter.f.enable_wide = device->wdtr; + nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr; +#endif + + if (driver_setup.no_sync || + (driver_setup.sync_mask && + (~driver_setup.sync_mask & (1 << target)))) + nv->bus[bus].target[target].parameter.f.enable_sync = 0; + if (driver_setup.no_wide || + (driver_setup.wide_mask && + (~driver_setup.wide_mask & (1 << target)))) + nv->bus[bus].target[target].parameter.f.enable_wide = 0; + if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || + ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) { + if (driver_setup.no_ppr || + (driver_setup.ppr_mask && + (~driver_setup.ppr_mask & (1 << target)))) + nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; + } + +#if LINUX_VERSION_CODE < 0x020500 + spin_lock_irqsave(HOST_LOCK, flags); +#endif + if (nv->bus[bus].target[target].parameter.f.enable_sync) { + status = qla12160_set_target_parameters(ha, bus, target); + } + + qla12160_get_target_parameters(ha, device); +#if LINUX_VERSION_CODE < 0x020500 + spin_unlock_irqrestore(HOST_LOCK, flags); +#endif + return status; } +#if LINUX_VERSION_CODE < 0x020545 +/************************************************************************** + * qla1280_select_queue_depth + * + * Sets the queue depth for each SCSI device hanging off the input + * host adapter. We use a queue depth of 2 for devices that do not + * support tagged queueing. + **************************************************************************/ +static void +qla1280_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) +{ + Scsi_Device *device; + struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; + + ENTER("qla1280_select_queue_depth"); + for (device = scsi_devs; device != NULL; device = device->next) { + if (device->host == host) + qla1280_slave_configure(device); + } + + if (scsi_devs) + qla1280_check_for_dead_scsi_bus(ha, scsi_devs->channel); + + LEAVE("qla1280_select_queue_depth"); +} +#endif + /* * Driver Support Routines */ @@ -1712,11 +1771,10 @@ qla1280_slave_configure(Scsi_Device * device) * done_q_last = done queue last pointer. */ static void -qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first, - srb_t ** done_q_last) +qla1280_done(struct scsi_qla_host *ha, struct srb ** done_q_first, + struct srb ** done_q_last) { - srb_t *sp; - scsi_lu_t *q; + struct srb *sp; int bus, target, lun; Scsi_Cmnd *cmd; @@ -1734,24 +1792,9 @@ qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first, bus = SCSI_BUS_32(cmd); target = SCSI_TCN_32(cmd); lun = SCSI_LUN_32(cmd); - q = LU_Q(ha, bus, target, lun); - - /* Decrement outstanding commands on device. */ - if (q->q_outcnt) - q->q_outcnt--; - if (q->q_outcnt < ha->bus_settings[bus].hiwat) { - q->q_flag &= ~QLA1280_QBUSY; - } - - q->io_cnt++; - if (sp->dir & BIT_5) - q->r_cnt++; - else - q->w_cnt++; switch ((CMD_RESULT(cmd) >> 16)) { case DID_RESET: - q->q_flag &= ~QLA1280_QRESET; /* Issue marker command. */ qla1280_marker(ha, bus, target, 0, MK_SYNC_ID); break; @@ -1765,10 +1808,9 @@ qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first, break; } - /* 3.13 64 and 32 bit */ /* Release memory used for this I/O */ if (cmd->use_sg) { - dprintk(1, "S/G unmap_sg cmd=%p\n", cmd); + dprintk(3, "S/G unmap_sg cmd=%p\n", cmd); pci_unmap_sg(ha->pdev, cmd->request_buffer, cmd->use_sg, @@ -1777,21 +1819,24 @@ qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first, /*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n", cmd, sp->saved_dma_handle); */ - pci_unmap_single(ha->pdev, sp->saved_dma_handle, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + pci_unmap_page(ha->pdev, sp->saved_dma_handle, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); } /* Call the mid-level driver interrupt handler */ - CMD_HANDLE(sp->cmd) = NULL; + CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; ha->actthreads--; +#if LINUX_KERNEL_VERSION < 0x020500 + if (cmd->cmnd[0] == INQUIRY) + qla1280_get_target_options(cmd, ha); +#endif (*(cmd)->scsi_done)(cmd); if(sp->wait != NULL) complete(sp->wait); - qla1280_next(ha, q, bus); } LEAVE("qla1280_done"); } @@ -1800,7 +1845,7 @@ qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first, * Translates a ISP error to a Linux SCSI error */ static int -qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp) +qla1280_return_status(struct response * sts, Scsi_Cmnd * cp) { int host_status = DID_ERROR; #if DEBUG_QLA1280_INTR @@ -1901,7 +1946,8 @@ qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp) * done_q_last = done queue last pointer. */ static void -qla1280_done_q_put(srb_t * sp, srb_t ** done_q_first, srb_t ** done_q_last) +qla1280_done_q_put(struct srb * sp, struct srb ** done_q_first, + struct srb ** done_q_last) { ENTER("qla1280_put_done_q"); @@ -1917,160 +1963,6 @@ qla1280_done_q_put(srb_t * sp, srb_t ** done_q_first, srb_t ** done_q_last) LEAVE("qla1280_put_done_q"); } -/* - * qla1280_next - * Retrieve and process next job in the queue. - * - * Input: - * ha = adapter block pointer. - * q = SCSI LU pointer. - * bus = SCSI bus number. - * SCSI_LU_Qlock must be already obtained and no other locks. - * - * Output: - * Releases SCSI_LU_Qupon exit. - */ -static void -qla1280_next(struct scsi_qla_host *ha, scsi_lu_t * q, int bus) -{ - srb_t *sp; - int cnt, status; - - ENTER("qla1280_next"); - - while (((sp = q->q_first) != NULL) && /* we have a queue pending */ - /* device not busy/suspended */ - !(q->q_flag & (QLA1280_QBUSY | QLA1280_QSUSP)) && !ha->flags.abort_isp_active) { /* not resetting the adapter */ - /* Remove srb from SCSI LU queue. */ - qla1280_removeq(q, sp); - - dprintk(1, "starting request 0x%p<-(0x%p)\n", q, sp); - { - /* Set busy flag if reached high water mark. */ - q->q_outcnt++; - if (q->q_outcnt >= ha->bus_settings[bus].hiwat) - q->q_flag |= QLA1280_QBUSY; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) - if (ha->flags.enable_64bit_addressing) - status = qla1280_64bit_start_scsi(ha, sp); - else -#endif - status = qla1280_32bit_start_scsi(ha, sp); - - if (status) { /* if couldn't start the request */ - if (q->q_outcnt == 1) { - /* Wait for 30 sec for command to be accepted. */ - for (cnt = 6000000; cnt; cnt--) { -#if QLA_64BIT_PTR - if (ha->flags.enable_64bit_addressing) - status = - qla1280_64bit_start_scsi(ha, sp); - else -#endif - status = - qla1280_32bit_start_scsi(ha, sp); - - if (!status) - break; - - /* Go check for pending interrupts. */ - qla1280_poll(ha); - - udelay(5); /* 10 */ - } - if (!cnt) { - /* Set timeout status */ - CMD_RESULT(sp->cmd) = - DID_TIME_OUT << 16; - -#if WATCHDOGTIMER - /* Remove command from watchdog queue. */ - if (sp->flags & SRB_WATCHDOG) - qla1280_timeout_remove - (ha, sp); -#endif - CMD_HANDLE(sp->cmd) = NULL; - - /* Call the mid-level driver interrupt handler */ - (*(sp->cmd)->scsi_done)(sp->cmd); - - if (q->q_outcnt) - q->q_outcnt--; - } - } else { /* Place request back on top of device queue. */ - qla1280_putq_t(q, sp); - - if (q->q_outcnt) - q->q_outcnt--; - if (q->q_outcnt < - ha->bus_settings[bus].hiwat) - q->q_flag &= ~QLA1280_QBUSY; - break; - } - } - } - } - - LEAVE("qla1280_next"); -} - -/* - * qla1280_putq_t - * Add the standard SCB job to the top of standard SCB commands. - * - * Input: - * q = SCSI LU pointer. - * sp = srb pointer. - * SCSI_LU_Qlock must be already obtained. - */ -static void -qla1280_putq_t(scsi_lu_t * q, srb_t * sp) -{ - ENTER("qla1280_putq_t"); - - dprintk(1, "Adding to device q=0x%p<-(0x%p)sp\n", (void *) q, - (void *) sp); - - sp->s_next = NULL; - if (!q->q_first) { /* If queue empty */ - sp->s_prev = NULL; - q->q_first = sp; - q->q_last = sp; - } else { - sp->s_prev = q->q_last; - q->q_last->s_next = sp; - q->q_last = sp; - } - - LEAVE("qla1280_putq_t"); -} - -/* - * qla1280_removeq - * Function used to remove a command block from the - * LU queue. - * - * Input: - * q = SCSI LU pointer. - * sp = srb pointer. - * SCSI_LU_Qlock must be already obtained. - */ -static void -qla1280_removeq(scsi_lu_t * q, srb_t * sp) -{ - dprintk(1, "Removing from device_q (0x%p)->(0x%p)\n", q, sp); - - if (sp->s_prev) { - if ((sp->s_prev->s_next = sp->s_next) != NULL) - sp->s_next->s_prev = sp->s_prev; - else - q->q_last = sp->s_prev; - } else if (!(q->q_first = sp->s_next)) - q->q_last = NULL; - else - q->q_first->s_prev = NULL; -} /* * qla1280_mem_alloc @@ -2088,7 +1980,6 @@ qla1280_mem_alloc(struct scsi_qla_host *ha) ENTER("qla1280_mem_alloc"); - /* 3.13 */ /* get consistent memory allocated for request and response rings */ ha->request_ring = pci_alloc_consistent(ha->pdev, ((REQUEST_ENTRY_CNT + 1) * @@ -2099,7 +1990,7 @@ qla1280_mem_alloc(struct scsi_qla_host *ha) ha->request_dma = dma_handle; ha->response_ring = pci_alloc_consistent(ha->pdev, ((RESPONSE_ENTRY_CNT + 1) * - (sizeof(response_t))), + (sizeof(struct response))), &dma_handle); if (!ha->request_ring) goto error; @@ -2124,26 +2015,7 @@ qla1280_mem_alloc(struct scsi_qla_host *ha) static void qla1280_mem_free(struct scsi_qla_host *ha) { - scsi_lu_t *q; - int bus, target, lun; - ENTER("qlc1280_mem_free"); - if (ha) { - /* Free device queues. */ - for (bus = 0; bus < MAX_BUSES; bus++) { - q = LU_Q(ha, bus, ha->bus_settings[bus].id, 0); - for (target = 0; target < MAX_TARGETS; target++) - for (lun = 0; lun < MAX_LUNS; lun++) - if (LU_Q(ha, bus, target, lun) != NULL - && LU_Q(ha, bus, target, lun) != q) - kfree(LU_Q(ha, bus, target, lun)); - kfree(q); - } - for (bus = 0; bus < MAX_EQ; bus++) - ha->dev[bus] = NULL; - } - - /* 3.13 */ /* free consistent memory allocated for request and response rings */ if (ha->request_ring) pci_free_consistent(ha->pdev, @@ -2154,7 +2026,7 @@ qla1280_mem_free(struct scsi_qla_host *ha) if (ha->response_ring) pci_free_consistent(ha->pdev, ((RESPONSE_ENTRY_CNT + 1) * - (sizeof(response_t))), + (sizeof(struct response))), ha->response_ring, ha->response_dma); if (qla1280_buffer) { @@ -2187,10 +2059,8 @@ qla1280_enable_intrs(struct scsi_qla_host *ha) reg = ha->iobase; /* enable risc and host interrupts */ WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); + RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ ha->flags.ints_enabled = 1; -#if 0 - printk("Enabling ints\n"); -#endif } static inline void @@ -2201,10 +2071,8 @@ qla1280_disable_intrs(struct scsi_qla_host *ha) reg = ha->iobase; /* disable risc and host interrupts */ WRT_REG_WORD(®->ictrl, 0); + RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ ha->flags.ints_enabled = 0; -#if 0 - printk("Disabling ints\n"); -#endif } /* @@ -2227,13 +2095,29 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) ENTER("qla1280_initialize_adapter"); /* Clear adapter flags. */ - ha->flags.online = FALSE; - ha->flags.isp_abort_needed = FALSE; - ha->flags.disable_host_adapter = FALSE; - ha->flags.reset_active = FALSE; - ha->flags.abort_isp_active = FALSE; + ha->flags.online = 0; + ha->flags.disable_host_adapter = 0; + ha->flags.reset_active = 0; + ha->flags.abort_isp_active = 0; - ha->flags.ints_enabled = FALSE; + ha->flags.ints_enabled = 0; +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ia64_platform_is("sn2")) { + int count1, count2; + int c; + + count1 = 3; + count2 = 3; + printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " + "dual channel lockup workaround\n", ha->host_no); + if ((c = snia_pcibr_rrb_alloc(ha->pdev, &count1, &count2)) < 0) + printk(KERN_ERR "scsi(%li): Unable to allocate SN2 " + "virtual DMA channels\n", ha->host_no); + ha->flags.use_pci_vchannel = 1; + + driver_setup.no_nvram = 1; + } +#endif dprintk(1, "Configure PCI space for adapter...\n"); @@ -2243,79 +2127,65 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); + RD_REG_WORD(®->host_cmd); + + if (qla1280_read_nvram(ha)) { + dprintk(2, "qla1280_initialize_adapter: failed to read " + "NVRAM\n"); + } /* If firmware needs to be loaded */ - if (qla1280_verbose) - printk(KERN_INFO "scsi(%li): Determining if RISC is " - "loaded...\n", ha->host_no); if (qla1280_isp_firmware(ha)) { - if (qla1280_verbose) - printk(KERN_INFO "scsi(%ld): Verifying chip...\n", - ha->host_no); if (!(status = qla1280_chip_diag (ha))) { - if (qla1280_verbose) - printk(KERN_INFO "scsi(%ld): Setup chip...\n", - ha->host_no); status = qla1280_setup_chip(ha); } } else { - printk(KERN_ERR "initialize: isp_firmware() failed!\n"); + printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n", + ha->host_no); status = 1; } - if (!status) { - /* Setup adapter based on NVRAM parameters. */ - if (qla1280_verbose) - printk(KERN_INFO - "scsi(%ld): Configure NVRAM parameters...\n", - ha->host_no); - qla1280_nvram_config(ha); - - if (!ha->flags.disable_host_adapter - && !qla1280_init_rings(ha)) { - /* Issue SCSI reset. */ - /* dg 03/13 if we can't reset twice then bus is dead */ - for (bus = 0; bus < ha->ports; bus++) { - if (!ha->bus_settings[bus].disable_scsi_reset){ + if (status) { + printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n", + ha->host_no); + goto out; + } + + /* Setup adapter based on NVRAM parameters. */ + dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no); + qla1280_nvram_config(ha); + + if (!ha->flags.disable_host_adapter && !qla1280_init_rings(ha)) { + /* Issue SCSI reset. */ + /* dg 03/13 if we can't reset twice then bus is dead */ + for (bus = 0; bus < ha->ports; bus++) { + if (!ha->bus_settings[bus].disable_scsi_reset){ + if (qla1280_bus_reset(ha, bus)) { if (qla1280_bus_reset(ha, bus)) { - if (qla1280_bus_reset(ha, bus)) { - ha->bus_settings[bus].scsi_bus_dead = TRUE; - } + ha->bus_settings[bus].scsi_bus_dead = 1; } } } - do { - /* Issue marker command. */ - ha->flags.reset_marker = FALSE; - for (bus = 0; bus < ha->ports; bus++) { - ha->bus_settings[bus].reset_marker = FALSE; - qla1280_marker(ha, bus, 0, 0, - MK_SYNC_ALL); - } - } while (ha->flags.reset_marker); - - ha->flags.online = TRUE; + } - /* Enable host adapter target mode. */ - for (bus = 0; bus < ha->ports; bus++) { - if (!(status = qla1280_enable_tgt(ha, bus))) { + /* + * qla1280_bus_reset() will take care of issueing markers, + * no need to do that here as well! + */ #if 0 - int cnt; - for (cnt = 0; cnt < MAX_LUNS; cnt++) { - qla1280_enable_lun(ha, bus, - cnt); - qla1280_poll(ha); - } + /* Issue marker command. */ + ha->flags.reset_marker = 0; + for (bus = 0; bus < ha->ports; bus++) { + ha->bus_settings[bus].reset_marker = 0; + qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL); + } #endif - } else - break; - } - } else - status = 1; + + ha->flags.online = 1; } else - printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n", - ha->host_no); + status = 1; + out: if (status) dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n"); @@ -2323,39 +2193,6 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) return status; } -/* - * qla1280_enable_tgt - * Enable target mode. - * - * Input: - * ha = adapter block pointer. - * bus = SCSI bus number. - * - * Returns: - * 0 = success. - */ -static int -qla1280_enable_tgt(struct scsi_qla_host *ha, int bus) -{ - int status = 0; - /* uint16_t mb[MAILBOX_REGISTER_COUNT]; */ - - dprintk(3, "qla1280_enable_tgt: entered\n"); - - /* Enable target mode. */ -#if 0 - mb[0] = MBC_ENABLE_TARGET_MODE; - mb[1] = BIT_15; - mb[2] = (uint16_t) (bus << 15); - status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); -#endif - if (status) - dprintk(2, "qla1280_enable_tgt: **** FAILED ****\n"); - else - dprintk(3, "qla1280_enable_tgt: exiting normally\n"); - - return status; -} /* * ISP Firmware Test @@ -2371,54 +2208,32 @@ qla1280_enable_tgt(struct scsi_qla_host *ha, int bus) static int qla1280_isp_firmware(struct scsi_qla_host *ha) { - nvram_t *nv = (nvram_t *) ha->response_ring; - uint16_t *wptr; + struct nvram *nv = (struct nvram *) ha->response_ring; int status = 0; /* dg 2/27 always loads RISC */ - int cnt; - uint8_t chksum; uint16_t mb[MAILBOX_REGISTER_COUNT]; ENTER("qla1280_isp_firmware"); - /* Verify valid NVRAM checksum. */ - wptr = (uint16_t *) ha->response_ring; - dprintk(1, "qla1280_isp_firmware: Reading NVRAM\n"); - - chksum = 0; - for (cnt = 0; cnt < sizeof(nvram_t) / 2; cnt++) { - *wptr = qla1280_get_nvram_word (ha, cnt); - chksum += (uint8_t) * wptr; - chksum += (uint8_t) (*wptr >> 8); - wptr++; - } - dprintk(1, "qla1280_isp_firmware: Completed Reading NVRAM\n"); - - dprintk(3, "qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n", - nv->id0, nv->id1, nv->id2); + dprintk(1, "scsi(%li): Determining if RISC is loaded\n", ha->host_no); /* Bad NVRAM data, load RISC code. */ - if (chksum || nv->id0 != 'I' || nv->id1 != 'S' || - nv->id2 != 'P' || nv->id3 != ' ' || nv->version < 1) { - printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic " - "number or version in NVRAM.\n"); - ha->flags.disable_risc_code_load = FALSE; + if (!ha->nvram_valid) { + ha->flags.disable_risc_code_load = 0; } else ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code; if (ha->flags.disable_risc_code_load) { - dprintk(3, - "qla1280_isp_firmware: Telling RISC to verify checksum " - "of loaded BIOS code.\n"); + dprintk(3, "qla1280_isp_firmware: Telling RISC to verify " + "checksum of loaded BIOS code.\n"); /* Verify checksum of loaded RISC code. */ mb[0] = MBC_VERIFY_CHECKSUM; /* mb[1] = ql12_risc_code_addr01; */ mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; - if (! - (status = - qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) { + if (!(status = + qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) { /* Start firmware execution. */ dprintk(3, "qla1280_isp_firmware: Startng F/W " "execution.\n"); @@ -2455,8 +2270,8 @@ static int qla1280_pci_config(struct scsi_qla_host *ha) { #if MEMORY_MAPPED_IO - uint32_t page_offset, base; - uint32_t mmapbase; + unsigned long base; + int size; #endif uint16_t buf_wd; int status = 1; @@ -2470,16 +2285,14 @@ qla1280_pci_config(struct scsi_qla_host *ha) */ pci_read_config_word (ha->pdev, PCI_COMMAND, &buf_wd); #if MEMORY_MAPPED_IO - dprintk(1, "qla1280: MEMORY MAPPED IO is enabled.\n"); - buf_wd |= PCI_COMMAND_MEMORY + PCI_COMMAND_IO; -#else - buf_wd |= PCI_COMMAND_IO; + buf_wd |= PCI_COMMAND_MEMORY; #endif + buf_wd |= PCI_COMMAND_IO; pci_write_config_word (ha->pdev, PCI_COMMAND, buf_wd); /* * Reset expansion ROM address decode enable. */ - pci_read_config_word (ha->pdev, PCI_ROM_ADDRESS, &buf_wd); + pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &buf_wd); buf_wd &= ~PCI_ROM_ADDRESS_ENABLE; pci_write_config_word (ha->pdev, PCI_ROM_ADDRESS, buf_wd); @@ -2489,23 +2302,16 @@ qla1280_pci_config(struct scsi_qla_host *ha) #if MEMORY_MAPPED_IO /* - * Get memory mapped I/O address. - */ - pci_read_config_word (ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase); - mmapbase &= PCI_BASE_ADDRESS_MEM_MASK; - - /* * Find proper memory chunk for memory map I/O reg. */ - base = mmapbase & PAGE_MASK; - page_offset = mmapbase - base; + base = pci_resource_start(ha->pdev, 1); + size = pci_resource_len(ha->pdev, 1); /* * Get virtual address for I/O registers. */ - ha->mmpbase = ioremap(base, page_offset + 256); + ha->mmpbase = ioremap(base, size); if (ha->mmpbase) { - ha->mmpbase += page_offset; - /* ha->iobase = ha->mmpbase; */ + ha->iobase = (struct device_reg *)ha->mmpbase; status = 0; } #else /* MEMORY_MAPPED_IO */ @@ -2537,50 +2343,69 @@ qla1280_chip_diag(struct scsi_qla_host *ha) dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", ®->id_l); + dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no); + /* Soft reset chip and wait for it to finish. */ WRT_REG_WORD(®->ictrl, ISP_RESET); + /* + * We can't do a traditional PCI write flush here by reading + * back the register. The card will not respond once the reset + * is in action and we end up with a machine check exception + * instead. Nothing to do but wait and hope for the best. + * A portable pci_write_flush(pdev) call would be very useful here. + */ + udelay(20); data = qla1280_debounce_register(®->ictrl); /* - * This is *AWESOME* + * Yet another QLogic gem ;-( */ - for (cnt = 6000000; cnt && data & ISP_RESET; cnt--) { + for (cnt = 1000000; cnt && data & ISP_RESET; cnt--) { udelay(5); data = RD_REG_WORD(®->ictrl); } + if (cnt) { - /* Reset register not cleared by chip reset. */ - dprintk(3, - "qla1280_chip_diag: reset register cleared by chip reset\n"); + /* Reset register cleared by chip reset. */ + dprintk(3, "qla1280_chip_diag: reset register cleared by " + "chip reset\n"); WRT_REG_WORD(®->cfg_1, 0); /* Reset RISC and disable BIOS which allows RISC to execute out of RAM. */ +#if 0 WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); + RD_REG_WORD(®->id_l); /* Flush PCI write */ WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); + RD_REG_WORD(®->id_l); /* Flush PCI write */ WRT_REG_WORD(®->host_cmd, HC_DISABLE_BIOS); +#else + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC | + HC_RELEASE_RISC | HC_DISABLE_BIOS); +#endif + RD_REG_WORD(®->id_l); /* Flush PCI write */ data = qla1280_debounce_register(®->mailbox0); /* * I *LOVE* this code! */ - for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--) { + for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) { udelay(5); data = RD_REG_WORD(®->mailbox0); } if (cnt) { /* Check product ID of chip */ - dprintk(3, - "qla1280_chip_diag: Checking product ID of chip\n"); + dprintk(3, "qla1280_chip_diag: Checking product " + "ID of chip\n"); if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || RD_REG_WORD(®->mailbox3) != PROD_ID_3 || RD_REG_WORD(®->mailbox4) != PROD_ID_4) { - printk(KERN_INFO - "qla1280: Wrong product ID = 0x%x,0x%x,0x%x," - "0x%x\n", RD_REG_WORD(®->mailbox1), + printk(KERN_INFO "qla1280: Wrong product ID = " + "0x%x,0x%x,0x%x,0x%x\n", + RD_REG_WORD(®->mailbox1), RD_REG_WORD(®->mailbox2), RD_REG_WORD(®->mailbox3), RD_REG_WORD(®->mailbox4)); @@ -2590,8 +2415,9 @@ qla1280_chip_diag(struct scsi_qla_host *ha) * Enable ints early!!! */ qla1280_enable_intrs(ha); - dprintk(1, - "qla1280_chip_diag: Checking mailboxes of chip\n"); + + dprintk(1, "qla1280_chip_diag: Checking " + "mailboxes of chip\n"); /* Wrap Incoming Mailboxes Test. */ mb[0] = MBC_MAILBOX_REGISTER_TEST; mb[1] = 0xAAAA; @@ -2602,14 +2428,7 @@ qla1280_chip_diag(struct scsi_qla_host *ha) mb[6] = 0x5A5A; mb[7] = 0x2525; if (!(status = qla1280_mailbox_command(ha, - BIT_7 | - BIT_6 | - BIT_5 | - BIT_4 | - BIT_3 | - BIT_2 | - BIT_1 | - BIT_0, + 0xff, &mb [0]))) { if (mb[1] != 0xAAAA || @@ -2618,11 +2437,11 @@ qla1280_chip_diag(struct scsi_qla_host *ha) mb[4] != 0x55AA || mb[5] != 0xA5A5 || mb[6] != 0x5A5A || - mb[7] != 0x2525) + mb[7] != 0x2525) { status = 1; - if (status == 1) - printk(KERN_INFO - "qla1280: Failed mailbox check\n"); + printk(KERN_INFO "qla1280: " + "Failed mbox check\n"); + } } } } else @@ -2648,7 +2467,7 @@ qla1280_chip_diag(struct scsi_qla_host *ha) * Returns: * 0 = success. */ -#define DUMP_IT_BACK 1 /* for debug of RISC loading */ +#define DUMP_IT_BACK 0 /* for debug of RISC loading */ static int qla1280_setup_chip(struct scsi_qla_host *ha) { @@ -2658,9 +2477,8 @@ qla1280_setup_chip(struct scsi_qla_host *ha) int risc_code_size; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t cnt; - int num; + int num, i; #if DUMP_IT_BACK - int i; uint8_t *sp; uint8_t *tbuf; dma_addr_t p_tbuf; @@ -2668,7 +2486,8 @@ qla1280_setup_chip(struct scsi_qla_host *ha) ENTER("qla1280_setup_chip"); - /* 3.13 */ + dprintk(1, "scsi(%ld): Setup chip\n", ha->host_no); + #if DUMP_IT_BACK /* get consistent memory allocated for setup_chip */ tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf); @@ -2691,7 +2510,7 @@ qla1280_setup_chip(struct scsi_qla_host *ha) if (cnt > risc_code_size) cnt = risc_code_size; - dprintk(1, "qla1280_setup_chip: loading risc @ =(0x%p)," + dprintk(2, "qla1280_setup_chip: loading risc @ =(0x%p)," "%d,%d(0x%x)\n", risc_code_address, cnt, num, risc_address); for(i = 0; i < cnt; i++) @@ -2703,18 +2522,18 @@ qla1280_setup_chip(struct scsi_qla_host *ha) mb[0] = MBC_LOAD_RAM; mb[1] = risc_address; mb[4] = cnt; - mb[3] = qla1280_addr0_15(ha->request_dma); - mb[2] = qla1280_addr16_31(ha->request_dma); - mb[7] = qla1280_addr32_47(ha->request_dma); - mb[6] = qla1280_addr48_63(ha->request_dma); - dprintk(1, "qla1280_setup_chip: op=%d 0x%p = 0x%4x,0x%4x," - "0x%4x,0x%4x\n", - mb[0], (void *)ha->request_dma, mb[6], mb[7], mb[2], mb[3]); + mb[3] = ha->request_dma & 0xffff; + mb[2] = (ha->request_dma >> 16) & 0xffff; + mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff; + mb[6] = pci_dma_hi32(ha->request_dma) >> 16; + dprintk(2, "qla1280_setup_chip: op=%d 0x%p = 0x%4x,0x%4x," + "0x%4x,0x%4x\n", mb[0], (void *)(long)ha->request_dma, + mb[6], mb[7], mb[2], mb[3]); if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]))) { - printk(KERN_ERR - "Failed to load partial segment of f/w\n"); + printk(KERN_ERR "scsi(%li): Failed to load partial " + "segment of f\n", ha->host_no); break; } @@ -2722,10 +2541,10 @@ qla1280_setup_chip(struct scsi_qla_host *ha) mb[0] = MBC_DUMP_RAM; mb[1] = risc_address; mb[4] = cnt; - mb[3] = qla1280_addr0_15(p_tbuf); - mb[2] = qla1280_addr16_31(p_tbuf); - mb[7] = qla1280_addr32_47(p_tbuf); - mb[6] = qla1280_addr48_63(p_tbuf); + mb[3] = p_tbuf & 0xffff; + mb[2] = (p_tbuf >> 16) & 0xffff; + mb[7] = pci_dma_hi32(p_tbuf) & 0xffff; + mb[6] = pci_dma_hi32(p_tbuf) >> 16; if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 | @@ -2737,7 +2556,7 @@ qla1280_setup_chip(struct scsi_qla_host *ha) } sp = (uint8_t *)ha->request_ring; for (i = 0; i < (cnt << 1); i++) { - if (tbuf[i] != sp[i] &&warn++ < 10) { + if (tbuf[i] != sp[i] && warn++ < 10) { printk(KERN_ERR "qla1280_setup_chip: FW " "compare error @ byte(0x%x) loop#=%x\n", i, num); @@ -2770,11 +2589,10 @@ qla1280_setup_chip(struct scsi_qla_host *ha) mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); } else - printk(KERN_ERR - "qla1280_setup_chip: Failed checksum.\n"); + printk(KERN_ERR "scsi(%li): qla1280_setup_chip: " + "Failed checksum\n", ha->host_no); } - /* 3.13 */ #if DUMP_IT_BACK /* free consistent memory allocated for setup_chip */ pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); @@ -2805,13 +2623,12 @@ qla1280_init_rings(struct scsi_qla_host *ha) { uint16_t mb[MAILBOX_REGISTER_COUNT]; int status = 0; - int cnt; ENTER("qla1280_init_rings"); /* Clear outstanding commands array. */ - for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) - ha->outstanding_cmds[cnt] = 0; + memset(ha->outstanding_cmds, 0, + sizeof(struct srb *) * MAX_OUTSTANDING_COMMANDS); /* Initialize request queue. */ ha->request_ring_ptr = ha->request_ring; @@ -2868,61 +2685,51 @@ static int qla1280_nvram_config(struct scsi_qla_host *ha) { struct device_reg *reg = ha->iobase; - nvram_t *nv = (nvram_t *)ha->response_ring; - int status = 0; - int cnt; + struct nvram *nv; + int is1x160, status = 0; int bus, target, lun; - uint16_t *wptr; uint16_t mb[MAILBOX_REGISTER_COUNT]; - uint8_t chksum; - int nvsize; + uint16_t mask; -#if DEBUG_PRINT_NVRAM - int saved_print_status = ql_debug_print; -#endif ENTER("qla1280_nvram_config"); - /* Verify valid NVRAM checksum. */ -#if USE_NVRAM_DEFAULTS - chksum = 1; -#else - wptr = (uint16_t *) ha->response_ring; - chksum = 0; if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) - nvsize = sizeof(nvram160_t) / 2; + is1x160 = 1; else - nvsize = sizeof(nvram_t) / 2; - for (cnt = 0; cnt < nvsize; cnt++) { - *wptr = qla1280_get_nvram_word(ha, cnt); - chksum += (uint8_t) * wptr; - chksum += (uint8_t) (*wptr >> 8); - wptr++; - } -#endif + is1x160 = 0; - /* Bad NVRAM data, set defaults parameters. */ - if (chksum || nv->id0 != 'I' || nv->id1 != 'S' || - nv->id2 != 'P' || nv->id3 != ' ' || nv->version < 1) { -#if USE_NVRAM_DEFAULTS - dprintk(1, "Using defaults for NVRAM\n"); -#else + nv = &ha->nvram; + if (!ha->nvram_valid) { dprintk(1, "Using defaults for NVRAM: \n"); - dprintk(1, "checksum=0x%x, Id=%c, version=0x%x\n", - chksum, nv->id[0], nv->version); - memset(ha->response_ring, 0, sizeof(nvram_t)); -#endif + memset(nv, 0, sizeof(struct nvram)); /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ - nv->firmware_feature.w = BIT_0; + nv->firmware_feature.f.enable_fast_posting = 1; + nv->firmware_feature.f.disable_synchronous_backoff = 1; + nv->termination.f.scsi_bus_0_control = 3; nv->termination.f.scsi_bus_1_control = 3; nv->termination.f.auto_term_support = 1; + /* + * Set default FIFO magic - What appropriate values + * would be here is unknown. This is what I have found + * testing with 12160s. + * Now, I would love the magic decoder ring for this one, + * the header file provided by QLogic seems to be bogus + * or incomplete at best. + */ + nv->isp_config.c = 0x44; + + if (is1x160) + nv->isp_parameter = 0x01; + for (bus = 0; bus < MAX_BUSES; bus++) { nv->bus[bus].config_1.initiator_id = 7; nv->bus[bus].bus_reset_delay = 5; - nv->bus[bus].config_2.async_data_setup_time = 9; + /* 8 = 5.0 clocks */ + nv->bus[bus].config_2.async_data_setup_time = 8; nv->bus[bus].config_2.req_ack_active_negation = 1; nv->bus[bus].config_2.data_line_active_negation = 1; nv->bus[bus].selection_timeout = 250; @@ -2930,21 +2737,46 @@ qla1280_nvram_config(struct scsi_qla_host *ha) for (target = 0; target < MAX_TARGETS; target++) { nv->bus[bus].target[target].parameter.f. - auto_request_sense = 1; + renegotiate_on_error = 1; nv->bus[bus].target[target].parameter.f. - disconnect_allowed = 1; + auto_request_sense = 1; nv->bus[bus].target[target].parameter.f. tag_queuing = 1; - nv->bus[bus].target[target].flags. - device_enable = 1; + nv->bus[bus].target[target].parameter.f. + enable_sync = 1; +#if 1 /* Some SCSI Processors do not seem to like this */ + nv->bus[bus].target[target].parameter.f. + enable_wide = 1; +#endif + nv->bus[bus].target[target].parameter.f. + parity_checking = 1; + nv->bus[bus].target[target].parameter.f. + disconnect_allowed = 1; + nv->bus[bus].target[target].execution_throttle= + nv->bus[bus].max_queue_depth - 1; + if (is1x160) { + nv->bus[bus].target[target].flags. + flags1x160.device_enable = 1; + nv->bus[bus].target[target].flags. + flags1x160.sync_offset = 0x0e; + nv->bus[bus].target[target]. + sync_period = 9; + nv->bus[bus].target[target]. + ppr_1x160.flags.enable_ppr = 1; + nv->bus[bus].target[target].ppr_1x160. + flags.ppr_options = 2; + nv->bus[bus].target[target].ppr_1x160. + flags.ppr_bus_width = 1; + } else { + nv->bus[bus].target[target].flags. + flags1x80.device_enable = 1; + nv->bus[bus].target[target].flags. + flags1x80.sync_offset = 0x8; + nv->bus[bus].target[target]. + sync_period = 10; + } } } - -#if USE_NVRAM_DEFAULTS - status = 0; -#else - status = 1; -#endif } else { /* Always force AUTO sense for LINUX SCSI */ for (bus = 0; bus < MAX_BUSES; bus++) @@ -2953,9 +2785,6 @@ qla1280_nvram_config(struct scsi_qla_host *ha) auto_request_sense = 1; } } -#if DEBUG_PRINT_NVRAM - ql_debug_print = 1; -#endif dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n", nv->bus[0].config_1.initiator_id); dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n", @@ -3016,33 +2845,50 @@ qla1280_nvram_config(struct scsi_qla_host *ha) ha->flags.enable_64bit_addressing = 0; #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) if (ha->flags.enable_64bit_addressing) { - printk(KERN_INFO "scsi(%li): 64 Bit PCI Addressing Enabled\n", - ha->host_no); + dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n", + ha->host_no); pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL); } -#endif /* Set ISP hardware DMA burst */ mb[0] = nv->isp_config.c; + /* Enable DMA arbitration on dual channel controllers */ + if (ha->ports > 1) + mb[0] |= BIT_13; WRT_REG_WORD(®->cfg_1, mb[0]); +#if 1 /* Is this safe? */ /* Set SCSI termination. */ WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0)); mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0); WRT_REG_WORD(®->gpio_data, mb[0]); +#endif /* ISP parameter word. */ mb[0] = MBC_SET_SYSTEM_PARAMETER; mb[1] = nv->isp_parameter; status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); +#if 0 + /* clock rate - for qla1240 and older, only */ + mb[0] = MBC_SET_CLOCK_RATE; + mb[1] = 0x50; + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); +#endif /* Firmware feature word. */ mb[0] = MBC_SET_FIRMWARE_FEATURES; - mb[1] = nv->firmware_feature.w & (BIT_1 | BIT_0); - status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + mask = BIT_5 | BIT_1 | BIT_0; + mb[1] = le16_to_cpu(nv->firmware_feature.w) & (mask); +#if defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_SGI_SN2) + if (ia64_platform_is("sn2")) { + printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " + "workaround\n", ha->host_no); + mb[1] |= BIT_9; + } +#endif + status |= qla1280_mailbox_command(ha, mask, &mb[0]); /* Retry count and delay. */ mb[0] = MBC_SET_RETRY_COUNT; @@ -3050,9 +2896,8 @@ qla1280_nvram_config(struct scsi_qla_host *ha) mb[2] = nv->bus[0].retry_delay; mb[6] = nv->bus[1].retry_count; mb[7] = nv->bus[1].retry_delay; - status |= - qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_2 | BIT_1 | BIT_0, - &mb[0]); + status |= qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_2 | + BIT_1 | BIT_0, &mb[0]); /* ASYNC data setup time. */ mb[0] = MBC_SET_ASYNC_DATA_SETUP; @@ -3074,6 +2919,16 @@ qla1280_nvram_config(struct scsi_qla_host *ha) mb[2] |= BIT_4; status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + mb[0] = MBC_SET_DATA_OVERRUN_RECOVERY; + mb[1] = 2; /* Reset SCSI bus and return all outstanding IO */ + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + + /* thingy */ + mb[0] = MBC_SET_PCI_CONTROL; + mb[1] = 2; /* Data DMA Channel Burst Enable */ + mb[2] = 2; /* Command DMA Channel Burst Enable */ + status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + /* Selection timeout. */ mb[0] = MBC_SET_SELECTION_TIMEOUT; mb[1] = nv->bus[0].selection_timeout; @@ -3101,36 +2956,52 @@ qla1280_nvram_config(struct scsi_qla_host *ha) /* Set target parameters. */ for (target = 0; target < MAX_TARGETS; target++) { - uint8_t mr = BIT_3 | BIT_2 | BIT_1 | BIT_0; + uint8_t mr = BIT_2 | BIT_1 | BIT_0; /* Set Target Parameters. */ mb[0] = MBC_SET_TARGET_PARAMETERS; mb[1] = (uint16_t) (bus ? target | BIT_7 : target); mb[1] <<= 8; + /* + * Do not enable wide, sync, and ppr for the initial + * INQUIRY run. We enable this later if we determine + * the target actually supports it. + */ + nv->bus[bus].target[target].parameter.f. + auto_request_sense = 1; + nv->bus[bus].target[target].parameter.f. + stop_queue_on_check = 0; + + if (is1x160) + nv->bus[bus].target[target].ppr_1x160. + flags.enable_ppr = 0; + /* + * No sync, wide, etc. while probing + */ + mb[2] = (nv->bus[bus].target[target].parameter.c << 8)& + ~(TP_SYNC /*| TP_WIDE | TP_PPR*/); - mb[2] = nv->bus[bus].target[target].parameter.c << 8; - mb[2] |= TP_AUTO_REQUEST_SENSE; - mb[2] &= ~TP_STOP_QUEUE; - - mb[3] = - nv->bus[bus].target[target].flags.sync_offset << 8; + if (is1x160) + mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; + else + mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; mb[3] |= nv->bus[bus].target[target].sync_period; + mr |= BIT_3; + + /* + * We don't want to enable ppr etc. before we have + * determined that the target actually supports it + */ +#if 0 + if (is1x160) { + mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; - if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) { - nvram160_t *nv2 = (nvram160_t *) nv; - mb[2] |= - nv2->bus[bus].target[target].flags2. - enable_ppr << 5; - - mb[6] = - nv2->bus[bus].target[target].flags2. - ppr_options << 8; - mb[6] |= - nv2->bus[bus].target[target].flags2. - ppr_bus_width; + mb[6] = nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8; + mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; mr |= BIT_6; } +#endif + status = qla1280_mailbox_command(ha, mr, &mb[0]); /* Save Tag queuing enable flag. */ @@ -3139,12 +3010,18 @@ qla1280_nvram_config(struct scsi_qla_host *ha) ha->bus_settings[bus].qtag_enables |= mb[0]; /* Save Device enable flag. */ - if (nv->bus[bus].target[target].flags.device_enable) - ha->bus_settings[bus].device_enables |= mb[0]; - - /* Save LUN disable flag. */ - if (nv->bus[bus].target[target].flags.lun_disable) + if (is1x160) { + if (nv->bus[bus].target[target].flags.flags1x160.device_enable) + ha->bus_settings[bus].device_enables |= mb[0]; + ha->bus_settings[bus].lun_disables |= 0; + } else { + if (nv->bus[bus].target[target].flags.flags1x80.device_enable) + ha->bus_settings[bus].device_enables |= mb[0]; + /* Save LUN disable flag. */ + if (nv->bus[bus].target[target].flags.flags1x80.lun_disable) ha->bus_settings[bus].lun_disables |= mb[0]; + } + /* Set Device Queue Parameters. */ for (lun = 0; lun < MAX_LUNS; lun++) { @@ -3153,19 +3030,12 @@ qla1280_nvram_config(struct scsi_qla_host *ha) mb[1] = mb[1] << 8 | lun; mb[2] = nv->bus[bus].max_queue_depth; mb[3] = nv->bus[bus].target[target].execution_throttle; - status |= - qla1280_mailbox_command(ha, - BIT_3 | BIT_2 | - BIT_1 | BIT_0, - &mb[0]); + status |= qla1280_mailbox_command(ha, 0x0f, + &mb[0]); } } } -#if DEBUG_PRINT_NVRAM - ql_debug_print = saved_print_status; -#endif - if (status) dprintk(2, "qla1280_nvram_config: **** FAILED ****\n"); @@ -3191,24 +3061,13 @@ qla1280_get_nvram_word(struct scsi_qla_host *ha, uint32_t address) uint32_t nv_cmd; uint16_t data; -#ifdef QL_DEBUG_ROUTINES - int saved_print_status = ql_debug_print; -#endif - nv_cmd = address << 16; nv_cmd |= NV_READ_OP; -#ifdef QL_DEBUG_ROUTINES - ql_debug_print = FALSE; -#endif - data = qla1280_nvram_request(ha, nv_cmd); -#ifdef QL_DEBUG_ROUTINES - ql_debug_print = saved_print_status; -#endif + data = le16_to_cpu(qla1280_nvram_request(ha, nv_cmd)); - dprintk(4, - "qla1280_get_nvram_word: exiting normally NVRAM data = 0x%x", - data); + dprintk(8, "qla1280_get_nvram_word: exiting normally NVRAM data = " + "0x%x", data); return data; } @@ -3250,18 +3109,21 @@ qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd) for (cnt = 0; cnt < 16; cnt++) { WRT_REG_WORD(®->nvram, (NV_SELECT | NV_CLOCK)); + RD_REG_WORD(®->id_l); /* Flush PCI write */ NVRAM_DELAY(); data <<= 1; reg_data = RD_REG_WORD(®->nvram); if (reg_data & NV_DATA_IN) data |= BIT_0; WRT_REG_WORD(®->nvram, NV_SELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ NVRAM_DELAY(); } /* Deselect chip. */ WRT_REG_WORD(®->nvram, NV_DESELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ NVRAM_DELAY(); return data; @@ -3273,10 +3135,13 @@ qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data) struct device_reg *reg = ha->iobase; WRT_REG_WORD(®->nvram, data | NV_SELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ NVRAM_DELAY(); WRT_REG_WORD(®->nvram, data | NV_SELECT | NV_CLOCK); + RD_REG_WORD(®->id_l); /* Flush PCI write */ NVRAM_DELAY(); WRT_REG_WORD(®->nvram, data | NV_SELECT); + RD_REG_WORD(®->id_l); /* Flush PCI write */ NVRAM_DELAY(); } @@ -3296,29 +3161,32 @@ qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data) * 0 = success */ static int -qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t * mb) +qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) { struct device_reg *reg = ha->iobase; #if 0 - srb_t *done_q_first = 0; - srb_t *done_q_last = 0; + struct srb *done_q_first = 0; + struct srb *done_q_last = 0; #endif int status = 0; int cnt; uint16_t *optr, *iptr; uint16_t data; + DECLARE_COMPLETION(wait); + struct timer_list timer; ENTER("qla1280_mailbox_command"); - ha->flags.mbox_busy = TRUE; + ha->flags.mbox_busy = 1; + + if (ha->mailbox_wait) { + printk(KERN_ERR "Warning mailbox wait already in use!\n"); + } + ha->mailbox_wait = &wait; - if (!ha->flags.ints_enabled) - printk(KERN_DEBUG - "Running qla1280_mailbox_command() with interrupts " - "disabled!\n"); /* - * We really should start out by verifying that the mailbox is available - * before starting sending the command data + * We really should start out by verifying that the mailbox is + * available before starting sending the command data */ /* Load mailbox registers. */ optr = (uint16_t *) ®->mailbox0; @@ -3334,41 +3202,44 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t * mb) } /* Issue set host interrupt command. */ - ha->flags.mbox_int = FALSE; - ha->flags.mbox_busy = FALSE; + ha->flags.mbox_busy = 0; + + /* set up a timer just in case we're really jammed */ + init_timer(&timer); + timer.expires = jiffies + 20*HZ; + timer.data = (unsigned long)ha; + timer.function = qla1280_mailbox_timeout; + add_timer(&timer); + +#if LINUX_VERSION_CODE < 0x020500 + spin_unlock_irq(HOST_LOCK); +#endif WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT); data = qla1280_debounce_register(®->istatus); - /* - * This is insane - instead of looping to wait for the interrupt - * to appear and run the handler (this is insane!!), use a waitqueue - * and go to sleep. - * - * We are never called here from interrupt context anyway! /Jes - */ - /* Wait for 30 seconds for command to finish. */ - for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--) { - /* Check for pending interrupts. */ -#if 0 - if (data & RISC_INT) { - qla1280_isr(ha, &done_q_first, &done_q_last); - } else + wait_for_completion(&wait); + del_timer_sync(&timer); + +#if LINUX_VERSION_CODE < 0x020500 + spin_lock_irq(HOST_LOCK); #endif - udelay(1); - data = RD_REG_WORD(®->istatus); - } + ha->mailbox_wait = NULL; /* Check for mailbox command timeout. */ - if (!cnt) { - printk(KERN_WARNING - "qla1280_mailbox_command: **** Command Timeout, " - "mailbox0 = 0x%x****\n", mb[0]); - - ha->flags.isp_abort_needed = TRUE; - status = 1; - } else if (ha->mailbox_out[0] != MBS_CMD_CMP) + if (ha->mailbox_out[0] != MBS_CMD_CMP) { + printk(KERN_WARNING "qla1280_mailbox_command: Command failed, " + "mailbox0 = 0x%04x, mailbox_out0 = 0x%04x, istatus = " + "0x%04x\n", + mb[0], ha->mailbox_out[0], RD_REG_WORD(®->istatus)); + printk(KERN_WARNING "m0 %04x, m1 %04x, m2 %04x, m3 %04x\n", + RD_REG_WORD(®->mailbox0), RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), RD_REG_WORD(®->mailbox3)); + printk(KERN_WARNING "m4 %04x, m5 %04x, m6 %04x, m7 %04x\n", + RD_REG_WORD(®->mailbox4), RD_REG_WORD(®->mailbox5), + RD_REG_WORD(®->mailbox6), RD_REG_WORD(®->mailbox7)); status = 1; + } /* Load return mailbox registers. */ optr = mb; @@ -3381,9 +3252,6 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t * mb) qla1280_isr(ha, &done_q_first, &done_q_last); #endif - if (ha->flags.isp_abort_needed) - qla1280_abort_isp(ha); - if (ha->flags.reset_marker) qla1280_rst_aen(ha); @@ -3393,9 +3261,8 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t * mb) #endif if (status) - dprintk(2, - "qla1280_mailbox_command: **** FAILED, mailbox0 = 0x%x " - "****n", mb[0]); + dprintk(2, "qla1280_mailbox_command: **** FAILED, mailbox0 = " + "0x%x ****\n", mb[0]); LEAVE("qla1280_mailbox_command"); return status; @@ -3413,8 +3280,8 @@ qla1280_poll(struct scsi_qla_host *ha) { struct device_reg *reg = ha->iobase; uint16_t data; - srb_t *done_q_first = 0; - srb_t *done_q_last = 0; + struct srb *done_q_first = 0; + struct srb *done_q_last = 0; /* ENTER("qla1280_poll"); */ @@ -3424,8 +3291,6 @@ qla1280_poll(struct scsi_qla_host *ha) qla1280_isr(ha, &done_q_first, &done_q_last); if (!ha->flags.mbox_busy) { - if (ha->flags.isp_abort_needed) - qla1280_abort_isp(ha); if (ha->flags.reset_marker) qla1280_rst_aen(ha); } @@ -3451,38 +3316,42 @@ static int qla1280_bus_reset(struct scsi_qla_host *ha, int bus) { uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t reset_delay; int status; dprintk(3, "qla1280_bus_reset: entered\n"); if (qla1280_verbose) - printk(KERN_INFO "scsi(%li): Resetting SCSI BUS (%i)\n", + printk(KERN_INFO "scsi(%li:%i): Resetting SCSI BUS\n", ha->host_no, bus); + reset_delay = ha->bus_settings[bus].bus_reset_delay; mb[0] = MBC_BUS_RESET; - mb[1] = ha->bus_settings[bus].bus_reset_delay; + mb[1] = reset_delay; mb[2] = (uint16_t) bus; status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); if (status) { - if (ha->bus_settings[bus].failed_reset_count > 2) /* dg - 03/13/99 */ - ha->bus_settings[bus].scsi_bus_dead = TRUE; + if (ha->bus_settings[bus].failed_reset_count > 2) + ha->bus_settings[bus].scsi_bus_dead = 1; ha->bus_settings[bus].failed_reset_count++; } else { - /* - * Eeeeep! This is evil! /Jes - */ -#if 0 - mdelay(4000); -#else - schedule_timeout(4 * HZ); -#endif - ha->bus_settings[bus].scsi_bus_dead = FALSE; /* dg - 03/13/99 */ + spin_unlock_irq(HOST_LOCK); + schedule_timeout(reset_delay * HZ); + spin_lock_irq(HOST_LOCK); + + ha->bus_settings[bus].scsi_bus_dead = 0; ha->bus_settings[bus].failed_reset_count = 0; + ha->bus_settings[bus].reset_marker = 0; /* Issue marker command. */ qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL); } + /* + * We should probably call qla1280_set_target_parameters() + * here as well for all devices on the bus. + */ + if (status) dprintk(2, "qla1280_bus_reset: **** FAILED ****\n"); else @@ -3573,35 +3442,31 @@ qla1280_abort_device(struct scsi_qla_host *ha, int bus, int target, int lun) * 0 = success */ static int -qla1280_abort_command(struct scsi_qla_host *ha, srb_t * sp) +qla1280_abort_command(struct scsi_qla_host *ha, struct srb * sp, int handle) { uint16_t mb[MAILBOX_REGISTER_COUNT]; unsigned int bus, target, lun; - uint32_t handle; int status; ENTER("qla1280_abort_command"); - /* Locate handle number. */ - for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++) - if (ha->outstanding_cmds[handle] == sp) - break; - bus = SCSI_BUS_32(sp->cmd); target = SCSI_TCN_32(sp->cmd); lun = SCSI_LUN_32(sp->cmd); + sp->flags |= SRB_ABORT_PENDING; + mb[0] = MBC_ABORT_COMMAND; mb[1] = (bus ? target | BIT_7 : target) << 8 | lun; mb[2] = handle >> 16; mb[3] = handle & 0xffff; - status = - qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]); + status = qla1280_mailbox_command(ha, 0x0f, &mb[0]); - if (status) + if (status) { dprintk(2, "qla1280_abort_command: **** FAILED ****\n"); + sp->flags &= ~SRB_ABORT_PENDING; + } - sp->flags |= SRB_ABORT_PENDING; LEAVE("qla1280_abort_command"); return status; @@ -3622,11 +3487,11 @@ qla1280_reset_adapter(struct scsi_qla_host *ha) ENTER("qla1280_reset_adapter"); /* Disable ISP chip */ - ha->flags.online = FALSE; + ha->flags.online = 0; WRT_REG_WORD(®->ictrl, ISP_RESET); - WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); - WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); - WRT_REG_WORD(®->host_cmd, HC_DISABLE_BIOS); + WRT_REG_WORD(®->host_cmd, + HC_RESET_RISC | HC_RELEASE_RISC | HC_DISABLE_BIOS); + RD_REG_WORD(®->id_l); /* Flush PCI write */ LEAVE("qla1280_reset_adapter"); } @@ -3645,16 +3510,17 @@ qla1280_reset_adapter(struct scsi_qla_host *ha) static void qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type) { - mrk_entry_t *pkt; + struct mrk_entry *pkt; ENTER("qla1280_marker"); /* Get request packet. */ - if ((pkt = (mrk_entry_t *) qla1280_req_pkt(ha))) { + if ((pkt = (struct mrk_entry *) qla1280_req_pkt(ha))) { pkt->entry_type = MARKER_TYPE; pkt->lun = (uint8_t) lun; pkt->target = (uint8_t) (bus ? (id | BIT_7) : id); pkt->modifier = type; + pkt->entry_status = 0; /* Issue command to ISP */ qla1280_isp_cmd(ha); @@ -3663,7 +3529,7 @@ qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type) LEAVE("qla1280_marker"); } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18) + /* * qla1280_64bit_start_scsi * The start SCSI is responsible for building request packets on @@ -3677,7 +3543,7 @@ qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type) * 0 = success, was able to issue command. */ static int -qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) +qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { struct device_reg *reg = ha->iobase; Scsi_Cmnd *cmd = sp->cmd; @@ -3692,15 +3558,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) ENTER("qla1280_64bit_start_scsi:"); - dprintk(1, "64bit_start: cmd=%p sp=%p CDB=%x\n", cmd, sp, - cmd->cmnd[0]); - /* Calculate number of entries and segments required. */ req_cnt = 1; - if (cmd->use_sg) { /* 3.13 64 bit */ + if (cmd->use_sg) { sg = (struct scatterlist *) cmd->request_buffer; - seg_cnt = pci_map_sg (ha->pdev, sg, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + seg_cnt = pci_map_sg(ha->pdev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); if (seg_cnt > 2) { req_cnt += (seg_cnt - 2) / 5; @@ -3724,220 +3587,218 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) } /* If room for request in request ring. */ - if ((req_cnt + 2) < ha->req_q_cnt) { - /* Check for room in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS && - ha->outstanding_cmds[cnt] != 0; cnt++) ; + if ((req_cnt + 2) >= ha->req_q_cnt) { + status = 1; + dprintk(2, "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt=" + "0x%xreq_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt, + req_cnt); + goto out; + } - if (cnt < MAX_OUTSTANDING_COMMANDS) { - ha->outstanding_cmds[cnt] = sp; - ha->req_q_cnt -= req_cnt; - CMD_HANDLE(sp->cmd) = - (unsigned char *)(unsigned long)cnt; + /* Check for room in outstanding command list. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS && + ha->outstanding_cmds[cnt] != 0; cnt++); - /* - * Build command packet. - */ - pkt = (cmd_a64_entry_t *) ha->request_ring_ptr; + if (cnt >= MAX_OUTSTANDING_COMMANDS) { + status = 1; + dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN " + "OUTSTANDING ARRAY, req_q_cnt=0x%x", ha->req_q_cnt); + goto out; + } - pkt->entry_type = COMMAND_A64_TYPE; - pkt->entry_count = (uint8_t) req_cnt; - pkt->sys_define = (uint8_t) ha->req_ring_index; - pkt->handle = cpu_to_le32(cnt); + ha->outstanding_cmds[cnt] = sp; + ha->req_q_cnt -= req_cnt; + CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)(cnt + 1); + + dprintk(2, "64bit_start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp, + cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd)); + dprintk(2, " bus %i, target %i, lun %i\n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(2, cmd->cmnd, MAX_COMMAND_SIZE); + + /* + * Build command packet. + */ + pkt = (cmd_a64_entry_t *) ha->request_ring_ptr; + + pkt->entry_type = COMMAND_A64_TYPE; + pkt->entry_count = (uint8_t) req_cnt; + pkt->sys_define = (uint8_t) ha->req_ring_index; + pkt->entry_status = 0; + pkt->handle = cpu_to_le32(cnt); - /* Zero out remaining portion of packet. */ - memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); + /* Zero out remaining portion of packet. */ + memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); - /* Set ISP command timeout. */ - pkt->timeout = cpu_to_le16(30); + /* Set ISP command timeout. */ + pkt->timeout = cpu_to_le16(30); - /* Set device target ID and LUN */ - pkt->lun = SCSI_LUN_32(cmd); - pkt->target = SCSI_BUS_32(cmd) ? - (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); + /* Set device target ID and LUN */ + pkt->lun = SCSI_LUN_32(cmd); + pkt->target = SCSI_BUS_32(cmd) ? + (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); - /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue) - pkt->control_flags |= cpu_to_le16(BIT_3); + /* Enable simple tag queuing if device supports it. */ + if (cmd->device->tagged_queue) + pkt->control_flags |= cpu_to_le16(BIT_3); - /* Load SCSI command packet. */ - pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); - /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ + /* Load SCSI command packet. */ + pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + /* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ - /* Set transfer direction. */ - sp->dir = qla1280_data_direction(cmd); - pkt->control_flags |= cpu_to_le16(sp->dir); - - /* Set total data segment count. */ - pkt->dseg_count = cpu_to_le16(seg_cnt); + /* Set transfer direction. */ + sp->dir = qla1280_data_direction(cmd); + pkt->control_flags |= cpu_to_le16(sp->dir); + + /* Set total data segment count. */ + pkt->dseg_count = cpu_to_le16(seg_cnt); + + /* + * Load data segments. + */ + if (seg_cnt) { /* If data transfer. */ + /* Setup packet address segment pointer. */ + dword_ptr = (u32 *)&pkt->dseg_0_address; + + if (cmd->use_sg) { /* If scatter gather */ + /* Load command entry data segments. */ + for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) { + dma_handle = sg_dma_address(sg); +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, &dma_handle, + SCSI_BUS_32(cmd)); +#endif + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = + cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); + sg++; + dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", + cpu_to_le32(pci_dma_hi32(dma_handle)), + cpu_to_le32(pci_dma_lo32(dma_handle)), + cpu_to_le32(sg_dma_len(sg))); + } + dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " + "command packet data - b %i, t %i, l %i \n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); /* - * Load data segments. + * Build continuation packets. */ - if (seg_cnt) { /* If data transfer. */ - /* Setup packet address segment pointer. */ - dword_ptr = (u32 *)&pkt->dseg_0_address; - - if (cmd->use_sg) { /* If scatter gather */ - /* Load command entry data segments. */ - for (cnt = 0; cnt < 2 && seg_cnt; - cnt++, seg_cnt--) { - /* 3.13 64 bit */ - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); - *dword_ptr++ = - cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))); - *dword_ptr++ = - cpu_to_le32(sg_dma_len(sg)); - sg++; - dprintk(1, - "S/G Segment phys_addr=%x %x, len=0x%x\n", - cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))), - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), - cpu_to_le32(sg_dma_len(sg))); - } - dprintk(5, - "qla1280_64bit_start_scsi: Scatter/gather " - "command packet data - b %i, t %i, l %i \n", - SCSI_BUS_32(cmd), - SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, (char *)pkt, - REQUEST_ENTRY_SIZE); + dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " + "remains\n", seg_cnt); + + while (seg_cnt > 0) { + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = + ha->request_ring; + } else + ha->request_ring_ptr++; - /* - * Build continuation packets. - */ - dprintk(1, - "S/G Building Continuation...seg_cnt=0x%x " - "remains\n", seg_cnt); - - while (seg_cnt > 0) { - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == - REQUEST_ENTRY_CNT) { - ha->req_ring_index = 0; - ha->request_ring_ptr = - ha->request_ring; - } else - ha->request_ring_ptr++; - - pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; - - /* Zero out packet. */ - memset(pkt, 0, - REQUEST_ENTRY_SIZE); - - /* Load packet defaults. */ - ((cont_a64_entry_t *) pkt)->entry_type = - CONTINUE_A64_TYPE; - ((cont_a64_entry_t *) pkt)->entry_count = 1; - ((cont_a64_entry_t *) pkt)->sys_define = - (uint8_t)ha->req_ring_index; - /* Setup packet address segment pointer. */ - dword_ptr = - (u32 *)&((cont_a64_entry_t *) pkt)->dseg_0_address; - - /* Load continuation entry data segments. */ - for (cnt = 0; - cnt < 5 && seg_cnt; - cnt++, seg_cnt--) { - /* 3.13 64 bit */ - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); - *dword_ptr++ = - cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))); - *dword_ptr++ = - cpu_to_le32(sg_dma_len(sg)); - dprintk(1, - "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", - cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))), - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), - cpu_to_le32(sg_dma_len(sg))); - sg++; - } - dprintk(5, - "qla1280_64bit_start_scsi: continuation " - "packet data - b %i, t %i, l %i \n", - SCSI_BUS_32(cmd), - SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, - (char *)pkt, - REQUEST_ENTRY_SIZE); - } - } else { /* No scatter gather data transfer */ - /* 3.13 64 bit */ - dma_handle = pci_map_single(ha->pdev, - cmd->request_buffer, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - /* save dma_handle for pci_unmap_single */ - sp->saved_dma_handle = dma_handle; + pkt = (cmd_a64_entry_t *)ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + /* Load packet defaults. */ + ((struct cont_a64_entry *) pkt)->entry_type = + CONTINUE_A64_TYPE; + ((struct cont_a64_entry *) pkt)->entry_count = 1; + ((struct cont_a64_entry *) pkt)->sys_define = + (uint8_t)ha->req_ring_index; + /* Setup packet address segment pointer. */ + dword_ptr = + (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; + + /* Load continuation entry data segments. */ + for (cnt = 0; cnt < 5 && seg_cnt; + cnt++, seg_cnt--) { + dma_handle = sg_dma_address(sg); +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, &dma_handle, + SCSI_BUS_32(cmd)); +#endif *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); - *dword_ptr = - (uint32_t)cmd->request_bufflen; - /* dprintk(1, - "No S/G map_single saved_dma_handle=%lx\n",dma_handle); - */ - dprintk(5, - "qla1280_64bit_start_scsi: No scatter/gather " - "command packet data - b %i, t %i, l %i \n", - SCSI_BUS_32(cmd), - SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, (char *)pkt, - REQUEST_ENTRY_SIZE); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(sg)); + dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", + cpu_to_le32(pci_dma_hi32(dma_handle)), + cpu_to_le32(pci_dma_lo32(dma_handle)), + cpu_to_le32(sg_dma_len(sg))); + sg++; } - } else { /* No data transfer */ - - dword_ptr = (uint32_t *)(pkt + 1); - *dword_ptr++ = 0; - *dword_ptr++ = 0; - *dword_ptr = 0; - dprintk(5, - "qla1280_64bit_start_scsi: No data, command " - "packet data - b %i, t %i, l %i \n", - SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); + dprintk(5, "qla1280_64bit_start_scsi: " + "continuation packet data - b %i, t " + "%i, l %i \n", SCSI_BUS_32(cmd), + SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); } - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } else - ha->request_ring_ptr++; - - /* Set chip new ring index. */ - dprintk(1, - "qla1280_64bit_start_scsi: Wakeup RISC for pending command\n"); - ha->qthreads--; - sp->flags |= SRB_SENT; - ha->actthreads++; - WRT_REG_WORD(®->mailbox4, ha->req_ring_index); - } else { - status = 1; - dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN " - "OUTSTANDING ARRAY, req_q_cnt=0x%x", - ha->req_q_cnt); + } else { /* No scatter gather data transfer */ + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK; + + dma_handle = pci_map_page(ha->pdev, page, off, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + /* save dma_handle for pci_unmap_page */ + sp->saved_dma_handle = dma_handle; +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) + if (ha->flags.use_pci_vchannel) + sn_pci_set_vchan(ha->pdev, &dma_handle, + SCSI_BUS_32(cmd)); +#endif + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle)); + *dword_ptr = (uint32_t)cmd->request_bufflen; + + dprintk(5, "qla1280_64bit_start_scsi: No scatter/" + "gather command packet data - b %i, t %i, " + "l %i \n", SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), + SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, + REQUEST_ENTRY_SIZE); } - } else { - status = 1; - dprintk(2, - "qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt=0x%x" - "req_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt, - req_cnt); + } else { /* No data transfer */ + dword_ptr = (uint32_t *)(pkt + 1); + *dword_ptr++ = 0; + *dword_ptr++ = 0; + *dword_ptr = 0; + dprintk(5, "qla1280_64bit_start_scsi: No data, command " + "packet data - b %i, t %i, l %i \n", + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); + qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); } + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + /* Set chip new ring index. */ + dprintk(2, + "qla1280_64bit_start_scsi: Wakeup RISC for pending command\n"); + sp->flags |= SRB_SENT; + ha->actthreads++; + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + out: if (status) dprintk(2, "qla1280_64bit_start_scsi: **** FAILED ****\n"); else @@ -3945,7 +3806,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) return status; } -#endif + /* * qla1280_32bit_start_scsi @@ -3967,11 +3828,11 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) * 0 = success, was able to issue command. */ static int -qla1280_32bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) +qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { struct device_reg *reg = ha->iobase; Scsi_Cmnd *cmd = sp->cmd; - cmd_entry_t *pkt; + struct cmd_entry *pkt; struct scatterlist *sg = NULL; uint32_t *dword_ptr; int status = 0; @@ -3989,15 +3850,14 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) req_cnt = 1; if (cmd->use_sg) { /* - * We must build an SG list in adapter format, as the kernel's SG list - * cannot be used directly because of data field size (__alpha__) - * differences and the kernel SG list uses virtual addresses where - * we need physical addresses. + * We must build an SG list in adapter format, as the kernel's + * SG list cannot be used directly because of data field size + * (__alpha__) differences and the kernel SG list uses virtual + * addresses where we need physical addresses. */ sg = (struct scatterlist *) cmd->request_buffer; - /* 3.13 32 bit */ - seg_cnt = pci_map_sg (ha->pdev, sg, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + seg_cnt = pci_map_sg(ha->pdev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); /* * if greater than four sg entries then we need to allocate @@ -4008,10 +3868,10 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) if ((seg_cnt - 4) % 7) req_cnt++; } - dprintk(1, "S/G Transfer cmd=%p seg_cnt=0x%x, req_cnt=%x\n", + dprintk(3, "S/G Transfer cmd=%p seg_cnt=0x%x, req_cnt=%x\n", cmd, seg_cnt, req_cnt); } else if (cmd->request_bufflen) { /* If data transfer. */ - dprintk(1, "No S/G transfer t=%x cmd=%p len=%x CDB=%x\n", + dprintk(3, "No S/G transfer t=%x cmd=%p len=%x CDB=%x\n", SCSI_TCN_32(cmd), cmd, cmd->request_bufflen, cmd->cmnd[0]); seg_cnt = 1; @@ -4030,234 +3890,184 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp) REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); } - dprintk(1, "Number of free entries=(%d) seg_cnt=0x%x\n", + dprintk(3, "Number of free entries=(%d) seg_cnt=0x%x\n", ha->req_q_cnt, seg_cnt); /* If room for request in request ring. */ - if ((req_cnt + 2) < ha->req_q_cnt) { - /* Check for empty slot in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS && - (ha->outstanding_cmds[cnt] != 0); cnt++) ; + if ((req_cnt + 2) >= ha->req_q_cnt) { + status = 1; + dprintk(2, "qla1280_32bit_start_scsi: in-ptr=0x%x, " + "req_q_cnt=0x%x, req_cnt=0x%x", ha->req_ring_index, + ha->req_q_cnt, req_cnt); + goto out; + } - if (cnt < MAX_OUTSTANDING_COMMANDS) { - CMD_HANDLE(sp->cmd) = - (unsigned char *) (unsigned long) cnt; - ha->outstanding_cmds[cnt] = sp; - ha->req_q_cnt -= req_cnt; + /* Check for empty slot in outstanding command list. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS && + (ha->outstanding_cmds[cnt] != 0); cnt++) ; - /* - * Build command packet. - */ - pkt = (cmd_entry_t *) ha->request_ring_ptr; + if (cnt >= MAX_OUTSTANDING_COMMANDS) { + status = 1; + dprintk(2, "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING " + "ARRAY, req_q_cnt=0x%x\n", ha->req_q_cnt); + goto out; + } - pkt->entry_type = COMMAND_TYPE; - pkt->entry_count = (uint8_t) req_cnt; - pkt->sys_define = (uint8_t) ha->req_ring_index; - pkt->handle = cpu_to_le32(cnt); + CMD_HANDLE(sp->cmd) = (unsigned char *) (unsigned long)(cnt + 1); + ha->outstanding_cmds[cnt] = sp; + ha->req_q_cnt -= req_cnt; - /* Zero out remaining portion of packet. */ - memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); + /* + * Build command packet. + */ + pkt = (struct cmd_entry *) ha->request_ring_ptr; - /* Set ISP command timeout. */ - pkt->timeout = cpu_to_le16(30); + pkt->entry_type = COMMAND_TYPE; + pkt->entry_count = (uint8_t) req_cnt; + pkt->sys_define = (uint8_t) ha->req_ring_index; + pkt->entry_status = 0; + pkt->handle = cpu_to_le32(cnt); - /* Set device target ID and LUN */ - pkt->lun = SCSI_LUN_32(cmd); - pkt->target = SCSI_BUS_32(cmd) ? - (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); + /* Zero out remaining portion of packet. */ + memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); - /* Enable simple tag queuing if device supports it. */ - if (cmd->device->tagged_queue) - pkt->control_flags |= cpu_to_le16(BIT_3); + /* Set ISP command timeout. */ + pkt->timeout = cpu_to_le16(30); - /* Load SCSI command packet. */ - pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); - memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + /* Set device target ID and LUN */ + pkt->lun = SCSI_LUN_32(cmd); + pkt->target = SCSI_BUS_32(cmd) ? + (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd); - /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ - /* Set transfer direction. */ - sp->dir = qla1280_data_direction(cmd); - pkt->control_flags |= cpu_to_le16(sp->dir); - - /* Set total data segment count. */ - pkt->dseg_count = cpu_to_le16(seg_cnt); + /* Enable simple tag queuing if device supports it. */ + if (cmd->device->tagged_queue) + pkt->control_flags |= cpu_to_le16(BIT_3); + /* Load SCSI command packet. */ + pkt->cdb_len = cpu_to_le16(CMD_CDBLEN(cmd)); + memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), CMD_CDBLEN(cmd)); + + /*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */ + /* Set transfer direction. */ + sp->dir = qla1280_data_direction(cmd); + pkt->control_flags |= cpu_to_le16(sp->dir); + + /* Set total data segment count. */ + pkt->dseg_count = cpu_to_le16(seg_cnt); + + /* + * Load data segments. + */ + if (seg_cnt) { + /* Setup packet address segment pointer. */ + dword_ptr = &pkt->dseg_0_address; + + if (cmd->use_sg) { /* If scatter gather */ + dprintk(3, "Building S/G data segments..\n"); + qla1280_dump_buffer(1, (char *)sg, 4 * 16); + + /* Load command entry data segments. */ + for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) { + *dword_ptr++ = + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); + *dword_ptr++ = + cpu_to_le32(sg_dma_len(sg)); + dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", + (pci_dma_lo32(sg_dma_address(sg))), + (sg_dma_len(sg))); + sg++; + } /* - * Load data segments. + * Build continuation packets. */ - if (seg_cnt) { + dprintk(3, "S/G Building Continuation" + "...seg_cnt=0x%x remains\n", seg_cnt); + while (seg_cnt > 0) { + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = + ha->request_ring; + } else + ha->request_ring_ptr++; + + pkt = (struct cmd_entry *)ha->request_ring_ptr; + + /* Zero out packet. */ + memset(pkt, 0, REQUEST_ENTRY_SIZE); + + /* Load packet defaults. */ + ((struct cont_entry *) pkt)-> + entry_type = CONTINUE_TYPE; + ((struct cont_entry *) pkt)->entry_count = 1; + + ((struct cont_entry *) pkt)->sys_define = + (uint8_t) ha->req_ring_index; + /* Setup packet address segment pointer. */ - dword_ptr = &pkt->dseg_0_address; - - if (cmd->use_sg) { /* If scatter gather */ - dprintk(1, "Building S/G data " - "segments..\n"); - qla1280_dump_buffer(1, (char *)sg, - 4 * 16); - - /* Load command entry data segments. */ - for (cnt = 0; cnt < 4 && seg_cnt; - cnt++, seg_cnt--) { - /* 3.13 32 bit */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) - *dword_ptr++ = - cpu_to_le32(virt_to_bus(sg->address)); - *dword_ptr++ = cpu_to_le32(sg->length); - dprintk(1, - "S/G Segment phys_addr=0x%x, len=0x%x\n", - cpu_to_le32(virt_to_bus(sg->address)), - sg->length); -#else - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); - *dword_ptr++ = - cpu_to_le32(sg_dma_len(sg)); - dprintk(1, "S/G Segment phys_addr=0x%x, len=0x%x\n", - (pci_dma_lo32(sg_dma_address(sg))), - (sg_dma_len(sg))); -#endif - sg++; - } - /* - * Build continuation packets. - */ - dprintk(1, "S/G Building Continuation" - "...seg_cnt=0x%x remains\n", - seg_cnt); - while (seg_cnt > 0) { - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == - REQUEST_ENTRY_CNT) { - ha->req_ring_index = 0; - ha->request_ring_ptr = - ha->request_ring; - } else - ha->request_ring_ptr++; - - pkt = (cmd_entry_t *) - ha->request_ring_ptr; - - /* Zero out packet. */ - memset(pkt, 0, - REQUEST_ENTRY_SIZE); - - /* Load packet defaults. */ - ((cont_entry_t *) pkt)-> - entry_type = CONTINUE_TYPE; - ((cont_entry_t *) pkt)-> - entry_count = 1; - - ((cont_entry_t *) pkt)-> - sys_define = - (uint8_t) ha-> - req_ring_index; - - /* Setup packet address segment pointer. */ - dword_ptr = - &((cont_entry_t *) pkt)->dseg_0_address; - - /* Load continuation entry data segments. */ - for (cnt = 0; - cnt < 7 && seg_cnt; - cnt++, seg_cnt--) { - /* 3.13 32 bit */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) - *dword_ptr++ = - cpu_to_le32(virt_to_bus(sg->address)); - *dword_ptr++ = cpu_to_le32(sg->length); - dprintk(1, - "S/G Segment Cont. phys_addr=0x%x, len=0x%x\n", - cpu_to_le32(pci_dma_lo32(virt_to_bus(sg->address))), sg->length); -#else - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); - *dword_ptr++ = - cpu_to_le32(sg_dma_len(sg)); - dprintk(1, - "S/G Segment Cont. phys_addr=0x%x, " - "len=0x%x\n", - cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), - cpu_to_le32(sg_dma_len(sg))); -#endif - sg++; - } - dprintk(5, - "qla1280_32bit_start_scsi: continuation " - "packet data - scsi(%i:%i:%i)\n", - SCSI_BUS_32(cmd), - SCSI_TCN_32(cmd), - SCSI_LUN_32(cmd)); - qla1280_dump_buffer(5, - (char *)pkt, - REQUEST_ENTRY_SIZE); - } - } else { /* No S/G data transfer */ + dword_ptr = + &((struct cont_entry *) pkt)->dseg_0_address; - /* 3.13 32 bit */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) + /* Load continuation entry data segments. */ + for (cnt = 0; cnt < 7 && seg_cnt; + cnt++, seg_cnt--) { *dword_ptr++ = - cpu_to_le32 (virt_to_bus - (cmd->request_buffer)); -#else - dma_handle = pci_map_single(ha->pdev, - cmd->request_buffer, - cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); - sp->saved_dma_handle = dma_handle; - + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(dma_handle)); -#endif - *dword_ptr = - cpu_to_le32(cmd->request_bufflen); - qla1280_dump_buffer(1,(char *)pkt, - REQUEST_ENTRY_SIZE); + cpu_to_le32(sg_dma_len(sg)); + dprintk(1, + "S/G Segment Cont. phys_addr=0x%x, " + "len=0x%x\n", + cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), + cpu_to_le32(sg_dma_len(sg))); + sg++; } - } else { /* No data transfer at all */ - - //dword_ptr = (uint32_t *)(pkt + 1); - //*dword_ptr++ = 0; - //*dword_ptr = 0; - dprintk(5, - "qla1280_32bit_start_scsi: No data, command " - "packet data - \n"); + dprintk(5, "qla1280_32bit_start_scsi: " + "continuation packet data - " + "scsi(%i:%i:%i)\n", SCSI_BUS_32(cmd), + SCSI_TCN_32(cmd), SCSI_LUN_32(cmd)); qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); } - dprintk(5, - "qla1280_32bit_start_scsi: First IOCB block:\n"); - qla1280_dump_buffer(5, (char *)ha->request_ring_ptr, - REQUEST_ENTRY_SIZE); - - /* Adjust ring index. */ - ha->req_ring_index++; - if (ha->req_ring_index == REQUEST_ENTRY_CNT) { - ha->req_ring_index = 0; - ha->request_ring_ptr = ha->request_ring; - } else - ha->request_ring_ptr++; - - /* Set chip new ring index. */ - dprintk(1, "qla1280_32bit_start_scsi: Wakeup RISC " - "for pending command\n"); - ha->qthreads--; - sp->flags |= SRB_SENT; - ha->actthreads++; - WRT_REG_WORD(®->mailbox4, ha->req_ring_index); - } else { - status = 1; - dprintk(2, - "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING " - "ARRAY, req_q_cnt=0x%x\n", ha->req_q_cnt); + } else { /* No S/G data transfer */ + struct page *page = virt_to_page(cmd->request_buffer); + unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK; + dma_handle = pci_map_page(ha->pdev, page, off, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + sp->saved_dma_handle = dma_handle; + + *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); + *dword_ptr = cpu_to_le32(cmd->request_bufflen); } - } else { - status = 1; - dprintk(2, - "qla1280_32bit_start_scsi: in-ptr=0x%x, req_q_cnt=0x%x, " - "req_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt, - req_cnt); + } else { /* No data transfer at all */ + dword_ptr = (uint32_t *)(pkt + 1); + *dword_ptr++ = 0; + *dword_ptr = 0; + dprintk(5, "qla1280_32bit_start_scsi: No data, command " + "packet data - \n"); + qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE); } + dprintk(5, "qla1280_32bit_start_scsi: First IOCB block:\n"); + qla1280_dump_buffer(5, (char *)ha->request_ring_ptr, + REQUEST_ENTRY_SIZE); + /* Adjust ring index. */ + ha->req_ring_index++; + if (ha->req_ring_index == REQUEST_ENTRY_CNT) { + ha->req_ring_index = 0; + ha->request_ring_ptr = ha->request_ring; + } else + ha->request_ring_ptr++; + + /* Set chip new ring index. */ + dprintk(2, "qla1280_32bit_start_scsi: Wakeup RISC " + "for pending command\n"); + sp->flags |= SRB_SENT; + ha->actthreads++; + WRT_REG_WORD(®->mailbox4, ha->req_ring_index); + +out: if (status) dprintk(2, "qla1280_32bit_start_scsi: **** FAILED ****\n"); @@ -4310,6 +4120,10 @@ qla1280_req_pkt(struct scsi_qla_host *ha) /* Zero out packet. */ memset(pkt, 0, REQUEST_ENTRY_SIZE); + /* + * How can this be right when we have a ring + * size of 512??? + */ /* Set system defined field. */ pkt->sys_define = (uint8_t) ha->req_ring_index; @@ -4379,13 +4193,13 @@ qla1280_isp_cmd(struct scsi_qla_host *ha) static void qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun) { - elun_entry_t *pkt; + struct elun_entry *pkt; ENTER("qla1280_enable_lun"); /* Get request packet. */ /* - if (pkt = (elun_entry_t *)qla1280_req_pkt(ha)) + if (pkt = (struct elun_entry *)qla1280_req_pkt(ha)) { pkt->entry_type = ENABLE_LUN_TYPE; pkt->lun = cpu_to_le16(bus ? lun | BIT_15 : lun); @@ -4398,7 +4212,7 @@ qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun) qla1280_isp_cmd(ha); } */ - pkt = (elun_entry_t *) 1; + pkt = (struct elun_entry *) 1; if (!pkt) dprintk(2, "qla1280_enable_lun: **** FAILED ****\n"); @@ -4407,211 +4221,6 @@ qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun) } #endif -#if QL1280_TARGET_MODE_SUPPORT -/****************************************************************************/ -/* Target Mode Support Functions. */ -/****************************************************************************/ - -/* - * qla1280_notify_ack - * Issue notify acknowledge IOCB. - * If sequence ID is zero, acknowledgement of - * SCSI bus reset or bus device reset is assumed. - * - * Input: - * ha = adapter block pointer. - * inotify = immediate notify entry pointer. - */ -static void -qla1280_notify_ack(struct scsi_qla_host *ha, notify_entry_t * inotify) -{ - nack_entry_t *pkt; - - dprintk(3, "qla1280_notify_ack: entered\n"); - - /* Get request packet. */ - if (pkt = (nack_entry_t *) qla1280_req_pkt(ha)) { - pkt->entry_type = NOTIFY_ACK_TYPE; - pkt->lun = inotify->lun; - pkt->initiator_id = inotify->initiator_id; - pkt->target_id = inotify->target_id; - if (inotify->seq_id == 0) - pkt->event = BIT_7; - else - pkt->seq_id = cpu_to_le16(inotify->seq_id); - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - - if (!pkt) - dprintk(2, "qla1280_notify_ack: **** FAILED ****\n"); - else - dprintk(3, "qla1280_notify_ack: exiting normally\n"); -} - -/* - * qla1280_immed_notify - * Issue immediate notify IOCB for LUN 0. - * - * Input: - * ha = adapter block pointer. - * inotify = immediate notify entry pointer. - */ -static void -qla1280_immed_notify(struct scsi_qla_host *ha, notify_entry_t * inotify) -{ - notify_entry_t *pkt; - - dprintk(3, "qla1280_immed_notify: entered\n"); - - /* Get request packet. */ - if (pkt = (notify_entry_t *) qla1280_req_pkt(ha)) { - pkt->entry_type = IMMED_NOTIFY_TYPE; - pkt->lun = inotify->lun; - pkt->initiator_id = inotify->initiator_id; - pkt->target_id = inotify->target_id; - pkt->status = 1; - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - - if (!pkt) - dprintk(2, "qla1280_immed_notify: **** FAILED ****\n"); - else - dprintk(3, "qla1280_immed_notify: exiting normally\n"); -} - -/* - * qla1280_accept_io - * Issue accept target I/O IOCB for LUN 0. - * - * Input: - * ha = adapter block pointer. - * ctio = ctio returned entry pointer. - */ -static void -qla1280_accept_io(struct scsi_qla_host *ha, ctio_ret_entry_t * ctio) -{ - atio_entry_t *pkt; - - dprintk(3, "qla1280_accept_io: entered\n"); - - /* Get request packet. */ - if (pkt = (atio_entry_t *) qla1280_req_pkt(ha)) { - pkt->entry_type = ACCEPT_TGT_IO_TYPE; - pkt->lun = ctio->lun; - pkt->initiator_id = ctio->initiator_id; - pkt->target_id = ctio->target_id; - pkt->tag_value = ctio->tag_value; - pkt->status = 1; - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - - if (!pkt) - dprintk(2, "qla1280_accept_io: **** FAILED ****\n"); - else - dprintk(3, "qla1280_accept_io: exiting normally\n"); -} - -/* - * qla1280_64bit_continue_io - * Issue continue target I/O IOCB. - * - * Input: - * ha = adapter block pointer. - * atio = atio pointer. - * len = total bytecount. - * addr = physical address pointer. - */ -static void -qla1280_64bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio, - uint32_t len, paddr32_t * addr) -{ - ctio_a64_entry_t *pkt; - uint32_t *dword_ptr; - - dprintk(3, "qla1280_64bit_continue_io: entered\n"); - - /* Get request packet. */ - if (pkt = (ctio_a64_entry_t *) qla1280_req_pkt(ha)) { - pkt->entry_type = CTIO_A64_TYPE; - pkt->lun = atio->lun; - pkt->initiator_id = atio->initiator_id; - pkt->target_id = atio->target_id; - pkt->option_flags = cpu_to_le32(atio->option_flags); - pkt->tag_value = atio->tag_value; - pkt->scsi_status = atio->scsi_status; - - if (len) { - pkt->dseg_count = cpu_to_le16(1); - pkt->transfer_length = cpu_to_le32(len); - pkt->dseg_0_length = cpu_to_le32(len); - dword_ptr = (uint32_t *) addr; - pkt->dseg_0_address[0] = cpu_to_le32(*dword_ptr++); - pkt->dseg_0_address[1] = cpu_to_le32(*dword_ptr); - } - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - - if (!pkt) - dprintk(2, "qla1280_64bit_continue_io: **** FAILED ****\n"); - else - dprintk(3, "qla1280_64bit_continue_io: exiting normally\n"); -} - -/* - * qla1280_32bit_continue_io - * Issue continue target I/O IOCB. - * - * Input: - * ha = adapter block pointer. - * atio = atio pointer. - * len = total bytecount. - * addr = physical address pointer. - */ -static void -qla1280_32bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio, - uint32_t len, paddr32_t * addr) -{ - ctio_entry_t *pkt; - uint32_t *dword_ptr; - - dprintk(3, "qla1280_32bit_continue_io: entered\n"); - - /* Get request packet. */ - if (pkt = (ctio_entry_t *) qla1280_req_pkt(ha)) { - pkt->entry_type = CONTINUE_TGT_IO_TYPE; - pkt->lun = atio->lun; - pkt->initiator_id = atio->initiator_id; - pkt->target_id = atio->target_id; - pkt->option_flags = cpu_to_le32(atio->option_flags); - pkt->tag_value = atio->tag_value; - pkt->scsi_status = atio->scsi_status; - - if (len) { - pkt->dseg_count = cpu_to_le16(1); - pkt->transfer_length = cpu_to_le32(len); - pkt->dseg_0_length = cpu_to_le32(len); - dword_ptr = (uint32_t *)addr; - pkt->dseg_0_address = cpu_to_le32(*dword_ptr); - } - - /* Issue command to ISP */ - qla1280_isp_cmd(ha); - } - - if (!pkt) - dprintk(2, "qla1280_32bit_continue_io: **** FAILED ****\n"); - else - dprintk(3, "qla1280_32bit_continue_io: exiting normally\n"); -} -#endif /* QL1280_TARGET_MODE_SUPPORT */ /****************************************************************************/ /* Interrupt Service Routine. */ @@ -4627,12 +4236,12 @@ qla1280_32bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio, * done_q_last = done queue last pointer. ****************************************************************************/ static void -qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, - srb_t ** done_q_last) +qla1280_isr(struct scsi_qla_host *ha, struct srb ** done_q_first, + struct srb ** done_q_last) { struct device_reg *reg = ha->iobase; - response_t *pkt; - srb_t *sp = 0; + struct response *pkt; + struct srb *sp = 0; uint16_t mailbox[MAILBOX_REGISTER_COUNT]; uint16_t *wptr; uint32_t index; @@ -4679,8 +4288,8 @@ qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, /* Handle asynchronous event */ switch (mailbox[0]) { case MBA_SCSI_COMPLETION: /* Response completion */ - dprintk(5, - "qla1280_isr: mailbox SCSI response completion\n"); + dprintk(5, "qla1280_isr: mailbox SCSI response " + "completion\n"); if (ha->flags.online) { /* Get outstanding command index. */ @@ -4713,39 +4322,34 @@ qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, */ printk(KERN_WARNING "qla1280: ISP invalid handle"); - ha->flags.isp_abort_needed = TRUE; } } break; case MBA_BUS_RESET: /* SCSI Bus Reset */ - ha->flags.reset_marker = TRUE; + ha->flags.reset_marker = 1; index = mailbox[6] & BIT_0; - ha->bus_settings[index].reset_marker = TRUE; + ha->bus_settings[index].reset_marker = 1; - printk(KERN_DEBUG - "qla1280_isr(): index %i asynchronous " - "BUS_RESET\n", index); + printk(KERN_DEBUG "qla1280_isr(): index %i " + "asynchronous BUS_RESET\n", index); break; case MBA_SYSTEM_ERR: /* System Error */ printk(KERN_WARNING - "qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, " - "mbx3=%xh\n", mailbox[1], mailbox[2], + "qla1280: ISP System Error - mbx1=%xh, mbx2=" + "%xh, mbx3=%xh\n", mailbox[1], mailbox[2], mailbox[3]); - ha->flags.isp_abort_needed = TRUE; break; case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ printk(KERN_WARNING "qla1280: ISP Request Transfer Error\n"); - ha->flags.isp_abort_needed = TRUE; break; case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ printk(KERN_WARNING "qla1280: ISP Response Transfer Error\n"); - ha->flags.isp_abort_needed = TRUE; break; case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ @@ -4758,14 +4362,12 @@ qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, break; case MBA_DEVICE_RESET: /* Bus Device Reset */ - dprintk(2, - "qla1280_isr: asynchronous BUS_DEVICE_RESET\n"); printk(KERN_INFO "qla1280_isr(): asynchronous " "BUS_DEVICE_RESET\n"); - ha->flags.reset_marker = TRUE; + ha->flags.reset_marker = 1; index = mailbox[6] & BIT_0; - ha->bus_settings[index].reset_marker = TRUE; + ha->bus_settings[index].reset_marker = 1; break; case MBA_BUS_MODE_CHANGE: @@ -4780,7 +4382,9 @@ qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, memcpy((uint16_t *) ha->mailbox_out, wptr, MAILBOX_REGISTER_COUNT * sizeof(uint16_t)); - ha->flags.mbox_int = TRUE; + + if(ha->mailbox_wait != NULL) + complete(ha->mailbox_wait); } break; } @@ -4793,123 +4397,68 @@ qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, * unnecessary as the mailbox data has been copied to ha->mailbox_out * by the time we actually get here! */ - if (ha->flags.online + if (!(ha->flags.online #if 0 && !ha->flags.mbox_busy #endif - ) { - if (mailbox[5] < RESPONSE_ENTRY_CNT) { - while (ha->rsp_ring_index != mailbox[5]) { - pkt = ha->response_ring_ptr; - - dprintk(5, - "qla1280_isr: ha->rsp_ring_index = 0x%x, " - "mailbox[5] = 0x%x\n", - ha->rsp_ring_index, mailbox[5]); - dprintk(5, - "qla1280_isr: response packet data\n"); - qla1280_dump_buffer(5, (char *)pkt, - RESPONSE_ENTRY_SIZE); - - if (pkt->entry_type == STATUS_TYPE) { - if ((le16_to_cpu(pkt->scsi_status) & 0xff) - || pkt->comp_status - || pkt->entry_status) { - dprintk(2, - "qla1280_isr: ha->rsp_ring_index = 0x%x" - "mailbox[5] = 0x%x, comp_status = 0x%x, " - "scsi_status = 0x%x\n", - ha->rsp_ring_index, - mailbox[5], - le16_to_cpu(pkt->comp_status), - le16_to_cpu(pkt->scsi_status)); - } - } else { - dprintk(2, - "qla1280_isr: ha->rsp_ring_index = 0x%x, " - "mailbox[5] = 0x%x\n", - ha->rsp_ring_index, - mailbox[5]); - dprintk(2, - "qla1280_isr: response packet data\n"); - qla1280_dump_buffer(2, (char *)pkt, - RESPONSE_ENTRY_SIZE); - } + )) { + dprintk(2, "qla1280_isr: Response pointer Error\n"); + goto out; + } - if (pkt->entry_type == STATUS_TYPE - || pkt->entry_status) { - if (pkt->entry_type == STATUS_TYPE) - qla1280_status_entry(ha, - (sts_entry_t *) pkt, - done_q_first, - done_q_last); - else - qla1280_error_entry(ha, pkt, - done_q_first, - done_q_last); - - /* Adjust ring index. */ - ha->rsp_ring_index++; - if (ha->rsp_ring_index == - RESPONSE_ENTRY_CNT) { - ha->rsp_ring_index = 0; - ha->response_ring_ptr = - ha->response_ring; - } else - ha->response_ring_ptr++; - WRT_REG_WORD(®->mailbox5, - ha->rsp_ring_index); - } -#if QLA1280_TARGET_MODE_SUPPORT - else { - pkt = &response_entry; - - /* Copy packet. */ - dptr1 = - (uint32_t *)ha->response_ring_ptr; - dptr2 = (uint32_t *) pkt; - for (index = 0; - index < RESPONSE_ENTRY_SIZE / 4; - index++) - *dptr2++ = *dptr1++; - - /* Adjust ring index. */ - ha->rsp_ring_index++; - if (ha->rsp_ring_index == - RESPONSE_ENTRY_CNT) { - ha->rsp_ring_index = 0; - ha->response_ring_ptr = - ha->response_ring; - } else - ha->response_ring_ptr++; - WRT_REG_WORD(®->mailbox5, - ha->rsp_ring_index); - - switch (pkt->entry_type) { - case ACCEPT_TGT_IO_TYPE: - qla1280_atio_entry(ha, - (atio_entry_t *) pkt); - break; - case IMMED_NOTIFY_TYPE: - qla1280_notify_entry(ha, - (notify_entry_t *) pkt); - break; - case CTIO_RET_TYPE: - qla1280_accept_io(ha, - (ctio_ret_entry_t *) pkt); - break; - default: - break; - } - } -#endif + if (mailbox[5] >= RESPONSE_ENTRY_CNT) + goto out; + + while (ha->rsp_ring_index != mailbox[5]) { + pkt = ha->response_ring_ptr; + + dprintk(5, "qla1280_isr: ha->rsp_ring_index = 0x%x, mailbox[5]" + " = 0x%x\n", ha->rsp_ring_index, mailbox[5]); + dprintk(5,"qla1280_isr: response packet data\n"); + qla1280_dump_buffer(5, (char *)pkt, RESPONSE_ENTRY_SIZE); + + if (pkt->entry_type == STATUS_TYPE) { + if ((le16_to_cpu(pkt->scsi_status) & 0xff) + || pkt->comp_status || pkt->entry_status) { + dprintk(2, "qla1280_isr: ha->rsp_ring_index = " + "0x%x mailbox[5] = 0x%x, comp_status " + "= 0x%x, scsi_status = 0x%x\n", + ha->rsp_ring_index, mailbox[5], + le16_to_cpu(pkt->comp_status), + le16_to_cpu(pkt->scsi_status)); } } else { - ha->flags.isp_abort_needed = TRUE; - dprintk(2, "qla1280_isr: Response pointer Error\n"); + dprintk(2, "qla1280_isr: ha->rsp_ring_index = " + "0x%x, mailbox[5] = 0x%x\n", + ha->rsp_ring_index, mailbox[5]); + dprintk(2, "qla1280_isr: response packet data\n"); + qla1280_dump_buffer(2, (char *)pkt, + RESPONSE_ENTRY_SIZE); } - } + if (pkt->entry_type == STATUS_TYPE || pkt->entry_status) { + dprintk(2, "status: Cmd %p, handle %i\n", + ha->outstanding_cmds[pkt->handle]->cmd, + pkt->handle); + if (pkt->entry_type == STATUS_TYPE) + qla1280_status_entry(ha, pkt, done_q_first, + done_q_last); + else + qla1280_error_entry(ha, pkt, done_q_first, + done_q_last); + + /* Adjust ring index. */ + ha->rsp_ring_index++; + if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) { + ha->rsp_ring_index = 0; + ha->response_ring_ptr = ha->response_ring; + } else + ha->response_ring_ptr++; + WRT_REG_WORD(®->mailbox5, ha->rsp_ring_index); + } + } + + out: LEAVE("qla1280_isr"); } @@ -4923,42 +4472,22 @@ qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first, static void qla1280_rst_aen(struct scsi_qla_host *ha) { -#if QL1280_TARGET_MODE_SUPPORT - notify_entry_t nentry; -#endif uint8_t bus; ENTER("qla1280_rst_aen"); if (ha->flags.online && !ha->flags.reset_active && !ha->flags.abort_isp_active) { - ha->flags.reset_active = TRUE; + ha->flags.reset_active = 1; while (ha->flags.reset_marker) { /* Issue marker command. */ - ha->flags.reset_marker = FALSE; + ha->flags.reset_marker = 0; for (bus = 0; bus < ha->ports && !ha->flags.reset_marker; bus++) { if (ha->bus_settings[bus].reset_marker) { - ha->bus_settings[bus].reset_marker = - FALSE; + ha->bus_settings[bus].reset_marker = 0; qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL); - - if (!ha->flags.reset_marker) { -#if QL1280_TARGET_MODE_SUPPORT - /* Issue notify acknowledgement command. */ - memset(&nentry, 0, - sizeof(notify_entry_t)); - - nentry.initiator_id = - nentry.target_id = - bus ? ha->bus_settings[bus].id | BIT_7 : - ha->bus_settings[bus].id; - qla1280_notify_entry(ha, - &nentry); -#endif - /* Asynchronous event notification */ - } } } } @@ -4967,432 +4496,50 @@ qla1280_rst_aen(struct scsi_qla_host *ha) LEAVE("qla1280_rst_aen"); } -#if QL1280_TARGET_MODE_SUPPORT -/* - * qla1280_atio_entry - * Processes received ISP accept target I/O entry. - * - * Input: - * ha = adapter block pointer. - * pkt = entry pointer. - */ -static void -qla1280_atio_entry(struct scsi_qla_host *ha, atio_entry_t * pkt) -{ - uint64_t *a64; - uint64_t *end_a64; - paddr32_t phy_addr[2]; - paddr32_t end_addr[2]; - uint32_t len; - uint32_t offset; - uint8_t t; - uint8_t *sense_ptr; - - dprintk(3, "qla1280_atio_entry: entered\n"); - - t = pkt->initiator_id; - sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE; - a64 = (uint64_t *)&phy_addr[0]; - end_a64 = (uint64_t *)&end_addr[0]; - - switch (pkt->status & ~BIT_7) { - case 7: /* Path invalid */ - dprintk(2, "qla1280_atio_entry: Path invalid\n"); - break; - - case 0x14: /* Target Bus Phase Sequence Failure */ - dprintk(2, "qla1280_atio_entry: Target Bus Phase " - "Sequence Failure\n"); - - if (pkt->status & BIT_7) { - memcpy(sense_ptr, &pkt->sense_data, TARGET_SENSE_SIZE); - } else { - memset(sense_ptr, 0, TARGET_SENSE_SIZE); - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_HARDERR; - *(sense_ptr + 7) = TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_SELFAIL; - } - pkt->scsi_status = S_CKCON; - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_NO_DATA); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) - if (ha->flags.enable_64bit_addressing) - qla1280_64bit_continue_io(ha, pkt, 0, 0); - else -#endif - qla1280_32bit_continue_io(ha, pkt, 0, 0); - break; - - case 0x16: /* Requested Capability Not Available */ - dprintk(2, "qla1280_atio_entry: Target Bus Phase " - "Sequence Failure\n"); - break; - - case 0x17: /* Bus Device Reset Message Received */ - dprintk(2, "qla1280_atio_entry: Target Bus Phase " - "Sequence Failure\n"); - break; - - case 0x3D: /* CDB Received */ - - /* Check for invalid LUN */ - if (pkt->lun && pkt->cdb[0] != SS_INQUIR && - pkt->cdb[0] != SS_REQSEN) - pkt->cdb[0] = SS_TEST; - - switch (pkt->cdb[0]) { - case SS_TEST: - dprintk(3, "qla1280_atio_entry: SS_TEST\n"); - - memset(sense_ptr, 0, TARGET_SENSE_SIZE); - len = 0; - if (pkt->lun == 0) - pkt->scsi_status = S_GOOD; - else { - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_INVLUN; - pkt->scsi_status = S_CKCON; - } - - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_NO_DATA); - break; - - case SS_REQSEN: - dprintk(3, "qla1280_atio_entry: SS_REQSEN\n"); - - phy_addr[0] = ha->tsense_dma; - phy_addr[1] = 0; - *a64 += t * TARGET_SENSE_SIZE; - if (pkt->cdb[4] > TARGET_SENSE_SIZE) - len = TARGET_SENSE_SIZE; - else - len = pkt->cdb[4]; - pkt->scsi_status = S_GOOD; - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_DATA_IN); - break; - - case SS_INQUIR: - dprintk(3, "qla1280_atio_entry: SS_INQUIR\n"); - - memset(sense_ptr, 0, TARGET_SENSE_SIZE); - phy_addr[0] = ha->tbuf_dma; - phy_addr[1] = 0; - *a64 += TARGET_INQ_OFFSET; - - if (pkt->lun == 0) { - ha->tbuf->inq.id_type = ID_PROCESOR; - ha->tbuf->inq.id_pqual = ID_QOK; - } else { - ha->tbuf->inq.id_type = ID_NODEV; - ha->tbuf->inq.id_pqual = ID_QNOLU; - } - - if (pkt->cdb[4] > sizeof(struct ident)) - len = sizeof(struct ident); - else - len = pkt->cdb[4]; - pkt->scsi_status = S_GOOD; - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_DATA_IN); - break; - - case SM_WRDB: - memset(sense_ptr, 0, TARGET_SENSE_SIZE); - offset = pkt->cdb[5]; - offset |= pkt->cdb[4] << 8; - offset |= pkt->cdb[3] << 16; - len = pkt->cdb[8]; - len |= pkt->cdb[7] << 8; - len |= pkt->cdb[6] << 16; - end_addr[0] = phy_addr[0] = ha->tbuf_dma; - end_addr[1] = phy_addr[1] = 0; - *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE; - switch (pkt->cdb[1] & 7) { - case RW_BUF_HDATA: - dprintk(3, "qla1280_atio_entry: SM_WRDB, " - "RW_BUF_HDATA\n"); - - if (len > TARGET_DATA_SIZE + 4) { - dprintk(2, - "qla1280_atio_entry: SM_WRDB, " - "length > buffer size\n"); - - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = - TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_ILLCDB; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - len = 0; - } else if (len) { - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_DATA_OUT); - dprintk(3, - "qla1280_atio_entry: Issuing " - "SDI_TARMOD_WRCOMP\n"); - - sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr, - pkt->target_id, pkt->lun, 0, - offset); - } else { - dprintk(2, - "qla1280_atio_entry: SM_WRDB, " - "zero length\n"); - - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } - - break; - case RW_BUF_DATA: - dprintk(3, "qla1280_atio_entry: SM_WRDB, " - "RW_BUF_DATA\n"); - - *a64 += offset + TARGET_DATA_OFFSET; - if (pkt->cdb[2] != 0 || *a64 >= *end_a64 || - *a64 + len > *end_a64) { - dprintk(2, - "qla1280_atio_entry: SM_WRDB, " - "RW_BUF_DATA BAD\n"); - dprintk(2, "buf_id=0x%x, offset=0x%x, " - "length=0x%x\n", pkt->cdb[2], - offset, len); - - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = - TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } else if (len) { - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_DATA_OUT); - dprintk(3, - "qla1280_atio_entry: Issuing " - "SDI_TARMOD_WRCOMP\n"); - - sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr, - pkt->target_id, pkt->lun, 0, - offset); - } else { - dprintk(2, - "qla1280_atio_entry: SM_WRDB, " - "zero length\n"); - - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } - break; - - default: - dprintk(2, "qla1280_atio_entry: SM_WRDB " - "unknown mode\n"); - - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_NO_DATA); - break; - } - break; - - case SM_RDDB: - memset(sense_ptr, 0, TARGET_SENSE_SIZE); - offset = pkt->cdb[5]; - offset |= pkt->cdb[4] << 8; - offset |= pkt->cdb[3] << 16; - len = pkt->cdb[8]; - len |= pkt->cdb[7] << 8; - len |= pkt->cdb[6] << 16; - end_addr[0] = phy_addr[0] = ha->tbuf_dma; - end_addr[1] = phy_addr[1] = 0; - *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE; - switch (pkt->cdb[1] & 7) { - case RW_BUF_HDATA: - dprintk(3, "qla1280_atio_entry: SM_RDDB, " - "RW_BUF_HDATA\n"); - - if (len) { - ha->tbuf->hdr[0] = 0; - ha->tbuf->hdr[1] = - (TARGET_DATA_SIZE >> 16) & 0xff; - ha->tbuf->hdr[2] = - (TARGET_DATA_SIZE >> 8) & 0xff; - ha->tbuf->hdr[3] = - TARGET_DATA_SIZE & 0xff; - if (len > TARGET_DATA_SIZE + 4) - len = TARGET_DATA_SIZE + 4; - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_DATA_IN); - } else { - dprintk(2, - "qla1280_atio_entry: SM_RDDB, " - "zero length\n"); - - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } - break; - case RW_BUF_DATA: - dprintk(3, "qla1280_atio_entry: SM_RDDB, " - "RW_BUF_DATA\n"); - - *a64 += offset + TARGET_DATA_OFFSET; - if (pkt->cdb[2] != 0 || *a64 >= *end_a64) { - dprintk(2, - "qla1280_atio_entry: SM_RDDB, " - "RW_BUF_DATA BAD\n"); - dprintk(2, "buf_id=0x%x, offset=0x%x\n" - pkt->cdb[2], offset); - - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = - TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } else { - if (*a64 + len > *end_a64) - len = *end_a64 - *a64; - if (len) { - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - (OF_SSTS | OF_DATA_IN); - } else { - dprintk(2, - "qla1280_atio_entry: SM_RDDB, " - "zero length\n"); - - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } - } - break; - case RW_BUF_DESC: - dprintk(3, "qla1280_atio_entry: SM_RDDB, " - "RW_BUF_DESC\n"); - - if (len) { - if (len > 4) - len = 4; - - ha->tbuf->hdr[0] = 0; - if (pkt->cdb[2] != 0) { - ha->tbuf->hdr[1] = 0; - ha->tbuf->hdr[2] = 0; - ha->tbuf->hdr[3] = 0; - } else { - ha->tbuf->hdr[1] = - (TARGET_DATA_SIZE >> 16) & - 0xff; - ha->tbuf->hdr[2] = - (TARGET_DATA_SIZE >> 8) & - 0xff; - ha->tbuf->hdr[3] = - TARGET_DATA_SIZE & 0xff; - } - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_DATA_IN); - } else { - dprintk(2, - "qla1280_atio_entry: SM_RDDB," - " zero length\n"); - - pkt->scsi_status = S_GOOD; - pkt->option_flags |= - cpu_to_le32(OF_SSTS | OF_NO_DATA); - } - break; - default: - dprintk(2, "qla1280_atio_entry: SM_RDDB " - "unknown mode\n"); - - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_ILLCDB; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_NO_DATA); - break; - } - break; - - default: - dprintk(2, - "qla1280_atio_entry: Unknown SCSI command\n"); - qla1280_dump_buffer(2, &pkt->cdb[0], pkt->cdb_len); - - memset(sense_ptr, 0, TARGET_SENSE_SIZE); - *sense_ptr = 0x70; - *(sense_ptr + 2) = SD_ILLREQ; - *(sense_ptr + 7) = TARGET_SENSE_SIZE - 8; - *(sense_ptr + 12) = SC_INVOPCODE; - len = 0; - pkt->scsi_status = S_CKCON; - pkt->option_flags |= cpu_to_le32(OF_SSTS | OF_NO_DATA); - break; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) - if (ha->flags.enable_64bit_addressing) - qla1280_64bit_continue_io(ha, pkt, len, - (paddr32_t *)&phy_addr); - else -#endif - qla1280_32bit_continue_io(ha, pkt, len, - (paddr32_t *)&phy_addr); - break; - - default: - break; - } - - dprintk(3, "qla1280_atio_entry: exiting normally\n"); -} +#if LINUX_KERNEL_VERSION < 0x020500 /* - * qla1280_notify_entry - * Processes received ISP immediate notify entry. * - * Input: - * ha = adapter block pointer. - * pkt = entry pointer. */ -static void -qla1280_notify_entry(struct scsi_qla_host *ha, notify_entry_t * pkt) +void +qla1280_get_target_options(struct scsi_cmnd *cmd, struct scsi_qla_host *ha) { - dprintk(3, "qla1280_notify_entry: entered\n"); + unsigned char *result; + struct nvram *n; + int bus, target, lun; - /* Acknowledge immediate notify */ - qla1280_notify_ack(ha, pkt); + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); - /* Issue notify entry to increment resource count */ - qla1280_immed_notify(ha, pkt); + /* + * Make sure to not touch anything if someone is using the + * sg interface. + */ + if (cmd->use_sg || (CMD_RESULT(cmd) >> 16) != DID_OK || lun) + return; - dprintk(3, "qla1280_notify_entry: exiting normally\n"); + result = cmd->request_buffer; + n = &ha->nvram; + + n->bus[bus].target[target].parameter.f.enable_wide = 0; + n->bus[bus].target[target].parameter.f.enable_sync = 0; + n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; + + if (result[7] & 0x60) + n->bus[bus].target[target].parameter.f.enable_wide = 1; + if (result[7] & 0x10) + n->bus[bus].target[target].parameter.f.enable_sync = 1; + if ((result[2] >= 3) && (result[4] + 5 > 56) && + (result[56] & 0x4)) + n->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1; + + dprintk(2, "get_target_options(): wide %i, sync %i, ppr %i\n", + n->bus[bus].target[target].parameter.f.enable_wide, + n->bus[bus].target[target].parameter.f.enable_sync, + n->bus[bus].target[target].ppr_1x160.flags.enable_ppr); } -#endif /* QLA1280_TARGET_MODE_SUPPORT */ +#endif /* * qla1280_status_entry @@ -5405,13 +4552,12 @@ qla1280_notify_entry(struct scsi_qla_host *ha, notify_entry_t * pkt) * done_q_last = done queue last pointer. */ static void -qla1280_status_entry(struct scsi_qla_host *ha, sts_entry_t * pkt, - srb_t ** done_q_first, srb_t ** done_q_last) +qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt, + struct srb **done_q_first, struct srb **done_q_last) { unsigned int bus, target, lun; int sense_sz; - srb_t *sp; - scsi_lu_t *q; + struct srb *sp; Scsi_Cmnd *cmd; uint32_t handle = le32_to_cpu(pkt->handle); uint16_t scsi_status = le16_to_cpu(pkt->scsi_status); @@ -5423,73 +4569,73 @@ qla1280_status_entry(struct scsi_qla_host *ha, sts_entry_t * pkt, if (handle < MAX_OUTSTANDING_COMMANDS) sp = ha->outstanding_cmds[handle]; else - sp = 0; + sp = NULL; - if (sp) { - /* Free outstanding command slot. */ - ha->outstanding_cmds[handle] = 0; + if (!sp) { + printk(KERN_WARNING "qla1280: Status Entry invalid handle\n"); + goto out; + } - cmd = sp->cmd; + /* Free outstanding command slot. */ + ha->outstanding_cmds[handle] = 0; - /* Generate LU queue on cntrl, target, LUN */ - bus = SCSI_BUS_32(cmd); - target = SCSI_TCN_32(cmd); - lun = SCSI_LUN_32(cmd); - q = LU_Q(ha, bus, target, lun); + cmd = sp->cmd; - if (comp_status || scsi_status) { - dprintk(1, "scsi: comp_status = 0x%x, scsi_status = " - "0x%x, handle = 0x%lx\n", comp_status, - scsi_status, handle); - } + /* Generate LU queue on cntrl, target, LUN */ + bus = SCSI_BUS_32(cmd); + target = SCSI_TCN_32(cmd); + lun = SCSI_LUN_32(cmd); - /* Target busy */ - if (scsi_status & SS_BUSY_CONDITION && - scsi_status != SS_RESERVE_CONFLICT) { - CMD_RESULT(cmd) = - DID_BUS_BUSY << 16 | (scsi_status & 0xff); - } else { + if (comp_status || scsi_status) { + dprintk(3, "scsi: comp_status = 0x%x, scsi_status = " + "0x%x, handle = 0x%x\n", comp_status, + scsi_status, handle); + } - /* Save ISP completion status */ - CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd); + /* Target busy */ + if (scsi_status & SS_BUSY_CONDITION && + scsi_status != SS_RESERVE_CONFLICT) { + CMD_RESULT(cmd) = + DID_BUS_BUSY << 16 | (scsi_status & 0xff); + } else { - if (scsi_status & SS_CHECK_CONDITION) { - if (comp_status != CS_ARS_FAILED) { - uint16_t req_sense_length = - le16_to_cpu(pkt->req_sense_length); - if (req_sense_length < - CMD_SNSLEN(cmd)) - sense_sz = req_sense_length; - else - /* - * Scsi_Cmnd->sense_buffer is - * 64 bytes, why only copy 63? - * This looks wrong! /Jes - */ - sense_sz = CMD_SNSLEN(cmd) - 1; - - memcpy(cmd->sense_buffer, - &pkt->req_sense_data, sense_sz); - } else - sense_sz = 0; - memset(cmd->sense_buffer + sense_sz, 0, - sizeof(cmd->sense_buffer) - sense_sz); - - dprintk(2, "qla1280_status_entry: Check " - "condition Sense data, b %i, t %i, " - "l %i\n", bus, target, lun); - if (sense_sz) - qla1280_dump_buffer(2, (char *)cmd->sense_buffer, - sense_sz); - } + /* Save ISP completion status */ + CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd); + + if (scsi_status & SS_CHECK_CONDITION) { + if (comp_status != CS_ARS_FAILED) { + uint16_t req_sense_length = + le16_to_cpu(pkt->req_sense_length); + if (req_sense_length < CMD_SNSLEN(cmd)) + sense_sz = req_sense_length; + else + /* + * Scsi_Cmnd->sense_buffer is + * 64 bytes, why only copy 63? + * This looks wrong! /Jes + */ + sense_sz = CMD_SNSLEN(cmd) - 1; + + memcpy(cmd->sense_buffer, + &pkt->req_sense_data, sense_sz); + } else + sense_sz = 0; + memset(cmd->sense_buffer + sense_sz, 0, + sizeof(cmd->sense_buffer) - sense_sz); + + dprintk(2, "qla1280_status_entry: Check " + "condition Sense data, b %i, t %i, " + "l %i\n", bus, target, lun); + if (sense_sz) + qla1280_dump_buffer(2, + (char *)cmd->sense_buffer, + sense_sz); } - /* Place command on done queue. */ - qla1280_done_q_put(sp, done_q_first, done_q_last); - } else { - printk(KERN_WARNING "qla1280: Status Entry invalid handle\n"); - ha->flags.isp_abort_needed = TRUE; } + /* Place command on done queue. */ + qla1280_done_q_put(sp, done_q_first, done_q_last); + out: LEAVE("qla1280_status_entry"); } @@ -5504,10 +4650,10 @@ qla1280_status_entry(struct scsi_qla_host *ha, sts_entry_t * pkt, * done_q_last = done queue last pointer. */ static void -qla1280_error_entry(struct scsi_qla_host *ha, response_t * pkt, - srb_t ** done_q_first, srb_t ** done_q_last) +qla1280_error_entry(struct scsi_qla_host *ha, struct response * pkt, + struct srb ** done_q_first, struct srb ** done_q_last) { - srb_t *sp; + struct srb *sp; uint32_t handle = le32_to_cpu(pkt->handle); ENTER("qla1280_error_entry"); @@ -5548,7 +4694,6 @@ qla1280_error_entry(struct scsi_qla_host *ha, response_t * pkt, #ifdef QLA_64BIT_PTR else if (pkt->entry_type == COMMAND_A64_TYPE) { printk(KERN_WARNING "!qla1280: Error Entry invalid handle"); - ha->flags.isp_abort_needed = TRUE; } #endif @@ -5568,49 +4713,39 @@ qla1280_error_entry(struct scsi_qla_host *ha, response_t * pkt, static int qla1280_abort_isp(struct scsi_qla_host *ha) { -#if 0 - struct device_reg *reg = ha->iobase; -#endif - srb_t *sp; - scsi_lu_t *q; + struct srb *sp; int status = 0; int cnt; - int bus, target, lun; + int bus; ENTER("qla1280_abort_isp"); - ha->flags.isp_abort_needed = FALSE; if (!ha->flags.abort_isp_active && ha->flags.online) { - ha->flags.abort_isp_active = TRUE; + struct device_reg *reg = ha->iobase; + ha->flags.abort_isp_active = 1; /* Disable ISP interrupts. */ qla1280_disable_intrs(ha); + WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); + RD_REG_WORD(®->id_l); + printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n", + ha->host_no); /* Dequeue all commands in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + Scsi_Cmnd *cmd; sp = ha->outstanding_cmds[cnt]; if (sp) { - ha->outstanding_cmds[cnt] = 0; - - /* Generate LU queue on controller, target, LUN */ - bus = SCSI_BUS_32(sp->cmd); - target = SCSI_TCN_32(sp->cmd); - lun = SCSI_LUN_32(sp->cmd); - q = LU_Q(ha, bus, target, lun); + cmd = sp->cmd; + CMD_RESULT(cmd) = DID_RESET << 16; - /* Reset outstanding command count. */ - q->q_outcnt = 0; - q->q_flag &= ~QLA1280_QBUSY; - q->q_flag = 0; + sp->cmd = NULL; + ha->outstanding_cmds[cnt] = NULL; - /* Adjust watchdog timer for command. */ - /* if (sp->flags & SRB_WATCHDOG) - sp->timeout += 2; */ + (*cmd->scsi_done)(cmd); - /* Place request back on top of device queue. */ sp->flags = 0; - qla1280_putq_t(q, sp); } } @@ -5629,38 +4764,21 @@ qla1280_abort_isp(struct scsi_qla_host *ha) for (bus = 0; bus < ha->ports; bus++) { qla1280_bus_reset(ha, bus); } - do { - /* Issue marker command. */ - ha->flags.reset_marker = FALSE; - for (bus = 0; bus < ha->ports; bus++) { - ha->bus_settings[bus]. - reset_marker = FALSE; - qla1280_marker(ha, bus, 0, 0, - MK_SYNC_ALL); - } - } while (ha->flags.reset_marker); - - /* Enable host adapter target mode. */ + /* + * qla1280_bus_reset() will do the marker + * dance - no reason to repeat here! + */ +#if 0 + /* Issue marker command. */ + ha->flags.reset_marker = 0; for (bus = 0; bus < ha->ports; bus++) { - if (! - (status = - qla1280_enable_tgt(ha, bus))) { - for (cnt = 0; cnt < MAX_LUNS; - cnt++) { - /* qla1280_enable_lun(ha, bus, cnt); */ - qla1280_poll(ha); - } - } else - break; - } - - if (!status) { - /* Enable ISP interrupts. */ - qla1280_enable_intrs(ha); - ha->flags.abort_isp_active = FALSE; - /* Restart queues that may have been stopped. */ - qla1280_restart_queues(ha); + ha->bus_settings[bus]. + reset_marker = 0; + qla1280_marker(ha, bus, 0, 0, + MK_SYNC_ALL); } +#endif + ha->flags.abort_isp_active = 0; } } } @@ -5669,8 +4787,6 @@ qla1280_abort_isp(struct scsi_qla_host *ha) printk(KERN_WARNING "qla1280: ISP error recovery failed, board disabled"); qla1280_reset_adapter(ha); - qla1280_abort_queues(ha); - dprintk(2, "qla1280_abort_isp: **** FAILED ****\n"); } @@ -5678,86 +4794,6 @@ qla1280_abort_isp(struct scsi_qla_host *ha) return status; } -/* - * qla1280_restart_queues - * Restart all device queues. - * - * Input: - * ha = adapter block pointer. - */ -static void -qla1280_restart_queues(struct scsi_qla_host *ha) -{ - scsi_lu_t *q; - int bus, target, lun; - - ENTER("qla1280_restart_queues"); - - for (bus = 0; bus < ha->ports; bus++) - for (target = 0; target < MAX_TARGETS; target++) - for (lun = 0; lun < MAX_LUNS; lun++) { - q = LU_Q(ha, bus, target, lun); - if (q != NULL) { - if (q->q_first) - qla1280_next(ha, q, bus); - } - } - dprintk(3, "qla1280_restart_queues: exiting normally\n"); -} - -/* - * qla1280_abort_queue_single - * Abort all commands on a device queues. - * - * Input: - * ha = adapter block pointer. - */ -static void -qla1280_abort_queue_single(struct scsi_qla_host *ha, int bus, - int target, int lun, uint32_t stat) -{ - scsi_lu_t *q; - srb_t *sp, *sp_next; - - ENTER("qla1280_abort_queue_single"); - q = LU_Q(ha, bus, target, lun); - if (q != NULL) { - sp = q->q_first; - q->q_first = q->q_last = NULL; - - while (sp) { - sp_next = sp->s_next; - CMD_RESULT(sp->cmd) = stat; - qla1280_done_q_put(sp, &ha->done_q_first, - &ha->done_q_last); - sp = sp_next; - } - } - LEAVE("qla1280_abort_queue_single"); -} - -/* - * qla1280_abort_queues - * Abort all commands on device queues. - * - * Input: - * ha = adapter block pointer. - */ -static void -qla1280_abort_queues(struct scsi_qla_host *ha) -{ - uint32_t bus, target, lun; - - ENTER("qla1280_abort_queues"); - - for (bus = 0; bus < ha->ports; bus++) - for (target = 0; target < MAX_TARGETS; target++) - for (lun = 0; lun < MAX_LUNS; lun++) - qla1280_abort_queue_single(ha, bus, target, - lun, DID_RESET); - - LEAVE("qla1280_abort_queues"); -} /* * qla1280_debounce_register @@ -5790,27 +4826,11 @@ qla1280_debounce_register(volatile u16 * addr) return ret; } -static Scsi_Host_Template driver_template = { - .proc_info = qla1280_proc_info, - .name = "Qlogic ISP 1280/12160", - .detect = qla1280_detect, - .release = qla1280_release, - .info = qla1280_info, - .queuecommand = qla1280_queuecommand, - .eh_abort_handler = qla1280_eh_abort, - .eh_device_reset_handler = qla1280_eh_device_reset, - .eh_bus_reset_handler = qla1280_eh_bus_reset, - .eh_host_reset_handler = qla1280_eh_adapter_reset, - .slave_configure = qla1280_slave_configure, - .bios_param = qla1280_biosparam, - .can_queue = 255, - .this_id = -1, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 3, - .use_clustering = ENABLE_CLUSTERING, \ -}; + +static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; #include "scsi_module.c" + /************************************************************************ * qla1280_check_for_dead_scsi_bus * * * @@ -5823,18 +4843,7 @@ qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus) { uint16_t config_reg, scsi_control; struct device_reg *reg = ha->iobase; -#if 0 - unsigned int bus; - Scsi_Cmnd *cp; - /* - * If SCSI Bus is Dead because of bad termination, - * we will return a status of Selection timeout. - */ - - cp = sp->cmd; - bus = SCSI_BUS_32(cp); -#endif if (ha->bus_settings[bus].scsi_bus_dead) { WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); config_reg = RD_REG_WORD(®->cfg_1); @@ -5844,218 +4853,82 @@ qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus) WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); if (scsi_control == SCSI_PHASE_INVALID) { - ha->bus_settings[bus].scsi_bus_dead = TRUE; + ha->bus_settings[bus].scsi_bus_dead = 1; #if 0 CMD_RESULT(cp) = DID_NO_CONNECT << 16; - CMD_HANDLE(cp) = NULL; + CMD_HANDLE(cp) = INVALID_HANDLE; /* ha->actthreads--; */ (*(cp)->scsi_done)(cp); #endif - return TRUE; /* bus is dead */ + return 1; /* bus is dead */ } else { - ha->bus_settings[bus].scsi_bus_dead = FALSE; + ha->bus_settings[bus].scsi_bus_dead = 0; ha->bus_settings[bus].failed_reset_count = 0; } } - return FALSE; /* bus is not dead */ + return 0; /* bus is not dead */ } static void -qla12160_get_target_parameters(struct scsi_qla_host *ha, uint32_t bus, - uint32_t target, uint32_t lun) +qla12160_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device) { uint16_t mb[MAILBOX_REGISTER_COUNT]; + int bus, target, lun; + + bus = device->channel; + target = device->id; + lun = device->lun; + mb[0] = MBC_GET_TARGET_PARAMETERS; mb[1] = (uint16_t) (bus ? target | BIT_7 : target); mb[1] <<= 8; qla1280_mailbox_command(ha, BIT_6 | BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]); - if (mb[3] != 0) { - printk(KERN_INFO - "scsi(%ld:%d:%d:%d): Synchronous transfer at period " - "%d, offset %d. \n", ha->host_no, bus, target, lun, - (mb[3] & 0xff), (mb[3] >> 8)); - } - - if ((mb[2] & BIT_5) && ((mb[6] >> 8) & 0xff) >= 2) { - printk(KERN_INFO - "scsi(%ld:%d:%d:%d): Dual Transition enabled.\n", - ha->host_no, bus, target, lun); - } -} - -#ifdef QL_DEBUG_ROUTINES -/****************************************************************************/ -/* Driver Debug Functions. */ -/****************************************************************************/ - -/* - * Get byte from I/O port - */ -static u8 -qla1280_getbyte (u8 * port) -{ - u8 ret; -#if MEMORY_MAPPED_IO - ret = readb((unsigned long) port); -#else - ret = inb((unsigned long) port); -#endif - - if (ql_debug_print) - printk(KERN_DEBUG - "qla1280_getbyte: address = 0x%p, data = 0x%x", port, - ret); - - return ret; -} - -/* - * Get word from I/O port - */ -static u16 -qla1280_getword (u16 * port) -{ - u16 ret; - -#if MEMORY_MAPPED_IO - ret = readw(unsigned long) port; -#else - ret = inw((unsigned long) port); -#endif - - if (ql_debug_print) - printk(KERN_DEBUG - "qla1280_getbyte: address = 0x%p, data = 0x%x", port, - ret); - - return ret; -} - -/* - * Get double word from I/O port - */ -static u32 -qla1280_getdword (u32 * port) -{ - u32 ret; + printk(KERN_INFO "scsi(%li:%d:%d:%d):", ha->host_no, bus, target, lun); -#if MEMORY_MAPPED_IO - ret = readl((unsigned long) port); -#else - ret = inl((unsigned long) port); -#endif - - if (ql_debug_print) - printk(KERN_DEBUG - "qla1280_getbyte: address = 0x%p, data = 0x%x", port, - ret); - - return ret; -} - -/* - * Send byte to I/O port - */ -static void -qla1280_putbyte(u8 * port, u8 data) -{ -#if MEMORY_MAPPED_IO - writeb(data, (unsigned long) port); -#else - outb(data, (unsigned long) port); -#endif - - if (ql_debug_print) - printk(KERN_DEBUG - "qla1280_getbyte: address = 0x%p, data = 0x%x", port, - data); -} - -/* - * Send word to I/O port - */ -static void -qla1280_putword(u16 * port, u16 data) -{ -#if MEMORY_MAPPED_IO - writew(data, (unsigned long) port); -#else - outw(data, (unsigned long) port); -#endif - - if (ql_debug_print) - printk(KERN_DEBUG - "qla1280_getbyte: address = 0x%p, data = 0x%x", port, - data); -} - -/* - * Send double word to I/O port - */ -static void -qla1280_putdword(u32 * port, u32 data) -{ -#if MEMORY_MAPPED_IO - writel(data, (unsigned long) port); -#else - outl(data, (unsigned long) port); -#endif + if (mb[3] != 0) { + printk(" Sync: period %d, offset %d", + (mb[3] & 0xff), (mb[3] >> 8)); + if (mb[2] & BIT_13) + printk(", Wide"); + if ((mb[2] & BIT_5) && ((mb[6] >> 8) & 0xff) >= 2) + printk(", DT"); + } else + printk(" Async"); - if (ql_debug_print) - printk(KERN_DEBUG - "qla1280_getbyte: address = 0x%p, data = 0x%x", port, - data); + if (device->tagged_queue) + printk(", Tagged queuing: depth %d", device->queue_depth); + printk("\n"); } -/* - * Dummy function to prevent warnings for - * declared and unused debug functions - */ -static void -qla1280_debug(void) -{ - qla1280_getbyte(0); - qla1280_getword(0); - qla1280_getdword(0); - qla1280_putbyte(0, 0); - qla1280_putword(0, 0); - qla1280_putdword(0, 0); -} +#if DEBUG_QLA1280 static void __qla1280_dump_buffer(char *b, int size) { int cnt; u8 c; - if (ql_debug_print) { - printk(KERN_DEBUG - " 0 1 2 3 4 5 6 7 8 9 Ah " - "Bh Ch Dh Eh Fh\n"); - printk(KERN_DEBUG - "---------------------------------------------" - "------------------\n"); - - for (cnt = 0; cnt < size;) { - c = *b++; - if (c < 16) - printk(' '); - printk("0x%x", c); - cnt++; - if (!(cnt % 16)) - printk("\n"); - else if (c < 10) - printk(" "); - else - printk(' '); - } - if (cnt % 16) + printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 Ah " + "Bh Ch Dh Eh Fh\n"); + printk(KERN_DEBUG "---------------------------------------------" + "------------------\n"); + + for (cnt = 0; cnt < size;) { + c = *b++; + + printk("0x%02x", c); + cnt++; + if (!(cnt % 16)) printk("\n"); + else + printk(" "); } + if (cnt % 16) + printk("\n"); } /************************************************************************** @@ -6063,20 +4936,21 @@ __qla1280_dump_buffer(char *b, int size) * **************************************************************************/ static void -qla1280_print_scsi_cmd(Scsi_Cmnd * cmd) +__qla1280_print_scsi_cmd(Scsi_Cmnd * cmd) { struct scsi_qla_host *ha; - struct Scsi_Host *host = cmd->host; - srb_t *sp; + struct Scsi_Host *host = CMD_HOST(cmd); + struct srb *sp; /* struct scatterlist *sg; */ int i; ha = (struct scsi_qla_host *)host->hostdata; - sp = (srb_t *)CMD_SP(cmd); + sp = (struct srb *)CMD_SP(cmd); printk("SCSI Command @= 0x%p, Handle=0x%p\n", cmd, CMD_HANDLE(cmd)); printk(" chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", - cmd->channel, cmd->target, cmd->lun, cmd->cmd_len); + SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd), + CMD_CDBLEN(cmd)); printk(" CDB = "); for (i = 0; i < cmd->cmd_len; i++) { printk("0x%02x ", cmd->cmnd[i]); @@ -6093,8 +4967,8 @@ qla1280_print_scsi_cmd(Scsi_Cmnd * cmd) printk(" tag=%d, flags=0x%x, transfersize=0x%x \n", cmd->tag, cmd->flags, cmd->transfersize); printk(" Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd)); - printk(" underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n", - cmd->underflow, sp->dir, cmd->request->cmd); + printk(" underflow size = 0x%x, direction=0x%x\n", + cmd->underflow, sp->dir); } /************************************************************************** @@ -6106,104 +4980,139 @@ ql1280_dump_device(struct scsi_qla_host *ha) { Scsi_Cmnd *cp; - srb_t *sp; + struct srb *sp; int i; - if (ql_debug_print) { - printk(KERN_DEBUG "Outstanding Commands on controller:\n"); - for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) { - if ((sp = ha->outstanding_cmds[i]) == NULL) - continue; - if ((cp = sp->cmd) == NULL) - continue; - qla1280_print_scsi_cmd(1, cp); - } + printk(KERN_DEBUG "Outstanding Commands on controller:\n"); + + for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) { + if ((sp = ha->outstanding_cmds[i]) == NULL) + continue; + if ((cp = sp->cmd) == NULL) + continue; + qla1280_print_scsi_cmd(1, cp); } } #endif -#if STOP_ON_ERROR -/************************************************************************** - * ql1280_panic - * - **************************************************************************/ -static void -qla1280_panic(char *cp, struct Scsi_Host *host) + +enum tokens { + TOKEN_NVRAM, + TOKEN_SYNC, + TOKEN_WIDE, + TOKEN_PPR, + TOKEN_VERBOSE, + TOKEN_DEBUG, +}; + +struct setup_tokens { + char *token; + int val; +}; + +static struct setup_tokens setup_token[] __initdata = { - struct scsi_qla_host *ha; - long *fp; + { "nvram", TOKEN_NVRAM }, + { "sync", TOKEN_SYNC }, + { "wide", TOKEN_WIDE }, + { "ppr", TOKEN_PPR }, + { "verbose", TOKEN_VERBOSE }, + { "debug", TOKEN_DEBUG }, +}; - ha = (struct scsi_qla_host *)host->hostdata; - printk(KERN_ERR "qla1280 - PANIC: %s\n", cp); - printk(KERN_ERR "Current time=0x%lx\n", jiffies); - printk(KERN_ERR "Number of pending commands =0x%lx\n", ha->actthreads); - printk(KERN_ERR "Number of SCSI queued commands =0x%lx\n", - ha->qthreads); - printk(KERN_ERR "Number of free entries = (%d)\n", ha->req_q_cnt); - printk(KERN_ERR "Request Queue @ 0x%lx, Response Queue @ 0x%lx\n", - ha->request_dma, ha->response_dma); - printk(KERN_ERR "Request In Ptr %d\n", ha->req_ring_index); - fp = (long *) &ha->flags; - printk(KERN_ERR "HA flags =0x%lx\n", *fp); - if (ql_debug_level >= 2) { - ql_debug_print = 1; -#if 0 - ql1280_dump_device((struct scsi_qla_host *)host->hostdata); -#endif - } - sti(); - panic("Ooops"); - /* cli(); - for(;;) - { - barrier(); - sti(); - } - */ -} -#endif -#ifdef MODULE /************************************************************************** * qla1280_setup * - * Handle Linux boot parameters. This routine allows for assigning a value - * to a parameter with a ':' between the parameter and the value. - * ie. qla1280=max_reqs:0x0A,verbose + * Handle boot parameters. This really needs to be changed so one + * can specify per adapter parameters. **************************************************************************/ -void -qla1280_setup(char *s, int *dummy) +int __init +qla1280_setup(char *s) { - char *end, *str, *cp; - - printk(KERN_INFO "scsi: Processing Option str = %s\n", s); - end = strchr (s, '\0'); - /* locate command */ - str = s; - for (cp = s; *cp && cp != end; cp++) { - cp = qla1280_get_token(cp, str); - printk(KERN_INFO "scsi: token str = %s\n", str); - /* if found execute routine */ + char *cp, *ptr; + unsigned long val; + int toke; + + cp = s; + + while (cp && (ptr = strchr(cp, ':'))) { + ptr++; + if (!strcmp(ptr, "yes")) { + val = 0x10000; + ptr += 3; + } else if (!strcmp(ptr, "no")) { + val = 0; + ptr += 2; + } else + val = simple_strtoul(ptr, &ptr, 0); + + switch ((toke = qla1280_get_token(cp))) { + case TOKEN_NVRAM: + if (!val) + driver_setup.no_nvram = 1; + break; + case TOKEN_SYNC: + if (!val) + driver_setup.no_sync = 1; + else if (val != 0x10000) + driver_setup.sync_mask = val; + break; + case TOKEN_WIDE: + if (!val) + driver_setup.no_wide = 1; + else if (val != 0x10000) + driver_setup.wide_mask = val; + break; + case TOKEN_PPR: + if (!val) + driver_setup.no_ppr = 1; + else if (val != 0x10000) + driver_setup.ppr_mask = val; + break; + case TOKEN_VERBOSE: + qla1280_verbose = val; + break; + default: + printk(KERN_INFO "qla1280: unknown boot option %s\n", + cp); + } + + cp = strchr(ptr, ';'); + if (cp) + cp++; + else { + break; + } } + return 1; } -static char * -qla1280_get_token(char *cmdline, char *str) + +static int +qla1280_get_token(char *str) { - register char *cp = cmdline; - - /* skip preceeding spaces */ - while (strchr (cp, ' ')) - ++cp; - /* symbol starts here */ - str = cp; - /* skip char if not a space or : */ - while (*cp && !(strchr (cp, ' ') || strchr (cp, ':'))) - cp++; - *cp = '\0'; - return cp; + char *sep; + long ret = -1; + int i, len; + + len = sizeof(setup_token)/sizeof(struct setup_tokens); + + sep = strchr(str, ':'); + + if (sep) { + for (i = 0; i < len; i++){ + + if (!strncmp(setup_token[i].token, str, (sep - str))) { + ret = setup_token[i].val; + break; + } + } + } + + return ret; } -#endif + /* * Overrides for Emacs so that we almost follow Linus's tabbing style. diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h index 103200cb25ed..177107d31976 100644 --- a/drivers/scsi/qla1280.h +++ b/drivers/scsi/qla1280.h @@ -21,18 +21,6 @@ #define _IO_HBA_QLA1280_H /* subject to change without notice */ #ifndef HOSTS_C /* included in hosts.c */ -/* - * Enable define statement to ignore Data Underrun Errors, - * remove define statement to enable detection. - */ -/* #define DATA_UNDERRUN_ERROR_DISABLE */ - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif /* * Data bit definitions. @@ -70,48 +58,13 @@ #define BIT_30 0x40000000 #define BIT_31 0x80000000 -/* - * Local Macro Definitions. - */ -#if defined(QL_DEBUG_LEVEL_1) || defined(QL_DEBUG_LEVEL_2) || \ - defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \ - defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \ - defined(QL_DEBUG_LEVEL_7) -#define QL_DEBUG_ROUTINES -#endif - -/* - * I/O port macros -*/ -/* #define MEMORY_MAPPED_IO *//* Enable memory mapped I/O */ -#undef MEMORY_MAPPED_IO /* Disable memory mapped I/O */ - -#ifdef QL_DEBUG_LEVEL_1 -#define RD_REG_BYTE(addr) qla1280_getbyte((u8 *)addr) -#define RD_REG_WORD(addr) qla1280_getword((u16 *)addr) -#define RD_REG_DWORD(addr) qla1280_getdword((u32 *)addr) -#define WRT_REG_BYTE(addr, data) qla1280_putbyte((u8 *)addr, data) -#define WRT_REG_WORD(addr, data) qla1280_putword((u16 *)addr, data) -#define WRT_REG_DWORD(addr, data) qla1280_putdword((u32 *)addr, data) -#else /* QL_DEBUG_LEVEL_1 */ - -#ifdef MEMORY_MAPPED_IO -#define RD_REG_BYTE(addr) readb(addr) +#if MEMORY_MAPPED_IO #define RD_REG_WORD(addr) readw(addr) -#define RD_REG_DWORD(addr) readl(addr) -#define WRT_REG_BYTE(addr, data) writeb(data, addr) #define WRT_REG_WORD(addr, data) writew(data, addr) -#define WRT_REG_DWORD(addr, data) writel(data, addr) #else /* MEMORY_MAPPED_IO */ -#define RD_REG_BYTE(addr) inb((unsigned long)addr) #define RD_REG_WORD(addr) inw((unsigned long)addr) -#define RD_REG_DWORD(addr) inl((unsigned long)addr) -/* Parameters are reversed in Linux */ -#define WRT_REG_BYTE(addr, data) outb(data, (unsigned long)addr) #define WRT_REG_WORD(addr, data) outw(data, (unsigned long)addr) -#define WRT_REG_DWORD(addr, data) outl(data, (unsigned long)addr) #endif /* MEMORY_MAPPED_IO */ -#endif /* QL_DEBUG_LEVEL_1 */ /* * Host adapter default definitions. @@ -133,16 +86,14 @@ /* Command retry count (0-65535) */ #define COMMAND_RETRY_COUNT 255 -/* Maximum outstanding commands in ISP queues (1-65535) */ +/* Maximum outstanding commands in ISP queues */ #define MAX_OUTSTANDING_COMMANDS 512 +#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 2) /* ISP request and response entry counts (37-65535) */ #define REQUEST_ENTRY_CNT 256 /* Number of request entries. */ #define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */ -/* Maximum equipage per controller */ -#define MAX_EQ (MAX_BUSES * MAX_TARGETS * MAX_LUNS) - /* Number of segments 1 - 65535 */ #define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ @@ -150,20 +101,20 @@ * SCSI Request Block structure (sp) that is placed * on cmd->SCp location of every I/O */ -typedef struct srb { +struct srb { Scsi_Cmnd *cmd; /* (4/8) SCSI command block */ struct srb *s_next; /* (4/8) Next block on LU queue */ struct srb *s_prev; /* (4/8) Previous block on LU queue */ uint8_t flags; /* (1) Status flags. */ uint8_t dir; /* direction of transfer */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) + /* + * This should be moved around to save space. + */ dma_addr_t saved_dma_handle; /* for unmap of single transfers */ /* NOTE: the sp->cmd will be NULL when this completion is * called, so you should know the scsi_cmnd when using this */ struct completion *wait; -#endif - -} srb_t; +}; /* * SRB flag definitions @@ -176,9 +127,9 @@ typedef struct srb { /* * Logical Unit Queue structure */ -typedef struct scsi_lu { - srb_t *q_first; /* First block on LU queue */ - srb_t *q_last; /* Last block on LU queue */ +struct scsi_lu { + struct srb *q_first; /* First block on LU queue */ + struct srb *q_last; /* Last block on LU queue */ uint8_t q_flag; /* LU queue state flags */ uint8_t q_sense[16]; /* sense data */ unsigned long io_cnt; /* total xfer count */ @@ -187,12 +138,7 @@ typedef struct scsi_lu { unsigned long w_cnt; /* total writes */ unsigned long r_cnt; /* total reads */ uint16_t q_outcnt; /* Pending jobs for this LU */ -#if QL1280_TARGET_MODE_SUPPORT - void (*q_func)(); /* Target driver event handler */ - int32_t q_param; /* Target driver event param */ - uint8_t q_lock; /* Device Queue Lock */ -#endif -} scsi_lu_t; +}; /* * Logical Unit flags @@ -317,44 +263,47 @@ struct device_reg { /* * ISP mailbox commands */ -#define MBC_NOP 0 /* No Operation. */ -#define MBC_LOAD_RAM 1 /* Load RAM. */ -#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware. */ -#define MBC_DUMP_RAM 3 /* Dump RAM contents */ -#define MBC_WRITE_RAM_WORD 4 /* Write ram word. */ -#define MBC_READ_RAM_WORD 5 /* Read ram word. */ -#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */ -#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum. */ -#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision. */ -#define MBC_INIT_REQUEST_QUEUE 0x10 /* Initialize request queue. */ -#define MBC_INIT_RESPONSE_QUEUE 0x11 /* Initialize response queue. */ -#define MBC_EXECUTE_IOCB 0x12 /* Execute IOCB command. */ -#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command. */ -#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN). */ -#define MBC_ABORT_TARGET 0x17 /* Abort target (ID). */ -#define MBC_BUS_RESET 0x18 /* SCSI bus reset. */ -#define MBC_GET_RETRY_COUNT 0x22 /* Get retry count and delay. */ -#define MBC_GET_TARGET_PARAMETERS 0x28 /* Get target parameters. */ -#define MBC_SET_INITIATOR_ID 0x30 /* Set initiator SCSI ID. */ -#define MBC_SET_SELECTION_TIMEOUT 0x31 /* Set selection timeout. */ -#define MBC_SET_RETRY_COUNT 0x32 /* Set retry count and delay. */ -#define MBC_SET_TAG_AGE_LIMIT 0x33 /* Set tag age limit. */ -#define MBC_SET_CLOCK_RATE 0x34 /* Set clock rate. */ -#define MBC_SET_ACTIVE_NEGATION 0x35 /* Set active negation state. */ -#define MBC_SET_ASYNC_DATA_SETUP 0x36 /* Set async data setup time. */ -#define MBC_SET_PCI_CONTROL 0x37 /* Set BUS control parameters. */ -#define MBC_SET_TARGET_PARAMETERS 0x38 /* Set target parameters. */ -#define MBC_SET_DEVICE_QUEUE 0x39 /* Set device queue parameters */ -#define MBC_SET_SYSTEM_PARAMETER 0x45 /* Set system parameter word. */ -#define MBC_SET_FIRMWARE_FEATURES 0x4A /* Set firmware feature word. */ -#define MBC_INIT_REQUEST_QUEUE_A64 0x52 /* Initialize request queue A64 */ -#define MBC_INIT_RESPONSE_QUEUE_A64 0x53 /* Initialize response q A64. */ -#define MBC_ENABLE_TARGET_MODE 0x55 /* Enable target mode. */ +#define MBC_NOP 0 /* No Operation */ +#define MBC_LOAD_RAM 1 /* Load RAM */ +#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware */ +#define MBC_DUMP_RAM 3 /* Dump RAM contents */ +#define MBC_WRITE_RAM_WORD 4 /* Write ram word */ +#define MBC_READ_RAM_WORD 5 /* Read ram word */ +#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */ +#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum */ +#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision */ +#define MBC_INIT_REQUEST_QUEUE 0x10 /* Initialize request queue */ +#define MBC_INIT_RESPONSE_QUEUE 0x11 /* Initialize response queue */ +#define MBC_EXECUTE_IOCB 0x12 /* Execute IOCB command */ +#define MBC_ABORT_COMMAND 0x15 /* Abort IOCB command */ +#define MBC_ABORT_DEVICE 0x16 /* Abort device (ID/LUN) */ +#define MBC_ABORT_TARGET 0x17 /* Abort target (ID) */ +#define MBC_BUS_RESET 0x18 /* SCSI bus reset */ +#define MBC_GET_RETRY_COUNT 0x22 /* Get retry count and delay */ +#define MBC_GET_TARGET_PARAMETERS 0x28 /* Get target parameters */ +#define MBC_SET_INITIATOR_ID 0x30 /* Set initiator SCSI ID */ +#define MBC_SET_SELECTION_TIMEOUT 0x31 /* Set selection timeout */ +#define MBC_SET_RETRY_COUNT 0x32 /* Set retry count and delay */ +#define MBC_SET_TAG_AGE_LIMIT 0x33 /* Set tag age limit */ +#define MBC_SET_CLOCK_RATE 0x34 /* Set clock rate */ +#define MBC_SET_ACTIVE_NEGATION 0x35 /* Set active negation state */ +#define MBC_SET_ASYNC_DATA_SETUP 0x36 /* Set async data setup time */ +#define MBC_SET_PCI_CONTROL 0x37 /* Set BUS control parameters */ +#define MBC_SET_TARGET_PARAMETERS 0x38 /* Set target parameters */ +#define MBC_SET_DEVICE_QUEUE 0x39 /* Set device queue parameters */ +#define MBC_SET_RESET_DELAY_PARAMETERS 0x3A /* Set reset delay parameters */ +#define MBC_SET_SYSTEM_PARAMETER 0x45 /* Set system parameter word */ +#define MBC_SET_FIRMWARE_FEATURES 0x4A /* Set firmware feature word */ +#define MBC_INIT_REQUEST_QUEUE_A64 0x52 /* Initialize request queue A64 */ +#define MBC_INIT_RESPONSE_QUEUE_A64 0x53 /* Initialize response q A64 */ +#define MBC_ENABLE_TARGET_MODE 0x55 /* Enable target mode */ +#define MBC_SET_DATA_OVERRUN_RECOVERY 0x5A /* Set data overrun recovery mode */ /* * ISP Get/Set Target Parameters mailbox command control flags. */ -#define TP_RENEGOTIATE BIT_8 /* Renegotiate on error. */ +#define TP_PPR BIT_5 /* PPR */ +#define TP_RENEGOTIATE BIT_8 /* Renegotiate on error. */ #define TP_STOP_QUEUE BIT_9 /* Stop que on check condition */ #define TP_AUTO_REQUEST_SENSE BIT_10 /* Automatic request sense. */ #define TP_TAGGED_QUEUE BIT_11 /* Tagged queuing. */ @@ -374,167 +323,9 @@ struct device_reg { #define NV_DELAY_COUNT 10 /* - * QLogic ISP1280 NVRAM structure definition. - * - * NOTE: the firmware structure is byte reversed on big-endian systems - * because it is read a word at a time from the chip, so the in-memory - * representation becomes correct + * QLogic ISP1280/ISP12160 NVRAM structure definition. */ -typedef struct { -#if defined(__BIG_ENDIAN) - uint8_t id1; /* 1 */ - uint8_t id0; /* 0 */ - - uint8_t id3; /* 3 */ - uint8_t id2; /* 2 */ - - struct { - uint8_t bios_configuration_mode:2; - uint8_t bios_disable:1; - uint8_t selectable_scsi_boot_enable:1; - uint8_t cd_rom_boot_enable:1; - uint8_t disable_loading_risc_code:1; - uint8_t enable_64bit_addressing:1; - uint8_t unused_7:1; - } cntr_flags_1; /* 5 */ - uint8_t version; /* 4 */ - - struct { - uint8_t boot_lun_number:5; - uint8_t scsi_bus_number:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - uint8_t boot_target_number:4; - uint8_t unused_12:1; - uint8_t unused_13:1; - uint8_t unused_14:1; - uint8_t unused_15:1; - } cntr_flags_2; /* 6, 7 */ - - uint16_t unused_8; /* 8, 9 */ - uint16_t unused_10; /* 10, 11 */ - uint16_t unused_12; /* 12, 13 */ - uint16_t unused_14; /* 14, 15 */ - - /* Termination - * 0 = Disable, 1 = high only, 3 = Auto term - */ - union { - uint8_t c; - struct { - uint8_t scsi_bus_1_control:2; - uint8_t scsi_bus_0_control:2; - uint8_t unused_0:1; - uint8_t unused_1:1; - uint8_t unused_2:1; - uint8_t auto_term_support:1; - } f; - } termination; /* 17 */ - union { - uint8_t c; - struct { - uint8_t reserved:2; - uint8_t burst_enable:1; - uint8_t reserved_1:1; - uint8_t fifo_threshold:4; - } f; - } isp_config; /* 16 */ - - - uint16_t isp_parameter; /* 18, 19 */ - - union { - uint16_t w; - struct { - uint16_t enable_fast_posting:1; - uint16_t report_lvd_bus_transition:1; - uint16_t unused_2:1; - uint16_t unused_3:1; - uint16_t unused_4:1; - uint16_t unused_5:1; - uint16_t unused_6:1; - uint16_t unused_7:1; - uint16_t unused_8:1; - uint16_t unused_9:1; - uint16_t unused_10:1; - uint16_t unused_11:1; - uint16_t unused_12:1; - uint16_t unused_13:1; - uint16_t unused_14:1; - uint16_t unused_15:1; - } f; - } firmware_feature; /* 20, 21 */ - - uint16_t unused_22; /* 22, 23 */ - - struct { - uint8_t bus_reset_delay; /* 25 */ - struct { - uint8_t initiator_id:4; - uint8_t scsi_reset_disable:1; - uint8_t scsi_bus_size:1; - uint8_t scsi_bus_type:1; - uint8_t unused_7:1; - } config_1; /* 24 */ - - uint8_t retry_delay; /* 27 */ - uint8_t retry_count; /* 26 */ - - uint8_t unused_29; /* 29 */ - struct { - uint8_t async_data_setup_time:4; - uint8_t req_ack_active_negation:1; - uint8_t data_line_active_negation:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } config_2; /* 28 */ - - - uint16_t selection_timeout; /* 30, 31 */ - uint16_t max_queue_depth; /* 32, 33 */ - - uint16_t unused_34; /* 34, 35 */ - uint16_t unused_36; /* 36, 37 */ - uint16_t unused_38; /* 38, 39 */ - - struct { - uint8_t execution_throttle; /* 41 */ - union { - uint8_t c; - struct { - uint8_t renegotiate_on_error:1; - uint8_t stop_queue_on_check:1; - uint8_t auto_request_sense:1; - uint8_t tag_queuing:1; - uint8_t sync_data_transfers:1; - uint8_t wide_data_transfers:1; - uint8_t parity_checking:1; - uint8_t disconnect_allowed:1; - } f; - } parameter; /* 40 */ - - struct { - uint8_t sync_offset:4; - uint8_t device_enable:1; - uint8_t lun_disable:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } flags; /* 43 */ - uint8_t sync_period; /* 42 */ - - - uint16_t unused_44; /* 44, 45 */ - } target[MAX_TARGETS]; - } bus[MAX_BUSES]; - - uint16_t unused_248; /* 248, 249 */ - - uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ - - uint8_t chksum; /* 255 */ - uint8_t unused_254; /* 254 */ - -#elif defined(__LITTLE_ENDIAN) +struct nvram { uint8_t id0; /* 0 */ uint8_t id1; /* 1 */ uint8_t id2; /* 2 */ @@ -552,174 +343,6 @@ typedef struct { } cntr_flags_1; /* 5 */ struct { - uint8_t boot_lun_number:5; - uint8_t scsi_bus_number:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - uint8_t boot_target_number:4; - uint8_t unused_12:1; - uint8_t unused_13:1; - uint8_t unused_14:1; - uint8_t unused_15:1; - } cntr_flags_2; /* 6, 7 */ - - uint16_t unused_8; /* 8, 9 */ - uint16_t unused_10; /* 10, 11 */ - uint16_t unused_12; /* 12, 13 */ - uint16_t unused_14; /* 14, 15 */ - - union { - uint8_t c; - struct { - uint8_t reserved:2; - uint8_t burst_enable:1; - uint8_t reserved_1:1; - uint8_t fifo_threshold:4; - } f; - } isp_config; /* 16 */ - - /* Termination - * 0 = Disable, 1 = high only, 3 = Auto term - */ - union { - uint8_t c; - struct { - uint8_t scsi_bus_1_control:2; - uint8_t scsi_bus_0_control:2; - uint8_t unused_0:1; - uint8_t unused_1:1; - uint8_t unused_2:1; - uint8_t auto_term_support:1; - } f; - } termination; /* 17 */ - - uint16_t isp_parameter; /* 18, 19 */ - - union { - uint16_t w; - struct { - uint8_t enable_fast_posting:1; - uint8_t report_lvd_bus_transition:1; - uint8_t unused_2:1; - uint8_t unused_3:1; - uint8_t unused_4:1; - uint8_t unused_5:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - uint8_t unused_8:1; - uint8_t unused_9:1; - uint8_t unused_10:1; - uint8_t unused_11:1; - uint8_t unused_12:1; - uint8_t unused_13:1; - uint8_t unused_14:1; - uint8_t unused_15:1; - } f; - } firmware_feature; /* 20, 21 */ - - uint16_t unused_22; /* 22, 23 */ - - struct { - struct { - uint8_t initiator_id:4; - uint8_t scsi_reset_disable:1; - uint8_t scsi_bus_size:1; - uint8_t scsi_bus_type:1; - uint8_t unused_7:1; - } config_1; /* 24 */ - - uint8_t bus_reset_delay; /* 25 */ - uint8_t retry_count; /* 26 */ - uint8_t retry_delay; /* 27 */ - - struct { - uint8_t async_data_setup_time:4; - uint8_t req_ack_active_negation:1; - uint8_t data_line_active_negation:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } config_2; /* 28 */ - - uint8_t unused_29; /* 29 */ - - uint16_t selection_timeout; /* 30, 31 */ - uint16_t max_queue_depth; /* 32, 33 */ - - uint16_t unused_34; /* 34, 35 */ - uint16_t unused_36; /* 36, 37 */ - uint16_t unused_38; /* 38, 39 */ - - struct { - union { - uint8_t c; - struct { - uint8_t renegotiate_on_error:1; - uint8_t stop_queue_on_check:1; - uint8_t auto_request_sense:1; - uint8_t tag_queuing:1; - uint8_t sync_data_transfers:1; - uint8_t wide_data_transfers:1; - uint8_t parity_checking:1; - uint8_t disconnect_allowed:1; - } f; - } parameter; /* 40 */ - - uint8_t execution_throttle; /* 41 */ - uint8_t sync_period; /* 42 */ - - struct { - uint8_t sync_offset:4; - uint8_t device_enable:1; - uint8_t lun_disable:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } flags; /* 43 */ - - uint16_t unused_44; /* 44, 45 */ - } target[MAX_TARGETS]; - } bus[MAX_BUSES]; - - uint16_t unused_248; /* 248, 249 */ - - uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ - - uint8_t unused_254; /* 254 */ - - uint8_t chksum; /* 255 */ -#else -#error neither __BIG_ENDIAN nor __LITTLE_ENDIAN is defined -#endif -} nvram_t; - -/* - * QLogic ISP12160 NVRAM structure definition. - * - * NOTE: the firmware structure is byte reversed on big-endian systems - * because it is read a word at a time from the chip, so the in-memory - * representation becomes correct - */ -typedef struct { -#if defined(__BIG_ENDIAN) - uint8_t id1; /* 1 */ - uint8_t id0; /* 0 */ - - uint8_t id3; /* 3 */ - uint8_t id2; /* 2 */ - - /* Host/Bios Flags */ - struct { - uint8_t bios_configuration_mode:2; - uint8_t bios_disable:1; - uint8_t selectable_scsi_boot_enable:1; - uint8_t cd_rom_boot_enable:1; - uint8_t disable_loading_risc_code:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } cntr_flags_1; /* 5 */ - uint8_t version; /* 4 */ - - /* Selectable Boot Support */ - struct { uint16_t boot_lun_number:5; uint16_t scsi_bus_number:1; uint16_t unused_6:1; @@ -736,167 +359,6 @@ typedef struct { uint16_t unused_12; /* 12, 13 */ uint16_t unused_14; /* 14, 15 */ - /* Termination - * 0 = Disable, 1 = high only, 3 = Auto term - */ - union { - uint8_t c; - struct { - uint8_t scsi_bus_1_control:2; - uint8_t scsi_bus_0_control:2; - uint8_t unused_0:1; - uint8_t unused_1:1; - uint8_t unused_2:1; - uint8_t auto_term_support:1; - } f; - } termination; /* 17 */ - /* Auto Term - 3 */ - /* High Only - 1 (GPIO2 = 1 & GPIO3 = 0) */ - /* Disable - 0 (GPIO2 = 0 & GPIO3 = X) */ - /* ISP Config Parameters */ - union { - uint8_t c; - struct { - uint8_t reserved:2; - uint8_t burst_enable:1; - uint8_t reserved_1:1; - uint8_t fifo_threshold:4; - } f; - } isp_config; /* 16 */ - - uint16_t isp_parameter; /* 18, 19 */ - - union { - uint16_t w; - struct { - uint16_t enable_fast_posting:1; - uint16_t report_lvd_bus_transition:1; - uint16_t unused_2:1; - uint16_t unused_3:1; - uint16_t unused_4:1; - uint16_t unused_5:1; - uint16_t unused_6:1; - uint16_t unused_7:1; - uint16_t unused_8:1; - uint16_t unused_9:1; - uint16_t unused_10:1; - uint16_t unused_11:1; - uint16_t unused_12:1; - uint16_t unused_13:1; - uint16_t unused_14:1; - uint16_t unused_15:1; - } f; - } firmware_feature; /* 20, 21 */ - - uint16_t unused_22; /* 22, 23 */ - - struct { - uint8_t bus_reset_delay; /* 25 */ - struct { - uint8_t initiator_id:4; - uint8_t scsi_reset_disable:1; - uint8_t scsi_bus_size:1; - uint8_t scsi_bus_type:1; - uint8_t unused_7:1; - } config_1; /* 24 */ - - uint8_t retry_delay; /* 27 */ - uint8_t retry_count; /* 26 */ - - uint8_t unused_29; /* 29 */ - /* Adapter Capabilities bits */ - struct { - uint8_t async_data_setup_time:4; - uint8_t req_ack_active_negation:1; - uint8_t data_line_active_negation:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } config_2; /* 28 */ - - uint16_t selection_timeout; /* 30, 31 */ - uint16_t max_queue_depth; /* 32, 33 */ - - uint16_t unused_34; /* 34, 35 */ - uint16_t unused_36; /* 36, 37 */ - uint16_t unused_38; /* 38, 39 */ - - struct { - uint8_t execution_throttle; /* 41 */ - union { - uint8_t c; - struct { - uint8_t renegotiate_on_error:1; - uint8_t stop_queue_on_check:1; - uint8_t auto_request_sense:1; - uint8_t tag_queuing:1; - uint8_t sync_data_transfers:1; - uint8_t wide_data_transfers:1; - uint8_t parity_checking:1; - uint8_t disconnect_allowed:1; - } f; - } parameter; /* 40 */ - - struct { - uint8_t sync_offset:5; - uint8_t device_enable:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } flags1; /* 43 */ - uint8_t sync_period; /* 42 */ - - uint8_t unused_45; /* 45 */ - struct { - uint8_t ppr_options:4; - uint8_t ppr_bus_width:2; - uint8_t unused_8:1; - uint8_t enable_ppr:1; - } flags2; /* 44 */ - - } target[MAX_TARGETS]; - } bus[MAX_BUSES]; - - uint16_t unused_248; /* 248, 249 */ - - uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ - - uint8_t chksum; /* 255 */ - uint8_t System_Id_Pointer; /* 254 */ - -#elif defined(__LITTLE_ENDIAN) - uint8_t id0; /* 0 */ - uint8_t id1; /* 1 */ - uint8_t id2; /* 2 */ - uint8_t id3; /* 3 */ - uint8_t version; /* 4 */ - /* Host/Bios Flags */ - struct { - uint8_t bios_configuration_mode:2; - uint8_t bios_disable:1; - uint8_t selectable_scsi_boot_enable:1; - uint8_t cd_rom_boot_enable:1; - uint8_t disable_loading_risc_code:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } cntr_flags_1; /* 5 */ - /* Selectable Boot Support */ - struct { - uint16_t boot_lun_number:5; - uint16_t scsi_bus_number:1; - uint16_t unused_6:1; - uint16_t unused_7:1; - uint16_t boot_target_number:4; - uint16_t unused_12:1; - uint16_t unused_13:1; - uint16_t unused_14:1; - uint16_t unused_15:1; - } cntr_flags_2; /* 6, 7 */ - - uint16_t unused_8; /* 8, 9 */ - uint16_t unused_10; /* 10, 11 */ - uint16_t unused_12; /* 12, 13 */ - uint16_t unused_14; /* 14, 15 */ - - /* ISP Config Parameters */ union { uint8_t c; struct { @@ -921,9 +383,6 @@ typedef struct { uint8_t auto_term_support:1; } f; } termination; /* 17 */ - /* Auto Term - 3 */ - /* High Only - 1 (GPIO2 = 1 & GPIO3 = 0) */ - /* Disable - 0 (GPIO2 = 0 & GPIO3 = X) */ uint16_t isp_parameter; /* 18, 19 */ @@ -934,11 +393,11 @@ typedef struct { uint16_t report_lvd_bus_transition:1; uint16_t unused_2:1; uint16_t unused_3:1; - uint16_t unused_4:1; - uint16_t unused_5:1; + uint16_t disable_iosbs_with_bus_reset_status:1; + uint16_t disable_synchronous_backoff:1; uint16_t unused_6:1; - uint16_t unused_7:1; - uint16_t unused_8:1; + uint16_t synchronous_backoff_reporting:1; + uint16_t disable_reselection_fairness:1; uint16_t unused_9:1; uint16_t unused_10:1; uint16_t unused_11:1; @@ -963,7 +422,7 @@ typedef struct { uint8_t bus_reset_delay; /* 25 */ uint8_t retry_count; /* 26 */ uint8_t retry_delay; /* 27 */ - /* Adapter Capabilities bits */ + struct { uint8_t async_data_setup_time:4; uint8_t req_ack_active_negation:1; @@ -989,8 +448,8 @@ typedef struct { uint8_t stop_queue_on_check:1; uint8_t auto_request_sense:1; uint8_t tag_queuing:1; - uint8_t sync_data_transfers:1; - uint8_t wide_data_transfers:1; + uint8_t enable_sync:1; + uint8_t enable_wide:1; uint8_t parity_checking:1; uint8_t disconnect_allowed:1; } f; @@ -999,20 +458,31 @@ typedef struct { uint8_t execution_throttle; /* 41 */ uint8_t sync_period; /* 42 */ - struct { - uint8_t sync_offset:5; - uint8_t device_enable:1; - uint8_t unused_6:1; - uint8_t unused_7:1; - } flags1; /* 43 */ - - struct { - uint8_t ppr_options:4; - uint8_t ppr_bus_width:2; - uint8_t unused_8:1; - uint8_t enable_ppr:1; - } flags2; /* 43 */ - + union { /* 43 */ + uint8_t flags_43; + struct { + uint8_t sync_offset:4; + uint8_t device_enable:1; + uint8_t lun_disable:1; + uint8_t unused_6:1; + uint8_t unused_7:1; + } flags1x80; + struct { + uint8_t sync_offset:5; + uint8_t device_enable:1; + uint8_t unused_6:1; + uint8_t unused_7:1; + } flags1x160; + } flags; + union { /* PPR flags for the 1x160 controllers */ + uint8_t unused_44; + struct { + uint8_t ppr_options:4; + uint8_t ppr_bus_width:2; + uint8_t unused_8:1; + uint8_t enable_ppr:1; + } flags; /* 44 */ + } ppr_1x160; uint8_t unused_45; /* 45 */ } target[MAX_TARGETS]; } bus[MAX_BUSES]; @@ -1021,19 +491,19 @@ typedef struct { uint16_t subsystem_id[2]; /* 250, 251, 252, 253 */ - uint8_t System_Id_Pointer; /* 254 */ + union { /* 254 */ + uint8_t unused_254; + uint8_t system_id_pointer; + } sysid_1x160; uint8_t chksum; /* 255 */ -#else -#error neither __BIG_ENDIAN nor __LITTLE_ENDIAN is defined -#endif -} nvram160_t; +}; /* * ISP queue - command entry structure definition. */ #define MAX_CMDSZ 12 /* SCSI maximum CDB size. */ -typedef struct { +struct cmd_entry { uint8_t entry_type; /* Entry type. */ #define COMMAND_TYPE 1 /* Command entry */ uint8_t entry_count; /* Entry count. */ @@ -1056,12 +526,12 @@ typedef struct { uint32_t dseg_2_length; /* Data segment 2 length. */ uint32_t dseg_3_address; /* Data segment 3 address. */ uint32_t dseg_3_length; /* Data segment 3 length. */ -} cmd_entry_t; +}; /* * ISP queue - continuation entry structure definition. */ -typedef struct { +struct cont_entry { uint8_t entry_type; /* Entry type. */ #define CONTINUE_TYPE 2 /* Continuation entry. */ uint8_t entry_count; /* Entry count. */ @@ -1082,12 +552,12 @@ typedef struct { uint32_t dseg_5_length; /* Data segment 5 length. */ uint32_t dseg_6_address; /* Data segment 6 address. */ uint32_t dseg_6_length; /* Data segment 6 length. */ -} cont_entry_t; +}; /* * ISP queue - status entry structure definition. */ -typedef struct { +struct response { uint8_t entry_type; /* Entry type. */ #define STATUS_TYPE 3 /* Status entry. */ uint8_t entry_count; /* Entry count. */ @@ -1114,12 +584,12 @@ typedef struct { uint32_t residual_length; /* Residual transfer length. */ uint16_t reserved[4]; uint8_t req_sense_data[32]; /* Request sense data. */ -} sts_entry_t, response_t; +}; /* * ISP queue - marker entry structure definition. */ -typedef struct { +struct mrk_entry { uint8_t entry_type; /* Entry type. */ #define MARKER_TYPE 4 /* Marker entry. */ uint8_t entry_count; /* Entry count. */ @@ -1133,12 +603,14 @@ typedef struct { #define MK_SYNC_ID 1 /* Synchronize ID */ #define MK_SYNC_ALL 2 /* Synchronize all ID/LUN */ uint8_t reserved_1[53]; -} mrk_entry_t; +}; /* * ISP queue - extended command entry structure definition. + * + * Unused by the driver! */ -typedef struct { +struct ecmd_entry { uint8_t entry_type; /* Entry type. */ #define EXTENDED_CMD_TYPE 5 /* Extended command entry. */ uint8_t entry_count; /* Entry count. */ @@ -1153,7 +625,7 @@ typedef struct { uint16_t timeout; /* Command timeout. */ uint16_t dseg_count; /* Data segment count. */ uint8_t scsi_cdb[88]; /* SCSI command words. */ -} ecmd_entry_t; +}; /* * ISP queue - 64-Bit addressing, command entry structure definition. @@ -1183,7 +655,7 @@ typedef struct { /* * ISP queue - 64-Bit addressing, continuation entry structure definition. */ -typedef struct { +struct cont_a64_entry { uint8_t entry_type; /* Entry type. */ #define CONTINUE_A64_TYPE 0xA /* Continuation A64 entry. */ uint8_t entry_count; /* Entry count. */ @@ -1199,12 +671,12 @@ typedef struct { uint32_t dseg_3_length; /* Data segment 3 length. */ uint32_t dseg_4_address[2]; /* Data segment 4 address. */ uint32_t dseg_4_length; /* Data segment 4 length. */ -} cont_a64_entry_t; +}; /* * ISP queue - enable LUN entry structure definition. */ -typedef struct { +struct elun_entry { uint8_t entry_type; /* Entry type. */ #define ENABLE_LUN_TYPE 0xB /* Enable LUN entry. */ uint8_t entry_count; /* Entry count. */ @@ -1225,12 +697,14 @@ typedef struct { /* commands (2-26). */ uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ uint16_t reserved_6[20]; -} elun_entry_t; +}; /* * ISP queue - modify LUN entry structure definition. + * + * Unused by the driver! */ -typedef struct { +struct modify_lun_entry { uint8_t entry_type; /* Entry type. */ #define MODIFY_LUN_TYPE 0xC /* Modify LUN entry. */ uint8_t entry_count; /* Entry count. */ @@ -1250,12 +724,12 @@ typedef struct { uint16_t reserved_6; uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ uint16_t reserved_7[20]; -} modify_lun_entry_t; +}; /* * ISP queue - immediate notify entry structure definition. */ -typedef struct { +struct notify_entry { uint8_t entry_type; /* Entry type. */ #define IMMED_NOTIFY_TYPE 0xD /* Immediate notify entry. */ uint8_t entry_count; /* Entry count. */ @@ -1276,12 +750,12 @@ typedef struct { uint8_t scsi_msg[8]; /* SCSI message not handled by ISP */ uint16_t reserved_5[8]; uint8_t sense_data[18]; -} notify_entry_t; +}; /* * ISP queue - notify acknowledge entry structure definition. */ -typedef struct { +struct nack_entry { uint8_t entry_type; /* Entry type. */ #define NOTIFY_ACK_TYPE 0xE /* Notify acknowledge entry. */ uint8_t entry_count; /* Entry count. */ @@ -1297,12 +771,12 @@ typedef struct { uint8_t event; uint16_t seq_id; uint16_t reserved_4[22]; -} nack_entry_t; +}; /* * ISP queue - Accept Target I/O (ATIO) entry structure definition. */ -typedef struct { +struct atio_entry { uint8_t entry_type; /* Entry type. */ #define ACCEPT_TGT_IO_TYPE 6 /* Accept target I/O entry. */ uint8_t entry_count; /* Entry count. */ @@ -1320,12 +794,12 @@ typedef struct { uint8_t tag_type; /* Received queue tag message type */ uint8_t cdb[26]; uint8_t sense_data[18]; -} atio_entry_t; +}; /* * ISP queue - Continue Target I/O (CTIO) entry structure definition. */ -typedef struct { +struct ctio_entry { uint8_t entry_type; /* Entry type. */ #define CONTINUE_TGT_IO_TYPE 7 /* CTIO entry */ uint8_t entry_count; /* Entry count. */ @@ -1353,12 +827,12 @@ typedef struct { uint32_t dseg_2_length; /* Data segment 2 length. */ uint32_t dseg_3_address; /* Data segment 3 address. */ uint32_t dseg_3_length; /* Data segment 3 length. */ -} ctio_entry_t; +}; /* * ISP queue - CTIO returned entry structure definition. */ -typedef struct { +struct ctio_ret_entry { uint8_t entry_type; /* Entry type. */ #define CTIO_RET_TYPE 7 /* CTIO return entry */ uint8_t entry_count; /* Entry count. */ @@ -1383,12 +857,12 @@ typedef struct { uint32_t dseg_1_address; /* Data segment 1 address. */ uint16_t dseg_1_length; /* Data segment 1 length. */ uint8_t sense_data[18]; -} ctio_ret_entry_t; +}; /* * ISP queue - CTIO A64 entry structure definition. */ -typedef struct { +struct ctio_a64_entry { uint8_t entry_type; /* Entry type. */ #define CTIO_A64_TYPE 0xF /* CTIO A64 entry */ uint8_t entry_count; /* Entry count. */ @@ -1413,12 +887,12 @@ typedef struct { uint32_t dseg_0_length; /* Data segment 0 length. */ uint32_t dseg_1_address[2]; /* Data segment 1 address. */ uint32_t dseg_1_length; /* Data segment 1 length. */ -} ctio_a64_entry_t; +}; /* * ISP queue - CTIO returned entry structure definition. */ -typedef struct { +struct ctio_a64_ret_entry { uint8_t entry_type; /* Entry type. */ #define CTIO_A64_RET_TYPE 0xF /* CTIO A64 returned entry */ uint8_t entry_count; /* Entry count. */ @@ -1440,12 +914,12 @@ typedef struct { uint16_t dseg_count; /* Data segment count. */ uint16_t reserved_4[7]; uint8_t sense_data[18]; -} ctio_a64_ret_entry_t; +}; /* * ISP request and response queue entry sizes */ -#define RESPONSE_ENTRY_SIZE (sizeof(response_t)) +#define RESPONSE_ENTRY_SIZE (sizeof(struct response)) #define REQUEST_ENTRY_SIZE (sizeof(request_t)) /* @@ -1508,27 +982,11 @@ typedef struct { #define OF_FORCE_DISC BIT_30 /* Disconnects mandatory */ #define OF_SSTS BIT_31 /* Send SCSI status */ -#if QL1280_TARGET_MODE_SUPPORT -/* - * Target Read/Write buffer structure. - */ -#define TARGET_DATA_OFFSET 4 -#define TARGET_DATA_SIZE 0x2000 /* 8K */ -#define TARGET_INQ_OFFSET (TARGET_DATA_OFFSET + TARGET_DATA_SIZE) -#define TARGET_SENSE_SIZE 18 -#define TARGET_BUF_SIZE 36 - -typedef struct { - uint8_t hdr[4]; - uint8_t data[TARGET_DATA_SIZE]; - struct ident inq; -} tgt_t; -#endif /* - * BUS parameters/settings structure + * BUS parameters/settings structure - UNUSED */ -typedef struct { +struct bus_param { uint8_t id; /* Host adapter SCSI id */ uint8_t bus_reset_delay; /* SCSI bus reset delay. */ uint8_t failed_reset_count; /* number of time reset failed */ @@ -1540,8 +998,19 @@ typedef struct { uint8_t reset_marker:1; uint8_t disable_scsi_reset:1; uint8_t scsi_bus_dead:1; /* SCSI Bus is Dead, when 5 back to back resets failed */ +}; + + +struct qla_driver_setup { + uint32_t no_sync:1; + uint32_t no_wide:1; + uint32_t no_ppr:1; + uint32_t no_nvram:1; + uint16_t sync_mask; + uint16_t wide_mask; + uint16_t ppr_mask; +}; -} bus_param_t; /* * Linux Host Adapter structure @@ -1551,35 +1020,32 @@ struct scsi_qla_host { struct Scsi_Host *host; /* pointer to host data */ struct scsi_qla_host *next; struct device_reg *iobase; /* Base Memory-mapped I/O address */ - uint8_t pci_bus; - uint8_t pci_device_fn; - uint8_t devnum; - struct pci_dev *pdev; - volatile unsigned char *mmpbase; /* memory mapped address */ + unsigned char *mmpbase; /* memory mapped address */ unsigned long host_no; unsigned long instance; + struct pci_dev *pdev; + uint32_t device_id; + uint8_t pci_bus; + uint8_t pci_device_fn; + uint8_t devnum; uint8_t revision; uint8_t ports; unsigned long actthreads; - unsigned long qthreads; unsigned long isr_count; /* Interrupt count */ unsigned long spurious_int; - uint32_t device_id; - /* Outstandings ISP commands. */ - srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; + struct srb *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; /* BUS configuration data */ - bus_param_t bus_settings[MAX_BUSES]; - - /* Device LUN queues. */ - struct scsi_lu *dev[MAX_EQ]; /* Logical unit queues */ + struct bus_param bus_settings[MAX_BUSES]; +#if 0 /* bottom half run queue */ - struct work_struct run_qla_bh; + struct tq_struct run_qla_bh; +#endif /* Received ISP mailbox data. */ volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; @@ -1595,49 +1061,43 @@ struct scsi_qla_host { uint16_t req_q_cnt; /* Number of available entries. */ dma_addr_t response_dma; /* Physical address. */ - response_t *response_ring; /* Base virtual address */ - response_t *response_ring_ptr; /* Current address. */ + struct response *response_ring; /* Base virtual address */ + struct response *response_ring_ptr; /* Current address. */ uint16_t rsp_ring_index; /* Current index. */ -#if QL1280_TARGET_MODE_SUPPORT - /* Target buffer and sense data. */ - dma_addr_t tbuf_dma; /* Physical address. */ - dma_addr_t tsense_dma; /* Physical address. */ - tgt_t *tbuf; - uint8_t *tsense; -#endif - #if WATCHDOGTIMER /* Watchdog queue, lock and total timer */ uint8_t watchdog_q_lock; /* Lock for watchdog queue */ - srb_t *wdg_q_first; /* First job on watchdog queue */ - srb_t *wdg_q_last; /* Last job on watchdog queue */ + struct srb *wdg_q_first; /* First job on watchdog queue */ + struct srb *wdg_q_last; /* Last job on watchdog queue */ uint32_t total_timeout; /* Total timeout (quantum count) */ uint32_t watchdogactive; #endif - srb_t *done_q_first; /* First job on done queue */ - srb_t *done_q_last; /* Last job on done queue */ + struct srb *done_q_first; /* First job on done queue */ + struct srb *done_q_last; /* Last job on done queue */ + + struct completion *mailbox_wait; volatile struct { - uint32_t mbox_int:1; /* 0 */ - uint32_t mbox_busy:1; /* 1 */ - uint32_t online:1; /* 2 */ - uint32_t reset_marker:1; /* 3 */ - uint32_t isp_abort_needed:1; /* 4 */ - uint32_t disable_host_adapter:1; /* 5 */ - uint32_t reset_active:1; /* 6 */ - uint32_t abort_isp_active:1; /* 7 */ - uint32_t disable_risc_code_load:1; /* 8 */ - uint32_t enable_64bit_addressing:1; /* 9 */ - uint32_t in_reset:1; /* 10 */ + uint32_t mbox_busy:1; /* 0 */ + uint32_t online:1; /* 1 */ + uint32_t reset_marker:1; /* 2 */ + uint32_t disable_host_adapter:1; /* 4 */ + uint32_t reset_active:1; /* 5 */ + uint32_t abort_isp_active:1; /* 6 */ + uint32_t disable_risc_code_load:1; /* 7 */ + uint32_t enable_64bit_addressing:1; /* 8 */ + uint32_t in_reset:1; /* 9 */ uint32_t ints_enabled:1; + uint32_t ignore_nvram:1; +#ifdef __ia64__ + uint32_t use_pci_vchannel:1; +#endif } flags; - /* needed holders for PCI ordered list of hosts */ - unsigned long io_port; - uint32_t irq; - + struct nvram nvram; + int nvram_valid; }; /* @@ -1651,16 +1111,60 @@ struct scsi_qla_host { /* * Linux - SCSI Driver Interface Function Prototypes. */ +int qla1280_proc_info(char *, char **, off_t, int, int, int); const char *qla1280_info(struct Scsi_Host *host); int qla1280_detect(Scsi_Host_Template *); int qla1280_release(struct Scsi_Host *); int qla1280_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -int qla1280_abort(Scsi_Cmnd *); -int qla1280_reset(Scsi_Cmnd *, unsigned int); +#if LINUX_VERSION_CODE < 0x020545 +int qla1280_biosparam(Disk *, kdev_t, int[]); +#else int qla1280_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); -static int qla1280_slave_configure(Scsi_Device *); -irqreturn_t qla1280_intr_handler(int, void *, struct pt_regs *); -void qla1280_setup(char *s, int *dummy); + sector_t, int *); +#endif +int __init qla1280_setup(char *s); +int qla1280_eh_abort(struct scsi_cmnd * cmd); +int qla1280_eh_device_reset(struct scsi_cmnd *cmd); +int qla1280_eh_bus_reset(struct scsi_cmnd *cmd); +int qla1280_eh_adapter_reset(struct scsi_cmnd *cmd); + +#if LINUX_VERSION_CODE < 0x020545 +#define USE_NEW_EH .use_new_eh_code= 1 +#else +#define USE_NEW_EH +#endif + +/* + * Scsi_Host_template (see hosts.h) + * Device driver Interfaces to mid-level SCSI driver. + */ + +#define QLA1280_LINUX_TEMPLATE { \ + .module = NULL, \ + .proc_dir = NULL, \ + .proc_info = qla1280_proc_info, \ + .name = "Qlogic ISP 1280/12160", \ + .detect = qla1280_detect, \ + .release = qla1280_release, \ + .info = qla1280_info, \ + .ioctl = NULL, \ + .command = NULL, \ + .queuecommand = qla1280_queuecommand, \ + .eh_strategy_handler = NULL, \ + .eh_abort_handler = qla1280_eh_abort, \ + .eh_device_reset_handler = qla1280_eh_device_reset, \ + .eh_bus_reset_handler = qla1280_eh_bus_reset, \ + .eh_host_reset_handler = qla1280_eh_adapter_reset, \ + .bios_param = qla1280_biosparam, \ + .can_queue = 255, /* max simultaneous cmds */\ + .this_id = -1, /* scsi id of host adapter */\ + .sg_tablesize = SG_ALL, /* max scatter-gather cmds */\ + .cmd_per_lun = 3, /* cmds per lun (linked cmds) */\ + .present = 0, /* number of 1280's present */\ + .unchecked_isa_dma = 0, /* no memory DMA restrictions */\ + .use_clustering = ENABLE_CLUSTERING, \ + .emulated = 0, \ + USE_NEW_EH \ +} #endif /* _IO_HBA_QLA1280_H */ diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 7765d8a4afd9..066a316cd2b0 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -2235,6 +2235,5 @@ static Scsi_Host_Template driver_template = { .sg_tablesize = QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN), .cmd_per_lun = QLOGICFC_CMD_PER_LUN, .use_clustering = ENABLE_CLUSTERING, - .highmem_io = 1, }; #include "scsi_module.c" diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 3116a90b7b27..005d20be5df1 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1550,10 +1550,6 @@ static Scsi_Host_Template driver_template = { .sg_tablesize = QLOGICPTI_MAX_SG(QLOGICPTI_REQ_QUEUE_LEN), .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, -/* Sparc32's iommu code cannot handle highmem pages yet. */ -#ifdef CONFIG_SPARC64 - .highmem_io = 1, -#endif }; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 633c9a028e29..6e17a28d4afe 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -370,7 +370,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) struct Scsi_Host *host = cmd->device->host; unsigned long flags = 0; unsigned long timeout; - int rtn = 1; + int rtn = 0; /* Assign a unique nonzero serial_number. */ /* XXX(hch): this is racy */ @@ -444,7 +444,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) host->hostt->queuecommand)); spin_lock_irqsave(host->host_lock, flags); - rtn = host->hostt->queuecommand(cmd, scsi_done); + if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) { + cmd->result = (DID_NO_CONNECT << 16); + scsi_done(cmd); + } else { + rtn = host->hostt->queuecommand(cmd, scsi_done); + } spin_unlock_irqrestore(host->host_lock, flags); if (rtn) { scsi_queue_insert(cmd, @@ -888,33 +893,65 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth) int scsi_device_get(struct scsi_device *sdev) { - if (!try_module_get(sdev->host->hostt->module)) - return -ENXIO; + struct class *class = class_get(&sdev_class); + int error = -ENXIO; + + if (class) { + down_write(&class->subsys.rwsem); + if (!test_bit(SDEV_DEL, &sdev->sdev_state)) + if (try_module_get(sdev->host->hostt->module)) + if (get_device(&sdev->sdev_gendev)) { + sdev->access_count++; + error = 0; + } + up_write(&class->subsys.rwsem); + class_put(&sdev_class); + } - sdev->access_count++; - return 0; + return error; } void scsi_device_put(struct scsi_device *sdev) { - sdev->access_count--; + struct class *class = class_get(&sdev_class); + + if (!class) + return; + + down_write(&class->subsys.rwsem); module_put(sdev->host->hostt->module); + if (--sdev->access_count == 0) { + if (test_bit(SDEV_DEL, &sdev->sdev_state)) + device_del(&sdev->sdev_gendev); + } + put_device(&sdev->sdev_gendev); + up_write(&class->subsys.rwsem); + + class_put(&sdev_class); +} + +int scsi_device_cancel_cb(struct device *dev, void *data) +{ + struct scsi_device *sdev = to_scsi_device(dev); + int recovery = *(int *)data; + + return scsi_device_cancel(sdev, recovery); } /** - * scsi_set_device_offline - set scsi_device offline - * @sdev: pointer to struct scsi_device to offline. + * scsi_device_cancel - cancel outstanding IO to this device + * @sdev: pointer to struct scsi_device + * @data: pointer to cancel value. * - * Locks: host_lock held on entry. **/ -void scsi_set_device_offline(struct scsi_device *sdev) +int scsi_device_cancel(struct scsi_device *sdev, int recovery) { struct scsi_cmnd *scmd; LIST_HEAD(active_list); struct list_head *lh, *lh_sf; unsigned long flags; - sdev->online = 0; + set_bit(SDEV_CANCEL, &sdev->sdev_state); spin_lock_irqsave(&sdev->list_lock, flags); list_for_each_entry(scmd, &sdev->cmd_list, list) { @@ -934,11 +971,17 @@ void scsi_set_device_offline(struct scsi_device *sdev) if (!list_empty(&active_list)) { list_for_each_safe(lh, lh_sf, &active_list) { scmd = list_entry(lh, struct scsi_cmnd, eh_entry); - scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); + list_del_init(lh); + if (recovery) { + scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); + } else { + scmd->result = (DID_ABORT << 16); + scsi_finish_command(scmd); + } } - } else { - /* FIXME: Send online state change hotplug event */ } + + return 0; } MODULE_DESCRIPTION("SCSI core"); diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 47125ef5d93e..dcf36f1c04fd 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1722,10 +1722,7 @@ static int sdebug_driver_remove(struct device * dev) return -ENODEV; } - if (scsi_remove_host(sdbg_host->shost)) { - printk(KERN_ERR "%s: scsi_remove_host failed\n", __FUNCTION__); - return -EBUSY; - } + scsi_remove_host(sdbg_host->shost); list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 6fc48eb0f834..f5d18f74beaf 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -84,7 +84,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) */ scmd->serial_number_at_timeout = scmd->serial_number; list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); - shost->in_recovery = 1; + set_bit(SHOST_RECOVERY, &shost->shost_state); shost->host_failed++; scsi_eh_wakeup(shost); spin_unlock_irqrestore(shost->host_lock, flags); @@ -187,7 +187,7 @@ void scsi_times_out(struct scsi_cmnd *scmd) **/ int scsi_block_when_processing_errors(struct scsi_device *sdev) { - wait_event(sdev->host->host_wait, (sdev->host->in_recovery == 0)); + wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state))); SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __FUNCTION__, sdev->online)); @@ -1389,7 +1389,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", __FUNCTION__)); - shost->in_recovery = 0; + clear_bit(SHOST_RECOVERY, &shost->shost_state); wake_up(&shost->host_wait); @@ -1599,7 +1599,6 @@ void scsi_error_handler(void *data) * that's fine. If the user sent a signal to this thing, we are * potentially in real danger. */ - shost->in_recovery = 0; shost->eh_active = 0; shost->ehandler = NULL; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7ad004d5e072..ef55ac3f119f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -318,7 +318,8 @@ void scsi_device_unbusy(struct scsi_device *sdev) spin_lock_irqsave(shost->host_lock, flags); shost->host_busy--; - if (unlikely(shost->in_recovery && shost->host_failed)) + if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) && + shost->host_failed)) scsi_eh_wakeup(shost); spin_unlock(shost->host_lock); spin_lock(&sdev->sdev_lock); @@ -1066,7 +1067,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, struct Scsi_Host *shost, struct scsi_device *sdev) { - if (shost->in_recovery) + if (test_bit(SHOST_RECOVERY, &shost->shost_state)) return 0; if (shost->host_busy == 0 && shost->host_blocked) { /* @@ -1207,21 +1208,20 @@ static void scsi_request_fn(struct request_queue *q) u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) { - if (shost->highmem_io) { - struct device *host_dev = scsi_get_device(shost); + struct device *host_dev; - if (PCI_DMA_BUS_IS_PHYS && host_dev && host_dev->dma_mask) - return *host_dev->dma_mask; - - /* - * Platforms with virtual-DMA translation - * hardware have no practical limit. - */ - return BLK_BOUNCE_ANY; - } else if (shost->unchecked_isa_dma) + if (shost->unchecked_isa_dma) return BLK_BOUNCE_ISA; - return BLK_BOUNCE_HIGH; + host_dev = scsi_get_device(shost); + if (PCI_DMA_BUS_IS_PHYS && host_dev && host_dev->dma_mask) + return *host_dev->dma_mask; + + /* + * Platforms with virtual-DMA translation + * hardware have no practical limit. + */ + return BLK_BOUNCE_ANY; } struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) @@ -1239,6 +1239,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); + blk_queue_segment_boundary(q, shost->dma_boundary); if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); diff --git a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c index 515a3e4b48fe..b8cc3ead92af 100644 --- a/drivers/scsi/scsi_module.c +++ b/drivers/scsi/scsi_module.c @@ -33,7 +33,7 @@ static int __init init_this_scsi_driver(void) INIT_LIST_HEAD(&sht->legacy_hosts); sht->detect(sht); - if (!sht->present) + if (list_empty(&sht->legacy_hosts)) return -ENODEV; list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) { diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index f17bdd42afe6..56566e3eef57 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -90,11 +90,15 @@ extern void scsi_exit_queue(void); /* scsi_proc.c */ #ifdef CONFIG_PROC_FS +extern void scsi_proc_hostdir_add(struct scsi_host_template *); +extern void scsi_proc_hostdir_rm(struct scsi_host_template *); extern void scsi_proc_host_add(struct Scsi_Host *); extern void scsi_proc_host_rm(struct Scsi_Host *); extern int scsi_init_procfs(void); extern void scsi_exit_procfs(void); #else +# define scsi_proc_hostdir_add(sht) do { } while (0) +# define scsi_proc_hostdir_rm(sht) do { } while (0) # define scsi_proc_host_add(shost) do { } while (0) # define scsi_proc_host_rm(shost) do { } while (0) # define scsi_init_procfs() (0) @@ -109,7 +113,6 @@ extern void scsi_rescan_device(struct device *); /* scsi_sysfs.c */ extern int scsi_device_register(struct scsi_device *); -extern void scsi_device_unregister(struct scsi_device *); extern void scsi_sysfs_init_host(struct Scsi_Host *); extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *); extern void scsi_sysfs_remove_host(struct Scsi_Host *); @@ -117,6 +120,7 @@ extern int scsi_sysfs_register(void); extern void scsi_sysfs_unregister(void); extern struct class shost_class; +extern struct class sdev_class; extern struct bus_type scsi_bus_type; #endif /* _SCSI_PRIV_H */ diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 7f671349c28a..02a66f128ace 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -41,6 +41,8 @@ struct proc_dir_entry *proc_scsi; EXPORT_SYMBOL(proc_scsi); +/* Protect sht->present and sht->proc_dir */ +static DECLARE_MUTEX(global_host_template_sem); static int proc_scsi_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) @@ -77,16 +79,10 @@ out: return ret; } -void scsi_proc_host_add(struct Scsi_Host *shost) +void scsi_proc_hostdir_add(struct scsi_host_template *sht) { - struct scsi_host_template *sht = shost->hostt; - struct proc_dir_entry *p; - char name[10]; - - if (!sht->proc_info) - return; - - if (!sht->proc_dir) { + down(&global_host_template_sem); + if (!sht->present++) { sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); if (!sht->proc_dir) { printk(KERN_ERR "%s: proc_mkdir failed for %s\n", @@ -95,6 +91,27 @@ void scsi_proc_host_add(struct Scsi_Host *shost) } sht->proc_dir->owner = sht->module; } + up(&global_host_template_sem); +} + +void scsi_proc_hostdir_rm(struct scsi_host_template *sht) +{ + down(&global_host_template_sem); + if (!--sht->present && sht->proc_dir) { + remove_proc_entry(sht->proc_name, proc_scsi); + sht->proc_dir = NULL; + } + up(&global_host_template_sem); +} + +void scsi_proc_host_add(struct Scsi_Host *shost) +{ + struct scsi_host_template *sht = shost->hostt; + struct proc_dir_entry *p; + char name[10]; + + if (!sht->proc_dir) + return; sprintf(name,"%d", shost->host_no); p = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, @@ -107,20 +124,18 @@ void scsi_proc_host_add(struct Scsi_Host *shost) } p->write_proc = proc_scsi_write_proc; - p->owner = shost->hostt->module; + p->owner = sht->module; } void scsi_proc_host_rm(struct Scsi_Host *shost) { - struct scsi_host_template *sht = shost->hostt; char name[10]; - if (sht->proc_info) { - sprintf(name,"%d", shost->host_no); - remove_proc_entry(name, sht->proc_dir); - if (!sht->present) - remove_proc_entry(sht->proc_name, proc_scsi); - } + if (!shost->hostt->proc_dir) + return; + + sprintf(name,"%d", shost->host_no); + remove_proc_entry(name, shost->hostt->proc_dir); } static int proc_print_scsidevice(struct device *dev, void *data) @@ -175,11 +190,11 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) { struct Scsi_Host *shost; struct scsi_device *sdev; - int error = -ENODEV; + int error = -ENXIO; shost = scsi_host_lookup(host); - if (!shost) - return -ENODEV; + if (IS_ERR(shost)) + return PTR_ERR(shost); if (!scsi_find_device(shost, channel, id, lun)) { sdev = scsi_add_device(shost, channel, id, lun); @@ -197,18 +212,19 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) { struct scsi_device *sdev; struct Scsi_Host *shost; - int error = -ENODEV; + int error = -ENXIO; shost = scsi_host_lookup(host); - if (!shost) - return -ENODEV; + if (IS_ERR(shost)) + return PTR_ERR(shost); sdev = scsi_find_device(shost, channel, id, lun); if (!sdev) goto out; if (sdev->access_count) goto out; - error = scsi_remove_device(sdev); + scsi_remove_device(sdev); + error = 0; out: scsi_host_put(shost); return error; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 3b8309105021..55969f3de38f 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -288,8 +288,6 @@ void scsi_free_sdev(struct scsi_device *sdev) if (sdev->request_queue) scsi_free_queue(sdev->request_queue); - if (sdev->host->hostt->slave_destroy) - sdev->host->hostt->slave_destroy(sdev); if (sdev->inquiry) kfree(sdev->inquiry); spin_lock_irqsave(sdev->host->host_lock, flags); @@ -1074,12 +1072,6 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, return sdev; } -int scsi_remove_device(struct scsi_device *sdev) -{ - scsi_device_unregister(sdev); - return 0; -} - void scsi_rescan_device(struct device *dev) { struct scsi_driver *drv = to_scsi_driver(dev->driver); diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c index 2ce7cb6c25bf..5c8dbdb5789c 100644 --- a/drivers/scsi/scsi_syms.c +++ b/drivers/scsi/scsi_syms.c @@ -86,7 +86,7 @@ EXPORT_SYMBOL(scsi_device_get); EXPORT_SYMBOL(scsi_device_put); EXPORT_SYMBOL(scsi_add_device); EXPORT_SYMBOL(scsi_remove_device); -EXPORT_SYMBOL(scsi_set_device_offline); +EXPORT_SYMBOL(scsi_device_cancel); EXPORT_SYMBOL(__scsi_mode_sense); EXPORT_SYMBOL(scsi_mode_sense); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 3801b768c733..0097b4868923 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -54,12 +54,52 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { NULL }; +static void scsi_host_cls_release(struct class_device *class_dev) +{ + struct Scsi_Host *shost; + + shost = class_to_shost(class_dev); + put_device(&shost->shost_gendev); +} + +static void scsi_host_dev_release(struct device *dev) +{ + struct Scsi_Host *shost; + struct device *parent; + + parent = dev->parent; + shost = dev_to_shost(dev); + scsi_free_shost(shost); + put_device(parent); +} + struct class shost_class = { .name = "scsi_host", + .release = scsi_host_cls_release, }; -static struct class sdev_class = { +static void scsi_device_cls_release(struct class_device *class_dev) +{ + struct scsi_device *sdev; + + sdev = class_to_sdev(class_dev); + put_device(&sdev->sdev_gendev); +} + +static void scsi_device_dev_release(struct device *dev) +{ + struct scsi_device *sdev; + struct device *parent; + + parent = dev->parent; + sdev = to_scsi_device(dev); + scsi_free_sdev(sdev); + put_device(parent); +} + +struct class sdev_class = { .name = "scsi_device", + .release = scsi_device_cls_release, }; /* all probing is done in the individual ->probe routines */ @@ -109,7 +149,7 @@ void scsi_sysfs_unregister(void) */ #define sdev_show_function(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf) \ +sdev_show_##field (struct device *dev, char *buf) \ { \ struct scsi_device *sdev; \ sdev = to_scsi_device(dev); \ @@ -122,7 +162,7 @@ show_##field (struct device *dev, char *buf) \ */ #define sdev_rd_attr(field, format_string) \ sdev_show_function(field, format_string) \ -static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) +static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL) /* @@ -140,7 +180,7 @@ sdev_store_##field (struct device *dev, const char *buf, size_t count) \ snscanf (buf, 20, format_string, &sdev->field); \ return count; \ } \ -static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, sdev_store_##field) +static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field) /* * sdev_rd_attr: create a function and attribute variable for a @@ -162,7 +202,7 @@ sdev_store_##field (struct device *dev, const char *buf, size_t count) \ } \ return ret; \ } \ -static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, sdev_store_##field) +static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field) /* * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1", @@ -218,15 +258,6 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { NULL }; -static void scsi_device_release(struct device *dev) -{ - struct scsi_device *sdev; - - sdev = to_scsi_device(dev); - if (!sdev) - return; - scsi_free_sdev(sdev); -} static struct device_attribute *attr_overridden( struct device_attribute **attrs, @@ -275,12 +306,13 @@ int scsi_device_register(struct scsi_device *sdev) { int error = 0, i; + set_bit(SDEV_ADD, &sdev->sdev_state); device_initialize(&sdev->sdev_gendev); sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); sdev->sdev_gendev.parent = &sdev->host->shost_gendev; sdev->sdev_gendev.bus = &scsi_bus_type; - sdev->sdev_gendev.release = scsi_device_release; + sdev->sdev_gendev.release = scsi_device_dev_release; class_device_initialize(&sdev->sdev_classdev); sdev->sdev_classdev.dev = &sdev->sdev_gendev; @@ -293,19 +325,24 @@ int scsi_device_register(struct scsi_device *sdev) printk(KERN_INFO "error 1\n"); return error; } + + get_device(sdev->sdev_gendev.parent); + error = class_device_add(&sdev->sdev_classdev); if (error) { printk(KERN_INFO "error 2\n"); - device_unregister(&sdev->sdev_gendev); + goto clean_device; return error; } + get_device(&sdev->sdev_gendev); + if (sdev->host->hostt->sdev_attrs) { for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { error = attr_add(&sdev->sdev_gendev, sdev->host->hostt->sdev_attrs[i]); if (error) - scsi_device_unregister(sdev); + scsi_remove_device(sdev); } } @@ -315,21 +352,40 @@ int scsi_device_register(struct scsi_device *sdev) error = device_create_file(&sdev->sdev_gendev, scsi_sysfs_sdev_attrs[i]); if (error) - scsi_device_unregister(sdev); + scsi_remove_device(sdev); } } return error; + +clean_device: + device_del(&sdev->sdev_gendev); + put_device(&sdev->sdev_gendev); + return error; + } /** - * scsi_device_unregister - unregister a device from the scsi bus + * scsi_remove_device - unregister a device from the scsi bus * @sdev: scsi_device to unregister **/ -void scsi_device_unregister(struct scsi_device *sdev) +void scsi_remove_device(struct scsi_device *sdev) { + struct class *class = class_get(&sdev_class); + class_device_unregister(&sdev->sdev_classdev); - device_unregister(&sdev->sdev_gendev); + + if (class) { + down_write(&class->subsys.rwsem); + set_bit(SDEV_DEL, &sdev->sdev_state); + if (sdev->access_count == 0) + device_del(&sdev->sdev_gendev); + up_write(&class->subsys.rwsem); + } + + put_device(&sdev->sdev_gendev); + + class_put(&sdev_class); } int scsi_register_driver(struct device_driver *drv) @@ -346,16 +402,6 @@ int scsi_register_interface(struct class_interface *intf) return class_interface_register(intf); } -static void scsi_host_release(struct device *dev) -{ - struct Scsi_Host *shost; - - shost = dev_to_shost(dev); - if (!shost) - return; - - scsi_free_shost(shost); -} void scsi_sysfs_init_host(struct Scsi_Host *shost) { @@ -364,7 +410,7 @@ void scsi_sysfs_init_host(struct Scsi_Host *shost) shost->host_no); snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s", shost->hostt->proc_name); - shost->shost_gendev.release = scsi_host_release; + shost->shost_gendev.release = scsi_host_dev_release; class_device_initialize(&shost->shost_classdev); shost->shost_classdev.dev = &shost->shost_gendev; @@ -426,10 +472,14 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) if (error) return error; + set_bit(SHOST_ADD, &shost->shost_state); + get_device(shost->shost_gendev.parent); + error = class_device_add(&shost->shost_classdev); if (error) goto clean_device; + get_device(&shost->shost_gendev); if (shost->hostt->shost_attrs) { for (i = 0; shost->hostt->shost_attrs[i]; i++) { error = class_attr_add(&shost->shost_classdev, @@ -465,6 +515,11 @@ clean_device: **/ void scsi_sysfs_remove_host(struct Scsi_Host *shost) { - class_device_del(&shost->shost_classdev); + unsigned long flags; + spin_lock_irqsave(shost->host_lock, flags); + set_bit(SHOST_DEL, &shost->shost_state); + spin_unlock_irqrestore(shost->host_lock, flags); + + class_device_unregister(&shost->shost_classdev); device_del(&shost->shost_gendev); } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 441ca6e58cfc..30bdd330828a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -651,9 +651,11 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) /* An error occurred */ if (driver_byte(result) != 0 && /* An error occurred */ - SCpnt->sense_buffer[0] == 0xF0) { /* Sense data is valid */ + (SCpnt->sense_buffer[0] & 0x7f) == 0x70) { /* Sense current */ switch (SCpnt->sense_buffer[2]) { case MEDIUM_ERROR: + if (!(SCpnt->sense_buffer[0] & 0x80)) + break; error_sector = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | @@ -696,7 +698,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) * hard error. */ print_sense("sd", SCpnt); - result = 0; + SCpnt->result = 0; SCpnt->sense_buffer[0] = 0x0; good_sectors = this_count; break; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index eef2346282e3..dc8e7e2a9095 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -954,7 +954,8 @@ sg_ioctl(struct inode *inode, struct file *filp, if (sdp->detached) return -ENODEV; if (filp->f_flags & O_NONBLOCK) { - if (sdp->device->host->in_recovery) + if (test_bit(SHOST_RECOVERY, + &sdp->device->host->shost_state)) return -EBUSY; } else if (!scsi_block_when_processing_errors(sdp->device)) return -EBUSY; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7c24b78e45e6..e91c870710d9 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -181,6 +181,7 @@ static void rw_intr(struct scsi_cmnd * SCpnt) int this_count = SCpnt->bufflen >> 9; int good_sectors = (result == 0 ? this_count : 0); int block_sectors = 0; + long error_sector; struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); #ifdef DEBUG @@ -194,33 +195,57 @@ static void rw_intr(struct scsi_cmnd * SCpnt) * memcpy's that could be avoided. */ if (driver_byte(result) != 0 && /* An error occurred */ - SCpnt->sense_buffer[0] == 0xF0 && /* Sense data is valid */ - (SCpnt->sense_buffer[2] == MEDIUM_ERROR || - SCpnt->sense_buffer[2] == VOLUME_OVERFLOW || - SCpnt->sense_buffer[2] == ILLEGAL_REQUEST)) { - long error_sector = (SCpnt->sense_buffer[3] << 24) | - (SCpnt->sense_buffer[4] << 16) | - (SCpnt->sense_buffer[5] << 8) | - SCpnt->sense_buffer[6]; - if (SCpnt->request->bio != NULL) - block_sectors = bio_sectors(SCpnt->request->bio); - if (block_sectors < 4) - block_sectors = 4; - if (cd->device->sector_size == 2048) - error_sector <<= 2; - error_sector &= ~(block_sectors - 1); - good_sectors = error_sector - SCpnt->request->sector; - if (good_sectors < 0 || good_sectors >= this_count) - good_sectors = 0; - /* - * The SCSI specification allows for the value returned by READ - * CAPACITY to be up to 75 2K sectors past the last readable - * block. Therefore, if we hit a medium error within the last - * 75 2K sectors, we decrease the saved size value. - */ - if (error_sector < get_capacity(cd->disk) && - cd->capacity - error_sector < 4 * 75) - set_capacity(cd->disk, error_sector); + (SCpnt->sense_buffer[0] & 0x7f) == 0x70) { /* Sense current */ + switch (SCpnt->sense_buffer[2]) { + case MEDIUM_ERROR: + case VOLUME_OVERFLOW: + case ILLEGAL_REQUEST: + if (!(SCpnt->sense_buffer[0] & 0x90)) + break; + error_sector = (SCpnt->sense_buffer[3] << 24) | + (SCpnt->sense_buffer[4] << 16) | + (SCpnt->sense_buffer[5] << 8) | + SCpnt->sense_buffer[6]; + if (SCpnt->request->bio != NULL) + block_sectors = + bio_sectors(SCpnt->request->bio); + if (block_sectors < 4) + block_sectors = 4; + if (cd->device->sector_size == 2048) + error_sector <<= 2; + error_sector &= ~(block_sectors - 1); + good_sectors = error_sector - SCpnt->request->sector; + if (good_sectors < 0 || good_sectors >= this_count) + good_sectors = 0; + /* + * The SCSI specification allows for the value + * returned by READ CAPACITY to be up to 75 2K + * sectors past the last readable block. + * Therefore, if we hit a medium error within the + * last 75 2K sectors, we decrease the saved size + * value. + */ + if (error_sector < get_capacity(cd->disk) && + cd->capacity - error_sector < 4 * 75) + set_capacity(cd->disk, error_sector); + break; + + case RECOVERED_ERROR: + + /* + * An error occured, but it recovered. Inform the + * user, but make sure that it's not treated as a + * hard error. + */ + print_sense("sr", SCpnt); + SCpnt->result = 0; + SCpnt->sense_buffer[0] = 0x0; + good_sectors = this_count; + break; + + default: + break; + } } /* diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 64d8671c3e76..afd0a5c8b1c5 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support */ -static char *verstr = "20030622"; +static char *verstr = "20030811"; #include <linux/module.h> @@ -1312,6 +1312,19 @@ static int setup_buffering(Scsi_Tape *STp, const char *buf, size_t count, int is } +/* Can be called more than once after each setup_buffer() */ +static void release_buffering(Scsi_Tape *STp) +{ + ST_buffer *STbp; + + STbp = STp->buffer; + if (STbp->do_dio) { + sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, FALSE); + STbp->do_dio = 0; + } +} + + /* Write command */ static ssize_t st_write(struct file *filp, const char *buf, size_t count, loff_t * ppos) @@ -1589,11 +1602,7 @@ static ssize_t out: if (SRpnt != NULL) scsi_release_request(SRpnt); - STbp = STp->buffer; - if (STbp->do_dio) { - sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, FALSE); - STbp->do_dio = 0; - } + release_buffering(STp); up(&STp->lock); return retval; @@ -1601,7 +1610,10 @@ static ssize_t /* Read data from the tape. Returns zero in the normal case, one if the eof status has changed, and the negative error code in case of a - fatal error. Otherwise updates the buffer and the eof state. */ + fatal error. Otherwise updates the buffer and the eof state. + + Does release user buffer mapping if it is set. +*/ static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt) { int transfer, blks, bytes; @@ -1647,6 +1659,7 @@ static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt) SRpnt = *aSRpnt; SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ, STp->timeout, MAX_RETRIES, TRUE); + release_buffering(STp); *aSRpnt = SRpnt; if (!SRpnt) return STbp->syscall_result; @@ -1788,7 +1801,7 @@ static ssize_t ssize_t total; ssize_t retval = 0; ssize_t i, transfer; - int special; + int special, do_dio = 0; Scsi_Request *SRpnt = NULL; Scsi_Tape *STp = filp->private_data; ST_mode *STm; @@ -1826,6 +1839,7 @@ static ssize_t retval = setup_buffering(STp, buf, count, TRUE); if (retval) goto out; + do_dio = STbp->do_dio; if (STbp->buffer_bytes == 0 && STps->eof >= ST_EOD_1) { @@ -1838,7 +1852,7 @@ static ssize_t goto out; } - if (!STbp->do_dio) { + if (do_dio) { /* Check the buffer writability before any tape movement. Don't alter buffer data. */ if (copy_from_user(&i, buf, 1) != 0 || @@ -1876,7 +1890,7 @@ static ssize_t ) /* end DEB */ transfer = STbp->buffer_bytes < count - total ? STbp->buffer_bytes : count - total; - if (!STbp->do_dio) { + if (!do_dio) { i = from_buffer(STbp, buf, transfer); if (i) { retval = i; @@ -1917,9 +1931,8 @@ static ssize_t scsi_release_request(SRpnt); SRpnt = NULL; } - if (STbp->do_dio) { - sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, TRUE); - STbp->do_dio = 0; + if (do_dio) { + release_buffering(STp); STbp->buffer_bytes = 0; } up(&STp->lock); @@ -2348,6 +2361,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) int datalen = 0, direction = SCSI_DATA_NONE; char *name = tape_name(STp); + WARN_ON(STp->buffer->do_dio != 0); if (STp->ready != ST_READY) { if (STp->ready == ST_NO_TAPE) return (-ENOMEDIUM); diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 2c98654769c0..80a0f397ce8a 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -11,7 +11,7 @@ typedef struct { unsigned char in_use; unsigned char dma; /* DMA-able buffer */ - unsigned char do_dio; + unsigned char do_dio; /* direct i/o set up? */ int buffer_size; int buffer_blocks; int buffer_bytes; diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index 8a6c3972a7c4..7d534560df2b 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -14720,6 +14720,5 @@ static Scsi_Host_Template driver_template = { .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, .max_sectors = MAX_HW_SEGMENTS*8, .use_clustering = DISABLE_CLUSTERING, - .highmem_io = 1 }; #include "scsi_module.c" diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index b0266f645172..7498d20f8c28 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -57,35 +57,6 @@ #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" -/* - * Simple Wrapper to kernel PCI bus interface. - */ - -typedef struct pci_dev *pcidev_t; -#define PCIDEV_NULL (0) -#define PciBusNumber(d) (d)->bus->number -#define PciDeviceFn(d) (d)->devfn -#define PciVendorId(d) (d)->vendor -#define PciDeviceId(d) (d)->device -#define PciIrqLine(d) (d)->irq - -static u_long __init -pci_get_base_cookie(struct pci_dev *pdev, int index) -{ - u_long base; - -#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,12) - base = pdev->resource[index].start; -#else - base = pdev->base_address[index]; -#if BITS_PER_LONG > 32 - if ((base & 0x7) == 0x4) - base |= (((u_long)pdev->base_address[++index]) << 32); -#endif -#endif - return (base & ~0x7ul); -} - static int __init pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) { @@ -95,7 +66,7 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp); *base = tmp; ++index; - if ((tmp & 0x7) == 0x4) { + if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) { #if BITS_PER_LONG > 32 pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp); *base |= (((u_long)tmp) << 32); @@ -106,14 +77,6 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) #undef PCI_BAR_OFFSET } -#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) -#define pci_enable_device(pdev) (0) -#endif - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,4) -#define scsi_set_pci_device(inst, pdev) do { ;} while (0) -#endif - /* * Insert a delay in micro-seconds and milli-seconds. */ @@ -235,53 +198,8 @@ static void __init pci_unmap_mem(u_long vaddr, u_long size) */ static struct Scsi_Host *first_host = NULL; -/* - * /proc directory entry and proc_info. - */ -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) -static struct proc_dir_entry proc_scsi_sym53c8xx = { - PROC_SCSI_SYM53C8XX, 9, NAME53C8XX, - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -#endif - -/* - * Transfer direction - * - * Until some linux kernel version near 2.3.40, low-level scsi - * drivers were not told about data transfer direction. - */ -#if LINUX_VERSION_CODE > LinuxVersionCode(2, 3, 40) - #define scsi_data_direction(cmd) (cmd->sc_data_direction) -#else - -static __inline__ int scsi_data_direction(Scsi_Cmnd *cmd) -{ - int direction; - - switch((int) cmd->cmnd[0]) { - case 0x08: /* READ(6) 08 */ - case 0x28: /* READ(10) 28 */ - case 0xA8: /* READ(12) A8 */ - direction = SCSI_DATA_READ; - break; - case 0x0A: /* WRITE(6) 0A */ - case 0x2A: /* WRITE(10) 2A */ - case 0xAA: /* WRITE(12) AA */ - direction = SCSI_DATA_WRITE; - break; - default: - direction = SCSI_DATA_UNKNOWN; - break; - } - - return direction; -} - -#endif - /* * Driver host data structure. */ @@ -305,7 +223,7 @@ typedef dma_addr_t bus_addr_t; struct sym_eh_wait { struct semaphore sem; struct timer_list timer; - void (*old_done)(Scsi_Cmnd *); + void (*old_done)(struct scsi_cmnd *); int to_do; int timed_out; }; @@ -325,7 +243,7 @@ struct sym_ucmd { /* Override the SCSI pointer structure */ typedef struct sym_ucmd *ucmd_p; #define SYM_UCMD_PTR(cmd) ((ucmd_p)(&(cmd)->SCp)) -#define SYM_SCMD_PTR(ucmd) sym_que_entry(ucmd, Scsi_Cmnd, SCp) +#define SYM_SCMD_PTR(ucmd) sym_que_entry(ucmd, struct scsi_cmnd, SCp) #define SYM_SOFTC_PTR(cmd) (((struct host_data *)cmd->device->host->hostdata)->ncb) /* @@ -367,7 +285,7 @@ typedef struct sym_ucmd *ucmd_p; #define bus_sg_dma_address(sc) sg_dma_address(sc) #define bus_sg_dma_len(sc) sg_dma_len(sc) -static void __unmap_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd) +static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) { int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); @@ -383,7 +301,7 @@ static void __unmap_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd) SYM_UCMD_PTR(cmd)->data_mapped = 0; } -static bus_addr_t __map_scsi_single_data(pcidev_t pdev, Scsi_Cmnd *cmd) +static bus_addr_t __map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) { bus_addr_t mapping; int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); @@ -398,7 +316,7 @@ static bus_addr_t __map_scsi_single_data(pcidev_t pdev, Scsi_Cmnd *cmd) return mapping; } -static int __map_scsi_sg_data(pcidev_t pdev, Scsi_Cmnd *cmd) +static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) { int use_sg; int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); @@ -412,7 +330,7 @@ static int __map_scsi_sg_data(pcidev_t pdev, Scsi_Cmnd *cmd) return use_sg; } -static void __sync_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd) +static void __sync_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) { int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); @@ -441,14 +359,14 @@ static void __sync_scsi_data(pcidev_t pdev, Scsi_Cmnd *cmd) /* * Complete a pending CAM CCB. */ -void sym_xpt_done(hcb_p np, Scsi_Cmnd *ccb) +void sym_xpt_done(hcb_p np, struct scsi_cmnd *ccb) { sym_remque(&SYM_UCMD_PTR(ccb)->link_cmdq); unmap_scsi_data(np, ccb); ccb->scsi_done(ccb); } -void sym_xpt_done2(hcb_p np, Scsi_Cmnd *ccb, int cam_status) +void sym_xpt_done2(hcb_p np, struct scsi_cmnd *ccb, int cam_status) { sym_set_cam_status(ccb, cam_status); sym_xpt_done(np, ccb); @@ -460,7 +378,7 @@ void sym_xpt_done2(hcb_p np, Scsi_Cmnd *ccb, int cam_status) */ void sym_print_addr (ccb_p cp) { - Scsi_Cmnd *cmd = cp->cam_ccb; + struct scsi_cmnd *cmd = cp->cam_ccb; if (cmd) printf("%s:%d:%d:", sym_name(SYM_SOFTC_PTR(cmd)), cmd->device->id,cmd->device->lun); @@ -521,7 +439,7 @@ static int sym_xerr_cam_status(int cam_status, int x_status) */ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid) { - Scsi_Cmnd *csio = cp->cam_ccb; + struct scsi_cmnd *csio = cp->cam_ccb; u_int cam_status, scsi_status, drv_status; drv_status = 0; @@ -581,9 +499,7 @@ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid) */ cam_status = sym_xerr_cam_status(DID_ERROR, cp->xerr_status); } -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,99) csio->resid = resid; -#endif csio->result = (drv_status << 24) + (cam_status << 16) + scsi_status; } @@ -591,7 +507,7 @@ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid) /* * Called on successfull INQUIRY response. */ -void sym_sniff_inquiry(hcb_p np, Scsi_Cmnd *cmd, int resid) +void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid) { int retv; @@ -612,7 +528,7 @@ void sym_sniff_inquiry(hcb_p np, Scsi_Cmnd *cmd, int resid) * Build the scatter/gather array for an I/O. */ -static int sym_scatter_no_sglist(hcb_p np, ccb_p cp, Scsi_Cmnd *cmd) +static int sym_scatter_no_sglist(hcb_p np, ccb_p cp, struct scsi_cmnd *cmd) { struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1]; int segment; @@ -634,7 +550,7 @@ static int sym_scatter_no_sglist(hcb_p np, ccb_p cp, Scsi_Cmnd *cmd) return segment; } -static int sym_scatter(hcb_p np, ccb_p cp, Scsi_Cmnd *cmd) +static int sym_scatter(hcb_p np, ccb_p cp, struct scsi_cmnd *cmd) { int segment; int use_sg = (int) cmd->use_sg; @@ -671,9 +587,9 @@ static int sym_scatter(hcb_p np, ccb_p cp, Scsi_Cmnd *cmd) /* * Queue a SCSI command. */ -static int sym_queue_command(hcb_p np, Scsi_Cmnd *ccb) +static int sym_queue_command(hcb_p np, struct scsi_cmnd *ccb) { -/* Scsi_Device *device = ccb->device; */ +/* struct scsi_device *device = ccb->device; */ tcb_p tp; lcb_p lp; ccb_p cp; @@ -736,7 +652,7 @@ static int sym_queue_command(hcb_p np, Scsi_Cmnd *ccb) /* * Setup buffers and pointers that address the CDB. */ -static int __inline sym_setup_cdb(hcb_p np, Scsi_Cmnd *ccb, ccb_p cp) +static int __inline sym_setup_cdb(hcb_p np, struct scsi_cmnd *ccb, ccb_p cp) { u32 cmd_ba; int cmd_len; @@ -762,7 +678,7 @@ static int __inline sym_setup_cdb(hcb_p np, Scsi_Cmnd *ccb, ccb_p cp) /* * Setup pointers that address the data and start the I/O. */ -int sym_setup_data_and_start(hcb_p np, Scsi_Cmnd *csio, ccb_p cp) +int sym_setup_data_and_start(hcb_p np, struct scsi_cmnd *csio, ccb_p cp) { int dir; tcb_p tp = &np->target[cp->target]; @@ -841,20 +757,6 @@ static void sym_timer (hcb_p np) { u_long thistime = ktime_get(0); -#if LINUX_VERSION_CODE < LinuxVersionCode(2, 4, 0) - /* - * If release process in progress, let's go - * Set the release stage from 1 to 2 to synchronize - * with the release process. - */ - - if (np->s.release_stage) { - if (np->s.release_stage == 1) - np->s.release_stage = 2; - return; - } -#endif - /* * Restart the timer. */ @@ -933,7 +835,7 @@ void sym_log_bus_error(hcb_p np) */ static void sym_requeue_awaiting_cmds(hcb_p np) { - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; ucmd_p ucp = SYM_UCMD_PTR(cmd); SYM_QUEHEAD tmp_cmdq; int sts; @@ -954,7 +856,7 @@ static void sym_requeue_awaiting_cmds(hcb_p np) /* * Linux entry point of the queuecommand() function */ -int sym53c8xx_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +int sym53c8xx_queue_command (struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { hcb_p np = SYM_SOFTC_PTR(cmd); ucmd_p ucp = SYM_UCMD_PTR(cmd); @@ -1066,7 +968,7 @@ static void sym53c8xx_timer(unsigned long npref) /* * Our general completion handler. */ -static void __sym_eh_done(Scsi_Cmnd *cmd, int timed_out) +static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out) { struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait; if (!ep) @@ -1091,18 +993,18 @@ static void __sym_eh_done(Scsi_Cmnd *cmd, int timed_out) /* * scsi_done() alias when error recovery is in progress. */ -static void sym_eh_done(Scsi_Cmnd *cmd) { __sym_eh_done(cmd, 0); } +static void sym_eh_done(struct scsi_cmnd *cmd) { __sym_eh_done(cmd, 0); } /* * Some timeout handler to avoid waiting too long. */ -static void sym_eh_timeout(u_long p) { __sym_eh_done((Scsi_Cmnd *)p, 1); } +static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); } /* * Generic method for our eh processing. * The 'op' argument tells what we have to do. */ -static int sym_eh_handler(int op, char *opname, Scsi_Cmnd *cmd) +static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) { hcb_p np = SYM_SOFTC_PTR(cmd); SYM_QUEHEAD *qp; @@ -1147,11 +1049,7 @@ prepare: goto finish; break; case SYM_EH_DO_WAIT: -#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,0) init_MUTEX_LOCKED(&ep->sem); -#else - ep->sem = MUTEX_LOCKED; -#endif /* fall through */ case SYM_EH_DO_COMPLETE: ep->old_done = cmd->scsi_done; @@ -1219,22 +1117,22 @@ finish: /* * Error handlers called from the eh thread (one thread per HBA). */ -int sym53c8xx_eh_abort_handler(Scsi_Cmnd *cmd) +int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd) { return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd); } -int sym53c8xx_eh_device_reset_handler(Scsi_Cmnd *cmd) +int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd) { return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd); } -int sym53c8xx_eh_bus_reset_handler(Scsi_Cmnd *cmd) +int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd) { return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd); } -int sym53c8xx_eh_host_reset_handler(Scsi_Cmnd *cmd) +int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd) { return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd); } @@ -1331,7 +1229,7 @@ static int device_queue_depth(hcb_p np, int target, int lun) * Linux entry point for device queue sizing. */ int -sym53c8xx_slave_configure(Scsi_Device *device) +sym53c8xx_slave_configure(struct scsi_device *device) { struct Scsi_Host *host = device->host; hcb_p np; @@ -1853,10 +1751,6 @@ static void sym_free_resources(hcb_p np) #ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING static int sym_setup_bus_dma_mask(hcb_p np) { -#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,3) - if (!pci_dma_supported(np->s.device, 0xffffffffUL)) - goto out_err32; -#else #if SYM_CONF_DMA_ADDRESSING_MODE == 0 if (pci_set_dma_mask(np->s.device, 0xffffffffUL)) goto out_err32; @@ -1879,7 +1773,6 @@ static int sym_setup_bus_dma_mask(hcb_p np) } #undef PciDmaMask #endif -#endif return 0; out_err32: @@ -1899,7 +1792,7 @@ out_err32: * start the timer daemon. */ static int __init -sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev) +sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) { struct host_data *host_data; hcb_p np = 0; @@ -1934,7 +1827,7 @@ sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev) /* * Allocate host_data structure */ - if (!(instance = scsi_register(tpnt, sizeof(*host_data)))) + if (!(instance = scsi_host_alloc(tpnt, sizeof(*host_data)))) goto attach_failed; host_data = (struct host_data *) instance->hostdata; @@ -1960,6 +1853,8 @@ sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev) host_data->ncb = np; np->s.host = instance; + pci_set_drvdata(dev->pdev, np); + SYM_INIT_LOCK_HCB(np); /* @@ -2106,11 +2001,7 @@ sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev) instance->max_id = np->maxwide ? 16 : 8; instance->max_lun = SYM_CONF_MAX_LUN; #ifndef SYM_CONF_IOMAPPED -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,29) instance->base = (unsigned long) np->s.mmio_va; -#else - instance->base = (char *) np->s.mmio_va; -#endif #endif instance->irq = np->s.irq; instance->unique_id = np->s.io_port; @@ -2120,23 +2011,21 @@ sym_attach (Scsi_Host_Template *tpnt, int unit, sym_device *dev) instance->cmd_per_lun = SYM_CONF_MAX_TAG; instance->can_queue = (SYM_CONF_MAX_START-2); instance->sg_tablesize = SYM_CONF_MAX_SG; -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) instance->max_cmd_len = 16; -#endif - instance->highmem_io = 1; SYM_UNLOCK_HCB(np, flags); - scsi_set_device(instance, &dev->pdev->dev); - /* * Now let the generic SCSI driver * look for the SCSI devices on the bus .. */ + scsi_add_host(instance, &dev->pdev->dev); /* XXX: handle failure */ + scsi_scan_host(instance); return 0; attach_failed: - if (!instance) return -1; + if (!instance) + return -1; printf_info("%s: giving up ...\n", sym_name(np)); if (np) sym_free_resources(np); @@ -2371,60 +2260,9 @@ int __init sym53c8xx_setup(char *str) return 1; } -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13) #ifndef MODULE __setup("sym53c8xx=", sym53c8xx_setup); #endif -#endif - -#ifdef SYM_CONF_PQS_PDS_SUPPORT -/* - * Detect all NCR PQS/PDS boards and keep track of their bus nr. - * - * The NCR PQS or PDS card is constructed as a DEC bridge - * behind which sit a proprietary NCR memory controller and - * four or two 53c875s as separate devices. In its usual mode - * of operation, the 875s are slaved to the memory controller - * for all transfers. We can tell if an 875 is part of a - * PQS/PDS or not since if it is, it will be on the same bus - * as the memory controller. To operate with the Linux - * driver, the memory controller is disabled and the 875s - * freed to function independently. The only wrinkle is that - * the preset SCSI ID (which may be zero) must be read in from - * a special configuration space register of the 875 - */ -#ifndef SYM_CONF_MAX_PQS_BUS -#define SYM_CONF_MAX_PQS_BUS 16 -#endif -static int pqs_bus[SYM_CONF_MAX_PQS_BUS] __initdata = { 0 }; - -static void __init sym_detect_pqs_pds(void) -{ - short index; - pcidev_t dev = PCIDEV_NULL; - - for(index=0; index < SYM_CONF_MAX_PQS_BUS; index++) { - u_char tmp; - - dev = pci_find_device(0x101a, 0x0009, dev); - if (dev == PCIDEV_NULL) { - pqs_bus[index] = -1; - break; - } - printf_info(NAME53C8XX ": NCR PQS/PDS memory controller detected on bus %d\n", PciBusNumber(dev)); - pci_read_config_byte(dev, 0x44, &tmp); - /* bit 1: allow individual 875 configuration */ - tmp |= 0x2; - pci_write_config_byte(dev, 0x44, tmp); - pci_read_config_byte(dev, 0x45, &tmp); - /* bit 2: drive individual 875 interrupts to the bus */ - tmp |= 0x4; - pci_write_config_byte(dev, 0x45, tmp); - - pqs_bus[index] = PciBusNumber(dev); - } -} -#endif /* SYM_CONF_PQS_PDS_SUPPORT */ /* * Read and check the PCI configuration for any detected NCR @@ -2432,7 +2270,7 @@ static void __init sym_detect_pqs_pds(void) * been detected. */ static int __init -sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, sym_device *device) +sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device) { u_short vendor_id, device_id, command, status_reg; u_char cache_line_size; @@ -2440,34 +2278,30 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, sym_device *device) u_char pci_fix_up = SYM_SETUP_PCI_FIX_UP; u_char revision; u_int irq; - u_long base, base_2, base_io; + u_long base, base_2; u_long base_c, base_2_c, io_port; int i; sym_chip *chip; /* Choose some short name for this device */ - sprintf(device->s.inst_name, "sym.%d.%d.%d", - PciBusNumber(pdev), - (int) (PciDeviceFn(pdev) & 0xf8) >> 3, - (int) (PciDeviceFn(pdev) & 7)); + sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* * Read needed minimal info from the PCI config space. */ - vendor_id = PciVendorId(pdev); - device_id = PciDeviceId(pdev); - irq = PciIrqLine(pdev); + vendor_id = pdev->vendor; + device_id = pdev->device; + irq = pdev->irq; - i = pci_get_base_address(pdev, 0, &base_io); - io_port = pci_get_base_cookie(pdev, 0); + io_port = pdev->resource[0].start; - base_c = pci_get_base_cookie(pdev, i); - i = pci_get_base_address(pdev, i, &base); + base_c = pdev->resource[1].start; + i = pci_get_base_address(pdev, 1, &base); - base_2_c = pci_get_base_cookie(pdev, i); - (void) pci_get_base_address(pdev, i, &base_2); + base_2_c = pdev->resource[i].start; + pci_get_base_address(pdev, i, &base_2); - io_port &= PCI_BASE_ADDRESS_IO_MASK; base &= PCI_BASE_ADDRESS_MEM_MASK; base_2 &= PCI_BASE_ADDRESS_MEM_MASK; @@ -2476,9 +2310,9 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, sym_device *device) /* * If user excluded this chip, donnot initialize it. */ - if (base_io) { + if (io_port) { for (i = 0 ; i < 8 ; i++) { - if (sym_driver_setup.excludes[i] == base_io) + if (sym_driver_setup.excludes[i] == io_port) return -1; } } @@ -2640,8 +2474,8 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, sym_device *device) * Initialise device structure with items required by sym_attach. */ device->pdev = pdev; - device->s.bus = PciBusNumber(pdev); - device->s.device_fn = PciDeviceFn(pdev); + device->s.bus = pdev->bus->number; + device->s.device_fn = pdev->devfn; device->s.base = base; device->s.base_2 = base_2; device->s.base_c = base_c; @@ -2653,26 +2487,7 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, sym_device *device) return 0; } -/* - * List of supported NCR chip ids - */ -static u_short sym_chip_ids[] __initdata = { - PCI_ID_SYM53C810, - PCI_ID_SYM53C815, - PCI_ID_SYM53C825, - PCI_ID_SYM53C860, - PCI_ID_SYM53C875, - PCI_ID_SYM53C875_2, - PCI_ID_SYM53C885, - PCI_ID_SYM53C875A, - PCI_ID_SYM53C895, - PCI_ID_SYM53C896, - PCI_ID_SYM53C895A, - PCI_ID_LSI53C1510D, - PCI_ID_LSI53C1010, - PCI_ID_LSI53C1010_2 -}; - +#if 0 /* * Detect all 53c8xx hosts and then attach them. * @@ -2683,9 +2498,9 @@ static u_short sym_chip_ids[] __initdata = { * If no NVRAM is found or data appears invalid attach boards in * the order they are detected. */ -int __init sym53c8xx_detect(Scsi_Host_Template *tpnt) +int __init sym53c8xx_detect(struct scsi_host_template *tpnt) { - pcidev_t pcidev; + struct pci_dev *pcidev; int i, j, chips, hosts, count; int attach_count = 0; sym_device *devtbl, *devp; @@ -2737,7 +2552,7 @@ if (sym53c8xx) #endif j = 0; count = 0; - pcidev = PCIDEV_NULL; + pcidev = NULL; while (1) { char *msg = ""; if (count >= hosts) @@ -2747,7 +2562,7 @@ if (sym53c8xx) i = sym_driver_setup.reverse_probe ? chips - 1 - j : j; pcidev = pci_find_device(PCI_VENDOR_ID_NCR, sym_chip_ids[i], pcidev); - if (pcidev == PCIDEV_NULL) { + if (pcidev == NULL) { ++j; continue; } @@ -2756,8 +2571,7 @@ if (sym53c8xx) continue; devp = &devtbl[count]; devp->host_id = SYM_SETUP_HOST_ID; - devp->attach_done = 0; - if (sym53c8xx_pci_init(tpnt, pcidev, devp)) { + if (sym53c8xx_pci_init(pcidev, devp)) { continue; } ++count; @@ -2789,7 +2603,7 @@ if (sym53c8xx) */ for(i = 0; i < SYM_CONF_MAX_PQS_BUS && pqs_bus[i] != -1; i++) { u_char tmp; - if (pqs_bus[i] == PciBusNumber(pcidev)) { + if (pqs_bus[i] == pcidev->bus->number) { pci_read_config_byte(pcidev, 0x84, &tmp); devp->pqs_pds = 1; devp->host_id = tmp; @@ -2868,7 +2682,7 @@ next: return attach_count; } - +#endif /* @@ -2883,32 +2697,7 @@ static int sym_detach(hcb_p np) { printk("%s: detaching ...\n", sym_name(np)); - /* - * Try to delete the timer. - * In the unlikely situation where this failed, - * try to synchronize with the timer handler. - */ -#if LINUX_VERSION_CODE < LinuxVersionCode(2, 4, 0) - np->s.release_stage = 1; - if (!del_timer(&np->s.timer)) { - int i = 1000; - int k = 1; - while (1) { - u_long flags; - SYM_LOCK_HCB(np, flags); - k = np->s.release_stage; - SYM_UNLOCK_HCB(np, flags); - if (k == 2 || !--i) - break; - MDELAY(5); - } - if (!i) - printk("%s: failed to kill timer!\n", sym_name(np)); - } - np->s.release_stage = 2; -#else - (void)del_timer_sync(&np->s.timer); -#endif + del_timer_sync(&np->s.timer); /* * Reset NCR chip. @@ -2928,27 +2717,26 @@ static int sym_detach(hcb_p np) return 1; } +#if 0 int sym53c8xx_release(struct Scsi_Host *host) { sym_detach(((struct host_data *) host->hostdata)->ncb); return 0; } +#endif -/* - * For bigots to keep silent. :) - */ -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); -#endif /* * Driver host template. */ -static Scsi_Host_Template driver_template = { +static struct scsi_host_template sym2_template = { .name = "sym53c8xx", +#if 0 .detect = sym53c8xx_detect, .release = sym53c8xx_release, +#endif .info = sym53c8xx_info, .queuecommand = sym53c8xx_queue_command, .slave_configure = sym53c8xx_slave_configure, @@ -2958,14 +2746,178 @@ static Scsi_Host_Template driver_template = { .eh_host_reset_handler = sym53c8xx_eh_host_reset_handler, .this_id = 7, .use_clustering = DISABLE_CLUSTERING, - .highmem_io = 1, #ifdef SYM_LINUX_PROC_INFO_SUPPORT .proc_info = sym53c8xx_proc_info, -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) - .proc_dir = &proc_scsi_sym53c8xx, -#else .proc_name = NAME53C8XX, #endif +}; + +#ifdef _SYM_CONF_PQS_PDS_SUPPORT +#if 0 +/* + * Detect all NCR PQS/PDS boards and keep track of their bus nr. + * + * The NCR PQS or PDS card is constructed as a DEC bridge + * behind which sit a proprietary NCR memory controller and + * four or two 53c875s as separate devices. In its usual mode + * of operation, the 875s are slaved to the memory controller + * for all transfers. We can tell if an 875 is part of a + * PQS/PDS or not since if it is, it will be on the same bus + * as the memory controller. To operate with the Linux + * driver, the memory controller is disabled and the 875s + * freed to function independently. The only wrinkle is that + * the preset SCSI ID (which may be zero) must be read in from + * a special configuration space register of the 875 + */ +#ifndef SYM_CONF_MAX_PQS_BUS +#define SYM_CONF_MAX_PQS_BUS 16 +#endif +static int pqs_bus[SYM_CONF_MAX_PQS_BUS] __initdata = { 0 }; + +static void __init sym_detect_pqs_pds(void) +{ + short index; + struct pci_dev *dev = NULL; + + for(index=0; index < SYM_CONF_MAX_PQS_BUS; index++) { + u_char tmp; + + dev = pci_find_device(0x101a, 0x0009, dev); + if (dev == NULL) { + pqs_bus[index] = -1; + break; + } + printf_info(NAME53C8XX ": NCR PQS/PDS memory controller detected on bus %d\n", dev->bus->number); + pci_read_config_byte(dev, 0x44, &tmp); + /* bit 1: allow individual 875 configuration */ + tmp |= 0x2; + pci_write_config_byte(dev, 0x44, tmp); + pci_read_config_byte(dev, 0x45, &tmp); + /* bit 2: drive individual 875 interrupts to the bus */ + tmp |= 0x4; + pci_write_config_byte(dev, 0x45, tmp); + + pqs_bus[index] = dev->bus->number; + } +} +#endif + +static int pqs_probe() +{ +} + +static void pqs_remove() +{ +} + +static struct pci_device_id pqs_id_table[] __devinitdata = { + { 0x101a, 0x0009, }, +}; + +MODULE_DEVICE_TABLE(pci, pqs_id_table); + +static struct pci_driver pqs_driver = { + .name = NAME53C8XX " (PQS)", + .id_table = pqs_id_table, + .probe = pqs_probe, + .remove = __devexit_p(pqs_remove), +}; +#endif /* PQS */ + +static int attach_count; + +static int __devinit sym2_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + sym_device sym_dev; + sym_nvram nvram; + + sym_dev.host_id = SYM_SETUP_HOST_ID; + if (sym53c8xx_pci_init(pdev, &sym_dev)) + return -ENODEV; + printk(KERN_INFO "%s: 53c%s detected\n", sym_name(&sym_dev), sym_dev.chip.name); + + sym_dev.nvram = &nvram; + nvram.type = 0; +#if SYM_CONF_NVRAM_SUPPORT + sym_get_nvram(&sym_dev, &nvram); #endif + + if (sym_attach(&sym2_template, attach_count, &sym_dev)) + return -ENODEV; + + attach_count++; + return 0; +} + +static void __devexit sym2_remove(struct pci_dev *pdev) +{ + sym_detach(pci_get_drvdata(pdev)); + attach_count--; +} + +static struct pci_device_id sym2_id_table[] __devinitdata = { + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C810, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C820, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, /* new */ + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C825, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C815, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C810AP, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, /* new */ + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C860, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1510, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C896, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C895, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C885, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C875, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C1510, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, /* new */ + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C895A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C875A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1010_33, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1010_66, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C875J, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, }; -#include "../scsi_module.c" + +MODULE_DEVICE_TABLE(pci, sym2_id_table); + +static struct pci_driver sym2_driver = { + .name = NAME53C8XX, + .id_table = sym2_id_table, + .probe = sym2_probe, + .remove = __devexit_p(sym2_remove), +}; + +static int __init sym2_init(void) +{ +#ifdef _SYM_CONF_PQS_PDS_SUPPORT + pci_register_driver(&pqs_driver); +#endif + pci_register_driver(&sym2_driver); + return 0; +} + +static void __exit sym2_exit(void) +{ + pci_unregister_driver(&sym2_driver); +#ifdef _SYM_CONF_PQS_PDS_SUPPORT + pci_unregister_driver(&pqs_driver); +#endif +} + +module_init(sym2_init); +module_exit(sym2_exit); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index 10904a7e3188..5ee8c1b63f0f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -57,20 +57,10 @@ #define SYM_CONF_DMA_ADDRESSING_MODE 2 #endif -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#include <linux/version.h> -#if LINUX_VERSION_CODE < LinuxVersionCode(2, 2, 0) -#error "This driver requires a kernel version not lower than 2.2.0" -#endif - #include <asm/dma.h> #include <asm/io.h> #include <asm/system.h> -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17) #include <linux/spinlock.h> -#else -#include <asm/spinlock.h> -#endif #include <linux/delay.h> #include <linux/signal.h> #include <linux/sched.h> @@ -91,29 +81,11 @@ #endif #include <linux/init.h> -#ifndef __init -#define __init -#endif -#ifndef __initdata -#define __initdata -#endif - #include "../scsi.h" #include "../hosts.h" #include <linux/types.h> -/* - * Define BITS_PER_LONG for earlier linux versions. - */ -#ifndef BITS_PER_LONG -#if (~0UL) == 0xffffffffUL -#define BITS_PER_LONG 32 -#else -#define BITS_PER_LONG 64 -#endif -#endif - typedef u_long vm_offset_t; #ifndef bcopy @@ -139,9 +111,7 @@ typedef u_long vm_offset_t; /* * Configuration addendum for Linux. */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,47) #define SYM_LINUX_DYNAMIC_DMA_MAPPING -#endif #define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2) @@ -472,9 +442,6 @@ struct sym_shcb { u_long lasttime; u_long settle_time; /* Resetting the SCSI BUS */ u_char settle_time_valid; -#if LINUX_VERSION_CODE < LinuxVersionCode(2, 4, 0) - u_char release_stage; /* Synchronisation on release */ -#endif }; /* @@ -647,9 +614,7 @@ static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid) { Scsi_Cmnd *cmd = cp->cam_ccb; -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,99) cmd->resid = resid; -#endif cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f)); } void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index ee67b5340adc..245fb97d923b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -978,16 +978,9 @@ BadDevice: static void storage_disconnect(struct usb_interface *intf) { struct us_data *us = usb_get_intfdata(intf); - struct scsi_device *sdev; US_DEBUGP("storage_disconnect() called\n"); - /* Set devices offline -- need host lock for this */ - scsi_lock(us->host); - list_for_each_entry(sdev, &us->host->my_devices, siblings) - sdev->online = 0; - scsi_unlock(us->host); - /* Prevent new USB transfers and stop the current command */ set_bit(US_FLIDX_DISCONNECTING, &us->flags); usb_stor_stop_transport(us); @@ -995,12 +988,7 @@ static void storage_disconnect(struct usb_interface *intf) /* Dissociate from the USB device */ dissociate_dev(us); - /* Begin the SCSI host removal sequence */ - if (scsi_remove_host(us->host)) { - US_DEBUGP("-- SCSI refused to remove the host\n"); - BUG(); - return; - } + scsi_remove_host(us->host); /* TODO: somehow, wait for the device to * be 'idle' (tasklet completion) */ diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 13603b67d7d6..776116d958a9 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -111,6 +111,9 @@ config BINFMT_MISC feature, and <file:Documentation/java.txt> for information about how to include Java support. + To use binfmt_misc, you will need to mount it: + mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc + You may say M here for module support and later load the module when you have use for it; the module is called binfmt_misc. If you don't know what to answer at this point, say Y. @@ -639,13 +639,13 @@ int aio_complete(struct kiocb *iocb, long res, long res2) iocb->ki_user_data = res; if (iocb->ki_users == 1) { iocb->ki_users = 0; - return 1; + ret = 1; + } else { + spin_lock_irq(&ctx->ctx_lock); + iocb->ki_users--; + ret = (0 == iocb->ki_users); + spin_unlock_irq(&ctx->ctx_lock); } - spin_lock_irq(&ctx->ctx_lock); - iocb->ki_users--; - ret = (0 == iocb->ki_users); - spin_unlock_irq(&ctx->ctx_lock); - /* sync iocbs put the task here for us */ wake_up_process(iocb->ki_user_obj); return ret; diff --git a/fs/befs/btree.c b/fs/befs/btree.c index 5d93d273509b..e1a0256f586c 100644 --- a/fs/befs/btree.c +++ b/fs/befs/btree.c @@ -86,7 +86,7 @@ typedef struct { } befs_btree_node; /* local constants */ -static const befs_off_t befs_bt_inval = 0xffffffffffffffff; +static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL; /* local functions */ static int befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds, diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index d0396689302e..1461252f66fe 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -90,7 +90,7 @@ xdr_encode_time(u32 *p, struct timespec *timep) { *p++ = htonl(timep->tv_sec); /* Convert nanoseconds into microseconds */ - *p++ = htonl(timep->tv_nsec / 1000); + *p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0); return p; } diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 02798d4b8cd8..71ca4d0e2019 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -4,6 +4,8 @@ * XDR support for nfsd/protocol version 3. * * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> + * + * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()! */ #include <linux/types.h> @@ -43,7 +45,7 @@ static u32 nfs3_ftypes[] = { static inline u32 * encode_time3(u32 *p, struct timespec *time) { - *p++ = htonl((u32) time->tv_sec); *p++ = htons(time->tv_nsec); + *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); return p; } diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index f724778dc44c..aa6b481595ea 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -123,13 +123,13 @@ decode_sattr(u32 *p, struct iattr *iap) if (tmp != (u32)-1 && tmp1 != (u32)-1) { iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; iap->ia_atime.tv_sec = tmp; - iap->ia_atime.tv_nsec = tmp1; + iap->ia_atime.tv_nsec = tmp1 * 1000; } tmp = ntohl(*p++); tmp1 = ntohl(*p++); if (tmp != (u32)-1 && tmp1 != (u32)-1) { iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; iap->ia_mtime.tv_sec = tmp; - iap->ia_mtime.tv_nsec = tmp1; + iap->ia_mtime.tv_nsec = tmp1 * 1000; } return p; } @@ -171,12 +171,12 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) *p++ = htonl((u32) stat.dev); *p++ = htonl((u32) stat.ino); *p++ = htonl((u32) stat.atime.tv_sec); - *p++ = htons(stat.atime.tv_nsec); + *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0); lease_get_mtime(dentry->d_inode, &time); *p++ = htonl((u32) time.tv_sec); - *p++ = htons(time.tv_nsec); + *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); *p++ = htonl((u32) stat.ctime.tv_sec); - *p++ = htons(stat.ctime.tv_nsec); + *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0); return p; } diff --git a/fs/partitions/efi.h b/fs/partitions/efi.h index bc1f5befea5a..d0eff3120ac8 100644 --- a/fs/partitions/efi.h +++ b/fs/partitions/efi.h @@ -39,7 +39,7 @@ #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE #define GPT_BLOCK_SIZE 512 -#define GPT_HEADER_SIGNATURE 0x5452415020494645L +#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL #define GPT_HEADER_REVISION_V1 0x00010000 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1 diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h index e853af05c2df..14abedb995c6 100644 --- a/fs/partitions/ldm.h +++ b/fs/partitions/ldm.h @@ -38,8 +38,8 @@ struct parsed_partitions; /* Magic numbers in CPU format. */ #define MAGIC_VMDB 0x564D4442 /* VMDB */ #define MAGIC_VBLK 0x56424C4B /* VBLK */ -#define MAGIC_PRIVHEAD 0x5052495648454144 /* PRIVHEAD */ -#define MAGIC_TOCBLOCK 0x544F43424C4F434B /* TOCBLOCK */ +#define MAGIC_PRIVHEAD 0x5052495648454144ULL /* PRIVHEAD */ +#define MAGIC_TOCBLOCK 0x544F43424C4F434BULL /* TOCBLOCK */ /* The defined vblk types. */ #define VBLK_VOL5 0x51 /* Volume, version 5 */ diff --git a/fs/reiserfs/hashes.c b/fs/reiserfs/hashes.c index eee4084e9cbc..08d0508c2d39 100644 --- a/fs/reiserfs/hashes.c +++ b/fs/reiserfs/hashes.c @@ -90,10 +90,6 @@ u32 keyed_hash(const signed char *msg, int len) if (len >= 12) { - //assert(len < 16); - if (len >= 16) - BUG(); - a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| @@ -116,9 +112,6 @@ u32 keyed_hash(const signed char *msg, int len) } else if (len >= 8) { - //assert(len < 12); - if (len >= 12) - BUG(); a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| @@ -137,9 +130,6 @@ u32 keyed_hash(const signed char *msg, int len) } else if (len >= 4) { - //assert(len < 8); - if (len >= 8) - BUG(); a = (u32)msg[ 0] | (u32)msg[ 1] << 8 | (u32)msg[ 2] << 16| @@ -154,9 +144,6 @@ u32 keyed_hash(const signed char *msg, int len) } else { - //assert(len < 4); - if (len >= 4) - BUG(); a = b = c = d = pad; for(i = 0; i < len; i++) { diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index 368f65b64360..f14d581fda8a 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h @@ -99,7 +99,7 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) } -/* void tlb_remove_page(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) +/* tlb_remove_page * Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)), while * handling the additional races in SMP caused by other CPUs caching valid * mappings in their TLBs. diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h index 0f458a0f115e..baabf274f815 100644 --- a/include/asm-ppc/smp.h +++ b/include/asm-ppc/smp.h @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/bitops.h> #include <linux/errno.h> +#include <linux/threads.h> #ifdef CONFIG_SMP diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h index 493aa82d889c..92260e080c5a 100644 --- a/include/asm-x86_64/bitops.h +++ b/include/asm-x86_64/bitops.h @@ -402,12 +402,12 @@ static inline void set_bit_string(unsigned long *bitmap, unsigned long i, } } -static inline void clear_bit_string(unsigned long *bitmap, unsigned long i, +static inline void __clear_bit_string(unsigned long *bitmap, unsigned long i, int len) { unsigned long end = i + len; while (i < end) { - clear_bit(i, bitmap); + __clear_bit(i, bitmap); i++; } } diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h index 45b50bf2679c..3d8256926d7c 100644 --- a/include/asm-x86_64/ia32_unistd.h +++ b/include/asm-x86_64/ia32_unistd.h @@ -264,7 +264,20 @@ #define __NR_ia32_sys_epoll_wait 256 #define __NR_ia32_remap_file_pages 257 #define __NR_ia32_set_tid_address 258 +#define __NR_ia32_timer_create 259 +#define __NR_ia32_timer_settime (__NR_ia32_timer_create+1) +#define __NR_ia32_timer_gettime (__NR_ia32_timer_create+2) +#define __NR_ia32_timer_getoverrun (__NR_ia32_timer_create+3) +#define __NR_ia32_timer_delete (__NR_ia32_timer_create+4) +#define __NR_ia32_clock_settime (__NR_ia32_timer_create+5) +#define __NR_ia32_clock_gettime (__NR_ia32_timer_create+6) +#define __NR_ia32_clock_getres (__NR_ia32_timer_create+7) +#define __NR_ia32_clock_nanosleep (__NR_ia32_timer_create+8) +#define __NR_ia32_statfs64 268 +#define __NR_ia32_fstatfs64 269 +#define __NR_ia32_tgkill 270 +#define __NR_ia32_utimes 271 -#define IA32_NR_syscalls 265 /* must be > than biggest syscall! */ +#define IA32_NR_syscalls 275 /* must be > than biggest syscall! */ #endif /* _ASM_X86_64_IA32_UNISTD_H_ */ diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h index b2cc4f1a241a..bf9738f9a23b 100644 --- a/include/asm-x86_64/io.h +++ b/include/asm-x86_64/io.h @@ -301,6 +301,12 @@ out: #define flush_write_buffers() +/* Disable vmerge for now. Need to fix the block layer code + to check for non iommu addresses first. + When the IOMMU is force it is safe to enable. */ +extern int force_iommu; +#define BIO_VERMGE_BOUNDARY (force_iommu ? 4096 : 0) + #endif /* __KERNEL__ */ #endif diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h index 66e9c5efc5e6..df002c539f58 100644 --- a/include/asm-x86_64/nmi.h +++ b/include/asm-x86_64/nmi.h @@ -48,6 +48,4 @@ static inline void unset_nmi_pm_callback(struct pm_dev * dev) extern void default_do_nmi(struct pt_regs *); -extern void default_do_nmi(struct pt_regs *); - #endif /* ASM_NMI_H */ diff --git a/include/asm-x86_64/pci-direct.h b/include/asm-x86_64/pci-direct.h index 5d9e1bec7144..08a2b783889f 100644 --- a/include/asm-x86_64/pci-direct.h +++ b/include/asm-x86_64/pci-direct.h @@ -14,7 +14,26 @@ static inline u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) u32 v; outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); v = inl(0xcfc); - PDprintk("%x reading from %x: %x\n", slot, offset, v); + if (v != 0xffffffff) + PDprintk("%x reading 4 from %x: %x\n", slot, offset, v); + return v; +} + +static inline u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset) +{ + u8 v; + outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); + v = inb(0xcfc + (offset&3)); + PDprintk("%x reading 1 from %x: %x\n", slot, offset, v); + return v; +} + +static inline u8 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset) +{ + u16 v; + outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); + v = inw(0xcfc + (offset&2)); + PDprintk("%x reading 2 from %x: %x\n", slot, offset, v); return v; } diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index 33550880dcbd..b072364de2bd 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -8,9 +8,6 @@ #include <linux/mm.h> /* for struct page */ - -extern dma_addr_t bad_dma_address; - /* Can be used to override the logic in pci_scan_bus for skipping already-configured bus numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the loader */ @@ -21,6 +18,8 @@ extern unsigned int pcibios_assign_all_busses(void); #define pcibios_assign_all_busses() 0 #endif +extern int no_iommu, force_iommu; + extern unsigned long pci_mem_start; #define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) @@ -46,6 +45,9 @@ struct pci_dev; extern int iommu_setup(char *opt); +extern dma_addr_t bad_dma_address; +#define pci_dma_error(x) ((x) == bad_dma_address) + /* Allocate and map kernel buffer using consistent mode DMA for a device. * hwdev should be valid struct pci_dev pointer for PCI devices, * NULL for PCI-like buses (ISA, EISA). @@ -119,10 +121,16 @@ static inline void pci_dma_sync_sg(struct pci_dev *hwdev, /* The PCI address space does equal the physical memory * address space. The networking and block device layers use - * this boolean for bounce buffer decisions. + * this boolean for bounce buffer decisions + * + * On AMD64 it mostly equals, but we set it to zero to tell some subsystems + * that an IOMMU is available. */ -#define PCI_DMA_BUS_IS_PHYS (0) +#define PCI_DMA_BUS_IS_PHYS (no_iommu ? 1 : 0) +/* We lie slightly when the IOMMU is forced to get the device to + use SAC instead of DAC. */ +#define pci_dac_dma_supported(pci_dev, mask) (force_iommu ? 0 : 1) #else static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, @@ -206,6 +214,7 @@ static inline void pci_dma_sync_sg(struct pci_dev *hwdev, #define PCI_DMA_BUS_IS_PHYS 1 +#define pci_dac_dma_supported(pci_dev, mask) 1 #endif extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, @@ -220,21 +229,7 @@ extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) -{ - /* - * we fall back to GFP_DMA when the mask isn't all 1s, - * so we can't guarantee allocations that must be - * within a tighter range than GFP_DMA.. - */ - if(mask < 0x00ffffff) - return 0; - - return 1; -} - -/* This is always fine. */ -#define pci_dac_dma_supported(pci_dev, mask) (1) +extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask); static __inline__ dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction) diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h index 578c6b12cf2b..832fc326fb02 100644 --- a/include/asm-x86_64/percpu.h +++ b/include/asm-x86_64/percpu.h @@ -1,53 +1,51 @@ #ifndef _ASM_X8664_PERCPU_H_ #define _ASM_X8664_PERCPU_H_ +#include <linux/compiler.h> -#include <asm/pda.h> +/* Same as asm-generic/percpu.h, except that we store the per cpu offset + in the PDA. Longer term the PDA and every per cpu variable + should be just put into a single section and referenced directly + from %gs */ #ifdef CONFIG_SMP -/* Same as the generic code except that we cache the per cpu offset - in the pda. This gives an 3 instruction reference for per cpu data */ - -#include <linux/compiler.h> #include <asm/pda.h> -#define __my_cpu_offset() read_pda(data_offset) + #define __per_cpu_offset(cpu) (cpu_pda[cpu].data_offset) +#define __my_cpu_offset() read_pda(data_offset) /* Separate out the type, so (int[3], foo) works. */ #define DEFINE_PER_CPU(type, name) \ - __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu + __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name /* var is in discarded region: offset to particular copy we want */ -#define per_cpu(var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset(cpu))) -#define __get_cpu_var(var) \ - (*RELOC_HIDE(&var##__per_cpu, __my_cpu_offset())) - -static inline void percpu_modcopy(void *pcpudst, const void *src, - unsigned long size) -{ - unsigned int i; - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) - memcpy(pcpudst + __per_cpu_offset(i), src, size); -} - -extern void setup_per_cpu_areas(void); - +#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu))) +#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset())) + +/* A macro to avoid #include hell... */ +#define percpu_modcopy(pcpudst, src, size) \ +do { \ + unsigned int __i; \ + for (__i = 0; __i < NR_CPUS; __i++) \ + if (cpu_possible(__i)) \ + memcpy((pcpudst)+__per_cpu_offset(__i), \ + (src), (size)); \ +} while (0) #else /* ! SMP */ #define DEFINE_PER_CPU(type, name) \ - __typeof__(type) name##__per_cpu + __typeof__(type) per_cpu__##name -#define per_cpu(var, cpu) ((void)cpu, var##__per_cpu) -#define __get_cpu_var(var) var##__per_cpu +#define per_cpu(var, cpu) ((void)cpu, per_cpu__##var) +#define __get_cpu_var(var) per_cpu__##var #endif /* SMP */ -#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu +#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name -#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu) -#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu) +#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) +#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) -DECLARE_PER_CPU(struct x8664_pda, per_cpu_pda); +extern void setup_per_cpu_areas(void); -#endif +#endif /* _ASM_X8664_PERCPU_H_ */ diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index ed86ba7abf06..5e176402f5c1 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -77,7 +77,7 @@ extern unsigned long end_pfn; extern unsigned long table_start, table_end; extern int exception_trace; -extern int no_iommu, force_mmu; +extern int force_iommu, no_iommu; extern int using_apic_timer; extern int disable_apic; extern unsigned cpu_khz; diff --git a/include/asm-x86_64/siginfo.h b/include/asm-x86_64/siginfo.h index dcb6b5731012..d09a1e6e7246 100644 --- a/include/asm-x86_64/siginfo.h +++ b/include/asm-x86_64/siginfo.h @@ -1,6 +1,8 @@ #ifndef _X8664_SIGINFO_H #define _X8664_SIGINFO_H +#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) + #include <asm-generic/siginfo.h> #endif diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 027d47e870ff..ac85fa9cd769 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -461,7 +461,7 @@ __SYSCALL(__NR_fremovexattr, sys_fremovexattr) #define __NR_tkill 200 __SYSCALL(__NR_tkill, sys_tkill) #define __NR_time 201 -__SYSCALL(__NR_time, sys_time) +__SYSCALL(__NR_time, sys_time64) #define __NR_futex 202 __SYSCALL(__NR_futex, sys_futex) #define __NR_sched_setaffinity 203 diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index f8459e01c896..ad1e168004ee 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -32,7 +32,7 @@ #endif struct tun_struct { - char *name; + struct list_head list; unsigned long flags; int attached; uid_t owner; diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 49207c629e4f..e4f91218676d 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -71,7 +71,7 @@ struct rt0_hdr { __u32 bitmap; /* strict/loose bit map */ struct in6_addr addr[0]; -#define rt0_type rt_hdr.type; +#define rt0_type rt_hdr.type }; struct ipv6_auth_hdr { diff --git a/include/linux/ppp-comp.h b/include/linux/ppp-comp.h index 82dd01c38920..7227e653b3be 100644 --- a/include/linux/ppp-comp.h +++ b/include/linux/ppp-comp.h @@ -185,10 +185,9 @@ struct compressor { #define DEFLATE_MIN_SIZE 9 #define DEFLATE_MAX_SIZE 15 #define DEFLATE_METHOD_VAL 8 -#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE) +#define DEFLATE_SIZE(x) (((x) >> 4) + 8) #define DEFLATE_METHOD(x) ((x) & 0x0F) -#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ - + DEFLATE_METHOD_VAL) +#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) #define DEFLATE_CHK_SEQUENCE 0 /* diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index a4dd169d9f6f..430370b12d13 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -37,6 +37,7 @@ struct xfrm_selector __u16 dport_mask; __u16 sport; __u16 sport_mask; + __u16 family; __u8 prefixlen_d; __u8 prefixlen_s; __u8 proto; @@ -125,6 +126,7 @@ enum struct xfrm_user_tmpl { struct xfrm_id id; + __u16 family; xfrm_address_t saddr; __u32 reqid; __u8 mode; @@ -189,7 +191,6 @@ struct xfrm_userpolicy_info { struct xfrm_lifetime_cur curlft; __u32 priority; __u32 index; - __u16 family; __u8 dir; __u8 action; #define XFRM_POLICY_ALLOW 0 diff --git a/include/net/dst.h b/include/net/dst.h index 8282f41ec600..42dd8f511cef 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -247,8 +247,16 @@ static inline int dst_input(struct sk_buff *skb) extern void dst_init(void); struct flowi; +#ifndef CONFIG_XFRM +static inline int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, + struct sock *sk, int flags) +{ + return 0; +} +#else extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, struct sock *sk, int flags); #endif +#endif #endif /* _NET_DST_H */ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 8aeb974d8592..9ed62a7db079 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -353,9 +353,7 @@ extern int ip6_push_pending_frames(struct sock *sk); extern void ip6_flush_pending_frames(struct sock *sk); -extern int ip6_dst_lookup(struct sock *sk, - struct dst_entry **dst, - struct flowi *fl); +extern struct dst_entry * ip6_dst_lookup(struct sock *sk, struct flowi *fl); /* * skb processing functions diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 337061ce242e..bca38f50f681 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -588,6 +588,8 @@ xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short return !0; } +#ifdef CONFIG_XFRM + extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family); static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) @@ -653,6 +655,26 @@ static inline void xfrm_sk_free_policy(struct sock *sk) } } +#else + +static inline void xfrm_sk_free_policy(struct sock *sk) {} +static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; } +static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; } +static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; } +static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb) +{ + return 1; +} +static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb) +{ + return 1; +} +static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) +{ + return 1; +} +#endif + static __inline__ xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family) { @@ -783,12 +805,32 @@ extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl); extern int xfrm_check_output(struct xfrm_state *x, struct sk_buff *skb, unsigned short family); extern int xfrm4_rcv(struct sk_buff *skb); -extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_check_size(struct sk_buff *skb); extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); + +#ifdef CONFIG_XFRM +extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen); +extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family); +#else +static inline int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen) +{ + return -ENOPROTOOPT; +} + +static inline int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) +{ + /* should not happen */ + kfree_skb(skb); + return 0; +} +static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family) +{ + return -EINVAL; +} +#endif void xfrm_policy_init(void); void xfrm4_policy_init(void); @@ -810,7 +852,6 @@ extern void xfrm_policy_kill(struct xfrm_policy *); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl); extern int xfrm_flush_bundles(struct xfrm_state *x); -extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family); extern wait_queue_head_t km_waitq; extern void km_state_expired(struct xfrm_state *x, int hard); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index de5ff9fd6c4a..04b8f47837a9 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -10,6 +10,16 @@ struct scsi_cmnd; struct scsi_mode_data; +/* + * sdev state + */ +enum { + SDEV_ADD, + SDEV_DEL, + SDEV_CANCEL, + SDEV_RECOVERY, +}; + struct scsi_device { struct list_head siblings; /* list of all devices on this host */ struct list_head same_target_siblings; /* just the devices sharing same target id */ @@ -86,14 +96,19 @@ struct scsi_device { struct device sdev_gendev; struct class_device sdev_classdev; + + unsigned long sdev_state; }; #define to_scsi_device(d) \ container_of(d, struct scsi_device, sdev_gendev) +#define class_to_sdev(d) \ + container_of(d, struct scsi_device, sdev_classdev) extern struct scsi_device *scsi_add_device(struct Scsi_Host *, uint, uint, uint); -extern int scsi_remove_device(struct scsi_device *); -extern void scsi_set_device_offline(struct scsi_device *); +extern void scsi_remove_device(struct scsi_device *); +extern int scsi_device_cancel_cb(struct device *, void *); +extern int scsi_device_cancel(struct scsi_device *, int); extern int scsi_device_get(struct scsi_device *); extern void scsi_device_put(struct scsi_device *); @@ -106,5 +121,4 @@ extern int scsi_set_medium_removal(struct scsi_device *, char); extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data); - #endif /* _SCSI_SCSI_DEVICE_H */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 3ef701078fef..7a2ccdf81e55 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -262,6 +262,12 @@ struct scsi_host_template { unsigned short max_sectors; /* + * dma scatter gather segment boundary limit. a segment crossing this + * boundary will be split in two. + */ + unsigned long dma_boundary; + + /* * This specifies "machine infinity" for host templates which don't * limit the transfer size. Note this limit represents an absolute * maximum, and may be over the transfer limits allowed for @@ -306,8 +312,6 @@ struct scsi_host_template { */ unsigned emulated:1; - unsigned highmem_io:1; - /* * True if the driver wishes to use the generic block layer * tag queueing functions @@ -348,6 +352,16 @@ struct scsi_host_template { struct list_head legacy_hosts; }; +/* + * shost states + */ +enum { + SHOST_ADD, + SHOST_DEL, + SHOST_CANCEL, + SHOST_RECOVERY, +}; + struct Scsi_Host { struct list_head my_devices; struct scsi_host_cmd_pool *cmd_pool; @@ -412,8 +426,8 @@ struct Scsi_Host { short cmd_per_lun; short unsigned int sg_tablesize; short unsigned int max_sectors; + unsigned long dma_boundary; - unsigned in_recovery:1; unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned highmem_io:1; @@ -448,6 +462,9 @@ struct Scsi_Host { unsigned char n_io_port; unsigned char dma_channel; unsigned int irq; + + + unsigned long shost_state; /* ldm bits */ struct device shost_gendev; @@ -478,8 +495,8 @@ struct Scsi_Host { extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int); extern int scsi_add_host(struct Scsi_Host *, struct device *); extern void scsi_scan_host(struct Scsi_Host *); -extern int scsi_remove_host(struct Scsi_Host *); -extern void scsi_host_get(struct Scsi_Host *); +extern void scsi_remove_host(struct Scsi_Host *); +extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *); extern void scsi_host_put(struct Scsi_Host *t); extern struct Scsi_Host *scsi_host_lookup(unsigned short); diff --git a/ipc/sem.c b/ipc/sem.c index d1a54864f753..b0d886377bb7 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -425,7 +425,7 @@ static void freeary (struct sem_array *sma, int id) ipc_rcu_free(sma, size); } -static unsigned long copy_semid_to_user(void *buf, struct semid64_ds *in, int version) +static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version) { switch(version) { case IPC_64: @@ -686,7 +686,7 @@ struct sem_setbuf { mode_t mode; }; -static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void *buf, int version) +static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __user *buf, int version) { switch(version) { case IPC_64: @@ -960,13 +960,13 @@ out: return un; } -asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops) +asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops) { return sys_semtimedop(semid, tsops, nsops, NULL); } -asmlinkage long sys_semtimedop(int semid, struct sembuf *tsops, - unsigned nsops, const struct timespec *timeout) +asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, + unsigned nsops, const struct timespec __user *timeout) { int error = -EINVAL; struct sem_array *sma; diff --git a/kernel/signal.c b/kernel/signal.c index bab76d941a3d..cd83653ef5d2 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1011,9 +1011,11 @@ void zap_other_threads(struct task_struct *p) * killed as part of a thread group due to another * thread doing an execve() or similar. So set the * exit signal to -1 to allow immediate reaping of - * the process. + * the process. But don't detach the thread group + * leader. */ - t->exit_signal = -1; + if (t != p->group_leader) + t->exit_signal = -1; sigaddset(&t->pending.signal, SIGKILL); rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 1bdfbac68637..80047ad9a25e 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -345,7 +345,7 @@ static void wb_kupdate(unsigned long arg) * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs */ int dirty_writeback_centisecs_handler(ctl_table *table, int write, - struct file *file, void *buffer, size_t *length) + struct file *file, void __user *buffer, size_t *length) { proc_dointvec(table, write, file, buffer, length); if (dirty_writeback_centisecs) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0ada7181364f..4d2d3ce1d430 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1610,7 +1610,7 @@ void setup_per_zone_pages_min(void) * changes. */ int min_free_kbytes_sysctl_handler(ctl_table *table, int write, - struct file *file, void *buffer, size_t *length) + struct file *file, void __user *buffer, size_t *length) { proc_dointvec(table, write, file, buffer, length); setup_per_zone_pages_min(); diff --git a/net/Kconfig b/net/Kconfig index 7b68450d1252..e2aa43ed5c15 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -83,6 +83,7 @@ config UNIX config NET_KEY tristate "PF_KEY sockets" + select XFRM ---help--- PF_KEYv2 socket family, compatible to KAME ones. They are required if you are going to use IPsec tools ported diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ef7095747c88..fceff2112058 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -225,7 +225,7 @@ void __kfree_skb(struct sk_buff *skb) } dst_release(skb->dst); -#ifdef CONFIG_INET +#ifdef CONFIG_XFRM secpath_put(skb->sp); #endif if(skb->destructor) { diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 22e98d25d467..cd82363b5897 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -187,6 +187,7 @@ config IP_PNP_RARP config NET_IPIP tristate "IP: tunneling" depends on INET + select XFRM ---help--- Tunneling means encapsulating data of one protocol type within another protocol and sending it over a channel that understands the @@ -205,6 +206,7 @@ config NET_IPIP config NET_IPGRE tristate "IP: GRE tunnels over IP" depends on INET + select XFRM help Tunneling means encapsulating data of one protocol type within another protocol and sending it over a channel that understands the @@ -343,6 +345,7 @@ config SYN_COOKIES config INET_AH tristate "IP: AH transformation" + select XFRM select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 @@ -354,6 +357,7 @@ config INET_AH config INET_ESP tristate "IP: ESP transformation" + select XFRM select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 @@ -366,6 +370,7 @@ config INET_ESP config INET_IPCOMP tristate "IP: IPComp transformation" + select XFRM select CRYPTO select CRYPTO_DEFLATE ---help--- diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 99c8f308bb60..5412b1caa989 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -23,4 +23,4 @@ obj-$(CONFIG_IP_PNP) += ipconfig.o obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_IP_VS) += ipvs/ -obj-y += xfrm4_policy.o xfrm4_state.o xfrm4_input.o xfrm4_tunnel.o +obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o xfrm4_tunnel.o diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 5ebb565c77d9..a713530ae557 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -279,6 +279,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) t->props.family = AF_INET; t->props.mode = 1; t->props.saddr.a4 = x->props.saddr.a4; + t->props.flags = x->props.flags; t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family); if (t->type == NULL) diff --git a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig index 33f519fc26da..49189f15a4d4 100644 --- a/net/ipv4/ipvs/Kconfig +++ b/net/ipv4/ipvs/Kconfig @@ -241,7 +241,7 @@ comment 'IPVS application helper' config IP_VS_FTP tristate "FTP protocol helper" - depends on IP_VS + depends on IP_VS && IP_VS_PROTO_TCP ---help--- FTP is a protocol that transfers IP address and/or port number in the payload. In the virtual server via Network Address Translation, diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 5695301dc253..f08b55144cb4 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -53,7 +53,9 @@ EXPORT_SYMBOL(ip_vs_proto_name); EXPORT_SYMBOL(ip_vs_conn_new); EXPORT_SYMBOL(ip_vs_conn_in_get); EXPORT_SYMBOL(ip_vs_conn_out_get); +#ifdef CONFIG_IP_VS_PROTO_TCP EXPORT_SYMBOL(ip_vs_tcp_conn_listen); +#endif EXPORT_SYMBOL(ip_vs_conn_put); #ifdef CONFIG_IP_VS_DEBUG EXPORT_SYMBOL(ip_vs_get_debug_level); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f54290251fc8..e60f43256f7a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2785,8 +2785,10 @@ int __init ip_rt_init(void) create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read, NULL); #endif #endif +#ifdef CONFIG_XFRM xfrm_init(); xfrm4_init(); +#endif out: return rc; out_enomem: diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index fbd17044ec5b..a4c77ae53c21 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -109,6 +109,7 @@ static int ipv4_sysctl_forward_strategy(ctl_table *table, int *name, int nlen, } } + *valp = new; inet_forward_change(); return 1; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6049b4853a65..08c3a40a4bd2 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -938,6 +938,9 @@ static void udp_close(struct sock *sk, long timeout) */ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) { +#ifndef CONFIG_XFRM + return 1; +#else struct udp_opt *up = udp_sk(sk); struct udphdr *uh = skb->h.uh; struct iphdr *iph; @@ -997,10 +1000,12 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) return -1; default: - printk(KERN_INFO "udp_encap_rcv(): Unhandled UDP encap type: %u\n", - encap_type); + if (net_ratelimit()) + printk(KERN_INFO "udp_encap_rcv(): Unhandled UDP encap type: %u\n", + encap_type); return 1; } +#endif } /* returns: diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 2412f9398682..9040408dbf81 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -27,6 +27,20 @@ static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff IP_ECN_set_ce(inner_iph); } +static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) +{ + switch (nexthdr) { + case IPPROTO_IPIP: + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + return -EINVAL; + *spi = skb->nh.iph->saddr; + *seq = 0; + return 0; + } + + return xfrm_parse_spi(skb, nexthdr, spi, seq); +} + int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) { int err; @@ -36,7 +50,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) int xfrm_nr = 0; int decaps = 0; - if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0) + if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0) goto drop; do { diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 1d0d2417893b..c4389b6f8d29 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -83,31 +83,8 @@ error_nolock: return err; } -static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) -{ - struct iphdr *inner_iph = skb->nh.iph; - - if (INET_ECN_is_ce(outer_iph->tos) && - INET_ECN_is_not_ce(inner_iph->tos)) - IP_ECN_set_ce(inner_iph); -} - static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { - struct iphdr *outer_iph = skb->nh.iph; - - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - return -EINVAL; - skb->mac.raw = skb->nh.raw; - skb->nh.raw = skb->data; - memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); - dst_release(skb->dst); - skb->dst = NULL; - skb->protocol = htons(ETH_P_IP); - skb->pkt_type = PACKET_HOST; - ipip_ecn_decapsulate(outer_iph, skb); - netif_rx(skb); - return 0; } @@ -149,46 +126,12 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) static int ipip_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler = ipip_handler; - struct xfrm_state *x = NULL; - int err; /* Tunnel devices take precedence. */ - if (handler) { - err = handler->handler(skb); - if (!err) - goto out; - } + if (handler && handler->handler(skb) == 0) + return 0; - x = xfrm_state_lookup((xfrm_address_t *)&skb->nh.iph->daddr, - skb->nh.iph->saddr, - IPPROTO_IPIP, AF_INET); - - if (!x) - goto drop; - - spin_lock(&x->lock); - - if (unlikely(x->km.state != XFRM_STATE_VALID)) - goto drop_unlock; - - err = ipip_xfrm_rcv(x, NULL, skb); - if (err) - goto drop_unlock; - - x->curlft.bytes += skb->len; - x->curlft.packets++; - spin_unlock(&x->lock); - xfrm_state_put(x); -out: - return err; - -drop_unlock: - spin_unlock(&x->lock); - xfrm_state_put(x); -drop: - err = NET_RX_DROP; - kfree_skb(skb); - goto out; + return xfrm4_rcv_encap(skb, 0); } static void ipip_err(struct sk_buff *skb, u32 info) diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index e74a41b878d9..f5b568867e08 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -22,6 +22,7 @@ config IPV6_PRIVACY config INET6_AH tristate "IPv6: AH transformation" depends on IPV6 + select XFRM select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 @@ -34,6 +35,7 @@ config INET6_AH config INET6_ESP tristate "IPv6: ESP transformation" depends on IPV6 + select XFRM select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 @@ -47,6 +49,7 @@ config INET6_ESP config INET6_IPCOMP tristate "IPv6: IPComp transformation" depends on IPV6 + select XFRM select CRYPTO select CRYPTO_DEFLATE ---help--- diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index cb3303428145..07d9848f02df 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -8,8 +8,10 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ - ip6_flowlabel.o ipv6_syms.o \ - xfrm6_policy.o xfrm6_state.o xfrm6_input.o + ip6_flowlabel.o ipv6_syms.o + +ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o +ipv6-objs += $(ipv6-y) obj-$(CONFIG_INET6_AH) += ah6.o obj-$(CONFIG_INET6_ESP) += esp6.o diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 925effb2390c..774ae2156efa 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2593,6 +2593,53 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp, return ret; } +static int addrconf_sysctl_forward_strategy(ctl_table *table, + int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, + void **context) +{ + int *valp = table->data; + int new; + + if (!newval || !newlen) + return 0; + if (newlen != sizeof(int)) + return -EINVAL; + if (get_user(new, (int *)newval)) + return -EFAULT; + if (new == *valp) + return 0; + if (oldval && oldlenp) { + size_t len; + if (get_user(len, oldlenp)) + return -EFAULT; + if (len) { + if (len > table->maxlen) + len = table->maxlen; + if (copy_to_user(oldval, valp, len)) + return -EFAULT; + if (put_user(len, oldlenp)) + return -EFAULT; + } + } + + if (valp != &ipv6_devconf_dflt.forwarding) { + struct inet6_dev *idev; + if (valp != &ipv6_devconf.forwarding) { + idev = (struct inet6_dev *)table->extra1; + if (unlikely(idev == NULL)) + return -ENODEV; + } else + idev = NULL; + *valp = new; + addrconf_forward_change(idev); + } else + *valp = new; + + return 1; +} + static struct addrconf_sysctl_table { struct ctl_table_header *sysctl_header; @@ -2611,6 +2658,7 @@ static struct addrconf_sysctl_table .maxlen = sizeof(int), .mode = 0644, .proc_handler = &addrconf_sysctl_forward, + .strategy = &addrconf_sysctl_forward_strategy, }, { .ctl_name = NET_IPV6_HOP_LIMIT, diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 07d92a2e48a3..c13efb13eaf9 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -265,13 +265,12 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu * There is offset of AH before IPv6 header after the process. */ - struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6_auth_hdr *ah; struct ah_data *ahp; unsigned char *tmp_hdr = NULL; - u16 hdr_len = skb->data - skb->nh.raw; + u16 hdr_len; u16 ah_hlen; - u16 cleared_hlen = hdr_len; + u16 cleared_hlen; u16 nh_offset = 0; u8 nexthdr = 0; u8 *prevhdr; @@ -279,6 +278,14 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) goto out; + /* We are going to _remove_ AH header to keep sockets happy, + * so... Later this can change. */ + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto out; + + hdr_len = skb->data - skb->nh.raw; + cleared_hlen = hdr_len; ah = (struct ipv6_auth_hdr*)skb->data; ahp = x->data; nexthdr = ah->nexthdr; @@ -297,27 +304,22 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu if (!pskb_may_pull(skb, ah_hlen)) goto out; - /* We are going to _remove_ AH header to keep sockets happy, - * so... Later this can change. */ - if (skb_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - goto out; - tmp_hdr = kmalloc(cleared_hlen, GFP_ATOMIC); if (!tmp_hdr) goto out; memcpy(tmp_hdr, skb->nh.raw, cleared_hlen); ipv6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN); - iph->priority = 0; - iph->flow_lbl[0] = 0; - iph->flow_lbl[1] = 0; - iph->flow_lbl[2] = 0; - iph->hop_limit = 0; + skb->nh.ipv6h->priority = 0; + skb->nh.ipv6h->flow_lbl[0] = 0; + skb->nh.ipv6h->flow_lbl[1] = 0; + skb->nh.ipv6h->flow_lbl[2] = 0; + skb->nh.ipv6h->hop_limit = 0; { u8 auth_data[ahp->icv_trunc_len]; memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); + memset(ah->auth_data, 0, ahp->icv_trunc_len); skb_push(skb, skb->data - skb->nh.raw); ahp->icv(ahp, skb, ah->auth_data); if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 727b681325aa..cbf54afae93b 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -355,8 +355,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - err = ip6_dst_lookup(sk, &dst, &fl); - if (err) goto out; + dst = ip6_dst_lookup(sk, &fl); + if (dst->error) goto out; if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) @@ -434,9 +434,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb) if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - err = ip6_dst_lookup(sk, &dst, &fl); + dst = ip6_dst_lookup(sk, &fl); - if (err) goto out; + if (dst->error) goto out; if (hlimit < 0) { if (ipv6_addr_is_multicast(&fl.fl6_dst)) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 6a5eaec0c3bd..840d4117d419 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -209,11 +209,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, int seg_len = skb->len; int hlimit; u32 mtu; - int err = 0; - - if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) { - return err; - } if (opt) { int head_room; @@ -1141,72 +1136,73 @@ fail: return err; } -int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) +struct dst_entry *ip6_dst_lookup(struct sock *sk, struct flowi *fl) { - struct ipv6_pinfo *np = inet6_sk(sk); + struct dst_entry *dst = NULL; int err = 0; - *dst = __sk_dst_check(sk, np->dst_cookie); - if (*dst) { - struct rt6_info *rt = (struct rt6_info*)*dst; - - /* Yes, checking route validity in not connected - case is not very simple. Take into account, - that we do not support routing by source, TOS, - and MSG_DONTROUTE --ANK (980726) - - 1. If route was host route, check that - cached destination is current. - If it is network route, we still may - check its validity using saved pointer - to the last used address: daddr_cache. - We do not want to save whole address now, - (because main consumer of this service - is tcp, which has not this problem), - so that the last trick works only on connected - sockets. - 2. oif also should be the same. - */ - - if (((rt->rt6i_dst.plen != 128 || - ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr)) - && (np->daddr_cache == NULL || - ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache))) - || (fl->oif && fl->oif != (*dst)->dev->ifindex)) { - *dst = NULL; - } else - dst_hold(*dst); + if (sk) { + struct ipv6_pinfo *np = inet6_sk(sk); + + dst = __sk_dst_check(sk, np->dst_cookie); + if (dst) { + struct rt6_info *rt = (struct rt6_info*)dst; + + /* Yes, checking route validity in not connected + case is not very simple. Take into account, + that we do not support routing by source, TOS, + and MSG_DONTROUTE --ANK (980726) + + 1. If route was host route, check that + cached destination is current. + If it is network route, we still may + check its validity using saved pointer + to the last used address: daddr_cache. + We do not want to save whole address now, + (because main consumer of this service + is tcp, which has not this problem), + so that the last trick works only on connected + sockets. + 2. oif also should be the same. + */ + + if (((rt->rt6i_dst.plen != 128 || + ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr)) + && (np->daddr_cache == NULL || + ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache))) + || (fl->oif && fl->oif != dst->dev->ifindex)) { + dst = NULL; + } else + dst_hold(dst); + } } - if (*dst == NULL) - *dst = ip6_route_output(sk, fl); + if (dst == NULL) + dst = ip6_route_output(sk, fl); - if ((*dst)->error) { - IP6_INC_STATS(Ip6OutNoRoutes); - dst_release(*dst); - return -ENETUNREACH; - } + if (dst->error) + return dst; if (ipv6_addr_any(&fl->fl6_src)) { - err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); + err = ipv6_get_saddr(dst, &fl->fl6_dst, &fl->fl6_src); if (err) { #if IP6_DEBUG >= 2 printk(KERN_DEBUG "ip6_build_xmit: " "no available source address\n"); #endif - return err; + dst->error = err; + return dst; } } - if (*dst) { - if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) { - dst_release(*dst); - return -ENETUNREACH; + if (dst) { + if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) { + dst->error = -ENETUNREACH; } } - return 0; + return dst; } int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 221a1dd22cbc..8aff8d51527e 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -621,6 +621,14 @@ merge_options(struct sock *sk, __u8 encap_limit, return opt; } +static int +ip6ip6_getfrag(void *from, char *to, int offset, int len, int odd, + struct sk_buff *skb) +{ + memcpy(to, (char *) from + offset, len); + return 0; +} + /** * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own * @t: the outgoing tunnel device @@ -755,9 +763,9 @@ int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) } if (skb->len > mtu) { icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); - goto tx_err_opt_release; + goto tx_err_dst_release; } - err = ip6_append_data(sk, ip_generic_getfrag, skb->nh.raw, skb->len, 0, + err = ip6_append_data(sk, ip6ip6_getfrag, skb->nh.raw, skb->len, 0, t->parms.hop_limit, opt, &fl, (struct rt6_info *)dst, MSG_DONTWAIT); @@ -785,7 +793,6 @@ int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) return 0; tx_err_dst_release: dst_release(dst); -tx_err_opt_release: if (opt && opt != orig_opt) sock_kfree_s(sk, opt, opt->tot_len); tx_err_free_fl_lbl: diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index a6eba6e81dbf..178f2cb0f629 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c @@ -36,7 +36,9 @@ EXPORT_SYMBOL(in6addr_any); EXPORT_SYMBOL(in6addr_loopback); EXPORT_SYMBOL(in6_dev_finish_destroy); EXPORT_SYMBOL(ip6_find_1stfragopt); +#ifdef CONFIG_XFRM EXPORT_SYMBOL(xfrm6_rcv); +#endif EXPORT_SYMBOL(rt6_lookup); EXPORT_SYMBOL(fl6_sock_lookup); EXPORT_SYMBOL(ipv6_ext_hdr); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ac2dbb6d0a0e..c5d193728e75 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -658,8 +658,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - err = ip6_dst_lookup(sk, &dst, &fl); - if (err) + dst = ip6_dst_lookup(sk, &fl); + if ((err = dst->error)) goto out; if (hlimit < 0) { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b3adf22ef02e..692c0477837c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1988,7 +1988,9 @@ void __init ip6_route_init(void) if (p) p->proc_fops = &rt6_stats_seq_fops; #endif +#ifdef CONFIG_XFRM xfrm6_init(); +#endif } #ifdef MODULE diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e5cd4c372577..4d16e99a8e84 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -663,7 +663,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_route_output(sk, &fl); + dst = ip6_dst_lookup(sk, &fl); if ((err = dst->error) != 0) { dst_release(dst); @@ -691,6 +691,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, tp->ext_header_len = 0; if (np->opt) tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen; + tp->ext2_header_len = dst->header_len; + tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); inet->dport = usin->sin6_port; @@ -788,7 +790,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, fl.fl_ip_dport = inet->dport; fl.fl_ip_sport = inet->sport; - dst = ip6_route_output(sk, &fl); + dst = ip6_dst_lookup(sk, &fl); } else dst_hold(dst); @@ -889,7 +891,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_route_output(sk, &fl); + dst = ip6_dst_lookup(sk, &fl); if (dst->error) goto done; } @@ -1018,7 +1020,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb) fl.fl_ip_sport = t1->source; /* sk = NULL, but it is safe for now. RST socket required. */ - buff->dst = ip6_route_output(NULL, &fl); + buff->dst = ip6_dst_lookup(NULL, &fl); if (buff->dst->error == 0) { ip6_xmit(NULL, buff, &fl, NULL, 0); @@ -1081,7 +1083,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 fl.fl_ip_dport = t1->dest; fl.fl_ip_sport = t1->source; - buff->dst = ip6_route_output(NULL, &fl); + buff->dst = ip6_dst_lookup(NULL, &fl); if (buff->dst->error == 0) { ip6_xmit(NULL, buff, &fl, NULL, 0); @@ -1329,7 +1331,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, fl.fl_ip_dport = req->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; - dst = ip6_route_output(sk, &fl); + dst = ip6_dst_lookup(sk, &fl); } if (dst->error) @@ -1401,6 +1403,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, if (newnp->opt) newtp->ext_header_len = newnp->opt->opt_nflen + newnp->opt->opt_flen; + newtp->ext2_header_len = dst->header_len; tcp_sync_mss(newsk, dst_pmtu(dst)); newtp->advmss = dst_metric(dst, RTAX_ADVMSS); @@ -1727,7 +1730,7 @@ static int tcp_v6_rebuild_header(struct sock *sk) ipv6_addr_copy(&fl.fl6_dst, rt0->addr); } - dst = ip6_route_output(sk, &fl); + dst = ip6_dst_lookup(sk, &fl); if (dst->error) { err = dst->error; @@ -1770,7 +1773,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) dst = __sk_dst_check(sk, np->dst_cookie); if (dst == NULL) { - dst = ip6_route_output(sk, &fl); + dst = ip6_dst_lookup(sk, &fl); if (dst->error) { sk->sk_err_soft = -dst->error; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 40859abf1600..699cbc866c77 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -811,8 +811,10 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg * The socket lock must be held while it's corked. */ lock_sock(sk); - if (likely(up->pending)) + if (likely(up->pending)) { + dst = NULL; goto do_append_data; + } release_sock(sk); } ulen += sizeof(struct udphdr); @@ -928,8 +930,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - err = ip6_dst_lookup(sk, &dst, &fl); - if (err) + dst = ip6_dst_lookup(sk, &fl); + if ((err = dst->error)) goto out; if (hlimit < 0) { @@ -968,9 +970,10 @@ do_append_data: else if (!corkreq) err = udp_v6_push_pending_frames(sk, up); - ip6_dst_store(sk, dst, - !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ? - &np->daddr : NULL); + if (dst) + ip6_dst_store(sk, dst, + !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ? + &np->daddr : NULL); if (err > 0) err = np->recverr ? net_xmit_errno(err) : 0; release_sock(sk); diff --git a/net/netsyms.c b/net/netsyms.c index 78efec6ffb89..2fa1ef842b1b 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -56,7 +56,6 @@ extern __u32 sysctl_rmem_max; #include <linux/inet.h> #include <linux/mroute.h> #include <linux/igmp.h> -#include <net/xfrm.h> #if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) #include <net/ah.h> #endif @@ -276,6 +275,7 @@ EXPORT_SYMBOL(ip_dev_find); EXPORT_SYMBOL(inetdev_by_index); EXPORT_SYMBOL(in_dev_finish_destroy); EXPORT_SYMBOL(ip_defrag); +EXPORT_SYMBOL(inet_peer_idlock); /* Route manipulation */ EXPORT_SYMBOL(ip_rt_ioctl); @@ -293,80 +293,6 @@ EXPORT_SYMBOL(tcp_proc_unregister); /* needed for ip_gre -cw */ EXPORT_SYMBOL(ip_statistics); - -EXPORT_SYMBOL(xfrm_user_policy); -EXPORT_SYMBOL(km_waitq); -EXPORT_SYMBOL(km_new_mapping); -EXPORT_SYMBOL(xfrm_cfg_sem); -EXPORT_SYMBOL(xfrm_policy_alloc); -EXPORT_SYMBOL(__xfrm_policy_destroy); -EXPORT_SYMBOL(xfrm_lookup); -EXPORT_SYMBOL(__xfrm_policy_check); -EXPORT_SYMBOL(__xfrm_route_forward); -EXPORT_SYMBOL(xfrm_state_alloc); -EXPORT_SYMBOL(__xfrm_state_destroy); -EXPORT_SYMBOL(xfrm_state_find); -EXPORT_SYMBOL(xfrm_state_insert); -EXPORT_SYMBOL(xfrm_state_add); -EXPORT_SYMBOL(xfrm_state_update); -EXPORT_SYMBOL(xfrm_state_check_expire); -EXPORT_SYMBOL(xfrm_state_check_space); -EXPORT_SYMBOL(xfrm_state_lookup); -EXPORT_SYMBOL(xfrm_state_register_afinfo); -EXPORT_SYMBOL(xfrm_state_unregister_afinfo); -EXPORT_SYMBOL(xfrm_state_get_afinfo); -EXPORT_SYMBOL(xfrm_state_put_afinfo); -EXPORT_SYMBOL(xfrm_state_delete_tunnel); -EXPORT_SYMBOL(xfrm_replay_check); -EXPORT_SYMBOL(xfrm_replay_advance); -EXPORT_SYMBOL(xfrm_check_selectors); -EXPORT_SYMBOL(xfrm_check_output); -EXPORT_SYMBOL(__secpath_destroy); -EXPORT_SYMBOL(secpath_dup); -EXPORT_SYMBOL(xfrm_get_acqseq); -EXPORT_SYMBOL(xfrm_parse_spi); -EXPORT_SYMBOL(xfrm4_rcv); -EXPORT_SYMBOL(xfrm4_tunnel_register); -EXPORT_SYMBOL(xfrm4_tunnel_deregister); -EXPORT_SYMBOL(xfrm4_tunnel_check_size); -EXPORT_SYMBOL(xfrm_register_type); -EXPORT_SYMBOL(xfrm_unregister_type); -EXPORT_SYMBOL(xfrm_get_type); -EXPORT_SYMBOL(inet_peer_idlock); -EXPORT_SYMBOL(xfrm_register_km); -EXPORT_SYMBOL(xfrm_unregister_km); -EXPORT_SYMBOL(xfrm_state_delete); -EXPORT_SYMBOL(xfrm_state_walk); -EXPORT_SYMBOL(xfrm_find_acq_byseq); -EXPORT_SYMBOL(xfrm_find_acq); -EXPORT_SYMBOL(xfrm_alloc_spi); -EXPORT_SYMBOL(xfrm_state_flush); -EXPORT_SYMBOL(xfrm_policy_kill); -EXPORT_SYMBOL(xfrm_policy_bysel); -EXPORT_SYMBOL(xfrm_policy_insert); -EXPORT_SYMBOL(xfrm_policy_walk); -EXPORT_SYMBOL(xfrm_policy_flush); -EXPORT_SYMBOL(xfrm_policy_byid); -EXPORT_SYMBOL(xfrm_policy_list); -EXPORT_SYMBOL(xfrm_dst_lookup); -EXPORT_SYMBOL(xfrm_policy_register_afinfo); -EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); -EXPORT_SYMBOL(xfrm_policy_get_afinfo); -EXPORT_SYMBOL(xfrm_policy_put_afinfo); - -EXPORT_SYMBOL_GPL(xfrm_probe_algs); -EXPORT_SYMBOL_GPL(xfrm_count_auth_supported); -EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); -EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx); -EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx); -EXPORT_SYMBOL_GPL(xfrm_calg_get_byidx); -EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid); -EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); -EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); -EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); -EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); -EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); -EXPORT_SYMBOL_GPL(skb_icv_walk); #if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) EXPORT_SYMBOL_GPL(skb_cow_data); EXPORT_SYMBOL_GPL(pskb_put); @@ -482,10 +408,8 @@ EXPORT_SYMBOL(sysctl_tcp_tw_recycle); EXPORT_SYMBOL(sysctl_max_syn_backlog); #endif -#endif - -#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE) || defined (CONFIG_IPV6_TUNNEL_MODULE) EXPORT_SYMBOL(ip_generic_getfrag); + #endif EXPORT_SYMBOL(tcp_read_sock); diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f6eea03b1e47..42f9f6bc359b 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -567,14 +567,17 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) (serv->sv_nrthreads+3) * serv->sv_bufsz, (serv->sv_nrthreads+3) * serv->sv_bufsz); - if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) + if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) { + svc_sock_received(svsk); return svc_deferred_recv(rqstp); + } clear_bit(SK_DATA, &svsk->sk_flags); while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { - svc_sock_received(svsk); - if (err == -EAGAIN) + if (err == -EAGAIN) { + svc_sock_received(svsk); return err; + } /* possibly an icmp error */ dprintk("svc: recvfrom returned error %d\n", -err); } @@ -869,8 +872,10 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) test_bit(SK_CONN, &svsk->sk_flags), test_bit(SK_CLOSE, &svsk->sk_flags)); - if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) + if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) { + svc_sock_received(svsk); return svc_deferred_recv(rqstp); + } if (test_bit(SK_CLOSE, &svsk->sk_flags)) { svc_delete_socket(svsk); @@ -1545,6 +1550,5 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk) set_bit(SK_DEFERRED, &svsk->sk_flags); } spin_unlock(&serv->sv_lock); - svc_sock_received(svsk); return dr; } diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig index f58b5094b183..58c7d2671389 100644 --- a/net/xfrm/Kconfig +++ b/net/xfrm/Kconfig @@ -1,9 +1,13 @@ # # XFRM configuration # +config XFRM + bool + depends on NET + config XFRM_USER tristate "IPsec user configuration interface" - depends on INET + depends on INET && XFRM ---help--- Support for IPsec user configuration interface used by native Linux tools. diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile index 227f8ec08a69..7cf00be13197 100644 --- a/net/xfrm/Makefile +++ b/net/xfrm/Makefile @@ -2,6 +2,7 @@ # Makefile for the XFRM subsystem. # -obj-y := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o xfrm_output.o +obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o xfrm_output.o \ + xfrm_export.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c new file mode 100644 index 000000000000..fdd4d0ee7af7 --- /dev/null +++ b/net/xfrm/xfrm_export.c @@ -0,0 +1,75 @@ +#include <linux/module.h> +#include <net/xfrm.h> + +EXPORT_SYMBOL(xfrm_user_policy); +EXPORT_SYMBOL(km_waitq); +EXPORT_SYMBOL(km_new_mapping); +EXPORT_SYMBOL(xfrm_cfg_sem); +EXPORT_SYMBOL(xfrm_policy_alloc); +EXPORT_SYMBOL(__xfrm_policy_destroy); +EXPORT_SYMBOL(xfrm_lookup); +EXPORT_SYMBOL(__xfrm_policy_check); +EXPORT_SYMBOL(__xfrm_route_forward); +EXPORT_SYMBOL(xfrm_state_alloc); +EXPORT_SYMBOL(__xfrm_state_destroy); +EXPORT_SYMBOL(xfrm_state_find); +EXPORT_SYMBOL(xfrm_state_insert); +EXPORT_SYMBOL(xfrm_state_add); +EXPORT_SYMBOL(xfrm_state_update); +EXPORT_SYMBOL(xfrm_state_check_expire); +EXPORT_SYMBOL(xfrm_state_check_space); +EXPORT_SYMBOL(xfrm_state_lookup); +EXPORT_SYMBOL(xfrm_state_register_afinfo); +EXPORT_SYMBOL(xfrm_state_unregister_afinfo); +EXPORT_SYMBOL(xfrm_state_get_afinfo); +EXPORT_SYMBOL(xfrm_state_put_afinfo); +EXPORT_SYMBOL(xfrm_state_delete_tunnel); +EXPORT_SYMBOL(xfrm_replay_check); +EXPORT_SYMBOL(xfrm_replay_advance); +EXPORT_SYMBOL(xfrm_check_selectors); +EXPORT_SYMBOL(xfrm_check_output); +EXPORT_SYMBOL(__secpath_destroy); +EXPORT_SYMBOL(secpath_dup); +EXPORT_SYMBOL(xfrm_get_acqseq); +EXPORT_SYMBOL(xfrm_parse_spi); +EXPORT_SYMBOL(xfrm4_rcv); +EXPORT_SYMBOL(xfrm4_tunnel_register); +EXPORT_SYMBOL(xfrm4_tunnel_deregister); +EXPORT_SYMBOL(xfrm4_tunnel_check_size); +EXPORT_SYMBOL(xfrm_register_type); +EXPORT_SYMBOL(xfrm_unregister_type); +EXPORT_SYMBOL(xfrm_get_type); +EXPORT_SYMBOL(xfrm_register_km); +EXPORT_SYMBOL(xfrm_unregister_km); +EXPORT_SYMBOL(xfrm_state_delete); +EXPORT_SYMBOL(xfrm_state_walk); +EXPORT_SYMBOL(xfrm_find_acq_byseq); +EXPORT_SYMBOL(xfrm_find_acq); +EXPORT_SYMBOL(xfrm_alloc_spi); +EXPORT_SYMBOL(xfrm_state_flush); +EXPORT_SYMBOL(xfrm_policy_kill); +EXPORT_SYMBOL(xfrm_policy_bysel); +EXPORT_SYMBOL(xfrm_policy_insert); +EXPORT_SYMBOL(xfrm_policy_walk); +EXPORT_SYMBOL(xfrm_policy_flush); +EXPORT_SYMBOL(xfrm_policy_byid); +EXPORT_SYMBOL(xfrm_policy_list); +EXPORT_SYMBOL(xfrm_dst_lookup); +EXPORT_SYMBOL(xfrm_policy_register_afinfo); +EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); +EXPORT_SYMBOL(xfrm_policy_get_afinfo); +EXPORT_SYMBOL(xfrm_policy_put_afinfo); + +EXPORT_SYMBOL_GPL(xfrm_probe_algs); +EXPORT_SYMBOL_GPL(xfrm_count_auth_supported); +EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); +EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx); +EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx); +EXPORT_SYMBOL_GPL(xfrm_calg_get_byidx); +EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid); +EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); +EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); +EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); +EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); +EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); +EXPORT_SYMBOL_GPL(skb_icv_walk); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b1c87c9924f2..049c7c833d95 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -527,7 +527,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) return -EINVAL; }; - switch (p->family) { + switch (p->sel.family) { case AF_INET: break; @@ -594,7 +594,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy memcpy(&xp->lft, &p->lft, sizeof(xp->lft)); xp->action = p->action; xp->flags = p->flags; - xp->family = p->family; + xp->family = p->sel.family; /* XXX xp->share = p->share; */ } @@ -605,7 +605,7 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); p->priority = xp->priority; p->index = xp->index; - p->family = xp->family; + p->sel.family = xp->family; p->dir = dir; p->action = xp->action; p->flags = xp->flags; diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 13372c7e3a61..5bfa82933ca0 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -16,6 +16,7 @@ #include <linux/slab.h> #include <linux/fs.h> #include <linux/dcache.h> +#include <linux/init.h> #include <linux/skbuff.h> #include <net/sock.h> #include <linux/un.h> diff --git a/security/selinux/ss/global.h b/security/selinux/ss/global.h index 5835dec93839..2358c85da0ae 100644 --- a/security/selinux/ss/global.h +++ b/security/selinux/ss/global.h @@ -7,7 +7,7 @@ #include <linux/ctype.h> #include <linux/in.h> #include <linux/spinlock.h> -#include <asm/semaphore.h> +#include <linux/sched.h> #include "flask.h" #include "avc.h" diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 2ff998428774..b53b9d1809a1 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -2971,8 +2971,10 @@ static struct isapnp_device_id id_table[] __devinitdata = { ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), 0 }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), 0 }, + /* The main driver for this card is opl3sa2 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), 0 }, + */ { ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001), ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000), 0 }, {0} diff --git a/sound/oss/gus_wave.c b/sound/oss/gus_wave.c index 8be49423b6d9..1baa1e62be42 100644 --- a/sound/oss/gus_wave.c +++ b/sound/oss/gus_wave.c @@ -3034,7 +3034,7 @@ void __init gus_wave_init(struct address_info *hw_config) gus_initialize(); - if ((gus_mem_size > 0) & !gus_no_wave_dma) + if ((gus_mem_size > 0) && !gus_no_wave_dma) { hw_config->slots[4] = -1; if ((gus_devnum = sound_install_audiodrv(AUDIO_DRIVER_VERSION, diff --git a/sound/oss/trident.c b/sound/oss/trident.c index a39163190630..117535456d47 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c @@ -3017,6 +3017,8 @@ static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg) } data = inl(TRID_REG(card, address)); + + spin_unlock_irqrestore(&card->lock, flags); return ((u16) (data >> 16)); |
