From 68d1498c3a7e5223b587ad067111fbed12df52a1 Mon Sep 17 00:00:00 2001 From: Russell Cattelan Date: Fri, 6 May 2005 06:42:22 -0700 Subject: [XFS] Fix a bug in xfs_iomap for extent handling of write cases This may be the cause of several open PV's of incorrect delay flags being set and then tripping asserts. Do not return a delay alloc extent when the caller is asking to do a write. SGI Modid: xfs-linux:xfs-kern:189616a Signed-off-by: Russell Cattelan Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_iomap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 991f8a6..469e1a7 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -278,7 +278,9 @@ phase2: switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { case BMAPI_WRITE: /* If we found an extent, return it */ - if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) { + if (nimaps && + (imap.br_startblock != HOLESTARTBLOCK) && + (imap.br_startblock != DELAYSTARTBLOCK)) { xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, offset, count, iomapp, &imap, flags); break; -- cgit v1.1 From d3870398fafd4911bd84573b78be4b6b762f32b0 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 6 May 2005 06:44:46 -0700 Subject: [XFS] Fix directory inodes ioctl compat code, minor code consistency cleanups SGI Modid: xfs-linux:xfs-kern:21810a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_file.c | 7 +++++-- fs/xfs/linux-2.6/xfs_ioctl32.c | 29 +++++++++++++++++++---------- fs/xfs/linux-2.6/xfs_ioctl32.h | 6 +++--- fs/xfs/linux-2.6/xfs_super.c | 3 +-- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index d0d412a..24fa3b1 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -565,7 +565,7 @@ struct file_operations linvfs_file_operations = { .sendfile = linvfs_sendfile, .unlocked_ioctl = linvfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = xfs_compat_ioctl, + .compat_ioctl = linvfs_compat_ioctl, #endif .mmap = linvfs_file_mmap, .open = linvfs_open, @@ -587,7 +587,7 @@ struct file_operations linvfs_invis_file_operations = { .sendfile = linvfs_sendfile, .unlocked_ioctl = linvfs_ioctl_invis, #ifdef CONFIG_COMPAT - .compat_ioctl = xfs_compat_invis_ioctl, + .compat_ioctl = linvfs_compat_invis_ioctl, #endif .mmap = linvfs_file_mmap, .open = linvfs_open, @@ -600,6 +600,9 @@ struct file_operations linvfs_dir_operations = { .read = generic_read_dir, .readdir = linvfs_readdir, .unlocked_ioctl = linvfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = linvfs_compat_ioctl, +#endif .fsync = linvfs_fsync, }; diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 7a12c83..0f8f138 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -58,8 +58,9 @@ typedef struct xfs_fsop_bulkreq32 { __s32 ocount; /* output count pointer */ } xfs_fsop_bulkreq32_t; -static unsigned long -xfs_ioctl32_bulkstat(unsigned long arg) +STATIC unsigned long +xfs_ioctl32_bulkstat( + unsigned long arg) { xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg; xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p)); @@ -78,11 +79,11 @@ xfs_ioctl32_bulkstat(unsigned long arg) } #endif -static long -__xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) +STATIC long +__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) { int error; - struct inode *inode = f->f_dentry->d_inode; + struct inode *inode = f->f_dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); switch (cmd) { @@ -152,12 +153,20 @@ __xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) return error; } -long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg) +long +linvfs_compat_ioctl( + struct file *f, + unsigned cmd, + unsigned long arg) { - return __xfs_compat_ioctl(0, f, cmd, arg); + return __linvfs_compat_ioctl(0, f, cmd, arg); } -long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg) +long +linvfs_compat_invis_ioctl( + struct file *f, + unsigned cmd, + unsigned long arg) { - return __xfs_compat_ioctl(IO_INVIS, f, cmd, arg); + return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg); } diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h index 779f69a..c874793 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.h +++ b/fs/xfs/linux-2.6/xfs_ioctl32.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -30,5 +30,5 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); -long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg); +long linvfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); +long linvfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg); diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 53dc658..455e2b2 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -66,7 +66,6 @@ #include "xfs_buf_item.h" #include "xfs_utils.h" #include "xfs_version.h" -#include "xfs_ioctl32.h" #include #include -- cgit v1.1 From 966dc11fcc48866a24d9b3fd16eeebb3f5e05931 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Fri, 6 May 2005 05:25:00 -0700 Subject: [IA64] Fix stack placement when INIT hits in kernel mode. Without this patch, the stack is placed _below_ the current task structure, which is risky at best. Tony, I think this patch needs to go into 2.6.12, since it fixes a real bug. Without it, INIT may case secondary errors, which would be most unpleasant. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/kernel/minstate.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index 1dbc7b2..f6d8a01 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h @@ -41,7 +41,7 @@ (pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \ (pKStk) ld8 r3 = [r3];; \ (pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \ -(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ +(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ (pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ (pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ ;; \ @@ -50,7 +50,6 @@ (pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ (pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \ ;; \ -(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ (pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ ;; \ (pUStk) mov r18=ar.bsp; \ -- cgit v1.1 From 66302f211a21bb9439a2ae7f7b6a4c386bb10ecd Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Tue, 12 Apr 2005 11:04:00 -0700 Subject: [IA64] fix "section mismatch" compile-time-error I noticed this typo when trying to compile a kernel which had CONFIG_HOTPLUG turned off. In that case, __devinit is no longer a no-op and the compiler then detects a section-conflict. Fix by using __devinitdata instead of __devinit. Same patch also submitted by Darren Williams to fix compilation error using sim_defconfig (which has CONFIG_HOTPLUG=n). Signed-off-by: David Mosberger-Tang Signed-off-by: Darren Williams Signed-off-by: Tony Luck --- arch/ia64/kernel/smpboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 0d5ee57..3865f08 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -624,7 +624,7 @@ static struct { __u16 thread_id; __u16 proc_fixed_addr; __u8 valid; -}mt_info[NR_CPUS] __devinit; +} mt_info[NR_CPUS] __devinitdata; #ifdef CONFIG_HOTPLUG_CPU static inline void -- cgit v1.1 From bfd68594082d8384781c242aa72a7950b5cf51aa Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Wed, 4 May 2005 06:42:00 -0700 Subject: [IA64] Avoid .spillpsp directive in handcoded assembly Some time ago, GAS was fixed to bring the .spillpsp directive in line with the Intel assembler manual (there was some disagreement as to whether or not there is a built-in 16-byte offset). Unfortunately, there are two places in the kernel where this directive is used in handwritten assembly files and those of course relied on the "buggy" behavior. As a result, when using a "fixed" assembler, the kernel picks up the UNaT bits from the wrong place (off by 16) and randomly sets NaT bits on the scratch registers. This can be noticed easily by looking at a coredump and finding various scratch registers with unexpected NaT values. The patch below fixes this by using the .spillsp directive instead, which works correctly no matter what assembler is in use. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/kernel/entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 81c45d4..d99316c 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user) ;; (pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 - .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) + .spillsp ar.unat, 16 st8 [sp]=r9,-16 // allocate space for ar.unat and save it st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch .body @@ -1208,7 +1208,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend) adds out2=8,sp // out2=&sigscratch->ar_pfs ;; .fframe 16 - .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) + .spillsp ar.unat, 16 st8 [sp]=r9,-16 // allocate space for ar.unat and save it st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch .body -- cgit v1.1 From e4fdee8e3b41239242a8f421a28736ef8e08ca55 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 11 May 2005 11:34:32 -0700 Subject: [SUNSAB]: Defer register updates until transmitter is idle. The chip can emit garbage characters if we touch the settings while characters are going out. Signed-off-by: David S. Miller --- drivers/serial/sunsab.c | 109 +++++++++++++++++++++++++++++++----------------- drivers/serial/sunsab.h | 1 + 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 39b788d..10e2990 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -61,6 +61,16 @@ struct uart_sunsab_port { unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */ unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */ int type; /* SAB82532 version */ + + /* Setting configuration bits while the transmitter is active + * can cause garbage characters to get emitted by the chip. + * Therefore, we cache such writes here and do the real register + * write the next time the transmitter becomes idle. + */ + unsigned int cached_ebrg; + unsigned char cached_mode; + unsigned char cached_pvr; + unsigned char cached_dafo; }; /* @@ -236,6 +246,7 @@ receive_chars(struct uart_sunsab_port *up, } static void sunsab_stop_tx(struct uart_port *, unsigned int); +static void sunsab_tx_idle(struct uart_sunsab_port *); static void transmit_chars(struct uart_sunsab_port *up, union sab82532_irq_status *stat) @@ -258,6 +269,7 @@ static void transmit_chars(struct uart_sunsab_port *up, return; set_bit(SAB82532_XPR, &up->irqflags); + sunsab_tx_idle(up); if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { up->interrupt_mask1 |= SAB82532_IMR1_XPR; @@ -397,21 +409,21 @@ static void sunsab_set_mctrl(struct uart_port *port, unsigned int mctrl) struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; if (mctrl & TIOCM_RTS) { - writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); + up->cached_mode &= ~SAB82532_MODE_FRTS; + up->cached_mode |= SAB82532_MODE_RTS; } else { - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); + up->cached_mode |= (SAB82532_MODE_FRTS | + SAB82532_MODE_RTS); } if (mctrl & TIOCM_DTR) { - writeb(readb(&up->regs->rw.pvr) & ~(up->pvr_dtr_bit), &up->regs->rw.pvr); + up->cached_pvr &= ~(up->pvr_dtr_bit); } else { - writeb(readb(&up->regs->rw.pvr) | up->pvr_dtr_bit, &up->regs->rw.pvr); + up->cached_pvr |= up->pvr_dtr_bit; } + + set_bit(SAB82532_REGS_PENDING, &up->irqflags); + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); } /* port->lock is not held. */ @@ -450,6 +462,25 @@ static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop) } /* port->lock held by caller. */ +static void sunsab_tx_idle(struct uart_sunsab_port *up) +{ + if (test_bit(SAB82532_REGS_PENDING, &up->irqflags)) { + u8 tmp; + + clear_bit(SAB82532_REGS_PENDING, &up->irqflags); + writeb(up->cached_mode, &up->regs->rw.mode); + writeb(up->cached_pvr, &up->regs->rw.pvr); + writeb(up->cached_dafo, &up->regs->w.dafo); + + writeb(up->cached_ebrg & 0xff, &up->regs->w.bgr); + tmp = readb(&up->regs->rw.ccr2); + tmp &= ~0xc0; + tmp |= (up->cached_ebrg >> 2) & 0xc0; + writeb(tmp, &up->regs->rw.ccr2); + } +} + +/* port->lock held by caller. */ static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; @@ -517,12 +548,16 @@ static void sunsab_break_ctl(struct uart_port *port, int break_state) spin_lock_irqsave(&up->port.lock, flags); - val = readb(&up->regs->rw.dafo); + val = up->cached_dafo; if (break_state) val |= SAB82532_DAFO_XBRK; else val &= ~SAB82532_DAFO_XBRK; - writeb(val, &up->regs->rw.dafo); + up->cached_dafo = val; + + set_bit(SAB82532_REGS_PENDING, &up->irqflags); + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -566,8 +601,9 @@ static int sunsab_startup(struct uart_port *port) SAB82532_CCR2_TOE, &up->regs->w.ccr2); writeb(0, &up->regs->w.ccr3); writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4); - writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS | - SAB82532_MODE_RAC, &up->regs->w.mode); + up->cached_mode = (SAB82532_MODE_RTS | SAB82532_MODE_FCTS | + SAB82532_MODE_RAC); + writeb(up->cached_mode, &up->regs->w.mode); writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc); tmp = readb(&up->regs->rw.ccr0); @@ -598,7 +634,6 @@ static void sunsab_shutdown(struct uart_port *port) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; - unsigned char tmp; spin_lock_irqsave(&up->port.lock, flags); @@ -609,14 +644,13 @@ static void sunsab_shutdown(struct uart_port *port) writeb(up->interrupt_mask1, &up->regs->w.imr1); /* Disable break condition */ - tmp = readb(&up->regs->rw.dafo); - tmp &= ~SAB82532_DAFO_XBRK; - writeb(tmp, &up->regs->rw.dafo); + up->cached_dafo = readb(&up->regs->rw.dafo); + up->cached_dafo &= ~SAB82532_DAFO_XBRK; + writeb(up->cached_dafo, &up->regs->rw.dafo); /* Disable Receiver */ - tmp = readb(&up->regs->rw.mode); - tmp &= ~SAB82532_MODE_RAC; - writeb(tmp, &up->regs->rw.mode); + up->cached_mode &= ~SAB82532_MODE_RAC; + writeb(up->cached_mode, &up->regs->rw.mode); /* * XXX FIXME @@ -685,7 +719,6 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla unsigned int iflag, unsigned int baud, unsigned int quot) { - unsigned int ebrg; unsigned char dafo; int bits, n, m; @@ -714,10 +747,11 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla } else { dafo |= SAB82532_DAFO_PAR_EVEN; } + up->cached_dafo = dafo; calc_ebrg(baud, &n, &m); - ebrg = n | (m << 6); + up->cached_ebrg = n | (m << 6); up->tec_timeout = (10 * 1000000) / baud; up->cec_timeout = up->tec_timeout >> 2; @@ -770,16 +804,13 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla uart_update_timeout(&up->port, cflag, (up->port.uartclk / (16 * quot))); - /* Now bang the new settings into the chip. */ - sunsab_cec_wait(up); - sunsab_tec_wait(up); - writeb(dafo, &up->regs->w.dafo); - writeb(ebrg & 0xff, &up->regs->w.bgr); - writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0), - &up->regs->rw.ccr2); - - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode); - + /* Now schedule a register update when the chip's + * transmitter is idle. + */ + up->cached_mode |= SAB82532_MODE_RAC; + set_bit(SAB82532_REGS_PENDING, &up->irqflags); + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); } /* port->lock is not held. */ @@ -1084,11 +1115,13 @@ static void __init sunsab_init_hw(void) up->pvr_dsr_bit = (1 << 3); up->pvr_dtr_bit = (1 << 2); } - writeb((1 << 1) | (1 << 2) | (1 << 4), &up->regs->w.pvr); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); + up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4); + writeb(up->cached_pvr, &up->regs->w.pvr); + up->cached_mode = readb(&up->regs->rw.mode); + up->cached_mode |= SAB82532_MODE_FRTS; + writeb(up->cached_mode, &up->regs->rw.mode); + up->cached_mode |= SAB82532_MODE_RTS; + writeb(up->cached_mode, &up->regs->rw.mode); up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT; up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT; diff --git a/drivers/serial/sunsab.h b/drivers/serial/sunsab.h index 686086f..b78e1f7 100644 --- a/drivers/serial/sunsab.h +++ b/drivers/serial/sunsab.h @@ -126,6 +126,7 @@ union sab82532_irq_status { /* irqflags bits */ #define SAB82532_ALLS 0x00000001 #define SAB82532_XPR 0x00000002 +#define SAB82532_REGS_PENDING 0x00000004 /* RFIFO Status Byte */ #define SAB82532_RSTAT_PE 0x80 -- cgit v1.1 From 4dbc30fb27ac4e647e6efadb382ff7d38c3d368e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 11 May 2005 11:37:00 -0700 Subject: [SPARC64]: Add timeouts to streaming buffer synchronization. If some hardware error occurs and the flush flag never updates, we will hang forever in these routines. Add a timeout, and print out a diagnostic if it is reached. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_iommu.c | 165 ++++++++++++++++------------------------ arch/sparc64/kernel/sbus.c | 31 ++++++-- 2 files changed, 88 insertions(+), 108 deletions(-) diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 2929834..f009b1b 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -379,6 +380,54 @@ bad: return PCI_DMA_ERROR_CODE; } +static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages) +{ + int limit; + + PCI_STC_FLUSHFLAG_INIT(strbuf); + if (strbuf->strbuf_ctxflush && + iommu->iommu_ctxflush) { + unsigned long matchreg, flushreg; + + flushreg = strbuf->strbuf_ctxflush; + matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); + + limit = 10000; + do { + pci_iommu_write(flushreg, ctx); + udelay(10); + limit--; + if (!limit) + break; + } while(((long)pci_iommu_read(matchreg)) < 0L); + if (!limit) + printk(KERN_WARNING "pci_strbuf_flush: ctx flush " + "timeout vaddr[%08x] ctx[%lx]\n", + vaddr, ctx); + } else { + unsigned long i; + + for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) + pci_iommu_write(strbuf->strbuf_pflush, vaddr); + } + + pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); + (void) pci_iommu_read(iommu->write_complete_reg); + + limit = 10000; + while (!PCI_STC_FLUSHFLAG_SET(strbuf)) { + limit--; + if (!limit) + break; + udelay(10); + membar("#LoadLoad"); + } + if (!limit) + printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout " + "vaddr[%08x] ctx[%lx] npages[%ld]\n", + vaddr, ctx, npages); +} + /* Unmap a single streaming mode DMA translation. */ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) { @@ -386,7 +435,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int struct pci_iommu *iommu; struct pci_strbuf *strbuf; iopte_t *base; - unsigned long flags, npages, i, ctx; + unsigned long flags, npages, ctx; if (direction == PCI_DMA_NONE) BUG(); @@ -414,29 +463,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; /* Step 1: Kick data out of streaming buffers if necessary. */ - if (strbuf->strbuf_enabled) { - u32 vaddr = bus_addr; - - PCI_STC_FLUSHFLAG_INIT(strbuf); - if (strbuf->strbuf_ctxflush && - iommu->iommu_ctxflush) { - unsigned long matchreg, flushreg; - - flushreg = strbuf->strbuf_ctxflush; - matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - do { - pci_iommu_write(flushreg, ctx); - } while(((long)pci_iommu_read(matchreg)) < 0L); - } else { - for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, vaddr); - } - - pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); - (void) pci_iommu_read(iommu->write_complete_reg); - while (!PCI_STC_FLUSHFLAG_SET(strbuf)) - membar("#LoadLoad"); - } + if (strbuf->strbuf_enabled) + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); @@ -647,29 +675,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; /* Step 1: Kick data out of streaming buffers if necessary. */ - if (strbuf->strbuf_enabled) { - u32 vaddr = (u32) bus_addr; - - PCI_STC_FLUSHFLAG_INIT(strbuf); - if (strbuf->strbuf_ctxflush && - iommu->iommu_ctxflush) { - unsigned long matchreg, flushreg; - - flushreg = strbuf->strbuf_ctxflush; - matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - do { - pci_iommu_write(flushreg, ctx); - } while(((long)pci_iommu_read(matchreg)) < 0L); - } else { - for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, vaddr); - } - - pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); - (void) pci_iommu_read(iommu->write_complete_reg); - while (!PCI_STC_FLUSHFLAG_SET(strbuf)) - membar("#LoadLoad"); - } + if (strbuf->strbuf_enabled) + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); @@ -715,28 +722,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size } /* Step 2: Kick data out of streaming buffers. */ - PCI_STC_FLUSHFLAG_INIT(strbuf); - if (iommu->iommu_ctxflush && - strbuf->strbuf_ctxflush) { - unsigned long matchreg, flushreg; - - flushreg = strbuf->strbuf_ctxflush; - matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - do { - pci_iommu_write(flushreg, ctx); - } while(((long)pci_iommu_read(matchreg)) < 0L); - } else { - unsigned long i; - - for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, bus_addr); - } - - /* Step 3: Perform flush synchronization sequence. */ - pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); - (void) pci_iommu_read(iommu->write_complete_reg); - while (!PCI_STC_FLUSHFLAG_SET(strbuf)) - membar("#LoadLoad"); + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -749,7 +735,8 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i struct pcidev_cookie *pcp; struct pci_iommu *iommu; struct pci_strbuf *strbuf; - unsigned long flags, ctx; + unsigned long flags, ctx, npages, i; + u32 bus_addr; pcp = pdev->sysdata; iommu = pcp->pbm->iommu; @@ -772,36 +759,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i } /* Step 2: Kick data out of streaming buffers. */ - PCI_STC_FLUSHFLAG_INIT(strbuf); - if (iommu->iommu_ctxflush && - strbuf->strbuf_ctxflush) { - unsigned long matchreg, flushreg; - - flushreg = strbuf->strbuf_ctxflush; - matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - do { - pci_iommu_write(flushreg, ctx); - } while (((long)pci_iommu_read(matchreg)) < 0L); - } else { - unsigned long i, npages; - u32 bus_addr; - - bus_addr = sglist[0].dma_address & IO_PAGE_MASK; - - for(i = 1; i < nelems; i++) - if (!sglist[i].dma_length) - break; - i--; - npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; - for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, bus_addr); - } - - /* Step 3: Perform flush synchronization sequence. */ - pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); - (void) pci_iommu_read(iommu->write_complete_reg); - while (!PCI_STC_FLUSHFLAG_SET(strbuf)) - membar("#LoadLoad"); + bus_addr = sglist[0].dma_address & IO_PAGE_MASK; + for(i = 1; i < nelems; i++) + if (!sglist[i].dma_length) + break; + i--; + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) + - bus_addr) >> IO_PAGE_SHIFT; + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); spin_unlock_irqrestore(&iommu->lock, flags); } diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 14d9c3a..d3eca98 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -117,19 +117,34 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages #define STRBUF_TAG_VALID 0x02UL -static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) +static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) { + unsigned long n; + int limit; + iommu->strbuf_flushflag = 0UL; - while (npages--) - upa_writeq(base + (npages << IO_PAGE_SHIFT), + n = npages; + while (n--) + upa_writeq(base + (n << IO_PAGE_SHIFT), iommu->strbuf_regs + STRBUF_PFLUSH); /* Whoopee cushion! */ upa_writeq(__pa(&iommu->strbuf_flushflag), iommu->strbuf_regs + STRBUF_FSYNC); upa_readq(iommu->sbus_control_reg); - while (iommu->strbuf_flushflag == 0UL) + + limit = 10000; + while (iommu->strbuf_flushflag == 0UL) { + limit--; + if (!limit) + break; + udelay(10); membar("#LoadLoad"); + } + if (!limit) + printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout " + "vaddr[%08x] npages[%ld]\n", + base, npages); } static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) @@ -406,7 +421,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, spin_lock_irqsave(&iommu->lock, flags); free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); - strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -569,7 +584,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); - strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -581,7 +596,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); spin_lock_irqsave(&iommu->lock, flags); - strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -605,7 +620,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; spin_lock_irqsave(&iommu->lock, flags); - strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } -- cgit v1.1 From dfa1b73ffb414b64dc0452260132a090eb25bf52 Mon Sep 17 00:00:00 2001 From: Liu Tao Date: Thu, 12 May 2005 19:40:38 -0400 Subject: [PATCH] drivers/net/amd8111e.c: fix NAPI interrupt in poll This patch makes the netif_rx_complete() and rx_interrupt_enable atomic when exiting the poll() method, so to avoid interrupt in poll. It also fixes the rx interrupt check logic in interrupt handler. Signed-off-by: Liu Tao Signed-off-by: Jeff Garzik --- drivers/net/amd8111e.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index f2e937a..b7dd726 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -738,6 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) short vtag; #endif int rx_pkt_limit = dev->quota; + unsigned long flags; do{ /* process receive packets until we use the quota*/ @@ -841,18 +842,19 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) /* Receive descriptor is empty now */ dev->quota -= num_rx_pkt; *budget -= num_rx_pkt; + + spin_lock_irqsave(&lp->lock, flags); netif_rx_complete(dev); - /* enable receive interrupt */ writel(VAL0|RINTEN0, mmio + INTEN0); writel(VAL2 | RDMD0, mmio + CMD0); + spin_unlock_irqrestore(&lp->lock, flags); return 0; + rx_not_empty: /* Do not call a netif_rx_complete */ dev->quota -= num_rx_pkt; *budget -= num_rx_pkt; return 1; - - } #else @@ -1261,18 +1263,20 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg struct net_device * dev = (struct net_device *) dev_id; struct amd8111e_priv *lp = netdev_priv(dev); void __iomem *mmio = lp->mmio; - unsigned int intr0; + unsigned int intr0, intren0; unsigned int handled = 1; - if(dev == NULL) + if(unlikely(dev == NULL)) return IRQ_NONE; - if (regs) spin_lock (&lp->lock); + spin_lock(&lp->lock); + /* disabling interrupt */ writel(INTREN, mmio + CMD0); /* Read interrupt status */ intr0 = readl(mmio + INT0); + intren0 = readl(mmio + INTEN0); /* Process all the INT event until INTR bit is clear. */ @@ -1293,11 +1297,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg /* Schedule a polling routine */ __netif_rx_schedule(dev); } - else { + else if (intren0 & RINTEN0) { printk("************Driver bug! \ interrupt while in poll\n"); - /* Fix by disabling interrupts */ - writel(RINT0, mmio + INT0); + /* Fix by disable receive interrupts */ + writel(RINTEN0, mmio + INTEN0); } } #else @@ -1321,7 +1325,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg err_no_interrupt: writel( VAL0 | INTREN,mmio + CMD0); - if (regs) spin_unlock(&lp->lock); + spin_unlock(&lp->lock); return IRQ_RETVAL(handled); } -- cgit v1.1 From 2918c35d311263bc313b3da272783860ce573189 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Thu, 12 May 2005 19:42:06 -0400 Subject: [PATCH] forcedeth: netpoll support --- drivers/net/forcedeth.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index cda48c5..c93f3d0 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -1480,6 +1480,13 @@ static void nv_do_nic_poll(unsigned long data) enable_irq(dev->irq); } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void nv_poll_controller(struct net_device *dev) +{ + nv_do_nic_poll((unsigned long) dev); +} +#endif + static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct fe_priv *np = get_nvpriv(dev); @@ -1962,6 +1969,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->get_stats = nv_get_stats; dev->change_mtu = nv_change_mtu; dev->set_multicast_list = nv_set_multicast; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = nv_poll_controller; +#endif SET_ETHTOOL_OPS(dev, &ops); dev->tx_timeout = nv_tx_timeout; dev->watchdog_timeo = NV_WATCHDOG_TIMEO; -- cgit v1.1 From da369b01d49b34803265096eb92a2d6da61cf0d0 Mon Sep 17 00:00:00 2001 From: Daniele Venzano Date: Thu, 12 May 2005 20:13:14 -0400 Subject: [PATCH] More ethtool support for sis900 and warning fix Add support to sis900 for the following ethtool ops: - get_link - get_settings - set_settings - nway_reset Signed-off-by: Daniele Venzano Signed-off-by: Jeff Garzik --- drivers/net/sis900.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 3e9d9aa..3107aed 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -162,6 +162,7 @@ struct sis900_private { struct mii_phy * mii; struct mii_phy * first_mii; /* record the first mii structure */ unsigned int cur_phy; + struct mii_if_info mii_info; struct timer_list timer; /* Link status detection timer. */ u8 autong_complete; /* 1: auto-negotiate complete */ @@ -203,7 +204,7 @@ static int sis900_open(struct net_device *net_dev); static int sis900_mii_probe (struct net_device * net_dev); static void sis900_init_rxfilter (struct net_device * net_dev); static u16 read_eeprom(long ioaddr, int location); -static u16 mdio_read(struct net_device *net_dev, int phy_id, int location); +static int mdio_read(struct net_device *net_dev, int phy_id, int location); static void mdio_write(struct net_device *net_dev, int phy_id, int location, int val); static void sis900_timer(unsigned long data); static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy); @@ -478,7 +479,13 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, sis_priv->msg_enable = sis900_debug; else sis_priv->msg_enable = SIS900_DEF_MSG; - + + sis_priv->mii_info.dev = net_dev; + sis_priv->mii_info.mdio_read = mdio_read; + sis_priv->mii_info.mdio_write = mdio_write; + sis_priv->mii_info.phy_id_mask = 0x1f; + sis_priv->mii_info.reg_num_mask = 0x1f; + /* Get Mac address according to the chip revision */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev)); if(netif_msg_probe(sis_priv)) @@ -725,6 +732,8 @@ static u16 sis900_default_phy(struct net_device * net_dev) pci_name(sis_priv->pci_dev), sis_priv->cur_phy); } + sis_priv->mii_info.phy_id = sis_priv->cur_phy; + status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); status &= (~MII_CNTL_ISOLATE); @@ -852,7 +861,7 @@ static void mdio_reset(long mdio_addr) * Please see SiS7014 or ICS spec */ -static u16 mdio_read(struct net_device *net_dev, int phy_id, int location) +static int mdio_read(struct net_device *net_dev, int phy_id, int location) { long mdio_addr = net_dev->base_addr + mear; int mii_cmd = MIIread|(phy_id<msg_enable = value; } +static u32 sis900_get_link(struct net_device *net_dev) +{ + struct sis900_private *sis_priv = net_dev->priv; + return mii_link_ok(&sis_priv->mii_info); +} + +static int sis900_get_settings(struct net_device *net_dev, + struct ethtool_cmd *cmd) +{ + struct sis900_private *sis_priv = net_dev->priv; + spin_lock_irq(&sis_priv->lock); + mii_ethtool_gset(&sis_priv->mii_info, cmd); + spin_unlock_irq(&sis_priv->lock); + return 0; +} + +static int sis900_set_settings(struct net_device *net_dev, + struct ethtool_cmd *cmd) +{ + struct sis900_private *sis_priv = net_dev->priv; + int rt; + spin_lock_irq(&sis_priv->lock); + rt = mii_ethtool_sset(&sis_priv->mii_info, cmd); + spin_unlock_irq(&sis_priv->lock); + return rt; +} + +static int sis900_nway_reset(struct net_device *net_dev) +{ + struct sis900_private *sis_priv = net_dev->priv; + return mii_nway_restart(&sis_priv->mii_info); +} + static struct ethtool_ops sis900_ethtool_ops = { .get_drvinfo = sis900_get_drvinfo, .get_msglevel = sis900_get_msglevel, .set_msglevel = sis900_set_msglevel, + .get_link = sis900_get_link, + .get_settings = sis900_get_settings, + .set_settings = sis900_set_settings, + .nway_reset = sis900_nway_reset, }; /** -- cgit v1.1 From e4eff7291c977308989b24fdfc7215a501302e6a Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:38:30 -0700 Subject: [PATCH] e1000: made loopback test robust Added enhanced functionality to the loopback diags to wrap the descriptor rings. Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_ethtool.c net-drivers-2.6/drivers/net/e1000.new/e1000_ethtool.c --- drivers/net/e1000/e1000_ethtool.c | 81 ++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 0a2ca7c..fae5854 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -919,7 +919,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) /* Setup Tx descriptor ring and Tx buffers */ - txdr->count = 80; + if(!txdr->count) + txdr->count = E1000_DEFAULT_TXD; size = txdr->count * sizeof(struct e1000_buffer); if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) { @@ -974,7 +975,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) /* Setup Rx descriptor ring and Rx buffers */ - rxdr->count = 80; + if(!rxdr->count) + rxdr->count = E1000_DEFAULT_RXD; size = rxdr->count * sizeof(struct e1000_buffer); if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) { @@ -1310,31 +1312,62 @@ e1000_run_loopback_test(struct e1000_adapter *adapter) struct e1000_desc_ring *txdr = &adapter->test_tx_ring; struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; struct pci_dev *pdev = adapter->pdev; - int i, ret_val; + int i, j, k, l, lc, good_cnt, ret_val=0; + unsigned long time; E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); - for(i = 0; i < 64; i++) { - e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); - pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma, - txdr->buffer_info[i].length, - PCI_DMA_TODEVICE); - } - E1000_WRITE_REG(&adapter->hw, TDT, i); - - msec_delay(200); - - i = 0; - do { - pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[i].dma, - rxdr->buffer_info[i].length, - PCI_DMA_FROMDEVICE); - - ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb, - 1024); - i++; - } while (ret_val != 0 && i < 64); + /* Calculate the loop count based on the largest descriptor ring + * The idea is to wrap the largest ring a number of times using 64 + * send/receive pairs during each loop + */ + if(rxdr->count <= txdr->count) + lc = ((txdr->count / 64) * 2) + 1; + else + lc = ((rxdr->count / 64) * 2) + 1; + + k = l = 0; + for(j = 0; j <= lc; j++) { /* loop count loop */ + for(i = 0; i < 64; i++) { /* send the packets */ + e1000_create_lbtest_frame(txdr->buffer_info[i].skb, + 1024); + pci_dma_sync_single_for_device(pdev, + txdr->buffer_info[k].dma, + txdr->buffer_info[k].length, + PCI_DMA_TODEVICE); + if(unlikely(++k == txdr->count)) k = 0; + } + E1000_WRITE_REG(&adapter->hw, TDT, k); + msec_delay(200); + time = jiffies; /* set the start time for the receive */ + good_cnt = 0; + do { /* receive the sent packets */ + pci_dma_sync_single_for_cpu(pdev, + rxdr->buffer_info[l].dma, + rxdr->buffer_info[l].length, + PCI_DMA_FROMDEVICE); + + ret_val = e1000_check_lbtest_frame( + rxdr->buffer_info[l].skb, + 1024); + if(!ret_val) + good_cnt++; + if(unlikely(++l == rxdr->count)) l = 0; + /* time + 20 msecs (200 msecs on 2.4) is more than + * enough time to complete the receives, if it's + * exceeded, break and error off + */ + } while (good_cnt < 64 && jiffies < (time + 20)); + if(good_cnt != 64) { + ret_val = 13; /* ret_val is the same as mis-compare */ + break; + } + if(jiffies >= (time + 2)) { + ret_val = 14; /* error code for time out error */ + break; + } + } /* end loop count loop */ return ret_val; } @@ -1371,6 +1404,8 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) *data = 1; } else { e1000_check_for_link(&adapter->hw); + if(adapter->hw.autoneg) /* if auto_neg is set wait for it */ + msec_delay(4000); if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) { *data = 1; -- cgit v1.1 From df25e164878836196ee93d1a5757867da6eac30e Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:38:43 -0700 Subject: [PATCH] e1000: Fix msec-delay definition to use msleep Fix msec-delay definition in e1000_osdep.h to use msleep Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_osdep.h net-drivers-2.6/drivers/net/e1000.new/e1000_osdep.h --- drivers/net/e1000/e1000_osdep.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 970c656..2efa3b1 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -42,7 +42,12 @@ #include #ifndef msec_delay -#define msec_delay(x) msleep(x) +#define msec_delay(x) do { if(in_interrupt()) { \ + /* Don't mdelay in interrupt context! */ \ + BUG(); \ + } else { \ + msleep(x); \ + } } while(0) /* Some workarounds require millisecond delays and are run during interrupt * context. Most notably, when establishing link, the phy may need tweaking -- cgit v1.1 From fa4f7ef3aaa6cee6b04ebe90266ee893e0b2ce07 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:39:13 -0700 Subject: [PATCH] e1000: MSI support for PCI-e adapters MSI support for PCI-e adapters Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000.h net-drivers-2.6/drivers/net/e1000.new/e1000.h --- drivers/net/e1000/e1000.h | 3 +++ drivers/net/e1000/e1000_main.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 148930d..da05552 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -257,5 +257,8 @@ struct e1000_adapter { int msg_enable; +#ifdef CONFIG_PCI_MSI + boolean_t have_msi; +#endif }; #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 82549a6..03e3ec7 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -312,6 +312,16 @@ e1000_up(struct e1000_adapter *adapter) e1000_configure_rx(adapter); e1000_alloc_rx_buffers(adapter); +#ifdef CONFIG_PCI_MSI + if(adapter->hw.mac_type > e1000_82547_rev_2) { + adapter->have_msi = TRUE; + if((err = pci_enable_msi(adapter->pdev))) { + DPRINTK(PROBE, ERR, + "Unable to allocate MSI interrupt Error: %d\n", err); + adapter->have_msi = FALSE; + } + } +#endif if((err = request_irq(adapter->pdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, netdev))) @@ -333,6 +343,11 @@ e1000_down(struct e1000_adapter *adapter) e1000_irq_disable(adapter); free_irq(adapter->pdev->irq, netdev); +#ifdef CONFIG_PCI_MSI + if(adapter->hw.mac_type > e1000_82547_rev_2 && + adapter->have_msi == TRUE) + pci_disable_msi(adapter->pdev); +#endif del_timer_sync(&adapter->tx_fifo_stall_timer); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); -- cgit v1.1 From 5de556249fde97493a4c79dbf8979ace0f76789f Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:39:30 -0700 Subject: [PATCH] e1000: Enable polling before enabling interrupts Enable polling before enabling interrupts -- avoids (in NAPI mode) entering the ISR and returning without doing any work because polling is not enabled. [romieu@fr.zoriel.com] Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 03e3ec7..9927106 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -328,11 +328,12 @@ e1000_up(struct e1000_adapter *adapter) return err; mod_timer(&adapter->watchdog_timer, jiffies); - e1000_irq_enable(adapter); #ifdef CONFIG_E1000_NAPI netif_poll_enable(netdev); #endif + e1000_irq_enable(adapter); + return 0; } -- cgit v1.1 From 4e48a2b91d408357cb0747151d8db5368ac8f1d0 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:39:53 -0700 Subject: [PATCH] e1000: Fix kernel panic with 82541 LOM Fix kernel panic with 82541 LOM when using a 100M cable Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9927106..9c6c1fb 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -372,6 +372,7 @@ e1000_down(struct e1000_adapter *adapter) e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg); + mdelay(1); } } -- cgit v1.1 From 2701234fc0372630457e3da14e36cde53c57d12e Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:40:28 -0700 Subject: [PATCH] e1000: Delay clean-up of last Tx packet Delay clean-up of last Tx packet to fix pre-mature writeback issue of Tx descriptors only when TSO is enabled Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 43 ++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9c6c1fb..4a8c069 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2384,11 +2384,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) eop_desc = E1000_TX_DESC(*tx_ring, eop); while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - /* pre-mature writeback of Tx descriptors */ - /* clear (free buffers and unmap pci_mapping) */ - /* previous_buffer_info */ + /* Premature writeback of Tx descriptors clear (free buffers + * and unmap pci_mapping) previous_buffer_info */ if (likely(adapter->previous_buffer_info.skb != NULL)) { - e1000_unmap_and_free_tx_resource(adapter, + e1000_unmap_and_free_tx_resource(adapter, &adapter->previous_buffer_info); } @@ -2397,20 +2396,25 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); - /* pre-mature writeback of Tx descriptors */ - /* save the cleaning of the this for the */ - /* next iteration */ - if (cleaned) { - memcpy(&adapter->previous_buffer_info, - buffer_info, - sizeof(struct e1000_buffer)); - memset(buffer_info, - 0, - sizeof(struct e1000_buffer)); +#ifdef NETIF_F_TSO + if (!(netdev->features & NETIF_F_TSO)) { +#endif + e1000_unmap_and_free_tx_resource(adapter, + buffer_info); +#ifdef NETIF_F_TSO } else { - e1000_unmap_and_free_tx_resource(adapter, - buffer_info); + if (cleaned) { + memcpy(&adapter->previous_buffer_info, + buffer_info, + sizeof(struct e1000_buffer)); + memset(buffer_info, 0, + sizeof(struct e1000_buffer)); + } else { + e1000_unmap_and_free_tx_resource( + adapter, buffer_info); + } } +#endif tx_desc->buffer_addr = 0; tx_desc->lower.data = 0; @@ -2443,7 +2447,14 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) netif_stop_queue(netdev); } +#ifdef NETIF_F_TSO + if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && + time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ))) + e1000_unmap_and_free_tx_resource( + adapter, &adapter->previous_buffer_info); + +#endif return cleaned; } -- cgit v1.1 From 70b8f1e16a788eccdd36f39679774b1a08a6ba55 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:40:40 -0700 Subject: [PATCH] e1000: Dump information on Tx ring Dump information on Tx ring when 'NETDEV: Watchdog' condition is reached Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4a8c069..b5811f4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2442,10 +2442,37 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) /* detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = FALSE; - if(tx_ring->buffer_info[i].dma && - time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) && - !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) + if (tx_ring->buffer_info[i].dma && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) + && !(E1000_READ_REG(&adapter->hw, STATUS) & + E1000_STATUS_TXOFF)) { + + /* detected Tx unit hang */ + i = tx_ring->next_to_clean; + eop = tx_ring->buffer_info[i].next_to_watch; + eop_desc = E1000_TX_DESC(*tx_ring, eop); + DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n" + " TDH <%x>\n" + " TDT <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "buffer_info[next_to_clean]\n" + " dma <%llx>\n" + " time_stamp <%lx>\n" + " next_to_watch <%x>\n" + " jiffies <%lx>\n" + " next_to_watch.status <%x>\n", + E1000_READ_REG(&adapter->hw, TDH), + E1000_READ_REG(&adapter->hw, TDT), + tx_ring->next_to_use, + i, + tx_ring->buffer_info[i].dma, + tx_ring->buffer_info[i].time_stamp, + eop, + jiffies, + eop_desc->upper.fields.status); netif_stop_queue(netdev); + } } #ifdef NETIF_F_TSO -- cgit v1.1 From 6d9157577d926d2a83fe8d4914c0cc216deb5842 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:41:11 -0700 Subject: [PATCH] e1000:Fix computation of netdev stats from controller stats counters Fix computation of netdev stats from controller stats counters - from sfeldma@pobox.com Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b5811f4..ed1e57a 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2230,9 +2230,9 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->net_stats.rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.rlec + adapter->stats.rnbc + - adapter->stats.mpc + adapter->stats.cexterr; - adapter->net_stats.rx_dropped = adapter->stats.rnbc; + adapter->stats.rlec + adapter->stats.mpc + + adapter->stats.cexterr; + adapter->net_stats.rx_dropped = adapter->stats.mpc; adapter->net_stats.rx_length_errors = adapter->stats.rlec; adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; -- cgit v1.1 From a4cb847dac40577dd751a4deb4085ed080780679 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:41:28 -0700 Subject: [PATCH] e1000: e1000 stops working after resume e1000 stops working after resume, call pci_enable_device after pci_restore_state - Modified Andrew Morton's patch Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ed1e57a..479915a 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3173,8 +3173,7 @@ e1000_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); ret = pci_enable_device(pdev); - if (pdev->is_busmaster) - pci_set_master(pdev); + pci_set_master(pdev); pci_enable_wake(pdev, 3, 0); pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ -- cgit v1.1 From 97338bde27d97347bc83203d6ac5e93be1ebcd03 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:41:46 -0700 Subject: [PATCH] e1000: Implement a workaround for 82546 errata 10 Implement 82546 errata 10 -- first Tx descriptor cannot have more than 2015 byte of data in it or it could hang the transmitter. Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 479915a..e54890a 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1777,6 +1777,15 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb, if(unlikely(mss && !nr_frags && size == len && size > 8)) size -= 4; #endif + /* work-around for errata 10 and it applies + * to all controllers in PCI-X mode + * The fix is to make sure that the first descriptor of a + * packet is smaller than 2048 - 16 - 16 (or 2016) bytes + */ + if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) && + (size > 2015) && count == 0)) + size = 2015; + /* Workaround for potential 82544 hang in PCI-X. Avoid * terminating buffers within evenly-aligned dwords. */ if(unlikely(adapter->pcix_82544 && @@ -1979,6 +1988,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if(adapter->pcix_82544) count++; + /* work-around for errata 10 and it applies to all controllers + * in PCI-X mode, so add one more descriptor to the count + */ + if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) && + (len > 2015))) + count++; + nr_frags = skb_shinfo(skb)->nr_frags; for(f = 0; f < nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, -- cgit v1.1 From f1d2e4905eed4b13c3ba56ac6d30c283be996963 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:42:04 -0700 Subject: [PATCH] e1000:Removed redundant statement in e1000_clean_tx_irq Removed redundant statement in e1000_clean_tx_irq Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e54890a..0fec670 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2436,7 +2436,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_desc->lower.data = 0; tx_desc->upper.data = 0; - cleaned = (i == eop); if(unlikely(++i == tx_ring->count)) i = 0; } -- cgit v1.1 From f0d11ed0b0650d2f93f56f65167c10a577c16c88 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:43:28 -0700 Subject: [PATCH] e1000: Modified e1000_clean: exit poll Modified e1000_clean:: exit poll if no Tx and work_done == 0 Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 0fec670..4cdf371 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2368,9 +2368,8 @@ e1000_clean(struct net_device *netdev, int *budget) *budget -= work_done; netdev->quota -= work_done; - /* if no Tx and not enough Rx work done, exit the polling mode */ - if((!tx_cleaned && (work_done < work_to_do)) || - !netif_running(netdev)) { + /* If no Tx and no Rx work done, exit the polling mode */ + if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { netif_rx_complete(netdev); e1000_irq_enable(adapter); return 0; -- cgit v1.1 From 2d7edb923a823660b081bd4c660300ee19adca8d Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:43:52 -0700 Subject: [PATCH] e1000:82573 specific code & packet split code 82573 specific code & packet split code Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000.h net-drivers-2.6/drivers/net/e1000.new/e1000.h --- drivers/net/e1000/e1000.h | 26 + drivers/net/e1000/e1000_hw.c | 2132 ++++++++++++++++++++++++++++++--------- drivers/net/e1000/e1000_hw.h | 568 ++++++++++- drivers/net/e1000/e1000_main.c | 804 ++++++++++++--- drivers/net/e1000/e1000_osdep.h | 23 + 5 files changed, 2956 insertions(+), 597 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index da05552..19858c2 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -112,6 +112,8 @@ struct e1000_adapter; #define E1000_MAX_82544_RXD 4096 /* Supported Rx Buffer Sizes */ +#define E1000_RXBUFFER_128 128 /* Used for packet split */ +#define E1000_RXBUFFER_256 256 /* Used for packet split */ #define E1000_RXBUFFER_2048 2048 #define E1000_RXBUFFER_4096 4096 #define E1000_RXBUFFER_8192 8192 @@ -146,6 +148,10 @@ struct e1000_adapter; #define E1000_MASTER_SLAVE e1000_ms_hw_default #endif +#define E1000_MNG_VLAN_NONE -1 +/* Number of packet split data buffers (not including the header buffer) */ +#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1 + /* only works for sizes that are powers of 2 */ #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) @@ -159,6 +165,9 @@ struct e1000_buffer { uint16_t next_to_watch; }; +struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; }; +struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; }; + struct e1000_desc_ring { /* pointer to the descriptor ring memory */ void *desc; @@ -174,12 +183,19 @@ struct e1000_desc_ring { unsigned int next_to_clean; /* array of buffer information structs */ struct e1000_buffer *buffer_info; + /* arrays of page information for packet split */ + struct e1000_ps_page *ps_page; + struct e1000_ps_page_dma *ps_page_dma; }; #define E1000_DESC_UNUSED(R) \ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ (R)->next_to_clean - (R)->next_to_use - 1) +#define E1000_RX_DESC_PS(R, i) \ + (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) +#define E1000_RX_DESC_EXT(R, i) \ + (&(((union e1000_rx_desc_extended *)((R).desc))[i])) #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) #define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) #define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) @@ -192,6 +208,7 @@ struct e1000_adapter { struct timer_list watchdog_timer; struct timer_list phy_info_timer; struct vlan_group *vlgrp; + uint16_t mng_vlan_id; uint32_t bd_number; uint32_t rx_buffer_len; uint32_t part_num; @@ -228,14 +245,23 @@ struct e1000_adapter { boolean_t detect_tx_hung; /* RX */ +#ifdef CONFIG_E1000_NAPI + boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done, + int work_to_do); +#else + boolean_t (*clean_rx) (struct e1000_adapter *adapter); +#endif + void (*alloc_rx_buf) (struct e1000_adapter *adapter); struct e1000_desc_ring rx_ring; uint64_t hw_csum_err; uint64_t hw_csum_good; uint32_t rx_int_delay; uint32_t rx_abs_int_delay; boolean_t rx_csum; + boolean_t rx_ps; uint32_t gorcl; uint64_t gorcl_old; + uint16_t rx_ps_bsize0; /* Interrupt Throttle Rate */ uint32_t itr; diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 786a9b9..b7a7ceb 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -63,10 +63,11 @@ static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count); static int32_t e1000_acquire_eeprom(struct e1000_hw *hw); static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); -static int32_t e1000_id_led_init(struct e1000_hw * hw); static int32_t e1000_set_vco_speed(struct e1000_hw *hw); static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw); static int32_t e1000_set_phy_mode(struct e1000_hw *hw); +static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer); +static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length); /* IGP cable length table */ static const @@ -80,6 +81,17 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; +static const +uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] = + { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, + 22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58, + 32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74, + 43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90, + 57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108, + 73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124, + 91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128, + 108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; + /****************************************************************************** * Set the phy type member in the hw struct. @@ -91,10 +103,14 @@ e1000_set_phy_type(struct e1000_hw *hw) { DEBUGFUNC("e1000_set_phy_type"); + if(hw->mac_type == e1000_undefined) + return -E1000_ERR_PHY_TYPE; + switch(hw->phy_id) { case M88E1000_E_PHY_ID: case M88E1000_I_PHY_ID: case M88E1011_I_PHY_ID: + case M88E1111_I_PHY_ID: hw->phy_type = e1000_phy_m88; break; case IGP01E1000_I_PHY_ID: @@ -271,6 +287,7 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82546GB_PCIE: + case E1000_DEV_ID_82546GB_QUAD_COPPER: hw->mac_type = e1000_82546_rev_3; break; case E1000_DEV_ID_82541EI: @@ -289,12 +306,19 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82547GI: hw->mac_type = e1000_82547_rev_2; break; + case E1000_DEV_ID_82573E: + case E1000_DEV_ID_82573E_IAMT: + hw->mac_type = e1000_82573; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } switch(hw->mac_type) { + case e1000_82573: + hw->eeprom_semaphore_present = TRUE; + /* fall through */ case e1000_82541: case e1000_82547: case e1000_82541_rev_2: @@ -360,6 +384,9 @@ e1000_reset_hw(struct e1000_hw *hw) uint32_t icr; uint32_t manc; uint32_t led_ctrl; + uint32_t timeout; + uint32_t extcnf_ctrl; + int32_t ret_val; DEBUGFUNC("e1000_reset_hw"); @@ -369,6 +396,15 @@ e1000_reset_hw(struct e1000_hw *hw) e1000_pci_clear_mwi(hw); } + if(hw->bus_type == e1000_bus_type_pci_express) { + /* Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + if(e1000_disable_pciex_master(hw) != E1000_SUCCESS) { + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + } + } + /* Clear interrupt mask to stop board from generating interrupts */ DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, IMC, 0xffffffff); @@ -393,10 +429,32 @@ e1000_reset_hw(struct e1000_hw *hw) /* Must reset the PHY before resetting the MAC */ if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); + E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); msec_delay(5); } + /* Must acquire the MDIO ownership before MAC reset. + * Ownership defaults to firmware after a reset. */ + if(hw->mac_type == e1000_82573) { + timeout = 10; + + extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + + do { + E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl); + extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); + + if(extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) + break; + else + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; + + msec_delay(2); + timeout--; + } while(timeout); + } + /* Issue a global reset to the MAC. This will reset the chip's * transmit, receive, DMA, and link units. It will not effect * the current PCI configuration. The global reset bit is self- @@ -450,6 +508,18 @@ e1000_reset_hw(struct e1000_hw *hw) /* Wait for EEPROM reload */ msec_delay(20); break; + case e1000_82573: + udelay(10); + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + /* fall through */ + ret_val = e1000_get_auto_rd_done(hw); + if(ret_val) + /* We don't want to continue accessing MAC registers. */ + return ret_val; + break; default: /* Wait for EEPROM reload (it happens automatically) */ msec_delay(5); @@ -457,7 +527,7 @@ e1000_reset_hw(struct e1000_hw *hw) } /* Disable HW ARPs on ASF enabled adapters */ - if(hw->mac_type >= e1000_82540) { + if(hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) { manc = E1000_READ_REG(hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(hw, MANC, manc); @@ -510,6 +580,8 @@ e1000_init_hw(struct e1000_hw *hw) uint16_t pcix_stat_hi_word; uint16_t cmd_mmrbc; uint16_t stat_mmrbc; + uint32_t mta_size; + DEBUGFUNC("e1000_init_hw"); /* Initialize Identification LED */ @@ -524,8 +596,8 @@ e1000_init_hw(struct e1000_hw *hw) /* Disabling VLAN filtering. */ DEBUGOUT("Initializing the IEEE VLAN\n"); - E1000_WRITE_REG(hw, VET, 0); - + if (hw->mac_type < e1000_82545_rev_3) + E1000_WRITE_REG(hw, VET, 0); e1000_clear_vfta(hw); /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ @@ -553,14 +625,16 @@ e1000_init_hw(struct e1000_hw *hw) /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); - for(i = 0; i < E1000_MC_TBL_SIZE; i++) + mta_size = E1000_MC_TBL_SIZE; + for(i = 0; i < mta_size; i++) E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); /* Set the PCI priority bit correctly in the CTRL register. This * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. + * gives equal priority to transmits and receives. Valid only on + * 82542 and 82543 silicon. */ - if(hw->dma_fairness) { + if(hw->dma_fairness && hw->mac_type <= e1000_82543) { ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } @@ -598,9 +672,21 @@ e1000_init_hw(struct e1000_hw *hw) if(hw->mac_type > e1000_82544) { ctrl = E1000_READ_REG(hw, TXDCTL); ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; + switch (hw->mac_type) { + default: + break; + case e1000_82573: + ctrl |= E1000_TXDCTL_COUNT_DESC; + break; + } E1000_WRITE_REG(hw, TXDCTL, ctrl); } + if (hw->mac_type == e1000_82573) { + e1000_enable_tx_pkt_filtering(hw); + } + + /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there @@ -679,7 +765,7 @@ e1000_setup_link(struct e1000_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -736,6 +822,7 @@ e1000_setup_link(struct e1000_hw *hw) E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); + E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); /* Set the flow control receive threshold registers. Normally, @@ -906,20 +993,18 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw) } /****************************************************************************** -* Detects which PHY is present and the speed and duplex +* Make sure we have a valid PHY and change PHY mode before link setup. * * hw - Struct containing variables accessed by shared code ******************************************************************************/ static int32_t -e1000_setup_copper_link(struct e1000_hw *hw) +e1000_copper_link_preconfig(struct e1000_hw *hw) { uint32_t ctrl; - uint32_t led_ctrl; int32_t ret_val; - uint16_t i; uint16_t phy_data; - DEBUGFUNC("e1000_setup_copper_link"); + DEBUGFUNC("e1000_copper_link_preconfig"); ctrl = E1000_READ_REG(hw, CTRL); /* With 82543, we need to force speed and duplex on the MAC equal to what @@ -933,7 +1018,9 @@ e1000_setup_copper_link(struct e1000_hw *hw) } else { ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); E1000_WRITE_REG(hw, CTRL, ctrl); - e1000_phy_hw_reset(hw); + ret_val = e1000_phy_hw_reset(hw); + if(ret_val) + return ret_val; } /* Make sure we have a valid PHY */ @@ -961,354 +1048,452 @@ e1000_setup_copper_link(struct e1000_hw *hw) hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) hw->phy_reset_disable = FALSE; - if(!hw->phy_reset_disable) { - if (hw->phy_type == e1000_phy_igp) { - - ret_val = e1000_phy_reset(hw); - if(ret_val) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } - - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); + return E1000_SUCCESS; +} - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - /* disable lplu d3 during driver init */ - ret_val = e1000_set_d3_lplu_state(hw, FALSE); - if(ret_val) { - DEBUGOUT("Error Disabling LPLU D3\n"); - return ret_val; - } +/******************************************************************** +* Copper link setup for e1000_phy_igp series. +* +* hw - Struct containing variables accessed by shared code +*********************************************************************/ +static int32_t +e1000_copper_link_igp_setup(struct e1000_hw *hw) +{ + uint32_t led_ctrl; + int32_t ret_val; + uint16_t phy_data; - /* Configure mdi-mdix settings */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - &phy_data); - if(ret_val) - return ret_val; + DEBUGFUNC("e1000_copper_link_igp_setup"); - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - hw->dsp_config_state = e1000_dsp_config_disabled; - /* Force MDI for earlier revs of the IGP PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); - hw->mdix = 1; + if (hw->phy_reset_disable) + return E1000_SUCCESS; + + ret_val = e1000_phy_reset(hw); + if (ret_val) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } - } else { - hw->dsp_config_state = e1000_dsp_config_enabled; - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (hw->mdix) { - case 1: - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - phy_data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - } - ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, - phy_data); - if(ret_val) - return ret_val; + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); - /* set auto-master slave resolution settings */ - if(hw->autoneg) { - e1000_ms_type phy_ms_setting = hw->master_slave; + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - if(hw->ffe_config_state == e1000_ffe_config_active) - hw->ffe_config_state = e1000_ffe_config_enabled; + /* disable lplu d3 during driver init */ + ret_val = e1000_set_d3_lplu_state(hw, FALSE); + if (ret_val) { + DEBUGOUT("Error Disabling LPLU D3\n"); + return ret_val; + } - if(hw->dsp_config_state == e1000_dsp_config_activated) - hw->dsp_config_state = e1000_dsp_config_enabled; + /* disable lplu d0 during driver init */ + ret_val = e1000_set_d0_lplu_state(hw, FALSE); + if (ret_val) { + DEBUGOUT("Error Disabling LPLU D0\n"); + return ret_val; + } + /* Configure mdi-mdix settings */ + ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); + if (ret_val) + return ret_val; - /* when autonegotiation advertisment is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. */ - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if(ret_val) - return ret_val; - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1000_write_phy_reg(hw, - IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if(ret_val) - return ret_val; - /* Set auto Master/Slave resolution process */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if(ret_val) - return ret_val; - phy_data &= ~CR_1000T_MS_ENABLE; - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if(ret_val) - return ret_val; - } + if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + hw->dsp_config_state = e1000_dsp_config_disabled; + /* Force MDI for earlier revs of the IGP PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX); + hw->mdix = 1; - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if(ret_val) - return ret_val; + } else { + hw->dsp_config_state = e1000_dsp_config_enabled; + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - /* load defaults for future use */ - hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? - ((phy_data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : - e1000_ms_auto; - - switch (phy_ms_setting) { - case e1000_ms_force_master: - phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - phy_data |= CR_1000T_MS_ENABLE; - phy_data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - phy_data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if(ret_val) - return ret_val; - } - } else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - &phy_data); - if(ret_val) - return ret_val; + switch (hw->mdix) { + case 1: + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 2: + phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 0: + default: + phy_data |= IGP01E1000_PSCR_AUTO_MDIX; + break; + } + } + ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); + if(ret_val) + return ret_val; - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + /* set auto-master slave resolution settings */ + if(hw->autoneg) { + e1000_ms_type phy_ms_setting = hw->master_slave; - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + if(hw->ffe_config_state == e1000_ffe_config_active) + hw->ffe_config_state = e1000_ffe_config_enabled; - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } + if(hw->dsp_config_state == e1000_dsp_config_activated) + hw->dsp_config_state = e1000_dsp_config_enabled; - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); + /* when autonegotiation advertisment is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. */ + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); if(ret_val) return ret_val; - - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + phy_data); if(ret_val) return ret_val; + /* Set auto Master/Slave resolution process */ + ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); + if(ret_val) + return ret_val; + phy_data &= ~CR_1000T_MS_ENABLE; + ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); + if(ret_val) + return ret_val; + } - phy_data |= M88E1000_EPSCR_TX_CLK_25; + ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); + if(ret_val) + return ret_val; - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if(ret_val) - return ret_val; - } + /* load defaults for future use */ + hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? + ((phy_data & CR_1000T_MS_VALUE) ? + e1000_ms_force_master : + e1000_ms_force_slave) : + e1000_ms_auto; - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if(ret_val) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } + switch (phy_ms_setting) { + case e1000_ms_force_master: + phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); + break; + case e1000_ms_force_slave: + phy_data |= CR_1000T_MS_ENABLE; + phy_data &= ~(CR_1000T_MS_VALUE); + break; + case e1000_ms_auto: + phy_data &= ~CR_1000T_MS_ENABLE; + default: + break; + } + ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); + if(ret_val) + return ret_val; } - /* Options: - * autoneg = 1 (default) - * PHY will advertise value(s) parsed from - * autoneg_advertised and fc - * autoneg = 0 - * PHY will be set to 10H, 10F, 100H, or 100F - * depending on value parsed from forced_speed_duplex. - */ + return E1000_SUCCESS; +} - /* Is autoneg enabled? This is enabled by default or by software - * override. If so, call e1000_phy_setup_autoneg routine to parse the - * autoneg_advertised and fc options. If autoneg is NOT enabled, then - * the user should have provided a speed/duplex override. If so, then - * call e1000_phy_force_speed_duplex to parse and set this up. - */ - if(hw->autoneg) { - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if(hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; +/******************************************************************** +* Copper link setup for e1000_phy_m88 series. +* +* hw - Struct containing variables accessed by shared code +*********************************************************************/ +static int32_t +e1000_copper_link_mgp_setup(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t phy_data; - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if(ret_val) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - DEBUGOUT("Restarting Auto-Neg\n"); + DEBUGFUNC("e1000_copper_link_mgp_setup"); - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if(ret_val) - return ret_val; + if(hw->phy_reset_disable) + return E1000_SUCCESS; + + /* Enable CRS on TX. This must be set for half-duplex operation. */ + ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); + if(ret_val) + return ret_val; - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); - if(ret_val) - return ret_val; + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if(hw->wait_autoneg_complete) { - ret_val = e1000_wait_autoneg(hw); - if(ret_val) { - DEBUGOUT("Error while waiting for autoneg to complete\n"); - return ret_val; - } - } - hw->get_link_status = TRUE; - } else { - DEBUGOUT("Forcing speed and duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); - if(ret_val) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } - } /* !hw->phy_reset_disable */ + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - /* Check link status. Wait up to 100 microseconds for link to become - * valid. + switch (hw->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } + + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled */ - for(i = 0; i < 10; i++) { - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if(hw->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if(ret_val) return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); + + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); + if(ret_val) + return ret_val; + + phy_data |= M88E1000_EPSCR_TX_CLK_25; + + if (hw->phy_revision < M88E1011_I_REV_4) { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if(ret_val) return ret_val; + } - if(phy_data & MII_SR_LINK_STATUS) { - /* We have link, so we need to finish the config process: - * 1) Set up the MAC to the current PHY speed/duplex - * if we are on 82543. If we - * are on newer silicon, we only need to configure - * collision distance in the Transmit Control Register. - * 2) Set up flow control on the MAC to that established with - * the link partner. - */ - if(hw->mac_type >= e1000_82544) { - e1000_config_collision_dist(hw); - } else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val) { - DEBUGOUT("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val) { - DEBUGOUT("Error Configuring Flow Control\n"); - return ret_val; - } - DEBUGOUT("Valid link established!!!\n"); - - if(hw->phy_type == e1000_phy_igp) { - ret_val = e1000_config_dsp_after_link_change(hw, TRUE); - if(ret_val) { - DEBUGOUT("Error Configuring DSP after link up\n"); - return ret_val; - } - } - DEBUGOUT("Valid link established!!!\n"); - return E1000_SUCCESS; - } - udelay(10); + /* SW Reset the PHY so all changes take effect */ + ret_val = e1000_phy_reset(hw); + if(ret_val) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; } - DEBUGOUT("Unable to establish link!!!\n"); - return E1000_SUCCESS; + return E1000_SUCCESS; } -/****************************************************************************** -* Configures PHY autoneg and flow control advertisement settings +/******************************************************************** +* Setup auto-negotiation and flow control advertisements, +* and then perform auto-negotiation. * * hw - Struct containing variables accessed by shared code -******************************************************************************/ -int32_t -e1000_phy_setup_autoneg(struct e1000_hw *hw) +*********************************************************************/ +static int32_t +e1000_copper_link_autoneg(struct e1000_hw *hw) { int32_t ret_val; - uint16_t mii_autoneg_adv_reg; - uint16_t mii_1000t_ctrl_reg; + uint16_t phy_data; - DEBUGFUNC("e1000_phy_setup_autoneg"); + DEBUGFUNC("e1000_copper_link_autoneg"); - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); + /* Perform some bounds checking on the hw->autoneg_advertised + * parameter. If this variable is zero, then set it to the default. + */ + hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; + + /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if(hw->autoneg_advertised == 0) + hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; + + DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); + ret_val = e1000_phy_setup_autoneg(hw); + if(ret_val) { + DEBUGOUT("Error Setting up Auto-Negotiation\n"); + return ret_val; + } + DEBUGOUT("Restarting Auto-Neg\n"); + + /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); if(ret_val) return ret_val; - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); + phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); + ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); if(ret_val) return ret_val; - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for + /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if(hw->wait_autoneg_complete) { + ret_val = e1000_wait_autoneg(hw); + if(ret_val) { + DEBUGOUT("Error while waiting for autoneg to complete\n"); + return ret_val; + } + } + + hw->get_link_status = TRUE; + + return E1000_SUCCESS; +} + + +/****************************************************************************** +* Config the MAC and the PHY after link is up. +* 1) Set up the MAC to the current PHY speed/duplex +* if we are on 82543. If we +* are on newer silicon, we only need to configure +* collision distance in the Transmit Control Register. +* 2) Set up flow control on the MAC to that established with +* the link partner. +* 3) Config DSP to improve Gigabit link quality for some PHY revisions. +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int32_t +e1000_copper_link_postconfig(struct e1000_hw *hw) +{ + int32_t ret_val; + DEBUGFUNC("e1000_copper_link_postconfig"); + + if(hw->mac_type >= e1000_82544) { + e1000_config_collision_dist(hw); + } else { + ret_val = e1000_config_mac_to_phy(hw); + if(ret_val) { + DEBUGOUT("Error configuring MAC to PHY settings\n"); + return ret_val; + } + } + ret_val = e1000_config_fc_after_link_up(hw); + if(ret_val) { + DEBUGOUT("Error Configuring Flow Control\n"); + return ret_val; + } + + /* Config DSP to improve Giga link quality */ + if(hw->phy_type == e1000_phy_igp) { + ret_val = e1000_config_dsp_after_link_change(hw, TRUE); + if(ret_val) { + DEBUGOUT("Error Configuring DSP after link up\n"); + return ret_val; + } + } + + return E1000_SUCCESS; +} + +/****************************************************************************** +* Detects which PHY is present and setup the speed and duplex +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +static int32_t +e1000_setup_copper_link(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t i; + uint16_t phy_data; + + DEBUGFUNC("e1000_setup_copper_link"); + + /* Check if it is a valid PHY and set PHY mode if necessary. */ + ret_val = e1000_copper_link_preconfig(hw); + if(ret_val) + return ret_val; + + if (hw->phy_type == e1000_phy_igp || + hw->phy_type == e1000_phy_igp_2) { + ret_val = e1000_copper_link_igp_setup(hw); + if(ret_val) + return ret_val; + } else if (hw->phy_type == e1000_phy_m88) { + ret_val = e1000_copper_link_mgp_setup(hw); + if(ret_val) + return ret_val; + } + + if(hw->autoneg) { + /* Setup autoneg and flow control advertisement + * and perform autonegotiation */ + ret_val = e1000_copper_link_autoneg(hw); + if(ret_val) + return ret_val; + } else { + /* PHY will be set to 10H, 10F, 100H,or 100F + * depending on value from forced_speed_duplex. */ + DEBUGOUT("Forcing speed and duplex\n"); + ret_val = e1000_phy_force_speed_duplex(hw); + if(ret_val) { + DEBUGOUT("Error Forcing Speed and Duplex\n"); + return ret_val; + } + } + + /* Check link status. Wait up to 100 microseconds for link to become + * valid. + */ + for(i = 0; i < 10; i++) { + ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); + if(ret_val) + return ret_val; + ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); + if(ret_val) + return ret_val; + + if(phy_data & MII_SR_LINK_STATUS) { + /* Config the MAC and PHY after link is up */ + ret_val = e1000_copper_link_postconfig(hw); + if(ret_val) + return ret_val; + + DEBUGOUT("Valid link established!!!\n"); + return E1000_SUCCESS; + } + udelay(10); + } + + DEBUGOUT("Unable to establish link!!!\n"); + return E1000_SUCCESS; +} + +/****************************************************************************** +* Configures PHY autoneg and flow control advertisement settings +* +* hw - Struct containing variables accessed by shared code +******************************************************************************/ +int32_t +e1000_phy_setup_autoneg(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t mii_autoneg_adv_reg; + uint16_t mii_1000t_ctrl_reg; + + DEBUGFUNC("e1000_phy_setup_autoneg"); + + /* Read the MII Auto-Neg Advertisement Register (Address 4). */ + ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); + if(ret_val) + return ret_val; + + /* Read the MII 1000Base-T Control Register (Address 9). */ + ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); + if(ret_val) + return ret_val; + + /* Need to parse both autoneg_advertised and fc and set up + * the appropriate PHY registers. First we will parse for * autoneg_advertised software override. Since we can advertise * a plethora of combinations, we need to check each bit * individually. @@ -1417,7 +1602,7 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw) DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); + ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); if(ret_val) return ret_val; @@ -1678,6 +1863,11 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) DEBUGFUNC("e1000_config_mac_to_phy"); + /* 82544 or newer MAC, Auto Speed Detection takes care of + * MAC speed/duplex configuration.*/ + if (hw->mac_type >= e1000_82544) + return E1000_SUCCESS; + /* Read the Device Control Register and set the bits to Force Speed * and Duplex. */ @@ -1688,45 +1878,25 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) /* Set up duplex in the Device Control and Transmit Control * registers depending on negotiated values. */ - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &phy_data); - if(ret_val) - return ret_val; - - if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; - - e1000_config_collision_dist(hw); + ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); + if(ret_val) + return ret_val; - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_100MBPS) - ctrl |= E1000_CTRL_SPD_100; - } else { - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if(ret_val) - return ret_val; + if(phy_data & M88E1000_PSSR_DPLX) + ctrl |= E1000_CTRL_FD; + else + ctrl &= ~E1000_CTRL_FD; - if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; + e1000_config_collision_dist(hw); - e1000_config_collision_dist(hw); + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) + ctrl |= E1000_CTRL_SPD_1000; + else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) + ctrl |= E1000_CTRL_SPD_100; - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; - } /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); return E1000_SUCCESS; @@ -2494,8 +2664,8 @@ e1000_read_phy_reg(struct e1000_hw *hw, DEBUGFUNC("e1000_read_phy_reg"); - - if(hw->phy_type == e1000_phy_igp && + if((hw->phy_type == e1000_phy_igp || + hw->phy_type == e1000_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); @@ -2600,8 +2770,8 @@ e1000_write_phy_reg(struct e1000_hw *hw, DEBUGFUNC("e1000_write_phy_reg"); - - if(hw->phy_type == e1000_phy_igp && + if((hw->phy_type == e1000_phy_igp || + hw->phy_type == e1000_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (uint16_t)reg_addr); @@ -2679,19 +2849,27 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, return E1000_SUCCESS; } + /****************************************************************************** * Returns the PHY to the power-on reset state * * hw - Struct containing variables accessed by shared code ******************************************************************************/ -void +int32_t e1000_phy_hw_reset(struct e1000_hw *hw) { uint32_t ctrl, ctrl_ext; uint32_t led_ctrl; + int32_t ret_val; DEBUGFUNC("e1000_phy_hw_reset"); + /* In the case of the phy reset being blocked, it's not an error, we + * simply return success without performing the reset. */ + ret_val = e1000_check_phy_reset_block(hw); + if (ret_val) + return E1000_SUCCESS; + DEBUGOUT("Resetting Phy...\n"); if(hw->mac_type > e1000_82543) { @@ -2727,6 +2905,11 @@ e1000_phy_hw_reset(struct e1000_hw *hw) led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, LEDCTL, led_ctrl); } + + /* Wait for FW to finish PHY configuration. */ + ret_val = e1000_get_phy_cfg_done(hw); + + return ret_val; } /****************************************************************************** @@ -2744,7 +2927,19 @@ e1000_phy_reset(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_reset"); - if(hw->mac_type != e1000_82541_rev_2) { + /* In the case of the phy reset being blocked, it's not an error, we + * simply return success without performing the reset. */ + ret_val = e1000_check_phy_reset_block(hw); + if (ret_val) + return E1000_SUCCESS; + + switch (hw->mac_type) { + case e1000_82541_rev_2: + ret_val = e1000_phy_hw_reset(hw); + if(ret_val) + return ret_val; + break; + default: ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); if(ret_val) return ret_val; @@ -2755,9 +2950,10 @@ e1000_phy_reset(struct e1000_hw *hw) return ret_val; udelay(1); - } else e1000_phy_hw_reset(hw); + break; + } - if(hw->phy_type == e1000_phy_igp) + if(hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) e1000_phy_init_script(hw); return E1000_SUCCESS; @@ -2811,6 +3007,9 @@ e1000_detect_gig_phy(struct e1000_hw *hw) case e1000_82547_rev_2: if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; break; + case e1000_82573: + if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE; + break; default: DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; @@ -2866,7 +3065,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw, /* The downshift status is checked only once, after link is established, * and it stored in the hw->speed_downgraded parameter. */ - phy_info->downshift = hw->speed_downgraded; + phy_info->downshift = (e1000_downshift)hw->speed_downgraded; /* IGP01E1000 does not need to support it. */ phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal; @@ -2905,7 +3104,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw, if(ret_val) return ret_val; - /* transalte to old method */ + /* Translate to old method */ average = (max_length + min_length) / 2; if(average <= e1000_igp_cable_length_50) @@ -2940,7 +3139,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw, /* The downshift status is checked only once, after link is established, * and it stored in the hw->speed_downgraded parameter. */ - phy_info->downshift = hw->speed_downgraded; + phy_info->downshift = (e1000_downshift)hw->speed_downgraded; ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if(ret_val) @@ -3029,7 +3228,8 @@ e1000_phy_get_info(struct e1000_hw *hw, return -E1000_ERR_CONFIG; } - if(hw->phy_type == e1000_phy_igp) + if(hw->phy_type == e1000_phy_igp || + hw->phy_type == e1000_phy_igp_2) return e1000_phy_igp_get_info(hw, phy_info); else return e1000_phy_m88_get_info(hw, phy_info); @@ -3055,11 +3255,12 @@ e1000_validate_mdi_setting(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +int32_t e1000_init_eeprom_params(struct e1000_hw *hw) { struct e1000_eeprom_info *eeprom = &hw->eeprom; uint32_t eecd = E1000_READ_REG(hw, EECD); + int32_t ret_val = E1000_SUCCESS; uint16_t eeprom_size; DEBUGFUNC("e1000_init_eeprom_params"); @@ -3074,6 +3275,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->opcode_bits = 3; eeprom->address_bits = 6; eeprom->delay_usec = 50; + eeprom->use_eerd = FALSE; + eeprom->use_eewr = FALSE; break; case e1000_82540: case e1000_82545: @@ -3090,6 +3293,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->word_size = 64; eeprom->address_bits = 6; } + eeprom->use_eerd = FALSE; + eeprom->use_eewr = FALSE; break; case e1000_82541: case e1000_82541_rev_2: @@ -3118,42 +3323,60 @@ e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->address_bits = 6; } } + eeprom->use_eerd = FALSE; + eeprom->use_eewr = FALSE; + break; + case e1000_82573: + eeprom->type = e1000_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + eeprom->use_eerd = TRUE; + eeprom->use_eewr = TRUE; + if(e1000_is_onboard_nvm_eeprom(hw) == FALSE) { + eeprom->type = e1000_eeprom_flash; + eeprom->word_size = 2048; + + /* Ensure that the Autonomous FLASH update bit is cleared due to + * Flash update issue on parts which use a FLASH for NVM. */ + eecd &= ~E1000_EECD_AUPDEN; + E1000_WRITE_REG(hw, EECD, eecd); + } break; default: break; } if (eeprom->type == e1000_eeprom_spi) { - eeprom->word_size = 64; - if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) { - eeprom_size &= EEPROM_SIZE_MASK; - - switch (eeprom_size) { - case EEPROM_SIZE_16KB: - eeprom->word_size = 8192; - break; - case EEPROM_SIZE_8KB: - eeprom->word_size = 4096; - break; - case EEPROM_SIZE_4KB: - eeprom->word_size = 2048; - break; - case EEPROM_SIZE_2KB: - eeprom->word_size = 1024; - break; - case EEPROM_SIZE_1KB: - eeprom->word_size = 512; - break; - case EEPROM_SIZE_512B: - eeprom->word_size = 256; - break; - case EEPROM_SIZE_128B: - default: - eeprom->word_size = 64; - break; - } + /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to + * 32KB (incremented by powers of 2). + */ + if(hw->mac_type <= e1000_82547_rev_2) { + /* Set to default value for initial eeprom read. */ + eeprom->word_size = 64; + ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size); + if(ret_val) + return ret_val; + eeprom_size = (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT; + /* 256B eeprom size was not supported in earlier hardware, so we + * bump eeprom_size up one to ensure that "1" (which maps to 256B) + * is never the result used in the shifting logic below. */ + if(eeprom_size) + eeprom_size++; + } else { + eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >> + E1000_EECD_SIZE_EX_SHIFT); } + + eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT); } + return ret_val; } /****************************************************************************** @@ -3306,8 +3529,12 @@ e1000_acquire_eeprom(struct e1000_hw *hw) DEBUGFUNC("e1000_acquire_eeprom"); + if(e1000_get_hw_eeprom_semaphore(hw)) + return -E1000_ERR_EEPROM; + eecd = E1000_READ_REG(hw, EECD); + if (hw->mac_type != e1000_82573) { /* Request EEPROM Access */ if(hw->mac_type > e1000_82544) { eecd |= E1000_EECD_REQ; @@ -3326,6 +3553,7 @@ e1000_acquire_eeprom(struct e1000_hw *hw) return -E1000_ERR_EEPROM; } } + } /* Setup EEPROM for Read/Write */ @@ -3443,6 +3671,8 @@ e1000_release_eeprom(struct e1000_hw *hw) eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, EECD, eecd); } + + e1000_put_hw_eeprom_semaphore(hw); } /****************************************************************************** @@ -3504,8 +3734,10 @@ e1000_read_eeprom(struct e1000_hw *hw, { struct e1000_eeprom_info *eeprom = &hw->eeprom; uint32_t i = 0; + int32_t ret_val; DEBUGFUNC("e1000_read_eeprom"); + /* A check for invalid values: offset too large, too many words, and not * enough words. */ @@ -3515,9 +3747,23 @@ e1000_read_eeprom(struct e1000_hw *hw, return -E1000_ERR_EEPROM; } - /* Prepare the EEPROM for reading */ - if(e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; + /* FLASH reads without acquiring the semaphore are safe in 82573-based + * controllers. + */ + if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) || + (hw->mac_type != e1000_82573)) { + /* Prepare the EEPROM for reading */ + if(e1000_acquire_eeprom(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; + } + + if(eeprom->use_eerd == TRUE) { + ret_val = e1000_read_eeprom_eerd(hw, offset, words, data); + if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) || + (hw->mac_type != e1000_82573)) + e1000_release_eeprom(hw); + return ret_val; + } if(eeprom->type == e1000_eeprom_spi) { uint16_t word_in; @@ -3569,65 +3815,212 @@ e1000_read_eeprom(struct e1000_hw *hw, } /****************************************************************************** - * Verifies that the EEPROM has a valid checksum + * Reads a 16 bit word from the EEPROM using the EERD register. * * hw - Struct containing variables accessed by shared code - * - * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is - * valid. + * offset - offset of word in the EEPROM to read + * data - word read from the EEPROM + * words - number of words to read *****************************************************************************/ int32_t -e1000_validate_eeprom_checksum(struct e1000_hw *hw) +e1000_read_eeprom_eerd(struct e1000_hw *hw, + uint16_t offset, + uint16_t words, + uint16_t *data) { - uint16_t checksum = 0; - uint16_t i, eeprom_data; + uint32_t i, eerd = 0; + int32_t error = 0; - DEBUGFUNC("e1000_validate_eeprom_checksum"); + for (i = 0; i < words; i++) { + eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) + + E1000_EEPROM_RW_REG_START; - for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; + E1000_WRITE_REG(hw, EERD, eerd); + error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ); + + if(error) { + break; } - checksum += eeprom_data; - } - - if(checksum == (uint16_t) EEPROM_SUM) - return E1000_SUCCESS; - else { - DEBUGOUT("EEPROM Checksum Invalid\n"); - return -E1000_ERR_EEPROM; + data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA); + } + + return error; } /****************************************************************************** - * Calculates the EEPROM checksum and writes it to the EEPROM + * Writes a 16 bit word from the EEPROM using the EEWR register. * * hw - Struct containing variables accessed by shared code - * - * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. - * Writes the difference to word offset 63 of the EEPROM. + * offset - offset of word in the EEPROM to read + * data - word read from the EEPROM + * words - number of words to read *****************************************************************************/ int32_t -e1000_update_eeprom_checksum(struct e1000_hw *hw) +e1000_write_eeprom_eewr(struct e1000_hw *hw, + uint16_t offset, + uint16_t words, + uint16_t *data) { - uint16_t checksum = 0; - uint16_t i, eeprom_data; + uint32_t register_value = 0; + uint32_t i = 0; + int32_t error = 0; - DEBUGFUNC("e1000_update_eeprom_checksum"); + for (i = 0; i < words; i++) { + register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | + ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | + E1000_EEPROM_RW_REG_START; - for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { - if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - DEBUGOUT("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - checksum = (uint16_t) EEPROM_SUM - checksum; + error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE); + if(error) { + break; + } + + E1000_WRITE_REG(hw, EEWR, register_value); + + error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE); + + if(error) { + break; + } + } + + return error; +} + +/****************************************************************************** + * Polls the status bit (bit 1) of the EERD to determine when the read is done. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +int32_t +e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd) +{ + uint32_t attempts = 100000; + uint32_t i, reg = 0; + int32_t done = E1000_ERR_EEPROM; + + for(i = 0; i < attempts; i++) { + if(eerd == E1000_EEPROM_POLL_READ) + reg = E1000_READ_REG(hw, EERD); + else + reg = E1000_READ_REG(hw, EEWR); + + if(reg & E1000_EEPROM_RW_REG_DONE) { + done = E1000_SUCCESS; + break; + } + udelay(5); + } + + return done; +} + +/*************************************************************************** +* Description: Determines if the onboard NVM is FLASH or EEPROM. +* +* hw - Struct containing variables accessed by shared code +****************************************************************************/ +boolean_t +e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw) +{ + uint32_t eecd = 0; + + if(hw->mac_type == e1000_82573) { + eecd = E1000_READ_REG(hw, EECD); + + /* Isolate bits 15 & 16 */ + eecd = ((eecd >> 15) & 0x03); + + /* If both bits are set, device is Flash type */ + if(eecd == 0x03) { + return FALSE; + } + } + return TRUE; +} + +/****************************************************************************** + * Verifies that the EEPROM has a valid checksum + * + * hw - Struct containing variables accessed by shared code + * + * Reads the first 64 16 bit words of the EEPROM and sums the values read. + * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is + * valid. + *****************************************************************************/ +int32_t +e1000_validate_eeprom_checksum(struct e1000_hw *hw) +{ + uint16_t checksum = 0; + uint16_t i, eeprom_data; + + DEBUGFUNC("e1000_validate_eeprom_checksum"); + + if ((hw->mac_type == e1000_82573) && + (e1000_is_onboard_nvm_eeprom(hw) == FALSE)) { + /* Check bit 4 of word 10h. If it is 0, firmware is done updating + * 10h-12h. Checksum may need to be fixed. */ + e1000_read_eeprom(hw, 0x10, 1, &eeprom_data); + if ((eeprom_data & 0x10) == 0) { + /* Read 0x23 and check bit 15. This bit is a 1 when the checksum + * has already been fixed. If the checksum is still wrong and this + * bit is a 1, we need to return bad checksum. Otherwise, we need + * to set this bit to a 1 and update the checksum. */ + e1000_read_eeprom(hw, 0x23, 1, &eeprom_data); + if ((eeprom_data & 0x8000) == 0) { + eeprom_data |= 0x8000; + e1000_write_eeprom(hw, 0x23, 1, &eeprom_data); + e1000_update_eeprom_checksum(hw); + } + } + } + + for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { + if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + checksum += eeprom_data; + } + + if(checksum == (uint16_t) EEPROM_SUM) + return E1000_SUCCESS; + else { + DEBUGOUT("EEPROM Checksum Invalid\n"); + return -E1000_ERR_EEPROM; + } +} + +/****************************************************************************** + * Calculates the EEPROM checksum and writes it to the EEPROM + * + * hw - Struct containing variables accessed by shared code + * + * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. + * Writes the difference to word offset 63 of the EEPROM. + *****************************************************************************/ +int32_t +e1000_update_eeprom_checksum(struct e1000_hw *hw) +{ + uint16_t checksum = 0; + uint16_t i, eeprom_data; + + DEBUGFUNC("e1000_update_eeprom_checksum"); + + for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { + if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { + DEBUGOUT("EEPROM Read Error\n"); + return -E1000_ERR_EEPROM; + } + checksum += eeprom_data; + } + checksum = (uint16_t) EEPROM_SUM - checksum; if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { DEBUGOUT("EEPROM Write Error\n"); return -E1000_ERR_EEPROM; + } else if (hw->eeprom.type == e1000_eeprom_flash) { + e1000_commit_shadow_ram(hw); } return E1000_SUCCESS; } @@ -3663,6 +4056,10 @@ e1000_write_eeprom(struct e1000_hw *hw, return -E1000_ERR_EEPROM; } + /* 82573 reads only through eerd */ + if(eeprom->use_eewr == TRUE) + return e1000_write_eeprom_eewr(hw, offset, words, data); + /* Prepare the EEPROM for writing */ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; @@ -3833,6 +4230,65 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw, } /****************************************************************************** + * Flushes the cached eeprom to NVM. This is done by saving the modified values + * in the eeprom cache and the non modified values in the currently active bank + * to the new bank. + * + * hw - Struct containing variables accessed by shared code + * offset - offset of word in the EEPROM to read + * data - word read from the EEPROM + * words - number of words to read + *****************************************************************************/ +int32_t +e1000_commit_shadow_ram(struct e1000_hw *hw) +{ + uint32_t attempts = 100000; + uint32_t eecd = 0; + uint32_t flop = 0; + uint32_t i = 0; + int32_t error = E1000_SUCCESS; + + /* The flop register will be used to determine if flash type is STM */ + flop = E1000_READ_REG(hw, FLOP); + + if (hw->mac_type == e1000_82573) { + for (i=0; i < attempts; i++) { + eecd = E1000_READ_REG(hw, EECD); + if ((eecd & E1000_EECD_FLUPD) == 0) { + break; + } + udelay(5); + } + + if (i == attempts) { + return -E1000_ERR_EEPROM; + } + + /* If STM opcode located in bits 15:8 of flop, reset firmware */ + if ((flop & 0xFF00) == E1000_STM_OPCODE) { + E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET); + } + + /* Perform the flash update */ + E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD); + + for (i=0; i < attempts; i++) { + eecd = E1000_READ_REG(hw, EECD); + if ((eecd & E1000_EECD_FLUPD) == 0) { + break; + } + udelay(5); + } + + if (i == attempts) { + return -E1000_ERR_EEPROM; + } + } + + return error; +} + +/****************************************************************************** * Reads the adapter's part number from the EEPROM * * hw - Struct containing variables accessed by shared code @@ -3911,6 +4367,7 @@ void e1000_init_rx_addrs(struct e1000_hw *hw) { uint32_t i; + uint32_t rar_num; DEBUGFUNC("e1000_init_rx_addrs"); @@ -3919,9 +4376,10 @@ e1000_init_rx_addrs(struct e1000_hw *hw) e1000_rar_set(hw, hw->mac_addr, 0); + rar_num = E1000_RAR_ENTRIES; /* Zero out the other 15 receive addresses. */ DEBUGOUT("Clearing RAR[1-15]\n"); - for(i = 1; i < E1000_RAR_ENTRIES; i++) { + for(i = 1; i < rar_num; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); } @@ -3950,7 +4408,9 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, { uint32_t hash_value; uint32_t i; - + uint32_t num_rar_entry; + uint32_t num_mta_entry; + DEBUGFUNC("e1000_mc_addr_list_update"); /* Set the new number of MC addresses that we are being requested to use. */ @@ -3958,14 +4418,16 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, /* Clear RAR[1-15] */ DEBUGOUT(" Clearing RAR[1-15]\n"); - for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) { + num_rar_entry = E1000_RAR_ENTRIES; + for(i = rar_used_count; i < num_rar_entry; i++) { E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); } /* Clear the MTA */ DEBUGOUT(" Clearing MTA\n"); - for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) { + num_mta_entry = E1000_NUM_MTA_REGISTERS; + for(i = 0; i < num_mta_entry; i++) { E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); } @@ -3989,7 +4451,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, /* Place this multicast address in the RAR if there is room, * * else put it in the MTA */ - if(rar_used_count < E1000_RAR_ENTRIES) { + if (rar_used_count < num_rar_entry) { e1000_rar_set(hw, mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)), rar_used_count); @@ -4040,6 +4502,7 @@ e1000_hash_mc_addr(struct e1000_hw *hw, } hash_value &= 0xFFF; + return hash_value; } @@ -4144,12 +4607,33 @@ void e1000_clear_vfta(struct e1000_hw *hw) { uint32_t offset; - - for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); + uint32_t vfta_value = 0; + uint32_t vfta_offset = 0; + uint32_t vfta_bit_in_reg = 0; + + if (hw->mac_type == e1000_82573) { + if (hw->mng_cookie.vlan_id != 0) { + /* The VFTA is a 4096b bit-field, each identifying a single VLAN + * ID. The following operations determine which 32b entry + * (i.e. offset) into the array we want to set the VLAN ID + * (i.e. bit) of the manageability unit. */ + vfta_offset = (hw->mng_cookie.vlan_id >> + E1000_VFTA_ENTRY_SHIFT) & + E1000_VFTA_ENTRY_MASK; + vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & + E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + } + } + for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { + /* If the offset we want to clear is the same offset of the + * manageability VLAN ID, then clear all bits except that of the + * manageability unit */ + vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; + E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value); + } } -static int32_t +int32_t e1000_id_led_init(struct e1000_hw * hw) { uint32_t ledctl; @@ -4480,6 +4964,19 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw) temp = E1000_READ_REG(hw, MGTPRC); temp = E1000_READ_REG(hw, MGTPDC); temp = E1000_READ_REG(hw, MGTPTC); + + if(hw->mac_type <= e1000_82547_rev_2) return; + + temp = E1000_READ_REG(hw, IAC); + temp = E1000_READ_REG(hw, ICRXOC); + temp = E1000_READ_REG(hw, ICRXPTC); + temp = E1000_READ_REG(hw, ICRXATC); + temp = E1000_READ_REG(hw, ICTXPTC); + temp = E1000_READ_REG(hw, ICTXATC); + temp = E1000_READ_REG(hw, ICTXQEC); + temp = E1000_READ_REG(hw, ICTXQMTC); + temp = E1000_READ_REG(hw, ICRXDMTC); + } /****************************************************************************** @@ -4646,6 +5143,11 @@ e1000_get_bus_info(struct e1000_hw *hw) hw->bus_speed = e1000_bus_speed_unknown; hw->bus_width = e1000_bus_width_unknown; break; + case e1000_82573: + hw->bus_type = e1000_bus_type_pci_express; + hw->bus_speed = e1000_bus_speed_2500; + hw->bus_width = e1000_bus_width_pciex_4; + break; default: status = E1000_READ_REG(hw, STATUS); hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? @@ -4749,6 +5251,7 @@ e1000_get_cable_length(struct e1000_hw *hw, /* Use old method for Phy older than IGP */ if(hw->phy_type == e1000_phy_m88) { + ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if(ret_val) @@ -4865,7 +5368,8 @@ e1000_check_polarity(struct e1000_hw *hw, return ret_val; *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> M88E1000_PSSR_REV_POLARITY_SHIFT; - } else if(hw->phy_type == e1000_phy_igp) { + } else if(hw->phy_type == e1000_phy_igp || + hw->phy_type == e1000_phy_igp_2) { /* Read the Status register to check the speed */ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data); @@ -4917,7 +5421,8 @@ e1000_check_downshift(struct e1000_hw *hw) DEBUGFUNC("e1000_check_downshift"); - if(hw->phy_type == e1000_phy_igp) { + if(hw->phy_type == e1000_phy_igp || + hw->phy_type == e1000_phy_igp_2) { ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data); if(ret_val) @@ -4933,6 +5438,7 @@ e1000_check_downshift(struct e1000_hw *hw) hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> M88E1000_PSSR_DOWNSHIFT_SHIFT; } + return E1000_SUCCESS; } @@ -5047,7 +5553,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw, if(ret_val) return ret_val; - msec_delay(20); + msec_delay_irq(20); ret_val = e1000_write_phy_reg(hw, 0x0000, IGP01E1000_IEEE_FORCE_GIGA); @@ -5071,7 +5577,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw, if(ret_val) return ret_val; - msec_delay(20); + msec_delay_irq(20); /* Now enable the transmitter */ ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); @@ -5096,7 +5602,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw, if(ret_val) return ret_val; - msec_delay(20); + msec_delay_irq(20); ret_val = e1000_write_phy_reg(hw, 0x0000, IGP01E1000_IEEE_FORCE_GIGA); @@ -5112,7 +5618,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw, if(ret_val) return ret_val; - msec_delay(20); + msec_delay_irq(20); /* Now enable the transmitter */ ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); @@ -5187,22 +5693,36 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw, uint16_t phy_data; DEBUGFUNC("e1000_set_d3_lplu_state"); - if(!((hw->mac_type == e1000_82541_rev_2) || - (hw->mac_type == e1000_82547_rev_2))) + if(hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2) return E1000_SUCCESS; /* During driver activity LPLU should not be used or it will attain link * from the lowest speeds starting from 10Mbps. The capability is used for * Dx transitions and states */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data); - if(ret_val) - return ret_val; - - if(!active) { - phy_data &= ~IGP01E1000_GMII_FLEX_SPD; - ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data); + if(hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) { + ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data); + if(ret_val) + return ret_val; + } else { + ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); if(ret_val) return ret_val; + } + + if(!active) { + if(hw->mac_type == e1000_82541_rev_2 || + hw->mac_type == e1000_82547_rev_2) { + phy_data &= ~IGP01E1000_GMII_FLEX_SPD; + ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data); + if(ret_val) + return ret_val; + } else { + phy_data &= ~IGP02E1000_PM_D3_LPLU; + ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, + phy_data); + if (ret_val) + return ret_val; + } /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during * Dx states where the power conservation is most important. During @@ -5236,11 +5756,105 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw, (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { - phy_data |= IGP01E1000_GMII_FLEX_SPD; - ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data); + if(hw->mac_type == e1000_82541_rev_2 || + hw->mac_type == e1000_82547_rev_2) { + phy_data |= IGP01E1000_GMII_FLEX_SPD; + ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data); + if(ret_val) + return ret_val; + } else { + phy_data |= IGP02E1000_PM_D3_LPLU; + ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, + phy_data); + if (ret_val) + return ret_val; + } + + /* When LPLU is enabled we should disable SmartSpeed */ + ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); + if(ret_val) + return ret_val; + + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data); + if(ret_val) + return ret_val; + + } + return E1000_SUCCESS; +} + +/***************************************************************************** + * + * This function sets the lplu d0 state according to the active flag. When + * activating lplu this function also disables smart speed and vise versa. + * lplu will not be activated unless the device autonegotiation advertisment + * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. + * hw: Struct containing variables accessed by shared code + * active - true to enable lplu false to disable lplu. + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_set_d0_lplu_state(struct e1000_hw *hw, + boolean_t active) +{ + int32_t ret_val; + uint16_t phy_data; + DEBUGFUNC("e1000_set_d0_lplu_state"); + + if(hw->mac_type <= e1000_82547_rev_2) + return E1000_SUCCESS; + + ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); if(ret_val) return ret_val; + if (!active) { + phy_data &= ~IGP02E1000_PM_D0_LPLU; + ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); + if (ret_val) + return ret_val; + + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during + * Dx states where the power conservation is most important. During + * driver activity we should enable SmartSpeed, so performance is + * maintained. */ + if (hw->smart_speed == e1000_smart_speed_on) { + ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data); + if(ret_val) + return ret_val; + + phy_data |= IGP01E1000_PSCFR_SMART_SPEED; + ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data); + if(ret_val) + return ret_val; + } else if (hw->smart_speed == e1000_smart_speed_off) { + ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data); + if (ret_val) + return ret_val; + + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data); + if(ret_val) + return ret_val; + } + + + } else { + + phy_data |= IGP02E1000_PM_D0_LPLU; + ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); + if (ret_val) + return ret_val; + /* When LPLU is enabled we should disable SmartSpeed */ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data); if(ret_val) @@ -5318,18 +5932,350 @@ e1000_set_vco_speed(struct e1000_hw *hw) return E1000_SUCCESS; } -static int32_t -e1000_polarity_reversal_workaround(struct e1000_hw *hw) -{ - int32_t ret_val; - uint16_t mii_status_reg; - uint16_t i; - /* Polarity reversal workaround for forced 10F/10H links. */ +/***************************************************************************** + * This function reads the cookie from ARC ram. + * + * returns: - E1000_SUCCESS . + ****************************************************************************/ +int32_t +e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer) +{ + uint8_t i; + uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; + uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH; - /* Disable the transmitter on the PHY */ + length = (length >> 2); + offset = (offset >> 2); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); + for (i = 0; i < length; i++) { + *((uint32_t *) buffer + i) = + E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i); + } + return E1000_SUCCESS; +} + + +/***************************************************************************** + * This function checks whether the HOST IF is enabled for command operaton + * and also checks whether the previous command is completed. + * It busy waits in case of previous command is not completed. + * + * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or + * timeout + * - E1000_SUCCESS for success. + ****************************************************************************/ +int32_t +e1000_mng_enable_host_if(struct e1000_hw * hw) +{ + uint32_t hicr; + uint8_t i; + + /* Check that the host interface is enabled. */ + hicr = E1000_READ_REG(hw, HICR); + if ((hicr & E1000_HICR_EN) == 0) { + DEBUGOUT("E1000_HOST_EN bit disabled.\n"); + return -E1000_ERR_HOST_INTERFACE_COMMAND; + } + /* check the previous command is completed */ + for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { + hicr = E1000_READ_REG(hw, HICR); + if (!(hicr & E1000_HICR_C)) + break; + msec_delay_irq(1); + } + + if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { + DEBUGOUT("Previous command timeout failed .\n"); + return -E1000_ERR_HOST_INTERFACE_COMMAND; + } + return E1000_SUCCESS; +} + +/***************************************************************************** + * This function writes the buffer content at the offset given on the host if. + * It also does alignment considerations to do the writes in most efficient way. + * Also fills up the sum of the buffer in *buffer parameter. + * + * returns - E1000_SUCCESS for success. + ****************************************************************************/ +int32_t +e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer, + uint16_t length, uint16_t offset, uint8_t *sum) +{ + uint8_t *tmp; + uint8_t *bufptr = buffer; + uint32_t data; + uint16_t remaining, i, j, prev_bytes; + + /* sum = only sum of the data and it is not checksum */ + + if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { + return -E1000_ERR_PARAM; + } + + tmp = (uint8_t *)&data; + prev_bytes = offset & 0x3; + offset &= 0xFFFC; + offset >>= 2; + + if (prev_bytes) { + data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset); + for (j = prev_bytes; j < sizeof(uint32_t); j++) { + *(tmp + j) = *bufptr++; + *sum += *(tmp + j); + } + E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset, data); + length -= j - prev_bytes; + offset++; + } + + remaining = length & 0x3; + length -= remaining; + + /* Calculate length in DWORDs */ + length >>= 2; + + /* The device driver writes the relevant command block into the + * ram area. */ + for (i = 0; i < length; i++) { + for (j = 0; j < sizeof(uint32_t); j++) { + *(tmp + j) = *bufptr++; + *sum += *(tmp + j); + } + + E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data); + } + if (remaining) { + for (j = 0; j < sizeof(uint32_t); j++) { + if (j < remaining) + *(tmp + j) = *bufptr++; + else + *(tmp + j) = 0; + + *sum += *(tmp + j); + } + E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data); + } + + return E1000_SUCCESS; +} + + +/***************************************************************************** + * This function writes the command header after does the checksum calculation. + * + * returns - E1000_SUCCESS for success. + ****************************************************************************/ +int32_t +e1000_mng_write_cmd_header(struct e1000_hw * hw, + struct e1000_host_mng_command_header * hdr) +{ + uint16_t i; + uint8_t sum; + uint8_t *buffer; + + /* Write the whole command header structure which includes sum of + * the buffer */ + + uint16_t length = sizeof(struct e1000_host_mng_command_header); + + sum = hdr->checksum; + hdr->checksum = 0; + + buffer = (uint8_t *) hdr; + i = length; + while(i--) + sum += buffer[i]; + + hdr->checksum = 0 - sum; + + length >>= 2; + /* The device driver writes the relevant command block into the ram area. */ + for (i = 0; i < length; i++) + E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i)); + + return E1000_SUCCESS; +} + + +/***************************************************************************** + * This function indicates to ARC that a new command is pending which completes + * one write operation by the driver. + * + * returns - E1000_SUCCESS for success. + ****************************************************************************/ +int32_t +e1000_mng_write_commit( + struct e1000_hw * hw) +{ + uint32_t hicr; + + hicr = E1000_READ_REG(hw, HICR); + /* Setting this bit tells the ARC that a new command is pending. */ + E1000_WRITE_REG(hw, HICR, hicr | E1000_HICR_C); + + return E1000_SUCCESS; +} + + +/***************************************************************************** + * This function checks the mode of the firmware. + * + * returns - TRUE when the mode is IAMT or FALSE. + ****************************************************************************/ +boolean_t +e1000_check_mng_mode( + struct e1000_hw *hw) +{ + uint32_t fwsm; + + fwsm = E1000_READ_REG(hw, FWSM); + + if((fwsm & E1000_FWSM_MODE_MASK) == + (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) + return TRUE; + + return FALSE; +} + + +/***************************************************************************** + * This function writes the dhcp info . + ****************************************************************************/ +int32_t +e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer, + uint16_t length) +{ + int32_t ret_val; + struct e1000_host_mng_command_header hdr; + + hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; + hdr.command_length = length; + hdr.reserved1 = 0; + hdr.reserved2 = 0; + hdr.checksum = 0; + + ret_val = e1000_mng_enable_host_if(hw); + if (ret_val == E1000_SUCCESS) { + ret_val = e1000_mng_host_if_write(hw, buffer, length, sizeof(hdr), + &(hdr.checksum)); + if (ret_val == E1000_SUCCESS) { + ret_val = e1000_mng_write_cmd_header(hw, &hdr); + if (ret_val == E1000_SUCCESS) + ret_val = e1000_mng_write_commit(hw); + } + } + return ret_val; +} + + +/***************************************************************************** + * This function calculates the checksum. + * + * returns - checksum of buffer contents. + ****************************************************************************/ +uint8_t +e1000_calculate_mng_checksum(char *buffer, uint32_t length) +{ + uint8_t sum = 0; + uint32_t i; + + if (!buffer) + return 0; + + for (i=0; i < length; i++) + sum += buffer[i]; + + return (uint8_t) (0 - sum); +} + +/***************************************************************************** + * This function checks whether tx pkt filtering needs to be enabled or not. + * + * returns - TRUE for packet filtering or FALSE. + ****************************************************************************/ +boolean_t +e1000_enable_tx_pkt_filtering(struct e1000_hw *hw) +{ + /* called in init as well as watchdog timer functions */ + + int32_t ret_val, checksum; + boolean_t tx_filter = FALSE; + struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie); + uint8_t *buffer = (uint8_t *) &(hw->mng_cookie); + + if (e1000_check_mng_mode(hw)) { + ret_val = e1000_mng_enable_host_if(hw); + if (ret_val == E1000_SUCCESS) { + ret_val = e1000_host_if_read_cookie(hw, buffer); + if (ret_val == E1000_SUCCESS) { + checksum = hdr->checksum; + hdr->checksum = 0; + if ((hdr->signature == E1000_IAMT_SIGNATURE) && + checksum == e1000_calculate_mng_checksum((char *)buffer, + E1000_MNG_DHCP_COOKIE_LENGTH)) { + if (hdr->status & + E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT) + tx_filter = TRUE; + } else + tx_filter = TRUE; + } else + tx_filter = TRUE; + } + } + + hw->tx_pkt_filtering = tx_filter; + return tx_filter; +} + +/****************************************************************************** + * Verifies the hardware needs to allow ARPs to be processed by the host + * + * hw - Struct containing variables accessed by shared code + * + * returns: - TRUE/FALSE + * + *****************************************************************************/ +uint32_t +e1000_enable_mng_pass_thru(struct e1000_hw *hw) +{ + uint32_t manc; + uint32_t fwsm, factps; + + if (hw->asf_firmware_present) { + manc = E1000_READ_REG(hw, MANC); + + if (!(manc & E1000_MANC_RCV_TCO_EN) || + !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) + return FALSE; + if (e1000_arc_subsystem_valid(hw) == TRUE) { + fwsm = E1000_READ_REG(hw, FWSM); + factps = E1000_READ_REG(hw, FACTPS); + + if (((fwsm & E1000_FWSM_MODE_MASK) == + (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)) && + (factps & E1000_FACTPS_MNGCG)) + return TRUE; + } else + if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) + return TRUE; + } + return FALSE; +} + +static int32_t +e1000_polarity_reversal_workaround(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t mii_status_reg; + uint16_t i; + + /* Polarity reversal workaround for forced 10F/10H links. */ + + /* Disable the transmitter on the PHY */ + + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); if(ret_val) return ret_val; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); @@ -5403,3 +6349,265 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw) return E1000_SUCCESS; } +/*************************************************************************** + * + * Disables PCI-Express master access. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - none. + * + ***************************************************************************/ +void +e1000_set_pci_express_master_disable(struct e1000_hw *hw) +{ + uint32_t ctrl; + + DEBUGFUNC("e1000_set_pci_express_master_disable"); + + if (hw->bus_type != e1000_bus_type_pci_express) + return; + + ctrl = E1000_READ_REG(hw, CTRL); + ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; + E1000_WRITE_REG(hw, CTRL, ctrl); +} + +/*************************************************************************** + * + * Enables PCI-Express master access. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - none. + * + ***************************************************************************/ +void +e1000_enable_pciex_master(struct e1000_hw *hw) +{ + uint32_t ctrl; + + DEBUGFUNC("e1000_enable_pciex_master"); + + if (hw->bus_type != e1000_bus_type_pci_express) + return; + + ctrl = E1000_READ_REG(hw, CTRL); + ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE; + E1000_WRITE_REG(hw, CTRL, ctrl); +} + +/******************************************************************************* + * + * Disables PCI-Express master access and verifies there are no pending requests + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_MASTER_REQUESTS_PENDING if master disable bit hasn't + * caused the master requests to be disabled. + * E1000_SUCCESS master requests disabled. + * + ******************************************************************************/ +int32_t +e1000_disable_pciex_master(struct e1000_hw *hw) +{ + int32_t timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */ + + DEBUGFUNC("e1000_disable_pciex_master"); + + if (hw->bus_type != e1000_bus_type_pci_express) + return E1000_SUCCESS; + + e1000_set_pci_express_master_disable(hw); + + while(timeout) { + if(!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) + break; + else + udelay(100); + timeout--; + } + + if(!timeout) { + DEBUGOUT("Master requests are pending.\n"); + return -E1000_ERR_MASTER_REQUESTS_PENDING; + } + + return E1000_SUCCESS; +} + +/******************************************************************************* + * + * Check for EEPROM Auto Read bit done. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_RESET if fail to reset MAC + * E1000_SUCCESS at any other case. + * + ******************************************************************************/ +int32_t +e1000_get_auto_rd_done(struct e1000_hw *hw) +{ + int32_t timeout = AUTO_READ_DONE_TIMEOUT; + + DEBUGFUNC("e1000_get_auto_rd_done"); + + switch (hw->mac_type) { + default: + msec_delay(5); + break; + case e1000_82573: + while(timeout) { + if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break; + else msec_delay(1); + timeout--; + } + + if(!timeout) { + DEBUGOUT("Auto read by HW from EEPROM has not completed.\n"); + return -E1000_ERR_RESET; + } + break; + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * Checks if the PHY configuration is done + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_RESET if fail to reset MAC + * E1000_SUCCESS at any other case. + * + ***************************************************************************/ +int32_t +e1000_get_phy_cfg_done(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_get_phy_cfg_done"); + + /* Simply wait for 10ms */ + msec_delay(10); + + return E1000_SUCCESS; +} + +/*************************************************************************** + * + * Using the combination of SMBI and SWESMBI semaphore bits when resetting + * adapter or Eeprom access. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_EEPROM if fail to access EEPROM. + * E1000_SUCCESS at any other case. + * + ***************************************************************************/ +int32_t +e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) +{ + int32_t timeout; + uint32_t swsm; + + DEBUGFUNC("e1000_get_hw_eeprom_semaphore"); + + if(!hw->eeprom_semaphore_present) + return E1000_SUCCESS; + + + /* Get the FW semaphore. */ + timeout = hw->eeprom.word_size + 1; + while(timeout) { + swsm = E1000_READ_REG(hw, SWSM); + swsm |= E1000_SWSM_SWESMBI; + E1000_WRITE_REG(hw, SWSM, swsm); + /* if we managed to set the bit we got the semaphore. */ + swsm = E1000_READ_REG(hw, SWSM); + if(swsm & E1000_SWSM_SWESMBI) + break; + + udelay(50); + timeout--; + } + + if(!timeout) { + /* Release semaphores */ + e1000_put_hw_eeprom_semaphore(hw); + DEBUGOUT("Driver can't access the Eeprom - SWESMBI bit is set.\n"); + return -E1000_ERR_EEPROM; + } + + return E1000_SUCCESS; +} + +/*************************************************************************** + * This function clears HW semaphore bits. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - None. + * + ***************************************************************************/ +void +e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) +{ + uint32_t swsm; + + DEBUGFUNC("e1000_put_hw_eeprom_semaphore"); + + if(!hw->eeprom_semaphore_present) + return; + + swsm = E1000_READ_REG(hw, SWSM); + /* Release both semaphores. */ + swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); + E1000_WRITE_REG(hw, SWSM, swsm); +} + +/****************************************************************************** + * Checks if PHY reset is blocked due to SOL/IDER session, for example. + * Returning E1000_BLK_PHY_RESET isn't necessarily an error. But it's up to + * the caller to figure out how to deal with it. + * + * hw - Struct containing variables accessed by shared code + * + * returns: - E1000_BLK_PHY_RESET + * E1000_SUCCESS + * + *****************************************************************************/ +int32_t +e1000_check_phy_reset_block(struct e1000_hw *hw) +{ + uint32_t manc = 0; + if(hw->mac_type > e1000_82547_rev_2) + manc = E1000_READ_REG(hw, MANC); + return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? + E1000_BLK_PHY_RESET : E1000_SUCCESS; +} + +uint8_t +e1000_arc_subsystem_valid(struct e1000_hw *hw) +{ + uint32_t fwsm; + + /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC + * may not be provided a DMA clock when no manageability features are + * enabled. We do not want to perform any reads/writes to these registers + * if this is the case. We read FWSM to determine the manageability mode. + */ + switch (hw->mac_type) { + case e1000_82573: + fwsm = E1000_READ_REG(hw, FWSM); + if((fwsm & E1000_FWSM_MODE_MASK) != 0) + return TRUE; + break; + default: + break; + } + return FALSE; +} + + + diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index f397e63..1573f60 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -57,6 +57,7 @@ typedef enum { e1000_82541_rev_2, e1000_82547, e1000_82547_rev_2, + e1000_82573, e1000_num_macs } e1000_mac_type; @@ -64,6 +65,7 @@ typedef enum { e1000_eeprom_uninitialized = 0, e1000_eeprom_spi, e1000_eeprom_microwire, + e1000_eeprom_flash, e1000_num_eeprom_types } e1000_eeprom_type; @@ -96,6 +98,7 @@ typedef enum { e1000_bus_type_unknown = 0, e1000_bus_type_pci, e1000_bus_type_pcix, + e1000_bus_type_pci_express, e1000_bus_type_reserved } e1000_bus_type; @@ -107,6 +110,7 @@ typedef enum { e1000_bus_speed_100, e1000_bus_speed_120, e1000_bus_speed_133, + e1000_bus_speed_2500, e1000_bus_speed_reserved } e1000_bus_speed; @@ -115,6 +119,8 @@ typedef enum { e1000_bus_width_unknown = 0, e1000_bus_width_32, e1000_bus_width_64, + e1000_bus_width_pciex_1, + e1000_bus_width_pciex_4, e1000_bus_width_reserved } e1000_bus_width; @@ -196,6 +202,7 @@ typedef enum { typedef enum { e1000_phy_m88 = 0, e1000_phy_igp, + e1000_phy_igp_2, e1000_phy_undefined = 0xFF } e1000_phy_type; @@ -242,8 +249,19 @@ struct e1000_eeprom_info { uint16_t address_bits; uint16_t delay_usec; uint16_t page_size; + boolean_t use_eerd; + boolean_t use_eewr; }; +/* Flex ASF Information */ +#define E1000_HOST_IF_MAX_SIZE 2048 + +typedef enum { + e1000_byte_align = 0, + e1000_word_align = 1, + e1000_dword_align = 2 +} e1000_align_type; + /* Error Codes */ @@ -254,11 +272,16 @@ struct e1000_eeprom_info { #define E1000_ERR_PARAM 4 #define E1000_ERR_MAC_TYPE 5 #define E1000_ERR_PHY_TYPE 6 +#define E1000_ERR_RESET 9 +#define E1000_ERR_MASTER_REQUESTS_PENDING 10 +#define E1000_ERR_HOST_INTERFACE_COMMAND 11 +#define E1000_BLK_PHY_RESET 12 /* Function prototypes */ /* Initialization */ int32_t e1000_reset_hw(struct e1000_hw *hw); int32_t e1000_init_hw(struct e1000_hw *hw); +int32_t e1000_id_led_init(struct e1000_hw * hw); int32_t e1000_set_mac_type(struct e1000_hw *hw); void e1000_set_media_type(struct e1000_hw *hw); @@ -275,7 +298,7 @@ int32_t e1000_force_mac_fc(struct e1000_hw *hw); /* PHY */ int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data); int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data); -void e1000_phy_hw_reset(struct e1000_hw *hw); +int32_t e1000_phy_hw_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw); int32_t e1000_detect_gig_phy(struct e1000_hw *hw); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); @@ -287,13 +310,86 @@ int32_t e1000_check_downshift(struct e1000_hw *hw); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); /* EEPROM Functions */ -void e1000_init_eeprom_params(struct e1000_hw *hw); +int32_t e1000_init_eeprom_params(struct e1000_hw *hw); +boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw); +int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); +int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); +int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd); + +/* MNG HOST IF functions */ +uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw); + +#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 +#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */ + +#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */ +#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */ +#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */ +#define E1000_MNG_IAMT_MODE 0x3 +#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */ + +#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */ +#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */ +#define E1000_VFTA_ENTRY_SHIFT 0x5 +#define E1000_VFTA_ENTRY_MASK 0x7F +#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F + +struct e1000_host_mng_command_header { + uint8_t command_id; + uint8_t checksum; + uint16_t reserved1; + uint16_t reserved2; + uint16_t command_length; +}; + +struct e1000_host_mng_command_info { + struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ + uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/ +}; +#ifdef __BIG_ENDIAN +struct e1000_host_mng_dhcp_cookie{ + uint32_t signature; + uint16_t vlan_id; + uint8_t reserved0; + uint8_t status; + uint32_t reserved1; + uint8_t checksum; + uint8_t reserved3; + uint16_t reserved2; +}; +#else +struct e1000_host_mng_dhcp_cookie{ + uint32_t signature; + uint8_t status; + uint8_t reserved0; + uint16_t vlan_id; + uint32_t reserved1; + uint16_t reserved2; + uint8_t reserved3; + uint8_t checksum; +}; +#endif + +int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, + uint16_t length); +boolean_t e1000_check_mng_mode(struct e1000_hw *hw); +boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); +int32_t e1000_mng_enable_host_if(struct e1000_hw *hw); +int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer, + uint16_t length, uint16_t offset, uint8_t *sum); +int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw, + struct e1000_host_mng_command_header* hdr); + +int32_t e1000_mng_write_commit(struct e1000_hw *hw); + int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num); int32_t e1000_read_mac_addr(struct e1000_hw * hw); +int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask); +void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask); /* Filters (multicast, vlan, receive) */ void e1000_init_rx_addrs(struct e1000_hw *hw); @@ -313,7 +409,6 @@ int32_t e1000_led_off(struct e1000_hw *hw); /* Adaptive IFS Functions */ /* Everything else */ -uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw); void e1000_clear_hw_cntrs(struct e1000_hw *hw); void e1000_reset_adaptive(struct e1000_hw *hw); void e1000_update_adaptive(struct e1000_hw *hw); @@ -330,6 +425,19 @@ void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value); void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up); int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); +int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active); +void e1000_set_pci_express_master_disable(struct e1000_hw *hw); +void e1000_enable_pciex_master(struct e1000_hw *hw); +int32_t e1000_disable_pciex_master(struct e1000_hw *hw); +int32_t e1000_get_auto_rd_done(struct e1000_hw *hw); +int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw); +int32_t e1000_get_software_semaphore(struct e1000_hw *hw); +void e1000_release_software_semaphore(struct e1000_hw *hw); +int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); +int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw); +void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw); +int32_t e1000_commit_shadow_ram(struct e1000_hw *hw); +uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw); #define E1000_READ_REG_IO(a, reg) \ e1000_read_reg_io((a), E1000_##reg) @@ -369,6 +477,10 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82546GB_PCIE 0x108A #define E1000_DEV_ID_82547EI 0x1019 +#define E1000_DEV_ID_82573E 0x108B +#define E1000_DEV_ID_82573E_IAMT 0x108C + +#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -381,6 +493,7 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 #define E1000_REVISION_2 2 +#define E1000_REVISION_3 3 #define SPEED_10 10 #define SPEED_100 100 @@ -437,6 +550,7 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); E1000_IMS_RXSEQ | \ E1000_IMS_LSC) + /* Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for @@ -457,14 +571,74 @@ struct e1000_rx_desc { uint16_t special; }; +/* Receive Descriptor - Extended */ +union e1000_rx_desc_extended { + struct { + uint64_t buffer_addr; + uint64_t reserved; + } read; + struct { + struct { + uint32_t mrq; /* Multiple Rx Queues */ + union { + uint32_t rss; /* RSS Hash */ + struct { + uint16_t ip_id; /* IP id */ + uint16_t csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { + uint32_t status_error; /* ext status/error */ + uint16_t length; + uint16_t vlan; /* VLAN tag */ + } upper; + } wb; /* writeback */ +}; + +#define MAX_PS_BUFFERS 4 +/* Receive Descriptor - Packet Split */ +union e1000_rx_desc_packet_split { + struct { + /* one buffer for protocol header(s), three data buffers */ + uint64_t buffer_addr[MAX_PS_BUFFERS]; + } read; + struct { + struct { + uint32_t mrq; /* Multiple Rx Queues */ + union { + uint32_t rss; /* RSS Hash */ + struct { + uint16_t ip_id; /* IP id */ + uint16_t csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { + uint32_t status_error; /* ext status/error */ + uint16_t length0; /* length of buffer 0 */ + uint16_t vlan; /* VLAN tag */ + } middle; + struct { + uint16_t header_status; + uint16_t length[3]; /* length of buffers 1-3 */ + } upper; + uint64_t reserved; + } wb; /* writeback */ +}; + /* Receive Decriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ #define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ #define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ #define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ +#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ +#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ +#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ +#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ @@ -474,9 +648,20 @@ struct e1000_rx_desc { #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ -#define E1000_RXD_SPC_PRI_SHIFT 0x000D /* Priority is in upper 3 of 16 */ +#define E1000_RXD_SPC_PRI_SHIFT 13 #define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ -#define E1000_RXD_SPC_CFI_SHIFT 0x000C /* CFI is bit 12 */ +#define E1000_RXD_SPC_CFI_SHIFT 12 + +#define E1000_RXDEXT_STATERR_CE 0x01000000 +#define E1000_RXDEXT_STATERR_SE 0x02000000 +#define E1000_RXDEXT_STATERR_SEQ 0x04000000 +#define E1000_RXDEXT_STATERR_CXE 0x10000000 +#define E1000_RXDEXT_STATERR_TCPE 0x20000000 +#define E1000_RXDEXT_STATERR_IPE 0x40000000 +#define E1000_RXDEXT_STATERR_RXE 0x80000000 + +#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 +#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF /* mask to determine if packets should be dropped due to frame errors */ #define E1000_RXD_ERR_FRAME_ERR_MASK ( \ @@ -486,6 +671,15 @@ struct e1000_rx_desc { E1000_RXD_ERR_CXE | \ E1000_RXD_ERR_RXE) + +/* Same mask, but for extended and packet split descriptors */ +#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ + E1000_RXDEXT_STATERR_CE | \ + E1000_RXDEXT_STATERR_SE | \ + E1000_RXDEXT_STATERR_SEQ | \ + E1000_RXDEXT_STATERR_CXE | \ + E1000_RXDEXT_STATERR_RXE) + /* Transmit Descriptor */ struct e1000_tx_desc { uint64_t buffer_addr; /* Address of the descriptor's data buffer */ @@ -667,6 +861,7 @@ struct e1000_ffvt_entry { #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ +#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ #define E1000_RCTL 0x00100 /* RX Control - RW */ #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ @@ -676,9 +871,23 @@ struct e1000_ffvt_entry { #define E1000_TBT 0x00448 /* TX Burst Timer - RW */ #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ #define E1000_LEDCTL 0x00E00 /* LED Control - RW */ +#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ +#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ +#define E1000_PBS 0x01008 /* Packet Buffer Size */ +#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ +#define E1000_FLASH_UPDATES 1000 +#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ +#define E1000_FLASHT 0x01028 /* FLASH Timer Register */ +#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ +#define E1000_FLSWCTL 0x01030 /* FLASH control register */ +#define E1000_FLSWDATA 0x01034 /* FLASH data register */ +#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ +#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ +#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ +#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ #define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ #define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ #define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ @@ -688,6 +897,7 @@ struct e1000_ffvt_entry { #define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */ #define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ #define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ +#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ #define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ #define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ @@ -703,6 +913,14 @@ struct e1000_ffvt_entry { #define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ #define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ #define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ +#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ +#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ +#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ +#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ +#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ +#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ +#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ +#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ #define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ #define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ @@ -761,7 +979,17 @@ struct e1000_ffvt_entry { #define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */ #define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */ #define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */ +#define E1000_IAC 0x4100 /* Interrupt Assertion Count */ +#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */ +#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */ +#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */ +#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */ +#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */ +#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */ +#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */ +#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */ #define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */ +#define E1000_RFCTL 0x05008 /* Receive Filter Control*/ #define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ #define E1000_RA 0x05400 /* Receive Address - RW Array */ #define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ @@ -779,6 +1007,16 @@ struct e1000_ffvt_entry { #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ #define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ +#define E1000_GCR 0x05B00 /* PCI-Ex Control */ +#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ +#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ +#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ +#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ +#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ +#define E1000_SWSM 0x05B50 /* SW Semaphore */ +#define E1000_FWSM 0x05B54 /* FW Semaphore */ +#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ +#define E1000_HICR 0x08F00 /* Host Inteface Control */ /* Register Set (82542) * * Some of the 82542 registers are located at different offsets than they are @@ -829,6 +1067,18 @@ struct e1000_ffvt_entry { #define E1000_82542_VFTA 0x00600 #define E1000_82542_LEDCTL E1000_LEDCTL #define E1000_82542_PBA E1000_PBA +#define E1000_82542_PBS E1000_PBS +#define E1000_82542_EEMNGCTL E1000_EEMNGCTL +#define E1000_82542_EEARBC E1000_EEARBC +#define E1000_82542_FLASHT E1000_FLASHT +#define E1000_82542_EEWR E1000_EEWR +#define E1000_82542_FLSWCTL E1000_FLSWCTL +#define E1000_82542_FLSWDATA E1000_FLSWDATA +#define E1000_82542_FLSWCNT E1000_FLSWCNT +#define E1000_82542_FLOP E1000_FLOP +#define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL +#define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE +#define E1000_82542_ERT E1000_ERT #define E1000_82542_RXDCTL E1000_RXDCTL #define E1000_82542_RADV E1000_RADV #define E1000_82542_RSRPD E1000_RSRPD @@ -913,6 +1163,38 @@ struct e1000_ffvt_entry { #define E1000_82542_FFMT E1000_FFMT #define E1000_82542_FFVT E1000_FFVT #define E1000_82542_HOST_IF E1000_HOST_IF +#define E1000_82542_IAM E1000_IAM +#define E1000_82542_EEMNGCTL E1000_EEMNGCTL +#define E1000_82542_PSRCTL E1000_PSRCTL +#define E1000_82542_RAID E1000_RAID +#define E1000_82542_TARC0 E1000_TARC0 +#define E1000_82542_TDBAL1 E1000_TDBAL1 +#define E1000_82542_TDBAH1 E1000_TDBAH1 +#define E1000_82542_TDLEN1 E1000_TDLEN1 +#define E1000_82542_TDH1 E1000_TDH1 +#define E1000_82542_TDT1 E1000_TDT1 +#define E1000_82542_TXDCTL1 E1000_TXDCTL1 +#define E1000_82542_TARC1 E1000_TARC1 +#define E1000_82542_RFCTL E1000_RFCTL +#define E1000_82542_GCR E1000_GCR +#define E1000_82542_GSCL_1 E1000_GSCL_1 +#define E1000_82542_GSCL_2 E1000_GSCL_2 +#define E1000_82542_GSCL_3 E1000_GSCL_3 +#define E1000_82542_GSCL_4 E1000_GSCL_4 +#define E1000_82542_FACTPS E1000_FACTPS +#define E1000_82542_SWSM E1000_SWSM +#define E1000_82542_FWSM E1000_FWSM +#define E1000_82542_FFLT_DBG E1000_FFLT_DBG +#define E1000_82542_IAC E1000_IAC +#define E1000_82542_ICRXPTC E1000_ICRXPTC +#define E1000_82542_ICRXATC E1000_ICRXATC +#define E1000_82542_ICTXPTC E1000_ICTXPTC +#define E1000_82542_ICTXATC E1000_ICTXATC +#define E1000_82542_ICTXQEC E1000_ICTXQEC +#define E1000_82542_ICTXQMTC E1000_ICTXQMTC +#define E1000_82542_ICRXDMTC E1000_ICRXDMTC +#define E1000_82542_ICRXOC E1000_ICRXOC +#define E1000_82542_HICR E1000_HICR /* Statistics counters collected by the MAC */ struct e1000_hw_stats { @@ -974,11 +1256,21 @@ struct e1000_hw_stats { uint64_t bptc; uint64_t tsctc; uint64_t tsctfc; + uint64_t iac; + uint64_t icrxptc; + uint64_t icrxatc; + uint64_t ictxptc; + uint64_t ictxatc; + uint64_t ictxqec; + uint64_t ictxqmtc; + uint64_t icrxdmtc; + uint64_t icrxoc; }; /* Structure containing variables used by the shared code (e1000_hw.c) */ struct e1000_hw { - uint8_t __iomem *hw_addr; + uint8_t *hw_addr; + uint8_t *flash_address; e1000_mac_type mac_type; e1000_phy_type phy_type; uint32_t phy_init_script; @@ -993,6 +1285,7 @@ struct e1000_hw { e1000_ms_type original_master_slave; e1000_ffe_config ffe_config_state; uint32_t asf_firmware_present; + uint32_t eeprom_semaphore_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; @@ -1009,6 +1302,8 @@ struct e1000_hw { uint32_t ledctl_default; uint32_t ledctl_mode1; uint32_t ledctl_mode2; + boolean_t tx_pkt_filtering; + struct e1000_host_mng_dhcp_cookie mng_cookie; uint16_t phy_spd_default; uint16_t autoneg_advertised; uint16_t pci_cmd_word; @@ -1047,16 +1342,24 @@ struct e1000_hw { boolean_t adaptive_ifs; boolean_t ifs_params_forced; boolean_t in_ifs_mode; + boolean_t mng_reg_access_disabled; }; #define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ #define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ +#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */ +#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ +#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */ +#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ +#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */ +#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */ /* Register Bit Masks */ /* Device Control */ #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ #define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ #define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ +#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ #define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ #define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ #define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ @@ -1070,6 +1373,7 @@ struct e1000_hw { #define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ #define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ +#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ @@ -1089,6 +1393,7 @@ struct e1000_hw { #define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ #define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ #define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ +#define E1000_STATUS_FUNC_SHIFT 2 #define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ #define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ #define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ @@ -1098,6 +1403,8 @@ struct e1000_hw { #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ +#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ +#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ #define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ #define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ @@ -1128,6 +1435,18 @@ struct e1000_hw { #ifndef E1000_EEPROM_GRANT_ATTEMPTS #define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ #endif +#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */ +#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */ +#define E1000_EECD_SIZE_EX_SHIFT 11 +#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */ +#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ +#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ +#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ +#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ +#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ +#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ +#define E1000_STM_OPCODE 0xDB00 +#define E1000_HICR_FW_RESET 0xC0 /* EEPROM Read */ #define E1000_EERD_START 0x00000001 /* Start Read */ @@ -1171,6 +1490,8 @@ struct e1000_hw { #define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 #define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 #define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 +#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ +#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ /* MDI Control */ #define E1000_MDIC_DATA_MASK 0x0000FFFF @@ -1187,14 +1508,17 @@ struct e1000_hw { /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_BLINK_RATE 0x0000020 #define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_LED0_BLINK 0x00000080 #define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 #define E1000_LEDCTL_LED1_MODE_SHIFT 8 +#define E1000_LEDCTL_LED1_BLINK_RATE 0x0002000 #define E1000_LEDCTL_LED1_IVRT 0x00004000 #define E1000_LEDCTL_LED1_BLINK 0x00008000 #define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 #define E1000_LEDCTL_LED2_MODE_SHIFT 16 +#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000 #define E1000_LEDCTL_LED2_IVRT 0x00400000 #define E1000_LEDCTL_LED2_BLINK 0x00800000 #define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 @@ -1238,6 +1562,10 @@ struct e1000_hw { #define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ #define E1000_ICR_TXD_LOW 0x00008000 #define E1000_ICR_SRPD 0x00010000 +#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ +#define E1000_ICR_MNG 0x00040000 /* Manageability event */ +#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ +#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ /* Interrupt Cause Set */ #define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1255,6 +1583,9 @@ struct e1000_hw { #define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ #define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW #define E1000_ICS_SRPD E1000_ICR_SRPD +#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1272,6 +1603,9 @@ struct e1000_hw { #define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ #define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW #define E1000_IMS_SRPD E1000_ICR_SRPD +#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ /* Interrupt Mask Clear */ #define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ @@ -1289,6 +1623,9 @@ struct e1000_hw { #define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ #define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW #define E1000_IMC_SRPD E1000_ICR_SRPD +#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */ +#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */ +#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */ /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ @@ -1301,6 +1638,8 @@ struct e1000_hw { #define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ #define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ +#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ #define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ #define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ @@ -1327,6 +1666,34 @@ struct e1000_hw { #define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ +#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */ +#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */ + +/* Use byte values for the following shift parameters + * Usage: + * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & + * E1000_PSRCTL_BSIZE0_MASK) | + * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & + * E1000_PSRCTL_BSIZE1_MASK) | + * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & + * E1000_PSRCTL_BSIZE2_MASK) | + * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; + * E1000_PSRCTL_BSIZE3_MASK)) + * where value0 = [128..16256], default=256 + * value1 = [1024..64512], default=4096 + * value2 = [0..64512], default=4096 + * value3 = [0..64512], default=0 + */ + +#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F +#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 +#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 +#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 + +#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ +#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ +#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ +#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ @@ -1341,6 +1708,23 @@ struct e1000_hw { #define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ +/* Header split receive */ +#define E1000_RFCTL_ISCSI_DIS 0x00000001 +#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E +#define E1000_RFCTL_ISCSI_DWC_SHIFT 1 +#define E1000_RFCTL_NFSW_DIS 0x00000040 +#define E1000_RFCTL_NFSR_DIS 0x00000080 +#define E1000_RFCTL_NFS_VER_MASK 0x00000300 +#define E1000_RFCTL_NFS_VER_SHIFT 8 +#define E1000_RFCTL_IPV6_DIS 0x00000400 +#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800 +#define E1000_RFCTL_ACK_DIS 0x00001000 +#define E1000_RFCTL_ACKD_DIS 0x00002000 +#define E1000_RFCTL_IPFRSP_DIS 0x00004000 +#define E1000_RFCTL_EXTEN 0x00008000 +#define E1000_RFCTL_IPV6_EX_DIS 0x00010000 +#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 + /* Receive Descriptor Control */ #define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */ #define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ @@ -1354,6 +1738,8 @@ struct e1000_hw { #define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ #define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ +#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc. + still to be processed. */ /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ @@ -1387,12 +1773,16 @@ struct e1000_hw { #define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ #define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ +#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ /* Receive Checksum Control */ #define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ #define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ #define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ +#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ +#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ + /* Definitions for power management and wakeup registers */ /* Wake Up Control */ @@ -1411,6 +1801,7 @@ struct e1000_hw { #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ +#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ #define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ #define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ @@ -1446,13 +1837,19 @@ struct e1000_hw { #define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ #define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery * Filtering */ +#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */ #define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ +#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address * filtering */ #define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host * memory */ +#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address + * filtering */ +#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */ +#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ #define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ #define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ #define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ @@ -1463,11 +1860,97 @@ struct e1000_hw { #define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ #define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ +/* SW Semaphore Register */ +#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ +#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ +#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ +#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ + +/* FW Semaphore Register */ +#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */ +#define E1000_FWSM_MODE_SHIFT 1 +#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */ + +/* FFLT Debug Register */ +#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */ + +typedef enum { + e1000_mng_mode_none = 0, + e1000_mng_mode_asf, + e1000_mng_mode_pt, + e1000_mng_mode_ipmi, + e1000_mng_mode_host_interface_only +} e1000_mng_mode; + +/* Host Inteface Control Register */ +#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */ +#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done + * to put command in RAM */ +#define E1000_HICR_SV 0x00000004 /* Status Validity */ +#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */ + +/* Host Interface Command Interface - Address range 0x8800-0x8EFF */ +#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */ +#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */ +#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */ +#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */ + +struct e1000_host_command_header { + uint8_t command_id; + uint8_t command_length; + uint8_t command_options; /* I/F bits for command, status for return */ + uint8_t checksum; +}; +struct e1000_host_command_info { + struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ + uint8_t command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */ +}; + +/* Host SMB register #0 */ +#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */ +#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */ +#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */ +#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */ + +/* Host SMB register #1 */ +#define E1000_HSMC1R_CLKIN E1000_HSMC0R_CLKIN +#define E1000_HSMC1R_DATAIN E1000_HSMC0R_DATAIN +#define E1000_HSMC1R_DATAOUT E1000_HSMC0R_DATAOUT +#define E1000_HSMC1R_CLKOUT E1000_HSMC0R_CLKOUT + +/* FW Status Register */ +#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */ + /* Wake Up Packet Length */ #define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ #define E1000_MDALIGN 4096 +#define E1000_GCR_BEM32 0x00400000 +/* Function Active and Power State to MNG */ +#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003 +#define E1000_FACTPS_LAN0_VALID 0x00000004 +#define E1000_FACTPS_FUNC0_AUX_EN 0x00000008 +#define E1000_FACTPS_FUNC1_POWER_STATE_MASK 0x000000C0 +#define E1000_FACTPS_FUNC1_POWER_STATE_SHIFT 6 +#define E1000_FACTPS_LAN1_VALID 0x00000100 +#define E1000_FACTPS_FUNC1_AUX_EN 0x00000200 +#define E1000_FACTPS_FUNC2_POWER_STATE_MASK 0x00003000 +#define E1000_FACTPS_FUNC2_POWER_STATE_SHIFT 12 +#define E1000_FACTPS_IDE_ENABLE 0x00004000 +#define E1000_FACTPS_FUNC2_AUX_EN 0x00008000 +#define E1000_FACTPS_FUNC3_POWER_STATE_MASK 0x000C0000 +#define E1000_FACTPS_FUNC3_POWER_STATE_SHIFT 18 +#define E1000_FACTPS_SP_ENABLE 0x00100000 +#define E1000_FACTPS_FUNC3_AUX_EN 0x00200000 +#define E1000_FACTPS_FUNC4_POWER_STATE_MASK 0x03000000 +#define E1000_FACTPS_FUNC4_POWER_STATE_SHIFT 24 +#define E1000_FACTPS_IPMI_ENABLE 0x04000000 +#define E1000_FACTPS_FUNC4_AUX_EN 0x08000000 +#define E1000_FACTPS_MNGCG 0x20000000 +#define E1000_FACTPS_LAN_FUNC_SEL 0x40000000 +#define E1000_FACTPS_PM_STATE_CHANGED 0x80000000 + /* EEPROM Commands - Microwire */ #define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ #define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ @@ -1477,22 +1960,20 @@ struct e1000_hw { /* EEPROM Commands - SPI */ #define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ -#define EEPROM_READ_OPCODE_SPI 0x3 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_SPI 0x2 /* EEPROM write opcode */ -#define EEPROM_A8_OPCODE_SPI 0x8 /* opcode bit-3 = address bit-8 */ -#define EEPROM_WREN_OPCODE_SPI 0x6 /* EEPROM set Write Enable latch */ -#define EEPROM_WRDI_OPCODE_SPI 0x4 /* EEPROM reset Write Enable latch */ -#define EEPROM_RDSR_OPCODE_SPI 0x5 /* EEPROM read Status register */ -#define EEPROM_WRSR_OPCODE_SPI 0x1 /* EEPROM write Status register */ +#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */ +#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ +#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ +#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */ +#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */ +#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */ +#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */ +#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */ +#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */ +#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ /* EEPROM Size definitions */ -#define EEPROM_SIZE_16KB 0x1800 -#define EEPROM_SIZE_8KB 0x1400 -#define EEPROM_SIZE_4KB 0x1000 -#define EEPROM_SIZE_2KB 0x0C00 -#define EEPROM_SIZE_1KB 0x0800 -#define EEPROM_SIZE_512B 0x0400 -#define EEPROM_SIZE_128B 0x0000 +#define EEPROM_WORD_SIZE_SHIFT 6 +#define EEPROM_SIZE_SHIFT 10 #define EEPROM_SIZE_MASK 0x1C00 /* EEPROM Word Offsets */ @@ -1606,7 +2087,22 @@ struct e1000_hw { #define IFS_MIN 40 #define IFS_RATIO 4 +/* Extended Configuration Control and Size */ +#define E1000_EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001 +#define E1000_EXTCNF_CTRL_PHY_WRITE_ENABLE 0x00000002 +#define E1000_EXTCNF_CTRL_D_UD_ENABLE 0x00000004 +#define E1000_EXTCNF_CTRL_D_UD_LATENCY 0x00000008 +#define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010 +#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 +#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040 +#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x1FFF0000 + +#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF +#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 +#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 + /* PBA constants */ +#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ #define E1000_PBA_22K 0x0016 #define E1000_PBA_24K 0x0018 @@ -1663,6 +2159,13 @@ struct e1000_hw { /* Number of milliseconds we wait for auto-negotiation to complete */ #define LINK_UP_TIMEOUT 500 +/* Number of 100 microseconds we wait for PCI Express master disable */ +#define MASTER_DISABLE_TIMEOUT 800 +/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */ +#define AUTO_READ_DONE_TIMEOUT 10 +/* Number of milliseconds we wait for PHY configuration done after MAC reset */ +#define PHY_CFG_TIMEOUT 40 + #define E1000_TX_BUFFER_SIZE ((uint32_t)1514) /* The carrier extension symbol, as received by the NIC. */ @@ -1763,6 +2266,7 @@ struct e1000_hw { #define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */ #define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */ #define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */ +#define IGP02E1000_PHY_POWER_MGMT 0x19 #define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */ /* IGP01E1000 AGC Registers - stores the cable length values*/ @@ -1771,12 +2275,20 @@ struct e1000_hw { #define IGP01E1000_PHY_AGC_C 0x1472 #define IGP01E1000_PHY_AGC_D 0x1872 +/* IGP02E1000 AGC Registers for cable length values */ +#define IGP02E1000_PHY_AGC_A 0x11B1 +#define IGP02E1000_PHY_AGC_B 0x12B1 +#define IGP02E1000_PHY_AGC_C 0x14B1 +#define IGP02E1000_PHY_AGC_D 0x18B1 + /* IGP01E1000 DSP Reset Register */ #define IGP01E1000_PHY_DSP_RESET 0x1F33 #define IGP01E1000_PHY_DSP_SET 0x1F71 #define IGP01E1000_PHY_DSP_FFE 0x1F35 #define IGP01E1000_PHY_CHANNEL_NUM 4 +#define IGP02E1000_PHY_CHANNEL_NUM 4 + #define IGP01E1000_PHY_AGC_PARAM_A 0x1171 #define IGP01E1000_PHY_AGC_PARAM_B 0x1271 #define IGP01E1000_PHY_AGC_PARAM_C 0x1471 @@ -2060,20 +2572,30 @@ struct e1000_hw { #define IGP01E1000_MSE_CHANNEL_B 0x0F00 #define IGP01E1000_MSE_CHANNEL_A 0xF000 +#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ +#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */ +#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */ + /* IGP01E1000 DSP reset macros */ #define DSP_RESET_ENABLE 0x0 #define DSP_RESET_DISABLE 0x2 #define E1000_MAX_DSP_RESETS 10 -/* IGP01E1000 AGC Registers */ +/* IGP01E1000 & IGP02E1000 AGC Registers */ #define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ +#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */ + +/* IGP02E1000 AGC Register Length 9-bit mask */ +#define IGP02E1000_AGC_LENGTH_MASK 0x7F /* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */ #define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128 +#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128 -/* The precision of the length is +/- 10 meters */ +/* The precision error of the cable length is +/- 10 meters */ #define IGP01E1000_AGC_RANGE 10 +#define IGP02E1000_AGC_RANGE 10 /* IGP01E1000 PCS Initialization register */ /* bits 3:6 in the PCS registers stores the channels polarity */ @@ -2113,6 +2635,8 @@ struct e1000_hw { #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID #define M88E1011_I_REV_4 0x04 +#define M88E1111_I_PHY_ID 0x01410CC0 +#define L1LXT971A_PHY_ID 0x001378E0 /* Miscellaneous PHY bit definitions. */ #define PHY_PREAMBLE 0xFFFFFFFF diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4cdf371..5e6e1f7 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -155,10 +155,14 @@ static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); static int e1000_clean(struct net_device *netdev, int *budget); static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done, int work_to_do); +static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, + int *work_done, int work_to_do); #else static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); +static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter); #endif static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); +static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); @@ -286,7 +290,29 @@ e1000_irq_enable(struct e1000_adapter *adapter) E1000_WRITE_FLUSH(&adapter->hw); } } - +void +e1000_update_mng_vlan(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + uint16_t vid = adapter->hw.mng_cookie.vlan_id; + uint16_t old_vid = adapter->mng_vlan_id; + if(adapter->vlgrp) { + if(!adapter->vlgrp->vlan_devices[vid]) { + if(adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { + e1000_vlan_rx_add_vid(netdev, vid); + adapter->mng_vlan_id = vid; + } else + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + + if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && + (vid != old_vid) && + !adapter->vlgrp->vlan_devices[old_vid]) + e1000_vlan_rx_kill_vid(netdev, old_vid); + } + } +} + int e1000_up(struct e1000_adapter *adapter) { @@ -310,7 +336,7 @@ e1000_up(struct e1000_adapter *adapter) e1000_configure_tx(adapter); e1000_setup_rctl(adapter); e1000_configure_rx(adapter); - e1000_alloc_rx_buffers(adapter); + adapter->alloc_rx_buf(adapter); #ifdef CONFIG_PCI_MSI if(adapter->hw.mac_type > e1000_82547_rev_2) { @@ -366,8 +392,12 @@ e1000_down(struct e1000_adapter *adapter) e1000_clean_rx_ring(adapter); /* If WoL is not enabled + * and management mode is not IAMT * Power down the PHY so no link is implied when interface is down */ - if(!adapter->wol && adapter->hw.media_type == e1000_media_type_copper) { + if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper && + !e1000_check_mng_mode(&adapter->hw) && + !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) { uint16_t mii_reg; e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; @@ -379,28 +409,34 @@ e1000_down(struct e1000_adapter *adapter) void e1000_reset(struct e1000_adapter *adapter) { - uint32_t pba; + uint32_t pba, manc; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. */ - if(adapter->hw.mac_type < e1000_82547) { - if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) - pba = E1000_PBA_40K; - else - pba = E1000_PBA_48K; - } else { - if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) - pba = E1000_PBA_22K; - else - pba = E1000_PBA_30K; + switch (adapter->hw.mac_type) { + case e1000_82547: + pba = E1000_PBA_30K; + break; + case e1000_82573: + pba = E1000_PBA_12K; + break; + default: + pba = E1000_PBA_48K; + break; + } + + + + if(adapter->hw.mac_type == e1000_82547) { adapter->tx_fifo_head = 0; adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; adapter->tx_fifo_size = (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; atomic_set(&adapter->tx_fifo_stall, 0); } + E1000_WRITE_REG(&adapter->hw, PBA, pba); /* flow control settings */ @@ -412,17 +448,23 @@ e1000_reset(struct e1000_adapter *adapter) adapter->hw.fc_send_xon = 1; adapter->hw.fc = adapter->hw.original_fc; + /* Allow time for pending master requests to run */ e1000_reset_hw(&adapter->hw); if(adapter->hw.mac_type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, WUC, 0); if(e1000_init_hw(&adapter->hw)) DPRINTK(PROBE, ERR, "Hardware Error\n"); - + e1000_update_mng_vlan(adapter); /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); e1000_reset_adaptive(&adapter->hw); e1000_phy_get_info(&adapter->hw, &adapter->phy_info); + if (adapter->en_mng_pt) { + manc = E1000_READ_REG(&adapter->hw, MANC); + manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); + E1000_WRITE_REG(&adapter->hw, MANC, manc); + } } /** @@ -443,15 +485,13 @@ e1000_probe(struct pci_dev *pdev, { struct net_device *netdev; struct e1000_adapter *adapter; + unsigned long mmio_start, mmio_len; + uint32_t swsm; + static int cards_found = 0; - unsigned long mmio_start; - int mmio_len; - int pci_using_dac; - int i; - int err; + int i, err, pci_using_dac; uint16_t eeprom_data; uint16_t eeprom_apme_mask = E1000_EEPROM_APME; - if((err = pci_enable_device(pdev))) return err; @@ -538,6 +578,9 @@ e1000_probe(struct pci_dev *pdev, if((err = e1000_sw_init(adapter))) goto err_sw_init; + if((err = e1000_check_phy_reset_block(&adapter->hw))) + DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); + if(adapter->hw.mac_type >= e1000_82543) { netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | @@ -550,6 +593,11 @@ e1000_probe(struct pci_dev *pdev, if((adapter->hw.mac_type >= e1000_82544) && (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; + +#ifdef NETIF_F_TSO_IPV6 + if(adapter->hw.mac_type > e1000_82547_rev_2) + netdev->features |= NETIF_F_TSO_IPV6; +#endif #endif if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -557,6 +605,8 @@ e1000_probe(struct pci_dev *pdev, /* hard_start_xmit is safe against parallel locking */ netdev->features |= NETIF_F_LLTX; + adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); + /* before reading the EEPROM, reset the controller to * put the device in a known good starting state */ @@ -646,6 +696,17 @@ e1000_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ e1000_reset(adapter); + /* Let firmware know the driver has taken over */ + switch(adapter->hw.mac_type) { + case e1000_82573: + swsm = E1000_READ_REG(&adapter->hw, SWSM); + E1000_WRITE_REG(&adapter->hw, SWSM, + swsm | E1000_SWSM_DRV_LOAD); + break; + default: + break; + } + strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) goto err_register; @@ -681,7 +742,7 @@ e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t manc; + uint32_t manc, swsm; flush_scheduled_work(); @@ -694,9 +755,21 @@ e1000_remove(struct pci_dev *pdev) } } + switch(adapter->hw.mac_type) { + case e1000_82573: + swsm = E1000_READ_REG(&adapter->hw, SWSM); + E1000_WRITE_REG(&adapter->hw, SWSM, + swsm & ~E1000_SWSM_DRV_LOAD); + break; + + default: + break; + } + unregister_netdev(netdev); - e1000_phy_hw_reset(&adapter->hw); + if(!e1000_check_phy_reset_block(&adapter->hw)) + e1000_phy_hw_reset(&adapter->hw); iounmap(adapter->hw.hw_addr); pci_release_regions(pdev); @@ -734,6 +807,7 @@ e1000_sw_init(struct e1000_adapter *adapter) pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); adapter->rx_buffer_len = E1000_RXBUFFER_2048; + adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; @@ -747,7 +821,10 @@ e1000_sw_init(struct e1000_adapter *adapter) /* initialize eeprom parameters */ - e1000_init_eeprom_params(hw); + if(e1000_init_eeprom_params(hw)) { + E1000_ERR("EEPROM initialization failed\n"); + return -EIO; + } switch(hw->mac_type) { default: @@ -812,6 +889,11 @@ e1000_open(struct net_device *netdev) if((err = e1000_up(adapter))) goto err_up; + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + if((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { + e1000_update_mng_vlan(adapter); + } return E1000_SUCCESS; @@ -847,14 +929,18 @@ e1000_close(struct net_device *netdev) e1000_free_tx_resources(adapter); e1000_free_rx_resources(adapter); + if((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { + e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + } return 0; } /** * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary * @adapter: address of board private structure - * @begin: address of beginning of memory - * @end: address of end of memory + * @start: address of beginning of memory + * @len: length of memory **/ static inline boolean_t e1000_check_64k_bound(struct e1000_adapter *adapter, @@ -1039,7 +1125,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter) { struct e1000_desc_ring *rxdr = &adapter->rx_ring; struct pci_dev *pdev = adapter->pdev; - int size; + int size, desc_len; size = sizeof(struct e1000_buffer) * rxdr->count; rxdr->buffer_info = vmalloc(size); @@ -1050,9 +1136,35 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter) } memset(rxdr->buffer_info, 0, size); + size = sizeof(struct e1000_ps_page) * rxdr->count; + rxdr->ps_page = kmalloc(size, GFP_KERNEL); + if(!rxdr->ps_page) { + vfree(rxdr->buffer_info); + DPRINTK(PROBE, ERR, + "Unable to allocate memory for the receive descriptor ring\n"); + return -ENOMEM; + } + memset(rxdr->ps_page, 0, size); + + size = sizeof(struct e1000_ps_page_dma) * rxdr->count; + rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL); + if(!rxdr->ps_page_dma) { + vfree(rxdr->buffer_info); + kfree(rxdr->ps_page); + DPRINTK(PROBE, ERR, + "Unable to allocate memory for the receive descriptor ring\n"); + return -ENOMEM; + } + memset(rxdr->ps_page_dma, 0, size); + + if(adapter->hw.mac_type <= e1000_82547_rev_2) + desc_len = sizeof(struct e1000_rx_desc); + else + desc_len = sizeof(union e1000_rx_desc_packet_split); + /* Round up to nearest 4K */ - rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); + rxdr->size = rxdr->count * desc_len; E1000_ROUNDUP(rxdr->size, 4096); rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); @@ -1062,6 +1174,8 @@ setup_rx_desc_die: DPRINTK(PROBE, ERR, "Unble to Allocate Memory for the Recieve descriptor ring\n"); vfree(rxdr->buffer_info); + kfree(rxdr->ps_page); + kfree(rxdr->ps_page_dma); return -ENOMEM; } @@ -1089,6 +1203,8 @@ setup_rx_desc_die: "Unable to Allocate aligned Memory for the" " Receive descriptor ring\n"); vfree(rxdr->buffer_info); + kfree(rxdr->ps_page); + kfree(rxdr->ps_page_dma); return -ENOMEM; } else { /* free old, move on with the new one since its okay */ @@ -1111,7 +1227,8 @@ setup_rx_desc_die: static void e1000_setup_rctl(struct e1000_adapter *adapter) { - uint32_t rctl; + uint32_t rctl, rfctl; + uint32_t psrctl = 0; rctl = E1000_READ_REG(&adapter->hw, RCTL); @@ -1126,24 +1243,69 @@ e1000_setup_rctl(struct e1000_adapter *adapter) else rctl &= ~E1000_RCTL_SBP; + if (adapter->netdev->mtu <= ETH_DATA_LEN) + rctl &= ~E1000_RCTL_LPE; + else + rctl |= E1000_RCTL_LPE; + /* Setup buffer sizes */ - rctl &= ~(E1000_RCTL_SZ_4096); - rctl |= (E1000_RCTL_BSEX | E1000_RCTL_LPE); - switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE); - break; - case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096; - break; - case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192; - break; - case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384; - break; + if(adapter->hw.mac_type == e1000_82573) { + /* We can now specify buffers in 1K increments. + * BSIZE and BSEX are ignored in this case. */ + rctl |= adapter->rx_buffer_len << 0x11; + } else { + rctl &= ~E1000_RCTL_SZ_4096; + rctl |= E1000_RCTL_BSEX; + switch (adapter->rx_buffer_len) { + case E1000_RXBUFFER_2048: + default: + rctl |= E1000_RCTL_SZ_2048; + rctl &= ~E1000_RCTL_BSEX; + break; + case E1000_RXBUFFER_4096: + rctl |= E1000_RCTL_SZ_4096; + break; + case E1000_RXBUFFER_8192: + rctl |= E1000_RCTL_SZ_8192; + break; + case E1000_RXBUFFER_16384: + rctl |= E1000_RCTL_SZ_16384; + break; + } + } + +#ifdef CONFIG_E1000_PACKET_SPLIT + /* 82571 and greater support packet-split where the protocol + * header is placed in skb->data and the packet data is + * placed in pages hanging off of skb_shinfo(skb)->nr_frags. + * In the case of a non-split, skb->data is linearly filled, + * followed by the page buffers. Therefore, skb->data is + * sized to hold the largest protocol header. + */ + adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2) + && (adapter->netdev->mtu + < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0)); +#endif + if(adapter->rx_ps) { + /* Configure extra packet-split registers */ + rfctl = E1000_READ_REG(&adapter->hw, RFCTL); + rfctl |= E1000_RFCTL_EXTEN; + /* disable IPv6 packet split support */ + rfctl |= E1000_RFCTL_IPV6_DIS; + E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl); + + rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC; + + psrctl |= adapter->rx_ps_bsize0 >> + E1000_PSRCTL_BSIZE0_SHIFT; + psrctl |= PAGE_SIZE >> + E1000_PSRCTL_BSIZE1_SHIFT; + psrctl |= PAGE_SIZE << + E1000_PSRCTL_BSIZE2_SHIFT; + psrctl |= PAGE_SIZE << + E1000_PSRCTL_BSIZE3_SHIFT; + + E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); } E1000_WRITE_REG(&adapter->hw, RCTL, rctl); @@ -1160,9 +1322,18 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) { uint64_t rdba = adapter->rx_ring.dma; - uint32_t rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc); - uint32_t rctl; - uint32_t rxcsum; + uint32_t rdlen, rctl, rxcsum; + + if(adapter->rx_ps) { + rdlen = adapter->rx_ring.count * + sizeof(union e1000_rx_desc_packet_split); + adapter->clean_rx = e1000_clean_rx_irq_ps; + adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; + } else { + rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc); + adapter->clean_rx = e1000_clean_rx_irq; + adapter->alloc_rx_buf = e1000_alloc_rx_buffers; + } /* disable receives while setting up the descriptors */ rctl = E1000_READ_REG(&adapter->hw, RCTL); @@ -1189,13 +1360,27 @@ e1000_configure_rx(struct e1000_adapter *adapter) E1000_WRITE_REG(&adapter->hw, RDT, 0); /* Enable 82543 Receive Checksum Offload for TCP and UDP */ - if((adapter->hw.mac_type >= e1000_82543) && - (adapter->rx_csum == TRUE)) { + if(adapter->hw.mac_type >= e1000_82543) { rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM); - rxcsum |= E1000_RXCSUM_TUOFL; + if(adapter->rx_csum == TRUE) { + rxcsum |= E1000_RXCSUM_TUOFL; + + /* Enable 82573 IPv4 payload checksum for UDP fragments + * Must be used in conjunction with packet-split. */ + if((adapter->hw.mac_type > e1000_82547_rev_2) && + (adapter->rx_ps)) { + rxcsum |= E1000_RXCSUM_IPPCSE; + } + } else { + rxcsum &= ~E1000_RXCSUM_TUOFL; + /* don't need to clear IPPCSE as it defaults to 0 */ + } E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum); } + if (adapter->hw.mac_type == e1000_82573) + E1000_WRITE_REG(&adapter->hw, ERT, 0x0100); + /* Enable Receives */ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } @@ -1298,6 +1483,10 @@ e1000_free_rx_resources(struct e1000_adapter *adapter) vfree(rx_ring->buffer_info); rx_ring->buffer_info = NULL; + kfree(rx_ring->ps_page); + rx_ring->ps_page = NULL; + kfree(rx_ring->ps_page_dma); + rx_ring->ps_page_dma = NULL; pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); @@ -1314,16 +1503,19 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter) { struct e1000_desc_ring *rx_ring = &adapter->rx_ring; struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct e1000_ps_page_dma *ps_page_dma; struct pci_dev *pdev = adapter->pdev; unsigned long size; - unsigned int i; + unsigned int i, j; /* Free all the Rx ring sk_buffs */ for(i = 0; i < rx_ring->count; i++) { buffer_info = &rx_ring->buffer_info[i]; if(buffer_info->skb) { - + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; pci_unmap_single(pdev, buffer_info->dma, buffer_info->length, @@ -1331,11 +1523,25 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter) dev_kfree_skb(buffer_info->skb); buffer_info->skb = NULL; + + for(j = 0; j < PS_PAGE_BUFFERS; j++) { + if(!ps_page->ps_page[j]) break; + pci_unmap_single(pdev, + ps_page_dma->ps_page_dma[j], + PAGE_SIZE, PCI_DMA_FROMDEVICE); + ps_page_dma->ps_page_dma[j] = 0; + put_page(ps_page->ps_page[j]); + ps_page->ps_page[j] = NULL; + } } } size = sizeof(struct e1000_buffer) * rx_ring->count; memset(rx_ring->buffer_info, 0, size); + size = sizeof(struct e1000_ps_page) * rx_ring->count; + memset(rx_ring->ps_page, 0, size); + size = sizeof(struct e1000_ps_page_dma) * rx_ring->count; + memset(rx_ring->ps_page_dma, 0, size); /* Zero out the descriptor ring */ @@ -1573,6 +1779,11 @@ e1000_watchdog_task(struct e1000_adapter *adapter) uint32_t link; e1000_check_for_link(&adapter->hw); + if (adapter->hw.mac_type == e1000_82573) { + e1000_enable_tx_pkt_filtering(&adapter->hw); + if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) + e1000_update_mng_vlan(adapter); + } if((adapter->hw.media_type == e1000_media_type_internal_serdes) && !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) @@ -1659,6 +1870,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter) #define E1000_TX_FLAGS_CSUM 0x00000001 #define E1000_TX_FLAGS_VLAN 0x00000002 #define E1000_TX_FLAGS_TSO 0x00000004 +#define E1000_TX_FLAGS_IPV4 0x00000008 #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 #define E1000_TX_FLAGS_VLAN_SHIFT 16 @@ -1669,7 +1881,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) struct e1000_context_desc *context_desc; unsigned int i; uint32_t cmd_length = 0; - uint16_t ipcse, tucse, mss; + uint16_t ipcse = 0, tucse, mss; uint8_t ipcss, ipcso, tucss, tucso, hdr_len; int err; @@ -1682,23 +1894,37 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); mss = skb_shinfo(skb)->tso_size; - skb->nh.iph->tot_len = 0; - skb->nh.iph->check = 0; - skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, - skb->nh.iph->daddr, - 0, - IPPROTO_TCP, - 0); + if(skb->protocol == ntohs(ETH_P_IP)) { + skb->nh.iph->tot_len = 0; + skb->nh.iph->check = 0; + skb->h.th->check = + ~csum_tcpudp_magic(skb->nh.iph->saddr, + skb->nh.iph->daddr, + 0, + IPPROTO_TCP, + 0); + cmd_length = E1000_TXD_CMD_IP; + ipcse = skb->h.raw - skb->data - 1; +#ifdef NETIF_F_TSO_IPV6 + } else if(skb->protocol == ntohs(ETH_P_IPV6)) { + skb->nh.ipv6h->payload_len = 0; + skb->h.th->check = + ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, + 0, + IPPROTO_TCP, + 0); + ipcse = 0; +#endif + } ipcss = skb->nh.raw - skb->data; ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data; - ipcse = skb->h.raw - skb->data - 1; tucss = skb->h.raw - skb->data; tucso = (void *)&(skb->h.th->check) - (void *)skb->data; tucse = 0; cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | - (skb->len - (hdr_len))); + E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); i = adapter->tx_ring.next_to_use; context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i); @@ -1866,7 +2092,10 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) if(likely(tx_flags & E1000_TX_FLAGS_TSO)) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | E1000_TXD_CMD_TSE; - txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8; + txd_upper |= E1000_TXD_POPTS_TXSM << 8; + + if(likely(tx_flags & E1000_TX_FLAGS_IPV4)) + txd_upper |= E1000_TXD_POPTS_IXSM << 8; } if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) { @@ -1941,6 +2170,53 @@ no_fifo_stall_required: return 0; } +#define MINIMUM_DHCP_PACKET_SIZE 282 +static inline int +e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) +{ + struct e1000_hw *hw = &adapter->hw; + uint16_t length, offset; + if(vlan_tx_tag_present(skb)) { + if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && + ( adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) + return 0; + } + if(htons(ETH_P_IP) == skb->protocol) { + const struct iphdr *ip = skb->nh.iph; + if(IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = (struct udphdr *)(skb->h.uh); + if(ntohs(udp->dest) == 67) { + offset = (uint8_t *)udp + 8 - skb->data; + length = skb->len - offset; + + return e1000_mng_write_dhcp_info(hw, + (uint8_t *)udp + 8, length); + } + } + } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { + struct ethhdr *eth = (struct ethhdr *) skb->data; + if((htons(ETH_P_IP) == eth->h_proto)) { + const struct iphdr *ip = + (struct iphdr *)((uint8_t *)skb->data+14); + if(IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = + (struct udphdr *)((uint8_t *)ip + + (ip->ihl << 2)); + if(ntohs(udp->dest) == 67) { + offset = (uint8_t *)udp + 8 - skb->data; + length = skb->len - offset; + + return e1000_mng_write_dhcp_info(hw, + (uint8_t *)udp + 8, + length); + } + } + } + } + return 0; +} + #define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) @@ -2008,6 +2284,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) local_irq_restore(flags); return NETDEV_TX_LOCKED; } + if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) ) + e1000_transfer_dhcp_info(adapter, skb); + /* need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ @@ -2044,6 +2323,12 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) else if(likely(e1000_tx_csum(adapter, skb))) tx_flags |= E1000_TX_FLAGS_CSUM; + /* Old method was to assume IPv4 packet by default if TSO was enabled. + * 82573 hardware supports TSO capabilities for IPv6 as well... + * no longer assume, we must. */ + if(likely(skb->protocol == ntohs(ETH_P_IP))) + tx_flags |= E1000_TX_FLAGS_IPV4; + e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss), tx_flags); @@ -2110,7 +2395,6 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) { struct e1000_adapter *adapter = netdev->priv; - int old_mtu = adapter->rx_buffer_len; int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || @@ -2119,29 +2403,45 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } - if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) { - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - - } else if(adapter->hw.mac_type < e1000_82543) { - DPRINTK(PROBE, ERR, "Jumbo Frames not supported on 82542\n"); +#define MAX_STD_JUMBO_FRAME_SIZE 9216 + /* might want this to be bigger enum check... */ + if (adapter->hw.mac_type == e1000_82573 && + max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { + DPRINTK(PROBE, ERR, "Jumbo Frames not supported " + "on 82573\n"); return -EINVAL; + } - } else if(max_frame <= E1000_RXBUFFER_4096) { - adapter->rx_buffer_len = E1000_RXBUFFER_4096; - - } else if(max_frame <= E1000_RXBUFFER_8192) { - adapter->rx_buffer_len = E1000_RXBUFFER_8192; - + if(adapter->hw.mac_type > e1000_82547_rev_2) { + adapter->rx_buffer_len = max_frame; + E1000_ROUNDUP(adapter->rx_buffer_len, 1024); } else { - adapter->rx_buffer_len = E1000_RXBUFFER_16384; + if(unlikely((adapter->hw.mac_type < e1000_82543) && + (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) { + DPRINTK(PROBE, ERR, "Jumbo Frames not supported " + "on 82542\n"); + return -EINVAL; + + } else { + if(max_frame <= E1000_RXBUFFER_2048) { + adapter->rx_buffer_len = E1000_RXBUFFER_2048; + } else if(max_frame <= E1000_RXBUFFER_4096) { + adapter->rx_buffer_len = E1000_RXBUFFER_4096; + } else if(max_frame <= E1000_RXBUFFER_8192) { + adapter->rx_buffer_len = E1000_RXBUFFER_8192; + } else if(max_frame <= E1000_RXBUFFER_16384) { + adapter->rx_buffer_len = E1000_RXBUFFER_16384; + } + } } - if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) { + netdev->mtu = new_mtu; + + if(netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); } - netdev->mtu = new_mtu; adapter->hw.max_frame_size = max_frame; return 0; @@ -2232,6 +2532,17 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); } + if(hw->mac_type > e1000_82547_rev_2) { + adapter->stats.iac += E1000_READ_REG(hw, IAC); + adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); + adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); + adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); + adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); + adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); + adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); + adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); + adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); + } /* Fill out the OS statistics structure */ @@ -2337,7 +2648,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) } for(i = 0; i < E1000_MAX_INTR; i++) - if(unlikely(!e1000_clean_rx_irq(adapter) & + if(unlikely(!adapter->clean_rx(adapter) & !e1000_clean_tx_irq(adapter))) break; @@ -2363,7 +2674,7 @@ e1000_clean(struct net_device *netdev, int *budget) int work_done = 0; tx_cleaned = e1000_clean_tx_irq(adapter); - e1000_clean_rx_irq(adapter, &work_done, work_to_do); + adapter->clean_rx(adapter, &work_done, work_to_do); *budget -= work_done; netdev->quota -= work_done; @@ -2501,41 +2812,57 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) /** * e1000_rx_checksum - Receive Checksum Offload for 82543 - * @adapter: board private structure - * @rx_desc: receive descriptor - * @sk_buff: socket buffer with received data + * @adapter: board private structure + * @status_err: receive descriptor status and error fields + * @csum: receive descriptor csum field + * @sk_buff: socket buffer with received data **/ static inline void e1000_rx_checksum(struct e1000_adapter *adapter, - struct e1000_rx_desc *rx_desc, - struct sk_buff *skb) + uint32_t status_err, uint32_t csum, + struct sk_buff *skb) { + uint16_t status = (uint16_t)status_err; + uint8_t errors = (uint8_t)(status_err >> 24); + skb->ip_summed = CHECKSUM_NONE; + /* 82543 or newer only */ - if(unlikely((adapter->hw.mac_type < e1000_82543) || + if(unlikely(adapter->hw.mac_type < e1000_82543)) return; /* Ignore Checksum bit is set */ - (rx_desc->status & E1000_RXD_STAT_IXSM) || - /* TCP Checksum has not been calculated */ - (!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - /* At this point we know the hardware did the TCP checksum */ - /* now look at the TCP checksum error bit */ - if(rx_desc->errors & E1000_RXD_ERR_TCPE) { + if(unlikely(status & E1000_RXD_STAT_IXSM)) return; + /* TCP/UDP checksum error bit is set */ + if(unlikely(errors & E1000_RXD_ERR_TCPE)) { /* let the stack verify checksum errors */ - skb->ip_summed = CHECKSUM_NONE; adapter->hw_csum_err++; + return; + } + /* TCP/UDP Checksum has not been calculated */ + if(adapter->hw.mac_type <= e1000_82547_rev_2) { + if(!(status & E1000_RXD_STAT_TCPCS)) + return; } else { + if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) + return; + } + /* It must be a TCP or UDP packet with a valid checksum */ + if (likely(status & E1000_RXD_STAT_TCPCS)) { /* TCP checksum is good */ skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; + } else if (adapter->hw.mac_type > e1000_82547_rev_2) { + /* IP fragment with UDP payload */ + /* Hardware complements the payload checksum, so we undo it + * and then put the value in host order for further stack use. + */ + csum = ntohl(csum ^ 0xFFFF); + skb->csum = csum; + skb->ip_summed = CHECKSUM_HW; } + adapter->hw_csum_good++; } /** - * e1000_clean_rx_irq - Send received data up the network stack + * e1000_clean_rx_irq - Send received data up the network stack; legacy * @adapter: board private structure **/ @@ -2608,15 +2935,17 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) skb_put(skb, length - ETHERNET_FCS_SIZE); /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, rx_desc, skb); - + e1000_rx_checksum(adapter, + (uint32_t)(rx_desc->status) | + ((uint32_t)(rx_desc->errors) << 24), + rx_desc->csum, skb); skb->protocol = eth_type_trans(skb, netdev); #ifdef CONFIG_E1000_NAPI if(unlikely(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP))) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->special) & - E1000_RXD_SPC_VLAN_MASK); + le16_to_cpu(rx_desc->special) & + E1000_RXD_SPC_VLAN_MASK); } else { netif_receive_skb(skb); } @@ -2639,16 +2968,142 @@ next_desc: rx_desc = E1000_RX_DESC(*rx_ring, i); } - rx_ring->next_to_clean = i; + adapter->alloc_rx_buf(adapter); + + return cleaned; +} + +/** + * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split + * @adapter: board private structure + **/ + +static boolean_t +#ifdef CONFIG_E1000_NAPI +e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done, + int work_to_do) +#else +e1000_clean_rx_irq_ps(struct e1000_adapter *adapter) +#endif +{ + struct e1000_desc_ring *rx_ring = &adapter->rx_ring; + union e1000_rx_desc_packet_split *rx_desc; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct e1000_ps_page_dma *ps_page_dma; + struct sk_buff *skb; + unsigned int i, j; + uint32_t length, staterr; + boolean_t cleaned = FALSE; + + i = rx_ring->next_to_clean; + rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + staterr = rx_desc->wb.middle.status_error; + + while(staterr & E1000_RXD_STAT_DD) { + buffer_info = &rx_ring->buffer_info[i]; + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; +#ifdef CONFIG_E1000_NAPI + if(unlikely(*work_done >= work_to_do)) + break; + (*work_done)++; +#endif + cleaned = TRUE; + pci_unmap_single(pdev, buffer_info->dma, + buffer_info->length, + PCI_DMA_FROMDEVICE); + + skb = buffer_info->skb; + + if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { + E1000_DBG("%s: Packet Split buffers didn't pick up" + " the full packet\n", netdev->name); + dev_kfree_skb_irq(skb); + goto next_desc; + } - e1000_alloc_rx_buffers(adapter); + if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { + dev_kfree_skb_irq(skb); + goto next_desc; + } + + length = le16_to_cpu(rx_desc->wb.middle.length0); + + if(unlikely(!length)) { + E1000_DBG("%s: Last part of the packet spanning" + " multiple descriptors\n", netdev->name); + dev_kfree_skb_irq(skb); + goto next_desc; + } + + /* Good Receive */ + skb_put(skb, length); + + for(j = 0; j < PS_PAGE_BUFFERS; j++) { + if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) + break; + + pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], + PAGE_SIZE, PCI_DMA_FROMDEVICE); + ps_page_dma->ps_page_dma[j] = 0; + skb_shinfo(skb)->frags[j].page = + ps_page->ps_page[j]; + ps_page->ps_page[j] = NULL; + skb_shinfo(skb)->frags[j].page_offset = 0; + skb_shinfo(skb)->frags[j].size = length; + skb_shinfo(skb)->nr_frags++; + skb->len += length; + skb->data_len += length; + } + + e1000_rx_checksum(adapter, staterr, + rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + skb->protocol = eth_type_trans(skb, netdev); + +#ifdef HAVE_RX_ZERO_COPY + if(likely(rx_desc->wb.upper.header_status & + E1000_RXDPS_HDRSTAT_HDRSP)) + skb_shinfo(skb)->zero_copy = TRUE; +#endif +#ifdef CONFIG_E1000_NAPI + if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, + le16_to_cpu(rx_desc->wb.middle.vlan & + E1000_RXD_SPC_VLAN_MASK)); + } else { + netif_receive_skb(skb); + } +#else /* CONFIG_E1000_NAPI */ + if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { + vlan_hwaccel_rx(skb, adapter->vlgrp, + le16_to_cpu(rx_desc->wb.middle.vlan & + E1000_RXD_SPC_VLAN_MASK)); + } else { + netif_rx(skb); + } +#endif /* CONFIG_E1000_NAPI */ + netdev->last_rx = jiffies; + +next_desc: + rx_desc->wb.middle.status_error &= ~0xFF; + buffer_info->skb = NULL; + if(unlikely(++i == rx_ring->count)) i = 0; + + rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + staterr = rx_desc->wb.middle.status_error; + } + rx_ring->next_to_clean = i; + adapter->alloc_rx_buf(adapter); return cleaned; } /** - * e1000_alloc_rx_buffers - Replace used receive buffers + * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended * @adapter: address of board private structure **/ @@ -2753,6 +3208,95 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) } /** + * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split + * @adapter: address of board private structure + **/ + +static void +e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter) +{ + struct e1000_desc_ring *rx_ring = &adapter->rx_ring; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + union e1000_rx_desc_packet_split *rx_desc; + struct e1000_buffer *buffer_info; + struct e1000_ps_page *ps_page; + struct e1000_ps_page_dma *ps_page_dma; + struct sk_buff *skb; + unsigned int i, j; + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; + + while(!buffer_info->skb) { + rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + + for(j = 0; j < PS_PAGE_BUFFERS; j++) { + if(unlikely(!ps_page->ps_page[j])) { + ps_page->ps_page[j] = + alloc_page(GFP_ATOMIC); + if(unlikely(!ps_page->ps_page[j])) + goto no_buffers; + ps_page_dma->ps_page_dma[j] = + pci_map_page(pdev, + ps_page->ps_page[j], + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + } + /* Refresh the desc even if buffer_addrs didn't + * change because each write-back erases this info. + */ + rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page_dma->ps_page_dma[j]); + } + + skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); + + if(unlikely(!skb)) + break; + + /* Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + + skb->dev = netdev; + + buffer_info->skb = skb; + buffer_info->length = adapter->rx_ps_bsize0; + buffer_info->dma = pci_map_single(pdev, skb->data, + adapter->rx_ps_bsize0, + PCI_DMA_FROMDEVICE); + + rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); + + if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) { + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); + /* Hardware increments by 16 bytes, but packet split + * descriptors are 32 bytes...so we increment tail + * twice as much. + */ + E1000_WRITE_REG(&adapter->hw, RDT, i<<1); + } + + if(unlikely(++i == rx_ring->count)) i = 0; + buffer_info = &rx_ring->buffer_info[i]; + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; + } + +no_buffers: + rx_ring->next_to_use = i; +} + +/** * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. * @adapter: **/ @@ -2986,6 +3530,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) rctl |= E1000_RCTL_VFE; rctl &= ~E1000_RCTL_CFIEN; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + e1000_update_mng_vlan(adapter); } else { /* disable VLAN tag insert/strip */ ctrl = E1000_READ_REG(&adapter->hw, CTRL); @@ -2996,6 +3541,10 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl &= ~E1000_RCTL_VFE; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { + e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + } } e1000_irq_enable(adapter); @@ -3006,7 +3555,10 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) { struct e1000_adapter *adapter = netdev->priv; uint32_t vfta, index; - + if((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) + return; /* add VID to filter table */ index = (vid >> 5) & 0x7F; vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); @@ -3027,6 +3579,10 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) e1000_irq_enable(adapter); + if((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) + return; /* remove VID from filter table */ index = (vid >> 5) & 0x7F; vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); @@ -3102,7 +3658,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t ctrl, ctrl_ext, rctl, manc, status; + uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; uint32_t wufc = adapter->wol; netif_device_detach(netdev); @@ -3144,6 +3700,9 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); } + /* Allow time for pending master requests to run */ + e1000_disable_pciex_master(&adapter->hw); + E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); E1000_WRITE_REG(&adapter->hw, WUFC, wufc); pci_enable_wake(pdev, 3, 1); @@ -3168,6 +3727,16 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) } } + switch(adapter->hw.mac_type) { + case e1000_82573: + swsm = E1000_READ_REG(&adapter->hw, SWSM); + E1000_WRITE_REG(&adapter->hw, SWSM, + swsm & ~E1000_SWSM_DRV_LOAD); + break; + default: + break; + } + pci_disable_device(pdev); state = (state > 0) ? 3 : 0; @@ -3182,7 +3751,7 @@ e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t manc, ret; + uint32_t manc, ret, swsm; pci_set_power_state(pdev, 0); pci_restore_state(pdev); @@ -3207,10 +3776,19 @@ e1000_resume(struct pci_dev *pdev) E1000_WRITE_REG(&adapter->hw, MANC, manc); } + switch(adapter->hw.mac_type) { + case e1000_82573: + swsm = E1000_READ_REG(&adapter->hw, SWSM); + E1000_WRITE_REG(&adapter->hw, SWSM, + swsm | E1000_SWSM_DRV_LOAD); + break; + default: + break; + } + return 0; } #endif - #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 2efa3b1..b1915e8 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -101,6 +101,29 @@ typedef enum { (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ ((offset) << 2))) +#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY +#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY + +#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ + writew((value), ((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ + ((offset) << 1)))) + +#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ + readw((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ + ((offset) << 1))) + +#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ + writeb((value), ((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ + (offset)))) + +#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ + readb((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ + (offset))) + #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS) #endif /* _E1000_OSDEP_H_ */ -- cgit v1.1 From 0e6ef3e02b6f07e37ba1c1abc059f8bee4e0847f Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:44:14 -0700 Subject: [PATCH] e1000:Fix Packet Buffer Allocation logic for 82547_rev_2 Fix Packet Buffer Allocation logic for 82547_rev_2 controller Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e6e1f7..13bde90 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -417,6 +417,7 @@ e1000_reset(struct e1000_adapter *adapter) switch (adapter->hw.mac_type) { case e1000_82547: + case e1000_82547_rev_2: pba = E1000_PBA_30K; break; case e1000_82573: -- cgit v1.1 From 1125ecbc0a89db07bb4eb1ba892a23367c3bdeb5 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:44:25 -0700 Subject: [PATCH] e1000:Adjust flow control watermarks for Jumbo Frames Adjust flow control watermarks for Jumbo Frames Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_main.c net-drivers-2.6/drivers/net/e1000.new/e1000_main.c --- drivers/net/e1000/e1000_main.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 13bde90..24d96c0 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -409,7 +409,10 @@ e1000_down(struct e1000_adapter *adapter) void e1000_reset(struct e1000_adapter *adapter) { + struct net_device *netdev = adapter->netdev; uint32_t pba, manc; + uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF; + uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. @@ -428,6 +431,16 @@ e1000_reset(struct e1000_adapter *adapter) break; } + if((adapter->hw.mac_type != e1000_82573) && + (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) { + pba -= 8; /* allocate more FIFO for Tx */ + /* send an XOFF when there is enough space in the + * Rx FIFO to hold one extra full size Rx packet + */ + fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE + + ETHERNET_FCS_SIZE + 1; + fc_low_water_mark = fc_high_water_mark + 8; + } if(adapter->hw.mac_type == e1000_82547) { @@ -442,9 +455,9 @@ e1000_reset(struct e1000_adapter *adapter) /* flow control settings */ adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) - - E1000_FC_HIGH_DIFF; + fc_high_water_mark; adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) - - E1000_FC_LOW_DIFF; + fc_low_water_mark; adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; adapter->hw.fc_send_xon = 1; adapter->hw.fc = adapter->hw.original_fc; -- cgit v1.1 From 2648345fcbadfae8e7113112ff9402e465a184dc Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:44:46 -0700 Subject: [PATCH] e1000:Driver version,white space,comments,device id Driver version, white space, comments, device id & other Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/e1000/e1000_ethtool.c net-drivers-2.6/drivers/net/e1000.new/e1000_ethtool.c --- drivers/net/e1000/e1000.h | 8 +- drivers/net/e1000/e1000_ethtool.c | 24 +++-- drivers/net/e1000/e1000_hw.c | 3 +- drivers/net/e1000/e1000_hw.h | 2 +- drivers/net/e1000/e1000_main.c | 199 +++++++++++++++++--------------------- drivers/net/e1000/e1000_osdep.h | 2 +- drivers/net/e1000/e1000_param.c | 3 +- 7 files changed, 106 insertions(+), 135 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 19858c2..af1e82c 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 @@ -139,9 +139,9 @@ struct e1000_adapter; /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_82544_APM 0x0004 -#define E1000_EEPROM_APME 0x0400 +#define AUTO_ALL_MODES 0 +#define E1000_EEPROM_82544_APM 0x0400 +#define E1000_EEPROM_APME 0x0400 #ifndef E1000_MASTER_SLAVE /* Switch to override PHY master/slave setting */ diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index fae5854..237247f 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 @@ -69,6 +69,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) }, { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, { "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) }, + { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, { "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) }, { "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) }, { "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) }, @@ -593,7 +594,7 @@ e1000_set_ringparam(struct net_device *netdev, tx_old = adapter->tx_ring; rx_old = adapter->rx_ring; - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + if((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; if(netif_running(adapter->netdev)) @@ -784,8 +785,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) /* Hook up test interrupt handler just for this test */ if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) { shared_int = FALSE; - } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, - netdev->name, netdev)){ + } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, + netdev->name, netdev)){ *data = 1; return -1; } @@ -842,10 +843,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) * test failed. */ adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMC, - (~mask & 0x00007FFF)); - E1000_WRITE_REG(&adapter->hw, ICS, - (~mask & 0x00007FFF)); + E1000_WRITE_REG(&adapter->hw, IMC, ~mask & 0x00007FFF); + E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF); msec_delay(10); if(adapter->test_icr) { @@ -1010,7 +1009,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); struct sk_buff *skb; - if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, + if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL))) { ret_val = 6; goto err_nomem; @@ -1387,13 +1386,12 @@ static int e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) { *data = 0; - if (adapter->hw.media_type == e1000_media_type_internal_serdes) { int i = 0; adapter->hw.serdes_link_down = TRUE; - /* on some blade server designs link establishment */ - /* could take as long as 2-3 minutes. */ + /* On some blade server designs, link establishment + * could take as long as 2-3 minutes */ do { e1000_check_for_link(&adapter->hw); if (adapter->hw.serdes_link_down == FALSE) @@ -1401,7 +1399,7 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data) msec_delay(20); } while (i++ < 3750); - *data = 1; + *data = 1; } else { e1000_check_for_link(&adapter->hw); if(adapter->hw.autoneg) /* if auto_neg is set wait for it */ diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index b7a7ceb..723589b 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 @@ -144,7 +144,6 @@ e1000_phy_init_script(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_init_script"); - if(hw->phy_init_script) { msec_delay(20); diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 1573f60..a0263ee 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 24d96c0..325495b 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 @@ -29,33 +29,9 @@ #include "e1000.h" /* Change Log - * 5.3.12 6/7/04 - * - kcompat NETIF_MSG for older kernels (2.4.9) - * - if_mii support and associated kcompat for older kernels - * - More errlogging support from Jon Mason - * - Fix TSO issues on PPC64 machines -- Jon Mason - * - * 5.7.1 12/16/04 - * - Resurrect 82547EI/GI related fix in e1000_intr to avoid deadlocks. This - * fix was removed as it caused system instability. The suspected cause of - * this is the called to e1000_irq_disable in e1000_intr. Inlined the - * required piece of e1000_irq_disable into e1000_intr - Anton Blanchard - * 5.7.0 12/10/04 - * - include fix to the condition that determines when to quit NAPI - Robert Olsson - * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down - * 5.6.5 11/01/04 - * - Enabling NETIF_F_SG without checksum offload is illegal - - John Mason - * 5.6.3 10/26/04 - * - Remove redundant initialization - Jamal Hadi - * - Reset buffer_info->dma in tx resource cleanup logic - * 5.6.2 10/12/04 - * - Avoid filling tx_ring completely - shemminger@osdl.org - * - Replace schedule_timeout() with msleep()/msleep_interruptible() - - * nacc@us.ibm.com - * - Sparse cleanup - shemminger@osdl.org - * - Fix tx resource cleanup logic - * - LLTX support - ak@suse.de and hadi@cyberus.ca + * 6.0.44+ 2/15/05 + * o applied Anton's patch to resolve tx hang in hardware + * o Applied Andrew Mortons patch - e1000 stops working after resume */ char e1000_driver_name[] = "e1000"; @@ -65,7 +41,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "5.7.6-k2"DRIVERNAPI +#define DRV_VERSION "6.0.54-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; @@ -96,6 +72,7 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x1017), INTEL_E1000_ETHERNET_DEVICE(0x1018), INTEL_E1000_ETHERNET_DEVICE(0x1019), + INTEL_E1000_ETHERNET_DEVICE(0x101A), INTEL_E1000_ETHERNET_DEVICE(0x101D), INTEL_E1000_ETHERNET_DEVICE(0x101E), INTEL_E1000_ETHERNET_DEVICE(0x1026), @@ -110,6 +87,9 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x107B), INTEL_E1000_ETHERNET_DEVICE(0x107C), INTEL_E1000_ETHERNET_DEVICE(0x108A), + INTEL_E1000_ETHERNET_DEVICE(0x108B), + INTEL_E1000_ETHERNET_DEVICE(0x108C), + INTEL_E1000_ETHERNET_DEVICE(0x1099), /* required last entry */ {0,} }; @@ -350,8 +330,11 @@ e1000_up(struct e1000_adapter *adapter) #endif if((err = request_irq(adapter->pdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, - netdev->name, netdev))) + netdev->name, netdev))) { + DPRINTK(PROBE, ERR, + "Unable to allocate interrupt Error: %d\n", err); return err; + } mod_timer(&adapter->watchdog_timer, jiffies); @@ -636,7 +619,7 @@ e1000_probe(struct pci_dev *pdev, /* copy the MAC address out of the EEPROM */ - if (e1000_read_mac_addr(&adapter->hw)) + if(e1000_read_mac_addr(&adapter->hw)) DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); @@ -963,12 +946,10 @@ e1000_check_64k_bound(struct e1000_adapter *adapter, unsigned long begin = (unsigned long) start; unsigned long end = begin + len; - /* first rev 82545 and 82546 need to not allow any memory - * write location to cross a 64k boundary due to errata 23 */ + /* First rev 82545 and 82546 need to not allow any memory + * write location to cross 64k boundary due to errata 23 */ if (adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546 ) { - - /* check buffer doesn't cross 64kB */ + adapter->hw.mac_type == e1000_82546) { return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE; } @@ -992,8 +973,8 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter) size = sizeof(struct e1000_buffer) * txdr->count; txdr->buffer_info = vmalloc(size); if(!txdr->buffer_info) { - DPRINTK(PROBE, ERR, - "Unable to Allocate Memory for the Transmit descriptor ring\n"); + DPRINTK(PROBE, ERR, + "Unable to allocate memory for the transmit descriptor ring\n"); return -ENOMEM; } memset(txdr->buffer_info, 0, size); @@ -1006,38 +987,38 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter) txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); if(!txdr->desc) { setup_tx_desc_die: - DPRINTK(PROBE, ERR, - "Unable to Allocate Memory for the Transmit descriptor ring\n"); vfree(txdr->buffer_info); + DPRINTK(PROBE, ERR, + "Unable to allocate memory for the transmit descriptor ring\n"); return -ENOMEM; } - /* fix for errata 23, cant cross 64kB boundary */ + /* Fix for errata 23, can't cross 64kB boundary */ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { void *olddesc = txdr->desc; dma_addr_t olddma = txdr->dma; - DPRINTK(TX_ERR,ERR,"txdr align check failed: %u bytes at %p\n", - txdr->size, txdr->desc); - /* try again, without freeing the previous */ + DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " + "at %p\n", txdr->size, txdr->desc); + /* Try again, without freeing the previous */ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); - /* failed allocation, critial failure */ if(!txdr->desc) { + /* Failed allocation, critical failure */ pci_free_consistent(pdev, txdr->size, olddesc, olddma); goto setup_tx_desc_die; } if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { /* give up */ - pci_free_consistent(pdev, txdr->size, - txdr->desc, txdr->dma); + pci_free_consistent(pdev, txdr->size, txdr->desc, + txdr->dma); pci_free_consistent(pdev, txdr->size, olddesc, olddma); DPRINTK(PROBE, ERR, - "Unable to Allocate aligned Memory for the Transmit" - " descriptor ring\n"); + "Unable to allocate aligned memory " + "for the transmit descriptor ring\n"); vfree(txdr->buffer_info); return -ENOMEM; } else { - /* free old, move on with the new one since its okay */ + /* Free old allocation, new allocation was successful */ pci_free_consistent(pdev, txdr->size, olddesc, olddma); } } @@ -1144,8 +1125,8 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter) size = sizeof(struct e1000_buffer) * rxdr->count; rxdr->buffer_info = vmalloc(size); if(!rxdr->buffer_info) { - DPRINTK(PROBE, ERR, - "Unable to Allocate Memory for the Recieve descriptor ring\n"); + DPRINTK(PROBE, ERR, + "Unable to allocate memory for the receive descriptor ring\n"); return -ENOMEM; } memset(rxdr->buffer_info, 0, size); @@ -1185,43 +1166,42 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter) if(!rxdr->desc) { setup_rx_desc_die: - DPRINTK(PROBE, ERR, - "Unble to Allocate Memory for the Recieve descriptor ring\n"); vfree(rxdr->buffer_info); kfree(rxdr->ps_page); kfree(rxdr->ps_page_dma); + DPRINTK(PROBE, ERR, + "Unable to allocate memory for the receive descriptor ring\n"); return -ENOMEM; } - /* fix for errata 23, cant cross 64kB boundary */ + /* Fix for errata 23, can't cross 64kB boundary */ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { void *olddesc = rxdr->desc; dma_addr_t olddma = rxdr->dma; - DPRINTK(RX_ERR,ERR, - "rxdr align check failed: %u bytes at %p\n", - rxdr->size, rxdr->desc); - /* try again, without freeing the previous */ + DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " + "at %p\n", rxdr->size, rxdr->desc); + /* Try again, without freeing the previous */ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); - /* failed allocation, critial failure */ if(!rxdr->desc) { + /* Failed allocation, critical failure */ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); goto setup_rx_desc_die; } if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { /* give up */ - pci_free_consistent(pdev, rxdr->size, - rxdr->desc, rxdr->dma); + pci_free_consistent(pdev, rxdr->size, rxdr->desc, + rxdr->dma); pci_free_consistent(pdev, rxdr->size, olddesc, olddma); - DPRINTK(PROBE, ERR, - "Unable to Allocate aligned Memory for the" - " Receive descriptor ring\n"); + DPRINTK(PROBE, ERR, + "Unable to allocate aligned memory " + "for the receive descriptor ring\n"); vfree(rxdr->buffer_info); kfree(rxdr->ps_page); kfree(rxdr->ps_page_dma); return -ENOMEM; } else { - /* free old, move on with the new one since its okay */ + /* Free old allocation, new allocation was successful */ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); } } @@ -1234,7 +1214,7 @@ setup_rx_desc_die: } /** - * e1000_setup_rctl - configure the receive control register + * e1000_setup_rctl - configure the receive control registers * @adapter: Board private structure **/ @@ -1426,13 +1406,11 @@ static inline void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { - struct pci_dev *pdev = adapter->pdev; - if(buffer_info->dma) { - pci_unmap_page(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); + pci_unmap_page(adapter->pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); buffer_info->dma = 0; } if(buffer_info->skb) { @@ -1457,7 +1435,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter) /* Free all the Tx ring sk_buffs */ if (likely(adapter->previous_buffer_info.skb != NULL)) { - e1000_unmap_and_free_tx_resource(adapter, + e1000_unmap_and_free_tx_resource(adapter, &adapter->previous_buffer_info); } @@ -1659,15 +1637,15 @@ e1000_set_multi(struct net_device *netdev) struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; struct dev_mc_list *mc_ptr; + unsigned long flags; uint32_t rctl; uint32_t hash_value; int i; - unsigned long flags; - - /* Check for Promiscuous and All Multicast modes */ spin_lock_irqsave(&adapter->tx_lock, flags); + /* Check for Promiscuous and All Multicast modes */ + rctl = E1000_READ_REG(hw, RCTL); if(netdev->flags & IFF_PROMISC) { @@ -1874,7 +1852,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter) /* Cause software interrupt to ensure rx ring is cleaned */ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); - /* Force detection of hung controller every watchdog period*/ + /* Force detection of hung controller every watchdog period */ adapter->detect_tx_hung = TRUE; /* Reset the timer */ @@ -2255,7 +2233,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) #ifdef NETIF_F_TSO mss = skb_shinfo(skb)->tso_size; - /* The controller does a simple calculation to + /* The controller does a simple calculation to * make sure there is enough room in the FIFO before * initiating the DMA for each buffer. The calc is: * 4 = ceil(buffer len/mss). To make sure we don't @@ -2268,7 +2246,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if((mss) || (skb->ip_summed == CHECKSUM_HW)) count++; - count++; /* for sentinel desc */ + count++; #else if(skb->ip_summed == CHECKSUM_HW) count++; @@ -2658,7 +2636,7 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) */ if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){ atomic_inc(&adapter->irq_sem); - E1000_WRITE_REG(&adapter->hw, IMC, ~0); + E1000_WRITE_REG(hw, IMC, ~0); } for(i = 0; i < E1000_MAX_INTR; i++) @@ -2686,7 +2664,7 @@ e1000_clean(struct net_device *netdev, int *budget) int work_to_do = min(*budget, netdev->quota); int tx_cleaned; int work_done = 0; - + tx_cleaned = e1000_clean_tx_irq(adapter); adapter->clean_rx(adapter, &work_done, work_to_do); @@ -2776,9 +2754,9 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) netif_wake_queue(netdev); spin_unlock(&adapter->tx_lock); - if(adapter->detect_tx_hung) { - /* detect a transmit hang in hardware, this serializes the + + /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = FALSE; if (tx_ring->buffer_info[i].dma && @@ -2923,7 +2901,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) { /* All receives must fit into a single buffer */ E1000_DBG("%s: Receive packet consumed multiple" - " buffers\n", netdev->name); + " buffers\n", netdev->name); dev_kfree_skb_irq(skb); goto next_desc; } @@ -3130,43 +3108,43 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) struct e1000_rx_desc *rx_desc; struct e1000_buffer *buffer_info; struct sk_buff *skb; - unsigned int i, bufsz; + unsigned int i; + unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; i = rx_ring->next_to_use; buffer_info = &rx_ring->buffer_info[i]; while(!buffer_info->skb) { - bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; - skb = dev_alloc_skb(bufsz); + if(unlikely(!skb)) { /* Better luck next round */ break; } - /* fix for errata 23, cant cross 64kB boundary */ + /* Fix for errata 23, can't cross 64kB boundary */ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { struct sk_buff *oldskb = skb; - DPRINTK(RX_ERR,ERR, - "skb align check failed: %u bytes at %p\n", - bufsz, skb->data); - /* try again, without freeing the previous */ + DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " + "at %p\n", bufsz, skb->data); + /* Try again, without freeing the previous */ skb = dev_alloc_skb(bufsz); + /* Failed allocation, critical failure */ if (!skb) { dev_kfree_skb(oldskb); break; } + if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { /* give up */ dev_kfree_skb(skb); dev_kfree_skb(oldskb); break; /* while !buffer_info->skb */ } else { - /* move on with the new one */ + /* Use new allocation */ dev_kfree_skb(oldskb); } } - /* Make buffer alignment 2 beyond a 16 byte boundary * this will result in a 16 byte aligned IP header after * the 14 byte MAC header is removed @@ -3182,25 +3160,23 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); - /* fix for errata 23, cant cross 64kB boundary */ - if(!e1000_check_64k_bound(adapter, - (void *)(unsigned long)buffer_info->dma, - adapter->rx_buffer_len)) { - DPRINTK(RX_ERR,ERR, - "dma align check failed: %u bytes at %ld\n", - adapter->rx_buffer_len, (unsigned long)buffer_info->dma); - + /* Fix for errata 23, can't cross 64kB boundary */ + if (!e1000_check_64k_bound(adapter, + (void *)(unsigned long)buffer_info->dma, + adapter->rx_buffer_len)) { + DPRINTK(RX_ERR, ERR, + "dma align check failed: %u bytes at %p\n", + adapter->rx_buffer_len, + (void *)(unsigned long)buffer_info->dma); dev_kfree_skb(skb); buffer_info->skb = NULL; - pci_unmap_single(pdev, - buffer_info->dma, + pci_unmap_single(pdev, buffer_info->dma, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); break; /* while !buffer_info->skb */ } - rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); @@ -3210,7 +3186,6 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) * applicable for weak-ordered memory model archs, * such as IA-64). */ wmb(); - E1000_WRITE_REG(&adapter->hw, RDT, i); } @@ -3483,9 +3458,10 @@ void e1000_pci_set_mwi(struct e1000_hw *hw) { struct e1000_adapter *adapter = hw->back; + int ret_val = pci_set_mwi(adapter->pdev); - int ret; - ret = pci_set_mwi(adapter->pdev); + if(ret_val) + DPRINTK(PROBE, ERR, "Error in setting MWI\n"); } void @@ -3643,8 +3619,7 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: - DPRINTK(PROBE, ERR, - "Unsupported Speed/Duplexity configuration\n"); + DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); return -EINVAL; } return 0; @@ -3810,7 +3785,7 @@ e1000_resume(struct pci_dev *pdev) * the interrupt routine is executing. */ static void -e1000_netpoll (struct net_device *netdev) +e1000_netpoll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; disable_irq(adapter->pdev->irq); diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index b1915e8..aac64de 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index e914d09..676247f 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. 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 @@ -478,7 +478,6 @@ e1000_check_options(struct e1000_adapter *adapter) DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name); break; - case -1: default: e1000_validate_option(&adapter->itr, &opt, adapter); -- cgit v1.1 From 5633684d008b777ab169e8efcef39a898482f531 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 18:45:50 -0700 Subject: [PATCH] ixgb: Fix multi-cast packet count in statistics Fix multi-cast packet count in statistics Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 7d26623..1498b4e 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1526,14 +1526,33 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu) void ixgb_update_stats(struct ixgb_adapter *adapter) { + struct net_device *netdev = adapter->netdev; + + if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) || + (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) { + u64 multi = IXGB_READ_REG(&adapter->hw, MPRCL); + u32 bcast_l = IXGB_READ_REG(&adapter->hw, BPRCL); + u32 bcast_h = IXGB_READ_REG(&adapter->hw, BPRCH); + u64 bcast = ((u64)bcast_h << 32) | bcast_l; + + multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32); + /* fix up multicast stats by removing broadcasts */ + multi -= bcast; + + adapter->stats.mprcl += (multi & 0xFFFFFFFF); + adapter->stats.mprch += (multi >> 32); + adapter->stats.bprcl += bcast_l; + adapter->stats.bprch += bcast_h; + } else { + adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL); + adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH); + adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL); + adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH); + } adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL); adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH); adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL); adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH); - adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL); - adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH); - adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL); - adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH); adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL); adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH); adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL); -- cgit v1.1 From 06c2f9ecb5b53f9d4fc1ef596da16683cc4af5ba Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 18:46:51 -0700 Subject: [PATCH] ixgb: Do not set the RS bit on context descriptors Don't set the RS bit on context descriptors, causes un-necessary bus activity Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 1498b4e..364a9e7 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1209,10 +1209,10 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) | IXGB_CONTEXT_DESC_CMD_TSE | IXGB_CONTEXT_DESC_CMD_IP | IXGB_CONTEXT_DESC_CMD_TCP - | IXGB_CONTEXT_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE | (skb->len - (hdr_len))); + if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; @@ -1247,8 +1247,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) context_desc->mss = 0; context_desc->cmd_type_len = cpu_to_le32(IXGB_CONTEXT_DESC_TYPE - | IXGB_TX_DESC_CMD_RS - | IXGB_TX_DESC_CMD_IDE); + | IXGB_TX_DESC_CMD_IDE); if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; -- cgit v1.1 From 0c73f58636385a4d3dc68d0d0829d4c39d61b621 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 18:48:06 -0700 Subject: [PATCH] ixgb: Change RDT write bump size to 4 Change RDT write bump size back to 4 Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb.h net-drivers-2.6/drivers/net/ixgb.new/ixgb.h --- drivers/net/ixgb/ixgb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 26c4f15..f8d3385 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -110,7 +110,7 @@ struct ixgb_adapter; #define IXGB_TX_QUEUE_WAKE 16 /* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define IXGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ +#define IXGB_RX_BUFFER_WRITE 4 /* Must be power of 2 */ /* only works for sizes that are powers of 2 */ #define IXGB_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) -- cgit v1.1 From 6dfbb6dd391139be9f1cd333877c6e2b03da4bba Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 18:56:40 -0700 Subject: [PATCH] ixgb: Mask RXO interrupt Disable RXO interrupt to decrease recovery time when system is overloaded with data Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 364a9e7..da6b9d6 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -224,8 +224,8 @@ ixgb_irq_enable(struct ixgb_adapter *adapter) { if(atomic_dec_and_test(&adapter->irq_sem)) { IXGB_WRITE_REG(&adapter->hw, IMS, - IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | - IXGB_INT_RXO | IXGB_INT_LSC); + IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | + IXGB_INT_LSC); IXGB_WRITE_FLUSH(&adapter->hw); } } -- cgit v1.1 From 41639fed1b32dde4ea3d94242a89308435d341be Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 18:51:54 -0700 Subject: [PATCH] ixgb: Reset status in the Rx Reset status in the Rx descriptor prior to handing it to the controller. Leave three Rx descriptors unused Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index da6b9d6..a6a13f6 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1977,8 +1977,8 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter) num_group_tail_writes = IXGB_RX_BUFFER_WRITE; - /* leave one descriptor unused */ - while(--cleancount > 0) { + /* leave three descriptors unused */ + while(--cleancount > 2) { rx_desc = IXGB_RX_DESC(*rx_ring, i); skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); @@ -2005,6 +2005,10 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter) PCI_DMA_FROMDEVICE); rx_desc->buff_addr = cpu_to_le64(buffer_info->dma); + /* guarantee DD bit not set now before h/w gets descriptor + * this is the rest of the workaround for h/w double + * writeback. */ + rx_desc->status = 0; if((i & ~(num_group_tail_writes- 1)) == i) { /* Force memory writes to complete before letting h/w -- cgit v1.1 From abf481d6af8670c89f33f354c6fbd9977b23cebc Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:03:32 -0700 Subject: [PATCH] ixgb: Fix EEPROM functions to be endian-aware Fix EEPROM functions to be endian-aware Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_ee.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_ee.c --- drivers/net/ixgb/ixgb_ee.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c index 653e99f..3aae110 100644 --- a/drivers/net/ixgb/ixgb_ee.c +++ b/drivers/net/ixgb/ixgb_ee.c @@ -411,7 +411,7 @@ ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data) ixgb_cleanup_eeprom(hw); /* clear the init_ctrl_reg_1 to signify that the cache is invalidated */ - ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR; + ee_map->init_ctrl_reg_1 = le16_to_cpu(EEPROM_ICW1_SIGNATURE_CLEAR); return; } @@ -483,7 +483,7 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw) DEBUGOUT("ixgb_ee: Checksum invalid.\n"); /* clear the init_ctrl_reg_1 to signify that the cache is * invalidated */ - ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR; + ee_map->init_ctrl_reg_1 = le16_to_cpu(EEPROM_ICW1_SIGNATURE_CLEAR); return (FALSE); } @@ -579,7 +579,7 @@ ixgb_get_ee_compatibility(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->compatibility); + return (le16_to_cpu(ee_map->compatibility)); return(0); } @@ -616,7 +616,7 @@ ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->init_ctrl_reg_1); + return (le16_to_cpu(ee_map->init_ctrl_reg_1)); return(0); } @@ -635,7 +635,7 @@ ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->init_ctrl_reg_2); + return (le16_to_cpu(ee_map->init_ctrl_reg_2)); return(0); } @@ -654,7 +654,7 @@ ixgb_get_ee_subsystem_id(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->subsystem_id); + return (le16_to_cpu(ee_map->subsystem_id)); return(0); } @@ -673,7 +673,7 @@ ixgb_get_ee_subvendor_id(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->subvendor_id); + return (le16_to_cpu(ee_map->subvendor_id)); return(0); } @@ -692,7 +692,7 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->device_id); + return (le16_to_cpu(ee_map->device_id)); return(0); } @@ -711,7 +711,7 @@ ixgb_get_ee_vendor_id(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->vendor_id); + return (le16_to_cpu(ee_map->vendor_id)); return(0); } @@ -730,7 +730,7 @@ ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->swdpins_reg); + return (le16_to_cpu(ee_map->swdpins_reg)); return(0); } @@ -749,7 +749,7 @@ ixgb_get_ee_d3_power(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->d3_power); + return (le16_to_cpu(ee_map->d3_power)); return(0); } @@ -768,7 +768,7 @@ ixgb_get_ee_d0_power(struct ixgb_hw *hw) struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom; if(ixgb_check_and_get_eeprom_data(hw) == TRUE) - return(ee_map->d0_power); + return (le16_to_cpu(ee_map->d0_power)); return(0); } -- cgit v1.1 From 5e3c30deb21d0eb0da44830fb1c1fc7054e54229 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:04:07 -0700 Subject: [PATCH] ixgb: Support for ethtool -d ixgb support for ethtool -d Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_ethtool.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_ethtool.c --- drivers/net/ixgb/ixgb_ethtool.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index aea10e8..3fa1138 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -252,7 +252,9 @@ ixgb_get_regs(struct net_device *netdev, uint32_t *reg_start = reg; uint8_t i; - regs->version = (adapter->hw.device_id << 16) | adapter->hw.subsystem_id; + /* the 1 (one) below indicates an attempt at versioning, if the + * interface in ethtool or the driver this 1 should be incremented */ + regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id; /* General Registers */ *reg++ = IXGB_READ_REG(hw, CTRL0); /* 0 */ -- cgit v1.1 From c2eba932b14718e34ac2609e35c6d41e032a2478 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:04:32 -0700 Subject: [PATCH] ixgb: Remove hook for suspend, no power management Remove hook for suspend. No power management in 10GbE Controllers Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 75 +++----------------------------------------- 1 file changed, 4 insertions(+), 71 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index a6a13f6..0a0f041 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -120,33 +120,20 @@ static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); static void ixgb_restore_vlan(struct ixgb_adapter *adapter); -static int ixgb_notify_reboot(struct notifier_block *, unsigned long event, - void *ptr); -static int ixgb_suspend(struct pci_dev *pdev, uint32_t state); - #ifdef CONFIG_NET_POLL_CONTROLLER /* for netdump / net console */ static void ixgb_netpoll(struct net_device *dev); #endif -struct notifier_block ixgb_notifier_reboot = { - .notifier_call = ixgb_notify_reboot, - .next = NULL, - .priority = 0 -}; - /* Exported from other modules */ extern void ixgb_check_options(struct ixgb_adapter *adapter); static struct pci_driver ixgb_driver = { - .name = ixgb_driver_name, + .name = ixgb_driver_name, .id_table = ixgb_pci_tbl, - .probe = ixgb_probe, - .remove = __devexit_p(ixgb_remove), - /* Power Managment Hooks */ - .suspend = NULL, - .resume = NULL + .probe = ixgb_probe, + .remove = __devexit_p(ixgb_remove), }; MODULE_AUTHOR("Intel Corporation, "); @@ -169,17 +156,12 @@ MODULE_LICENSE("GPL"); static int __init ixgb_init_module(void) { - int ret; printk(KERN_INFO "%s - version %s\n", ixgb_driver_string, ixgb_driver_version); printk(KERN_INFO "%s\n", ixgb_copyright); - ret = pci_module_init(&ixgb_driver); - if(ret >= 0) { - register_reboot_notifier(&ixgb_notifier_reboot); - } - return ret; + return pci_module_init(&ixgb_driver); } module_init(ixgb_init_module); @@ -194,7 +176,6 @@ module_init(ixgb_init_module); static void __exit ixgb_exit_module(void) { - unregister_reboot_notifier(&ixgb_notifier_reboot); pci_unregister_driver(&ixgb_driver); } @@ -2121,54 +2102,6 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter) } } -/** - * ixgb_notify_reboot - handles OS notification of reboot event. - * @param nb notifier block, unused - * @param event Event being passed to driver to act upon - * @param p A pointer to our net device - **/ -static int -ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -{ - struct pci_dev *pdev = NULL; - - switch(event) { - case SYS_DOWN: - case SYS_HALT: - case SYS_POWER_OFF: - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { - if (pci_dev_driver(pdev) == &ixgb_driver) - ixgb_suspend(pdev, 3); - } - } - return NOTIFY_DONE; -} - -/** - * ixgb_suspend - driver suspend function called from notify. - * @param pdev pci driver structure used for passing to - * @param state power state to enter - **/ -static int -ixgb_suspend(struct pci_dev *pdev, uint32_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgb_adapter *adapter = netdev->priv; - - netif_device_detach(netdev); - - if(netif_running(netdev)) - ixgb_down(adapter, TRUE); - - pci_save_state(pdev); - - state = (state > 0) ? 3 : 0; - pci_set_power_state(pdev, state); - msec_delay(200); - - return 0; -} - #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs -- cgit v1.1 From f404de1cd407c1f56fa478810c6c48e015d377bd Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:04:54 -0700 Subject: [PATCH] ixgb: Code optimization Code optimization Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 0a0f041..db1089c 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1822,7 +1822,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) struct pci_dev *pdev = adapter->pdev; struct ixgb_rx_desc *rx_desc, *next_rxd; struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer; - struct sk_buff *skb, *next_skb; uint32_t length; unsigned int i, j; boolean_t cleaned = FALSE; @@ -1832,6 +1831,8 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) buffer_info = &rx_ring->buffer_info[i]; while(rx_desc->status & IXGB_RX_DESC_STATUS_DD) { + struct sk_buff *skb, *next_skb; + u8 status; #ifdef CONFIG_IXGB_NAPI if(*work_done >= work_to_do) @@ -1839,7 +1840,9 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) (*work_done)++; #endif + status = rx_desc->status; skb = buffer_info->skb; + prefetch(skb->data); if(++i == rx_ring->count) i = 0; @@ -1864,7 +1867,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) length = le16_to_cpu(rx_desc->length); - if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) { + if(unlikely(!(status & IXGB_RX_DESC_STATUS_EOP))) { /* All receives must fit into a single buffer */ @@ -1872,12 +1875,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) "length<%x>\n", length); dev_kfree_skb_irq(skb); - rx_desc->status = 0; - buffer_info->skb = NULL; - - rx_desc = next_rxd; - buffer_info = next_buffer; - continue; + goto rxdesc_done; } if (unlikely(rx_desc->errors @@ -1886,12 +1884,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) IXGB_RX_DESC_ERRORS_RXE))) { dev_kfree_skb_irq(skb); - rx_desc->status = 0; - buffer_info->skb = NULL; - - rx_desc = next_rxd; - buffer_info = next_buffer; - continue; + goto rxdesc_done; } /* Good Receive */ @@ -1902,7 +1895,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) skb->protocol = eth_type_trans(skb, netdev); #ifdef CONFIG_IXGB_NAPI - if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) { + if(adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, le16_to_cpu(rx_desc->special) & IXGB_RX_DESC_SPECIAL_VLAN_MASK); @@ -1910,7 +1903,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) netif_receive_skb(skb); } #else /* CONFIG_IXGB_NAPI */ - if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) { + if(adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) { vlan_hwaccel_rx(skb, adapter->vlgrp, le16_to_cpu(rx_desc->special) & IXGB_RX_DESC_SPECIAL_VLAN_MASK); @@ -1920,9 +1913,12 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) #endif /* CONFIG_IXGB_NAPI */ netdev->last_rx = jiffies; +rxdesc_done: + /* clean up descriptor, might be written over by hw */ rx_desc->status = 0; buffer_info->skb = NULL; + /* use prefetched values */ rx_desc = next_rxd; buffer_info = next_buffer; } -- cgit v1.1 From 37d16f823799918107440cb9e552b0709347f77c Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:05:12 -0700 Subject: [PATCH] ixgb: Fixed msec_delay in osdep to use msleep Fixed msec_delay in osdep to use msleep Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_osdep.h net-drivers-2.6/drivers/net/ixgb.new/ixgb_osdep.h --- drivers/net/ixgb/ixgb_osdep.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h index 9eba928..dba2048 100644 --- a/drivers/net/ixgb/ixgb_osdep.h +++ b/drivers/net/ixgb/ixgb_osdep.h @@ -45,8 +45,7 @@ /* Don't mdelay in interrupt context! */ \ BUG(); \ } else { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout((x * HZ)/1000 + 2); \ + msleep(x); \ } } while(0) #endif -- cgit v1.1 From ac79c82e793bc2440c4765e5eb1b834d2c18edf2 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:05:32 -0700 Subject: [PATCH] ixgb: Driver version, white space, comments, device id Driver version, white space, comments, device id & other Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak diff -up net-drivers-2.6/drivers/net/ixgb/ixgb_main.c net-drivers-2.6/drivers/net/ixgb.new/ixgb_main.c --- drivers/net/ixgb/ixgb_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index db1089c..35f6a7c 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -47,7 +47,7 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -char ixgb_driver_version[] = "1.0.90-k2"DRIVERNAPI; +char ixgb_driver_version[] = "1.0.95-k2"DRIVERNAPI; char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; /* ixgb_pci_tbl - PCI Device ID Table @@ -103,6 +103,7 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu); static int ixgb_set_mac(struct net_device *netdev, void *p); static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs); static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter); + #ifdef CONFIG_IXGB_NAPI static int ixgb_clean(struct net_device *netdev, int *budget); static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, @@ -1253,6 +1254,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; + len -= skb->data_len; i = tx_ring->next_to_use; @@ -1857,7 +1859,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter) next_skb = next_buffer->skb; prefetch(next_skb); - cleaned = TRUE; pci_unmap_single(pdev, @@ -2108,6 +2109,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter) static void ixgb_netpoll(struct net_device *dev) { struct ixgb_adapter *adapter = dev->priv; + disable_irq(adapter->pdev->irq); ixgb_intr(adapter->pdev->irq, dev, NULL); enable_irq(adapter->pdev->irq); -- cgit v1.1 From 2acdb1e05c1a92e05ee710ed8f226a8f3183d5a0 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:16:58 -0700 Subject: [PATCH] e100: Execute tx_timeout task outside interrupt context Execute tx_timeout task outside the interrupt context Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak --- drivers/net/e100.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 1b68dd5..0f2837e 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -539,6 +539,7 @@ struct nic { struct timer_list watchdog; struct timer_list blink_timer; struct mii_if_info mii; + struct work_struct tx_timeout_task; enum loopback loopback; struct mem *mem; @@ -1716,6 +1717,15 @@ static void e100_tx_timeout(struct net_device *netdev) { struct nic *nic = netdev_priv(netdev); + /* Reset outside of interrupt context, to avoid request_irq + * in interrupt context */ + schedule_work(&nic->tx_timeout_task); +} + +static void e100_tx_timeout_task(struct net_device *netdev) +{ + struct nic *nic = netdev_priv(netdev); + DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", readb(&nic->csr->scb.status)); e100_down(netdev_priv(netdev)); @@ -2240,6 +2250,9 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->blink_timer.function = e100_blink_led; nic->blink_timer.data = (unsigned long)nic; + INIT_WORK(&nic->tx_timeout_task, + (void (*)(void *))e100_tx_timeout_task, netdev); + if((err = e100_alloc(nic))) { DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); goto err_out_iounmap; -- cgit v1.1 From 1f53367d5d75ba37f258f6e955d6fc24814051a0 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:17:20 -0700 Subject: [PATCH] e100: Render e100 NAPI state machine Render e100 NAPI state machine to be similar to the non-NAPI one. Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak --- drivers/net/e100.c | 86 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 0f2837e..2c8c14e 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -269,6 +269,12 @@ enum scb_status { rus_mask = 0x3C, }; +enum ru_state { + RU_SUSPENDED = 0, + RU_RUNNING = 1, + RU_UNINITIALIZED = -1, +}; + enum scb_stat_ack { stat_ack_not_ours = 0x00, stat_ack_sw_gen = 0x04, @@ -510,7 +516,7 @@ struct nic { struct rx *rx_to_use; struct rx *rx_to_clean; struct rfd blank_rfd; - int ru_running; + enum ru_state ru_running; spinlock_t cb_lock ____cacheline_aligned; spinlock_t cmd_lock; @@ -1204,7 +1210,9 @@ static void e100_update_stats(struct nic *nic) } } - e100_exec_cmd(nic, cuc_dump_reset, 0); + + if(e100_exec_cmd(nic, cuc_dump_reset, 0)) + DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); } static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) @@ -1298,7 +1306,8 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. Issue a NOP command followed by a 1us delay before issuing the Tx command. */ - e100_exec_cmd(nic, cuc_nop, 0); + if(e100_exec_cmd(nic, cuc_nop, 0)) + DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); udelay(1); } @@ -1416,12 +1425,18 @@ static int e100_alloc_cbs(struct nic *nic) return 0; } -static inline void e100_start_receiver(struct nic *nic) +static inline void e100_start_receiver(struct nic *nic, struct rx *rx) { + if(!nic->rxs) return; + if(RU_SUSPENDED != nic->ru_running) return; + + /* handle init time starts */ + if(!rx) rx = nic->rxs; + /* (Re)start RU if suspended or idle and RFA is non-NULL */ - if(!nic->ru_running && nic->rx_to_clean->skb) { - e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr); - nic->ru_running = 1; + if(rx->skb) { + e100_exec_cmd(nic, ruc_start, rx->dma_addr); + nic->ru_running = RU_RUNNING; } } @@ -1438,6 +1453,13 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); + if(pci_dma_mapping_error(rx->dma_addr)) { + dev_kfree_skb_any(rx->skb); + rx->skb = 0; + rx->dma_addr = 0; + return -ENOMEM; + } + /* Link the RFD to end of RFA by linking previous RFD to * this one, and clearing EL bit of previous. */ if(rx->prev->skb) { @@ -1472,7 +1494,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, /* If data isn't ready, nothing to indicate */ if(unlikely(!(rfd_status & cb_complete))) - return -EAGAIN; + return -ENODATA; /* Get actual data size */ actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; @@ -1483,6 +1505,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, pci_unmap_single(nic->pdev, rx->dma_addr, RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + /* this allows for a fast restart without re-enabling interrupts */ + if(le16_to_cpu(rfd->command) & cb_el) + nic->ru_running = RU_SUSPENDED; + /* Pull off the RFD and put the actual data (minus eth hdr) */ skb_reserve(skb, sizeof(struct rfd)); skb_put(skb, actual_size); @@ -1515,20 +1541,45 @@ static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done, unsigned int work_to_do) { struct rx *rx; + int restart_required = 0; + struct rx *rx_to_start = NULL; + + /* are we already rnr? then pay attention!!! this ensures that + * the state machine progression never allows a start with a + * partially cleaned list, avoiding a race between hardware + * and rx_to_clean when in NAPI mode */ + if(RU_SUSPENDED == nic->ru_running) + restart_required = 1; /* Indicate newly arrived packets */ for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - if(e100_rx_indicate(nic, rx, work_done, work_to_do)) + int err = e100_rx_indicate(nic, rx, work_done, work_to_do); + if(-EAGAIN == err) { + /* hit quota so have more work to do, restart once + * cleanup is complete */ + restart_required = 0; + break; + } else if(-ENODATA == err) break; /* No more to clean */ } + /* save our starting point as the place we'll restart the receiver */ + if(restart_required) + rx_to_start = nic->rx_to_clean; + /* Alloc new skbs to refill list */ for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { if(unlikely(e100_rx_alloc_skb(nic, rx))) break; /* Better luck next time (see watchdog) */ } - e100_start_receiver(nic); + if(restart_required) { + // ack the rnr? + writeb(stat_ack_rnr, &nic->csr->scb.stat_ack); + e100_start_receiver(nic, rx_to_start); + if(work_done) + (*work_done)++; + } } static void e100_rx_clean_list(struct nic *nic) @@ -1536,6 +1587,8 @@ static void e100_rx_clean_list(struct nic *nic) struct rx *rx; unsigned int i, count = nic->params.rfds.count; + nic->ru_running = RU_UNINITIALIZED; + if(nic->rxs) { for(rx = nic->rxs, i = 0; i < count; rx++, i++) { if(rx->skb) { @@ -1549,7 +1602,6 @@ static void e100_rx_clean_list(struct nic *nic) } nic->rx_to_use = nic->rx_to_clean = NULL; - nic->ru_running = 0; } static int e100_rx_alloc_list(struct nic *nic) @@ -1558,6 +1610,7 @@ static int e100_rx_alloc_list(struct nic *nic) unsigned int i, count = nic->params.rfds.count; nic->rx_to_use = nic->rx_to_clean = NULL; + nic->ru_running = RU_UNINITIALIZED; if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC))) return -ENOMEM; @@ -1573,6 +1626,7 @@ static int e100_rx_alloc_list(struct nic *nic) } nic->rx_to_use = nic->rx_to_clean = nic->rxs; + nic->ru_running = RU_SUSPENDED; return 0; } @@ -1594,7 +1648,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) /* We hit Receive No Resource (RNR); restart RU after cleaning */ if(stat_ack & stat_ack_rnr) - nic->ru_running = 0; + nic->ru_running = RU_SUSPENDED; e100_disable_irq(nic); netif_rx_schedule(netdev); @@ -1684,7 +1738,7 @@ static int e100_up(struct nic *nic) if((err = e100_hw_init(nic))) goto err_clean_cbs; e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic); + e100_start_receiver(nic, 0); mod_timer(&nic->watchdog, jiffies); if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ, nic->netdev->name, nic->netdev))) @@ -1759,7 +1813,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, BMCR_LOOPBACK); - e100_start_receiver(nic); + e100_start_receiver(nic, 0); if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) { err = -ENOMEM; @@ -2233,6 +2287,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, e100_get_defaults(nic); + /* locks must be initialized before calling hw_reset */ spin_lock_init(&nic->cb_lock); spin_lock_init(&nic->cmd_lock); @@ -2348,7 +2403,8 @@ static int e100_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - e100_hw_init(nic); + if(e100_hw_init(nic)) + DPRINTK(HW, ERR, "e100_hw_init failed\n"); netif_device_attach(netdev); if(netif_running(netdev)) -- cgit v1.1 From 0236ebb7ae85935b3b96eef7e8a4e203ea9958a0 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:17:42 -0700 Subject: [PATCH] e100: Synchronize interface link state with poll routine Synchronize interface link state with e100 poll routine Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak --- drivers/net/e100.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 2c8c14e..c1ca2da 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1743,8 +1743,11 @@ static int e100_up(struct nic *nic) if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ, nic->netdev->name, nic->netdev))) goto err_no_irq; - e100_enable_irq(nic); netif_wake_queue(nic->netdev); + netif_poll_enable(nic->netdev); + /* enable ints _after_ enabling poll, preventing a race between + * disable ints+schedule */ + e100_enable_irq(nic); return 0; err_no_irq: @@ -1758,11 +1761,13 @@ err_rx_clean_list: static void e100_down(struct nic *nic) { + /* wait here for poll to complete */ + netif_poll_disable(nic->netdev); + netif_stop_queue(nic->netdev); e100_hw_reset(nic); free_irq(nic->pdev->irq, nic->netdev); del_timer_sync(&nic->watchdog); netif_carrier_off(nic->netdev); - netif_stop_queue(nic->netdev); e100_clean_cbs(nic); e100_rx_clean_list(nic); } -- cgit v1.1 From 6bdacb1ad58bb6b772a4fc18f21684437bd5f439 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:17:54 -0700 Subject: [PATCH] e100: Fix Wake on lan related issues Fix Wake on lan related issues Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak --- drivers/net/e100.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index c1ca2da..a43b825 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -971,7 +971,8 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) if(nic->flags & multicast_all) config->multicast_all = 0x1; /* 1=accept, 0=no */ - if(!(nic->flags & wol_magic)) + /* disable WoL when up */ + if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) config->magic_packet_disable = 0x1; /* 1=off, 0=on */ if(nic->mac >= mac_82558_D101_A4) { @@ -1718,6 +1719,7 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu) return 0; } +#ifdef CONFIG_PM static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ @@ -1726,6 +1728,7 @@ static int e100_asf(struct nic *nic) !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); } +#endif static int e100_up(struct nic *nic) { @@ -1938,7 +1941,6 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) else nic->flags &= ~wol_magic; - pci_enable_wake(nic->pdev, 0, nic->flags & (wol_magic | e100_asf(nic))); e100_exec_cb(nic, NULL, e100_configure); return 0; @@ -2336,7 +2338,8 @@ static int __devinit e100_probe(struct pci_dev *pdev, (nic->eeprom[eeprom_id] & eeprom_id_wol)) nic->flags |= wol_magic; - pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic))); + /* ack any pending wake events, disable PME */ + pci_enable_wake(pdev, 0, 0); strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) { @@ -2408,6 +2411,8 @@ static int e100_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + /* ack any pending wake events, disable PME */ + pci_enable_wake(pdev, 0, 0); if(e100_hw_init(nic)) DPRINTK(HW, ERR, "e100_hw_init failed\n"); @@ -2419,6 +2424,21 @@ static int e100_resume(struct pci_dev *pdev) } #endif + +static void e100_shutdown(struct device *dev) +{ + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev_priv(netdev); + +#ifdef CONFIG_PM + pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic))); +#else + pci_enable_wake(pdev, 0, nic->flags & (wol_magic)); +#endif +} + + static struct pci_driver e100_driver = { .name = DRV_NAME, .id_table = e100_id_table, @@ -2428,6 +2448,11 @@ static struct pci_driver e100_driver = { .suspend = e100_suspend, .resume = e100_resume, #endif + + .driver = { + .shutdown = e100_shutdown, + } + }; static int __init e100_init_module(void) -- cgit v1.1 From 962082b6df11fe8cabafd2971b07c914cd52ee2a Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:19:46 -0700 Subject: [PATCH] e100: Performance optimizations to e100 Tx Path Performance optimizations to e100 Tx Path Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak --- drivers/net/e100.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index a43b825..fc2a401 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -777,7 +777,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) return 0; } -#define E100_WAIT_SCB_TIMEOUT 40 +#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) { unsigned long flags; @@ -847,6 +847,10 @@ static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb, * because the controller is too busy, so * let's just queue the command and try again * when another command is scheduled. */ + if(err == -ENOSPC) { + //request a reset + schedule_work(&nic->tx_timeout_task); + } break; } else { nic->cuc_cmd = cuc_resume; @@ -891,7 +895,7 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data) static void e100_get_defaults(struct nic *nic) { - struct param_range rfds = { .min = 64, .max = 256, .count = 64 }; + struct param_range rfds = { .min = 16, .max = 256, .count = 64 }; struct param_range cbs = { .min = 64, .max = 256, .count = 64 }; pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); @@ -906,8 +910,9 @@ static void e100_get_defaults(struct nic *nic) /* Quadwords to DMA into FIFO before starting frame transmit */ nic->tx_threshold = 0xE0; - nic->tx_command = cpu_to_le16(cb_tx | cb_i | cb_tx_sf | - ((nic->mac >= mac_82558_D101_A4) ? cb_cid : 0)); + /* no interrupt for every tx completion, delay = 256us if not 557*/ + nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf | + ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); /* Template for a freshly allocated RFD */ nic->blank_rfd.command = cpu_to_le16(cb_el); @@ -1289,12 +1294,15 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, struct sk_buff *skb) { cb->command = nic->tx_command; + /* interrupt every 16 packets regardless of delay */ + if((nic->cbs_avail & ~15) == nic->cbs_avail) cb->command |= cb_i; cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); cb->u.tcb.tcb_byte_count = 0; cb->u.tcb.threshold = nic->tx_threshold; cb->u.tcb.tbd_count = 1; cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, skb->data, skb->len, PCI_DMA_TODEVICE)); + // check for mapping failure? cb->u.tcb.tbd.size = cpu_to_le16(skb->len); } -- cgit v1.1 From 042e2fb70006f135469d546726451b7d14768980 Mon Sep 17 00:00:00 2001 From: Malli Chilakala Date: Thu, 28 Apr 2005 19:20:14 -0700 Subject: [PATCH] e100: Driver version, white space, comments, device id Driver version, white space, comments. Also enabled ICH-7 support Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Ganesh Venkatesan Signed-off-by: John Ronciak --- drivers/net/e100.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index fc2a401..4a47df5 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -155,9 +155,9 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.3.6-k2"DRV_EXT +#define DRV_VERSION "3.4.8-k2"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation" #define PFX DRV_NAME ": " #define E100_WATCHDOG_PERIOD (2 * HZ) @@ -210,11 +210,17 @@ static struct pci_device_id e100_id_table[] = { INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), + INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), + INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), + INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), + INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), + INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), { 0, } }; MODULE_DEVICE_TABLE(pci, e100_id_table); -- cgit v1.1 From 321de3c8cc12bdff073c23524aa1f6ed47cbeee4 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:17:46 +0200 Subject: [PATCH] s390: claw driver wiring [patch 1/10] s390: claw driver wiring. From: Andy Richter claw network driver changes: - Add an entry to the drivers/s390/net Makefile to build the claw driver. - Add claw channel type to cu3088. Signed-off-by: Frank Pavlic --- drivers/s390/net/Makefile | 1 + drivers/s390/net/cu3088.c | 4 +++- drivers/s390/net/cu3088.h | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 7cabb80..85b590c 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_LCS) += lcs.o cu3088.o +obj-$(CONFIG_CLAW) += claw.o cu3088.o qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o qeth-$(CONFIG_PROC_FS) += qeth_proc.o obj-$(CONFIG_QETH) += qeth.o diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index 1b0a9f1..0075894 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c @@ -1,5 +1,5 @@ /* - * $Id: cu3088.c,v 1.34 2004/06/15 13:16:27 pavlic Exp $ + * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $ * * CTC / LCS ccw_device driver * @@ -39,6 +39,7 @@ const char *cu3088_type[] = { "FICON channel", "P390 LCS card", "OSA LCS card", + "CLAW channel device", "unknown channel type", "unsupported channel type", }; @@ -51,6 +52,7 @@ static struct ccw_device_id cu3088_ids[] = { { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon }, { CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 }, { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 }, + { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw }, { /* end of list */ } }; diff --git a/drivers/s390/net/cu3088.h b/drivers/s390/net/cu3088.h index 0ec49a8..1753661 100644 --- a/drivers/s390/net/cu3088.h +++ b/drivers/s390/net/cu3088.h @@ -23,6 +23,9 @@ enum channel_types { /* Device is a OSA2 card */ channel_type_osa2, + /* Device is a CLAW channel device */ + channel_type_claw, + /* Device is a channel, but we don't know * anything about it */ channel_type_unknown, -- cgit v1.1 From 109a260b66bfbab7ba9f985495791af21f910218 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:19:44 +0200 Subject: [PATCH] s390: multicast address registration in lcs [patch 2/10] s390: multicast address registration in lcs. From: Michael Holzheu When setting lcs devices online you can run into an endless loop, because the code that registers the multicast addresses uses list_for_each_entry instead of list_for_each_entry_safe. Signed-off-by: Frank Pavlic --- drivers/s390/net/lcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 0f76e94..8d0262e 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.96 $ $Date: 2004/11/11 13:42:33 $ + * $Revision: 1.97 $ $Date: 2005/03/31 09:42:02 $ * * 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 @@ -59,7 +59,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.96 $" +#define VERSION_LCS_C "$Revision: 1.97 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char debug_buffer[255]; @@ -1160,7 +1160,7 @@ list_modified: } } /* re-insert all entries from the failed_list into ipm_list */ - list_for_each_entry(ipm, &failed_list, list) { + list_for_each_entry_safe(ipm, tmp, &failed_list, list) { list_del_init(&ipm->list); list_add_tail(&ipm->list, &card->ipm_list); } -- cgit v1.1 From b5f9d55b64a5c7193f8965c90ba62244ea3180b2 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:35:57 +0200 Subject: [PATCH] s390: set online race in the lcs driver [patch 3/10] s390: set online race in the lcs driver. From: Michael Holzheu There is a race between lcs_stopcard() and lcs_open_device() which can lead to the error 'lcs: Error in starting channel, rc=-16'. lcs_open_device() is invoked when 'ifconfig up' is called due to a hotplug event, which is caused by register_netdev(). In parallel lcs_stopcard() is executed. Both functions are sending lcs commands. The second invocation fails with -EBUSY (-16) as return value. Move invocation of register_netdev() after invocation of lcs_stopcard to avoid the race. Signed-off-by: Frank Pavlic --- drivers/s390/net/lcs.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 8d0262e..cccfed2 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.97 $ $Date: 2005/03/31 09:42:02 $ + * $Revision: 1.98 $ $Date: 2005/04/18 13:41:29 $ * * 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 @@ -59,7 +59,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.97 $" +#define VERSION_LCS_C "$Revision: 1.98 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char debug_buffer[255]; @@ -1098,14 +1098,6 @@ lcs_check_multicast_support(struct lcs_card *card) PRINT_ERR("Query IPAssist failed. Assuming unsupported!\n"); return -EOPNOTSUPP; } - /* Print out supported assists: IPv6 */ - PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name, - (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ? - "with" : "without"); - /* Print out supported assist: Multicast */ - PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name, - (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ? - "with" : "without"); if (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) return 0; return -EOPNOTSUPP; @@ -2198,30 +2190,39 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) if (!dev) goto out; card->dev = dev; -netdev_out: card->dev->priv = card; card->dev->open = lcs_open_device; card->dev->stop = lcs_stop_device; card->dev->hard_start_xmit = lcs_start_xmit; card->dev->get_stats = lcs_getstats; SET_MODULE_OWNER(dev); - if (lcs_register_netdev(ccwgdev) != 0) - goto out; memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH); #ifdef CONFIG_IP_MULTICAST if (!lcs_check_multicast_support(card)) card->dev->set_multicast_list = lcs_set_multicast_list; #endif - netif_stop_queue(card->dev); +netdev_out: lcs_set_allowed_threads(card,0xffffffff); if (recover_state == DEV_STATE_RECOVER) { lcs_set_multicast_list(card->dev); card->dev->flags |= IFF_UP; netif_wake_queue(card->dev); card->state = DEV_STATE_UP; - } else + } else { lcs_stopcard(card); + } + if (lcs_register_netdev(ccwgdev) != 0) + goto out; + + /* Print out supported assists: IPv6 */ + PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name, + (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ? + "with" : "without"); + /* Print out supported assist: Multicast */ + PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name, + (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ? + "with" : "without"); return 0; out: -- cgit v1.1 From 7f81947b46c3efacc084ac5033f3fed702e46532 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:36:22 +0200 Subject: [PATCH] s390: schedule_timeout cleanup in ctctty [patch 4/10] s390: schedule_timeout cleanup in ctctty. From: Domen Puncer Use msleep_interruptible() instead of schedule_timeout() to guarantee the task delays as expected. Signed-off-by: Nishanth Aravamudan Signed-off-by: Maximilian Attems Signed-off-by: Domen Puncer Signed-off-by: Frank Pavlic Acked-by: Martin Schwidefsky --- drivers/s390/net/ctctty.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 9257d60..3080393 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -1,5 +1,5 @@ /* - * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $ + * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $ * * CTC / ESCON network driver, tty interface. * @@ -1056,8 +1056,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp) info->tty = 0; tty->closing = 0; if (info->blocked_open) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); + msleep_interruptible(500); wake_up_interruptible(&info->open_wait); } info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING); -- cgit v1.1 From 7394c928c849fe2ea5c20b6d73cbe7f220810d94 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:36:47 +0200 Subject: [PATCH] s390: ctc code cleanup [patch 5/10] s390: ctc code cleanup. From: Peter Tiedemann ctc network driver changes: - Some code cleanup. Signed-off-by: Martin Schwidefsky --- drivers/s390/net/ctcdbug.h | 12 +- drivers/s390/net/ctcmain.c | 616 +++++++++++++++------------------------------ drivers/s390/net/ctcmain.h | 276 ++++++++++++++++++++ 3 files changed, 490 insertions(+), 414 deletions(-) create mode 100644 drivers/s390/net/ctcmain.h diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h index ef88839..7fe2ebd 100644 --- a/drivers/s390/net/ctcdbug.h +++ b/drivers/s390/net/ctcdbug.h @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $) + * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $) * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,7 +9,7 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $ + * $Revision: 1.5 $ $Date: 2005/02/27 19:46:44 $ * * 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 @@ -25,9 +25,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#ifndef _CTCDBUG_H_ +#define _CTCDBUG_H_ #include +#include "ctcmain.h" /** * Debug Facility stuff */ @@ -41,7 +43,7 @@ #define CTC_DBF_DATA_LEN 128 #define CTC_DBF_DATA_INDEX 3 #define CTC_DBF_DATA_NR_AREAS 1 -#define CTC_DBF_DATA_LEVEL 2 +#define CTC_DBF_DATA_LEVEL 3 #define CTC_DBF_TRACE_NAME "ctc_trace" #define CTC_DBF_TRACE_LEN 16 @@ -121,3 +123,5 @@ hex_dump(unsigned char *buf, size_t len) printk("\n"); } + +#endif diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 7266bf5..ff3e95e 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $ + * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $ * * CTC / ESCON network driver * @@ -37,12 +37,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $ * */ #undef DEBUG - #include #include #include @@ -74,288 +73,13 @@ #include "ctctty.h" #include "fsm.h" #include "cu3088.h" + #include "ctcdbug.h" +#include "ctcmain.h" MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)"); MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver"); MODULE_LICENSE("GPL"); - -/** - * CCW commands, used in this driver. - */ -#define CCW_CMD_WRITE 0x01 -#define CCW_CMD_READ 0x02 -#define CCW_CMD_SET_EXTENDED 0xc3 -#define CCW_CMD_PREPARE 0xe3 - -#define CTC_PROTO_S390 0 -#define CTC_PROTO_LINUX 1 -#define CTC_PROTO_LINUX_TTY 2 -#define CTC_PROTO_OS390 3 -#define CTC_PROTO_MAX 3 - -#define CTC_BUFSIZE_LIMIT 65535 -#define CTC_BUFSIZE_DEFAULT 32768 - -#define CTC_TIMEOUT_5SEC 5000 - -#define CTC_INITIAL_BLOCKLEN 2 - -#define READ 0 -#define WRITE 1 - -#define CTC_ID_SIZE BUS_ID_SIZE+3 - - -struct ctc_profile { - unsigned long maxmulti; - unsigned long maxcqueue; - unsigned long doios_single; - unsigned long doios_multi; - unsigned long txlen; - unsigned long tx_time; - struct timespec send_stamp; -}; - -/** - * Definition of one channel - */ -struct channel { - - /** - * Pointer to next channel in list. - */ - struct channel *next; - char id[CTC_ID_SIZE]; - struct ccw_device *cdev; - - /** - * Type of this channel. - * CTC/A or Escon for valid channels. - */ - enum channel_types type; - - /** - * Misc. flags. See CHANNEL_FLAGS_... below - */ - __u32 flags; - - /** - * The protocol of this channel - */ - __u16 protocol; - - /** - * I/O and irq related stuff - */ - struct ccw1 *ccw; - struct irb *irb; - - /** - * RX/TX buffer size - */ - int max_bufsize; - - /** - * Transmit/Receive buffer. - */ - struct sk_buff *trans_skb; - - /** - * Universal I/O queue. - */ - struct sk_buff_head io_queue; - - /** - * TX queue for collecting skb's during busy. - */ - struct sk_buff_head collect_queue; - - /** - * Amount of data in collect_queue. - */ - int collect_len; - - /** - * spinlock for collect_queue and collect_len - */ - spinlock_t collect_lock; - - /** - * Timer for detecting unresposive - * I/O operations. - */ - fsm_timer timer; - - /** - * Retry counter for misc. operations. - */ - int retry; - - /** - * The finite state machine of this channel - */ - fsm_instance *fsm; - - /** - * The corresponding net_device this channel - * belongs to. - */ - struct net_device *netdev; - - struct ctc_profile prof; - - unsigned char *trans_skb_data; - - __u16 logflags; -}; - -#define CHANNEL_FLAGS_READ 0 -#define CHANNEL_FLAGS_WRITE 1 -#define CHANNEL_FLAGS_INUSE 2 -#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4 -#define CHANNEL_FLAGS_FAILED 8 -#define CHANNEL_FLAGS_WAITIRQ 16 -#define CHANNEL_FLAGS_RWMASK 1 -#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK) - -#define LOG_FLAG_ILLEGALPKT 1 -#define LOG_FLAG_ILLEGALSIZE 2 -#define LOG_FLAG_OVERRUN 4 -#define LOG_FLAG_NOMEM 8 - -#define CTC_LOGLEVEL_INFO 1 -#define CTC_LOGLEVEL_NOTICE 2 -#define CTC_LOGLEVEL_WARN 4 -#define CTC_LOGLEVEL_EMERG 8 -#define CTC_LOGLEVEL_ERR 16 -#define CTC_LOGLEVEL_DEBUG 32 -#define CTC_LOGLEVEL_CRIT 64 - -#define CTC_LOGLEVEL_DEFAULT \ -(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT) - -#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1) - -static int loglevel = CTC_LOGLEVEL_DEFAULT; - -#define ctc_pr_debug(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0) - -#define ctc_pr_info(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0) - -#define ctc_pr_notice(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0) - -#define ctc_pr_warn(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0) - -#define ctc_pr_emerg(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0) - -#define ctc_pr_err(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0) - -#define ctc_pr_crit(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0) - -/** - * Linked list of all detected channels. - */ -static struct channel *channels = NULL; - -struct ctc_priv { - struct net_device_stats stats; - unsigned long tbusy; - /** - * The finite state machine of this interface. - */ - fsm_instance *fsm; - /** - * The protocol of this device - */ - __u16 protocol; - /** - * Timer for restarting after I/O Errors - */ - fsm_timer restart_timer; - - int buffer_size; - - struct channel *channel[2]; -}; - -/** - * Definition of our link level header. - */ -struct ll_header { - __u16 length; - __u16 type; - __u16 unused; -}; -#define LL_HEADER_LENGTH (sizeof(struct ll_header)) - -/** - * Compatibility macros for busy handling - * of network devices. - */ -static __inline__ void -ctc_clear_busy(struct net_device * dev) -{ - clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_wake_queue(dev); -} - -static __inline__ int -ctc_test_and_set_busy(struct net_device * dev) -{ - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_stop_queue(dev); - return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); -} - -/** - * Print Banner. - */ -static void -print_banner(void) -{ - static int printed = 0; - char vbuf[] = "$Revision: 1.72 $"; - char *version = vbuf; - - if (printed) - return; - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - printk(KERN_INFO "CTC driver Version%s" -#ifdef DEBUG - " (DEBUG-VERSION, " __DATE__ __TIME__ ")" -#endif - " initialized\n", version); - printed = 1; -} - -/** - * Return type of a detected device. - */ -static enum channel_types -get_channel_type(struct ccw_device_id *id) -{ - enum channel_types type = (enum channel_types) id->driver_info; - - if (type == channel_type_ficon) - type = channel_type_escon; - - return type; -} - /** * States of the interface statemachine. */ @@ -371,7 +95,7 @@ enum dev_states { /** * MUST be always the last element!! */ - NR_DEV_STATES + CTC_NR_DEV_STATES }; static const char *dev_state_names[] = { @@ -399,7 +123,7 @@ enum dev_events { /** * MUST be always the last element!! */ - NR_DEV_EVENTS + CTC_NR_DEV_EVENTS }; static const char *dev_event_names[] = { @@ -476,40 +200,6 @@ enum ch_events { NR_CH_EVENTS, }; -static const char *ch_event_names[] = { - "ccw_device success", - "ccw_device busy", - "ccw_device enodev", - "ccw_device ioerr", - "ccw_device unknown", - - "Status ATTN & BUSY", - "Status ATTN", - "Status BUSY", - - "Unit check remote reset", - "Unit check remote system reset", - "Unit check TX timeout", - "Unit check TX parity", - "Unit check Hardware failure", - "Unit check RX parity", - "Unit check ZERO", - "Unit check Unknown", - - "SubChannel check Unknown", - - "Machine check failure", - "Machine check operational", - - "IRQ normal", - "IRQ final", - - "Timer", - - "Start", - "Stop", -}; - /** * States of the channel statemachine. */ @@ -545,6 +235,87 @@ enum ch_states { NR_CH_STATES, }; +static int loglevel = CTC_LOGLEVEL_DEFAULT; + +/** + * Linked list of all detected channels. + */ +static struct channel *channels = NULL; + +/** + * Print Banner. + */ +static void +print_banner(void) +{ + static int printed = 0; + char vbuf[] = "$Revision: 1.74 $"; + char *version = vbuf; + + if (printed) + return; + if ((version = strchr(version, ':'))) { + char *p = strchr(version + 1, '$'); + if (p) + *p = '\0'; + } else + version = " ??? "; + printk(KERN_INFO "CTC driver Version%s" +#ifdef DEBUG + " (DEBUG-VERSION, " __DATE__ __TIME__ ")" +#endif + " initialized\n", version); + printed = 1; +} + +/** + * Return type of a detected device. + */ +static enum channel_types +get_channel_type(struct ccw_device_id *id) +{ + enum channel_types type = (enum channel_types) id->driver_info; + + if (type == channel_type_ficon) + type = channel_type_escon; + + return type; +} + +static const char *ch_event_names[] = { + "ccw_device success", + "ccw_device busy", + "ccw_device enodev", + "ccw_device ioerr", + "ccw_device unknown", + + "Status ATTN & BUSY", + "Status ATTN", + "Status BUSY", + + "Unit check remote reset", + "Unit check remote system reset", + "Unit check TX timeout", + "Unit check TX parity", + "Unit check Hardware failure", + "Unit check RX parity", + "Unit check ZERO", + "Unit check Unknown", + + "SubChannel check Unknown", + + "Machine check failure", + "Machine check operational", + + "IRQ normal", + "IRQ final", + + "Timer", + + "Start", + "Stop", +}; + static const char *ch_state_names[] = { "Idle", "Stopped", @@ -1934,7 +1705,6 @@ add_channel(struct ccw_device *cdev, enum channel_types type) ch->cdev = cdev; snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id); ch->type = type; - loglevel = CTC_LOGLEVEL_DEFAULT; ch->fsm = init_fsm(ch->id, ch_state_names, ch_event_names, NR_CH_STATES, NR_CH_EVENTS, ch_fsm, CH_FSM_LEN, GFP_KERNEL); @@ -2697,6 +2467,7 @@ ctc_stats(struct net_device * dev) /* * sysfs attributes */ + static ssize_t buffer_show(struct device *dev, char *buf) { @@ -2715,57 +2486,61 @@ buffer_write(struct device *dev, const char *buf, size_t count) struct ctc_priv *priv; struct net_device *ndev; int bs1; + char buffer[16]; DBF_TEXT(trace, 3, __FUNCTION__); + DBF_TEXT(trace, 3, buf); priv = dev->driver_data; - if (!priv) + if (!priv) { + DBF_TEXT(trace, 3, "bfnopriv"); return -ENODEV; + } + + sscanf(buf, "%u", &bs1); + if (bs1 > CTC_BUFSIZE_LIMIT) + goto einval; + if (bs1 < (576 + LL_HEADER_LENGTH + 2)) + goto einval; + priv->buffer_size = bs1; // just to overwrite the default + ndev = priv->channel[READ]->netdev; - if (!ndev) + if (!ndev) { + DBF_TEXT(trace, 3, "bfnondev"); return -ENODEV; - sscanf(buf, "%u", &bs1); + } - if (bs1 > CTC_BUFSIZE_LIMIT) - return -EINVAL; if ((ndev->flags & IFF_RUNNING) && (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2))) - return -EINVAL; - if (bs1 < (576 + LL_HEADER_LENGTH + 2)) - return -EINVAL; + goto einval; - priv->buffer_size = bs1; - priv->channel[READ]->max_bufsize = - priv->channel[WRITE]->max_bufsize = bs1; + priv->channel[READ]->max_bufsize = bs1; + priv->channel[WRITE]->max_bufsize = bs1; if (!(ndev->flags & IFF_RUNNING)) ndev->mtu = bs1 - LL_HEADER_LENGTH - 2; priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; + sprintf(buffer, "%d",priv->buffer_size); + DBF_TEXT(trace, 3, buffer); return count; +einval: + DBF_TEXT(trace, 3, "buff_err"); + return -EINVAL; } static ssize_t loglevel_show(struct device *dev, char *buf) { - struct ctc_priv *priv; - - priv = dev->driver_data; - if (!priv) - return -ENODEV; return sprintf(buf, "%d\n", loglevel); } static ssize_t loglevel_write(struct device *dev, const char *buf, size_t count) { - struct ctc_priv *priv; int ll1; DBF_TEXT(trace, 5, __FUNCTION__); - priv = dev->driver_data; - if (!priv) - return -ENODEV; sscanf(buf, "%i", &ll1); if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0)) @@ -2835,27 +2610,6 @@ stats_write(struct device *dev, const char *buf, size_t count) return count; } -static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); -static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write); -static DEVICE_ATTR(stats, 0644, stats_show, stats_write); - -static int -ctc_add_attributes(struct device *dev) -{ -// device_create_file(dev, &dev_attr_buffer); - device_create_file(dev, &dev_attr_loglevel); - device_create_file(dev, &dev_attr_stats); - return 0; -} - -static void -ctc_remove_attributes(struct device *dev) -{ - device_remove_file(dev, &dev_attr_stats); - device_remove_file(dev, &dev_attr_loglevel); -// device_remove_file(dev, &dev_attr_buffer); -} - static void ctc_netdev_unregister(struct net_device * dev) @@ -2899,52 +2653,6 @@ ctc_free_netdevice(struct net_device * dev, int free_dev) #endif } -/** - * Initialize everything of the net device except the name and the - * channel structs. - */ -static struct net_device * -ctc_init_netdevice(struct net_device * dev, int alloc_device, - struct ctc_priv *privptr) -{ - if (!privptr) - return NULL; - - DBF_TEXT(setup, 3, __FUNCTION__); - if (alloc_device) { - dev = kmalloc(sizeof (struct net_device), GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, sizeof (struct net_device)); - } - - dev->priv = privptr; - privptr->fsm = init_fsm("ctcdev", dev_state_names, - dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS, - dev_fsm, DEV_FSM_LEN, GFP_KERNEL); - if (privptr->fsm == NULL) { - if (alloc_device) - kfree(dev); - return NULL; - } - fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); - fsm_settimer(privptr->fsm, &privptr->restart_timer); - if (dev->mtu == 0) - dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; - dev->hard_start_xmit = ctc_tx; - dev->open = ctc_open; - dev->stop = ctc_close; - dev->get_stats = ctc_stats; - dev->change_mtu = ctc_change_mtu; - dev->hard_header_len = LL_HEADER_LENGTH + 2; - dev->addr_len = 0; - dev->type = ARPHRD_SLIP; - dev->tx_queue_len = 100; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - SET_MODULE_OWNER(dev); - return dev; -} - static ssize_t ctc_proto_show(struct device *dev, char *buf) { @@ -2977,7 +2685,6 @@ ctc_proto_store(struct device *dev, const char *buf, size_t count) return count; } -static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store); static ssize_t ctc_type_show(struct device *dev, char *buf) @@ -2991,8 +2698,13 @@ ctc_type_show(struct device *dev, char *buf) return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]); } +static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); +static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store); static DEVICE_ATTR(type, 0444, ctc_type_show, NULL); +static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write); +static DEVICE_ATTR(stats, 0644, stats_show, stats_write); + static struct attribute *ctc_attr[] = { &dev_attr_protocol.attr, &dev_attr_type.attr, @@ -3005,6 +2717,21 @@ static struct attribute_group ctc_attr_group = { }; static int +ctc_add_attributes(struct device *dev) +{ + device_create_file(dev, &dev_attr_loglevel); + device_create_file(dev, &dev_attr_stats); + return 0; +} + +static void +ctc_remove_attributes(struct device *dev) +{ + device_remove_file(dev, &dev_attr_stats); + device_remove_file(dev, &dev_attr_loglevel); +} + +static int ctc_add_files(struct device *dev) { pr_debug("%s() called\n", __FUNCTION__); @@ -3028,15 +2755,15 @@ ctc_remove_files(struct device *dev) * * @returns 0 on success, !0 on failure. */ - static int ctc_probe_device(struct ccwgroup_device *cgdev) { struct ctc_priv *priv; int rc; + char buffer[16]; pr_debug("%s() called\n", __FUNCTION__); - DBF_TEXT(trace, 3, __FUNCTION__); + DBF_TEXT(setup, 3, __FUNCTION__); if (!get_device(&cgdev->dev)) return -ENODEV; @@ -3060,10 +2787,70 @@ ctc_probe_device(struct ccwgroup_device *cgdev) cgdev->cdev[1]->handler = ctc_irq_handler; cgdev->dev.driver_data = priv; + sprintf(buffer, "%p", priv); + DBF_TEXT(data, 3, buffer); + + sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv)); + DBF_TEXT(data, 3, buffer); + + sprintf(buffer, "%p", &channels); + DBF_TEXT(data, 3, buffer); + + sprintf(buffer, "%u", (unsigned int)sizeof(struct channel)); + DBF_TEXT(data, 3, buffer); + return 0; } /** + * Initialize everything of the net device except the name and the + * channel structs. + */ +static struct net_device * +ctc_init_netdevice(struct net_device * dev, int alloc_device, + struct ctc_priv *privptr) +{ + if (!privptr) + return NULL; + + DBF_TEXT(setup, 3, __FUNCTION__); + + if (alloc_device) { + dev = kmalloc(sizeof (struct net_device), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof (struct net_device)); + } + + dev->priv = privptr; + privptr->fsm = init_fsm("ctcdev", dev_state_names, + dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS, + dev_fsm, DEV_FSM_LEN, GFP_KERNEL); + if (privptr->fsm == NULL) { + if (alloc_device) + kfree(dev); + return NULL; + } + fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); + fsm_settimer(privptr->fsm, &privptr->restart_timer); + if (dev->mtu == 0) + dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; + dev->hard_start_xmit = ctc_tx; + dev->open = ctc_open; + dev->stop = ctc_close; + dev->get_stats = ctc_stats; + dev->change_mtu = ctc_change_mtu; + dev->hard_header_len = LL_HEADER_LENGTH + 2; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; + dev->tx_queue_len = 100; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + SET_MODULE_OWNER(dev); + return dev; +} + + +/** * * Setup an interface. * @@ -3081,6 +2868,7 @@ ctc_new_device(struct ccwgroup_device *cgdev) struct ctc_priv *privptr; struct net_device *dev; int ret; + char buffer[16]; pr_debug("%s() called\n", __FUNCTION__); DBF_TEXT(setup, 3, __FUNCTION__); @@ -3089,6 +2877,9 @@ ctc_new_device(struct ccwgroup_device *cgdev) if (!privptr) return -ENODEV; + sprintf(buffer, "%d", privptr->buffer_size); + DBF_TEXT(setup, 3, buffer); + type = get_channel_type(&cgdev->cdev[0]->id); snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id); @@ -3177,9 +2968,10 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev) struct ctc_priv *priv; struct net_device *ndev; - DBF_TEXT(trace, 3, __FUNCTION__); + DBF_TEXT(setup, 3, __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__); + priv = cgdev->dev.driver_data; ndev = NULL; if (!priv) @@ -3215,7 +3007,6 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev) channel_remove(priv->channel[READ]); if (priv->channel[WRITE]) channel_remove(priv->channel[WRITE]); - priv->channel[READ] = priv->channel[WRITE] = NULL; return 0; @@ -3228,7 +3019,7 @@ ctc_remove_device(struct ccwgroup_device *cgdev) struct ctc_priv *priv; pr_debug("%s() called\n", __FUNCTION__); - DBF_TEXT(trace, 3, __FUNCTION__); + DBF_TEXT(setup, 3, __FUNCTION__); priv = cgdev->dev.driver_data; if (!priv) @@ -3265,6 +3056,7 @@ static struct ccwgroup_driver ctc_group_driver = { static void __exit ctc_exit(void) { + DBF_TEXT(setup, 3, __FUNCTION__); unregister_cu3088_discipline(&ctc_group_driver); ctc_tty_cleanup(); ctc_unregister_dbf_views(); @@ -3282,6 +3074,10 @@ ctc_init(void) { int ret = 0; + loglevel = CTC_LOGLEVEL_DEFAULT; + + DBF_TEXT(setup, 3, __FUNCTION__); + print_banner(); ret = ctc_register_dbf_views(); diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h new file mode 100644 index 0000000..ba3605f --- /dev/null +++ b/drivers/s390/net/ctcmain.h @@ -0,0 +1,276 @@ +/* + * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $ + * + * CTC / ESCON network driver + * + * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) + Peter Tiedemann (ptiedem@de.ibm.com) + * + * + * Documentation used: + * - Principles of Operation (IBM doc#: SA22-7201-06) + * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02) + * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535) + * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00) + * - ESCON I/O Interface (IBM doc#: SA22-7202-029 + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $ + * + */ + +#ifndef _CTCMAIN_H_ +#define _CTCMAIN_H_ + +#include +#include + +#include "ctctty.h" +#include "fsm.h" +#include "cu3088.h" + + +/** + * CCW commands, used in this driver. + */ +#define CCW_CMD_WRITE 0x01 +#define CCW_CMD_READ 0x02 +#define CCW_CMD_SET_EXTENDED 0xc3 +#define CCW_CMD_PREPARE 0xe3 + +#define CTC_PROTO_S390 0 +#define CTC_PROTO_LINUX 1 +#define CTC_PROTO_LINUX_TTY 2 +#define CTC_PROTO_OS390 3 +#define CTC_PROTO_MAX 3 + +#define CTC_BUFSIZE_LIMIT 65535 +#define CTC_BUFSIZE_DEFAULT 32768 + +#define CTC_TIMEOUT_5SEC 5000 + +#define CTC_INITIAL_BLOCKLEN 2 + +#define READ 0 +#define WRITE 1 + +#define CTC_ID_SIZE BUS_ID_SIZE+3 + + +struct ctc_profile { + unsigned long maxmulti; + unsigned long maxcqueue; + unsigned long doios_single; + unsigned long doios_multi; + unsigned long txlen; + unsigned long tx_time; + struct timespec send_stamp; +}; + +/** + * Definition of one channel + */ +struct channel { + + /** + * Pointer to next channel in list. + */ + struct channel *next; + char id[CTC_ID_SIZE]; + struct ccw_device *cdev; + + /** + * Type of this channel. + * CTC/A or Escon for valid channels. + */ + enum channel_types type; + + /** + * Misc. flags. See CHANNEL_FLAGS_... below + */ + __u32 flags; + + /** + * The protocol of this channel + */ + __u16 protocol; + + /** + * I/O and irq related stuff + */ + struct ccw1 *ccw; + struct irb *irb; + + /** + * RX/TX buffer size + */ + int max_bufsize; + + /** + * Transmit/Receive buffer. + */ + struct sk_buff *trans_skb; + + /** + * Universal I/O queue. + */ + struct sk_buff_head io_queue; + + /** + * TX queue for collecting skb's during busy. + */ + struct sk_buff_head collect_queue; + + /** + * Amount of data in collect_queue. + */ + int collect_len; + + /** + * spinlock for collect_queue and collect_len + */ + spinlock_t collect_lock; + + /** + * Timer for detecting unresposive + * I/O operations. + */ + fsm_timer timer; + + /** + * Retry counter for misc. operations. + */ + int retry; + + /** + * The finite state machine of this channel + */ + fsm_instance *fsm; + + /** + * The corresponding net_device this channel + * belongs to. + */ + struct net_device *netdev; + + struct ctc_profile prof; + + unsigned char *trans_skb_data; + + __u16 logflags; +}; + +#define CHANNEL_FLAGS_READ 0 +#define CHANNEL_FLAGS_WRITE 1 +#define CHANNEL_FLAGS_INUSE 2 +#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4 +#define CHANNEL_FLAGS_FAILED 8 +#define CHANNEL_FLAGS_WAITIRQ 16 +#define CHANNEL_FLAGS_RWMASK 1 +#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK) + +#define LOG_FLAG_ILLEGALPKT 1 +#define LOG_FLAG_ILLEGALSIZE 2 +#define LOG_FLAG_OVERRUN 4 +#define LOG_FLAG_NOMEM 8 + +#define CTC_LOGLEVEL_INFO 1 +#define CTC_LOGLEVEL_NOTICE 2 +#define CTC_LOGLEVEL_WARN 4 +#define CTC_LOGLEVEL_EMERG 8 +#define CTC_LOGLEVEL_ERR 16 +#define CTC_LOGLEVEL_DEBUG 32 +#define CTC_LOGLEVEL_CRIT 64 + +#define CTC_LOGLEVEL_DEFAULT \ +(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT) + +#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1) + +#define ctc_pr_debug(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0) + +#define ctc_pr_info(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0) + +#define ctc_pr_notice(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0) + +#define ctc_pr_warn(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0) + +#define ctc_pr_emerg(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0) + +#define ctc_pr_err(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0) + +#define ctc_pr_crit(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0) + +struct ctc_priv { + struct net_device_stats stats; + unsigned long tbusy; + /** + * The finite state machine of this interface. + */ + fsm_instance *fsm; + /** + * The protocol of this device + */ + __u16 protocol; + /** + * Timer for restarting after I/O Errors + */ + fsm_timer restart_timer; + + int buffer_size; + + struct channel *channel[2]; +}; + +/** + * Definition of our link level header. + */ +struct ll_header { + __u16 length; + __u16 type; + __u16 unused; +}; +#define LL_HEADER_LENGTH (sizeof(struct ll_header)) + +/** + * Compatibility macros for busy handling + * of network devices. + */ +static __inline__ void +ctc_clear_busy(struct net_device * dev) +{ + clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); + if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) + netif_wake_queue(dev); +} + +static __inline__ int +ctc_test_and_set_busy(struct net_device * dev) +{ + if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) + netif_stop_queue(dev); + return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); +} + +#endif -- cgit v1.1 From 5e39f2933f6707fc824b5e419dcac8ced67a57b6 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:37:00 +0200 Subject: [PATCH] s390: enable iucv_send2way_xxx functions [patch 6/10] s390: enable iucv_send2way_xxx functions. From: Ursula Braun-Krahl The SSL-Server of z/VM wants to use the iucv_send2way and iucv_send2way_array function. Enable them again. Signed-off-by: Frank Pavlic --- drivers/s390/net/iucv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index 1ac6563..e08e74e 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu Exp $ + * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $ * */ @@ -355,7 +355,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.43 $"; + char vbuf[] = "$Revision: 1.45 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -2553,12 +2553,12 @@ EXPORT_SYMBOL (iucv_resume); #endif EXPORT_SYMBOL (iucv_reply_prmmsg); EXPORT_SYMBOL (iucv_send); -#if 0 EXPORT_SYMBOL (iucv_send2way); EXPORT_SYMBOL (iucv_send2way_array); -EXPORT_SYMBOL (iucv_send_array); EXPORT_SYMBOL (iucv_send2way_prmmsg); EXPORT_SYMBOL (iucv_send2way_prmmsg_array); +#if 0 +EXPORT_SYMBOL (iucv_send_array); EXPORT_SYMBOL (iucv_send_prmmsg); EXPORT_SYMBOL (iucv_setmask); #endif -- cgit v1.1 From d801145d910cc4a0fb418dda1dee227cec993cbd Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:37:53 +0200 Subject: [PATCH] s390: qeth bug fixes [patch 7/10] s390: qeth bug fixes. From: Frank Pavlic qeth network driver changes: - Removed redundant code, use the same qeth_fill_buffer_frag for TSO path either - Using skb->frags solely is not correct since skb->data still points to the beginning of the whole data, even when it is a small portion we have to fill the qdio buffer with it. Signed-off-by: Frank Pavlic --- drivers/s390/net/qeth.h | 13 +++++++- drivers/s390/net/qeth_eddp.c | 15 ++-------- drivers/s390/net/qeth_main.c | 49 +++--------------------------- drivers/s390/net/qeth_tso.c | 49 +++++++----------------------- drivers/s390/net/qeth_tso.h | 71 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 86 insertions(+), 111 deletions(-) diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index a341041..501b87e 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.135 $" +#define VERSION_QETH_H "$Revision: 1.136 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -866,6 +866,17 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) return hdr; } +static inline int +qeth_get_skb_data_len(struct sk_buff *skb) +{ + int len = skb->len; + int i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) + len -= skb_shinfo(skb)->frags[i].size; + return len; +} + inline static int qeth_get_hlen(__u8 link_type) { diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 7ee1c06..45aa4a9 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $) + * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.12 $) * * Enhanced Device Driver Packing (EDDP) support for the qeth driver. * @@ -8,7 +8,7 @@ * * Author(s): Thomas Spatzier * - * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $ + * $Revision: 1.12 $ $Date: 2005/04/01 21:40:40 $ * */ #include @@ -202,17 +202,6 @@ out: return flush_cnt; } -static inline int -qeth_get_skb_data_len(struct sk_buff *skb) -{ - int len = skb->len; - int i; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) - len -= skb_shinfo(skb)->frags[i].size; - return len; -} - static inline void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, struct qeth_eddp_data *eddp) diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 607b925..17e8d16 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.207 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $ + * $Revision: 1.207 $ $Date: 2005/04/01 21:40:40 $ * * 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 @@ -80,7 +80,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.206 $" +#define VERSION_QETH_C "$Revision: 1.207 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -3894,47 +3894,6 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } static inline void -__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer, - int *next_element_to_fill) -{ - int length = skb->len; - struct skb_frag_struct *frag; - int fragno; - unsigned long addr; - int element; - int first_lap = 1; - - fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */ - element = *next_element_to_fill + fragno; - while (length > 0) { - if (fragno > 0) { - frag = &skb_shinfo(skb)->frags[fragno - 1]; - addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + - frag->page_offset; - buffer->element[element].addr = (char *)addr; - buffer->element[element].length = frag->size; - length -= frag->size; - if (first_lap) - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - } else { - buffer->element[element].addr = skb->data; - buffer->element[element].length = length; - length = 0; - buffer->element[element].flags = - SBAL_FLAGS_FIRST_FRAG; - } - element--; - fragno--; - first_lap = 0; - } - *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1; -} - -static inline void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, int *next_element_to_fill) { @@ -3991,7 +3950,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, __qeth_fill_buffer(skb, buffer, (int *)&buf->next_element_to_fill); else - __qeth_fill_buffer_frag(skb, buffer, + __qeth_fill_buffer_frag(skb, buffer, 0, (int *)&buf->next_element_to_fill); if (!queue->do_pack) { diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c index c919762..4e58f19 100644 --- a/drivers/s390/net/qeth_tso.c +++ b/drivers/s390/net/qeth_tso.c @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $) + * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.7 $) * * Header file for qeth TCP Segmentation Offload support. * @@ -7,7 +7,7 @@ * * Author(s): Frank Pavlic * - * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $ + * $Revision: 1.7 $ $Date: 2005/04/01 21:40:41 $ * */ @@ -144,38 +144,6 @@ qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue) return flush_cnt; } -static inline void -__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf, - struct sk_buff *skb) -{ - struct skb_frag_struct *frag; - struct qdio_buffer *buffer; - int fragno, cnt, element; - unsigned long addr; - - QETH_DBF_TEXT(trace, 6, "tsfilfrg"); - - /*initialize variables ...*/ - fragno = skb_shinfo(skb)->nr_frags; - buffer = buf->buffer; - element = buf->next_element_to_fill; - /*fill buffer elements .....*/ - for (cnt = 0; cnt < fragno; cnt++) { - frag = &skb_shinfo(skb)->frags[cnt]; - addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + - frag->page_offset; - buffer->element[element].addr = (char *)addr; - buffer->element[element].length = frag->size; - if (cnt < (fragno - 1)) - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - element++; - } - buf->next_element_to_fill = element; -} static inline int qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, @@ -205,19 +173,22 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, buffer->element[element].length = hdr_len; buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; buf->next_element_to_fill++; - + /*check if we have frags ...*/ if (skb_shinfo(skb)->nr_frags > 0) { - __qeth_tso_fill_buffer_frag(buf, skb); + skb->len = length; + skb->data = data; + __qeth_fill_buffer_frag(skb, buffer,1, + (int *)&buf->next_element_to_fill); goto out; } - /*start filling buffer entries ...*/ + /*... if not, use this */ element++; while (length > 0) { /* length_here is the remaining amount of data in this page */ length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); if (length < length_here) - length_here = length; + length_here = length; buffer->element[element].addr = data; buffer->element[element].length = length_here; length -= length_here; @@ -230,9 +201,9 @@ qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, data += length_here; element++; } - /*set the buffer to primed ...*/ buf->next_element_to_fill = element; out: + /*prime buffer now ...*/ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); return 1; } diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 83504de..ff585ae 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $) + * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.5 $) * * Header file for qeth TCP Segmentation Offload support. * @@ -7,7 +7,7 @@ * * Author(s): Frank Pavlic * - * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $ + * $Revision: 1.5 $ $Date: 2005/04/01 21:40:41 $ * */ #ifndef __QETH_TSO_H__ @@ -37,22 +37,67 @@ struct qeth_hdr_tso { } __attribute__ ((packed)); /*some helper functions*/ - static inline int qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) { int elements_needed = 0; - if (skb_shinfo(skb)->nr_frags > 0) - elements_needed = (skb_shinfo(skb)->nr_frags + 1); - if (elements_needed == 0 ) - elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) - + skb->len) >> PAGE_SHIFT); - if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ - PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet. Discarded."); - return 0; + if (skb_shinfo(skb)->nr_frags > 0) + elements_needed = (skb_shinfo(skb)->nr_frags + 1); + if (elements_needed == 0 ) + elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + + skb->len) >> PAGE_SHIFT); + if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ + PRINT_ERR("qeth_do_send_packet: invalid size of " + "IP packet. Discarded."); + return 0; + } + return elements_needed; +} + +static inline void +__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer, + int is_tso, int *next_element_to_fill) +{ + int length = skb->len; + struct skb_frag_struct *frag; + int fragno; + unsigned long addr; + int element; + int first_lap = 1; + + fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */ + element = *next_element_to_fill + fragno; + while (length > 0) { + if (fragno > 0) { + frag = &skb_shinfo(skb)->frags[fragno - 1]; + addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + + frag->page_offset; + buffer->element[element].addr = (char *)addr; + buffer->element[element].length = frag->size; + length -= frag->size; + if (first_lap) + buffer->element[element].flags = + SBAL_FLAGS_LAST_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + } else { + buffer->element[element].addr = skb->data; + buffer->element[element].length = length; + length = 0; + if (is_tso) + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_FIRST_FRAG; + } + element--; + fragno--; + first_lap = 0; } - return elements_needed; + *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1; } + #endif /* __QETH_TSO_H__ */ -- cgit v1.1 From e23dd9cdd676323c95fab47dc55123ba18f7e1ff Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:38:11 +0200 Subject: [PATCH] s390: fakell for high speed token ring [patch 8/10] s390: fakell for high speed token ring. From: Michael Holzheu Implement fake-link-layer for high speed token ring. Without it token ring packages get leading ethernet headers, which confuses dhcp. Signed-off-by: Frank Pavlic --- drivers/s390/net/qeth.h | 5 +- drivers/s390/net/qeth_main.c | 136 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 114 insertions(+), 27 deletions(-) diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 501b87e..d13c105 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.136 $" +#define VERSION_QETH_H "$Revision: 1.137 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -288,7 +288,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) #define QETH_TX_TIMEOUT 100 * HZ #define QETH_HEADER_SIZE 32 #define MAX_PORTNO 15 -#define QETH_FAKE_LL_LEN ETH_HLEN +#define QETH_FAKE_LL_LEN_ETH ETH_HLEN +#define QETH_FAKE_LL_LEN_TR (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc)) #define QETH_FAKE_LL_V6_ADDR_POS 24 /*IPv6 address autoconfiguration stuff*/ diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 17e8d16..2afe515 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.207 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.209 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.207 $ $Date: 2005/04/01 21:40:40 $ + * $Revision: 1.209 $ $Date: 2005/04/18 11:58:48 $ * * 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 @@ -80,7 +80,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.207 $" +#define VERSION_QETH_C "$Revision: 1.209 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -2152,9 +2152,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, if (!skb_len) return NULL; if (card->options.fake_ll){ - if (!(skb = qeth_get_skb(skb_len + QETH_FAKE_LL_LEN))) - goto no_mem; - skb_pull(skb, QETH_FAKE_LL_LEN); + if(card->dev->type == ARPHRD_IEEE802_TR){ + if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR))) + goto no_mem; + skb_reserve(skb,QETH_FAKE_LL_LEN_TR); + } else { + if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH))) + goto no_mem; + skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); + } } else if (!(skb = qeth_get_skb(skb_len))) goto no_mem; data_ptr = element->addr + offset; @@ -2229,14 +2235,68 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev) } static inline void -qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, +qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, + struct qeth_hdr *hdr) +{ + struct trh_hdr *fake_hdr; + struct trllc *fake_llc; + struct iphdr *ip_hdr; + + QETH_DBF_TEXT(trace,5,"skbfktr"); + skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR; + /* this is a fake ethernet header */ + fake_hdr = (struct trh_hdr *) skb->mac.raw; + + /* the destination MAC address */ + switch (skb->pkt_type){ + case PACKET_MULTICAST: + switch (skb->protocol){ +#ifdef CONFIG_QETH_IPV6 + case __constant_htons(ETH_P_IPV6): + ndisc_mc_map((struct in6_addr *) + skb->data + QETH_FAKE_LL_V6_ADDR_POS, + fake_hdr->daddr, card->dev, 0); + break; +#endif /* CONFIG_QETH_IPV6 */ + case __constant_htons(ETH_P_IP): + ip_hdr = (struct iphdr *)skb->data; + ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr); + break; + default: + memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN); + } + break; + case PACKET_BROADCAST: + memset(fake_hdr->daddr, 0xff, TR_ALEN); + break; + default: + memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN); + } + /* the source MAC address */ + if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) + memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN); + else + memset(fake_hdr->saddr, 0, TR_ALEN); + fake_hdr->rcf=0; + fake_llc = (struct trllc*)&(fake_hdr->rcf); + fake_llc->dsap = EXTENDED_SAP; + fake_llc->ssap = EXTENDED_SAP; + fake_llc->llc = UI_CMD; + fake_llc->protid[0] = 0; + fake_llc->protid[1] = 0; + fake_llc->protid[2] = 0; + fake_llc->ethertype = ETH_P_IP; +} + +static inline void +qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { struct ethhdr *fake_hdr; struct iphdr *ip_hdr; - QETH_DBF_TEXT(trace,5,"skbfake"); - skb->mac.raw = skb->data - QETH_FAKE_LL_LEN; + QETH_DBF_TEXT(trace,5,"skbfketh"); + skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH; /* this is a fake ethernet header */ fake_hdr = (struct ethhdr *) skb->mac.raw; @@ -2253,10 +2313,7 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, #endif /* CONFIG_QETH_IPV6 */ case __constant_htons(ETH_P_IP): ip_hdr = (struct iphdr *)skb->data; - if (card->dev->type == ARPHRD_IEEE802_TR) - ip_tr_mc_map(ip_hdr->daddr, fake_hdr->h_dest); - else - ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest); + ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest); break; default: memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN); @@ -2278,6 +2335,16 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, } static inline void +qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, + struct qeth_hdr *hdr) +{ + if (card->dev->type == ARPHRD_IEEE802_TR) + qeth_rebuild_skb_fake_ll_tr(card, skb, hdr); + else + qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); +} + +static inline void qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { @@ -3440,16 +3507,25 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct ethhdr *hdr; + if(dev->type == ARPHRD_IEEE802_TR){ + struct trh_hdr *hdr; + hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR); + memcpy(hdr->saddr, dev->dev_addr, TR_ALEN); + memcpy(hdr->daddr, "FAKELL", TR_ALEN); + return QETH_FAKE_LL_LEN_TR; + + } else { + struct ethhdr *hdr; + hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH); + memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN); + memcpy(hdr->h_dest, "FAKELL", ETH_ALEN); + if (type != ETH_P_802_3) + hdr->h_proto = htons(type); + else + hdr->h_proto = htons(len); + return QETH_FAKE_LL_LEN_ETH; - hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN); - memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN); - memcpy(hdr->h_dest, "FAKELL", ETH_ALEN); - if (type != ETH_P_802_3) - hdr->h_proto = htons(type); - else - hdr->h_proto = htons(len); - return QETH_FAKE_LL_LEN; + } } static inline int @@ -3882,9 +3958,15 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16); } } else { /* passthrough */ - if (!memcmp(skb->data + sizeof(struct qeth_hdr), + if((skb->dev->type == ARPHRD_IEEE802_TR) && + !memcmp(skb->data + sizeof(struct qeth_hdr) + 2, + skb->dev->broadcast, 6)) { + hdr->hdr.l3.flags = QETH_CAST_BROADCAST | + QETH_HDR_PASSTHRU; + } else if (!memcmp(skb->data + sizeof(struct qeth_hdr), skb->dev->broadcast, 6)) { /* broadcast? */ - hdr->hdr.l3.flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU; + hdr->hdr.l3.flags = QETH_CAST_BROADCAST | + QETH_HDR_PASSTHRU; } else { hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ? QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU : @@ -4164,7 +4246,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) dev_kfree_skb_irq(skb); return 0; } - skb_pull(skb, QETH_FAKE_LL_LEN); + if(card->dev->type == ARPHRD_IEEE802_TR){ + skb_pull(skb, QETH_FAKE_LL_LEN_TR); + } else { + skb_pull(skb, QETH_FAKE_LL_LEN_ETH); + } } } cast_type = qeth_get_cast_type(card, skb); -- cgit v1.1 From 9a4558193662e933588ee53e0202c103a68c9366 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:38:28 +0200 Subject: [PATCH] s390: qeth bug fixes [patch 9/10] s390: qeth bug fixes. From: Frank Pavlic qeth network driver changes: - Use sizeof(__u16) instead of '2' in qeth_fill_header. Signed-off-by: Frank Pavlic --- drivers/s390/net/qeth_main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 2afe515..e18bcf9 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.209 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.210 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.209 $ $Date: 2005/04/18 11:58:48 $ + * $Revision: 1.210 $ $Date: 2005/04/18 17:27:39 $ * * 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 @@ -80,7 +80,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.209 $" +#define VERSION_QETH_C "$Revision: 1.210 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -3959,10 +3959,10 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } } else { /* passthrough */ if((skb->dev->type == ARPHRD_IEEE802_TR) && - !memcmp(skb->data + sizeof(struct qeth_hdr) + 2, - skb->dev->broadcast, 6)) { - hdr->hdr.l3.flags = QETH_CAST_BROADCAST | - QETH_HDR_PASSTHRU; + !memcmp(skb->data + sizeof(struct qeth_hdr) + + sizeof(__u16), skb->dev->broadcast, 6)) { + hdr->hdr.l3.flags = QETH_CAST_BROADCAST | + QETH_HDR_PASSTHRU; } else if (!memcmp(skb->data + sizeof(struct qeth_hdr), skb->dev->broadcast, 6)) { /* broadcast? */ hdr->hdr.l3.flags = QETH_CAST_BROADCAST | -- cgit v1.1 From 05e08a2a297371564020f76d1bf8b3a931d5e1ed Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Thu, 12 May 2005 20:39:09 +0200 Subject: [PATCH] s390: qeth bug fixes [patch 10/10] s390: qeth bug fixes. From: Frank Pavlic qeth network driver related changes: - due to OSA hardware changes in TCP Segmentation Offload support we are able now to pack TSO packets too. This fits perfectly in design of qeth buffer handling and sending data respectively. - remove skb_realloc_headroom from the sending path since hard_header_len value provides enough headroom now. - device recovery behaviour improvement - bug fixed in Enhanced Device Driver Packing functionality Signed-off-by: Frank Pavlic --- drivers/s390/net/Makefile | 2 +- drivers/s390/net/qeth.h | 41 ++++--- drivers/s390/net/qeth_eddp.c | 40 +++---- drivers/s390/net/qeth_main.c | 145 +++++++++++++++++------- drivers/s390/net/qeth_tso.c | 256 ------------------------------------------- drivers/s390/net/qeth_tso.h | 193 ++++++++++++++++++++------------ 6 files changed, 273 insertions(+), 404 deletions(-) delete mode 100644 drivers/s390/net/qeth_tso.c diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 85b590c..90d4d0e 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -10,6 +10,6 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_LCS) += lcs.o cu3088.o obj-$(CONFIG_CLAW) += claw.o cu3088.o -qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o +qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth-$(CONFIG_PROC_FS) += qeth_proc.o obj-$(CONFIG_QETH) += qeth.o diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index d13c105..a755b57 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.137 $" +#define VERSION_QETH_H "$Revision: 1.139 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -370,6 +370,25 @@ struct qeth_hdr { } hdr; } __attribute__ ((packed)); +/*TCP Segmentation Offload header*/ +struct qeth_hdr_ext_tso { + __u16 hdr_tot_len; + __u8 imb_hdr_no; + __u8 reserved; + __u8 hdr_type; + __u8 hdr_version; + __u16 hdr_len; + __u32 payload_len; + __u16 mss; + __u16 dg_hdr_len; + __u8 padding[16]; +} __attribute__ ((packed)); + +struct qeth_hdr_tso { + struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/ + struct qeth_hdr_ext_tso ext; +} __attribute__ ((packed)); + /* flags for qeth_hdr.flags */ #define QETH_HDR_PASSTHRU 0x10 @@ -867,16 +886,6 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) return hdr; } -static inline int -qeth_get_skb_data_len(struct sk_buff *skb) -{ - int len = skb->len; - int i; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) - len -= skb_shinfo(skb)->frags[i].size; - return len; -} inline static int qeth_get_hlen(__u8 link_type) @@ -885,19 +894,19 @@ qeth_get_hlen(__u8 link_type) switch (link_type) { case QETH_LINK_TYPE_HSTR: case QETH_LINK_TYPE_LANE_TR: - return sizeof(struct qeth_hdr) + TR_HLEN; + return sizeof(struct qeth_hdr_tso) + TR_HLEN; default: #ifdef CONFIG_QETH_VLAN - return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN; + return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN; #else - return sizeof(struct qeth_hdr) + ETH_HLEN; + return sizeof(struct qeth_hdr_tso) + ETH_HLEN; #endif } #else /* CONFIG_QETH_IPV6 */ #ifdef CONFIG_QETH_VLAN - return sizeof(struct qeth_hdr) + VLAN_HLEN; + return sizeof(struct qeth_hdr_tso) + VLAN_HLEN; #else - return sizeof(struct qeth_hdr); + return sizeof(struct qeth_hdr_tso); #endif #endif /* CONFIG_QETH_IPV6 */ } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 45aa4a9..f94f1f25 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.12 $) + * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $) * * Enhanced Device Driver Packing (EDDP) support for the qeth driver. * @@ -8,7 +8,7 @@ * * Author(s): Thomas Spatzier * - * $Revision: 1.12 $ $Date: 2005/04/01 21:40:40 $ + * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $ * */ #include @@ -85,7 +85,7 @@ void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) { struct qeth_eddp_context_reference *ref; - + QETH_DBF_TEXT(trace, 6, "eddprctx"); while (!list_empty(&buf->ctx_list)){ ref = list_entry(buf->ctx_list.next, @@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, "buffer!\n"); goto out; } - } + } /* check if the whole next skb fits into current buffer */ if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) - buf->next_element_to_fill) @@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, * and increment ctx's refcnt */ must_refcnt = 1; continue; - } + } if (must_refcnt){ must_refcnt = 0; if (qeth_eddp_buf_ref_context(buf, ctx)){ @@ -204,27 +204,27 @@ out: static inline void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, - struct qeth_eddp_data *eddp) + struct qeth_eddp_data *eddp, int data_len) { u8 *page; int page_remainder; int page_offset; - int hdr_len; + int pkt_len; struct qeth_eddp_element *element; QETH_DBF_TEXT(trace, 5, "eddpcrsh"); page = ctx->pages[ctx->offset >> PAGE_SHIFT]; page_offset = ctx->offset % PAGE_SIZE; element = &ctx->elements[ctx->num_elements]; - hdr_len = eddp->nhl + eddp->thl; + pkt_len = eddp->nhl + eddp->thl + data_len; /* FIXME: layer2 and VLAN !!! */ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) - hdr_len += ETH_HLEN; + pkt_len += ETH_HLEN; if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) - hdr_len += VLAN_HLEN; - /* does complete header fit in current page ? */ + pkt_len += VLAN_HLEN; + /* does complete packet fit in current page ? */ page_remainder = PAGE_SIZE - page_offset; - if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){ + if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){ /* no -> go to start of next page */ ctx->offset += page_remainder; page = ctx->pages[ctx->offset >> PAGE_SHIFT]; @@ -270,7 +270,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, int left_in_frag; int copy_len; u8 *src; - + QETH_DBF_TEXT(trace, 5, "eddpcdtc"); if (skb_shinfo(eddp->skb)->nr_frags == 0) { memcpy(dst, eddp->skb->data + eddp->skb_offset, len); @@ -281,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, while (len > 0) { if (eddp->frag < 0) { /* we're in skb->data */ - left_in_frag = qeth_get_skb_data_len(eddp->skb) + left_in_frag = (eddp->skb->len - eddp->skb->data_len) - eddp->skb_offset; src = eddp->skb->data + eddp->skb_offset; } else { @@ -413,7 +413,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, struct tcphdr *tcph; int data_len; u32 hcsum; - + QETH_DBF_TEXT(trace, 5, "eddpftcp"); eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; tcph = eddp->skb->h.th; @@ -453,7 +453,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, else hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len); /* fill the next segment into the context */ - qeth_eddp_create_segment_hdrs(ctx, eddp); + qeth_eddp_create_segment_hdrs(ctx, eddp, data_len); qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum); if (eddp->skb_offset >= eddp->skb->len) break; @@ -463,13 +463,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, eddp->th.tcp.h.seq += data_len; } } - + static inline int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, struct sk_buff *skb, struct qeth_hdr *qhdr) { struct qeth_eddp_data *eddp = NULL; - + QETH_DBF_TEXT(trace, 5, "eddpficx"); /* create our segmentation headers and copy original headers */ if (skb->protocol == ETH_P_IP) @@ -509,7 +509,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, int hdr_len) { int skbs_per_page; - + QETH_DBF_TEXT(trace, 5, "eddpcanp"); /* can we put multiple skbs in one page? */ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); @@ -589,7 +589,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *qhdr) { struct qeth_eddp_context *ctx = NULL; - + QETH_DBF_TEXT(trace, 5, "creddpct"); if (skb->protocol == ETH_P_IP) ctx = qeth_eddp_create_context_generic(card, skb, diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index e18bcf9..208127a 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.210 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.210 $ $Date: 2005/04/18 17:27:39 $ + * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ * * 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 @@ -80,7 +80,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.210 $" +#define VERSION_QETH_C "$Revision: 1.214 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -158,6 +158,9 @@ qeth_irq_tasklet(unsigned long); static int qeth_set_online(struct ccwgroup_device *); +static int +__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode); + static struct qeth_ipaddr * qeth_get_addr_buffer(enum qeth_prot_versions); @@ -510,10 +513,10 @@ qeth_irq_tasklet(unsigned long data) wake_up(&card->wait_q); } -static int qeth_stop_card(struct qeth_card *); +static int qeth_stop_card(struct qeth_card *, int); static int -qeth_set_offline(struct ccwgroup_device *cgdev) +__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) { struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; int rc = 0; @@ -523,7 +526,7 @@ qeth_set_offline(struct ccwgroup_device *cgdev) QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); recover_flag = card->state; - if (qeth_stop_card(card) == -ERESTARTSYS){ + if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ PRINT_WARN("Stopping card %s interrupted by user!\n", CARD_BUS_ID(card)); return -ERESTARTSYS; @@ -540,6 +543,12 @@ qeth_set_offline(struct ccwgroup_device *cgdev) } static int +qeth_set_offline(struct ccwgroup_device *cgdev) +{ + return __qeth_set_offline(cgdev, 0); +} + +static int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads); @@ -953,8 +962,8 @@ qeth_recover(void *ptr) PRINT_WARN("Recovery of device %s started ...\n", CARD_BUS_ID(card)); card->use_hard_stop = 1; - qeth_set_offline(card->gdev); - rc = qeth_set_online(card->gdev); + __qeth_set_offline(card->gdev,1); + rc = __qeth_set_online(card->gdev,1); if (!rc) PRINT_INFO("Device %s successfully recovered!\n", CARD_BUS_ID(card)); @@ -3786,16 +3795,12 @@ static inline int qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, struct qeth_hdr **hdr, int ipv) { - int rc = 0; #ifdef CONFIG_QETH_VLAN u16 *tag; #endif QETH_DBF_TEXT(trace, 6, "prepskb"); - rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); - if (rc) - return rc; #ifdef CONFIG_QETH_VLAN if (card->vlangrp && vlan_tx_tag_present(*skb) && ((ipv == 6) || card->options.layer2) ) { @@ -3977,25 +3982,28 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, static inline void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, - int *next_element_to_fill) + int is_tso, int *next_element_to_fill) { int length = skb->len; int length_here; int element; char *data; - int first_lap = 1; + int first_lap ; element = *next_element_to_fill; data = skb->data; + first_lap = (is_tso == 0 ? 1 : 0); + while (length > 0) { /* length_here is the remaining amount of data in this page */ length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); if (length < length_here) length_here = length; + buffer->element[element].addr = data; buffer->element[element].length = length_here; length -= length_here; - if (!length){ + if (!length) { if (first_lap) buffer->element[element].flags = 0; else @@ -4022,17 +4030,35 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct sk_buff *skb) { struct qdio_buffer *buffer; - int flush_cnt = 0; + struct qeth_hdr_tso *hdr; + int flush_cnt = 0, hdr_len, large_send = 0; QETH_DBF_TEXT(trace, 6, "qdfillbf"); + buffer = buf->buffer; atomic_inc(&skb->users); skb_queue_tail(&buf->skb_list, skb); + + hdr = (struct qeth_hdr_tso *) skb->data; + /*check first on TSO ....*/ + if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) { + int element = buf->next_element_to_fill; + + hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len; + /*fill first buffer entry only with header information */ + buffer->element[element].addr = skb->data; + buffer->element[element].length = hdr_len; + buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; + buf->next_element_to_fill++; + skb->data += hdr_len; + skb->len -= hdr_len; + large_send = 1; + } if (skb_shinfo(skb)->nr_frags == 0) - __qeth_fill_buffer(skb, buffer, + __qeth_fill_buffer(skb, buffer, large_send, (int *)&buf->next_element_to_fill); else - __qeth_fill_buffer_frag(skb, buffer, 0, + __qeth_fill_buffer_frag(skb, buffer, large_send, (int *)&buf->next_element_to_fill); if (!queue->do_pack) { @@ -4225,6 +4251,25 @@ out: } static inline int +qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) +{ + int elements_needed = 0; + + if (skb_shinfo(skb)->nr_frags > 0) { + elements_needed = (skb_shinfo(skb)->nr_frags + 1); + } + if (elements_needed == 0 ) + elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + + skb->len) >> PAGE_SHIFT); + if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ + PRINT_ERR("qeth_do_send_packet: invalid size of " + "IP packet. Discarded."); + return 0; + } + return elements_needed; +} + +static inline int qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) { int ipv = 0; @@ -4266,19 +4311,25 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) if (skb_shinfo(skb)->tso_size) large_send = card->options.large_send; - if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){ - QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); - return rc; - } /*are we able to do TSO ? If so ,prepare and send it from here */ if ((large_send == QETH_LARGE_SEND_TSO) && (cast_type == RTN_UNSPEC)) { - rc = qeth_tso_send_packet(card, skb, queue, - ipv, cast_type); - goto do_statistics; + rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type); + if (rc) { + card->stats.tx_dropped++; + card->stats.tx_errors++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + elements_needed++; + } else { + if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) { + QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); + return rc; + } + qeth_fill_header(card, hdr, skb, ipv, cast_type); } - qeth_fill_header(card, hdr, skb, ipv, cast_type); if (large_send == QETH_LARGE_SEND_EDDP) { ctx = qeth_eddp_create_context(card, skb, hdr); if (ctx == NULL) { @@ -4286,7 +4337,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) return -EINVAL; } } else { - elements_needed = qeth_get_elements_no(card,(void*) hdr, skb); + elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); if (!elements_needed) return -EINVAL; } @@ -4297,12 +4348,12 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) else rc = qeth_do_send_packet_fast(card, queue, skb, hdr, elements_needed, ctx); -do_statistics: if (!rc){ card->stats.tx_packets++; card->stats.tx_bytes += skb->len; #ifdef CONFIG_QETH_PERF_STATS - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->tso_size && + !(large_send == QETH_LARGE_SEND_NO)) { card->perf_stats.large_send_bytes += skb->len; card->perf_stats.large_send_cnt++; } @@ -7199,7 +7250,7 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads) } static int -qeth_stop_card(struct qeth_card *card) +qeth_stop_card(struct qeth_card *card, int recovery_mode) { int rc = 0; @@ -7212,9 +7263,13 @@ qeth_stop_card(struct qeth_card *card) if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); + if(recovery_mode) { + qeth_stop(card->dev); + } else { + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); + } if (!card->use_hard_stop) { __u8 *mac = &card->dev->dev_addr[0]; rc = qeth_layer2_send_delmac(card, mac); @@ -7386,13 +7441,17 @@ qeth_register_netdev(struct qeth_card *card) } static void -qeth_start_again(struct qeth_card *card) +qeth_start_again(struct qeth_card *card, int recovery_mode) { QETH_DBF_TEXT(setup ,2, "startag"); - rtnl_lock(); - dev_open(card->dev); - rtnl_unlock(); + if(recovery_mode) { + qeth_open(card->dev); + } else { + rtnl_lock(); + dev_open(card->dev); + rtnl_unlock(); + } /* this also sets saved unicast addresses */ qeth_set_multicast_list(card->dev); } @@ -7449,7 +7508,7 @@ static void qeth_make_parameters_consistent(struct qeth_card *card) static int -qeth_set_online(struct ccwgroup_device *gdev) +__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) { struct qeth_card *card = gdev->dev.driver_data; int rc = 0; @@ -7509,12 +7568,12 @@ qeth_set_online(struct ccwgroup_device *gdev) * we can also use this state for recovery purposes*/ qeth_set_allowed_threads(card, 0xffffffff, 0); if (recover_flag == CARD_STATE_RECOVER) - qeth_start_again(card); + qeth_start_again(card, recovery_mode); qeth_notify_processes(); return 0; out_remove: card->use_hard_stop = 1; - qeth_stop_card(card); + qeth_stop_card(card, 0); ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); @@ -7525,6 +7584,12 @@ out_remove: return -ENODEV; } +static int +qeth_set_online(struct ccwgroup_device *gdev) +{ + return __qeth_set_online(gdev, 0); +} + static struct ccw_device_id qeth_ids[] = { {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c deleted file mode 100644 index 4e58f19..0000000 --- a/drivers/s390/net/qeth_tso.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.7 $) - * - * Header file for qeth TCP Segmentation Offload support. - * - * Copyright 2004 IBM Corporation - * - * Author(s): Frank Pavlic - * - * $Revision: 1.7 $ $Date: 2005/04/01 21:40:41 $ - * - */ - -#include -#include -#include -#include -#include -#include "qeth.h" -#include "qeth_mpc.h" -#include "qeth_tso.h" - -/** - * skb already partially prepared - * classic qdio header in skb->data - * */ -static inline struct qeth_hdr_tso * -qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) -{ - int rc = 0; - - QETH_DBF_TEXT(trace, 5, "tsoprsk"); - rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso)); - if (rc) - return NULL; - - return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso)); -} - -/** - * fill header for a TSO packet - */ -static inline void -qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) -{ - struct qeth_hdr_tso *hdr; - struct tcphdr *tcph; - struct iphdr *iph; - - QETH_DBF_TEXT(trace, 5, "tsofhdr"); - - hdr = (struct qeth_hdr_tso *) skb->data; - iph = skb->nh.iph; - tcph = skb->h.th; - /*fix header to TSO values ...*/ - hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; - /*set values which are fix for the first approach ...*/ - hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); - hdr->ext.imb_hdr_no = 1; - hdr->ext.hdr_type = 1; - hdr->ext.hdr_version = 1; - hdr->ext.hdr_len = 28; - /*insert non-fix values */ - hdr->ext.mss = skb_shinfo(skb)->tso_size; - hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); - hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - - sizeof(struct qeth_hdr_tso)); -} - -/** - * change some header values as requested by hardware - */ -static inline void -qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ip6h; - struct tcphdr *tcph; - - iph = skb->nh.iph; - ip6h = skb->nh.ipv6h; - tcph = skb->h.th; - - tcph->check = 0; - if (skb->protocol == ETH_P_IPV6) { - ip6h->payload_len = 0; - tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - 0, IPPROTO_TCP, 0); - return; - } - /*OSA want us to set these values ...*/ - tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - 0, IPPROTO_TCP, 0); - iph->tot_len = 0; - iph->check = 0; -} - -static inline struct qeth_hdr_tso * -qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb, - int ipv, int cast_type) -{ - struct qeth_hdr_tso *hdr; - int rc = 0; - - QETH_DBF_TEXT(trace, 5, "tsoprep"); - - /*get headroom for tso qdio header */ - hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb); - if (hdr == NULL) { - QETH_DBF_TEXT_(trace, 4, "2err%d", rc); - return NULL; - } - memset(hdr, 0, sizeof(struct qeth_hdr_tso)); - /*fill first 32 bytes of qdio header as used - *FIXME: TSO has two struct members - * with different names but same size - * */ - qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type); - qeth_tso_fill_header(card, skb); - qeth_tso_set_tcpip_header(card, skb); - return hdr; -} - -static inline int -qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue) -{ - struct qeth_qdio_out_buffer *buffer; - int flush_cnt = 0; - - QETH_DBF_TEXT(trace, 5, "tsobuf"); - - /* force to non-packing*/ - if (queue->do_pack) - queue->do_pack = 0; - buffer = &queue->bufs[queue->next_buf_to_fill]; - /* get a new buffer if current is already in use*/ - if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && - (buffer->next_element_to_fill > 0)) { - atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); - queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % - QDIO_MAX_BUFFERS_PER_Q; - flush_cnt++; - } - return flush_cnt; -} - - -static inline int -qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, - struct sk_buff *skb) -{ - int length, length_here, element; - int hdr_len; - struct qdio_buffer *buffer; - struct qeth_hdr_tso *hdr; - char *data; - - QETH_DBF_TEXT(trace, 3, "tsfilbuf"); - - /*increment user count and queue skb ...*/ - atomic_inc(&skb->users); - skb_queue_tail(&buf->skb_list, skb); - - /*initialize all variables...*/ - buffer = buf->buffer; - hdr = (struct qeth_hdr_tso *)skb->data; - hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len; - data = skb->data + hdr_len; - length = skb->len - hdr_len; - element = buf->next_element_to_fill; - /*fill first buffer entry only with header information */ - buffer->element[element].addr = skb->data; - buffer->element[element].length = hdr_len; - buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; - buf->next_element_to_fill++; - /*check if we have frags ...*/ - if (skb_shinfo(skb)->nr_frags > 0) { - skb->len = length; - skb->data = data; - __qeth_fill_buffer_frag(skb, buffer,1, - (int *)&buf->next_element_to_fill); - goto out; - } - - /*... if not, use this */ - element++; - while (length > 0) { - /* length_here is the remaining amount of data in this page */ - length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); - if (length < length_here) - length_here = length; - buffer->element[element].addr = data; - buffer->element[element].length = length_here; - length -= length_here; - if (!length) - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - data += length_here; - element++; - } - buf->next_element_to_fill = element; -out: - /*prime buffer now ...*/ - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - return 1; -} - -int -qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb, - struct qeth_qdio_out_q *queue, int ipv, int cast_type) -{ - int flush_cnt = 0; - struct qeth_hdr_tso *hdr; - struct qeth_qdio_out_buffer *buffer; - int start_index; - - QETH_DBF_TEXT(trace, 3, "tsosend"); - - if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type))) - return -ENOMEM; - /*check if skb fits in one SBAL ...*/ - if (!(qeth_get_elements_no(card, (void*)hdr, skb))) - return -EINVAL; - /*lock queue, force switching to non-packing and send it ...*/ - while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, - QETH_OUT_Q_LOCKED, - &queue->state)); - start_index = queue->next_buf_to_fill; - buffer = &queue->bufs[queue->next_buf_to_fill]; - /*check if card is too busy ...*/ - if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ - card->stats.tx_dropped++; - goto out; - } - /*let's force to non-packing and get a new SBAL*/ - flush_cnt += qeth_tso_get_queue_buffer(queue); - buffer = &queue->bufs[queue->next_buf_to_fill]; - if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { - card->stats.tx_dropped++; - goto out; - } - flush_cnt += qeth_tso_fill_buffer(buffer, skb); - queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % - QDIO_MAX_BUFFERS_PER_Q; -out: - atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); - if (flush_cnt) - qeth_flush_buffers(queue, 0, start_index, flush_cnt); - /*do some statistics */ - card->stats.tx_packets++; - card->stats.tx_bytes += skb->len; - return 0; -} diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index ff585ae..ad33e6f 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.5 $) + * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.7 $) * * Header file for qeth TCP Segmentation Offload support. * @@ -7,97 +7,148 @@ * * Author(s): Frank Pavlic * - * $Revision: 1.5 $ $Date: 2005/04/01 21:40:41 $ + * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $ * */ #ifndef __QETH_TSO_H__ #define __QETH_TSO_H__ +#include +#include +#include +#include +#include +#include "qeth.h" +#include "qeth_mpc.h" -extern int -qeth_tso_send_packet(struct qeth_card *, struct sk_buff *, - struct qeth_qdio_out_q *, int , int); -struct qeth_hdr_ext_tso { - __u16 hdr_tot_len; - __u8 imb_hdr_no; - __u8 reserved; - __u8 hdr_type; - __u8 hdr_version; - __u16 hdr_len; - __u32 payload_len; - __u16 mss; - __u16 dg_hdr_len; - __u8 padding[16]; -} __attribute__ ((packed)); +static inline struct qeth_hdr_tso * +qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) +{ + QETH_DBF_TEXT(trace, 5, "tsoprsk"); + return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_tso)); +} + +/** + * fill header for a TSO packet + */ +static inline void +qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) +{ + struct qeth_hdr_tso *hdr; + struct tcphdr *tcph; + struct iphdr *iph; -struct qeth_hdr_tso { - struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/ - struct qeth_hdr_ext_tso ext; -} __attribute__ ((packed)); + QETH_DBF_TEXT(trace, 5, "tsofhdr"); + + hdr = (struct qeth_hdr_tso *) skb->data; + iph = skb->nh.iph; + tcph = skb->h.th; + /*fix header to TSO values ...*/ + hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; + /*set values which are fix for the first approach ...*/ + hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); + hdr->ext.imb_hdr_no = 1; + hdr->ext.hdr_type = 1; + hdr->ext.hdr_version = 1; + hdr->ext.hdr_len = 28; + /*insert non-fix values */ + hdr->ext.mss = skb_shinfo(skb)->tso_size; + hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); + hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - + sizeof(struct qeth_hdr_tso)); +} + +/** + * change some header values as requested by hardware + */ +static inline void +qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb) +{ + struct iphdr *iph; + struct ipv6hdr *ip6h; + struct tcphdr *tcph; + + iph = skb->nh.iph; + ip6h = skb->nh.ipv6h; + tcph = skb->h.th; + + tcph->check = 0; + if (skb->protocol == ETH_P_IPV6) { + ip6h->payload_len = 0; + tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + 0, IPPROTO_TCP, 0); + return; + } + /*OSA want us to set these values ...*/ + tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, + 0, IPPROTO_TCP, 0); + iph->tot_len = 0; + iph->check = 0; +} -/*some helper functions*/ static inline int -qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) +qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb, + int ipv, int cast_type) { - int elements_needed = 0; + struct qeth_hdr_tso *hdr; - if (skb_shinfo(skb)->nr_frags > 0) - elements_needed = (skb_shinfo(skb)->nr_frags + 1); - if (elements_needed == 0 ) - elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) - + skb->len) >> PAGE_SHIFT); - if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ - PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet. Discarded."); - return 0; - } - return elements_needed; + QETH_DBF_TEXT(trace, 5, "tsoprep"); + + hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb); + if (hdr == NULL) { + QETH_DBF_TEXT(trace, 4, "tsoperr"); + return -ENOMEM; + } + memset(hdr, 0, sizeof(struct qeth_hdr_tso)); + /*fill first 32 bytes of qdio header as used + *FIXME: TSO has two struct members + * with different names but same size + * */ + qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type); + qeth_tso_fill_header(card, skb); + qeth_tso_set_tcpip_header(card, skb); + return 0; } static inline void __qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill) { - int length = skb->len; struct skb_frag_struct *frag; int fragno; unsigned long addr; - int element; - int first_lap = 1; - - fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */ - element = *next_element_to_fill + fragno; - while (length > 0) { - if (fragno > 0) { - frag = &skb_shinfo(skb)->frags[fragno - 1]; - addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + - frag->page_offset; - buffer->element[element].addr = (char *)addr; - buffer->element[element].length = frag->size; - length -= frag->size; - if (first_lap) - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - } else { - buffer->element[element].addr = skb->data; - buffer->element[element].length = length; - length = 0; - if (is_tso) - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_FIRST_FRAG; - } - element--; - fragno--; - first_lap = 0; + int element, cnt, dlen; + + fragno = skb_shinfo(skb)->nr_frags; + element = *next_element_to_fill; + dlen = 0; + + if (is_tso) + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_FIRST_FRAG; + if ( (dlen = (skb->len - skb->data_len)) ) { + buffer->element[element].addr = skb->data; + buffer->element[element].length = dlen; + element++; } - *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1; + for (cnt = 0; cnt < fragno; cnt++) { + frag = &skb_shinfo(skb)->frags[cnt]; + addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + + frag->page_offset; + buffer->element[element].addr = (char *)addr; + buffer->element[element].length = frag->size; + if (cnt < (fragno - 1)) + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_LAST_FRAG; + element++; + } + *next_element_to_fill = element; } - #endif /* __QETH_TSO_H__ */ -- cgit v1.1 From f27eff1ffd65236b8e421188f76ad1b0b94e06eb Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 12 May 2005 17:47:27 +1000 Subject: [PATCH] iseries_veth: Don't send packets to LPARs which aren't up Hi Andrew, Jeff, The iseries_veth driver has a logic bug which means it will erroneously send packets to LPARs for which we don't have a connection. This usually isn't a big problem because the Hypervisor call fails gracefully and we return, but if packets are TX'ed during the negotiation of the connection bad things might happen. Regardless, the right thing is to bail early if we know there's no connection. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 855f8b2..7d0ef29 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -924,7 +924,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp, spin_lock_irqsave(&cnx->lock, flags); - if (! cnx->state & VETH_STATE_READY) + if (! (cnx->state & VETH_STATE_READY)) goto drop; if ((skb->len - 14) > VETH_MAX_MTU) -- cgit v1.1 From eb235aef724568ae15af831968000cf9a3974b26 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 12 May 2005 17:53:18 +1000 Subject: [PATCH] iseries_veth: Set dev->trans_start so watchdog timer works right Hi Andrew, Jeff, The iseries_veth driver doesn't set dev->trans_start in it's TX path. This will cause the net device watchdog timer to fire earlier than we want it to, which causes the driver to needlessly reset its connections to other LPARs. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 7d0ef29..1e869df 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1023,6 +1023,8 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) lpmask = veth_transmit_to_many(skb, lpmask, dev); + dev->trans_start = jiffies; + if (! lpmask) { dev_kfree_skb(skb); } else { -- cgit v1.1 From 41664c03f6c96a1f8a91714309b36f1b5ca85610 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 12 May 2005 17:55:08 +1000 Subject: [PATCH] iseries_veth: Don't leak skbs in RX path Hi Andrew, Jeff, Under some strange circumstances the iseries_veth driver can leak skbs. Fix is simply to call dev_kfree_skb() in the right place. Fix up the comment as well. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 1e869df..1edecb1 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1264,13 +1264,18 @@ static void veth_receive(struct veth_lpar_connection *cnx, vlan = skb->data[9]; dev = veth_dev[vlan]; - if (! dev) - /* Some earlier versions of the driver sent - broadcasts down all connections, even to - lpars that weren't on the relevant vlan. - So ignore packets belonging to a vlan we're - not on. */ + if (! dev) { + /* + * Some earlier versions of the driver sent + * broadcasts down all connections, even to lpars + * that weren't on the relevant vlan. So ignore + * packets belonging to a vlan we're not on. + * We can also be here if we receive packets while + * the driver is going down, because then dev is NULL. + */ + dev_kfree_skb_irq(skb); continue; + } port = (struct veth_port *)dev->priv; dest = *((u64 *) skb->data) & 0xFFFFFFFFFFFF0000; -- cgit v1.1 From b2e0852e1eee7c445b1789bef41204b64f981102 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 12 May 2005 18:09:45 +1000 Subject: [PATCH] iseries_veth: Cleanup skbs to prevent unregister_netdevice() hanging Hi Andrew, Jeff, The iseries_veth driver is badly behaved in that it will keep TX packets hanging around forever if they're not ACK'ed and the queue never fills up. This causes the unregister_netdevice code to wait forever when we try to take the device down, because there's still skbs around with references to our struct net_device. There's already code to cleanup any un-ACK'ed packets in veth_stop_connection() but it's being called after we unregister the net_device, which is too late. The fix is to rearrange the module exit function so that we cleanup any outstanding skbs and then unregister the driver. Signed-off-by: Michael Ellerman --- drivers/net/iseries_veth.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 1edecb1..13ed8dc 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1388,18 +1388,25 @@ void __exit veth_module_cleanup(void) { int i; - vio_unregister_driver(&veth_driver); + /* Stop the queues first to stop any new packets being sent. */ + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) + if (veth_dev[i]) + netif_stop_queue(veth_dev[i]); + /* Stop the connections before we unregister the driver. This + * ensures there's no skbs lying around holding the device open. */ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) veth_stop_connection(i); HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan); /* Hypervisor callbacks may have scheduled more work while we - * were destroying connections. Now that we've disconnected from + * were stoping connections. Now that we've disconnected from * the hypervisor make sure everything's finished. */ flush_scheduled_work(); + vio_unregister_driver(&veth_driver); + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) veth_destroy_connection(i); -- cgit v1.1 From 22c6d143f33f10721216a8cfa3a83f7edfc2bd4e Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Tue, 19 Apr 2005 21:17:09 +0200 Subject: [PATCH] forcedeth: Update error handling Ayaz wrote an update to the error handling for forcedeth (which I modified heavily, thus all bugs are mine): The ERROR4 bit is not a fatal error, it just indicates a mismatch between the actual packet len and the len according to the 802.3 header. The patch adds proper handling. The patch also removes the code that drops all packets with RX_ERROR & (!RX_FRAMINGERR): ERROR4 errors are also not fatal. --- drivers/net/forcedeth.c | 93 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index c93f3d0..4ebcd05 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -81,6 +81,7 @@ * cause DMA to kfree'd memory. * 0.31: 14 Nov 2004: ethtool support for getting/setting link * capabilities. + * 0.32: 16 Apr 2005: RX_ERROR4 handling added. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -92,7 +93,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.31" +#define FORCEDETH_VERSION "0.32" #define DRV_NAME "forcedeth" #include @@ -109,6 +110,7 @@ #include #include #include +#include #include #include @@ -1013,6 +1015,59 @@ static void nv_tx_timeout(struct net_device *dev) spin_unlock_irq(&np->lock); } +/* + * Called when the nic notices a mismatch between the actual data len on the + * wire and the len indicated in the 802 header + */ +static int nv_getlen(struct net_device *dev, void *packet, int datalen) +{ + int hdrlen; /* length of the 802 header */ + int protolen; /* length as stored in the proto field */ + + /* 1) calculate len according to header */ + if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == __constant_htons(ETH_P_8021Q)) { + protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto ); + hdrlen = VLAN_HLEN; + } else { + protolen = ntohs( ((struct ethhdr *)packet)->h_proto); + hdrlen = ETH_HLEN; + } + dprintk(KERN_DEBUG "%s: nv_getlen: datalen %d, protolen %d, hdrlen %d\n", + dev->name, datalen, protolen, hdrlen); + if (protolen > ETH_DATA_LEN) + return datalen; /* Value in proto field not a len, no checks possible */ + + protolen += hdrlen; + /* consistency checks: */ + if (datalen > ETH_ZLEN) { + if (datalen >= protolen) { + /* more data on wire than in 802 header, trim of + * additional data. + */ + dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", + dev->name, protolen); + return protolen; + } else { + /* less data on wire than mentioned in header. + * Discard the packet. + */ + dprintk(KERN_DEBUG "%s: nv_getlen: discarding long packet.\n", + dev->name); + return -1; + } + } else { + /* short packet. Accept only if 802 values are also short */ + if (protolen > ETH_ZLEN) { + dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n", + dev->name); + return -1; + } + dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", + dev->name, datalen); + return datalen; + } +} + static void nv_rx_process(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); @@ -1064,7 +1119,7 @@ static void nv_rx_process(struct net_device *dev) np->stats.rx_errors++; goto next_pkt; } - if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3|NV_RX_ERROR4)) { + if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) { np->stats.rx_errors++; goto next_pkt; } @@ -1078,22 +1133,24 @@ static void nv_rx_process(struct net_device *dev) np->stats.rx_errors++; goto next_pkt; } - if (Flags & NV_RX_ERROR) { - /* framing errors are soft errors, the rest is fatal. */ - if (Flags & NV_RX_FRAMINGERR) { - if (Flags & NV_RX_SUBSTRACT1) { - len--; - } - } else { + if (Flags & NV_RX_ERROR4) { + len = nv_getlen(dev, np->rx_skbuff[i]->data, len); + if (len < 0) { np->stats.rx_errors++; goto next_pkt; } } + /* framing errors are soft errors. */ + if (Flags & NV_RX_FRAMINGERR) { + if (Flags & NV_RX_SUBSTRACT1) { + len--; + } + } } else { if (!(Flags & NV_RX2_DESCRIPTORVALID)) goto next_pkt; - if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3|NV_RX2_ERROR4)) { + if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) { np->stats.rx_errors++; goto next_pkt; } @@ -1107,17 +1164,19 @@ static void nv_rx_process(struct net_device *dev) np->stats.rx_errors++; goto next_pkt; } - if (Flags & NV_RX2_ERROR) { - /* framing errors are soft errors, the rest is fatal. */ - if (Flags & NV_RX2_FRAMINGERR) { - if (Flags & NV_RX2_SUBSTRACT1) { - len--; - } - } else { + if (Flags & NV_RX2_ERROR4) { + len = nv_getlen(dev, np->rx_skbuff[i]->data, len); + if (len < 0) { np->stats.rx_errors++; goto next_pkt; } } + /* framing errors are soft errors */ + if (Flags & NV_RX2_FRAMINGERR) { + if (Flags & NV_RX2_SUBSTRACT1) { + len--; + } + } Flags &= NV_RX2_CHECKSUMMASK; if (Flags == NV_RX2_CHECKSUMOK1 || Flags == NV_RX2_CHECKSUMOK2 || -- cgit v1.1 From e885b5e83965c320e8eff1ec3ebfbf821b375568 Mon Sep 17 00:00:00 2001 From: "simon@thekelleys.org.uk" Date: Sat, 7 May 2005 21:33:31 +0100 Subject: [PATCH] atmel wireless Below is a one-liner for the atmel wireless driver, just adding another card to the table. --- drivers/net/wireless/atmel_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index a91b507..a4ed28d 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -321,6 +321,7 @@ static struct { { 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" }, { 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" }, { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" }, + { 0, 0, "IEEE 802.11b/Wireless LAN Card S", ATMEL_FW_TYPE_504_2958, "Siemens Gigaset PC Card II" }, { 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" }, { 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" }, { 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" }, -- cgit v1.1 From 760f86d78d92f39e2ceb55b40f0885eb755c8c2f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 16 Apr 2005 16:24:16 +1000 Subject: [PATCH] Fw: [Bugme-new] [Bug 4482] New: natsemi: incorrect initialization of IPv6 Neighbor-discovery multicast On Wed, Apr 13, 2005 at 05:36:42PM +0000, Andrew Morton wrote: > Summary: natsemi: incorrect initialization of IPv6 Neighbor- > discovery multicast I've got a pair of FA312 cards and this problem has bothered me for ages. This has finally prompted me to do something about it :) Turns out that somebody wasn't following the documentation. We were doing 16-bit writes to 32-bit registers which led to some addresses working and others not so lucky. This patch should fix the problem. Signed-off-by: Herbert Xu --- drivers/net/natsemi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 223bdad..babb59e 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2433,9 +2433,9 @@ static void __set_rx_mode(struct net_device *dev) rx_mode = RxFilterEnable | AcceptBroadcast | AcceptMulticast | AcceptMyPhys; for (i = 0; i < 64; i += 2) { - writew(HASH_TABLE + i, ioaddr + RxFilterAddr); - writew((mc_filter[i+1]<<8) + mc_filter[i], - ioaddr + RxFilterData); + writel(HASH_TABLE + i, ioaddr + RxFilterAddr); + writel((mc_filter[i + 1] << 8) + mc_filter[i], + ioaddr + RxFilterData); } } writel(rx_mode, ioaddr + RxFilterAddr); -- cgit v1.1 From 41480af27a85d6008d9e11db8bc2730407c25e1d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 May 2005 09:45:51 -0400 Subject: [PATCH] wireless/airo: WEXT and quality corrections This patch brings the airo driver into line with the current WEXT specification of signal quality. It also fixes the values used to determine signal quality and level for MPI & PCMCIA 350 cards. It turns out that BSSListRid.rssi was actually in dBm for 350 series cards, and that we can use the normalized signal strength reported by the card as our "quality" value, on a scale of 0 - 100. Since signal level values are in dBm for this driver, max_qual->level MUST be 0, as specified in the WEXT spec. This patch also uses the IW_QUAL constants new in WEXT version 17. Signed-off-by: Dan Williams --- drivers/net/wireless/airo.c | 150 ++++++++++++++++++++++++++++++-------------- 1 file changed, 104 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 463c789..fb10a2d 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -754,7 +754,7 @@ typedef struct { u8 zero; u8 ssidLen; u8 ssid[32]; - u16 rssi; + u16 dBm; #define CAP_ESS (1<<0) #define CAP_IBSS (1<<1) #define CAP_PRIVACY (1<<4) @@ -1125,6 +1125,9 @@ static int micsetup(struct airo_info *ai); static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len); static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen); +static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); +static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); + #include #endif @@ -1713,6 +1716,7 @@ static int readBSSListRid(struct airo_info *ai, int first, list->fh.dwell = le16_to_cpu(list->fh.dwell); list->dsChannel = le16_to_cpu(list->dsChannel); list->atimWindow = le16_to_cpu(list->atimWindow); + list->dBm = le16_to_cpu(list->dBm); return rc; } @@ -3245,7 +3249,10 @@ badrx: wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; else wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.updated = 3; + wstats.noise = apriv->wstats.qual.noise; + wstats.updated = IW_QUAL_LEVEL_UPDATED + | IW_QUAL_QUAL_UPDATED + | IW_QUAL_NOISE_UPDATED; /* Update spy records */ wireless_spy_update(dev, sa, &wstats); } @@ -3588,7 +3595,10 @@ void mpi_receive_802_11 (struct airo_info *ai) wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; else wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.updated = 3; + wstats.noise = ai->wstats.qual.noise; + wstats.updated = IW_QUAL_QUAL_UPDATED + | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_UPDATED; /* Update spy records */ wireless_spy_update(ai->dev, sa, &wstats); } @@ -3679,7 +3689,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock); if ( status == SUCCESS ) { if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) - memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); + memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */ } else { if (ai->rssi) { @@ -5348,7 +5358,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { (int)BSSList_rid.bssid[5], (int)BSSList_rid.ssidLen, BSSList_rid.ssid, - (int)BSSList_rid.rssi); + (int)BSSList_rid.dBm); ptr += sprintf(ptr, " channel = %d %s %s %s %s\n", (int)BSSList_rid.dsChannel, BSSList_rid.cap & CAP_ESS ? "ESS" : "", @@ -5593,6 +5603,29 @@ static void __exit airo_cleanup_module( void ) * would not work at all... - Jean II */ +static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) +{ + if( !rssi_rid ) + return 0; + + return (0x100 - rssi_rid[rssi].rssidBm); +} + +static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) +{ + int i; + + if( !rssi_rid ) + return 0; + + for( i = 0; i < 256; i++ ) + if (rssi_rid[i].rssidBm == dbm) + return rssi_rid[i].rssipct; + + return 0; +} + + static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) { int quality = 0; @@ -6443,11 +6476,29 @@ static int airo_get_range(struct net_device *dev, } range->num_frequency = k; + range->sensitivity = 65535; + /* Hum... Should put the right values there */ - range->max_qual.qual = airo_get_max_quality(&cap_rid); - range->max_qual.level = 0x100 - 120; /* -120 dBm */ + if (local->rssi) + range->max_qual.qual = 100; /* % */ + else + range->max_qual.qual = airo_get_max_quality(&cap_rid); + range->max_qual.level = 0; /* 0 means we use dBm */ range->max_qual.noise = 0; - range->sensitivity = 65535; + range->max_qual.updated = 0; + + /* Experimental measurements - boundary 11/5.5 Mb/s */ + /* Note : with or without the (local->rssi), results + * are somewhat different. - Jean II */ + if (local->rssi) { + range->avg_qual.qual = 50; /* % */ + range->avg_qual.level = 186; /* -70 dBm */ + } else { + range->avg_qual.qual = airo_get_avg_quality(&cap_rid); + range->avg_qual.level = 176; /* -80 dBm */ + } + range->avg_qual.noise = 0; + range->avg_qual.updated = 0; for(i = 0 ; i < 8 ; i++) { range->bitrate[i] = cap_rid.supportedRates[i] * 500000; @@ -6508,15 +6559,6 @@ static int airo_get_range(struct net_device *dev, range->max_retry = 65535; range->min_r_time = 1024; range->max_r_time = 65535 * 1024; - /* Experimental measurements - boundary 11/5.5 Mb/s */ - /* Note : with or without the (local->rssi), results - * are somewhat different. - Jean II */ - range->avg_qual.qual = airo_get_avg_quality(&cap_rid); - if (local->rssi) - range->avg_qual.level = 186; /* -70 dBm */ - else - range->avg_qual.level = 176; /* -80 dBm */ - range->avg_qual.noise = 0; /* Event capability (kernel + driver) */ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | @@ -6676,12 +6718,18 @@ static int airo_get_aplist(struct net_device *dev, loseSync = 0; memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN); address[i].sa_family = ARPHRD_ETHER; - if (local->rssi) - qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm; - else - qual[i].level = (BSSList.rssi + 321) / 2; - qual[i].qual = qual[i].noise = 0; - qual[i].updated = 2; + if (local->rssi) { + qual[i].level = 0x100 - BSSList.dBm; + qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm ); + qual[i].updated = IW_QUAL_QUAL_UPDATED; + } else { + qual[i].level = (BSSList.dBm + 321) / 2; + qual[i].qual = 0; + qual[i].updated = IW_QUAL_QUAL_INVALID; + } + qual[i].noise = local->wstats.qual.noise; + qual[i].updated = IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_UPDATED; if (BSSList.index == 0xffff) break; } @@ -6760,7 +6808,7 @@ static int airo_set_scan(struct net_device *dev, static inline char *airo_translate_scan(struct net_device *dev, char *current_ev, char *end_buf, - BSSListRid *list) + BSSListRid *bss) { struct airo_info *ai = dev->priv; struct iw_event iwe; /* Temporary buffer */ @@ -6771,22 +6819,22 @@ static inline char *airo_translate_scan(struct net_device *dev, /* First entry *MUST* be the AP MAC address */ iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN); + memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); /* Other entries will be displayed in the order we give them */ /* Add the ESSID */ - iwe.u.data.length = list->ssidLen; + iwe.u.data.length = bss->ssidLen; if(iwe.u.data.length > 32) iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); /* Add mode */ iwe.cmd = SIOCGIWMODE; - capabilities = le16_to_cpu(list->cap); + capabilities = le16_to_cpu(bss->cap); if(capabilities & (CAP_ESS | CAP_IBSS)) { if(capabilities & CAP_ESS) iwe.u.mode = IW_MODE_MASTER; @@ -6797,19 +6845,25 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Add frequency */ iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = le16_to_cpu(list->dsChannel); + iwe.u.freq.m = le16_to_cpu(bss->dsChannel); iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000; iwe.u.freq.e = 1; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); /* Add quality statistics */ iwe.cmd = IWEVQUAL; - if (ai->rssi) - iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm; - else - iwe.u.qual.level = (list->rssi + 321) / 2; - iwe.u.qual.noise = 0; - iwe.u.qual.qual = 0; + if (ai->rssi) { + iwe.u.qual.level = 0x100 - bss->dBm; + iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm ); + iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED; + } else { + iwe.u.qual.level = (bss->dBm + 321) / 2; + iwe.u.qual.qual = 0; + iwe.u.qual.updated = IW_QUAL_QUAL_INVALID; + } + iwe.u.qual.noise = ai->wstats.qual.noise; + iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_UPDATED; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ @@ -6819,7 +6873,7 @@ static inline char *airo_translate_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); /* Rate : stuffing multiple values in a single event require a bit * more of magic - Jean II */ @@ -6831,10 +6885,10 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Max 8 values */ for(i = 0 ; i < 8 ; i++) { /* NULL terminated */ - if(list->rates[i] == 0) + if(bss->rates[i] == 0) break; /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000); + iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); /* Add new value to event */ current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } @@ -7153,18 +7207,22 @@ static void airo_read_wireless_stats(struct airo_info *local) /* The status */ local->wstats.status = status_rid.mode; - /* Signal quality and co. But where is the noise level ??? */ - local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); - if (local->rssi) - local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm; - else + /* Signal quality and co */ + if (local->rssi) { + local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality ); + /* normalizedSignalStrength appears to be a percentage */ + local->wstats.qual.qual = status_rid.normalizedSignalStrength; + } else { local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; + local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); + } + local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED; if (status_rid.len >= 124) { - local->wstats.qual.noise = 256 - status_rid.noisedBm; - local->wstats.qual.updated = 7; + local->wstats.qual.noise = 0x100 - status_rid.noisedBm; + local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED; } else { local->wstats.qual.noise = 0; - local->wstats.qual.updated = 3; + local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID; } /* Packets discarded in the wireless adapter due to wireless -- cgit v1.1 From 1bcd315362e215a72b56d1330bbf32f1c74eefb5 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Fri, 29 Apr 2005 14:51:17 -0700 Subject: [PATCH] pcnet32: fix resource leak with loopback test When running the loopback test, resources are not properly released on completion. This patch frees all transmit resources after running the loopback test. Tested on ia32 and ppc64 hardware. Signed-off-by: Don Fry --- drivers/net/pcnet32.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 17947e6..13f1148 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.30i" -#define DRV_RELDATE "06.28.2004" +#define DRV_VERSION "1.30j" +#define DRV_RELDATE "29.04.2005" #define PFX DRV_NAME ": " static const char *version = @@ -256,6 +256,7 @@ static int homepna[MAX_UNITS]; * homepna for selecting HomePNA mode for PCNet/Home 79C978. * v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32. * v1.30i 28 Jun 2004 Don Fry change to use module_param. + * v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test. */ @@ -395,6 +396,7 @@ static void pcnet32_led_blink_callback(struct net_device *dev); static int pcnet32_get_regs_len(struct net_device *dev); static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *ptr); +static void pcnet32_purge_tx_ring(struct net_device *dev); enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, @@ -785,6 +787,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) } clean_up: + pcnet32_purge_tx_ring(dev); x = a->read_csr(ioaddr, 15) & 0xFFFF; a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ -- cgit v1.1 From 6da0f685935e13458a2206ac872d0d3c67a52f65 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 30 Apr 2005 13:52:49 +0200 Subject: [PATCH] SIS900 must select MII This patch fixes the following compile error caused by bk-netdev: <-- snip --> ... LD .tmp_vmlinux1 drivers/built-in.o(.text+0x98528): In function `sis900_get_settings': : undefined reference to `mii_ethtool_gset' drivers/built-in.o(.text+0x98538): In function `sis900_set_settings': : undefined reference to `mii_ethtool_sset' drivers/built-in.o(.text+0x98517): In function `sis900_get_link': : undefined reference to `mii_link_ok' drivers/built-in.o(.text+0x98547): In function `sis900_nway_reset': : undefined reference to `mii_nway_restart' make: *** [.tmp_vmlinux1] Error 1 <-- snip --> Signed-off-by: Adrian Bunk Signed-off-by: Daniele Venzano --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3a0a55b..7c5c1ac 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1555,6 +1555,7 @@ config SIS900 tristate "SiS 900/7016 PCI Fast Ethernet Adapter support" depends on NET_PCI && PCI select CRC32 + select MII ---help--- This is a driver for the Fast Ethernet PCI network cards based on the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in -- cgit v1.1 From 15efa9bb2d4da7cd9feb1c67fcf3d9e0e1bd00c6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 4 May 2005 15:33:11 -0700 Subject: [PATCH] tlan: restore deleted module parameters. The module parameter values got lost in the conversion to the new module_param interface. This should fix it. Signed-off-by: Stephen Hemminger Index: tlan/drivers/net/tlan.c =================================================================== --- drivers/net/tlan.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index a7ffa64..f0851c4 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -193,6 +193,12 @@ static int aui[MAX_TLAN_BOARDS]; static int duplex[MAX_TLAN_BOARDS]; static int speed[MAX_TLAN_BOARDS]; static int boards_found; +module_param_array(aui, int, NULL, 0); +module_param_array(duplex, int, NULL, 0); +module_param_array(speed, int, NULL, 0); +MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)"); +MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)"); +MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)"); MODULE_AUTHOR("Maintainer: Samuel Chessman "); MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters"); @@ -204,8 +210,13 @@ MODULE_LICENSE("GPL"); /* Turn on debugging. See Documentation/networking/tlan.txt for details */ static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "ThunderLAN debug mask"); static int bbuf; +module_param(bbuf, int, 0); +MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)"); + static u8 *TLanPadBuffer; static dma_addr_t TLanPadBufferDMA; static char TLanSignature[] = "TLAN"; -- cgit v1.1 From 4b40033ef110b833986c1a1d958a951b695f9fbc Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Sun, 15 May 2005 16:01:50 -0700 Subject: [SPARC]: Eliminate local MIN/MAX macros in drivers/sbus/char/aurora.c From: Christophe Lucas min/max macros from kernel.h are safe, a lot of handcrafted MIN/MAX are not. Signed-off-by: Christophe Lucas Signed-off-by: Domen Puncer --- drivers/sbus/char/aurora.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index e5fa170..650d5e9 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -81,10 +81,6 @@ unsigned char irqs[4] = { int irqhit=0; #endif -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - static struct tty_driver *aurora_driver; static struct Aurora_board aurora_board[AURORA_NBOARD] = { {0,}, @@ -594,7 +590,7 @@ static void aurora_transmit(struct Aurora_board const * bp, int chip) &bp->r[chip]->r[CD180_TDR]); port->COR2 &= ~COR2_ETC; } - count = MIN(port->break_length, 0xff); + count = min(port->break_length, 0xff); sbus_writeb(CD180_C_ESC, &bp->r[chip]->r[CD180_TDR]); sbus_writeb(CD180_C_DELAY, @@ -1575,7 +1571,7 @@ static int aurora_write(struct tty_struct * tty, save_flags(flags); while (1) { cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + c = min(count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, SERIAL_XMIT_SIZE - port->xmit_head)); if (c <= 0) { restore_flags(flags); -- cgit v1.1 From c16ef1ceedff27c1b452724ca7f89b729651098f Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Wed, 6 Apr 2005 11:17:59 -0400 Subject: [PATCH] ns83820 update Changes: - improved DAC ifdefs from Andi Kleen - removal of dead code from Adrian Bunk - fix half duplex collision behaviour --- drivers/net/ns83820.c | 69 ++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 2fcc181..c336b46 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1,4 +1,4 @@ -#define _VERSION "0.20" +#define VERSION "0.22" /* ns83820.c by Benjamin LaHaise with contributions. * * Questions/comments/discussion to linux-ns83820@kvack.org. @@ -63,9 +63,11 @@ * - fix missed txok introduced during performance * tuning * 0.20 - fix stupid RFEN thinko. i am such a smurf. - * * 20040828 0.21 - add hardware vlan accleration * by Neil Horman + * 20050406 0.22 - improved DAC ifdefs from Andi Kleen + * - removal of dead code from Adrian Bunk + * - fix half duplex collision behaviour * Driver Overview * =============== * @@ -129,18 +131,6 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #undef Dprintk #define Dprintk dprintk -#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__) -#define USE_64BIT_ADDR "+" -#endif - -#if defined(USE_64BIT_ADDR) -#define VERSION _VERSION USE_64BIT_ADDR -#define TRY_DAC 1 -#else -#define VERSION _VERSION -#define TRY_DAC 0 -#endif - /* tunables */ #define RX_BUF_SIZE 1500 /* 8192 */ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -386,22 +376,16 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define LINK_DOWN 0x02 #define LINK_UP 0x04 -#ifdef USE_64BIT_ADDR -#define HW_ADDR_LEN 8 +#define HW_ADDR_LEN sizeof(dma_addr_t) #define desc_addr_set(desc, addr) \ do { \ - u64 __addr = (addr); \ - (desc)[0] = cpu_to_le32(__addr); \ - (desc)[1] = cpu_to_le32(__addr >> 32); \ + ((desc)[0] = cpu_to_le32(addr)); \ + if (HW_ADDR_LEN == 8) \ + (desc)[1] = cpu_to_le32(((u64)addr) >> 32); \ } while(0) #define desc_addr_get(desc) \ - (((u64)le32_to_cpu((desc)[1]) << 32) \ - | le32_to_cpu((desc)[0])) -#else -#define HW_ADDR_LEN 4 -#define desc_addr_set(desc, addr) ((desc)[0] = cpu_to_le32(addr)) -#define desc_addr_get(desc) (le32_to_cpu((desc)[0])) -#endif + (le32_to_cpu((desc)[0]) | \ + (HW_ADDR_LEN == 8 ? ((dma_addr_t)le32_to_cpu((desc)[1]))<<32 : 0)) #define DESC_LINK 0 #define DESC_BUFPTR (DESC_LINK + HW_ADDR_LEN/4) @@ -727,11 +711,23 @@ static void fastcall phy_intr(struct net_device *ndev) speed = ((cfg / CFG_SPDSTS0) & 3); fullduplex = (cfg & CFG_DUPSTS); - if (fullduplex) + if (fullduplex) { new_cfg |= CFG_SB; + writel(readl(dev->base + TXCFG) + | TXCFG_CSI | TXCFG_HBI, + dev->base + TXCFG); + writel(readl(dev->base + RXCFG) | RXCFG_RX_FD, + dev->base + RXCFG); + } else { + writel(readl(dev->base + TXCFG) + & ~(TXCFG_CSI | TXCFG_HBI), + dev->base + TXCFG); + writel(readl(dev->base + RXCFG) & ~(RXCFG_RX_FD), + dev->base + RXCFG); + } if ((cfg & CFG_LNKSTS) && - ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) { + ((new_cfg ^ dev->CFG_cache) != 0)) { writel(new_cfg, dev->base + CFG); dev->CFG_cache = new_cfg; } @@ -1189,7 +1185,6 @@ again: for (;;) { volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); - u32 residue = 0; dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len, (unsigned long long)buf); @@ -1199,17 +1194,11 @@ again: desc_addr_set(desc + DESC_BUFPTR, buf); desc[DESC_EXTSTS] = cpu_to_le32(extsts); - cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); + cmdsts = ((nr_frags) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN; cmdsts |= len; desc[DESC_CMDSTS] = cpu_to_le32(cmdsts); - if (residue) { - buf += len; - len = residue; - continue; - } - if (!nr_frags) break; @@ -1841,7 +1830,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ int using_dac = 0; /* See if we can set the dma mask early on; failure is fatal. */ - if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { + if (sizeof(dma_addr_t) == 8 && + !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { using_dac = 1; } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) { using_dac = 0; @@ -1972,9 +1962,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ /* When compiled with 64 bit addressing, we must always enable * the 64 bit descriptor format. */ -#ifdef USE_64BIT_ADDR - dev->CFG_cache |= CFG_M64ADDR; -#endif + if (sizeof(dma_addr_t) == 8) + dev->CFG_cache |= CFG_M64ADDR; if (using_dac) dev->CFG_cache |= CFG_T64ADDR; -- cgit v1.1 From 562faf469f35bf63c0b021550811280c81bdc52e Mon Sep 17 00:00:00 2001 From: James Harper Date: Thu, 5 May 2005 15:14:18 -0700 Subject: [PATCH] fix PROMISC/bridging in TLAN driver This has been a problem for me for ages. When using bridging, the driver is switched into promiscuous mode before the link init is complete. The init complete routine then resets the promisc bit on the card so the kernel still thinks the card is in promiscuous mode but the card isn't. doh. I think this bug only shows up in bridging when the bridge is started at boot time (or something else that sets promisc at the same time the card was started). If promisc is enabled later it works. Here's a trivial (and hopefully correct) patch that works for me. It just calls the promisc/multicast setup routine after init. Cc: Jeff Garzik Signed-off-by: Andrew Morton --- drivers/net/tlan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index f0851c4..9680a30 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -2392,6 +2392,7 @@ TLan_FinishReset( struct net_device *dev ) TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET ); return; } + TLan_SetMulticastList(dev); } /* TLan_FinishReset */ -- cgit v1.1 From 67594feb4b68074d8807f5566536e06db9130679 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 17 May 2005 13:04:49 -0500 Subject: [CIFS] missing break needed to handle < when mount option "mapchars" specified Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/README | 4 ++-- fs/cifs/misc.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/cifs/README b/fs/cifs/README index e74df0c..34b0cf7 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -371,7 +371,7 @@ A partial list of the supported mount options follows: on newly created files, directories, and devices (create, mkdir, mknod) which will result in the server setting the uid and gid to the default (usually the server uid of the - usern who mounted the share). Letting the server (rather than + user who mounted the share). Letting the server (rather than the client) set the uid and gid is the default. This parameter has no effect if the CIFS Unix Extensions are not negotiated. @@ -384,7 +384,7 @@ A partial list of the supported mount options follows: client (e.g. when the application is doing large sequential reads bigger than page size without rereading the same data) this can provide better performance than the default - behavior which caches reads (reaadahead) and writes + behavior which caches reads (readahead) and writes (writebehind) through the local Linux client pagecache if oplock (caching token) is granted and held. Note that direct allows write operations larger than page size diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index db14b50..072b4ee 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -571,6 +571,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, break; case UNI_LESSTHAN: target[j] = '<'; + break; default: len = cp->uni2char(src_char, &target[j], NLS_MAX_CHARSET_SIZE); -- cgit v1.1 From b2aeb9d565be5ef00fb9f921c6d2459c74d90cdf Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 17 May 2005 13:16:18 -0500 Subject: [CIFS] Fix oops in cifs_unlink. Caused in some cases when renaming over existing, newly created, file. Samba bugzilla: 2697 Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/dir.c | 3 ++- fs/cifs/inode.c | 24 +++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e3137aa..3f3538d 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name rc = 0; d_add(direntry, NULL); } else { - cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc)); + cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", + rc,full_path)); /* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6709472..b8b78cb 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { - direntry->d_inode->i_nlink--; + if(direntry->d_inode) + direntry->d_inode->i_nlink--; } else if (rc == -ENOENT) { d_drop(direntry); } else if (rc == -ETXTBSY) { @@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); CIFSSMBClose(xid, pTcon, netfid); - direntry->d_inode->i_nlink--; + if(direntry->d_inode) + direntry->d_inode->i_nlink--; } } else if (rc == -EACCES) { /* try only if r/o attribute set in local lookup data? */ @@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { - direntry->d_inode->i_nlink--; + if(direntry->d_inode) + direntry->d_inode->i_nlink--; } else if (rc == -ETXTBSY) { int oplock = FALSE; __u16 netfid; @@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); CIFSSMBClose(xid, pTcon, netfid); - direntry->d_inode->i_nlink--; + if(direntry->d_inode) + direntry->d_inode->i_nlink--; } /* BB if rc = -ETXTBUSY goto the rename logic BB */ } } } - cifsInode = CIFS_I(direntry->d_inode); - cifsInode->time = 0; /* will force revalidate to get info when - needed */ - direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = - current_fs_time(inode->i_sb); + if(direntry->d_inode) { + cifsInode = CIFS_I(direntry->d_inode); + cifsInode->time = 0; /* will force revalidate to get info + when needed */ + direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); + } + inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); cifsInode = CIFS_I(inode); cifsInode->time = 0; /* force revalidate of dir as well */ -- cgit v1.1 From 02a017a9f37ae6842e065da919b5952eb847e869 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Tue, 10 May 2005 11:35:00 -0700 Subject: [IA64] Correct convert_to_non_syscall() convert_to_non_syscall() has the same problem that unwind_to_user() used to have. Fix it likewise. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/kernel/ptrace.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 907464e..08c8a5e 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -692,16 +692,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt, unsigned long cfm) { struct unw_frame_info info, prev_info; - unsigned long ip, pr; + unsigned long ip, sp, pr; unw_init_from_blocked_task(&info, child); while (1) { prev_info = info; if (unw_unwind(&info) < 0) return; - if (unw_get_rp(&info, &ip) < 0) + + unw_get_sp(&info, &sp); + if ((long)((unsigned long)child + IA64_STK_OFFSET - sp) + < IA64_PT_REGS_SIZE) { + dprintk("ptrace.%s: ran off the top of the kernel " + "stack\n", __FUNCTION__); + return; + } + if (unw_get_pr (&prev_info, &pr) < 0) { + unw_get_rp(&prev_info, &ip); + dprintk("ptrace.%s: failed to read " + "predicate register (ip=0x%lx)\n", + __FUNCTION__, ip); return; - if (ip < FIXADDR_USER_END) + } + if (unw_is_intr_frame(&info) + && (pr & (1UL << PRED_USER_STACK))) break; } -- cgit v1.1 From 056b5033fb8d16095fb074fc910fad90186374f3 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 9 May 2005 14:52:00 -0700 Subject: [PATCH] update sn2 maintainer Now that I'm no longer at SGI and don't have access to Altix equipment, it's time to pass on the job of patch monkey to someone else. Greg Edwards has foolishly^Wkindly volunteered for the job, so here's a patch to update the MAINTAINERS file with the appropriate information. Signed-off-by: Jesse Barnes Signed-off-by: Tony Luck --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5b84833..97bc927 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1023,8 +1023,8 @@ W: http://www.ia64-linux.org/ S: Maintained SN-IA64 (Itanium) SUB-PLATFORM -P: Jesse Barnes -M: jbarnes@sgi.com +P: Greg Edwards +M: edwardsg@sgi.com L: linux-altix@sgi.com L: linux-ia64@vger.kernel.org W: http://www.sgi.com/altix -- cgit v1.1 From bb68c12b40c3c745381d7ce61d7b2e371f157505 Mon Sep 17 00:00:00 2001 From: Russ Anderson <(rja@sgi.com)> Date: Mon, 9 May 2005 15:03:00 -0700 Subject: [IA64-SGI] cpe interrupts are not being enabled. acpi_request_vector() is called in ia64_mca_init() to get the cpe_vector. The problem is that acpi_request_vector() looks in platform_intr_list[] to get the vector, but platform_intr_list[] is not initialized with a valid vector until later (in sn_setup()). Without a valid vector the code defaults to polling mode. This patch moves the call to acpi_request_vector() from ia64_mca_init() to ia64_mca_late_init(), which is after platform_intr_list[] is initialized. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck --- arch/ia64/kernel/mca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 4d6c7b8f..2c75741 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1390,8 +1390,7 @@ ia64_mca_init(void) register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); #ifdef CONFIG_ACPI - /* Setup the CPEI/P vector and handler */ - cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI); + /* Setup the CPEI/P handler */ register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); #endif @@ -1436,6 +1435,7 @@ ia64_mca_late_init(void) #ifdef CONFIG_ACPI /* Setup the CPEI/P vector and handler */ + cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI); init_timer(&cpe_poll_timer); cpe_poll_timer.function = ia64_mca_cpe_poll; -- cgit v1.1 From 8eac3757158ccd9c6b43f44f228a5762fec33781 Mon Sep 17 00:00:00 2001 From: Russ Anderson <(rja@sgi.com)> Date: Mon, 16 May 2005 15:19:00 -0700 Subject: [IA64-SGI] Make Altix SAL call to POD reentrant Change the SAL call for POD mode to be reentrant. This change is SN specific. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck --- include/asm-ia64/sn/sn_sal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 56d74ca..94cc539 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -472,7 +472,7 @@ static inline u64 ia64_sn_pod_mode(void) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SN_SAL_POD_MODE, 0, 0, 0, 0, 0, 0, 0); + SAL_CALL_REENTRANT(isrv, SN_SAL_POD_MODE, 0, 0, 0, 0, 0, 0, 0); if (isrv.status) return 0; return isrv.v0; -- cgit v1.1 From 6872ec548970e9fb3ccd61013f84f9bb8b30fa9a Mon Sep 17 00:00:00 2001 From: Russ Anderson <(rja@sgi.com)> Date: Mon, 16 May 2005 15:30:00 -0700 Subject: [IS64-SGI] Set Altix error handling features The 2.6 kernel has CPE error thresholding. This patch lets SAL know of this error handling feature. The changes are SN specific. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/setup.c | 2 ++ include/asm-ia64/sn/sn_sal.h | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 4fb4498..e64cb81 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -271,6 +271,8 @@ void __init sn_setup(char **cmdline_p) int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); extern void sn_cpu_init(void); + ia64_sn_plat_set_error_handling_features(); + /* * If the generic code has enabled vga console support - lets * get rid of it again. This is a kludge for the fact that ACPI diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 94cc539..eb0395a 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -115,6 +115,13 @@ #define SAL_IROUTER_INTR_XMIT SAL_CONSOLE_INTR_XMIT #define SAL_IROUTER_INTR_RECV SAL_CONSOLE_INTR_RECV +/* + * Error Handling Features + */ +#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV 0x1 +#define SAL_ERR_FEAT_LOG_SBES 0x2 +#define SAL_ERR_FEAT_MFR_OVERRIDE 0x4 +#define SAL_ERR_FEAT_SBE_THRESHOLD 0xffff0000 /* * SAL Error Codes @@ -342,6 +349,25 @@ ia64_sn_plat_cpei_handler(void) } /* + * Set Error Handling Features + */ +static inline u64 +ia64_sn_plat_set_error_handling_features(void) +{ + struct ia64_sal_retval ret_stuff; + + ret_stuff.status = 0; + ret_stuff.v0 = 0; + ret_stuff.v1 = 0; + ret_stuff.v2 = 0; + SAL_CALL_REENTRANT(ret_stuff, SN_SAL_SET_ERROR_HANDLING_FEATURES, + (SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV | SAL_ERR_FEAT_LOG_SBES), + 0, 0, 0, 0, 0, 0); + + return ret_stuff.status; +} + +/* * Checks for console input. */ static inline u64 -- cgit v1.1 From b1a45695bde0204597957e448923f09ce271ca80 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 17 May 2005 16:07:23 -0500 Subject: [CIFS] fix casts of unicode strings to match function definition Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/cifsproto.h | 2 +- fs/cifs/cifssmb.c | 56 ++++++++++++++++++++++++++--------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0010511..ea239de 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -228,7 +228,7 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const struct nls_table *nls_codepage, int remap_special_chars); #endif /* CONFIG_CIFS_EXPERIMENTAL */ -extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, +extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, const struct nls_table * codepage); extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, const struct nls_table * cp, int mapChars); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 741ff0c..3c628bf 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -567,7 +567,7 @@ DelFileRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->fileName, fileName, + cifsConvertToUCS((__le16 *) pSMB->fileName, fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -665,7 +665,7 @@ MkDirRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name, + name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -719,7 +719,7 @@ openRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { count = 1; /* account for one byte pad to word boundary */ name_len = - cifsConvertToUCS((__u16 *) (pSMB->fileName + 1), + cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -1141,7 +1141,7 @@ renameRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, + cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -1149,7 +1149,7 @@ renameRetry: /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = - cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2], + cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ @@ -1236,10 +1236,10 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, /* unicode only call */ if(target_name == NULL) { sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); - len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, + len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, dummy_string, 24, nls_codepage, remap); } else { - len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, + len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, target_name, PATH_MAX, nls_codepage, remap); } rename_info->target_name_len = cpu_to_le32(2 * len_of_str); @@ -1296,7 +1296,7 @@ copyRetry: pSMB->Flags = cpu_to_le16(flags & COPY_TREE); if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName, + name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ @@ -1304,7 +1304,7 @@ copyRetry: pSMB->OldFileName[name_len] = 0x04; /* pad */ /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; - name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], + name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ @@ -1453,7 +1453,7 @@ createHardLinkRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName, + name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -1476,7 +1476,7 @@ createHardLinkRetry: data_offset = (char *) (&pSMB->hdr.Protocol) + offset; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = - cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX, + cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX, nls_codepage, remap); name_len_target++; /* trailing null */ name_len_target *= 2; @@ -1546,14 +1546,14 @@ winCreateHardLinkRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, + cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->OldFileName[name_len] = 0; /* pad */ pSMB->OldFileName[name_len + 1] = 0x04; name_len2 = - cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], + cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ @@ -1939,7 +1939,7 @@ queryAclRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -2024,7 +2024,7 @@ setAclRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -2188,7 +2188,7 @@ QPathInfoRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -2269,7 +2269,7 @@ UnixQPathInfoRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -2350,7 +2350,7 @@ findUniqueRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ @@ -2435,7 +2435,7 @@ findFirstRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName,searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName,searchName, PATH_MAX, nls_codepage, remap); /* We can not add the asterik earlier in case it got remapped to 0xF03A as if it were part of the @@ -2726,7 +2726,7 @@ GetInodeNumberRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX,nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -2837,7 +2837,7 @@ getDFSRetry: if (ses->capabilities & CAP_UNICODE) { pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; name_len = - cifsConvertToUCS((__u16 *) pSMB->RequestFileName, + cifsConvertToUCS((__le16 *) pSMB->RequestFileName, searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -3369,7 +3369,7 @@ SetEOFRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -3627,7 +3627,7 @@ SetTimesRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -3708,7 +3708,7 @@ SetAttrLgcyRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - ConvertToUCS((wchar_t *) pSMB->fileName, fileName, + ConvertToUCS((__le16 *) pSMB->fileName, fileName, PATH_MAX, nls_codepage); name_len++; /* trailing null */ name_len *= 2; @@ -3759,7 +3759,7 @@ setPermsRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -3904,7 +3904,7 @@ QAllEAsRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -4047,7 +4047,7 @@ QEARetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -4194,7 +4194,7 @@ SetEARetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; -- cgit v1.1 From a1ecf7f6e65637ba4470405ad39794710dbf85d4 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 18 May 2005 16:06:00 -0700 Subject: [IA64] alternate perfmon handler Patch from Charles Spirakis Some linux customers want to optimize their applications on the latest hardware but are not yet willing to upgrade to the latest kernel. This patch provides a way to plug in an alternate, basic, and GPL'ed PMU subsystem to help with their monitoring needs or for specialty work. It can also be used in case of serious unexpected bugs in perfmon. Mutual exclusion between the two subsystems is guaranteed, hence no conflict can arise from both subsystem being present. Acked-by: Stephane Eranian Signed-off-by: Tony Luck --- arch/ia64/kernel/perfmon.c | 175 +++++++++++++++++++++++++++++++++++++++++---- include/asm-ia64/perfmon.h | 8 +++ 2 files changed, 168 insertions(+), 15 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 71c1016..ab9682f 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -11,7 +11,7 @@ * Version Perfmon-2.x is a rewrite of perfmon-1.x * by Stephane Eranian, Hewlett Packard Co. * - * Copyright (C) 1999-2003, 2005 Hewlett Packard Co + * Copyright (C) 1999-2005 Hewlett Packard Co * Stephane Eranian * David Mosberger-Tang * @@ -497,6 +497,9 @@ typedef struct { static pfm_stats_t pfm_stats[NR_CPUS]; static pfm_session_t pfm_sessions; /* global sessions information */ +static spinlock_t pfm_alt_install_check; +static pfm_intr_handler_desc_t *pfm_alt_intr_handler; + static struct proc_dir_entry *perfmon_dir; static pfm_uuid_t pfm_null_uuid = {0,}; @@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info); DEFINE_PER_CPU(struct task_struct *, pmu_owner); DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); DEFINE_PER_CPU(unsigned long, pmu_activation_number); +EXPORT_SYMBOL_GPL(per_cpu__pfm_syst_info); /* forward declaration */ @@ -1325,7 +1329,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) error_conflict: DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n", pfm_sessions.pfs_sys_session[cpu]->pid, - smp_processor_id())); + cpu)); abort: UNLOCK_PFS(flags); @@ -5555,26 +5559,32 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) int ret; this_cpu = get_cpu(); - min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; - max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; + if (likely(!pfm_alt_intr_handler)) { + min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; + max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; - start_cycles = ia64_get_itc(); + start_cycles = ia64_get_itc(); - ret = pfm_do_interrupt_handler(irq, arg, regs); + ret = pfm_do_interrupt_handler(irq, arg, regs); - total_cycles = ia64_get_itc(); + total_cycles = ia64_get_itc(); - /* - * don't measure spurious interrupts - */ - if (likely(ret == 0)) { - total_cycles -= start_cycles; + /* + * don't measure spurious interrupts + */ + if (likely(ret == 0)) { + total_cycles -= start_cycles; - if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles; - if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles; + if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles; + if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles; - pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; + pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; + } + } + else { + (*pfm_alt_intr_handler->handler)(irq, arg, regs); } + put_cpu_no_resched(); return IRQ_HANDLED; } @@ -6425,6 +6435,141 @@ static struct irqaction perfmon_irqaction = { .name = "perfmon" }; +static void +pfm_alt_save_pmu_state(void *data) +{ + struct pt_regs *regs; + + regs = ia64_task_regs(current); + + DPRINT(("called\n")); + + /* + * should not be necessary but + * let's take not risk + */ + pfm_clear_psr_up(); + pfm_clear_psr_pp(); + ia64_psr(regs)->pp = 0; + + /* + * This call is required + * May cause a spurious interrupt on some processors + */ + pfm_freeze_pmu(); + + ia64_srlz_d(); +} + +void +pfm_alt_restore_pmu_state(void *data) +{ + struct pt_regs *regs; + + regs = ia64_task_regs(current); + + DPRINT(("called\n")); + + /* + * put PMU back in state expected + * by perfmon + */ + pfm_clear_psr_up(); + pfm_clear_psr_pp(); + ia64_psr(regs)->pp = 0; + + /* + * perfmon runs with PMU unfrozen at all times + */ + pfm_unfreeze_pmu(); + + ia64_srlz_d(); +} + +int +pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl) +{ + int ret, i; + int reserve_cpu; + + /* some sanity checks */ + if (hdl == NULL || hdl->handler == NULL) return -EINVAL; + + /* do the easy test first */ + if (pfm_alt_intr_handler) return -EBUSY; + + /* one at a time in the install or remove, just fail the others */ + if (!spin_trylock(&pfm_alt_install_check)) { + return -EBUSY; + } + + /* reserve our session */ + for_each_online_cpu(reserve_cpu) { + ret = pfm_reserve_session(NULL, 1, reserve_cpu); + if (ret) goto cleanup_reserve; + } + + /* save the current system wide pmu states */ + ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1); + if (ret) { + DPRINT(("on_each_cpu() failed: %d\n", ret)); + goto cleanup_reserve; + } + + /* officially change to the alternate interrupt handler */ + pfm_alt_intr_handler = hdl; + + spin_unlock(&pfm_alt_install_check); + + return 0; + +cleanup_reserve: + for_each_online_cpu(i) { + /* don't unreserve more than we reserved */ + if (i >= reserve_cpu) break; + + pfm_unreserve_session(NULL, 1, i); + } + + spin_unlock(&pfm_alt_install_check); + + return ret; +} +EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt); + +int +pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl) +{ + int i; + int ret; + + if (hdl == NULL) return -EINVAL; + + /* cannot remove someone else's handler! */ + if (pfm_alt_intr_handler != hdl) return -EINVAL; + + /* one at a time in the install or remove, just fail the others */ + if (!spin_trylock(&pfm_alt_install_check)) { + return -EBUSY; + } + + pfm_alt_intr_handler = NULL; + + ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1); + if (ret) { + DPRINT(("on_each_cpu() failed: %d\n", ret)); + } + + for_each_online_cpu(i) { + pfm_unreserve_session(NULL, 1, i); + } + + spin_unlock(&pfm_alt_install_check); + + return 0; +} +EXPORT_SYMBOL_GPL(pfm_remove_alt_pmu_interrupt); + /* * perfmon initialization routine, called from the initcall() table */ diff --git a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h index ed5416c..7f3333d 100644 --- a/include/asm-ia64/perfmon.h +++ b/include/asm-ia64/perfmon.h @@ -177,6 +177,10 @@ typedef union { extern long perfmonctl(int fd, int cmd, void *arg, int narg); +typedef struct { + void (*handler)(int irq, void *arg, struct pt_regs *regs); +} pfm_intr_handler_desc_t; + extern void pfm_save_regs (struct task_struct *); extern void pfm_load_regs (struct task_struct *); @@ -187,6 +191,10 @@ extern void pfm_syst_wide_update_task(struct task_struct *, unsigned long info, extern void pfm_inherit(struct task_struct *task, struct pt_regs *regs); extern void pfm_init_percpu(void); extern void pfm_handle_work(void); +extern int pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *h); +extern int pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *h); + + /* * Reset PMD register flags -- cgit v1.1 From fe12e25ebdd195a57d3fd655061fd2525609b16b Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 18 May 2005 17:09:06 -0700 Subject: [IA64] initialize spinlock pfm_alt_install_check I applied the penultimate version of the perfmon patch, which didn't have the initialization of the new spinlock that was added. Signed-off-by: Tony Luck --- arch/ia64/kernel/perfmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index ab9682f..0e58ec7 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -497,7 +497,7 @@ typedef struct { static pfm_stats_t pfm_stats[NR_CPUS]; static pfm_session_t pfm_sessions; /* global sessions information */ -static spinlock_t pfm_alt_install_check; +static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED; static pfm_intr_handler_desc_t *pfm_alt_intr_handler; static struct proc_dir_entry *perfmon_dir; -- cgit v1.1 From fac9b83ea79aa3112ed245d9a4fc2a5c3ec2b7ec Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2005 22:46:34 -0700 Subject: [TG3]: Add tagged status support. When supported, use the TAGGED interrupt processing support the chip provides. In this mode, instead of a "on/off" binary semaphore, an incrementing tag scheme is used to ACK interrupts. All MSI supporting chips support TAGGED mode, so the tg3_msi() interrupt handler uses it unconditionally. This invariant is verified when MSI support is tested. Since we can invoke tg3_poll() multiple times per interrupt under high packet load, we fetch a new copy of the tag value in the status block right before we actually do the work. Also, because the tagged status tells the chip exactly which work we have processed, we can make two optimizations: 1) tg3_restart_ints() need not check tg3_has_work() 2) the tg3_timer() need not poke the chip 10 times per second to keep from losing interrupt events Based upon valuable feedback from Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 195 +++++++++++++++++++++++++++++++++++++++--------------- drivers/net/tg3.h | 2 + 2 files changed, 142 insertions(+), 55 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f79b02e..488b8c6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -420,7 +420,8 @@ static void tg3_enable_ints(struct tg3 *tp) { tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + (tp->last_tag << 24)); tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); tg3_cond_int(tp); @@ -455,10 +456,16 @@ static void tg3_restart_ints(struct tg3 *tp) { tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); - tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + tp->last_tag << 24); mmiowb(); - if (tg3_has_work(tp)) + /* When doing tagged status, this work check is unnecessary. + * The last_tag we write above tells the chip which piece of + * work we've completed. + */ + if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) && + tg3_has_work(tp)) tw32(HOSTCC_MODE, tp->coalesce_mode | (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); } @@ -2862,6 +2869,9 @@ static int tg3_poll(struct net_device *netdev, int *budget) spin_lock_irqsave(&tp->lock, flags); + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + tp->last_tag = sblk->status_tag; + /* handle link change and other phy events */ if (!(tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | @@ -2928,22 +2938,21 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs) spin_lock_irqsave(&tp->lock, flags); /* - * writing any value to intr-mbox-0 clears PCI INTA# and + * Writing any value to intr-mbox-0 clears PCI INTA# and * chip-internal interrupt pending events. - * writing non-zero to intr-mbox-0 additional tells the + * Writing non-zero to intr-mbox-0 additional tells the * NIC to stop sending us irqs, engaging "in-intr-handler" * event coalescing. */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + tp->last_tag = sblk->status_tag; sblk->status &= ~SD_STATUS_UPDATED; - if (likely(tg3_has_work(tp))) netif_rx_schedule(dev); /* schedule NAPI poll */ else { - /* no work, re-enable interrupts - */ + /* No work, re-enable interrupts. */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000000); + tp->last_tag << 24); } spin_unlock_irqrestore(&tp->lock, flags); @@ -2969,21 +2978,62 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) if ((sblk->status & SD_STATUS_UPDATED) || !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { /* - * writing any value to intr-mbox-0 clears PCI INTA# and + * Writing any value to intr-mbox-0 clears PCI INTA# and * chip-internal interrupt pending events. - * writing non-zero to intr-mbox-0 additional tells the + * Writing non-zero to intr-mbox-0 additional tells the * NIC to stop sending us irqs, engaging "in-intr-handler" * event coalescing. */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + sblk->status &= ~SD_STATUS_UPDATED; + if (likely(tg3_has_work(tp))) + netif_rx_schedule(dev); /* schedule NAPI poll */ + else { + /* No work, shared interrupt perhaps? re-enable + * interrupts, and flush that PCI write + */ + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + 0x00000000); + tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); + } + } else { /* shared interrupt */ + handled = 0; + } + + spin_unlock_irqrestore(&tp->lock, flags); + + return IRQ_RETVAL(handled); +} + +static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct tg3 *tp = netdev_priv(dev); + struct tg3_hw_status *sblk = tp->hw_status; + unsigned long flags; + unsigned int handled = 1; + + spin_lock_irqsave(&tp->lock, flags); + + /* In INTx mode, it is possible for the interrupt to arrive at + * the CPU before the status block posted prior to the interrupt. + * Reading the PCI State register will confirm whether the + * interrupt is ours and will flush the status block. + */ + if ((sblk->status & SD_STATUS_UPDATED) || + !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { /* - * Flush PCI write. This also guarantees that our - * status block has been flushed to host memory. + * writing any value to intr-mbox-0 clears PCI INTA# and + * chip-internal interrupt pending events. + * writing non-zero to intr-mbox-0 additional tells the + * NIC to stop sending us irqs, engaging "in-intr-handler" + * event coalescing. */ - tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, + 0x00000001); + tp->last_tag = sblk->status_tag; sblk->status &= ~SD_STATUS_UPDATED; - if (likely(tg3_has_work(tp))) netif_rx_schedule(dev); /* schedule NAPI poll */ else { @@ -2991,7 +3041,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) * interrupts, and flush that PCI write */ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, - 0x00000000); + tp->last_tag << 24); tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); } } else { /* shared interrupt */ @@ -5445,7 +5495,8 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(100); tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); - tr32(MAILBOX_INTERRUPT_0); + tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); + tp->last_tag = 0; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); @@ -5723,31 +5774,33 @@ static void tg3_timer(unsigned long __opaque) spin_lock_irqsave(&tp->lock, flags); spin_lock(&tp->tx_lock); - /* All of this garbage is because when using non-tagged - * IRQ status the mailbox/status_block protocol the chip - * uses with the cpu is race prone. - */ - if (tp->hw_status->status & SD_STATUS_UPDATED) { - tw32(GRC_LOCAL_CTRL, - tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); - } else { - tw32(HOSTCC_MODE, tp->coalesce_mode | - (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); - } + if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { + /* All of this garbage is because when using non-tagged + * IRQ status the mailbox/status_block protocol the chip + * uses with the cpu is race prone. + */ + if (tp->hw_status->status & SD_STATUS_UPDATED) { + tw32(GRC_LOCAL_CTRL, + tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); + } else { + tw32(HOSTCC_MODE, tp->coalesce_mode | + (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW)); + } - if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER; - spin_unlock(&tp->tx_lock); - spin_unlock_irqrestore(&tp->lock, flags); - schedule_work(&tp->reset_task); - return; + if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { + tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER; + spin_unlock(&tp->tx_lock); + spin_unlock_irqrestore(&tp->lock, flags); + schedule_work(&tp->reset_task); + return; + } } - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) - tg3_periodic_fetch_stats(tp); - /* This part only runs once per second. */ if (!--tp->timer_counter) { + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + tg3_periodic_fetch_stats(tp); + if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { u32 mac_stat; int phy_event; @@ -5846,9 +5899,13 @@ static int tg3_test_interrupt(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) err = request_irq(tp->pdev->irq, tg3_msi, SA_SAMPLE_RANDOM, dev->name, dev); - else - err = request_irq(tp->pdev->irq, tg3_interrupt, + else { + irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt; + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + fn = tg3_interrupt_tagged; + err = request_irq(tp->pdev->irq, fn, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + } if (err) return err; @@ -5900,9 +5957,14 @@ static int tg3_test_msi(struct tg3 *tp) tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; - err = request_irq(tp->pdev->irq, tg3_interrupt, - SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + { + irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt; + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + fn = tg3_interrupt_tagged; + err = request_irq(tp->pdev->irq, fn, + SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + } if (err) return err; @@ -5948,7 +6010,13 @@ static int tg3_open(struct net_device *dev) if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) && (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) { - if (pci_enable_msi(tp->pdev) == 0) { + /* All MSI supporting chips should support tagged + * status. Assert that this is the case. + */ + if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { + printk(KERN_WARNING PFX "%s: MSI without TAGGED? " + "Not using MSI.\n", tp->dev->name); + } else if (pci_enable_msi(tp->pdev) == 0) { u32 msi_mode; msi_mode = tr32(MSGINT_MODE); @@ -5959,9 +6027,14 @@ static int tg3_open(struct net_device *dev) if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) err = request_irq(tp->pdev->irq, tg3_msi, SA_SAMPLE_RANDOM, dev->name, dev); - else - err = request_irq(tp->pdev->irq, tg3_interrupt, + else { + irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt; + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + fn = tg3_interrupt_tagged; + + err = request_irq(tp->pdev->irq, fn, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + } if (err) { if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { @@ -5980,9 +6053,16 @@ static int tg3_open(struct net_device *dev) tg3_halt(tp, 1); tg3_free_rings(tp); } else { - tp->timer_offset = HZ / 10; - tp->timer_counter = tp->timer_multiplier = 10; - tp->asf_counter = tp->asf_multiplier = (10 * 120); + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + tp->timer_offset = HZ; + else + tp->timer_offset = HZ / 10; + + BUG_ON(tp->timer_offset > HZ); + tp->timer_counter = tp->timer_multiplier = + (HZ / tp->timer_offset); + tp->asf_counter = tp->asf_multiplier = + ((HZ / tp->timer_offset) * 120); init_timer(&tp->timer); tp->timer.expires = jiffies + tp->timer_offset; @@ -6005,6 +6085,7 @@ static int tg3_open(struct net_device *dev) if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { err = tg3_test_msi(tp); + if (err) { spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); @@ -8422,15 +8503,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; - /* Only 5701 and later support tagged irq status mode. - * Also, 5788 chips cannot use tagged irq status. - * - * However, since we are using NAPI avoid tagged irq status - * because the interrupt condition is more difficult to - * fully clear in that mode. - */ tp->coalesce_mode = 0; - if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) tp->coalesce_mode |= HOSTCC_MODE_32BYTE; @@ -8494,6 +8567,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) tp->tg3_flags2 |= TG3_FLG2_IS_5788; + if (!(tp->tg3_flags2 & TG3_FLG2_IS_5788) && + (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)) + tp->tg3_flags |= TG3_FLAG_TAGGED_STATUS; + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { + tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD | + HOSTCC_MODE_CLRTICK_TXBD); + + tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS; + pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, + tp->misc_host_ctrl); + } + /* these are limited to 10/100 only */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 8de6f21..44c6516 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2023,6 +2023,7 @@ struct tg3 { struct tg3_hw_status *hw_status; dma_addr_t status_mapping; + u32 last_tag; u32 msg_enable; @@ -2068,6 +2069,7 @@ struct tg3 { u32 rx_offset; u32 tg3_flags; +#define TG3_FLAG_TAGGED_STATUS 0x00000001 #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 #define TG3_FLAG_RX_CHECKSUMS 0x00000004 #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 -- cgit v1.1 From 15f9850d3c2d46f5851a424d2990a18b5bb5ebfd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2005 22:49:26 -0700 Subject: [TG3]: Set minimal hw interrupt mitigation. Even though we do software interrupt mitigation via NAPI, it still helps to have some minimal hw assisted mitigation. This helps, particularly, on systems where register I/O overhead is much greater than the CPU horsepower. For example, it helps on NUMA systems. In such cases the PIO overhead to disable interrupts for NAPI accounts for the majority of the packet processing cost. The CPU is fast enough such that only a single packet is processed by each NAPI poll call. Thanks to Michael Chan for reviewing this patch. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 72 +++++++++++++++++++++++++++++++++++++++++++++---------- drivers/net/tg3.h | 6 ++++- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 488b8c6..3df5b78 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2507,7 +2507,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { if (netif_carrier_ok(tp->dev)) { tw32(HOSTCC_STAT_COAL_TICKS, - DEFAULT_STAT_COAL_TICKS); + tp->coal.stats_block_coalesce_usecs); } else { tw32(HOSTCC_STAT_COAL_TICKS, 0); } @@ -5094,6 +5094,27 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, } static void __tg3_set_rx_mode(struct net_device *); +static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) +{ + tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs); + tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs); + tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames); + tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames); + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); + tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); + } + tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq); + tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq); + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { + u32 val = ec->stats_block_coalesce_usecs; + + if (!netif_carrier_ok(tp->dev)) + val = 0; + + tw32(HOSTCC_STAT_COAL_TICKS, val); + } +} /* tp->lock is held. */ static int tg3_reset_hw(struct tg3 *tp) @@ -5416,16 +5437,7 @@ static int tg3_reset_hw(struct tg3 *tp) udelay(10); } - tw32(HOSTCC_RXCOL_TICKS, 0); - tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS); - tw32(HOSTCC_RXMAX_FRAMES, 1); - tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { - tw32(HOSTCC_RXCOAL_TICK_INT, 0); - tw32(HOSTCC_TXCOAL_TICK_INT, 0); - } - tw32(HOSTCC_RXCOAL_MAXF_INT, 1); - tw32(HOSTCC_TXCOAL_MAXF_INT, 0); + tg3_set_coalesce(tp, &tp->coal); /* set status block DMA address */ tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, @@ -5438,8 +5450,6 @@ static int tg3_reset_hw(struct tg3 *tp) * the tg3_periodic_fetch_stats call there, and * tg3_get_stats to see how this works for 5705/5750 chips. */ - tw32(HOSTCC_STAT_COAL_TICKS, - DEFAULT_STAT_COAL_TICKS); tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, ((u64) tp->stats_mapping >> 32)); tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, @@ -7284,6 +7294,14 @@ static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) } #endif +static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) +{ + struct tg3 *tp = netdev_priv(dev); + + memcpy(ec, &tp->coal, sizeof(*ec)); + return 0; +} + static struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, @@ -7316,6 +7334,7 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_strings = tg3_get_strings, .get_stats_count = tg3_get_stats_count, .get_ethtool_stats = tg3_get_ethtool_stats, + .get_coalesce = tg3_get_coalesce, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) @@ -9096,6 +9115,31 @@ static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) return peer; } +static void __devinit tg3_init_coal(struct tg3 *tp) +{ + struct ethtool_coalesce *ec = &tp->coal; + + memset(ec, 0, sizeof(*ec)); + ec->cmd = ETHTOOL_GCOALESCE; + ec->rx_coalesce_usecs = LOW_RXCOL_TICKS; + ec->tx_coalesce_usecs = LOW_TXCOL_TICKS; + ec->rx_max_coalesced_frames = LOW_RXMAX_FRAMES; + ec->tx_max_coalesced_frames = LOW_TXMAX_FRAMES; + ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT; + ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT; + ec->rx_max_coalesced_frames_irq = DEFAULT_RXCOAL_MAXF_INT; + ec->tx_max_coalesced_frames_irq = DEFAULT_TXCOAL_MAXF_INT; + ec->stats_block_coalesce_usecs = DEFAULT_STAT_COAL_TICKS; + + if (tp->coalesce_mode & (HOSTCC_MODE_CLRTICK_RXBD | + HOSTCC_MODE_CLRTICK_TXBD)) { + ec->rx_coalesce_usecs = LOW_RXCOL_TICKS_CLRTCKS; + ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT_CLRTCKS; + ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS; + ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS; + } +} + static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -9341,6 +9385,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, /* flow control autonegotiation is default behavior */ tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + tg3_init_coal(tp); + err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 44c6516..993f84c 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -876,10 +876,12 @@ #define HOSTCC_STATUS_ERROR_ATTN 0x00000004 #define HOSTCC_RXCOL_TICKS 0x00003c08 #define LOW_RXCOL_TICKS 0x00000032 +#define LOW_RXCOL_TICKS_CLRTCKS 0x00000014 #define DEFAULT_RXCOL_TICKS 0x00000048 #define HIGH_RXCOL_TICKS 0x00000096 #define HOSTCC_TXCOL_TICKS 0x00003c0c #define LOW_TXCOL_TICKS 0x00000096 +#define LOW_TXCOL_TICKS_CLRTCKS 0x00000048 #define DEFAULT_TXCOL_TICKS 0x0000012c #define HIGH_TXCOL_TICKS 0x00000145 #define HOSTCC_RXMAX_FRAMES 0x00003c10 @@ -892,8 +894,10 @@ #define HIGH_TXMAX_FRAMES 0x00000052 #define HOSTCC_RXCOAL_TICK_INT 0x00003c18 #define DEFAULT_RXCOAL_TICK_INT 0x00000019 +#define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014 #define HOSTCC_TXCOAL_TICK_INT 0x00003c1c #define DEFAULT_TXCOAL_TICK_INT 0x00000019 +#define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014 #define HOSTCC_RXCOAL_MAXF_INT 0x00003c20 #define DEFAULT_RXCOAL_MAXF_INT 0x00000005 #define HOSTCC_TXCOAL_MAXF_INT 0x00003c24 @@ -2227,7 +2231,7 @@ struct tg3 { #define SST_25VF0X0_PAGE_SIZE 4098 - + struct ethtool_coalesce coal; }; #endif /* !(_T3_H) */ -- cgit v1.1 From 59e6b4343299373bc10dd131ab5142f53ddd838a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2005 22:50:10 -0700 Subject: [TG3]: Refine DMA boundary setting. Extract DMA boundary bit selection into a seperate function, tg3_calc_dma_bndry(). Call this from tg3_test_dma(). Make DMA test more reliable by using no DMA boundry setting during the test. If the test passes, then use the setting we selected before the test. Signed-off-by: David S. Miller Signed-off-by: Michael Chan --- drivers/net/tg3.c | 207 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 163 insertions(+), 44 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3df5b78..4ab9680 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8775,6 +8775,146 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) return 0; } +#define BOUNDARY_SINGLE_CACHELINE 1 +#define BOUNDARY_MULTI_CACHELINE 2 + +static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) +{ + int cacheline_size; + u8 byte; + int goal; + + pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte); + if (byte == 0) + cacheline_size = 1024; + else + cacheline_size = (int) byte * 4; + + /* On 5703 and later chips, the boundary bits have no + * effect. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 && + !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) + goto out; + +#if defined(CONFIG_PPC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC) + goal = BOUNDARY_MULTI_CACHELINE; +#else +#if defined(CONFIG_SPARC64) || defined(CONFIG_ALPHA) + goal = BOUNDARY_SINGLE_CACHELINE; +#else + goal = 0; +#endif +#endif + + if (!goal) + goto out; + + /* PCI controllers on most RISC systems tend to disconnect + * when a device tries to burst across a cache-line boundary. + * Therefore, letting tg3 do so just wastes PCI bandwidth. + * + * Unfortunately, for PCI-E there are only limited + * write-side controls for this, and thus for reads + * we will still get the disconnects. We'll also waste + * these PCI cycles for both read and write for chips + * other than 5700 and 5701 which do not implement the + * boundary bits. + */ + if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && + !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) { + switch (cacheline_size) { + case 16: + case 32: + case 64: + case 128: + if (goal == BOUNDARY_SINGLE_CACHELINE) { + val |= (DMA_RWCTRL_READ_BNDRY_128_PCIX | + DMA_RWCTRL_WRITE_BNDRY_128_PCIX); + } else { + val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX | + DMA_RWCTRL_WRITE_BNDRY_384_PCIX); + } + break; + + case 256: + val |= (DMA_RWCTRL_READ_BNDRY_256_PCIX | + DMA_RWCTRL_WRITE_BNDRY_256_PCIX); + break; + + default: + val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX | + DMA_RWCTRL_WRITE_BNDRY_384_PCIX); + break; + }; + } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + switch (cacheline_size) { + case 16: + case 32: + case 64: + if (goal == BOUNDARY_SINGLE_CACHELINE) { + val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE; + val |= DMA_RWCTRL_WRITE_BNDRY_64_PCIE; + break; + } + /* fallthrough */ + case 128: + default: + val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE; + val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE; + break; + }; + } else { + switch (cacheline_size) { + case 16: + if (goal == BOUNDARY_SINGLE_CACHELINE) { + val |= (DMA_RWCTRL_READ_BNDRY_16 | + DMA_RWCTRL_WRITE_BNDRY_16); + break; + } + /* fallthrough */ + case 32: + if (goal == BOUNDARY_SINGLE_CACHELINE) { + val |= (DMA_RWCTRL_READ_BNDRY_32 | + DMA_RWCTRL_WRITE_BNDRY_32); + break; + } + /* fallthrough */ + case 64: + if (goal == BOUNDARY_SINGLE_CACHELINE) { + val |= (DMA_RWCTRL_READ_BNDRY_64 | + DMA_RWCTRL_WRITE_BNDRY_64); + break; + } + /* fallthrough */ + case 128: + if (goal == BOUNDARY_SINGLE_CACHELINE) { + val |= (DMA_RWCTRL_READ_BNDRY_128 | + DMA_RWCTRL_WRITE_BNDRY_128); + break; + } + /* fallthrough */ + case 256: + val |= (DMA_RWCTRL_READ_BNDRY_256 | + DMA_RWCTRL_WRITE_BNDRY_256); + break; + case 512: + val |= (DMA_RWCTRL_READ_BNDRY_512 | + DMA_RWCTRL_WRITE_BNDRY_512); + break; + case 1024: + default: + val |= (DMA_RWCTRL_READ_BNDRY_1024 | + DMA_RWCTRL_WRITE_BNDRY_1024); + break; + }; + } + +out: + return val; +} + static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device) { struct tg3_internal_buffer_desc test_desc; @@ -8861,7 +9001,7 @@ static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dm static int __devinit tg3_test_dma(struct tg3 *tp) { dma_addr_t buf_dma; - u32 *buf; + u32 *buf, saved_dma_rwctrl; int ret; buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma); @@ -8873,46 +9013,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) | (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT)); -#ifndef CONFIG_X86 - { - u8 byte; - int cacheline_size; - pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte); - - if (byte == 0) - cacheline_size = 1024; - else - cacheline_size = (int) byte * 4; - - switch (cacheline_size) { - case 16: - case 32: - case 64: - case 128: - if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && - !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) { - tp->dma_rwctrl |= - DMA_RWCTRL_WRITE_BNDRY_384_PCIX; - break; - } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - tp->dma_rwctrl &= - ~(DMA_RWCTRL_PCI_WRITE_CMD); - tp->dma_rwctrl |= - DMA_RWCTRL_WRITE_BNDRY_128_PCIE; - break; - } - /* fallthrough */ - case 256: - if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) && - !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) - tp->dma_rwctrl |= - DMA_RWCTRL_WRITE_BNDRY_256; - else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) - tp->dma_rwctrl |= - DMA_RWCTRL_WRITE_BNDRY_256_PCIX; - }; - } -#endif + tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl); if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { /* DMA read watermark not used on PCIE */ @@ -8931,7 +9032,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp) if (ccval == 0x6 || ccval == 0x7) tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA; - /* Set bit 23 to renable PCIX hw bug fix */ + /* Set bit 23 to enable PCIX hw bug fix */ tp->dma_rwctrl |= 0x009f0000; } else { tp->dma_rwctrl |= 0x001b000f; @@ -8972,6 +9073,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) goto out; + /* It is best to perform DMA test with maximum write burst size + * to expose the 5700/5701 write DMA bug. + */ + saved_dma_rwctrl = tp->dma_rwctrl; + tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK; + tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); + while (1) { u32 *p = buf, i; @@ -9010,8 +9118,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp) if (p[i] == i) continue; - if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) == - DMA_RWCTRL_WRITE_BNDRY_DISAB) { + if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) != + DMA_RWCTRL_WRITE_BNDRY_16) { + tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK; tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16; tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); break; @@ -9028,6 +9137,14 @@ static int __devinit tg3_test_dma(struct tg3 *tp) break; } } + if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) != + DMA_RWCTRL_WRITE_BNDRY_16) { + /* DMA test passed without adjusting DMA boundary, + * just restore the calculated DMA boundary + */ + tp->dma_rwctrl = saved_dma_rwctrl; + tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); + } out: pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma); @@ -9429,6 +9546,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0, (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0, (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); + printk(KERN_INFO "%s: dma_rwctrl[%08x]\n", + dev->name, tp->dma_rwctrl); return 0; -- cgit v1.1 From f7383c22246cfccbe912541dd83103009ed2b537 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 May 2005 22:50:53 -0700 Subject: [TG3]: In tg3_poll(), resample status_tag after doing work. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4ab9680..4d2bdbd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2869,9 +2869,6 @@ static int tg3_poll(struct net_device *netdev, int *budget) spin_lock_irqsave(&tp->lock, flags); - if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) - tp->last_tag = sblk->status_tag; - /* handle link change and other phy events */ if (!(tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | @@ -2896,7 +2893,6 @@ static int tg3_poll(struct net_device *netdev, int *budget) * All RX "locking" is done by ensuring outside * code synchronizes with dev->poll() */ - done = 1; if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) { int orig_budget = *budget; int work_done; @@ -2908,12 +2904,14 @@ static int tg3_poll(struct net_device *netdev, int *budget) *budget -= work_done; netdev->quota -= work_done; - - if (work_done >= orig_budget) - done = 0; } + if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) + tp->last_tag = sblk->status_tag; + rmb(); + /* if no more work, tell net stack and NIC we're done */ + done = !tg3_has_work(tp); if (done) { spin_lock_irqsave(&tp->lock, flags); __netif_rx_complete(netdev); -- cgit v1.1 From d48102007d068df7ba3055cdc1723e12db1ba30f Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Wed, 18 May 2005 22:51:45 -0700 Subject: [XFRM]: skb_cow_data() does not set proper owner for new skbs. It looks like skb_cow_data() does not set proper owner for newly created skb. If we have several fragments for skb and some of them are shared(?) or cloned (like in async IPsec) there might be a situation when we require recreating skb and thus using skb_copy() for it. Newly created skb has neither a destructor nor a socket assotiated with it, which must be copied from the old skb. As far as I can see, current code sets destructor and socket for the first one skb only and uses truesize of the first skb only to increment sk_wmem_alloc value. If above "analysis" is correct then attached patch fixes that. Signed-off-by: Evgeniy Polyakov Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/xfrm/xfrm_algo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 080aae2..2f4531f 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -698,7 +698,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) return -ENOMEM; if (skb1->sk) - skb_set_owner_w(skb, skb1->sk); + skb_set_owner_w(skb2, skb1->sk); /* Looking around. Are we still alive? * OK, link new skb, drop old one */ -- cgit v1.1 From 2fdba6b085eb7068e9594cfa55ffe40466184b4d Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 18 May 2005 22:52:33 -0700 Subject: [IPV4/IPV6] Ensure all frag_list members have NULL sk Having frag_list members which holds wmem of an sk leads to nightmares with partially cloned frag skb's. The reason is that once you unleash a skb with a frag_list that has individual sk ownerships into the stack you can never undo those ownerships safely as they may have been cloned by things like netfilter. Since we have to undo them in order to make skb_linearize happy this approach leads to a dead-end. So let's go the other way and make this an invariant: For any skb on a frag_list, skb->sk must be NULL. That is, the socket ownership always belongs to the head skb. It turns out that the implementation is actually pretty simple. The above invariant is actually violated in the following patch for a short duration inside ip_fragment. This is OK because the offending frag_list member is either destroyed at the end of the slow path without being sent anywhere, or it is detached from the frag_list before being sent. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 8 ++++++++ net/ipv6/ip6_output.c | 14 ++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index daebd93..760dc82 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -490,6 +490,14 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) /* Partially cloned skb? */ if (skb_shared(frag)) goto slow_path; + + BUG_ON(frag->sk); + if (skb->sk) { + sock_hold(skb->sk); + frag->sk = skb->sk; + frag->destructor = sock_wfree; + skb->truesize -= frag->truesize; + } } /* Everything is OK. Generate! */ diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0f07114..b78a535 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -552,13 +552,17 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb_headroom(frag) < hlen) goto slow_path; - /* Correct socket ownership. */ - if (frag->sk == NULL) - goto slow_path; - /* Partially cloned skb? */ if (skb_shared(frag)) goto slow_path; + + BUG_ON(frag->sk); + if (skb->sk) { + sock_hold(skb->sk); + frag->sk = skb->sk; + frag->destructor = sock_wfree; + skb->truesize -= frag->truesize; + } } err = 0; @@ -1116,12 +1120,10 @@ int ip6_push_pending_frames(struct sock *sk) tail_skb = &(tmp_skb->next); skb->len += tmp_skb->len; skb->data_len += tmp_skb->len; -#if 0 /* Logically correct, but useless work, ip_fragment() will have to undo */ skb->truesize += tmp_skb->truesize; __sock_put(tmp_skb->sk); tmp_skb->destructor = NULL; tmp_skb->sk = NULL; -#endif } ipv6_addr_copy(final_dst, &fl->fl6_dst); -- cgit v1.1 From 49a43876b935c811cfd29d8fe998a6912a1cc5c4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 18 May 2005 15:39:33 -0700 Subject: [PATCH] prevent NULL mmap in topdown model Prevent the topdown allocator from allocating mmap areas all the way down to address zero. We still allow a MAP_FIXED mapping of page 0 (needed for various things, ranging from Wine and DOSEMU to people who want to allow speculative loads off a NULL pointer). Tested by Chris Wright. Signed-off-by: Linus Torvalds --- mm/mmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 01f9793..63df2d6 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1244,7 +1244,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, addr = mm->free_area_cache; /* make sure it can fit in the remaining address space */ - if (addr >= len) { + if (addr > len) { vma = find_vma(mm, addr-len); if (!vma || addr <= vma->vm_start) /* remember the address as a hint for next time */ @@ -1266,7 +1266,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, /* try just below the current vma->vm_start */ addr = vma->vm_start-len; - } while (len <= vma->vm_start); + } while (len < vma->vm_start); /* * A failed mmap() very likely causes application failure, -- cgit v1.1 From f81a0bffa116ea22149aa7cfb0b4ee09096d9d92 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 19 May 2005 12:26:43 -0700 Subject: [AF_UNIX]: Use lookup_create(). currently it opencodes it, but that's in the way of chaning the lookup_hash interface. I'd prefer to disallow modular af_unix over exporting lookup_create, but I'll leave that to you. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- fs/namei.c | 1 + net/unix/af_unix.c | 28 +++------------------------- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index defe678..dd78f01 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1580,6 +1580,7 @@ enoent: fail: return dentry; } +EXPORT_SYMBOL_GPL(lookup_create); int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c478fc8..c420eba 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -770,33 +770,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd); if (err) goto out_mknod_parent; - /* - * Yucky last component or no last component at all? - * (foo/., foo/.., /////) - */ - err = -EEXIST; - if (nd.last_type != LAST_NORM) - goto out_mknod; - /* - * Lock the directory. - */ - down(&nd.dentry->d_inode->i_sem); - /* - * Do the final lookup. - */ - dentry = lookup_hash(&nd.last, nd.dentry); + + dentry = lookup_create(&nd, 0); err = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_mknod_unlock; - err = -ENOENT; - /* - * Special case - lookup gave negative, but... we had foo/bar/ - * From the vfs_mknod() POV we just have a negative dentry - - * all is fine. Let's be bastards - you had / on the end, you've - * been asking for (non-existent) directory. -ENOENT for you. - */ - if (nd.last.name[nd.last.len] && !dentry->d_inode) - goto out_mknod_dput; + /* * All right, let's create it. */ @@ -845,7 +824,6 @@ out_mknod_dput: dput(dentry); out_mknod_unlock: up(&nd.dentry->d_inode->i_sem); -out_mknod: path_release(&nd); out_mknod_parent: if (err==-EEXIST) -- cgit v1.1 From d9fa0f392b20b2b8e3df379c44194492a2446c6e Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Thu, 19 May 2005 12:29:59 -0700 Subject: [IP_VS]: Remove extra __ip_vs_conn_put() for incoming ICMP. Remove extra __ip_vs_conn_put for incoming ICMP in direct routing mode. Mark de Vries reports that IPVS connections are not leaked anymore. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller --- net/ipv4/ipvs/ip_vs_xmit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index faa6176..de21da0 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c @@ -508,7 +508,6 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, rc = NF_ACCEPT; /* do not touch skb anymore */ atomic_inc(&cp->in_pkts); - __ip_vs_conn_put(cp); goto out; } -- cgit v1.1 From 8be58932ca596972e4953ae980d8bc286857cae8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 19 May 2005 12:36:33 -0700 Subject: [NETFILTER]: Do not be clever about SKB ownership in ip_ct_gather_frags(). Just do an skb_orphan() and be done with it. Based upon discussions with Herbert Xu on netdev. Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_core.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 28d9425..09e8246 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -940,37 +940,25 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct, struct sk_buff * ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user) { - struct sock *sk = skb->sk; #ifdef CONFIG_NETFILTER_DEBUG unsigned int olddebug = skb->nf_debug; #endif - if (sk) { - sock_hold(sk); - skb_orphan(skb); - } + skb_orphan(skb); local_bh_disable(); skb = ip_defrag(skb, user); local_bh_enable(); - if (!skb) { - if (sk) - sock_put(sk); - return skb; - } - - if (sk) { - skb_set_owner_w(skb, sk); - sock_put(sk); - } - - ip_send_check(skb->nh.iph); - skb->nfcache |= NFC_ALTERED; + if (skb) { + ip_send_check(skb->nh.iph); + skb->nfcache |= NFC_ALTERED; #ifdef CONFIG_NETFILTER_DEBUG - /* Packet path as if nothing had happened. */ - skb->nf_debug = olddebug; + /* Packet path as if nothing had happened. */ + skb->nf_debug = olddebug; #endif + } + return skb; } -- cgit v1.1 From b9e9dead05b19e7f52c9aa00cd3a5b7ac4fcacf4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 19 May 2005 12:39:04 -0700 Subject: [IPSEC]: Fixed alg_key_len usage in attach_one_algo The variable alg_key_len is in bits and not bytes. The function attach_one_algo is currently using it as if it were in bytes. This causes it to read memory which may not be there. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 5ddda2c..15ba086 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -162,6 +162,7 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, struct rtattr *rta = u_arg; struct xfrm_algo *p, *ualg; struct xfrm_algo_desc *algo; + int len; if (!rta) return 0; @@ -173,11 +174,12 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, return -ENOSYS; *props = algo->desc.sadb_alg_id; - p = kmalloc(sizeof(*ualg) + ualg->alg_key_len, GFP_KERNEL); + len = sizeof(*ualg) + (ualg->alg_key_len + 7U) / 8; + p = kmalloc(len, GFP_KERNEL); if (!p) return -ENOMEM; - memcpy(p, ualg, sizeof(*ualg) + ualg->alg_key_len); + memcpy(p, ualg, len); *algpp = p; return 0; } -- cgit v1.1 From 31c26852cb2ac77f1d4acb37bcf31f165fd5eb68 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 19 May 2005 12:39:49 -0700 Subject: [IPSEC]: Verify key payload in verify_one_algo We need to verify that the payload contains enough data so that attach_one_algo can copy alg_key_len bits from the payload. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 15ba086..9750901 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -34,14 +34,21 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) { struct rtattr *rt = xfrma[type - 1]; struct xfrm_algo *algp; + int len; if (!rt) return 0; - if ((rt->rta_len - sizeof(*rt)) < sizeof(*algp)) + len = (rt->rta_len - sizeof(*rt)) - sizeof(*algp); + if (len < 0) return -EINVAL; algp = RTA_DATA(rt); + + len -= (algp->alg_key_len + 7U) / 8; + if (len < 0) + return -EINVAL; + switch (type) { case XFRMA_ALG_AUTH: if (!algp->alg_key_len && -- cgit v1.1 From 1eda339e76a9aac05883c548028bf91aed734783 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Thu, 19 May 2005 12:42:39 -0700 Subject: [PKT_SCHED]: Fixup simple action define. Make it consistent with other net/sched files Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/act_generic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/act_generic.h b/include/net/act_generic.h index 95b1207..c9daa7e 100644 --- a/include/net/act_generic.h +++ b/include/net/act_generic.h @@ -2,8 +2,8 @@ * include/net/act_generic.h * */ -#ifndef ACT_GENERIC_H -#define ACT_GENERIC_H +#ifndef _NET_ACT_GENERIC_H +#define _NET_ACT_GENERIC_H static inline int tcf_defact_release(struct tcf_defact *p, int bind) { int ret = 0; -- cgit v1.1 From db61ecc3352d72513c1b07805bd6f760e30c001b Mon Sep 17 00:00:00 2001 From: "Tommy S. Christensen" Date: Thu, 19 May 2005 12:46:59 -0700 Subject: [NETLINK]: Fix race with recvmsg(). This bug causes: assertion (!atomic_read(&sk->sk_rmem_alloc)) failed at net/netlink/af_netlink.c (122) What's happening is that: 1) The skb is sent to socket 1. 2) Someone does a recvmsg on socket 1 and drops the ref on the skb. Note that the rmalloc is not returned at this point since the skb is still referenced. 3) The same skb is now sent to socket 2. This version of the fix resurrects the skb_orphan call that was moved out, last time we had 'shared-skb troubles'. It is practically a no-op in the common case, but still prevents the possible race with recvmsg. Signed-off-by: Tommy S. Christensen Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 733bf52..b40c9a9 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -697,6 +697,7 @@ static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf && !test_bit(0, &nlk->state)) { + skb_orphan(skb); skb_set_owner_r(skb, sk); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); -- cgit v1.1 From 68acc024ea7391e03c2c695ba0b9fb31baa974bf Mon Sep 17 00:00:00 2001 From: "Tommy S. Christensen" Date: Thu, 19 May 2005 13:06:35 -0700 Subject: [NETLINK]: Move broadcast skb_orphan to the skb_get path. Cloned packets don't need the orphan call. Signed-off-by: Tommy S. Christensen Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index b40c9a9..4b91f4b 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -697,7 +697,6 @@ static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf && !test_bit(0, &nlk->state)) { - skb_orphan(skb); skb_set_owner_r(skb, sk); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); @@ -736,11 +735,15 @@ static inline int do_one_broadcast(struct sock *sk, sock_hold(sk); if (p->skb2 == NULL) { - if (atomic_read(&p->skb->users) != 1) { + if (skb_shared(p->skb)) { p->skb2 = skb_clone(p->skb, p->allocation); } else { - p->skb2 = p->skb; - atomic_inc(&p->skb->users); + p->skb2 = skb_get(p->skb); + /* + * skb ownership may have been set when + * delivered to a previous socket. + */ + skb_orphan(p->skb2); } } if (p->skb2 == NULL) { -- cgit v1.1 From aa1c6a6f7f0518b42994d02756a41cbfdcac1916 Mon Sep 17 00:00:00 2001 From: "Tommy S. Christensen" Date: Thu, 19 May 2005 13:07:32 -0700 Subject: [NETLINK]: Defer socket destruction a bit In netlink_broadcast() we're sending shared skb's to netlink listeners when possible (saves some copying). This is OK, since we hold the only other reference to the skb. However, this implies that we must drop our reference on the skb, before allowing a receiving socket to disappear. Otherwise, the socket buffer accounting is disrupted. Signed-off-by: Tommy S. Christensen Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4b91f4b..e41ce45 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -789,11 +789,12 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) do_one_broadcast(sk, &info); + kfree_skb(skb); + netlink_unlock_table(); if (info.skb2) kfree_skb(info.skb2); - kfree_skb(skb); if (info.delivered) { if (info.congested && (allocation & __GFP_WAIT)) -- cgit v1.1 From 07ab67c8d0d7c1021343b7d5c045033d6bf7be69 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 19 May 2005 22:43:37 -0700 Subject: Fix get_unmapped_area sanity tests As noted by Chris Wright, we need to do the full range of tests regardless of whether MAP_FIXED is set or not, so re-organize get_unmapped_area() slightly to do the sanity checks unconditionally. --- include/linux/err.h | 4 +++- mm/mmap.c | 59 ++++++++++++++++++++++++++++------------------------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/include/linux/err.h b/include/linux/err.h index 17c55df..ff71d2a 100644 --- a/include/linux/err.h +++ b/include/linux/err.h @@ -13,6 +13,8 @@ * This should be a per-architecture thing, to allow different * error and pointer decisions. */ +#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L) + static inline void *ERR_PTR(long error) { return (void *) error; @@ -25,7 +27,7 @@ static inline long PTR_ERR(const void *ptr) static inline long IS_ERR(const void *ptr) { - return unlikely((unsigned long)ptr > (unsigned long)-1000L); + return IS_ERR_VALUE((unsigned long)ptr); } #endif /* _LINUX_ERR_H */ diff --git a/mm/mmap.c b/mm/mmap.c index 63df2d6..de54acd 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1302,37 +1302,40 @@ unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - if (flags & MAP_FIXED) { - unsigned long ret; + unsigned long ret; - if (addr > TASK_SIZE - len) - return -ENOMEM; - if (addr & ~PAGE_MASK) - return -EINVAL; - if (file && is_file_hugepages(file)) { - /* - * Check if the given range is hugepage aligned, and - * can be made suitable for hugepages. - */ - ret = prepare_hugepage_range(addr, len); - } else { - /* - * Ensure that a normal request is not falling in a - * reserved hugepage range. For some archs like IA-64, - * there is a separate region for hugepages. - */ - ret = is_hugepage_only_range(current->mm, addr, len); - } - if (ret) - return -EINVAL; - return addr; - } + if (!(flags & MAP_FIXED)) { + unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - if (file && file->f_op && file->f_op->get_unmapped_area) - return file->f_op->get_unmapped_area(file, addr, len, - pgoff, flags); + get_area = current->mm->get_unmapped_area; + if (file && file->f_op && file->f_op->get_unmapped_area) + get_area = file->f_op->get_unmapped_area; + addr = get_area(file, addr, len, pgoff, flags); + if (IS_ERR_VALUE(addr)) + return addr; + } - return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); + if (addr > TASK_SIZE - len) + return -ENOMEM; + if (addr & ~PAGE_MASK) + return -EINVAL; + if (file && is_file_hugepages(file)) { + /* + * Check if the given range is hugepage aligned, and + * can be made suitable for hugepages. + */ + ret = prepare_hugepage_range(addr, len); + } else { + /* + * Ensure that a normal request is not falling in a + * reserved hugepage range. For some archs like IA-64, + * there is a separate region for hugepages. + */ + ret = is_hugepage_only_range(current->mm, addr, len); + } + if (ret) + return -EINVAL; + return addr; } EXPORT_SYMBOL(get_unmapped_area); -- cgit v1.1 From 6c37a88c5b1195d4ac74d44a6413839b93df5af4 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 20 May 2005 16:57:22 +1000 Subject: [PATCH] ppc32: don't call progress functions after boot On ppc32, the platform code can supply a "progress" function that is used to show progress through the boot. These functions are usually in an init section and so can't be called after the init pages are freed. Now that the cpu bringup code can be called after the system is booted (for hotplug cpu) we can get the situation where the progress function can be called after boot. The simple fix is to set the progress function pointer to NULL when the init pages are freed, and that is what this patch does (note that all callers already check whether the function pointer is NULL before trying to call it). Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc/mm/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index be02a7f..363c157 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -179,6 +179,7 @@ void free_initmem(void) if (!have_of) FREESEC(openfirmware); printk("\n"); + ppc_md.progress = NULL; #undef FREESEC } -- cgit v1.1 From 3207a80a6e11c7ceff7e46d5ec6bfcc03c14e729 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 20 May 2005 17:15:00 +1000 Subject: [PATCH] ppc32: remove unused computation We are computing phys in the code below and never using. This patch takes out the redundant computation. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc/syslib/open_pic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index 7619e16..9d4ed68 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -557,12 +557,10 @@ static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec) */ void openpic_cause_IPI(u_int ipi, cpumask_t cpumask) { - cpumask_t phys; DECL_THIS_CPU; CHECK_THIS_CPU; check_arg_ipi(ipi); - phys = physmask(cpumask); openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpus_addr(physmask(cpumask))[0]); } -- cgit v1.1 From 72480ef863740c3dc301b0803c9ed6d10716aa11 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 20 May 2005 16:50:55 +1000 Subject: [PATCH] ppc32: Fix __copy_tofrom_user return value Recently the __copy_tofrom_user routine was modified to avoid doing prefetches past the end of the source array. However, in doing so we introduced a bug in that it now returns the wrong value for the number of bytes not copied when a fault is encountered. This fixes it to return the correct number. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc/lib/string.S | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S index 8d08a2e..36c9b97 100644 --- a/arch/ppc/lib/string.S +++ b/arch/ppc/lib/string.S @@ -446,6 +446,7 @@ _GLOBAL(__copy_tofrom_user) #ifdef CONFIG_8xx /* Don't use prefetch on 8xx */ mtctr r0 + li r0,0 53: COPY_16_BYTES_WITHEX(0) bdnz 53b @@ -564,7 +565,9 @@ _GLOBAL(__copy_tofrom_user) /* or write fault in cacheline loop */ 105: li r9,1 92: li r3,LG_CACHELINE_BYTES - b 99f + mfctr r8 + add r0,r0,r8 + b 106f /* read fault in final word loop */ 108: li r9,0 b 93f @@ -585,7 +588,7 @@ _GLOBAL(__copy_tofrom_user) * r5 + (ctr << r3), and r9 is 0 for read or 1 for write. */ 99: mfctr r0 - slw r3,r0,r3 +106: slw r3,r0,r3 add. r3,r3,r5 beq 120f /* shouldn't happen */ cmpwi 0,r9,0 -- cgit v1.1 From 45fed46f5b98aaf439e9ef125992ec853cd98499 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 20 May 2005 16:45:58 +1000 Subject: [PATCH] ppx32: Fix uninitialized variable in set_preferred_console This fixes an uninitialized variable warning in arch/ppc/kernel/setup.c, and this time gcc is actually right, there is a path that could result in offset being uninitialized. Zero is a sane default in this instance. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 309797d..5c20266 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -499,7 +499,7 @@ static int __init set_preferred_console(void) { struct device_node *prom_stdout; char *name; - int offset; + int offset = 0; if (of_stdout_device == NULL) return -ENODEV; -- cgit v1.1 From 37e0915b701281182cea9fc90e894d10addf134a Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 20 May 2005 08:56:23 +0200 Subject: [PATCH] Add sysfs support for the IPMI device interface Add support for sysfs to the IPMI device interface. Clean-ups based on Dimitry Torokovs comment by Philipp Hahn. Signed-off-by: Corey Minyard Signed-off-by: Philipp Hahn Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 49d67f5..4bb9af7 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -44,6 +44,7 @@ #include #include #include +#include #define IPMI_DEVINTF_VERSION "v33" @@ -519,15 +520,21 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" " interface. Other values will set the major device number" " to that value."); +static struct class *ipmi_class; + static void ipmi_new_smi(int if_num) { - devfs_mk_cdev(MKDEV(ipmi_major, if_num), - S_IFCHR | S_IRUSR | S_IWUSR, + dev_t dev = MKDEV(ipmi_major, if_num); + + devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, "ipmidev/%d", if_num); + + class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num); } static void ipmi_smi_gone(int if_num) { + class_simple_device_remove(ipmi_class, MKDEV(ipmi_major, if_num)); devfs_remove("ipmidev/%d", if_num); } @@ -548,8 +555,15 @@ static __init int init_ipmi_devintf(void) printk(KERN_INFO "ipmi device interface version " IPMI_DEVINTF_VERSION "\n"); + ipmi_class = class_simple_create(THIS_MODULE, "ipmi"); + if (IS_ERR(ipmi_class)) { + printk(KERN_ERR "ipmi: can't register device class\n"); + return PTR_ERR(ipmi_class); + } + rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops); if (rv < 0) { + class_simple_destroy(ipmi_class); printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major); return rv; } @@ -563,6 +577,7 @@ static __init int init_ipmi_devintf(void) rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { unregister_chrdev(ipmi_major, DEVICE_NAME); + class_simple_destroy(ipmi_class); printk(KERN_WARNING "ipmi: can't register smi watcher\n"); return rv; } @@ -573,6 +588,7 @@ module_init(init_ipmi_devintf); static __exit void cleanup_ipmi(void) { + class_simple_destroy(ipmi_class); ipmi_smi_watcher_unregister(&smi_watcher); devfs_remove(DEVICE_NAME); unregister_chrdev(ipmi_major, DEVICE_NAME); -- cgit v1.1 From a228dfd5dc4b92288ea22d427b2bfc48ba5bb8b0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 20 May 2005 11:40:32 -0700 Subject: [SPARC64]: Fix bad performance side effect of strbuf timeout changes. The recent change to add a timeout to strbuf flushing had a negative performance impact. The udelay()'s are too long, and they were done in the wrong order wrt. the register read checks. Fix both, and things are happy again. There are more possible improvements in this area. In fact, PCI streaming buffer flushing seems to be part of the bottleneck in network receive performance on my SunBlade1000 box. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_iommu.c | 16 +++++++++------- arch/sparc64/kernel/sbus.c | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index f009b1b..33ca56c 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -392,14 +392,16 @@ static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, flushreg = strbuf->strbuf_ctxflush; matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - limit = 10000; - do { - pci_iommu_write(flushreg, ctx); - udelay(10); + limit = 100000; + pci_iommu_write(flushreg, ctx); + for(;;) { + if (((long)pci_iommu_read(matchreg)) >= 0L) + break; limit--; if (!limit) break; - } while(((long)pci_iommu_read(matchreg)) < 0L); + udelay(1); + } if (!limit) printk(KERN_WARNING "pci_strbuf_flush: ctx flush " "timeout vaddr[%08x] ctx[%lx]\n", @@ -414,12 +416,12 @@ static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); (void) pci_iommu_read(iommu->write_complete_reg); - limit = 10000; + limit = 100000; while (!PCI_STC_FLUSHFLAG_SET(strbuf)) { limit--; if (!limit) break; - udelay(10); + udelay(1); membar("#LoadLoad"); } if (!limit) diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index d3eca98..76ea645 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -133,12 +133,12 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long iommu->strbuf_regs + STRBUF_FSYNC); upa_readq(iommu->sbus_control_reg); - limit = 10000; + limit = 100000; while (iommu->strbuf_flushflag == 0UL) { limit--; if (!limit) break; - udelay(10); + udelay(1); membar("#LoadLoad"); } if (!limit) -- cgit v1.1 From 1c7878f024705594ac455e501ad51e475a400d5d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 20 May 2005 13:36:19 -0700 Subject: Remove some left-over empty files Hopefully the addition of -E to my applypatch script will mean that I won't have these kinds of leftovers in the future. --- arch/um/kernel/checksum.c | 0 include/asm-ia64/ioctl32.h | 0 include/asm-um/arch-signal-i386.h | 0 include/asm-x86_64/ioctl32.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 arch/um/kernel/checksum.c delete mode 100644 include/asm-ia64/ioctl32.h delete mode 100644 include/asm-um/arch-signal-i386.h delete mode 100644 include/asm-x86_64/ioctl32.h diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c deleted file mode 100644 index e69de29..0000000 diff --git a/include/asm-ia64/ioctl32.h b/include/asm-ia64/ioctl32.h deleted file mode 100644 index e69de29..0000000 diff --git a/include/asm-um/arch-signal-i386.h b/include/asm-um/arch-signal-i386.h deleted file mode 100644 index e69de29..0000000 diff --git a/include/asm-x86_64/ioctl32.h b/include/asm-x86_64/ioctl32.h deleted file mode 100644 index e69de29..0000000 -- cgit v1.1 From 62a8612972eaea804e1e42c63ee403cd4e14cc35 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 6 May 2005 18:05:20 -0500 Subject: [SCSI] implement parameter limits in the SPI transport class There's a basic need not to have parameters go under or over certain values when doing domain validation. The basic ones are max_offset, max_width and min_period This patch makes the transport class take and enforce these three limits. Currently they can be set by the user, although they could obviously be read from the HBA's on-board NVRAM area during slave_configure (if it has one). Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 188 ++++++++++++++++++++++++++++++++------ include/scsi/scsi_transport_spi.h | 6 ++ 2 files changed, 167 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 28966d0..67c6cc4 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -35,7 +35,7 @@ #define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) -#define SPI_NUM_ATTRS 10 /* increase this if you add attributes */ +#define SPI_NUM_ATTRS 13 /* increase this if you add attributes */ #define SPI_OTHER_ATTRS 1 /* Increase this if you add "always * on" attributes */ #define SPI_HOST_ATTRS 1 @@ -219,8 +219,11 @@ static int spi_setup_transport_attrs(struct device *dev) struct scsi_target *starget = to_scsi_target(dev); spi_period(starget) = -1; /* illegal value */ + spi_min_period(starget) = 0; spi_offset(starget) = 0; /* async */ + spi_max_offset(starget) = 255; spi_width(starget) = 0; /* narrow */ + spi_max_width(starget) = 1; spi_iu(starget) = 0; /* no IU */ spi_dt(starget) = 0; /* ST */ spi_qas(starget) = 0; @@ -235,6 +238,34 @@ static int spi_setup_transport_attrs(struct device *dev) return 0; } +#define spi_transport_show_simple(field, format_string) \ + \ +static ssize_t \ +show_spi_transport_##field(struct class_device *cdev, char *buf) \ +{ \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct spi_transport_attrs *tp; \ + \ + tp = (struct spi_transport_attrs *)&starget->starget_data; \ + return snprintf(buf, 20, format_string, tp->field); \ +} + +#define spi_transport_store_simple(field, format_string) \ + \ +static ssize_t \ +store_spi_transport_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + int val; \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct spi_transport_attrs *tp; \ + \ + tp = (struct spi_transport_attrs *)&starget->starget_data; \ + val = simple_strtoul(buf, NULL, 0); \ + tp->field = val; \ + return count; \ +} + #define spi_transport_show_function(field, format_string) \ \ static ssize_t \ @@ -261,6 +292,25 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ struct spi_internal *i = to_spi_internal(shost->transportt); \ \ val = simple_strtoul(buf, NULL, 0); \ + i->f->set_##field(starget, val); \ + return count; \ +} + +#define spi_transport_store_max(field, format_string) \ +static ssize_t \ +store_spi_transport_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + int val; \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ + struct spi_internal *i = to_spi_internal(shost->transportt); \ + struct spi_transport_attrs *tp \ + = (struct spi_transport_attrs *)&starget->starget_data; \ + \ + val = simple_strtoul(buf, NULL, 0); \ + if (val > tp->max_##field) \ + val = tp->max_##field; \ i->f->set_##field(starget, val); \ return count; \ } @@ -272,9 +322,24 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ show_spi_transport_##field, \ store_spi_transport_##field); +#define spi_transport_simple_attr(field, format_string) \ + spi_transport_show_simple(field, format_string) \ + spi_transport_store_simple(field, format_string) \ +static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ + show_spi_transport_##field, \ + store_spi_transport_##field); + +#define spi_transport_max_attr(field, format_string) \ + spi_transport_show_function(field, format_string) \ + spi_transport_store_max(field, format_string) \ + spi_transport_simple_attr(max_##field, format_string) \ +static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ + show_spi_transport_##field, \ + store_spi_transport_##field); + /* The Parallel SCSI Tranport Attributes: */ -spi_transport_rd_attr(offset, "%d\n"); -spi_transport_rd_attr(width, "%d\n"); +spi_transport_max_attr(offset, "%d\n"); +spi_transport_max_attr(width, "%d\n"); spi_transport_rd_attr(iu, "%d\n"); spi_transport_rd_attr(dt, "%d\n"); spi_transport_rd_attr(qas, "%d\n"); @@ -300,26 +365,18 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); /* Translate the period into ns according to the current spec * for SDTR/PPR messages */ -static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) - +static ssize_t +show_spi_transport_period_helper(struct class_device *cdev, char *buf, + int period) { - struct scsi_target *starget = transport_class_to_starget(cdev); - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct spi_transport_attrs *tp; int len, picosec; - struct spi_internal *i = to_spi_internal(shost->transportt); - - tp = (struct spi_transport_attrs *)&starget->starget_data; - - if (i->f->get_period) - i->f->get_period(starget); - if (tp->period < 0 || tp->period > 0xff) { + if (period < 0 || period > 0xff) { picosec = -1; - } else if (tp->period <= SPI_STATIC_PPR) { - picosec = ppr_to_ps[tp->period]; + } else if (period <= SPI_STATIC_PPR) { + picosec = ppr_to_ps[period]; } else { - picosec = tp->period * 4000; + picosec = period * 4000; } if (picosec == -1) { @@ -334,12 +391,9 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) } static ssize_t -store_spi_transport_period(struct class_device *cdev, const char *buf, - size_t count) +store_spi_transport_period_helper(struct class_device *cdev, const char *buf, + size_t count, int *periodp) { - struct scsi_target *starget = transport_class_to_starget(cdev); - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct spi_internal *i = to_spi_internal(shost->transportt); int j, picosec, period = -1; char *endp; @@ -368,15 +422,79 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, if (period > 0xff) period = 0xff; - i->f->set_period(starget, period); + *periodp = period; return count; } +static ssize_t +show_spi_transport_period(struct class_device *cdev, char *buf) +{ + struct scsi_target *starget = transport_class_to_starget(cdev); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct spi_internal *i = to_spi_internal(shost->transportt); + struct spi_transport_attrs *tp = + (struct spi_transport_attrs *)&starget->starget_data; + + if (i->f->get_period) + i->f->get_period(starget); + + return show_spi_transport_period_helper(cdev, buf, tp->period); +} + +static ssize_t +store_spi_transport_period(struct class_device *cdev, const char *buf, + size_t count) +{ + struct scsi_target *starget = transport_class_to_starget(cdev); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct spi_internal *i = to_spi_internal(shost->transportt); + struct spi_transport_attrs *tp = + (struct spi_transport_attrs *)&starget->starget_data; + int period, retval; + + retval = store_spi_transport_period_helper(cdev, buf, count, &period); + + if (period < tp->min_period) + period = tp->min_period; + + i->f->set_period(starget, period); + + return retval; +} + static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, show_spi_transport_period, store_spi_transport_period); +static ssize_t +show_spi_transport_min_period(struct class_device *cdev, char *buf) +{ + struct scsi_target *starget = transport_class_to_starget(cdev); + struct spi_transport_attrs *tp = + (struct spi_transport_attrs *)&starget->starget_data; + + return show_spi_transport_period_helper(cdev, buf, tp->min_period); +} + +static ssize_t +store_spi_transport_min_period(struct class_device *cdev, const char *buf, + size_t count) +{ + struct scsi_target *starget = transport_class_to_starget(cdev); + struct spi_transport_attrs *tp = + (struct spi_transport_attrs *)&starget->starget_data; + + return store_spi_transport_period_helper(cdev, buf, count, + &tp->min_period); +} + + +static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR, + show_spi_transport_min_period, + store_spi_transport_min_period); + + static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) { struct Scsi_Host *shost = transport_class_to_shost(cdev); @@ -642,6 +760,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) { struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); struct scsi_device *sdev = sreq->sr_device; + struct scsi_target *starget = sdev->sdev_target; int len = sdev->inquiry_len; /* first set us up for narrow async */ DV_SET(offset, 0); @@ -655,9 +774,11 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) } /* test width */ - if (i->f->set_width && sdev->wdtr) { + if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) { i->f->set_width(sdev->sdev_target, 1); + printk("WIDTH IS %d\n", spi_max_width(starget)); + if (spi_dv_device_compare_inquiry(sreq, buffer, buffer + len, DV_LOOPS) @@ -684,8 +805,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) retry: /* now set up to the maximum */ - DV_SET(offset, 255); - DV_SET(period, 1); + DV_SET(offset, spi_max_offset(starget)); + DV_SET(period, spi_min_period(starget)); if (len == 0) { SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); @@ -892,6 +1013,16 @@ EXPORT_SYMBOL(spi_display_xfer_agreement); if (i->f->show_##field) \ count++ +#define SETUP_RELATED_ATTRIBUTE(field, rel_field) \ + i->private_attrs[count] = class_device_attr_##field; \ + if (!i->f->set_##rel_field) { \ + i->private_attrs[count].attr.mode = S_IRUGO; \ + i->private_attrs[count].store = NULL; \ + } \ + i->attrs[count] = &i->private_attrs[count]; \ + if (i->f->show_##rel_field) \ + count++ + #define SETUP_HOST_ATTRIBUTE(field) \ i->private_host_attrs[count] = class_device_attr_##field; \ if (!i->f->set_##field) { \ @@ -975,8 +1106,11 @@ spi_attach_transport(struct spi_function_template *ft) i->f = ft; SETUP_ATTRIBUTE(period); + SETUP_RELATED_ATTRIBUTE(min_period, period); SETUP_ATTRIBUTE(offset); + SETUP_RELATED_ATTRIBUTE(max_offset, offset); SETUP_ATTRIBUTE(width); + SETUP_RELATED_ATTRIBUTE(max_width, width); SETUP_ATTRIBUTE(iu); SETUP_ATTRIBUTE(dt); SETUP_ATTRIBUTE(qas); diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index 6dcf497..a30d6cd 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -27,8 +27,11 @@ struct scsi_transport_template; struct spi_transport_attrs { int period; /* value in the PPR/SDTR command */ + int min_period; int offset; + int max_offset; unsigned int width:1; /* 0 - narrow, 1 - wide */ + unsigned int max_width:1; unsigned int iu:1; /* Information Units enabled */ unsigned int dt:1; /* DT clocking enabled */ unsigned int qas:1; /* Quick Arbitration and Selection enabled */ @@ -63,8 +66,11 @@ struct spi_host_attrs { /* accessor functions */ #define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period) +#define spi_min_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->min_period) #define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset) +#define spi_max_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_offset) #define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width) +#define spi_max_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_width) #define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu) #define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt) #define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas) -- cgit v1.1 From fad01ef88d2a27303757924c1fc013b31fe9a76b Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 8 May 2005 16:00:15 -0500 Subject: [SCSI] correct aic7xxx period setting routines This is similar to the previous sym2 problem. For Domain Validation to work we can't allow any period setting to turn wide on if it was previously off. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 71 ++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index d978e4a..0ed9ccc 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -3346,6 +3346,32 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) static void ahc_linux_exit(void); +static void ahc_linux_get_width(struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); + struct ahc_tmode_tstate *tstate; + struct ahc_initiator_tinfo *tinfo + = ahc_fetch_transinfo(ahc, + starget->channel + 'A', + shost->this_id, starget->id, &tstate); + spi_width(starget) = tinfo->curr.width; +} + +static void ahc_linux_set_width(struct scsi_target *starget, int width) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); + struct ahc_devinfo devinfo; + unsigned long flags; + + ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, + starget->channel + 'A', ROLE_INITIATOR); + ahc_lock(ahc, &flags); + ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE); + ahc_unlock(ahc, &flags); +} + static void ahc_linux_get_period(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -3378,6 +3404,14 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period) ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); + + /* all PPR requests apart from QAS require wide transfers */ + if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) { + ahc_linux_get_width(starget); + if (spi_width(starget) == 0) + ppr_options &= MSG_EXT_PPR_QAS_REQ; + } + syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); ahc_lock(ahc, &flags); ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, @@ -3425,32 +3459,6 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset) ahc_unlock(ahc, &flags); } -static void ahc_linux_get_width(struct scsi_target *starget) -{ - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); - struct ahc_tmode_tstate *tstate; - struct ahc_initiator_tinfo *tinfo - = ahc_fetch_transinfo(ahc, - starget->channel + 'A', - shost->this_id, starget->id, &tstate); - spi_width(starget) = tinfo->curr.width; -} - -static void ahc_linux_set_width(struct scsi_target *starget, int width) -{ - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata); - struct ahc_devinfo devinfo; - unsigned long flags; - - ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, - starget->channel + 'A', ROLE_INITIATOR); - ahc_lock(ahc, &flags); - ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE); - ahc_unlock(ahc, &flags); -} - static void ahc_linux_get_dt(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -3481,8 +3489,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); - syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, - dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2); + syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,AHC_SYNCRATE_DT); ahc_lock(ahc, &flags); ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, ppr_options, AHC_TRANS_GOAL, FALSE); @@ -3514,7 +3521,6 @@ static void ahc_linux_set_qas(struct scsi_target *starget, int qas) unsigned int ppr_options = tinfo->curr.ppr_options & ~MSG_EXT_PPR_QAS_REQ; unsigned int period = tinfo->curr.period; - unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; unsigned long flags; struct ahc_syncrate *syncrate; @@ -3523,8 +3529,7 @@ static void ahc_linux_set_qas(struct scsi_target *starget, int qas) ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); - syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, - dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2); + syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); ahc_lock(ahc, &flags); ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, ppr_options, AHC_TRANS_GOAL, FALSE); @@ -3556,7 +3561,6 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu) unsigned int ppr_options = tinfo->curr.ppr_options & ~MSG_EXT_PPR_IU_REQ; unsigned int period = tinfo->curr.period; - unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; unsigned long flags; struct ahc_syncrate *syncrate; @@ -3565,8 +3569,7 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu) ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); - syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, - dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2); + syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT); ahc_lock(ahc, &flags); ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset, ppr_options, AHC_TRANS_GOAL, FALSE); -- cgit v1.1 From e4e360c325c90f7830baaa2a27cd7a1f2bdeb6b0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 16 May 2005 16:39:38 -0500 Subject: [SCSI] remove aic7xxx busyq The aic7xxx driver has two spurious queues in it's linux glue code: the busyq which queues incoming commands to the driver and the completeq which queues finished commands before sending them back to the mid-layer This patch just removes the busyq and makes the aic finally return the correct status to get the mid-layer to manage its queueing, so a command is either committed to the sequencer or returned to the midlayer for requeue. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 625 +++++++++++-------------------------- drivers/scsi/aic7xxx/aic7xxx_osm.h | 4 +- 2 files changed, 191 insertions(+), 438 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 0ed9ccc..9017942 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -458,26 +458,20 @@ static struct ahc_linux_device* ahc_linux_alloc_device(struct ahc_softc*, u_int); static void ahc_linux_free_device(struct ahc_softc*, struct ahc_linux_device*); -static void ahc_linux_run_device_queue(struct ahc_softc*, - struct ahc_linux_device*); +static int ahc_linux_run_command(struct ahc_softc*, + struct ahc_linux_device *, + struct scsi_cmnd *); static void ahc_linux_setup_tag_info_global(char *p); static aic_option_callback_t ahc_linux_setup_tag_info; static int aic7xxx_setup(char *s); static int ahc_linux_next_unit(void); -static void ahc_runq_tasklet(unsigned long data); static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); /********************************* Inlines ************************************/ -static __inline void ahc_schedule_runq(struct ahc_softc *ahc); static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc); static __inline void ahc_schedule_completeq(struct ahc_softc *ahc); -static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev); -static __inline struct ahc_linux_device * - ahc_linux_next_device_to_run(struct ahc_softc *ahc); -static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc); static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, @@ -494,15 +488,6 @@ ahc_schedule_completeq(struct ahc_softc *ahc) } } -/* - * Must be called with our lock held. - */ -static __inline void -ahc_schedule_runq(struct ahc_softc *ahc) -{ - tasklet_schedule(&ahc->platform_data->runq_tasklet); -} - static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc) @@ -569,45 +554,6 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc) } static __inline void -ahc_linux_check_device_queue(struct ahc_softc *ahc, - struct ahc_linux_device *dev) -{ - if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0 - && dev->active == 0) { - dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY; - dev->qfrozen--; - } - - if (TAILQ_FIRST(&dev->busyq) == NULL - || dev->openings == 0 || dev->qfrozen != 0) - return; - - ahc_linux_run_device_queue(ahc, dev); -} - -static __inline struct ahc_linux_device * -ahc_linux_next_device_to_run(struct ahc_softc *ahc) -{ - - if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 - || (ahc->platform_data->qfrozen != 0)) - return (NULL); - return (TAILQ_FIRST(&ahc->platform_data->device_runq)); -} - -static __inline void -ahc_linux_run_device_queues(struct ahc_softc *ahc) -{ - struct ahc_linux_device *dev; - - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); - } -} - -static __inline void ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) { Scsi_Cmnd *cmd; @@ -871,7 +817,6 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) { struct ahc_softc *ahc; struct ahc_linux_device *dev; - u_long flags; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; @@ -880,42 +825,22 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) */ cmd->scsi_done = scsi_done; - ahc_midlayer_entrypoint_lock(ahc, &flags); - /* * Close the race of a command that was in the process of * being queued to us just as our simq was frozen. Let * DV commands through so long as we are only frozen to * perform DV. */ - if (ahc->platform_data->qfrozen != 0) { + if (ahc->platform_data->qfrozen != 0) + return SCSI_MLQUEUE_HOST_BUSY; - ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); - ahc_linux_queue_cmd_complete(ahc, cmd); - ahc_schedule_completeq(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &flags); - return (0); - } dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/TRUE); - if (dev == NULL) { - ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); - ahc_linux_queue_cmd_complete(ahc, cmd); - ahc_schedule_completeq(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &flags); - printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n", - ahc_name(ahc)); - return (0); - } + BUG_ON(dev == NULL); + cmd->result = CAM_REQ_INPROG << 16; - TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe); - if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - ahc_linux_run_device_queues(ahc); - } - ahc_midlayer_entrypoint_unlock(ahc, &flags); - return (0); + + return ahc_linux_run_command(ahc, dev, cmd); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -987,8 +912,7 @@ ahc_linux_slave_destroy(Scsi_Device *device) if (dev != NULL && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) { dev->flags |= AHC_DEV_UNCONFIGURED; - if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0 + if (dev->active == 0 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) ahc_linux_free_device(ahc, dev); } @@ -1206,33 +1130,6 @@ Scsi_Host_Template aic7xxx_driver_template = { /**************************** Tasklet Handler *********************************/ -/* - * In 2.4.X and above, this routine is called from a tasklet, - * so we must re-acquire our lock prior to executing this code. - * In all prior kernels, ahc_schedule_runq() calls this routine - * directly and ahc_schedule_runq() is called with our lock held. - */ -static void -ahc_runq_tasklet(unsigned long data) -{ - struct ahc_softc* ahc; - struct ahc_linux_device *dev; - u_long flags; - - ahc = (struct ahc_softc *)data; - ahc_lock(ahc, &flags); - while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { - - TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); - dev->flags &= ~AHC_DEV_ON_RUN_LIST; - ahc_linux_check_device_queue(ahc, dev); - /* Yeild to our interrupt handler */ - ahc_unlock(ahc, &flags); - ahc_lock(ahc, &flags); - } - ahc_unlock(ahc, &flags); -} - /******************************** Macros **************************************/ #define BUILD_SCSIID(ahc, cmd) \ ((((cmd)->device->id << TID_SHIFT) & TID) \ @@ -1728,8 +1625,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) ahc->platform_data->completeq_timer.function = (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); - tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, - (unsigned long)ahc); ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; if (aic7xxx_pci_parity == 0) @@ -1747,7 +1642,6 @@ ahc_platform_free(struct ahc_softc *ahc) if (ahc->platform_data != NULL) { del_timer_sync(&ahc->platform_data->completeq_timer); - tasklet_kill(&ahc->platform_data->runq_tasklet); if (ahc->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); @@ -1906,71 +1800,7 @@ int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, int lun, u_int tag, role_t role, uint32_t status) { - int chan; - int maxchan; - int targ; - int maxtarg; - int clun; - int maxlun; - int count; - - if (tag != SCB_LIST_NULL) - return (0); - - chan = 0; - if (channel != ALL_CHANNELS) { - chan = channel - 'A'; - maxchan = chan + 1; - } else { - maxchan = (ahc->features & AHC_TWIN) ? 2 : 1; - } - targ = 0; - if (target != CAM_TARGET_WILDCARD) { - targ = target; - maxtarg = targ + 1; - } else { - maxtarg = (ahc->features & AHC_WIDE) ? 16 : 8; - } - clun = 0; - if (lun != CAM_LUN_WILDCARD) { - clun = lun; - maxlun = clun + 1; - } else { - maxlun = AHC_NUM_LUNS; - } - - count = 0; - for (; chan < maxchan; chan++) { - - for (; targ < maxtarg; targ++) { - - for (; clun < maxlun; clun++) { - struct ahc_linux_device *dev; - struct ahc_busyq *busyq; - struct ahc_cmd *acmd; - - dev = ahc_linux_get_device(ahc, chan, - targ, clun, - /*alloc*/FALSE); - if (dev == NULL) - continue; - - busyq = &dev->busyq; - while ((acmd = TAILQ_FIRST(busyq)) != NULL) { - Scsi_Cmnd *cmd; - - cmd = &acmd_scsi_cmd(acmd); - TAILQ_REMOVE(busyq, acmd, - acmd_links.tqe); - count++; - cmd->result = status << 16; - ahc_linux_queue_cmd_complete(ahc, cmd); - } - } - } - } - - return (count); + return 0; } static void @@ -2045,213 +1875,203 @@ ahc_linux_device_queue_depth(struct ahc_softc *ahc, } } -static void -ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) +static int +ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, + struct scsi_cmnd *cmd) { - struct ahc_cmd *acmd; - struct scsi_cmnd *cmd; struct scb *scb; struct hardware_scb *hscb; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; uint16_t mask; + struct scb_tailq *untagged_q = NULL; - if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0) - panic("running device on run list"); + /* + * Schedule us to run later. The only reason we are not + * running is because the whole controller Q is frozen. + */ + if (ahc->platform_data->qfrozen != 0) + return SCSI_MLQUEUE_HOST_BUSY; - while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL - && dev->openings > 0 && dev->qfrozen == 0) { + /* + * We only allow one untagged transaction + * per target in the initiator role unless + * we are storing a full busy target *lun* + * table in SCB space. + */ + if (!blk_rq_tagged(cmd->request) + && (ahc->features & AHC_SCB_BTT) == 0) { + int target_offset; - /* - * Schedule us to run later. The only reason we are not - * running is because the whole controller Q is frozen. - */ - if (ahc->platform_data->qfrozen != 0) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, - dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - return; - } - /* - * Get an scb to use. - */ - if ((scb = ahc_get_scb(ahc)) == NULL) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, - dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; + target_offset = cmd->device->id + cmd->device->channel * 8; + untagged_q = &(ahc->untagged_queues[target_offset]); + if (!TAILQ_EMPTY(untagged_q)) + /* if we're already executing an untagged command + * we're busy to another */ + return SCSI_MLQUEUE_DEVICE_BUSY; + } + + /* + * Get an scb to use. + */ + if ((scb = ahc_get_scb(ahc)) == NULL) { ahc->flags |= AHC_RESOURCE_SHORTAGE; - return; - } - TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe); - cmd = &acmd_scsi_cmd(acmd); - scb->io_ctx = cmd; - scb->platform_data->dev = dev; - hscb = scb->hscb; - cmd->host_scribble = (char *)scb; + return SCSI_MLQUEUE_HOST_BUSY; + } - /* - * Fill out basics of the HSCB. - */ - hscb->control = 0; - hscb->scsiid = BUILD_SCSIID(ahc, cmd); - hscb->lun = cmd->device->lun; - mask = SCB_GET_TARGET_MASK(ahc, scb); - tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb), - SCB_GET_OUR_ID(scb), - SCB_GET_TARGET(ahc, scb), &tstate); - hscb->scsirate = tinfo->scsirate; - hscb->scsioffset = tinfo->curr.offset; - if ((tstate->ultraenb & mask) != 0) - hscb->control |= ULTRAENB; - - if ((ahc->user_discenable & mask) != 0) - hscb->control |= DISCENB; - - if ((tstate->auto_negotiate & mask) != 0) { - scb->flags |= SCB_AUTO_NEGOTIATE; - scb->hscb->control |= MK_MESSAGE; - } + scb->io_ctx = cmd; + scb->platform_data->dev = dev; + hscb = scb->hscb; + cmd->host_scribble = (char *)scb; - if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) { + /* + * Fill out basics of the HSCB. + */ + hscb->control = 0; + hscb->scsiid = BUILD_SCSIID(ahc, cmd); + hscb->lun = cmd->device->lun; + mask = SCB_GET_TARGET_MASK(ahc, scb); + tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb), + SCB_GET_OUR_ID(scb), + SCB_GET_TARGET(ahc, scb), &tstate); + hscb->scsirate = tinfo->scsirate; + hscb->scsioffset = tinfo->curr.offset; + if ((tstate->ultraenb & mask) != 0) + hscb->control |= ULTRAENB; + + if ((ahc->user_discenable & mask) != 0) + hscb->control |= DISCENB; + + if ((tstate->auto_negotiate & mask) != 0) { + scb->flags |= SCB_AUTO_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; + } + + if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - int msg_bytes; - uint8_t tag_msgs[2]; - - msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs); - if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) { - hscb->control |= tag_msgs[0]; - if (tag_msgs[0] == MSG_ORDERED_TASK) - dev->commands_since_idle_or_otag = 0; - } else -#endif - if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH - && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { - hscb->control |= MSG_ORDERED_TASK; + int msg_bytes; + uint8_t tag_msgs[2]; + + msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs); + if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) { + hscb->control |= tag_msgs[0]; + if (tag_msgs[0] == MSG_ORDERED_TASK) dev->commands_since_idle_or_otag = 0; - } else { - hscb->control |= MSG_SIMPLE_TASK; - } - } - - hscb->cdb_len = cmd->cmd_len; - if (hscb->cdb_len <= 12) { - memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len); + } else +#endif + if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH + && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { + hscb->control |= MSG_ORDERED_TASK; + dev->commands_since_idle_or_otag = 0; } else { - memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len); - scb->flags |= SCB_CDB32_PTR; + hscb->control |= MSG_SIMPLE_TASK; } + } - scb->platform_data->xfer_len = 0; - ahc_set_residual(scb, 0); - ahc_set_sense_residual(scb, 0); - scb->sg_count = 0; - if (cmd->use_sg != 0) { - struct ahc_dma_seg *sg; - struct scatterlist *cur_seg; - struct scatterlist *end_seg; - int nseg; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg, - cmd->sc_data_direction); - end_seg = cur_seg + nseg; - /* Copy the segments into the SG list. */ - sg = scb->sg_list; - /* - * The sg_count may be larger than nseg if - * a transfer crosses a 32bit page. - */ - while (cur_seg < end_seg) { - dma_addr_t addr; - bus_size_t len; - int consumed; - - addr = sg_dma_address(cur_seg); - len = sg_dma_len(cur_seg); - consumed = ahc_linux_map_seg(ahc, scb, - sg, addr, len); - sg += consumed; - scb->sg_count += consumed; - cur_seg++; - } - sg--; - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); - - /* - * Reset the sg list pointer. - */ - scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + hscb->cdb_len = cmd->cmd_len; + if (hscb->cdb_len <= 12) { + memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len); + } else { + memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len); + scb->flags |= SCB_CDB32_PTR; + } - /* - * Copy the first SG into the "current" - * data pointer area. - */ - scb->hscb->dataptr = scb->sg_list->addr; - scb->hscb->datacnt = scb->sg_list->len; - } else if (cmd->request_bufflen != 0) { - struct ahc_dma_seg *sg; + scb->platform_data->xfer_len = 0; + ahc_set_residual(scb, 0); + ahc_set_sense_residual(scb, 0); + scb->sg_count = 0; + if (cmd->use_sg != 0) { + struct ahc_dma_seg *sg; + struct scatterlist *cur_seg; + struct scatterlist *end_seg; + int nseg; + + cur_seg = (struct scatterlist *)cmd->request_buffer; + nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg, + cmd->sc_data_direction); + end_seg = cur_seg + nseg; + /* Copy the segments into the SG list. */ + sg = scb->sg_list; + /* + * The sg_count may be larger than nseg if + * a transfer crosses a 32bit page. + */ + while (cur_seg < end_seg) { dma_addr_t addr; - - sg = scb->sg_list; - addr = pci_map_single(ahc->dev_softc, - cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - scb->platform_data->buf_busaddr = addr; - scb->sg_count = ahc_linux_map_seg(ahc, scb, - sg, addr, - cmd->request_bufflen); - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); - - /* - * Reset the sg list pointer. - */ - scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); - - /* - * Copy the first SG into the "current" - * data pointer area. - */ - scb->hscb->dataptr = sg->addr; - scb->hscb->datacnt = sg->len; - } else { - scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); - scb->hscb->dataptr = 0; - scb->hscb->datacnt = 0; - scb->sg_count = 0; + bus_size_t len; + int consumed; + + addr = sg_dma_address(cur_seg); + len = sg_dma_len(cur_seg); + consumed = ahc_linux_map_seg(ahc, scb, + sg, addr, len); + sg += consumed; + scb->sg_count += consumed; + cur_seg++; } + sg--; + sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); - ahc_sync_sglist(ahc, scb, BUS_DMASYNC_PREWRITE); - LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); - dev->openings--; - dev->active++; - dev->commands_issued++; - if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0) - dev->commands_since_idle_or_otag++; + /* + * Reset the sg list pointer. + */ + scb->hscb->sgptr = + ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + + /* + * Copy the first SG into the "current" + * data pointer area. + */ + scb->hscb->dataptr = scb->sg_list->addr; + scb->hscb->datacnt = scb->sg_list->len; + } else if (cmd->request_bufflen != 0) { + struct ahc_dma_seg *sg; + dma_addr_t addr; + + sg = scb->sg_list; + addr = pci_map_single(ahc->dev_softc, + cmd->request_buffer, + cmd->request_bufflen, + cmd->sc_data_direction); + scb->platform_data->buf_busaddr = addr; + scb->sg_count = ahc_linux_map_seg(ahc, scb, + sg, addr, + cmd->request_bufflen); + sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); /* - * We only allow one untagged transaction - * per target in the initiator role unless - * we are storing a full busy target *lun* - * table in SCB space. + * Reset the sg list pointer. */ - if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 - && (ahc->features & AHC_SCB_BTT) == 0) { - struct scb_tailq *untagged_q; - int target_offset; - - target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); - untagged_q = &(ahc->untagged_queues[target_offset]); - TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); - scb->flags |= SCB_UNTAGGEDQ; - if (TAILQ_FIRST(untagged_q) != scb) - continue; - } - scb->flags |= SCB_ACTIVE; - ahc_queue_scb(ahc, scb); + scb->hscb->sgptr = + ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); + + /* + * Copy the first SG into the "current" + * data pointer area. + */ + scb->hscb->dataptr = sg->addr; + scb->hscb->datacnt = sg->len; + } else { + scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); + scb->hscb->dataptr = 0; + scb->hscb->datacnt = 0; + scb->sg_count = 0; + } + + LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); + dev->openings--; + dev->active++; + dev->commands_issued++; + if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0) + dev->commands_since_idle_or_otag++; + + scb->flags |= SCB_ACTIVE; + if (untagged_q) { + TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); + scb->flags |= SCB_UNTAGGEDQ; } + ahc_queue_scb(ahc, scb); + return 0; } /* @@ -2267,8 +2087,6 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) ahc = (struct ahc_softc *) dev_id; ahc_lock(ahc, &flags); ours = ahc_intr(ahc); - if (ahc_linux_next_device_to_run(ahc) != NULL) - ahc_schedule_runq(ahc); ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); return IRQ_RETVAL(ours); @@ -2349,7 +2167,6 @@ ahc_linux_alloc_device(struct ahc_softc *ahc, return (NULL); memset(dev, 0, sizeof(*dev)); init_timer(&dev->timer); - TAILQ_INIT(&dev->busyq); dev->flags = AHC_DEV_UNCONFIGURED; dev->lun = lun; dev->target = targ; @@ -2515,7 +2332,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); untagged_q = &(ahc->untagged_queues[target_offset]); TAILQ_REMOVE(untagged_q, scb, links.tqe); - ahc_run_untagged_queue(ahc, untagged_q); + BUG_ON(!TAILQ_EMPTY(untagged_q)); } if ((scb->flags & SCB_ACTIVE) == 0) { @@ -2606,12 +2423,11 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) if (dev->active == 0) dev->commands_since_idle_or_otag = 0; - if (TAILQ_EMPTY(&dev->busyq)) { - if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 - && dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) - ahc_linux_free_device(ahc, dev); - } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { + if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 + && dev->active == 0 + && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) + ahc_linux_free_device(ahc, dev); + else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); dev->flags |= AHC_DEV_ON_RUN_LIST; } @@ -2940,7 +2756,6 @@ ahc_linux_release_simq(u_long arg) ahc->platform_data->qfrozen--; if (ahc->platform_data->qfrozen == 0) unblock_reqs = 1; - ahc_schedule_runq(ahc); ahc_unlock(ahc, &s); /* * There is still a race here. The mid-layer @@ -2965,11 +2780,7 @@ ahc_linux_dev_timed_unfreeze(u_long arg) dev->flags &= ~AHC_DEV_TIMER_ACTIVE; if (dev->qfrozen > 0) dev->qfrozen--; - if (dev->qfrozen == 0 - && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0) - ahc_linux_run_device_queue(ahc, dev); - if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0) + if (dev->active == 0) __ahc_linux_free_device(ahc, dev); ahc_unlock(ahc, &s); } @@ -2978,8 +2789,6 @@ static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) { struct ahc_softc *ahc; - struct ahc_cmd *acmd; - struct ahc_cmd *list_acmd; struct ahc_linux_device *dev; struct scb *pending_scb; u_long s; @@ -2998,7 +2807,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) paused = FALSE; wait = FALSE; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; - acmd = (struct ahc_cmd *)cmd; printf("%s:%d:%d:%d: Attempting to queue a%s message\n", ahc_name(ahc), cmd->device->channel, @@ -3048,24 +2856,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) goto no_cmd; } - TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) { - if (list_acmd == acmd) - break; - } - - if (list_acmd != NULL) { - printf("%s:%d:%d:%d: Command found on device queue\n", - ahc_name(ahc), cmd->device->channel, cmd->device->id, - cmd->device->lun); - if (flag == SCB_ABORT) { - TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe); - cmd->result = DID_ABORT << 16; - ahc_linux_queue_cmd_complete(ahc, cmd); - retval = SUCCESS; - goto done; - } - } - if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id, cmd->device->channel + 'A', @@ -3299,7 +3089,6 @@ done: } spin_lock_irq(&ahc->platform_data->spin_lock); } - ahc_schedule_runq(ahc); ahc_linux_run_complete_queue(ahc); ahc_midlayer_entrypoint_unlock(ahc, &s); return (retval); @@ -3308,40 +3097,6 @@ done: void ahc_platform_dump_card_state(struct ahc_softc *ahc) { - struct ahc_linux_device *dev; - int channel; - int maxchannel; - int target; - int maxtarget; - int lun; - int i; - - maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0; - maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7; - for (channel = 0; channel <= maxchannel; channel++) { - - for (target = 0; target <=maxtarget; target++) { - - for (lun = 0; lun < AHC_NUM_LUNS; lun++) { - struct ahc_cmd *acmd; - - dev = ahc_linux_get_device(ahc, channel, target, - lun, /*alloc*/FALSE); - if (dev == NULL) - continue; - - printf("DevQ(%d:%d:%d): ", - channel, target, lun); - i = 0; - TAILQ_FOREACH(acmd, &dev->busyq, - acmd_links.tqe) { - if (i++ > AHC_SCB_MAX) - break; - } - printf("%d waiting\n", i); - } - } - } } static void ahc_linux_exit(void); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index ed9027b..9560970 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -66,11 +66,11 @@ #include #include #include +#include #include #include #include -#include /* For tasklet support. */ #include #include @@ -341,7 +341,6 @@ typedef enum { struct ahc_linux_target; struct ahc_linux_device { TAILQ_ENTRY(ahc_linux_device) links; - struct ahc_busyq busyq; /* * The number of transactions currently @@ -488,7 +487,6 @@ struct ahc_platform_data { struct ahc_completeq completeq; spinlock_t spin_lock; - struct tasklet_struct runq_tasklet; u_int qfrozen; pid_t dv_pid; struct timer_list completeq_timer; -- cgit v1.1 From c06716fe1cea97749668c83e8374b453fbd00823 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 May 2005 18:51:13 +0200 Subject: [SCSI] aic7xxx: remove some DV leftovers Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 9560970..6ea2bfb 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -488,15 +488,9 @@ struct ahc_platform_data { spinlock_t spin_lock; u_int qfrozen; - pid_t dv_pid; struct timer_list completeq_timer; struct timer_list reset_timer; struct semaphore eh_sem; - struct semaphore dv_sem; - struct semaphore dv_cmd_sem; /* XXX This needs to be in - * the target struct - */ - struct scsi_device *dv_scsi_dev; struct Scsi_Host *host; /* pointer to scsi host */ #define AHC_LINUX_NOIRQ ((uint32_t)~0) uint32_t irq; /* IRQ for this adapter */ -- cgit v1.1 From dedd831081052028f35aaf924ea3d6c55109074f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 May 2005 18:52:06 +0200 Subject: [SCSI] aic7xxx: remove Linux 2.4 ifdefs There's not much sense in sharing code anymore now that aic7xxx uses various transport class facilities. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7770_osm.c | 52 +----- drivers/scsi/aic7xxx/aic7xxx_osm.c | 314 +-------------------------------- drivers/scsi/aic7xxx/aic7xxx_osm.h | 89 ---------- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 9 +- drivers/scsi/aic7xxx/aic7xxx_proc.c | 13 -- 5 files changed, 5 insertions(+), 472 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index c2b47f2..682ca0b 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -41,7 +41,6 @@ #include "aic7xxx_osm.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #include #include @@ -62,13 +61,6 @@ static struct eisa_driver aic7770_driver = { }; typedef struct device *aic7770_dev_t; -#else -#define MINSLOT 1 -#define NUMSLOTS 16 -#define IDOFFSET 0x80 - -typedef void *aic7770_dev_t; -#endif static int aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, u_int eisaBase); @@ -76,7 +68,6 @@ static int aic7770_linux_config(struct aic7770_identity *entry, int ahc_linux_eisa_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) struct eisa_device_id *eid; struct aic7770_identity *id; int i; @@ -110,44 +101,6 @@ ahc_linux_eisa_init(void) eid->sig[0] = 0; return eisa_driver_register(&aic7770_driver); -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */ - struct aic7770_identity *entry; - u_int slot; - u_int eisaBase; - u_int i; - int ret = -ENODEV; - - if (aic7xxx_probe_eisa_vl == 0) - return ret; - - eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET; - for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) { - uint32_t eisa_id; - size_t id_size; - - if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0) - continue; - - eisa_id = 0; - id_size = sizeof(eisa_id); - for (i = 0; i < 4; i++) { - /* VLcards require priming*/ - outb(0x80 + i, eisaBase + IDOFFSET); - eisa_id |= inb(eisaBase + IDOFFSET + i) - << ((id_size-i-1) * 8); - } - release_region(eisaBase, AHC_EISA_IOSIZE); - if (eisa_id & 0x80000000) - continue; /* no EISA card in slot */ - - entry = aic7770_find_device(eisa_id); - if (entry != NULL) { - aic7770_linux_config(entry, NULL, eisaBase); - ret = 0; - } - } - return ret; -#endif } void @@ -187,11 +140,10 @@ aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, ahc_free(ahc); return (error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + dev->driver_data = (void *)ahc; if (aic7xxx_detect_complete) error = ahc_linux_register_host(ahc, &aic7xxx_driver_template); -#endif return (error); } @@ -225,7 +177,6 @@ aic7770_map_int(struct ahc_softc *ahc, u_int irq) return (-error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) static int aic7770_eisa_dev_probe(struct device *dev) { @@ -261,4 +212,3 @@ aic7770_eisa_dev_remove(struct device *dev) return (0); } -#endif diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 9017942..37fda70 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -134,11 +134,6 @@ static struct scsi_transport_template *ahc_linux_transport_template = NULL; #include "aiclib.c" #include /* __setup */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#include "sd.h" /* For geometry detection */ -#endif - #include /* For fetching system memory size */ #include /* For block_size() */ #include /* For ssleep/msleep */ @@ -148,11 +143,6 @@ static struct scsi_transport_template *ahc_linux_transport_template = NULL; */ spinlock_t ahc_list_spinlock; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -/* For dynamic sglist size calculation. */ -u_int ahc_linux_nseg; -#endif - /* * Set this to the delay in seconds after SCSI bus reset. * Note, we honor this only for the initial bus reset. @@ -443,7 +433,6 @@ static void ahc_linux_release_simq(u_long arg); static void ahc_linux_dev_timed_unfreeze(u_long arg); static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); -static void ahc_linux_size_nseg(void); static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); @@ -519,11 +508,9 @@ static struct ahc_cmd * ahc_linux_run_complete_queue(struct ahc_softc *ahc) { struct ahc_cmd *acmd; - u_long done_flags; int with_errors; with_errors = 0; - ahc_done_lock(ahc, &done_flags); while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; @@ -549,7 +536,6 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc) cmd->scsi_done(cmd); } - ahc_done_unlock(ahc, &done_flags); return (acmd); } @@ -600,7 +586,6 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, static int ahc_linux_detect(Scsi_Host_Template *); static int ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); static const char *ahc_linux_info(struct Scsi_Host *); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) static int ahc_linux_slave_alloc(Scsi_Device *); static int ahc_linux_slave_configure(Scsi_Device *); static void ahc_linux_slave_destroy(Scsi_Device *); @@ -609,80 +594,11 @@ static int ahc_linux_biosparam(struct scsi_device*, struct block_device*, sector_t, int[]); #endif -#else -static int ahc_linux_release(struct Scsi_Host *); -static void ahc_linux_select_queue_depth(struct Scsi_Host *host, - Scsi_Device *scsi_devs); -#if defined(__i386__) -static int ahc_linux_biosparam(Disk *, kdev_t, int[]); -#endif -#endif static int ahc_linux_bus_reset(Scsi_Cmnd *); static int ahc_linux_dev_reset(Scsi_Cmnd *); static int ahc_linux_abort(Scsi_Cmnd *); /* - * Calculate a safe value for AHC_NSEG (as expressed through ahc_linux_nseg). - * - * In pre-2.5.X... - * The midlayer allocates an S/G array dynamically when a command is issued - * using SCSI malloc. This array, which is in an OS dependent format that - * must later be copied to our private S/G list, is sized to house just the - * number of segments needed for the current transfer. Since the code that - * sizes the SCSI malloc pool does not take into consideration fragmentation - * of the pool, executing transactions numbering just a fraction of our - * concurrent transaction limit with list lengths aproaching AHC_NSEG will - * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the - * mid-layer does not properly handle this scsi malloc failures for the S/G - * array and the result can be a lockup of the I/O subsystem. We try to size - * our S/G list so that it satisfies our drivers allocation requirements in - * addition to avoiding fragmentation of the SCSI malloc pool. - */ -static void -ahc_linux_size_nseg(void) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - u_int cur_size; - u_int best_size; - - /* - * The SCSI allocator rounds to the nearest 512 bytes - * an cannot allocate across a page boundary. Our algorithm - * is to start at 1K of scsi malloc space per-command and - * loop through all factors of the PAGE_SIZE and pick the best. - */ - best_size = 0; - for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) { - u_int nseg; - - nseg = cur_size / sizeof(struct scatterlist); - if (nseg < AHC_LINUX_MIN_NSEG) - continue; - - if (best_size == 0) { - best_size = cur_size; - ahc_linux_nseg = nseg; - } else { - u_int best_rem; - u_int cur_rem; - - /* - * Compare the traits of the current "best_size" - * with the current size to determine if the - * current size is a better size. - */ - best_rem = best_size % sizeof(struct scatterlist); - cur_rem = cur_size % sizeof(struct scatterlist); - if (cur_rem < best_rem) { - best_size = cur_size; - ahc_linux_nseg = nseg; - } - } - } -#endif -} - -/* * Try to detect an Adaptec 7XXX controller. */ static int @@ -691,14 +607,6 @@ ahc_linux_detect(Scsi_Host_Template *template) struct ahc_softc *ahc; int found = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - /* - * It is a bug that the upper layer takes - * this lock just prior to calling us. - */ - spin_unlock_irq(&io_request_lock); -#endif - /* * Sanity checking of Linux SCSI data structures so * that some of our hacks^H^H^H^H^Hassumptions aren't @@ -710,7 +618,6 @@ ahc_linux_detect(Scsi_Host_Template *template) printf("ahc_linux_detect: Unable to attach\n"); return (0); } - ahc_linux_size_nseg(); /* * If we've been passed any parameters, process them now. */ @@ -739,48 +646,11 @@ ahc_linux_detect(Scsi_Host_Template *template) found++; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - spin_lock_irq(&io_request_lock); -#endif aic7xxx_detect_complete++; return (found); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -/* - * Free the passed in Scsi_Host memory structures prior to unloading the - * module. - */ -int -ahc_linux_release(struct Scsi_Host * host) -{ - struct ahc_softc *ahc; - u_long l; - - ahc_list_lock(&l); - if (host != NULL) { - - /* - * We should be able to just perform - * the free directly, but check our - * list for extra sanity. - */ - ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata); - if (ahc != NULL) { - u_long s; - - ahc_lock(ahc, &s); - ahc_intr_enable(ahc, FALSE); - ahc_unlock(ahc, &s); - ahc_free(ahc); - } - } - ahc_list_unlock(&l); - return (0); -} -#endif - /* * Return a string describing the driver. */ @@ -843,7 +713,6 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) return ahc_linux_run_command(ahc, dev, cmd); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) static int ahc_linux_slave_alloc(Scsi_Device *device) { @@ -860,12 +729,10 @@ ahc_linux_slave_configure(Scsi_Device *device) { struct ahc_softc *ahc; struct ahc_linux_device *dev; - u_long flags; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id); - ahc_midlayer_entrypoint_lock(ahc, &flags); /* * Since Linux has attached to the device, configure * it so we don't free and allocate the device @@ -879,7 +746,6 @@ ahc_linux_slave_configure(Scsi_Device *device) dev->scsi_device = device; ahc_linux_device_queue_depth(ahc, dev); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); /* Initial Domain Validation */ if (!spi_initial_dv(device->sdev_target)) @@ -893,12 +759,10 @@ ahc_linux_slave_destroy(Scsi_Device *device) { struct ahc_softc *ahc; struct ahc_linux_device *dev; - u_long flags; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id); - ahc_midlayer_entrypoint_lock(ahc, &flags); dev = ahc_linux_get_device(ahc, device->channel, device->id, device->lun, /*alloc*/FALSE); @@ -916,93 +780,17 @@ ahc_linux_slave_destroy(Scsi_Device *device) && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) ahc_linux_free_device(ahc, dev); } - ahc_midlayer_entrypoint_unlock(ahc, &flags); } -#else -/* - * Sets the queue depth for each SCSI device hanging - * off the input host adapter. - */ -static void -ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) -{ - Scsi_Device *device; - Scsi_Device *ldev; - struct ahc_softc *ahc; - u_long flags; - - ahc = *((struct ahc_softc **)host->hostdata); - ahc_lock(ahc, &flags); - for (device = scsi_devs; device != NULL; device = device->next) { - - /* - * Watch out for duplicate devices. This works around - * some quirks in how the SCSI scanning code does its - * device management. - */ - for (ldev = scsi_devs; ldev != device; ldev = ldev->next) { - if (ldev->host == device->host - && ldev->channel == device->channel - && ldev->id == device->id - && ldev->lun == device->lun) - break; - } - /* Skip duplicate. */ - if (ldev != device) - continue; - - if (device->host == host) { - struct ahc_linux_device *dev; - - /* - * Since Linux has attached to the device, configure - * it so we don't free and allocate the device - * structure on every command. - */ - dev = ahc_linux_get_device(ahc, device->channel, - device->id, device->lun, - /*alloc*/TRUE); - if (dev != NULL) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; - dev->scsi_device = device; - ahc_linux_device_queue_depth(ahc, dev); - device->queue_depth = dev->openings - + dev->active; - if ((dev->flags & (AHC_DEV_Q_BASIC - | AHC_DEV_Q_TAGGED)) == 0) { - /* - * We allow the OS to queue 2 untagged - * transactions to us at any time even - * though we can only execute them - * serially on the controller/device. - * This should remove some latency. - */ - device->queue_depth = 2; - } - } - } - } - ahc_unlock(ahc, &flags); -} -#endif #if defined(__i386__) /* * Return the disk geometry for the given SCSI device. */ static int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) { uint8_t *bh; -#else -ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) -{ - struct scsi_device *sdev = disk->device; - u_long capacity = disk->capacity; - struct buffer_head *bh; -#endif int heads; int sectors; int cylinders; @@ -1014,22 +802,11 @@ ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) ahc = *((struct ahc_softc **)sdev->host->hostdata); channel = sdev->channel; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) bh = scsi_bios_ptable(bdev); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17) - bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev)); -#else - bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024); -#endif - if (bh) { ret = scsi_partsize(bh, capacity, &geom[2], &geom[0], &geom[1]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) kfree(bh); -#else - brelse(bh); -#endif if (ret != -1) return (ret); } @@ -1090,15 +867,12 @@ static int ahc_linux_bus_reset(Scsi_Cmnd *cmd) { struct ahc_softc *ahc; - u_long s; int found; ahc = *(struct ahc_softc **)cmd->device->host->hostdata; - ahc_midlayer_entrypoint_lock(ahc, &s); found = ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate reset*/TRUE); ahc_linux_run_complete_queue(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &s); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1461,11 +1235,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) *((struct ahc_softc **)host->hostdata) = ahc; ahc_lock(ahc, &s); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_assign_lock(host, &ahc->platform_data->spin_lock); -#elif AHC_SCSI_HAS_HOST_LOCK != 0 - host->lock = &ahc->platform_data->spin_lock; -#endif ahc->platform_data->host = host; host->can_queue = AHC_MAX_QUEUE; host->cmd_per_lun = 2; @@ -1484,19 +1254,14 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) ahc_set_name(ahc, new_name); } host->unique_id = ahc->unit; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - scsi_set_pci_device(host, ahc->dev_softc); -#endif ahc_linux_initialize_scsi_bus(ahc); ahc_intr_enable(ahc, TRUE); ahc_unlock(ahc, &s); host->transportt = ahc_linux_transport_template; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */ scsi_scan_host(host); -#endif return (0); } @@ -1619,7 +1384,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; ahc_lockinit(ahc); - ahc_done_lockinit(ahc); init_timer(&ahc->platform_data->completeq_timer); ahc->platform_data->completeq_timer.data = (u_long)ahc; ahc->platform_data->completeq_timer.function = @@ -1643,9 +1407,7 @@ ahc_platform_free(struct ahc_softc *ahc) if (ahc->platform_data != NULL) { del_timer_sync(&ahc->platform_data->completeq_timer); if (ahc->platform_data->host != NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); -#endif scsi_host_put(ahc->platform_data->host); } @@ -1681,16 +1443,7 @@ ahc_platform_free(struct ahc_softc *ahc) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - /* - * In 2.4 we detach from the scsi midlayer before the PCI - * layer invokes our remove callback. No per-instance - * detach is provided, so we must reach inside the PCI - * subsystem's internals and detach our driver manually. - */ - if (ahc->dev_softc != NULL) - ahc->dev_softc->driver = NULL; -#endif + free(ahc->platform_data, M_DEVBUF); } } @@ -1767,7 +1520,6 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, dev->maxtags = 0; dev->openings = 1 - dev->active; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (dev->scsi_device != NULL) { switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { case AHC_DEV_Q_BASIC: @@ -1793,7 +1545,6 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, break; } } -#endif } int @@ -1948,7 +1699,6 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, } if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) int msg_bytes; uint8_t tag_msgs[2]; @@ -1957,10 +1707,8 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, hscb->control |= tag_msgs[0]; if (tag_msgs[0] == MSG_ORDERED_TASK) dev->commands_since_idle_or_otag = 0; - } else -#endif - if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH - && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { + } else if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH + && (dev->flags & AHC_DEV_Q_TAGGED) != 0) { hscb->control |= MSG_ORDERED_TASK; dev->commands_since_idle_or_otag = 0; } else { @@ -2280,28 +2028,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel, } case AC_SENT_BDR: { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahc->platform_data->host, channel - 'A', target); -#else - Scsi_Device *scsi_dev; - - /* - * Find the SCSI device associated with this - * request and indicate that a UA is expected. - */ - for (scsi_dev = ahc->platform_data->host->host_queue; - scsi_dev != NULL; scsi_dev = scsi_dev->next) { - if (channel - 'A' == scsi_dev->channel - && target == scsi_dev->id - && (lun == CAM_LUN_WILDCARD - || lun == scsi_dev->lun)) { - scsi_dev->was_reset = 1; - scsi_dev->expecting_cc_ua = 1; - } - } -#endif break; } case AC_BUS_RESET: @@ -2791,7 +2520,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) struct ahc_softc *ahc; struct ahc_linux_device *dev; struct scb *pending_scb; - u_long s; u_int saved_scbptr; u_int active_scb_index; u_int last_phase; @@ -2819,22 +2547,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) printf("\n"); /* - * In all versions of Linux, we have to work around - * a major flaw in how the mid-layer is locked down - * if we are to sleep successfully in our error handler - * while allowing our interrupt handler to run. Since - * the midlayer acquires either the io_request_lock or - * our lock prior to calling us, we must use the - * spin_unlock_irq() method for unlocking our lock. - * This will force interrupts to be enabled on the - * current CPU. Since the EH thread should not have - * been running with CPU interrupts disabled other than - * by acquiring either the io_request_lock or our own - * lock, this *should* be safe. - */ - ahc_midlayer_entrypoint_lock(ahc, &s); - - /* * First determine if we currently own this command. * Start by searching the device queue. If not found * there, check the pending_scb list. If not found @@ -3090,7 +2802,6 @@ done: spin_lock_irq(&ahc->platform_data->spin_lock); } ahc_linux_run_complete_queue(ahc); - ahc_midlayer_entrypoint_unlock(ahc, &s); return (retval); } @@ -3357,7 +3068,6 @@ static struct spi_function_template ahc_linux_transport_functions = { static int __init ahc_linux_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions); if (!ahc_linux_transport_template) return -ENODEV; @@ -3366,29 +3076,11 @@ ahc_linux_init(void) spi_release_transport(ahc_linux_transport_template); ahc_linux_exit(); return -ENODEV; -#else - scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template); - if (aic7xxx_driver_template.present == 0) { - scsi_unregister_module(MODULE_SCSI_HA, - &aic7xxx_driver_template); - return (-ENODEV); - } - - return (0); -#endif } static void ahc_linux_exit(void) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - /* - * In 2.4 we have to unregister from the PCI core _after_ - * unregistering from the scsi midlayer to avoid dangling - * references. - */ - scsi_unregister_module(MODULE_SCSI_HA, &aic7xxx_driver_template); -#endif ahc_linux_pci_exit(); ahc_linux_eisa_exit(); spi_release_transport(ahc_linux_transport_template); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 6ea2bfb..752022e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -281,12 +281,6 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec) /***************************** SMP support ************************************/ #include -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) -#define AHC_SCSI_HAS_HOST_LOCK 1 -#else -#define AHC_SCSI_HAS_HOST_LOCK 0 -#endif - #define AIC7XXX_DRIVER_VERSION "6.2.36" /**************************** Front End Queues ********************************/ @@ -438,18 +432,7 @@ struct ahc_linux_target { * manner and are allocated below 4GB, the number of S/G segments is * unrestricted. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -/* - * We dynamically adjust the number of segments in pre-2.5 kernels to - * avoid fragmentation issues in the SCSI mid-layer's private memory - * allocator. See aic7xxx_osm.c ahc_linux_size_nseg() for details. - */ -extern u_int ahc_linux_nseg; -#define AHC_NSEG ahc_linux_nseg -#define AHC_LINUX_MIN_NSEG 64 -#else #define AHC_NSEG 128 -#endif /* * Per-SCB OSM storage. @@ -607,17 +590,6 @@ static __inline void ahc_lockinit(struct ahc_softc *); static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags); static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags); -/* Lock acquisition and release of the above lock in midlayer entry points. */ -static __inline void ahc_midlayer_entrypoint_lock(struct ahc_softc *, - unsigned long *flags); -static __inline void ahc_midlayer_entrypoint_unlock(struct ahc_softc *, - unsigned long *flags); - -/* Lock held during command compeletion to the upper layer */ -static __inline void ahc_done_lockinit(struct ahc_softc *); -static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags); -static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags); - /* Lock held during ahc_list manipulation and ahc softc frees */ extern spinlock_t ahc_list_spinlock; static __inline void ahc_list_lockinit(void); @@ -643,57 +615,6 @@ ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) } static __inline void -ahc_midlayer_entrypoint_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - /* - * In 2.5.X and some 2.4.X versions, the midlayer takes our - * lock just before calling us, so we avoid locking again. - * For other kernel versions, the io_request_lock is taken - * just before our entry point is called. In this case, we - * trade the io_request_lock for our per-softc lock. - */ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&io_request_lock); - spin_lock(&ahc->platform_data->spin_lock); -#endif -} - -static __inline void -ahc_midlayer_entrypoint_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock(&ahc->platform_data->spin_lock); - spin_lock(&io_request_lock); -#endif -} - -static __inline void -ahc_done_lockinit(struct ahc_softc *ahc) -{ - /* - * In 2.5.X, our own lock is held during completions. - * In previous versions, the io_request_lock is used. - * In either case, we can't initialize this lock again. - */ -} - -static __inline void -ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_lock_irqsave(&io_request_lock, *flags); -#endif -} - -static __inline void -ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -#if AHC_SCSI_HAS_HOST_LOCK == 0 - spin_unlock_irqrestore(&io_request_lock, *flags); -#endif -} - -static __inline void ahc_list_lockinit(void) { spin_lock_init(&ahc_list_spinlock); @@ -759,12 +680,6 @@ typedef enum } ahc_power_state; /**************************** VL/EISA Routines ********************************/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) \ - && (defined(__i386__) || defined(__alpha__)) \ - && (!defined(CONFIG_EISA))) -#define CONFIG_EISA -#endif - #ifdef CONFIG_EISA extern uint32_t aic7xxx_probe_eisa_vl; int ahc_linux_eisa_init(void); @@ -880,12 +795,8 @@ ahc_flush_device_writes(struct ahc_softc *ahc) } /**************************** Proc FS Support *********************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -int ahc_linux_proc_info(char *, char **, off_t, int, int, int); -#else int ahc_linux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); -#endif /*************************** Domain Validation ********************************/ /*********************** Transaction Access Wrappers *************************/ diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 6f6674a..886f92f 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -236,15 +236,8 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (-error); } pci_set_drvdata(pdev, ahc); - if (aic7xxx_detect_complete) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (aic7xxx_detect_complete) ahc_linux_register_host(ahc, &aic7xxx_driver_template); -#else - printf("aic7xxx: ignoring PCI device found after " - "initialization\n"); - return (-ENODEV); -#endif - } return (0); } diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 85e80ee..5fece85 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -289,13 +289,8 @@ done: * Return information to handle /proc support for the driver. */ int -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -ahc_linux_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -#else ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout) -#endif { struct ahc_softc *ahc; struct info_str info; @@ -307,15 +302,7 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, retval = -EINVAL; ahc_list_lock(&s); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - if (ahc->platform_data->host->host_no == hostno) - break; - } -#else ahc = ahc_find_softc(*(struct ahc_softc **)shost->hostdata); -#endif - if (ahc == NULL) goto done; -- cgit v1.1 From 7dfa0f2673c17334c5de75a449f7bc161c9bd2c0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 May 2005 18:54:12 +0200 Subject: [SCSI] remove dma_mask hacks pci_alloc_consistent is under 4G by default. Also simplify the definition of bus_dmamap_t. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 43 ++++------------------------------ drivers/scsi/aic7xxx/aic7xxx_osm.h | 7 +----- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 2 -- 3 files changed, 6 insertions(+), 46 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 37fda70..717401b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -949,37 +949,11 @@ int ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp) { - bus_dmamap_t map; - - map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); - if (map == NULL) - return (ENOMEM); - /* - * Although we can dma data above 4GB, our - * "consistent" memory is below 4GB for - * space efficiency reasons (only need a 4byte - * address). For this reason, we have to reset - * our dma mask when doing allocations. - */ - if (ahc->dev_softc != NULL) - if (pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) { - printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); - kfree(map); - return (ENODEV); - } *vaddr = pci_alloc_consistent(ahc->dev_softc, - dmat->maxsize, &map->bus_addr); - if (ahc->dev_softc != NULL) - if (pci_set_dma_mask(ahc->dev_softc, - ahc->platform_data->hw_dma_mask)) { - printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); - kfree(map); - return (ENODEV); - } + dmat->maxsize, mapp); if (*vaddr == NULL) - return (ENOMEM); - *mapp = map; - return(0); + return ENOMEM; + return 0; } void @@ -987,7 +961,7 @@ ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map) { pci_free_consistent(ahc->dev_softc, dmat->maxsize, - vaddr, map->bus_addr); + vaddr, map); } int @@ -1001,7 +975,7 @@ ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map, */ bus_dma_segment_t stack_sg; - stack_sg.ds_addr = map->bus_addr; + stack_sg.ds_addr = map; stack_sg.ds_len = dmat->maxsize; cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); return (0); @@ -1010,12 +984,6 @@ ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map, void ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) { - /* - * The map may is NULL in our < 2.3.X implementation. - * Now it's 2.6.5, but just in case... - */ - BUG_ON(map == NULL); - free(map, M_DEVBUF); } int @@ -1382,7 +1350,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) TAILQ_INIT(&ahc->platform_data->completeq); TAILQ_INIT(&ahc->platform_data->device_runq); ahc->platform_data->irq = AHC_LINUX_NOIRQ; - ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; ahc_lockinit(ahc); init_timer(&ahc->platform_data->completeq_timer); ahc->platform_data->completeq_timer.data = (u_long)ahc; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 752022e..9cfb46b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -174,11 +174,7 @@ struct ahc_linux_dma_tag }; typedef struct ahc_linux_dma_tag* bus_dma_tag_t; -struct ahc_linux_dmamap -{ - dma_addr_t bus_addr; -}; -typedef struct ahc_linux_dmamap* bus_dmamap_t; +typedef dma_addr_t bus_dmamap_t; typedef int bus_dma_filter_t(void*, dma_addr_t); typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); @@ -479,7 +475,6 @@ struct ahc_platform_data { uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - uint64_t hw_dma_mask; ahc_linux_softc_flags flags; }; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 886f92f..2a0ebce 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -221,13 +221,11 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) && ahc_linux_get_memsize() > 0x80000000 && pci_set_dma_mask(pdev, mask_39bit) == 0) { ahc->flags |= AHC_39BIT_ADDRESSING; - ahc->platform_data->hw_dma_mask = mask_39bit; } else { if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); return (-ENODEV); } - ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK; } ahc->dev_softc = pci; error = ahc_pci_config(ahc, entry); -- cgit v1.1 From 013791ee01754f83dbb4ccfd266381db74e120b5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 May 2005 18:52:39 +0200 Subject: [SCSI] aic7xxx: remove usage of obsolete typedefs Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 52 +++++++++++++------------------------- drivers/scsi/aic7xxx/aic7xxx_osm.h | 36 ++++++++++++++------------ drivers/scsi/aic7xxx/aiclib.c | 1 - 3 files changed, 38 insertions(+), 51 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 717401b..ff2a212 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -426,12 +426,12 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *, struct ahc_linux_device *, struct scb *); static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, - Scsi_Cmnd *cmd); + struct scsi_cmnd *cmd); static void ahc_linux_sem_timeout(u_long arg); static void ahc_linux_freeze_simq(struct ahc_softc *ahc); static void ahc_linux_release_simq(u_long arg); static void ahc_linux_dev_timed_unfreeze(u_long arg); -static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); +static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, @@ -512,7 +512,7 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc) with_errors = 0; while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) { /* @@ -542,7 +542,7 @@ ahc_linux_run_complete_queue(struct ahc_softc *ahc) static __inline void ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) { - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; cmd = scb->io_ctx; ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE); @@ -582,27 +582,11 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, return (consumed); } -/************************ Host template entry points *************************/ -static int ahc_linux_detect(Scsi_Host_Template *); -static int ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -static const char *ahc_linux_info(struct Scsi_Host *); -static int ahc_linux_slave_alloc(Scsi_Device *); -static int ahc_linux_slave_configure(Scsi_Device *); -static void ahc_linux_slave_destroy(Scsi_Device *); -#if defined(__i386__) -static int ahc_linux_biosparam(struct scsi_device*, - struct block_device*, - sector_t, int[]); -#endif -static int ahc_linux_bus_reset(Scsi_Cmnd *); -static int ahc_linux_dev_reset(Scsi_Cmnd *); -static int ahc_linux_abort(Scsi_Cmnd *); - /* * Try to detect an Adaptec 7XXX controller. */ static int -ahc_linux_detect(Scsi_Host_Template *template) +ahc_linux_detect(struct scsi_host_template *template) { struct ahc_softc *ahc; int found = 0; @@ -683,7 +667,7 @@ ahc_linux_info(struct Scsi_Host *host) * Queue an SCB to the controller. */ static int -ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) +ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) { struct ahc_softc *ahc; struct ahc_linux_device *dev; @@ -714,7 +698,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) } static int -ahc_linux_slave_alloc(Scsi_Device *device) +ahc_linux_slave_alloc(struct scsi_device *device) { struct ahc_softc *ahc; @@ -725,7 +709,7 @@ ahc_linux_slave_alloc(Scsi_Device *device) } static int -ahc_linux_slave_configure(Scsi_Device *device) +ahc_linux_slave_configure(struct scsi_device *device) { struct ahc_softc *ahc; struct ahc_linux_device *dev; @@ -755,7 +739,7 @@ ahc_linux_slave_configure(Scsi_Device *device) } static void -ahc_linux_slave_destroy(Scsi_Device *device) +ahc_linux_slave_destroy(struct scsi_device *device) { struct ahc_softc *ahc; struct ahc_linux_device *dev; @@ -836,7 +820,7 @@ ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, * Abort the current SCSI command(s). */ static int -ahc_linux_abort(Scsi_Cmnd *cmd) +ahc_linux_abort(struct scsi_cmnd *cmd) { int error; @@ -850,7 +834,7 @@ ahc_linux_abort(Scsi_Cmnd *cmd) * Attempt to send a target reset message to the device that timed out. */ static int -ahc_linux_dev_reset(Scsi_Cmnd *cmd) +ahc_linux_dev_reset(struct scsi_cmnd *cmd) { int error; @@ -864,7 +848,7 @@ ahc_linux_dev_reset(Scsi_Cmnd *cmd) * Reset the SCSI bus. */ static int -ahc_linux_bus_reset(Scsi_Cmnd *cmd) +ahc_linux_bus_reset(struct scsi_cmnd *cmd) { struct ahc_softc *ahc; int found; @@ -881,7 +865,7 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd) return SUCCESS; } -Scsi_Host_Template aic7xxx_driver_template = { +struct scsi_host_template aic7xxx_driver_template = { .module = THIS_MODULE, .name = "aic7xxx", .proc_info = ahc_linux_proc_info, @@ -1189,7 +1173,7 @@ __setup("aic7xxx=", aic7xxx_setup); uint32_t aic7xxx_verbose; int -ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) +ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template) { char buf[80]; struct Scsi_Host *host; @@ -2017,7 +2001,7 @@ ahc_send_async(struct ahc_softc *ahc, char channel, void ahc_done(struct ahc_softc *ahc, struct scb *scb) { - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; struct ahc_linux_device *dev; LIST_REMOVE(scb, pending_links); @@ -2171,7 +2155,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, case SCSI_STATUS_CHECK_COND: case SCSI_STATUS_CMD_TERMINATED: { - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; /* * Copy sense information to the OS's cmd @@ -2293,7 +2277,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, } static void -ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd) +ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) { /* * Typically, the complete queue has very few entries @@ -2482,7 +2466,7 @@ ahc_linux_dev_timed_unfreeze(u_long arg) } static int -ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag) +ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) { struct ahc_softc *ahc; struct ahc_linux_device *dev; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 9cfb46b..2afd052 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -59,6 +59,7 @@ #ifndef _AIC7XXX_LINUX_H_ #define _AIC7XXX_LINUX_H_ +#include #include #include #include @@ -68,16 +69,19 @@ #include #include #include +#include #include #include -#include -#include +#include +#include +#include +#include +#include +#include /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahc -#include "scsi.h" -#include /* Name space conflict with BSD queue macros */ #ifdef LIST_HEAD @@ -106,7 +110,7 @@ /************************* Forward Declarations *******************************/ struct ahc_softc; typedef struct pci_dev *ahc_dev_softc_t; -typedef Scsi_Cmnd *ahc_io_ctx_t; +typedef struct scsi_cmnd *ahc_io_ctx_t; /******************************* Byte Order ***********************************/ #define ahc_htobe16(x) cpu_to_be16(x) @@ -144,7 +148,7 @@ typedef Scsi_Cmnd *ahc_io_ctx_t; extern u_int aic7xxx_no_probe; extern u_int aic7xxx_allow_memio; extern int aic7xxx_detect_complete; -extern Scsi_Host_Template aic7xxx_driver_template; +extern struct scsi_host_template aic7xxx_driver_template; /***************************** Bus Space/DMA **********************************/ @@ -408,7 +412,7 @@ struct ahc_linux_device { #define AHC_OTAG_THRESH 500 int lun; - Scsi_Device *scsi_device; + struct scsi_device *scsi_device; struct ahc_linux_target *target; }; @@ -564,7 +568,7 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) /**************************** Initialization **********************************/ int ahc_linux_register_host(struct ahc_softc *, - Scsi_Host_Template *); + struct scsi_host_template *); uint64_t ahc_linux_get_memsize(void); @@ -795,13 +799,13 @@ int ahc_linux_proc_info(struct Scsi_Host *, char *, char **, /*************************** Domain Validation ********************************/ /*********************** Transaction Access Wrappers *************************/ -static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); +static __inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); static __inline void ahc_set_transaction_status(struct scb *, uint32_t); -static __inline void ahc_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); +static __inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); static __inline void ahc_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd); +static __inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd); static __inline uint32_t ahc_get_transaction_status(struct scb *); -static __inline uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd); +static __inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd); static __inline uint32_t ahc_get_scsi_status(struct scb *); static __inline void ahc_set_transaction_tag(struct scb *, int, u_int); static __inline u_long ahc_get_transfer_length(struct scb *); @@ -820,7 +824,7 @@ static __inline void ahc_platform_scb_free(struct ahc_softc *ahc, static __inline void ahc_freeze_scb(struct scb *scb); static __inline -void ahc_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) +void ahc_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status) { cmd->result &= ~(CAM_STATUS_MASK << 16); cmd->result |= status << 16; @@ -833,7 +837,7 @@ void ahc_set_transaction_status(struct scb *scb, uint32_t status) } static __inline -void ahc_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) +void ahc_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status) { cmd->result &= ~0xFFFF; cmd->result |= status; @@ -846,7 +850,7 @@ void ahc_set_scsi_status(struct scb *scb, uint32_t status) } static __inline -uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd) +uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd) { return ((cmd->result >> 16) & CAM_STATUS_MASK); } @@ -858,7 +862,7 @@ uint32_t ahc_get_transaction_status(struct scb *scb) } static __inline -uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd) +uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd) { return (cmd->result & 0xFFFF); } diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c index 79bfd9e..7c5a6db 100644 --- a/drivers/scsi/aic7xxx/aiclib.c +++ b/drivers/scsi/aic7xxx/aiclib.c @@ -35,7 +35,6 @@ #include /* Core SCSI definitions */ -#include "scsi.h" #include #include "aiclib.h" #include "cam.h" -- cgit v1.1 From 38c29ce06d24691d6e6dd786175fcc54efd5995b Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 16 May 2005 21:37:58 -0500 Subject: [SCSI] aic7xxx: remove the last vestiges of the runq This was rendered obsolete by the busyq removal; remove some of the last remnants of its presence. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 5 ----- drivers/scsi/aic7xxx/aic7xxx_osm.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index ff2a212..d0c71da 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1332,7 +1332,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) return (ENOMEM); memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); TAILQ_INIT(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->device_runq); ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc_lockinit(ahc); init_timer(&ahc->platform_data->completeq_timer); @@ -2107,10 +2106,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) && dev->active == 0 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) ahc_linux_free_device(ahc, dev); - else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { - TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); - dev->flags |= AHC_DEV_ON_RUN_LIST; - } if ((scb->flags & SCB_RECOVERY_SCB) != 0) { printf("Recovery SCB completes\n"); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 2afd052..9ce7639 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -325,7 +325,6 @@ typedef enum { AHC_DEV_UNCONFIGURED = 0x01, AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ - AHC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */ AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ @@ -466,7 +465,6 @@ struct ahc_platform_data { * Fields accessed from interrupt context. */ struct ahc_linux_target *targets[AHC_NUM_TARGETS]; - TAILQ_HEAD(, ahc_linux_device) device_runq; struct ahc_completeq completeq; spinlock_t spin_lock; -- cgit v1.1 From 8e45ebcc661069bfb002c56dd942aedf43ba9239 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 17 May 2005 00:06:08 -0500 Subject: [SCSI] aic7xxx: remove the completeq This should finish the spurious queue removal from aic7xxx (there are other queues that are probably unnecessary, but at least the major and obviously unnecessary ones are done with). Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 121 +------------------------------------ drivers/scsi/aic7xxx/aic7xxx_osm.h | 17 +----- 2 files changed, 5 insertions(+), 133 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index d0c71da..ca796b9 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -433,7 +433,6 @@ static void ahc_linux_release_simq(u_long arg); static void ahc_linux_dev_timed_unfreeze(u_long arg); static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); -static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo); static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, @@ -454,29 +453,17 @@ static void ahc_linux_setup_tag_info_global(char *p); static aic_option_callback_t ahc_linux_setup_tag_info; static int aic7xxx_setup(char *s); static int ahc_linux_next_unit(void); -static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); /********************************* Inlines ************************************/ static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc); -static __inline void ahc_schedule_completeq(struct ahc_softc *ahc); static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len); -static __inline void -ahc_schedule_completeq(struct ahc_softc *ahc) -{ - if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) { - ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER; - ahc->platform_data->completeq_timer.expires = jiffies; - add_timer(&ahc->platform_data->completeq_timer); - } -} - static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc) @@ -503,42 +490,6 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, return (dev); } -#define AHC_LINUX_MAX_RETURNED_ERRORS 4 -static struct ahc_cmd * -ahc_linux_run_complete_queue(struct ahc_softc *ahc) -{ - struct ahc_cmd *acmd; - int with_errors; - - with_errors = 0; - while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { - struct scsi_cmnd *cmd; - - if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) { - /* - * Linux uses stack recursion to requeue - * commands that need to be retried. Avoid - * blowing out the stack by "spoon feeding" - * commands that completed with error back - * the operating system in case they are going - * to be retried. "ick" - */ - ahc_schedule_completeq(ahc); - break; - } - TAILQ_REMOVE(&ahc->platform_data->completeq, - acmd, acmd_links.tqe); - cmd = &acmd_scsi_cmd(acmd); - cmd->host_scribble = NULL; - if (ahc_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - - cmd->scsi_done(cmd); - } - return (acmd); -} - static __inline void ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) { @@ -856,7 +807,6 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd) ahc = *(struct ahc_softc **)cmd->device->host->hostdata; found = ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate reset*/TRUE); - ahc_linux_run_complete_queue(ahc); if (bootverbose) printf("%s: SCSI bus reset delivered. " @@ -1331,13 +1281,8 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) if (ahc->platform_data == NULL) return (ENOMEM); memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); - TAILQ_INIT(&ahc->platform_data->completeq); ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc_lockinit(ahc); - init_timer(&ahc->platform_data->completeq_timer); - ahc->platform_data->completeq_timer.data = (u_long)ahc; - ahc->platform_data->completeq_timer.function = - (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; @@ -1355,7 +1300,6 @@ ahc_platform_free(struct ahc_softc *ahc) int i, j; if (ahc->platform_data != NULL) { - del_timer_sync(&ahc->platform_data->completeq_timer); if (ahc->platform_data->host != NULL) { scsi_remove_host(ahc->platform_data->host); scsi_host_put(ahc->platform_data->host); @@ -1504,18 +1448,6 @@ ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, return 0; } -static void -ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc) -{ - u_long flags; - - ahc_lock(ahc, &flags); - del_timer(&ahc->platform_data->completeq_timer); - ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER; - ahc_linux_run_complete_queue(ahc); - ahc_unlock(ahc, &flags); -} - static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) { @@ -1785,7 +1717,6 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) ahc = (struct ahc_softc *) dev_id; ahc_lock(ahc, &flags); ours = ahc_intr(ahc); - ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); return IRQ_RETVAL(ours); } @@ -1794,8 +1725,6 @@ void ahc_platform_flushwork(struct ahc_softc *ahc) { - while (ahc_linux_run_complete_queue(ahc) != NULL) - ; } static struct ahc_linux_target* @@ -2275,22 +2204,6 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) { /* - * Typically, the complete queue has very few entries - * queued to it before the queue is emptied by - * ahc_linux_run_complete_queue, so sorting the entries - * by generation number should be inexpensive. - * We perform the sort so that commands that complete - * with an error are retuned in the order origionally - * queued to the controller so that any subsequent retries - * are performed in order. The underlying ahc routines do - * not guarantee the order that aborted commands will be - * returned to us. - */ - struct ahc_completeq *completeq; - struct ahc_cmd *list_cmd; - struct ahc_cmd *acmd; - - /* * Map CAM error codes into Linux Error codes. We * avoid the conversion so that the DV code has the * full error information available when making @@ -2343,26 +2256,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) new_status = DID_ERROR; break; case CAM_REQUEUE_REQ: - /* - * If we want the request requeued, make sure there - * are sufficent retries. In the old scsi error code, - * we used to be able to specify a result code that - * bypassed the retry count. Now we must use this - * hack. We also "fake" a check condition with - * a sense code of ABORTED COMMAND. This seems to - * evoke a retry even if this command is being sent - * via the eh thread. Ick! Ick! Ick! - */ - if (cmd->retries > 0) - cmd->retries--; - new_status = DID_OK; - ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND); - cmd->result |= (DRIVER_SENSE << 24); - memset(cmd->sense_buffer, 0, - sizeof(cmd->sense_buffer)); - cmd->sense_buffer[0] = SSD_ERRCODE_VALID - | SSD_CURRENT_ERROR; - cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND; + new_status = DID_REQUEUE; break; default: /* We should never get here */ @@ -2373,17 +2267,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) ahc_cmd_set_transaction_status(cmd, new_status); } - completeq = &ahc->platform_data->completeq; - list_cmd = TAILQ_FIRST(completeq); - acmd = (struct ahc_cmd *)cmd; - while (list_cmd != NULL - && acmd_scsi_cmd(list_cmd).serial_number - < acmd_scsi_cmd(acmd).serial_number) - list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); - if (list_cmd != NULL) - TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); - else - TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); + cmd->scsi_done(cmd); } static void @@ -2747,7 +2631,6 @@ done: } spin_lock_irq(&ahc->platform_data->spin_lock); } - ahc_linux_run_complete_queue(ahc); return (retval); } diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 9ce7639..e70c1fa 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -436,16 +436,11 @@ struct ahc_linux_target { /* * Per-SCB OSM storage. */ -typedef enum { - AHC_UP_EH_SEMAPHORE = 0x1 -} ahc_linux_scb_flags; - struct scb_platform_data { struct ahc_linux_device *dev; dma_addr_t buf_busaddr; uint32_t xfer_len; uint32_t sense_resid; /* Auto-Sense residual */ - ahc_linux_scb_flags flags; }; /* @@ -454,22 +449,14 @@ struct scb_platform_data { * alignment restrictions of the various platforms supported by * this driver. */ -typedef enum { - AHC_RUN_CMPLT_Q_TIMER = 0x10 -} ahc_linux_softc_flags; - -TAILQ_HEAD(ahc_completeq, ahc_cmd); - struct ahc_platform_data { /* * Fields accessed from interrupt context. */ struct ahc_linux_target *targets[AHC_NUM_TARGETS]; - struct ahc_completeq completeq; spinlock_t spin_lock; u_int qfrozen; - struct timer_list completeq_timer; struct timer_list reset_timer; struct semaphore eh_sem; struct Scsi_Host *host; /* pointer to scsi host */ @@ -477,7 +464,9 @@ struct ahc_platform_data { uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - ahc_linux_softc_flags flags; + +#define AHC_UP_EH_SEMAPHORE 0x1 + uint32_t flags; }; /************************** OS Utility Wrappers *******************************/ -- cgit v1.1 From c7525233d2df39b95552f6f49c6b390a9c4d2e80 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 17 May 2005 18:07:34 -0500 Subject: [SCSI] aic7xxx: make correct use of slave_alloc/destroy and remove the per device timer The allocation of all of our components should be done in slave alloc. Currently it's rather fancifully refcounted in the queuecommand callback. This patch moves allocation and destroy to their correct places in slave_alloc/slave_destory. Now we can guarantee that everywhere a device is requested, it's actually been allocated, so don't check for this anymore. Additionally, the per device busy timer was the only source of potential use after free. It's been deleted because Linux does the correct thing with busy returns, so there's no need to implement a separate timer in the driver. Finally, implement code that forces all the device parameters to zero (i.e. async and narrow) in the slave alloc, inform the spi class of the bios recorded maximums and wait until slave configure before trying anything more adventurous. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 183 ++++++++++++++++--------------------- drivers/scsi/aic7xxx/aic7xxx_osm.h | 8 -- 2 files changed, 79 insertions(+), 112 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index ca796b9..c03f294 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -430,7 +430,6 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, static void ahc_linux_sem_timeout(u_long arg); static void ahc_linux_freeze_simq(struct ahc_softc *ahc); static void ahc_linux_release_simq(u_long arg); -static void ahc_linux_dev_timed_unfreeze(u_long arg); static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, @@ -457,7 +456,7 @@ static int ahc_linux_next_unit(void); /********************************* Inlines ************************************/ static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, - u_int target, u_int lun, int alloc); + u_int target, u_int lun); static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, @@ -466,7 +465,7 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, - u_int lun, int alloc) + u_int lun) { struct ahc_linux_target *targ; struct ahc_linux_device *dev; @@ -476,18 +475,9 @@ ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, if (channel != 0) target_offset += 8; targ = ahc->platform_data->targets[target_offset]; - if (targ == NULL) { - if (alloc != 0) { - targ = ahc_linux_alloc_target(ahc, channel, target); - if (targ == NULL) - return (NULL); - } else - return (NULL); - } + BUG_ON(targ == NULL); dev = targ->devices[lun]; - if (dev == NULL && alloc != 0) - dev = ahc_linux_alloc_device(ahc, targ, lun); - return (dev); + return dev; } static __inline void @@ -640,7 +630,7 @@ ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, - cmd->device->lun, /*alloc*/TRUE); + cmd->device->lun); BUG_ON(dev == NULL); cmd->result = CAM_REQ_INPROG << 16; @@ -652,11 +642,69 @@ static int ahc_linux_slave_alloc(struct scsi_device *device) { struct ahc_softc *ahc; + struct ahc_linux_target *targ; + struct scsi_target *starget = device->sdev_target; + struct ahc_linux_device *dev; + u_int target_offset; + + target_offset = starget->id; + if (starget->channel != 0) + target_offset += 8; ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id); - return (0); + targ = ahc->platform_data->targets[target_offset]; + if (targ == NULL) { + targ = ahc_linux_alloc_target(ahc, starget->channel, starget->id); + struct seeprom_config *sc = ahc->seep_config; + if (targ == NULL) + return -ENOMEM; + if (sc) { + unsigned short scsirate; + struct ahc_devinfo devinfo; + struct ahc_initiator_tinfo *tinfo; + struct ahc_tmode_tstate *tstate; + char channel = starget->channel + 'A'; + unsigned int our_id = ahc->our_id; + + if (starget->channel) + our_id = ahc->our_id_b; + + if ((ahc->features & AHC_ULTRA2) != 0) { + scsirate = sc->device_flags[target_offset] & CFXFER; + } else { + scsirate = (sc->device_flags[target_offset] & CFXFER) << 4; + if (sc->device_flags[target_offset] & CFSYNCH) + scsirate |= SOFS; + } + if (sc->device_flags[target_offset] & CFWIDEB) { + scsirate |= WIDEXFER; + spi_max_width(starget) = 1; + } else + spi_max_width(starget) = 0; + spi_min_period(starget) = + ahc_find_period(ahc, scsirate, AHC_SYNCRATE_DT); + tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id, + targ->target, &tstate); + ahc_compile_devinfo(&devinfo, our_id, targ->target, + CAM_LUN_WILDCARD, channel, + ROLE_INITIATOR); + ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0, + AHC_TRANS_GOAL, /*paused*/FALSE); + ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, + AHC_TRANS_GOAL, /*paused*/FALSE); + } + + } + dev = targ->devices[device->lun]; + if (dev == NULL) { + dev = ahc_linux_alloc_device(ahc, targ, device->lun); + if (dev == NULL) + return -ENOMEM; + } + + return 0; } static int @@ -666,27 +714,20 @@ ahc_linux_slave_configure(struct scsi_device *device) struct ahc_linux_device *dev; ahc = *((struct ahc_softc **)device->host->hostdata); + if (bootverbose) printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id); - /* - * Since Linux has attached to the device, configure - * it so we don't free and allocate the device - * structure on every command. - */ - dev = ahc_linux_get_device(ahc, device->channel, - device->id, device->lun, - /*alloc*/TRUE); - if (dev != NULL) { - dev->flags &= ~AHC_DEV_UNCONFIGURED; - dev->scsi_device = device; - ahc_linux_device_queue_depth(ahc, dev); - } + + dev = ahc_linux_get_device(ahc, device->channel, device->id, + device->lun); + dev->scsi_device = device; + ahc_linux_device_queue_depth(ahc, dev); /* Initial Domain Validation */ if (!spi_initial_dv(device->sdev_target)) spi_dv_device(device); - return (0); + return 0; } static void @@ -699,22 +740,11 @@ ahc_linux_slave_destroy(struct scsi_device *device) if (bootverbose) printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id); dev = ahc_linux_get_device(ahc, device->channel, - device->id, device->lun, - /*alloc*/FALSE); - /* - * Filter out "silly" deletions of real devices by only - * deleting devices that have had slave_configure() - * called on them. All other devices that have not - * been configured will automatically be deleted by - * the refcounting process. - */ - if (dev != NULL - && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) { - dev->flags |= AHC_DEV_UNCONFIGURED; - if (dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) - ahc_linux_free_device(ahc, dev); - } + device->id, device->lun); + + BUG_ON(dev->active); + + ahc_linux_free_device(ahc, dev); } #if defined(__i386__) @@ -1361,7 +1391,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, dev = ahc_linux_get_device(ahc, devinfo->channel - 'A', devinfo->target, - devinfo->lun, /*alloc*/FALSE); + devinfo->lun); if (dev == NULL) return; was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED); @@ -1793,8 +1823,6 @@ ahc_linux_alloc_device(struct ahc_softc *ahc, if (dev == NULL) return (NULL); memset(dev, 0, sizeof(*dev)); - init_timer(&dev->timer); - dev->flags = AHC_DEV_UNCONFIGURED; dev->lun = lun; dev->target = targ; @@ -1817,7 +1845,7 @@ ahc_linux_alloc_device(struct ahc_softc *ahc, } static void -__ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) +ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) { struct ahc_linux_target *targ; @@ -1829,13 +1857,6 @@ __ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) ahc_linux_free_target(ahc, targ); } -static void -ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev) -{ - del_timer_sync(&dev->timer); - __ahc_linux_free_device(ahc, dev); -} - void ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun, ac_code code, void *arg) @@ -2008,8 +2029,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) } } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { ahc_linux_handle_scsi_status(ahc, dev, scb); - } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { - dev->flags |= AHC_DEV_UNCONFIGURED; } if (dev->openings == 1 @@ -2031,11 +2050,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) if (dev->active == 0) dev->commands_since_idle_or_otag = 0; - if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 - && dev->active == 0 - && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) - ahc_linux_free_device(ahc, dev); - if ((scb->flags & SCB_RECOVERY_SCB) != 0) { printf("Recovery SCB completes\n"); if (ahc_get_transaction_status(scb) == CAM_BDR_SENT @@ -2174,27 +2188,6 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, ahc_platform_set_tags(ahc, &devinfo, (dev->flags & AHC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); - /* FALLTHROUGH */ - } - case SCSI_STATUS_BUSY: - { - /* - * Set a short timer to defer sending commands for - * a bit since Linux will not delay in this case. - */ - if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) { - printf("%s:%c:%d: Device Timer still active during " - "busy processing\n", ahc_name(ahc), - dev->target->channel, dev->target->target); - break; - } - dev->flags |= AHC_DEV_TIMER_ACTIVE; - dev->qfrozen++; - init_timer(&dev->timer); - dev->timer.data = (u_long)dev; - dev->timer.expires = jiffies + (HZ/2); - dev->timer.function = ahc_linux_dev_timed_unfreeze; - add_timer(&dev->timer); break; } } @@ -2326,24 +2319,6 @@ ahc_linux_release_simq(u_long arg) scsi_unblock_requests(ahc->platform_data->host); } -static void -ahc_linux_dev_timed_unfreeze(u_long arg) -{ - struct ahc_linux_device *dev; - struct ahc_softc *ahc; - u_long s; - - dev = (struct ahc_linux_device *)arg; - ahc = dev->target->ahc; - ahc_lock(ahc, &s); - dev->flags &= ~AHC_DEV_TIMER_ACTIVE; - if (dev->qfrozen > 0) - dev->qfrozen--; - if (dev->active == 0) - __ahc_linux_free_device(ahc, dev); - ahc_unlock(ahc, &s); -} - static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) { @@ -2384,7 +2359,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) * command, return success. */ dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, - cmd->device->lun, /*alloc*/FALSE); + cmd->device->lun); if (dev == NULL) { /* diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index e70c1fa..30c200d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -322,13 +322,10 @@ struct ahc_cmd { */ TAILQ_HEAD(ahc_busyq, ahc_cmd); typedef enum { - AHC_DEV_UNCONFIGURED = 0x01, AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ - AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */ AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ - AHC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */ } ahc_linux_dev_flags; struct ahc_linux_target; @@ -374,11 +371,6 @@ struct ahc_linux_device { ahc_linux_dev_flags flags; /* - * Per device timer. - */ - struct timer_list timer; - - /* * The high limit for the tags variable. */ u_int maxtags; -- cgit v1.1 From fb3089dfb58bf07992252b42e77c6f35d45dff5e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 17 May 2005 21:09:52 -0500 Subject: [SCSI] aic7xxx: add back locking Tampering with the settings has to be done under the host lock ... slave_alloc isn't called under any lock, so this has to be done explicitly. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index c03f294..b216de4 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -645,7 +645,9 @@ ahc_linux_slave_alloc(struct scsi_device *device) struct ahc_linux_target *targ; struct scsi_target *starget = device->sdev_target; struct ahc_linux_device *dev; - u_int target_offset; + unsigned int target_offset; + unsigned long flags; + int retval = -ENOMEM; target_offset = starget->id; if (starget->channel != 0) @@ -654,12 +656,14 @@ ahc_linux_slave_alloc(struct scsi_device *device) ahc = *((struct ahc_softc **)device->host->hostdata); if (bootverbose) printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id); + ahc_lock(ahc, &flags); targ = ahc->platform_data->targets[target_offset]; if (targ == NULL) { targ = ahc_linux_alloc_target(ahc, starget->channel, starget->id); struct seeprom_config *sc = ahc->seep_config; if (targ == NULL) - return -ENOMEM; + goto out; + if (sc) { unsigned short scsirate; struct ahc_devinfo devinfo; @@ -701,10 +705,13 @@ ahc_linux_slave_alloc(struct scsi_device *device) if (dev == NULL) { dev = ahc_linux_alloc_device(ahc, targ, device->lun); if (dev == NULL) - return -ENOMEM; + goto out; } + retval = 0; - return 0; + out: + ahc_unlock(ahc, &flags); + return retval; } static int -- cgit v1.1 From 2bf2c568c878b9c0bbacac5c3210a6bd81856d21 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 19 May 2005 21:30:13 -0500 Subject: [SCSI] aic7xxx: fix U160 mode The new period/dt setting routines don't get the coupling of these parameters correct. This means that Domain Validation never gets DT set, and thus the drive gets restricted to U80. Fix this by restoring the couplings in the set routines. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index b216de4..f90efa2 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2679,6 +2679,11 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period) if (offset == 0) offset = MAX_OFFSET; + if (period < 9) + period = 9; /* 12.5ns is our minimum */ + if (period == 9) + ppr_options |= MSG_EXT_PPR_DT_REQ; + ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); @@ -2764,6 +2769,12 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) unsigned long flags; struct ahc_syncrate *syncrate; + if (dt) { + period = 9; /* 12.5ns is the only period valid for DT */ + ppr_options |= MSG_EXT_PPR_DT_REQ; + } else if (period == 9) + period = 10; /* if resetting DT, period must be >= 25ns */ + ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,AHC_SYNCRATE_DT); -- cgit v1.1 From 46f4e1b7d5fa3ddf2486bf69716c404147e38ebf Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Fri, 20 May 2005 13:59:06 -0700 Subject: [PATCH] packet driver permission checking fix If you tried to open a packet device first in read-only mode and then a second time in read-write mode, the second open succeeded even though the device was not correctly set up for writing. If you then tried to write data to the device, the writes would fail with I/O errors. This patch prevents that problem by making the second open fail with -EBUSY. Signed-off-by: Peter Osterlund Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index b9a6b7a..bc56770 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2021,7 +2021,13 @@ static int pkt_open(struct inode *inode, struct file *file) BUG_ON(pd->refcnt < 0); pd->refcnt++; - if (pd->refcnt == 1) { + if (pd->refcnt > 1) { + if ((file->f_mode & FMODE_WRITE) && + !test_bit(PACKET_WRITABLE, &pd->flags)) { + ret = -EBUSY; + goto out_dec; + } + } else { if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) { ret = -EIO; goto out_dec; -- cgit v1.1 From ba9950c820e556e39cd26581826b5581a64fb641 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:07 -0700 Subject: [PATCH] uml: small fixes left over from rc4 Some changes that I sent in didn't make 2.6.12-rc4 for some reason. This adds them back. We have an x86_64 definition of TOP_ADDR a reimplementation of the x86_64 csum_partial_copy_from_user some syntax fixes in arch/um/kernel/ptrace.c removal of a CFLAGS definition in the x86_64 Makefile some include changes in the x86_64 ptrace.c and user-offsets.h a syntax fix in elf-x86_64.h Also moved an include in the i386 and x86_64 Makefiles to make the symlinks work, and some small fixes from Al Viro. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig_x86_64 | 4 +++ arch/um/include/sysdep-i386/ptrace.h | 2 +- arch/um/include/sysdep-x86_64/checksum.h | 26 ++++++-------- arch/um/include/sysdep-x86_64/ptrace.h | 62 ++++++++++++++------------------ arch/um/kernel/ptrace.c | 6 ++-- arch/um/kernel/uml.lds.S | 2 ++ arch/um/sys-i386/Makefile | 4 +-- arch/um/sys-x86_64/Makefile | 6 ++-- arch/um/sys-x86_64/ksyms.c | 3 +- arch/um/sys-x86_64/ptrace.c | 9 ++--- arch/um/sys-x86_64/syscalls.c | 1 + arch/um/sys-x86_64/user-offsets.c | 8 +++++ include/asm-um/elf-i386.h | 2 +- include/asm-um/elf-x86_64.h | 24 ++++++++++++- 14 files changed, 89 insertions(+), 70 deletions(-) diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64 index fd8d7e8..f162f50 100644 --- a/arch/um/Kconfig_x86_64 +++ b/arch/um/Kconfig_x86_64 @@ -6,6 +6,10 @@ config 64BIT bool default y +config TOP_ADDR + hex + default 0x80000000 + config 3_LEVEL_PGTABLES bool default y diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h index 84ec7ff..6eaeb99 100644 --- a/arch/um/include/sysdep-i386/ptrace.h +++ b/arch/um/include/sysdep-i386/ptrace.h @@ -31,7 +31,6 @@ extern int sysemu_supported; #ifdef UML_CONFIG_MODE_SKAS #include "skas_ptregs.h" -#include "sysdep/faultinfo.h" #define REGS_IP(r) ((r)[HOST_IP]) #define REGS_SP(r) ((r)[HOST_SP]) @@ -59,6 +58,7 @@ extern int sysemu_supported; #define PTRACE_SYSEMU_SINGLESTEP 32 #endif +#include "sysdep/faultinfo.h" #include "choose-mode.h" union uml_pt_regs { diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h index 572c6c1..ea97005 100644 --- a/arch/um/include/sysdep-x86_64/checksum.h +++ b/arch/um/include/sysdep-x86_64/checksum.h @@ -9,8 +9,6 @@ #include "linux/in6.h" #include "asm/uaccess.h" -extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len, - int sum, int *err_ptr); extern unsigned csum_partial(const unsigned char *buff, unsigned len, unsigned sum); @@ -31,10 +29,15 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char * } static __inline__ -unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, - int len, int sum, int *err_ptr) +unsigned int csum_partial_copy_from_user(const unsigned char *src, + unsigned char *dst, int len, int sum, + int *err_ptr) { - return csum_partial_copy_from(src, dst, len, sum, err_ptr); + if(copy_from_user(dst, src, len)){ + *err_ptr = -EFAULT; + return(-1); + } + return csum_partial(dst, len, sum); } /** @@ -137,15 +140,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b) return a; } -#endif +extern unsigned short ip_compute_csum(unsigned char * buff, int len); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +#endif diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h index 348e8fc..be8acd5 100644 --- a/arch/um/include/sysdep-x86_64/ptrace.h +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -135,6 +135,7 @@ extern int mode_tt; __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) #define UPT_SC(r) ((r)->tt.sc) #define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) +#define UPT_SYSCALL_RET(r) UPT_RAX(r) extern int user_context(unsigned long sp); @@ -196,32 +197,32 @@ struct syscall_args { #define UPT_SET(regs, reg, val) \ - ({ unsigned long val; \ + ({ unsigned long __upt_val = val; \ switch(reg){ \ - case R8: UPT_R8(regs) = val; break; \ - case R9: UPT_R9(regs) = val; break; \ - case R10: UPT_R10(regs) = val; break; \ - case R11: UPT_R11(regs) = val; break; \ - case R12: UPT_R12(regs) = val; break; \ - case R13: UPT_R13(regs) = val; break; \ - case R14: UPT_R14(regs) = val; break; \ - case R15: UPT_R15(regs) = val; break; \ - case RIP: UPT_IP(regs) = val; break; \ - case RSP: UPT_SP(regs) = val; break; \ - case RAX: UPT_RAX(regs) = val; break; \ - case RBX: UPT_RBX(regs) = val; break; \ - case RCX: UPT_RCX(regs) = val; break; \ - case RDX: UPT_RDX(regs) = val; break; \ - case RSI: UPT_RSI(regs) = val; break; \ - case RDI: UPT_RDI(regs) = val; break; \ - case RBP: UPT_RBP(regs) = val; break; \ - case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \ - case CS: UPT_CS(regs) = val; break; \ - case DS: UPT_DS(regs) = val; break; \ - case ES: UPT_ES(regs) = val; break; \ - case FS: UPT_FS(regs) = val; break; \ - case GS: UPT_GS(regs) = val; break; \ - case EFLAGS: UPT_EFLAGS(regs) = val; break; \ + case R8: UPT_R8(regs) = __upt_val; break; \ + case R9: UPT_R9(regs) = __upt_val; break; \ + case R10: UPT_R10(regs) = __upt_val; break; \ + case R11: UPT_R11(regs) = __upt_val; break; \ + case R12: UPT_R12(regs) = __upt_val; break; \ + case R13: UPT_R13(regs) = __upt_val; break; \ + case R14: UPT_R14(regs) = __upt_val; break; \ + case R15: UPT_R15(regs) = __upt_val; break; \ + case RIP: UPT_IP(regs) = __upt_val; break; \ + case RSP: UPT_SP(regs) = __upt_val; break; \ + case RAX: UPT_RAX(regs) = __upt_val; break; \ + case RBX: UPT_RBX(regs) = __upt_val; break; \ + case RCX: UPT_RCX(regs) = __upt_val; break; \ + case RDX: UPT_RDX(regs) = __upt_val; break; \ + case RSI: UPT_RSI(regs) = __upt_val; break; \ + case RDI: UPT_RDI(regs) = __upt_val; break; \ + case RBP: UPT_RBP(regs) = __upt_val; break; \ + case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ + case CS: UPT_CS(regs) = __upt_val; break; \ + case DS: UPT_DS(regs) = __upt_val; break; \ + case ES: UPT_ES(regs) = __upt_val; break; \ + case FS: UPT_FS(regs) = __upt_val; break; \ + case GS: UPT_GS(regs) = __upt_val; break; \ + case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ default : \ panic("Bad register in UPT_SET : %d\n", reg); \ break; \ @@ -245,14 +246,3 @@ struct syscall_args { CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 2b75d8d..2925e15 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on) child->thread.singlestep_syscall = 0; #ifdef SUBARCH_SET_SINGLESTEPPING - SUBARCH_SET_SINGLESTEPPING(child, on) + SUBARCH_SET_SINGLESTEPPING(child, on); #endif - } +} /* * Called by kernel/ptrace.c when detaching.. @@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data) } #ifdef SUBACH_PTRACE_SPECIAL - SUBARCH_PTRACE_SPECIAL(child,request,addr,data) + SUBARCH_PTRACE_SPECIAL(child,request,addr,data); #endif ret = ptrace_check_attach(child, request == PTRACE_KILL); diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 76eadb3..dd53555 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -73,6 +73,8 @@ SECTIONS .got : { *(.got.plt) *(.got) } .dynamic : { *(.dynamic) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } /* We want the small data sections together, so single-instruction offsets can access them all, and initialized data all before uninitialized, so we can shorten the on-disk segment size. */ diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index fcd67c3..4351e56 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -9,11 +9,11 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o SYMLINKS = bitops.c semaphore.c highmem.c module.c +include arch/um/scripts/Makefile.rules + bitops.c-dir = lib semaphore.c-dir = kernel highmem.c-dir = mm module.c-dir = kernel subdir- := util - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index 3d7da91..608466a 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -14,11 +14,11 @@ obj-$(CONFIG_MODULES) += module.o um_module.o USER_OBJS := ptrace_user.o sigcontext.o -include arch/um/scripts/Makefile.rules - SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ semaphore.c thunk.S module.c +include arch/um/scripts/Makefile.rules + bitops.c-dir = lib csum-copy.S-dir = lib csum-partial.c-dir = lib @@ -28,6 +28,4 @@ semaphore.c-dir = kernel thunk.S-dir = lib module.c-dir = kernel -CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial - subdir- := util diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c index a27f0ee..8592738 100644 --- a/arch/um/sys-x86_64/ksyms.c +++ b/arch/um/sys-x86_64/ksyms.c @@ -16,5 +16,4 @@ EXPORT_SYMBOL(__up_wakeup); EXPORT_SYMBOL(__memcpy); /* Networking helper routines. */ -/*EXPORT_SYMBOL(csum_partial_copy_from); -EXPORT_SYMBOL(csum_partial_copy_to);*/ +EXPORT_SYMBOL(ip_compute_csum); diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index b593bb2..74eee5c 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c @@ -5,10 +5,11 @@ */ #define __FRAME_OFFSETS -#include "asm/ptrace.h" -#include "linux/sched.h" -#include "linux/errno.h" -#include "asm/elf.h" +#include +#include +#include +#include +#include /* XXX x86_64 */ unsigned long not_ss; diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index dd99146..d4a5965 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -15,6 +15,7 @@ #include "asm/unistd.h" #include "asm/prctl.h" /* XXX This should get the constants from libc */ #include "choose-mode.h" +#include "kern.h" asmlinkage long sys_uname64(struct new_utsname __user * name) { diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 5e14792..513d17c 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c @@ -3,6 +3,14 @@ #include #define __FRAME_OFFSETS #include +#include +/* For some reason, x86_64 defines u64 and u32 only in , which I + * refuse to include here, even though they're used throughout the headers. + * These are used in asm/user.h, and that include can't be avoided because of + * the sizeof(struct user_regs_struct) below. + */ +typedef __u64 u64; +typedef __u32 u32; #include #define DEFINE(sym, val) \ diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h index b72e235..9bab712 100644 --- a/include/asm-um/elf-i386.h +++ b/include/asm-um/elf-i386.h @@ -5,7 +5,7 @@ #ifndef __UM_ELF_I386_H #define __UM_ELF_I386_H -#include "user.h" +#include #define R_386_NONE 0 #define R_386_32 1 diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h index 19309d0..8a8246d 100644 --- a/include/asm-um/elf-x86_64.h +++ b/include/asm-um/elf-x86_64.h @@ -8,6 +8,27 @@ #include +/* x86-64 relocation types, taken from asm-x86_64/elf.h */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ + +#define R_X86_64_NUM 16 + typedef unsigned long elf_greg_t; #define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) @@ -44,7 +65,8 @@ typedef struct { } elf_fpregset_t; } while (0) #ifdef TIF_IA32 /* XXX */ - clear_thread_flag(TIF_IA32); \ +#error XXX, indeed + clear_thread_flag(TIF_IA32); #endif #define USE_ELF_CORE_DUMP -- cgit v1.1 From 13479d52c7a61a18900d7f36730b7d3b43723d97 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:08 -0700 Subject: [PATCH] uml: Page fault fixes Any access to a PROT_NONE page should segfault the process. A JVM seems to do this on purpose. Also, Al noticed some bogus code, which is now deleted. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/trap_kern.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 5fca2c6..9ae2eff 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -57,10 +57,11 @@ int handle_page_fault(unsigned long address, unsigned long ip, *code_out = SEGV_ACCERR; if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; + + if(!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto out; + page = address & PAGE_MASK; - pgd = pgd_offset(mm, page); - pud = pud_offset(pgd, page); - pmd = pmd_offset(pud, page); do { survive: switch (handle_mm_fault(mm, vma, address, is_write)){ -- cgit v1.1 From 060e352236ece3325a684c72817fbacdac597574 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:08 -0700 Subject: [PATCH] uml: Delay loop cleanups This patch cleans up the delay implementations a bit, makes the loops unoptimizable, and exports __udelay and __const_udelay. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/sys-i386/delay.c | 16 ++++++++++++---- arch/um/sys-x86_64/delay.c | 33 +++++++++++++++------------------ 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c index e9892ee..2c11b97 100644 --- a/arch/um/sys-i386/delay.c +++ b/arch/um/sys-i386/delay.c @@ -1,5 +1,7 @@ -#include "linux/delay.h" -#include "asm/param.h" +#include +#include +#include +#include void __delay(unsigned long time) { @@ -20,13 +22,19 @@ void __udelay(unsigned long usecs) int i, n; n = (loops_per_jiffy * HZ * usecs) / MILLION; - for(i=0;i +#include +#include +#include void __delay(unsigned long loops) { unsigned long i; - for(i = 0; i < loops; i++) ; + for(i = 0; i < loops; i++) + cpu_relax(); } void __udelay(unsigned long usecs) { - int i, n; + unsigned long i, n; n = (loops_per_jiffy * HZ * usecs) / MILLION; - for(i=0;i Date: Fri, 20 May 2005 13:59:09 -0700 Subject: [PATCH] uml: multicast driver cleanup Byte-swapping of the port and IP address passed in to the multicast driver by the user used to happen in different places, which was a bug in itself. The port also was swapped before being printk-ed, which led to a misleading message. This patch moves the port swapping to the same place as the IP address swapping. It also cleans up the error paths of mcast_open. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mcast_kern.c | 4 +--- arch/um/drivers/mcast_user.c | 47 ++++++++++++++------------------------------ 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index faf714e..217438c 100644 --- a/arch/um/drivers/mcast_kern.c +++ b/arch/um/drivers/mcast_kern.c @@ -73,7 +73,6 @@ int mcast_setup(char *str, char **mac_out, void *data) struct mcast_init *init = data; char *port_str = NULL, *ttl_str = NULL, *remain; char *last; - int n; *init = ((struct mcast_init) { .addr = "239.192.168.1", @@ -89,13 +88,12 @@ int mcast_setup(char *str, char **mac_out, void *data) } if(port_str != NULL){ - n = simple_strtoul(port_str, &last, 10); + init->port = simple_strtoul(port_str, &last, 10); if((*last != '\0') || (last == port_str)){ printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", port_str); return(0); } - init->port = htons(n); } if(ttl_str != NULL){ diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 0fe1d9f..7a0d115 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port) } sin->sin_family = AF_INET; sin->sin_addr.s_addr = in_aton(addr); - sin->sin_port = port; + sin->sin_port = htons(port); return(sin); } @@ -55,28 +55,25 @@ static int mcast_open(void *data) struct mcast_data *pri = data; struct sockaddr_in *sin = pri->mcast_addr; struct ip_mreq mreq; - int fd, yes = 1; + int fd = -EINVAL, yes = 1, err = -EINVAL;; - if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) { - fd = -EINVAL; + if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) goto out; - } fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0){ printk("mcast_open : data socket failed, errno = %d\n", errno); - fd = -ENOMEM; + fd = -errno; goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); - os_close_file(fd); - fd = -EINVAL; - goto out; + goto out_close; } /* set ttl according to config */ @@ -84,26 +81,20 @@ static int mcast_open(void *data) sizeof(pri->ttl)) < 0) { printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); - os_close_file(fd); - fd = -EINVAL; - goto out; + goto out_close; } /* set LOOP, so data does get fed back to local sockets */ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); - os_close_file(fd); - fd = -EINVAL; - goto out; + goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { printk("mcast_open : data bind failed, errno = %d\n", errno); - os_close_file(fd); - fd = -EINVAL; - goto out; + goto out_close; } /* subscribe to the multicast group */ @@ -117,12 +108,15 @@ static int mcast_open(void *data) "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); - os_close_file(fd); - fd = -EINVAL; + goto out_close; } out: - return(fd); + return fd; + + out_close: + os_close_file(fd); + return err; } static void mcast_close(int fd, void *data) @@ -164,14 +158,3 @@ struct net_user_info mcast_user_info = { .delete_address = NULL, .max_packet = MAX_PACKET - ETH_HEADER_OTHER }; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v1.1 From 41a9cf8ebe08ccdd5799c175f9758f14617c0b0a Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:10 -0700 Subject: [PATCH] uml: Export clear_user_* From: Oleg Drokin: This patch is needed to support kernel modules that want to use clear_user() (that is exported symbol on all other architectures). Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/ksyms.c | 1 + arch/um/kernel/tt/ksyms.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 78d69dc..99439fa 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -57,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt); EXPORT_SYMBOL(strncpy_from_user_skas); EXPORT_SYMBOL(copy_to_user_skas); EXPORT_SYMBOL(copy_from_user_skas); +EXPORT_SYMBOL(clear_user_skas); #endif EXPORT_SYMBOL(uml_strdup); diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c index 92ec85d..84a9385 100644 --- a/arch/um/kernel/tt/ksyms.c +++ b/arch/um/kernel/tt/ksyms.c @@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user); EXPORT_SYMBOL(__do_strncpy_from_user); EXPORT_SYMBOL(__do_strnlen_user); EXPORT_SYMBOL(__do_clear_user); +EXPORT_SYMBOL(clear_user_tt); EXPORT_SYMBOL(tracing_pid); EXPORT_SYMBOL(honeypot); -- cgit v1.1 From 9b67a3c4cd380968bffe8efb681470acda42b441 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:10 -0700 Subject: [PATCH] uml: initrd cleanup The serial UML OS-abstraction layer patch (um/kernel dir). This moves all systemcalls from initrd_user.c file under os-Linux dir and join initrd_user.c and initrd_kern.c files in new file initrd.c Signed-off-by: Gennady Sharapov Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/Makefile | 2 +- arch/um/kernel/initrd.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 arch/um/kernel/initrd.c diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 9736ca2..a8918e80 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \ tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \ user_util.o -obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o +obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o obj-$(CONFIG_TTY_LOG) += tty_log.o diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c new file mode 100644 index 0000000..82ecf90 --- /dev/null +++ b/arch/um/kernel/initrd.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/init.h" +#include "linux/bootmem.h" +#include "linux/initrd.h" +#include "asm/types.h" +#include "user_util.h" +#include "kern_util.h" +#include "initrd.h" +#include "init.h" +#include "os.h" + +/* Changed by uml_initrd_setup, which is a setup */ +static char *initrd __initdata = NULL; + +static int __init read_initrd(void) +{ + void *area; + long long size; + int err; + + if(initrd == NULL) return 0; + err = os_file_size(initrd, &size); + if(err) return 0; + area = alloc_bootmem(size); + if(area == NULL) return 0; + if(load_initrd(initrd, area, size) == -1) return 0; + initrd_start = (unsigned long) area; + initrd_end = initrd_start + size; + return 0; +} + +__uml_postsetup(read_initrd); + +static int __init uml_initrd_setup(char *line, int *add) +{ + initrd = line; + return 0; +} + +__uml_setup("initrd=", uml_initrd_setup, +"initrd=\n" +" This is used to boot UML from an initrd image. The argument is the\n" +" name of the file containing the image.\n\n" +); + +int load_initrd(char *filename, void *buf, int size) +{ + int fd, n; + + fd = os_open_file(filename, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Opening '%s' failed - err = %d\n", filename, -fd); + return(-1); + } + n = os_read_file(fd, buf, size); + if(n != size){ + printk("Read of %d bytes from '%s' failed, err = %d\n", size, + filename, -n); + return(-1); + } + + os_close_file(fd); + return(0); +} +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ -- cgit v1.1 From 7b9014c1da380384efe7752db38a0253a74d0238 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:11 -0700 Subject: [PATCH] uml: Remove ubd-mmap support Finally rip out the ubd-mmap code, which turned out to be broken by design. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 296 +-------------------------------------------- arch/um/kernel/trap_kern.c | 29 ----- 2 files changed, 3 insertions(+), 322 deletions(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 9a56ff9..88f956c 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -55,7 +55,7 @@ #include "mem_kern.h" #include "cow.h" -enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; +enum ubd_req { UBD_READ, UBD_WRITE }; struct io_thread_req { enum ubd_req op; @@ -68,8 +68,6 @@ struct io_thread_req { unsigned long sector_mask; unsigned long long cow_offset; unsigned long bitmap_words[2]; - int map_fd; - unsigned long long map_offset; int error; }; @@ -122,10 +120,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file, #define MAX_DEV (8) -/* Changed in early boot */ -static int ubd_do_mmap = 0; -#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE - static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, .open = ubd_open, @@ -175,12 +169,6 @@ struct ubd { int no_cow; struct cow cow; struct platform_device pdev; - - int map_writes; - int map_reads; - int nomap_writes; - int nomap_reads; - int write_maps; }; #define DEFAULT_COW { \ @@ -200,11 +188,6 @@ struct ubd { .openflags = OPEN_FLAGS, \ .no_cow = 0, \ .cow = DEFAULT_COW, \ - .map_writes = 0, \ - .map_reads = 0, \ - .nomap_writes = 0, \ - .nomap_reads = 0, \ - .write_maps = 0, \ } struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; @@ -314,13 +297,6 @@ static int ubd_setup_common(char *str, int *index_out) int major; str++; - if(!strcmp(str, "mmap")){ - CHOOSE_MODE(printk("mmap not supported by the ubd " - "driver in tt mode\n"), - ubd_do_mmap = 1); - return(0); - } - if(!strcmp(str, "sync")){ global_openflags = of_sync(global_openflags); return(0); @@ -524,7 +500,7 @@ static void ubd_handler(void) { struct io_thread_req req; struct request *rq = elv_next_request(ubd_queue); - int n, err; + int n; do_ubd = NULL; intr_count++; @@ -538,19 +514,6 @@ static void ubd_handler(void) return; } - if((req.op != UBD_MMAP) && - ((req.offset != ((__u64) (rq->sector)) << 9) || - (req.length != (rq->current_nr_sectors) << 9))) - panic("I/O op mismatch"); - - if(req.map_fd != -1){ - err = physmem_subst_mapping(req.buffer, req.map_fd, - req.map_offset, 1); - if(err) - printk("ubd_handler - physmem_subst_mapping failed, " - "err = %d\n", -err); - } - ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); do_ubd_request(ubd_queue); @@ -583,14 +546,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out) static void ubd_close(struct ubd *dev) { - if(ubd_do_mmap) - physmem_forget_descriptor(dev->fd); os_close_file(dev->fd); if(dev->cow.file == NULL) return; - if(ubd_do_mmap) - physmem_forget_descriptor(dev->cow.fd); os_close_file(dev->cow.fd); vfree(dev->cow.bitmap); dev->cow.bitmap = NULL; @@ -1010,94 +969,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, req->bitmap_words, bitmap_len); } -static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset) -{ - __u64 sector; - unsigned char *bitmap; - int bit, i; - - /* mmap must have been requested on the command line */ - if(!ubd_do_mmap) - return(-1); - - /* The buffer must be page aligned */ - if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0) - return(-1); - - /* The request must be a page long */ - if((req->current_nr_sectors << 9) != PAGE_SIZE) - return(-1); - - if(dev->cow.file == NULL) - return(dev->fd); - - sector = offset >> 9; - bitmap = (unsigned char *) dev->cow.bitmap; - bit = ubd_test_bit(sector, bitmap); - - for(i = 1; i < req->current_nr_sectors; i++){ - if(ubd_test_bit(sector + i, bitmap) != bit) - return(-1); - } - - if(bit || (rq_data_dir(req) == WRITE)) - offset += dev->cow.data_offset; - - /* The data on disk must be page aligned */ - if((offset % UBD_MMAP_BLOCK_SIZE) != 0) - return(-1); - - return(bit ? dev->fd : dev->cow.fd); -} - -static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset, - struct request *req, - struct io_thread_req *io_req) -{ - int err; - - if(rq_data_dir(req) == WRITE){ - /* Writes are almost no-ops since the new data is already in the - * host page cache - */ - dev->map_writes++; - if(dev->cow.file != NULL) - cowify_bitmap(io_req->offset, io_req->length, - &io_req->sector_mask, &io_req->cow_offset, - dev->cow.bitmap, dev->cow.bitmap_offset, - io_req->bitmap_words, - dev->cow.bitmap_len); - } - else { - int w; - - if((dev->cow.file != NULL) && (fd == dev->cow.fd)) - w = 0; - else w = dev->openflags.w; - - if((dev->cow.file != NULL) && (fd == dev->fd)) - offset += dev->cow.data_offset; - - err = physmem_subst_mapping(req->buffer, fd, offset, w); - if(err){ - printk("physmem_subst_mapping failed, err = %d\n", - -err); - return(1); - } - dev->map_reads++; - } - io_req->op = UBD_MMAP; - io_req->buffer = req->buffer; - return(0); -} - /* Called with ubd_io_lock held */ static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; struct ubd *dev = disk->private_data; __u64 offset; - int len, fd; + int len; if(req->rq_status == RQ_INACTIVE) return(1); @@ -1114,34 +992,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; io_req->fds[1] = dev->fd; - io_req->map_fd = -1; io_req->cow_offset = -1; io_req->offset = offset; io_req->length = len; io_req->error = 0; io_req->sector_mask = 0; - fd = mmap_fd(req, dev, io_req->offset); - if(fd > 0){ - /* If mmapping is otherwise OK, but the first access to the - * page is a write, then it's not mapped in yet. So we have - * to write the data to disk first, then we can map the disk - * page in and continue normally from there. - */ - if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){ - io_req->map_fd = dev->fd; - io_req->map_offset = io_req->offset + - dev->cow.data_offset; - dev->write_maps++; - } - else return(prepare_mmap_request(dev, fd, io_req->offset, req, - io_req)); - } - - if(rq_data_dir(req) == READ) - dev->nomap_reads++; - else dev->nomap_writes++; - io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; io_req->offsets[1] = dev->cow.data_offset; @@ -1229,143 +1085,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file, return(-EINVAL); } -static int ubd_check_remapped(int fd, unsigned long address, int is_write, - __u64 offset) -{ - __u64 bitmap_offset; - unsigned long new_bitmap[2]; - int i, err, n; - - /* If it's not a write access, we can't do anything about it */ - if(!is_write) - return(0); - - /* We have a write */ - for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){ - struct ubd *dev = &ubd_dev[i]; - - if((dev->fd != fd) && (dev->cow.fd != fd)) - continue; - - /* It's a write to a ubd device */ - - /* This should be impossible now */ - if(!dev->openflags.w){ - /* It's a write access on a read-only device - probably - * shouldn't happen. If the kernel is trying to change - * something with no intention of writing it back out, - * then this message will clue us in that this needs - * fixing - */ - printk("Write access to mapped page from readonly ubd " - "device %d\n", i); - return(0); - } - - /* It's a write to a writeable ubd device - it must be COWed - * because, otherwise, the page would have been mapped in - * writeable - */ - - if(!dev->cow.file) - panic("Write fault on writeable non-COW ubd device %d", - i); - - /* It should also be an access to the backing file since the - * COW pages should be mapped in read-write - */ - - if(fd == dev->fd) - panic("Write fault on a backing page of ubd " - "device %d\n", i); - - /* So, we do the write, copying the backing data to the COW - * file... - */ - - err = os_seek_file(dev->fd, offset + dev->cow.data_offset); - if(err < 0) - panic("Couldn't seek to %lld in COW file of ubd " - "device %d, err = %d", - offset + dev->cow.data_offset, i, -err); - - n = os_write_file(dev->fd, (void *) address, PAGE_SIZE); - if(n != PAGE_SIZE) - panic("Couldn't copy data to COW file of ubd " - "device %d, err = %d", i, -n); - - /* ... updating the COW bitmap... */ - - cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset, - dev->cow.bitmap, dev->cow.bitmap_offset, - new_bitmap, dev->cow.bitmap_len); - - err = os_seek_file(dev->fd, bitmap_offset); - if(err < 0) - panic("Couldn't seek to %lld in COW file of ubd " - "device %d, err = %d", bitmap_offset, i, -err); - - n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap)); - if(n != sizeof(new_bitmap)) - panic("Couldn't update bitmap of ubd device %d, " - "err = %d", i, -n); - - /* Maybe we can map the COW page in, and maybe we can't. If - * it is a pre-V3 COW file, we can't, since the alignment will - * be wrong. If it is a V3 or later COW file which has been - * moved to a system with a larger page size, then maybe we - * can't, depending on the exact location of the page. - */ - - offset += dev->cow.data_offset; - - /* Remove the remapping, putting the original anonymous page - * back. If the COW file can be mapped in, that is done. - * Otherwise, the COW page is read in. - */ - - if(!physmem_remove_mapping((void *) address)) - panic("Address 0x%lx not remapped by ubd device %d", - address, i); - if((offset % UBD_MMAP_BLOCK_SIZE) == 0) - physmem_subst_mapping((void *) address, dev->fd, - offset, 1); - else { - err = os_seek_file(dev->fd, offset); - if(err < 0) - panic("Couldn't seek to %lld in COW file of " - "ubd device %d, err = %d", offset, i, - -err); - - n = os_read_file(dev->fd, (void *) address, PAGE_SIZE); - if(n != PAGE_SIZE) - panic("Failed to read page from offset %llx of " - "COW file of ubd device %d, err = %d", - offset, i, -n); - } - - return(1); - } - - /* It's not a write on a ubd device */ - return(0); -} - -static struct remapper ubd_remapper = { - .list = LIST_HEAD_INIT(ubd_remapper.list), - .proc = ubd_check_remapped, -}; - -static int ubd_remapper_setup(void) -{ - if(ubd_do_mmap) - register_remapper(&ubd_remapper); - - return(0); -} - -__initcall(ubd_remapper_setup); - static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) { struct uml_stat buf1, buf2; @@ -1568,15 +1287,6 @@ void do_io(struct io_thread_req *req) int err; __u64 off; - if(req->op == UBD_MMAP){ - /* Touch the page to force the host to do any necessary IO to - * get it into memory - */ - n = *((volatile int *) req->buffer); - req->error = update_bitmap(req); - return; - } - nsectors = req->length / req->sectorsize; start = 0; do { diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 9ae2eff..1de22d8 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -107,33 +107,6 @@ out_of_memory: goto out; } -LIST_HEAD(physmem_remappers); - -void register_remapper(struct remapper *info) -{ - list_add(&info->list, &physmem_remappers); -} - -static int check_remapped_addr(unsigned long address, int is_write) -{ - struct remapper *remapper; - struct list_head *ele; - __u64 offset; - int fd; - - fd = phys_mapping(__pa(address), &offset); - if(fd == -1) - return(0); - - list_for_each(ele, &physmem_remappers){ - remapper = list_entry(ele, struct remapper, list); - if((*remapper->proc)(fd, address, is_write, offset)) - return(1); - } - - return(0); -} - /* * We give a *copy* of the faultinfo in the regs to segv. * This must be done, since nesting SEGVs could overwrite @@ -152,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) flush_tlb_kernel_vm(); return(0); } - else if(check_remapped_addr(address & PAGE_MASK, is_write)) - return(0); else if(current->mm == NULL) panic("Segfault with no mm"); err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); -- cgit v1.1 From 12f49643bc44c428919b210148a930496827dd26 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:12 -0700 Subject: [PATCH] uml: fixrange_init 3-level page table support From: Al Viro - add three-level page table support to fixrange_init. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/mem.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index f156661..c22825f 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -100,12 +100,37 @@ void mem_init(void) #endif } +/* + * Create a page table and place a pointer to it in a middle page + * directory entry. + */ +static void __init one_page_table_init(pmd_t *pmd) +{ + if (pmd_none(*pmd)) { + pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + set_pmd(pmd, __pmd(_KERNPG_TABLE + + (unsigned long) __pa(pte))); + if (pte != pte_offset_kernel(pmd, 0)) + BUG(); + } +} + +static void __init one_md_table_init(pud_t *pud) +{ +#ifdef CONFIG_3_LEVEL_PGTABLES + pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); + set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table))); + if (pmd_table != pmd_offset(pud, 0)) + BUG(); +#endif +} + static void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; - pte_t *pte; int i, j; unsigned long vaddr; @@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end, pgd = pgd_base + i; for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { - pmd = (pmd_t *)pgd; + pud = pud_offset(pgd, vaddr); + if (pud_none(*pud)) + one_md_table_init(pud); + pmd = pmd_offset(pud, vaddr); for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { - if (pmd_none(*pmd)) { - pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - set_pmd(pmd, __pmd(_KERNPG_TABLE + - (unsigned long) __pa(pte))); - if (pte != pte_offset_kernel(pmd, 0)) - BUG(); - } + one_page_table_init(pmd); vaddr += PMD_SIZE; } j = 0; -- cgit v1.1 From 84ddaa8c86fc12ee1c3509be5ff3464821535c17 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 20 May 2005 13:59:12 -0700 Subject: [PATCH] uml: Change printf to printk in console driver From: Al Viro - we have error messages with KERN_ERR in them, so they should be printk-ed rather than printf-ed. Signed-off-by: Jeff Dike Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_kern.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 0150038..14a12d6 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -20,9 +20,17 @@ #include "os.h" #ifdef CONFIG_NOCONFIG_CHAN + +/* The printk's here are wrong because we are complaining that there is no + * output device, but printk is printing to that output device. The user will + * never see the error. printf would be better, except it can't run on a + * kernel stack because it will overflow it. + * Use printk for now since that will avoid crashing. + */ + static void *not_configged_init(char *str, int device, struct chan_opts *opts) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return(NULL); } @@ -30,27 +38,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts) static int not_configged_open(int input, int output, int primary, void *data, char **dev_out) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return(-ENODEV); } static void not_configged_close(int fd, void *data) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); } static int not_configged_read(int fd, char *c_out, void *data) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return(-EIO); } static int not_configged_write(int fd, const char *buf, int len, void *data) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return(-EIO); } @@ -58,7 +66,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data) static int not_configged_console_write(int fd, const char *buf, int len, void *data) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return(-EIO); } @@ -66,7 +74,7 @@ static int not_configged_console_write(int fd, const char *buf, int len, static int not_configged_window_size(int fd, void *data, unsigned short *rows, unsigned short *cols) { - printf(KERN_ERR "Using a channel type which is configured out of " + printk(KERN_ERR "Using a channel type which is configured out of " "UML\n"); return(-ENODEV); } -- cgit v1.1 From 7f8cd80fb261177244c1479cfcad1387dbf3cd4b Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 20 May 2005 13:59:13 -0700 Subject: [PATCH] ppc32: Fix platform device initialization of 8250 serial ports Initialization of 8250 serial ports that are platform devices require that at empty entry exists in the array of plat_serial8250_port. With out an empty entry we can get some pretty random behavior. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/mpc83xx_devices.c | 1 + arch/ppc/syslib/mpc85xx_devices.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 5c1a919e..75c8e98 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = { .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, }, + { }, }; struct platform_device ppc_sys_platform_devices[] = { diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index a231795..1e658ef 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c @@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = { .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, }, + { }, }; struct platform_device ppc_sys_platform_devices[] = { -- cgit v1.1 From b2665f92ae67a2d086537979d317a6f3a5697c63 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 20 May 2005 13:59:14 -0700 Subject: [PATCH] ppc32: fix CONFIG_TASK_SIZE handling on 44x This patch fixed CONFIG_TASK_SIZE handling on 44x. Currently head_44x.S hardcodes 0x80000000, which breaks if user chooses to change TASK_SIZE (e.g. for 3G user-space). Tested on Ocotea in 3G/1G configuration. Signed-off-by: Eugene Surovegin Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/head_44x.S | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 9b6a8e5..6c7ae60 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -330,8 +330,9 @@ interrupt_base: /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - andis. r11, r10, 0x8000 - beq 3f + lis r11, TASK_SIZE@h + cmplw r10, r11 + blt+ 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l @@ -464,8 +465,9 @@ interrupt_base: /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - andis. r11, r10, 0x8000 - beq 3f + lis r11, TASK_SIZE@h + cmplw r10, r11 + blt+ 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l @@ -533,8 +535,9 @@ interrupt_base: /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - andis. r11, r10, 0x8000 - beq 3f + lis r11, TASK_SIZE@h + cmplw r10, r11 + blt+ 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l -- cgit v1.1 From b39c4fab259b216148e705344a892c96efe1946d Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Fri, 20 May 2005 13:59:15 -0700 Subject: [PATCH] cpusets+hotplug+preepmt broken This patch removes the entwining of cpusets and hotplug code in the "No more Mr. Nice Guy" case of sched.c move_task_off_dead_cpu(). Since the hotplug code is holding a spinlock at this point, we cannot take the cpuset semaphore, cpuset_sem, as would seem to be required either to update the tasks cpuset, or to scan up the nested cpuset chain, looking for the nearest cpuset ancestor that still has some CPUs that are online. So we just punt and blast the tasks cpus_allowed with all bits allowed. This reverts these lines of code to what they were before the cpuset patch. And it updates the cpuset Doc file, to match. The one known alternative to this that seems to work came from Dinakar Guniguntala, and required the hotplug code to take the cpuset_sem semaphore much earlier in its processing. So far as we know, the increased locking entanglement between cpusets and hot plug of this alternative approach is not worth doing in this case. Signed-off-by: Paul Jackson Acked-by: Nathan Lynch Acked-by: Dinakar Guniguntala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cpusets.txt | 3 +-- kernel/sched.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt index 1ad26d2..2f8f24e 100644 --- a/Documentation/cpusets.txt +++ b/Documentation/cpusets.txt @@ -252,8 +252,7 @@ in a tasks processor placement. There is an exception to the above. If hotplug funtionality is used to remove all the CPUs that are currently assigned to a cpuset, then the kernel will automatically update the cpus_allowed of all -tasks attached to CPUs in that cpuset with the online CPUs of the -nearest parent cpuset that still has some CPUs online. When memory +tasks attached to CPUs in that cpuset to allow all CPUs. When memory hotplug functionality for removing Memory Nodes is available, a similar exception is expected to apply there as well. In general, the kernel prefers to violate cpuset placement, over starving a task diff --git a/kernel/sched.c b/kernel/sched.c index 0dc3158..66b2ed7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4243,7 +4243,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk) /* No more Mr. Nice Guy. */ if (dest_cpu == NR_CPUS) { - tsk->cpus_allowed = cpuset_cpus_allowed(tsk); + cpus_setall(tsk->cpus_allowed); dest_cpu = any_online_cpu(tsk->cpus_allowed); /* -- cgit v1.1 From b41e29398a873945d02e0009ce7e57608fdb4042 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:55 -0700 Subject: [PATCH] x86_64: 386/x86-64 Further AMD dual core fixes - Remove duplicated ifdef - Make core_id match what Intel uses - Initialize phys_proc_id correctly for non DC case - Handle non power of two core numbers. Fixes for both i386 and x86-64 Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/amd.c | 9 ++++++--- arch/i386/kernel/cpu/common.c | 5 +---- arch/x86_64/kernel/setup.c | 25 ++++++++++++------------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index fa34a06..73aeaf5 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -195,7 +195,7 @@ static void __init init_amd(struct cpuinfo_x86 *c) c->x86_num_cores = 1; } -#ifdef CONFIG_X86_SMP +#ifdef CONFIG_X86_HT /* * On a AMD dual core setup the lower bits of the APIC id * distingush the cores. Assumes number of cores is a power @@ -203,8 +203,11 @@ static void __init init_amd(struct cpuinfo_x86 *c) */ if (c->x86_num_cores > 1) { int cpu = smp_processor_id(); - /* Fix up the APIC ID following AMD specifications. */ - cpu_core_id[cpu] >>= hweight32(c->x86_num_cores - 1); + unsigned bits = 0; + while ((1 << bits) < c->x86_num_cores) + bits++; + cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<>= bits; printk(KERN_INFO "CPU %d(%d) -> Core %d\n", cpu, c->x86_num_cores, cpu_core_id[cpu]); } diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 11e6e6f..d199e52 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -244,11 +244,8 @@ static void __init early_cpu_detect(void) early_intel_workaround(c); -#ifdef CONFIG_SMP #ifdef CONFIG_X86_HT - phys_proc_id[smp_processor_id()] = -#endif - cpu_core_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; + phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; #endif } diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index b9fd025..99f038e 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -719,7 +719,6 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c) } } -#ifdef CONFIG_SMP /* * On a AMD dual core setup the lower bits of the APIC id distingush the cores. * Assumes number of cores is a power of two. @@ -729,16 +728,24 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) #ifdef CONFIG_SMP int cpu = smp_processor_id(); int node = 0; + unsigned bits; if (c->x86_num_cores == 1) return; - /* Fix up the APIC ID following the AMD specification. */ - cpu_core_id[cpu] >>= hweight32(c->x86_num_cores - 1); + + bits = 0; + while ((1 << bits) < c->x86_num_cores) + bits++; + + /* Low order bits define the core id (index of core in socket) */ + cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1); + /* Convert the APIC ID into the socket ID */ + phys_proc_id[cpu] >>= bits; #ifdef CONFIG_NUMA /* When an ACPI SRAT table is available use the mappings from SRAT instead. */ if (acpi_numa <= 0) { - node = cpu_core_id[cpu]; + node = phys_proc_id[cpu]; if (!node_online(node)) node = first_node(node_online_map); cpu_to_node[cpu] = node; @@ -746,18 +753,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) node = cpu_to_node[cpu]; } #endif - /* For now: - better than BAD_APIC_ID at least*/ - phys_proc_id[cpu] = cpu_core_id[cpu]; printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", cpu, c->x86_num_cores, node, cpu_core_id[cpu]); #endif } -#else -static void __init amd_detect_cmp(struct cpuinfo_x86 *c) -{ -} -#endif static int __init init_amd(struct cpuinfo_x86 *c) { @@ -963,8 +963,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) } #ifdef CONFIG_SMP - phys_proc_id[smp_processor_id()] = - cpu_core_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; + phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; #endif } -- cgit v1.1 From c4d1fcf3a2ea89b6d6221fa8b4588c77aff50995 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:56 -0700 Subject: [PATCH] x86_64: Don't allow accesses below register frame in ptrace There was a "off by one quad word" error in there. I don't think it is exploitable because it will only store into a unused area, but better to plug it. Found and fixed by John Blackwood Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/ptrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 60dc9b9..525f6a1 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -380,7 +380,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data break; switch (addr) { - case 0 ... sizeof(struct user_regs_struct): + case 0 ... sizeof(struct user_regs_struct) - sizeof(long): tmp = getreg(child, addr); break; case offsetof(struct user, u_debugreg[0]): @@ -425,7 +425,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data break; switch (addr) { - case 0 ... sizeof(struct user_regs_struct): + case 0 ... sizeof(struct user_regs_struct) - sizeof(long): ret = putreg(child, addr, data); break; /* Disallows to set a breakpoint into the vsyscall */ -- cgit v1.1 From 7856dfeb23c16ef3d8dac8871b4d5b93c70b59b9 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:57 -0700 Subject: [PATCH] x86_64: Fixed guard page handling again in iounmap Caused oopses again. Also fix potential mismatch in checking if change_page_attr was needed. To do it without races I needed to change mm/vmalloc.c to export a __remove_vm_area that does not take vmlist lock. Noticed by Terence Ripperda and based on a patch of his. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/mm/ioremap.c | 29 ++++++++--------------------- include/linux/vmalloc.h | 1 + mm/vmalloc.c | 33 ++++++++++++++++++++------------- 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index c6fb0cb..58aac23 100644 --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -133,7 +133,7 @@ ioremap_change_attr(unsigned long phys_addr, unsigned long size, unsigned long flags) { int err = 0; - if (flags && phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) { + if (phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) { unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long vaddr = (unsigned long) __va(phys_addr); @@ -214,7 +214,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr)); return NULL; } - if (ioremap_change_attr(phys_addr, size, flags) < 0) { + if (flags && ioremap_change_attr(phys_addr, size, flags) < 0) { area->flags &= 0xffffff; vunmap(addr); return NULL; @@ -251,7 +251,7 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size) void iounmap(volatile void __iomem *addr) { - struct vm_struct *p, **pprev; + struct vm_struct *p; if (addr <= high_memory) return; @@ -260,24 +260,11 @@ void iounmap(volatile void __iomem *addr) return; write_lock(&vmlist_lock); - for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = *pprev) - if (p->addr == (void *)(PAGE_MASK & (unsigned long)addr)) - break; - if (!p) { - printk("__iounmap: bad address %p\n", addr); - goto out_unlock; - } - *pprev = p->next; - unmap_vm_area(p); - if ((p->flags >> 20) && - p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) { - /* p->size includes the guard page, but cpa doesn't like that */ - change_page_attr_addr((unsigned long)__va(p->phys_addr), - p->size >> PAGE_SHIFT, - PAGE_KERNEL); - global_flush_tlb(); - } -out_unlock: + p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK)); + if (!p) + printk("iounmap: bad address %p\n", addr); + else if (p->flags >> 20) + ioremap_change_attr(p->phys_addr, p->size, 0); write_unlock(&vmlist_lock); kfree(p); } diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 3a358c8..6409d9c 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -41,6 +41,7 @@ extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags); extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, unsigned long start, unsigned long end); extern struct vm_struct *remove_vm_area(void *addr); +extern struct vm_struct *__remove_vm_area(void *addr); extern int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages); extern void unmap_vm_area(struct vm_struct *area); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 2bd83e5..8ff16a1 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -248,31 +248,20 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags) return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END); } -/** - * remove_vm_area - find and remove a contingous kernel virtual area - * - * @addr: base address - * - * Search for the kernel VM area starting at @addr, and remove it. - * This function returns the found VM area, but using it is NOT safe - * on SMP machines. - */ -struct vm_struct *remove_vm_area(void *addr) +/* Caller must hold vmlist_lock */ +struct vm_struct *__remove_vm_area(void *addr) { struct vm_struct **p, *tmp; - write_lock(&vmlist_lock); for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) { if (tmp->addr == addr) goto found; } - write_unlock(&vmlist_lock); return NULL; found: unmap_vm_area(tmp); *p = tmp->next; - write_unlock(&vmlist_lock); /* * Remove the guard page. @@ -281,6 +270,24 @@ found: return tmp; } +/** + * remove_vm_area - find and remove a contingous kernel virtual area + * + * @addr: base address + * + * Search for the kernel VM area starting at @addr, and remove it. + * This function returns the found VM area, but using it is NOT safe + * on SMP machines, except for its size or flags. + */ +struct vm_struct *remove_vm_area(void *addr) +{ + struct vm_struct *v; + write_lock(&vmlist_lock); + v = __remove_vm_area(addr); + write_unlock(&vmlist_lock); + return v; +} + void __vunmap(void *addr, int deallocate_pages) { struct vm_struct *area; -- cgit v1.1 From 4057923614e2868a865aa6c6e3bc53542c818d4d Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:57 -0700 Subject: [PATCH] i386: Fix race in iounmap We need to hold the vmlist_lock while doing change_page_attr, otherwise we could reset someone else's mapping. Requires previous patch to add __remove_vm_area Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/ioremap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index db06f73..ab54279 100644 --- a/arch/i386/mm/ioremap.c +++ b/arch/i386/mm/ioremap.c @@ -238,19 +238,21 @@ void iounmap(volatile void __iomem *addr) addr < phys_to_virt(ISA_END_ADDRESS)) return; - p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); + write_lock(&vmlist_lock); + p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); if (!p) { - printk("__iounmap: bad address %p\n", addr); - return; + printk("iounmap: bad address %p\n", addr); + goto out_unlock; } if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) { - /* p->size includes the guard page, but cpa doesn't like that */ change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, PAGE_KERNEL); global_flush_tlb(); } +out_unlock: + write_unlock(&vmlist_lock); kfree(p); } -- cgit v1.1 From 607a16858397829806c5a4db999ce6daf327f98c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:58 -0700 Subject: [PATCH] x86_64: Fix 32bit system call restart The test case at http://cvs.sourceforge.net/viewcvs.py/posixtest/posixtestsuite/conforman ce/interfaces/clock_nanosleep/1-5.c fails if it runs as a 32bit process on x86_86 machines. The root cause is the sub 32bit process fails to restart the syscall after it is interrupted by a signal. The syscall number of sys_restart_syscall in table sys_call_table is __NR_restart_syscall (219) while it's __NR_ia32_restart_syscall (0) in ia32_sys_call_table. When regs->rax==(unsigned long)-ERESTART_RESTARTBLOCK, function do_signal doesn't distinguish if the process is 64bit or 32bit, and always sets restart syscall number as __NR_restart_syscall (219). Signed-off-by: Zhang Yanmin Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/signal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index d439ced..3fdcdba 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -452,7 +452,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) regs->rip -= 2; } if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) { - regs->rax = __NR_restart_syscall; + regs->rax = test_thread_flag(TIF_IA32) ? + __NR_ia32_restart_syscall : + __NR_restart_syscall; regs->rip -= 2; } } -- cgit v1.1 From 14d98cad82b78956957e95567b8b5fb38ec5859f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:59 -0700 Subject: [PATCH] x86_64: Add option to disable timer check This works around the too fast timer seen on some ATI boards. I don't feel confident enough about it yet to enable it by default, but give users the option. Patch and debugging from Christopher Allen Wing , with minor tweaks (renamed the option and documented it) Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/x86_64/boot-options.txt | 3 +++ arch/x86_64/kernel/io_apic.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index 44b6eea..b9e6be0 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -25,6 +25,9 @@ APICs noapictimer Don't set up the APIC timer + no_timer_check Don't check the IO-APIC timer. This can work around + problems with incorrect timer initialization on some boards. + Early Console syntax: earlyprintk=vga diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index ac76843..80e9b49 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -42,6 +42,8 @@ int sis_apic_bug; /* not actually supported, dummy for compile */ +static int no_timer_check; + static DEFINE_SPINLOCK(ioapic_lock); /* @@ -1601,7 +1603,7 @@ static inline void check_timer(void) * Ok, does IRQ0 through the IOAPIC work? */ unmask_IO_APIC_irq(0); - if (timer_irq_works()) { + if (!no_timer_check && timer_irq_works()) { nmi_watchdog_default(); if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); @@ -1671,6 +1673,13 @@ static inline void check_timer(void) panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n"); } +static int __init notimercheck(char *s) +{ + no_timer_check = 1; + return 1; +} +__setup("no_timer_check", notimercheck); + /* * * IRQ's that are handled by the PIC in the MPS IOAPIC case. -- cgit v1.1 From 2df9fa36643f03b0462b170515c1e221c3709fa9 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 20 May 2005 14:27:59 -0700 Subject: [PATCH] x86_64: i386/x86-64: Export cpu_core_map Needed for the powernow k8 driver for dual core support. Signed-off-by: Andi Kleen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smpboot.c | 1 + arch/x86_64/kernel/smpboot.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index cbea7ac..35bfe13 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -888,6 +888,7 @@ void *xquad_portio; cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; +EXPORT_SYMBOL(cpu_core_map); static void __init smp_boot_cpus(unsigned int max_cpus) { diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 5abdee1..f1ec0f3 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -94,6 +94,7 @@ int smp_threads_ready; cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; +EXPORT_SYMBOL(cpu_core_map); /* * Trampoline 80x86 program as an array. -- cgit v1.1 From 912490db699d83cb3d03570b63df7448677a3f56 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 21 May 2005 10:27:02 +0100 Subject: [PATCH] MMC: Proper MMC command classes support Defines for the different command classes as defined in the MMC and SD specifications. Removes the check for high command classes and instead checks that the command classes needed are present. Previous solution killed forward compatibility at no apparent gain. Signed-of-by: Pierre Ossman --- drivers/mmc/mmc_block.c | 5 ++++- include/linux/mmc/protocol.h | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index b5b4a7b..d4eee99 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -383,7 +383,10 @@ static int mmc_blk_probe(struct mmc_card *card) struct mmc_blk_data *md; int err; - if (card->csd.cmdclass & ~0x1ff) + /* + * Check that the card supports the command class(es) we need. + */ + if (!(card->csd.cmdclass & CCC_BLOCK_READ)) return -ENODEV; if (card->csd.read_blkbits < 9) { diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h index 7b904c5..8963428 100644 --- a/include/linux/mmc/protocol.h +++ b/include/linux/mmc/protocol.h @@ -195,6 +195,33 @@ struct _mmc_csd { #define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ #define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ +/* + * Card Command Classes (CCC) + */ +#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ + /* (CMD0,1,2,3,4,7,9,10,12,13,15) */ +#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */ + /* (CMD11) */ +#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */ + /* (CMD16,17,18) */ +#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */ + /* (CMD20) */ +#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */ + /* (CMD16,24,25,26,27) */ +#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */ + /* (CMD32,33,34,35,36,37,38,39) */ +#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */ + /* (CMD28,29,30) */ +#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */ + /* (CMD16,CMD42) */ +#define CCC_APP_SPEC (1<<8) /* (8) Application specific */ + /* (CMD55,56,57,ACMD*) */ +#define CCC_IO_MODE (1<<9) /* (9) I/O mode */ + /* (CMD5,39,40,52,53) */ +#define CCC_SWITCH (1<<10) /* (10) High speed switch */ + /* (CMD6,34,35,36,37,50) */ + /* (11) Reserved */ + /* (CMD?) */ /* * CSD field definitions -- cgit v1.1 From 857dde2e79082d2954ede7f10783addaae956777 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 21 May 2005 15:52:23 +0100 Subject: When we detect that a 16550 was in fact part of a NatSemi SuperIO chip with high-speed mode enabled, we switch it to high-speed mode so that baud_base becomes 921600. However, we also need to multiply the baud divisor by 8 at the same time, in case it's already in use as a console. Signed-off-by: David Woodhouse Acked-by: Tom Rini Signed-off-by: Russell King --- drivers/serial/8250.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 3bbf0cc..30e8beb 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -682,8 +682,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) * from EXCR1. Switch back to bank 0, change it in MCR. Then * switch back to bank 2, read it from EXCR1 again and check * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2 - * On PowerPC we don't want to change baud_base, as we have - * a number of different divisors. -- Tom Rini */ serial_outp(up, UART_LCR, 0); status1 = serial_in(up, UART_MCR); @@ -699,16 +697,25 @@ static void autoconfig_16550a(struct uart_8250_port *up) serial_outp(up, UART_MCR, status1); if ((status2 ^ status1) & UART_MCR_LOOP) { -#ifndef CONFIG_PPC + unsigned short quot; + serial_outp(up, UART_LCR, 0xE0); + + quot = serial_inp(up, UART_DLM) << 8; + quot += serial_inp(up, UART_DLL); + quot <<= 3; + status1 = serial_in(up, 0x04); /* EXCR1 */ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ serial_outp(up, 0x04, status1); + + serial_outp(up, UART_DLL, quot & 0xff); + serial_outp(up, UART_DLM, quot >> 8); + serial_outp(up, UART_LCR, 0); - up->port.uartclk = 921600*16; -#endif + up->port.uartclk = 921600*16; up->port.type = PORT_NS16550A; up->capabilities |= UART_NATSEMI; return; -- cgit v1.1 From 10f02d1c59e55f529140dda3a92f0099d748451c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 21 May 2005 17:50:15 +0200 Subject: [PATCH] spin_unlock_bh() and preempt_check_resched() In _spin_unlock_bh(lock): do { \ _raw_spin_unlock(lock); \ preempt_enable(); \ local_bh_enable(); \ __release(lock); \ } while (0) there is no reason for using preempt_enable() instead of a simple preempt_enable_no_resched() Since we know bottom halves are disabled, preempt_schedule() will always return at once (preempt_count!=0), and hence preempt_check_resched() is useless here... This fixes it by using "preempt_enable_no_resched()" instead of the "preempt_enable()", and thus avoids the useless preempt_check_resched() just before re-enabling bottom halves. Signed-off-by: Samuel Thibault Signed-off-by: Linus Torvalds --- include/linux/spinlock.h | 8 ++++---- kernel/spinlock.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index e895f3e..d6ba068 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -248,7 +248,7 @@ typedef struct { #define _spin_trylock_bh(lock) ({preempt_disable(); local_bh_disable(); \ _raw_spin_trylock(lock) ? \ - 1 : ({preempt_enable(); local_bh_enable(); 0;});}) + 1 : ({preempt_enable_no_resched(); local_bh_enable(); 0;});}) #define _spin_lock(lock) \ do { \ @@ -383,7 +383,7 @@ do { \ #define _spin_unlock_bh(lock) \ do { \ _raw_spin_unlock(lock); \ - preempt_enable(); \ + preempt_enable_no_resched(); \ local_bh_enable(); \ __release(lock); \ } while (0) @@ -391,7 +391,7 @@ do { \ #define _write_unlock_bh(lock) \ do { \ _raw_write_unlock(lock); \ - preempt_enable(); \ + preempt_enable_no_resched(); \ local_bh_enable(); \ __release(lock); \ } while (0) @@ -423,8 +423,8 @@ do { \ #define _read_unlock_bh(lock) \ do { \ _raw_read_unlock(lock); \ + preempt_enable_no_resched(); \ local_bh_enable(); \ - preempt_enable(); \ __release(lock); \ } while (0) diff --git a/kernel/spinlock.c b/kernel/spinlock.c index e15ed17..0c3f9d8 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c @@ -294,7 +294,7 @@ EXPORT_SYMBOL(_spin_unlock_irq); void __lockfunc _spin_unlock_bh(spinlock_t *lock) { _raw_spin_unlock(lock); - preempt_enable(); + preempt_enable_no_resched(); local_bh_enable(); } EXPORT_SYMBOL(_spin_unlock_bh); @@ -318,7 +318,7 @@ EXPORT_SYMBOL(_read_unlock_irq); void __lockfunc _read_unlock_bh(rwlock_t *lock) { _raw_read_unlock(lock); - preempt_enable(); + preempt_enable_no_resched(); local_bh_enable(); } EXPORT_SYMBOL(_read_unlock_bh); @@ -342,7 +342,7 @@ EXPORT_SYMBOL(_write_unlock_irq); void __lockfunc _write_unlock_bh(rwlock_t *lock) { _raw_write_unlock(lock); - preempt_enable(); + preempt_enable_no_resched(); local_bh_enable(); } EXPORT_SYMBOL(_write_unlock_bh); @@ -354,7 +354,7 @@ int __lockfunc _spin_trylock_bh(spinlock_t *lock) if (_raw_spin_trylock(lock)) return 1; - preempt_enable(); + preempt_enable_no_resched(); local_bh_enable(); return 0; } -- cgit v1.1 From f359b74c80bc76c1f6c2cb8f2837882f2335ba0c Mon Sep 17 00:00:00 2001 From: Vladimir Saveliev Date: Sat, 21 May 2005 16:33:34 -0700 Subject: [PATCH] reiserfs: max_key fix This patch fixes a bug introduced by Al Viro's patch: [patch 136/174] reiserfs endianness: clone struct reiserfs_key The problem is MAX_KEY and MAX_IN_CORE_KEY defined in this patch do not look equal from reiserfs comp_key's point of view. This caused reiserfs' sanity check to complain. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/stree.c | 1 - fs/reiserfs/super.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index da23ba7..c47f8fd 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -230,7 +230,6 @@ const struct reiserfs_key MAX_KEY = { __constant_cpu_to_le32(0xffffffff)},} }; -const struct in_core_key MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15}; /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom of the path, and going upwards. We must check the path's validity at each step. If the key is not in diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 31e7512..b35b877 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -164,7 +164,9 @@ static int finish_unfinished (struct super_block * s) /* compose key to look for "save" links */ max_cpu_key.version = KEY_FORMAT_3_5; - max_cpu_key.on_disk_key = MAX_IN_CORE_KEY; + max_cpu_key.on_disk_key.k_dir_id = ~0U; + max_cpu_key.on_disk_key.k_objectid = ~0U; + set_cpu_key_k_offset (&max_cpu_key, ~0U); max_cpu_key.key_length = 3; #ifdef CONFIG_QUOTA -- cgit v1.1 From b5c44c2147a447f77e07fecdb087ae288e1f4e40 Mon Sep 17 00:00:00 2001 From: Suparna Bhattacharya Date: Sat, 21 May 2005 16:33:36 -0700 Subject: [PATCH] fix for __generic_file_aio_read() to return 0 on EOF I came across the following problem while running ltp-aiodio testcases from ltp-full-20050405 on linux-2.6.12-rc3-mm3. I tried running the tests with EXT3 as well as JFS filesystems. One or two fsx-linux testcases were hung after some time. These testcases were hanging at wait_for_all_aios(). Debugging shows that there were some iocbs which were not getting completed eventhough the last retry for those returned -EIOCBQUEUED. Also all such pending iocbs represented READ operation. Further debugging revealed that all such iocbs hit EOF in the DIO layer. To be more precise, the "pos" from which they were trying to read was greater than the "size" of the file. So the generic_file_direct_IO returned 0. This happens rarely as there is already a check in __generic_file_aio_read(), for whether "pos" < "size" before calling direct IO routine. >size = i_size_read(inode); >if (pos < size) { > retval = generic_file_direct_IO(READ, iocb, > iov, pos, nr_segs); But for READ, we are taking the inode->i_sem only in the DIO layer. So it is possible that some other process can change the size of the file before we take the i_sem. In such a case ( when "pos" > "size"), the __generic_file_aio_read() would return -EIOCBQUEUED even though there were no I/O requests submitted by the DIO layer. This would cause the AIO layer to expect aio_complete() for THE iocb, which doesnot happen. And thus the test hangs forever, waiting for an I/O completion, where there are no requests submitted at all. The following patch makes __generic_file_aio_read() return 0 (instead of returning -EIOCBQUEUED), on getting 0 from generic_file_direct_IO(), so that the AIO layer does the aio_complete(). Testing: I have tested the patch on a SMP machine(with 2 Pentium 4 (HT)) running linux-2.6.12-rc3-mm3. I ran the ltp-aiodio testcases and none of the fsx-linux tests hung. Also the aio-stress tests ran without any problem. Signed-off-by: Suzuki K P Signed-off-by: Suparna Bhattacharya Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/filemap.c b/mm/filemap.c index 47263ac..1d33fec 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1004,7 +1004,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, if (pos < size) { retval = generic_file_direct_IO(READ, iocb, iov, pos, nr_segs); - if (retval >= 0 && !is_sync_kiocb(iocb)) + if (retval > 0 && !is_sync_kiocb(iocb)) retval = -EIOCBQUEUED; if (retval > 0) *ppos = pos + retval; -- cgit v1.1 From 1263cc67c09bc7f913a6877f3ba0427f0b76617e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 23 May 2005 10:03:52 +1000 Subject: [PATCH] ppc64: Fix booting on latest G5 models The latest speedbumped Apple G5 models have a "bug" in the Open Firmware device tree that lacks the proper interrupt routing information for the northbridge i2c controller. Apple's driver silently falls back into a sub-optimal "polled" mode (heh, maybe they didn't even notice the bug because of that :), our driver didn't properly check and crashes :( This patch fixes our driver to not crash, and adds code to the prom_init() OF trampoline code that detects the "bug" and adds the missing information back for this chipset revision. This fixes booting and thermal control on these models. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/prom_init.c | 44 +++++++++++++++++++++++++++++++++++++++- drivers/i2c/busses/i2c-keywest.c | 5 +++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 35ec42d..6f79b7b 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1750,7 +1750,44 @@ static void __init flatten_device_tree(void) prom_printf("Device tree struct 0x%x -> 0x%x\n", RELOC(dt_struct_start), RELOC(dt_struct_end)); - } +} + + +static void __init fixup_device_tree(void) +{ + unsigned long offset = reloc_offset(); + phandle u3, i2c, mpic; + u32 u3_rev; + u32 interrupts[2]; + u32 parent; + + /* Some G5s have a missing interrupt definition, fix it up here */ + u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); + if ((long)u3 <= 0) + return; + i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); + if ((long)i2c <= 0) + return; + mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); + if ((long)mpic <= 0) + return; + + /* check if proper rev of u3 */ + if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) + return; + if (u3_rev != 0x35) + return; + /* does it need fixup ? */ + if (prom_getproplen(i2c, "interrupts") > 0) + return; + /* interrupt on this revision of u3 is number 0 and level */ + interrupts[0] = 0; + interrupts[1] = 1; + prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); + parent = (u32)mpic; + prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); +} + static void __init prom_find_boot_cpu(void) { @@ -1920,6 +1957,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long } /* + * Fixup any known bugs in the device-tree + */ + fixup_device_tree(); + + /* * Now finally create the flattened device-tree */ prom_printf("copying OF device tree ...\n"); diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c index dd0d4c4..867d443 100644 --- a/drivers/i2c/busses/i2c-keywest.c +++ b/drivers/i2c/busses/i2c-keywest.c @@ -516,6 +516,11 @@ create_iface(struct device_node *np, struct device *dev) u32 *psteps, *prate; int rc; + if (np->n_intrs < 1 || np->n_addrs < 1) { + printk(KERN_ERR "%s: Missing interrupt or address !\n", + np->full_name); + return -ENODEV; + } if (pmac_low_i2c_lock(np)) return -ENODEV; -- cgit v1.1 From e16fa6b9d2ad9467cf5bdf517e6b6f45e5867ad6 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 23 May 2005 12:29:56 -0500 Subject: [PATCH] ppc32: Fix an off-by-one error in ipic_init There is an off-by-one error in the IPIC code that configures the external interrupts (Edge or Level Sensitive). Signed-off-by: Randy Vinson Signed-off-by: Kumar Gala Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ipic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c index acb2cde..580ed65 100644 --- a/arch/ppc/syslib/ipic.c +++ b/arch/ppc/syslib/ipic.c @@ -479,7 +479,7 @@ void __init ipic_init(phys_addr_t phys_addr, temp = 0; for (i = 0 ; i < senses_count ; i++) { if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { - temp |= 1 << (16 - i); + temp |= 1 << (15 - i); if (i != 0) irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; else -- cgit v1.1 From f10d20c1f192aa90fc935207f22da32462e793ee Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 23 May 2005 16:54:14 +1000 Subject: [PATCH] ppc64: Fix g5 hw timebase sync The hardware sync of the timebase on SMP G5s uses a black magic incantation to the i2c clock chip that was inspired from what Darwin does. However, this was an earlier version of Darwin that was ... buggy ! heh. This causes the latest models to break though when starting SMP, so it's worth fixing. Here's a new version of the incantation based on careful transcription of the said incantations as found in the latest version of apple's temple. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/pmac_smp.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c index c27588e..a23de37 100644 --- a/arch/ppc64/kernel/pmac_smp.c +++ b/arch/ppc64/kernel/pmac_smp.c @@ -68,6 +68,7 @@ extern struct smp_ops_t *smp_ops; static void (*pmac_tb_freeze)(int freeze); static struct device_node *pmac_tb_clock_chip_host; +static u8 pmac_tb_pulsar_addr; static DEFINE_SPINLOCK(timebase_lock); static unsigned long timebase; @@ -106,12 +107,9 @@ static void smp_core99_pulsar_tb_freeze(int freeze) u8 data; int rc; - /* Strangely, the device-tree says address is 0xd2, but darwin - * accesses 0xd0 ... - */ pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, - 0xd4 | pmac_low_i2c_read, + pmac_tb_pulsar_addr | pmac_low_i2c_read, 0x2e, &data, 1); if (rc != 0) goto bail; @@ -120,7 +118,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze) pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, - 0xd4 | pmac_low_i2c_write, + pmac_tb_pulsar_addr | pmac_low_i2c_write, 0x2e, &data, 1); bail: if (rc != 0) { @@ -185,6 +183,12 @@ static int __init smp_core99_probe(void) if (ncpus <= 1) return 1; + /* HW sync only on these platforms */ + if (!machine_is_compatible("PowerMac7,2") && + !machine_is_compatible("PowerMac7,3") && + !machine_is_compatible("RackMac3,1")) + goto nohwsync; + /* Look for the clock chip */ for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) { struct device_node *p = of_get_parent(cc); @@ -198,11 +202,18 @@ static int __init smp_core99_probe(void) goto next; switch (*reg) { case 0xd2: - pmac_tb_freeze = smp_core99_cypress_tb_freeze; - printk(KERN_INFO "Timebase clock is Cypress chip\n"); + if (device_is_compatible(cc, "pulsar-legacy-slewing")) { + pmac_tb_freeze = smp_core99_pulsar_tb_freeze; + pmac_tb_pulsar_addr = 0xd2; + printk(KERN_INFO "Timebase clock is Pulsar chip\n"); + } else if (device_is_compatible(cc, "cy28508")) { + pmac_tb_freeze = smp_core99_cypress_tb_freeze; + printk(KERN_INFO "Timebase clock is Cypress chip\n"); + } break; case 0xd4: pmac_tb_freeze = smp_core99_pulsar_tb_freeze; + pmac_tb_pulsar_addr = 0xd4; printk(KERN_INFO "Timebase clock is Pulsar chip\n"); break; } @@ -210,12 +221,15 @@ static int __init smp_core99_probe(void) pmac_tb_clock_chip_host = p; smp_ops->give_timebase = smp_core99_give_timebase; smp_ops->take_timebase = smp_core99_take_timebase; + of_node_put(cc); + of_node_put(p); break; } next: of_node_put(p); } + nohwsync: mpic_request_ipis(); return ncpus; -- cgit v1.1 From 314324121f9b94b2ca657a494cf2b9cb0e4a28cc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2005 12:03:06 -0700 Subject: [TCP]: Fix stretch ACK performance killer when doing ucopy. When we are doing ucopy, we try to defer the ACK generation to cleanup_rbuf(). This works most of the time very well, but if the ucopy prequeue is large, this ACKing behavior kills performance. With TSO, it is possible to fill the prequeue so large that by the time the ACK is sent and gets back to the sender, most of the window has emptied of data and performance suffers significantly. This behavior does help in some cases, so we should think about re-enabling this trick in the future, using some kind of limit in order to avoid the bug case. Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 79835a6..5bad504 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4355,16 +4355,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, goto no_ack; } - if (eaten) { - if (tcp_in_quickack_mode(tp)) { - tcp_send_ack(sk); - } else { - tcp_send_delayed_ack(sk); - } - } else { - __tcp_ack_snd_check(sk, 0); - } - + __tcp_ack_snd_check(sk, 0); no_ack: if (eaten) __kfree_skb(skb); -- cgit v1.1 From 15333038d577b0c0255c0f14a38d9e6895937453 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 23 May 2005 12:36:25 -0700 Subject: [CRYPTO]: Only reschedule if !in_atomic() The netlink gfp_any() problem made me double-check the uses of in_softirq() in crypto/*. It seems to me that we should be checking in_atomic() instead of in_softirq() in crypto_yield. Otherwise people calling the crypto ops with spin locks held or preemption disabled will get burnt, right? Signed-off-by: David S. Miller --- crypto/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/internal.h b/crypto/internal.h index e68e438..964b9a6 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -38,7 +38,7 @@ static inline void crypto_kunmap(void *vaddr, int out) static inline void crypto_yield(struct crypto_tfm *tfm) { - if (!in_softirq()) + if (!in_atomic()) cond_resched(); } -- cgit v1.1 From deaf2622bdc74270381873c7936c91500c683853 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2005 12:45:26 -0700 Subject: [NET]: Kill stray reference to sock->passcred. That struct member was deleted, but a comment was not updated to reflect this. Signed-off-by: David S. Miller --- include/linux/net.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/net.h b/include/linux/net.h index 6d997ff..20cb226 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -101,7 +101,6 @@ enum sock_type { * @sk: internal networking protocol agnostic socket representation * @wait: wait queue for several uses * @type: socket type (%SOCK_STREAM, etc) - * @passcred: credentials (used only in Unix Sockets (aka PF_LOCAL)) */ struct socket { socket_state state; -- cgit v1.1 From 82d1542c1df6b3a0105843deddebeff03068d1dc Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Mon, 23 May 2005 12:53:14 -0700 Subject: [NET]: include/linux/if_tr.h clean-up I removed the ethernet definitions (which were commented out) and cleaned up the tabs. Signed-off-by: Jon Mason --- include/linux/if_tr.h | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h index 4fd451f..a2b01e1e 100644 --- a/include/linux/if_tr.h +++ b/include/linux/if_tr.h @@ -9,7 +9,7 @@ * * Author: Fred N. van Kempen, * Donald Becker, - * Peter De Schrijver, + * Peter De Schrijver, * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,24 +19,16 @@ #ifndef _LINUX_IF_TR_H #define _LINUX_IF_TR_H - /* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble and FCS/CRC (frame check sequence). */ -#define TR_ALEN 6 /* Octets in one ethernet addr */ -#define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc)) -#define AC 0x10 -#define LLC_FRAME 0x40 -#if 0 -#define ETH_HLEN 14 /* Total octets in header. */ -#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ -#define ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ -#endif - +#define TR_ALEN 6 /* Octets in one token-ring addr */ +#define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc)) +#define AC 0x10 +#define LLC_FRAME 0x40 /* LLC and SNAP constants */ -#define EXTENDED_SAP 0xAA -#define UI_CMD 0x03 +#define EXTENDED_SAP 0xAA +#define UI_CMD 0x03 /* This is an Token-Ring frame header. */ struct trh_hdr { @@ -96,14 +88,13 @@ struct tr_statistics { }; /* source routing stuff */ - -#define TR_RII 0x80 -#define TR_RCF_DIR_BIT 0x80 -#define TR_RCF_LEN_MASK 0x1f00 -#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ -#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ -#define TR_RCF_FRAME2K 0x20 -#define TR_RCF_BROADCAST_MASK 0xC000 -#define TR_MAXRIFLEN 18 +#define TR_RII 0x80 +#define TR_RCF_DIR_BIT 0x80 +#define TR_RCF_LEN_MASK 0x1f00 +#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ +#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ +#define TR_RCF_FRAME2K 0x20 +#define TR_RCF_BROADCAST_MASK 0xC000 +#define TR_MAXRIFLEN 18 #endif /* _LINUX_IF_TR_H */ -- cgit v1.1 From d8659255c599ba497bcfb8b4abc187d9e0951d99 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Mon, 23 May 2005 12:54:51 -0700 Subject: [TG3]: Add 5752M device ID. Add 0x1601 as 5752M, it's a 5752 but for mobile PCs. Stolen from Broadcom bcm5700-8.1.55 driver. Someone forgot to add it to tg3 ;-) Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 ++ include/linux/pci_ids.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4d2bdbd..ebd882f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -206,6 +206,8 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ae27792..7b9720e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2064,6 +2064,7 @@ #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_DEVICE_ID_TIGON3_5752 0x1600 +#define PCI_DEVICE_ID_TIGON3_5752M 0x1601 #define PCI_DEVICE_ID_TIGON3_5700 0x1644 #define PCI_DEVICE_ID_TIGON3_5701 0x1645 #define PCI_DEVICE_ID_TIGON3_5702 0x1646 -- cgit v1.1 From 205902ecc7bcb2a007ed27bb3518e8f70e5d113e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 23 May 2005 13:09:19 -0700 Subject: [NET]: netdevice.h: be'ify packet_type Everybody does struct packet_type foo_packet_type = { .type = __constant_htons(ETH_P_FOO); }; 5 introduced warnings will be properly fixed later. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ac11d73..b25bd02 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -503,7 +503,7 @@ static inline void *netdev_priv(struct net_device *dev) #define SET_NETDEV_DEV(net, pdev) ((net)->class_dev.dev = (pdev)) struct packet_type { - unsigned short type; /* This is really htons(ether_type). */ + __be16 type; /* This is really htons(ether_type). */ struct net_device *dev; /* NULL is wildcarded here */ int (*func) (struct sk_buff *, struct net_device *, struct packet_type *); -- cgit v1.1 From 180e42503300629692b513daeb55a6bb0b51500c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 23 May 2005 13:11:07 -0700 Subject: [IPV6]: Fix xfrm tunnel oops with large packets Signed-off-by: Herbert Xu Acked-by: Hideaki YOSHIFUJI Signed-off-by: David S. Miller --- net/ipv6/xfrm6_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 601a148..6b98677 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -84,6 +84,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) mtu = IPV6_MIN_MTU; if (skb->len > mtu) { + skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); ret = -EMSGSIZE; } -- cgit v1.1 From 413f5431a5a27e44c6610de640e507e1e3c885f4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2005 13:13:15 -0700 Subject: [TG3]: Update driver version and reldate. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ebd882f..fb16885 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -61,8 +61,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.27" -#define DRV_MODULE_RELDATE "May 5, 2005" +#define DRV_MODULE_VERSION "3.28" +#define DRV_MODULE_RELDATE "May 23, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.1 From ded7340d9d9142807a1ef94ab9c51d13ab76a1c9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2005 13:59:47 -0700 Subject: [TG3]: Increase TEST_BUFFER_SIZE to 8K. This makes the DMA bug workaround test more likely to find the problem on some systems. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index fb16885..2bb022a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8996,7 +8996,7 @@ static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dm return ret; } -#define TEST_BUFFER_SIZE 0x400 +#define TEST_BUFFER_SIZE 0x2000 static int __devinit tg3_test_dma(struct tg3 *tp) { -- cgit v1.1 From d1faeaeb95a05275cf0c5b51b88f2fa833434625 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2005 14:00:44 -0700 Subject: [TG3]: Update driver version. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2bb022a..f10dd74 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -61,7 +61,7 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.28" +#define DRV_MODULE_VERSION "3.29" #define DRV_MODULE_RELDATE "May 23, 2005" #define TG3_DEF_MAC_MODE 0 -- cgit v1.1 From 816242da3735957bee99aeba40aa60c4f120a101 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 23 May 2005 15:52:08 -0700 Subject: [SPARC64]: Add boot option to force UltraSPARC-III P-Cache on. Older UltraSPARC-III chips have a P-Cache bug that makes us disable it by default at boot time. However, this does hurt performance substantially, particularly with memcpy(), and the bug is _incredibly_ obscure. I have never seen it triggered in practice, ever. So provide a "-P" boot option that forces the P-Cache on. It taints the kernel, so if it does trigger and cause some data corruption or OOPS, we will find out in the logs that this option was on when it happened. Signed-off-by: David S. Miller --- arch/sparc64/kernel/setup.c | 11 +++++++++++ arch/sparc64/kernel/smp.c | 3 +++ arch/sparc64/kernel/traps.c | 19 +++++++++++++++++++ include/asm-sparc64/spitfire.h | 3 +++ 4 files changed, 36 insertions(+) diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 12c3d84b..b7e6a91 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -383,6 +383,17 @@ static void __init process_switch(char c) /* Use PROM debug console. */ register_console(&prom_debug_console); break; + case 'P': + /* Force UltraSPARC-III P-Cache on. */ + if (tlb_type != cheetah) { + printk("BOOT: Ignoring P-Cache force option.\n"); + break; + } + cheetah_pcache_forced_on = 1; + add_taint(TAINT_MACHINE_CHECK); + cheetah_enable_pcache(); + break; + default: printk("Unknown boot switch (-%c)\n", c); break; diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 6dff06a..e5b9c7a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -123,6 +123,9 @@ void __init smp_callin(void) smp_setup_percpu_timer(); + if (cheetah_pcache_forced_on) + cheetah_enable_pcache(); + local_irq_enable(); calibrate_delay(); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 56b203a..a9f4596 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -421,6 +421,25 @@ asmlinkage void cee_log(unsigned long ce_status, } } +int cheetah_pcache_forced_on; + +void cheetah_enable_pcache(void) +{ + unsigned long dcr; + + printk("CHEETAH: Enabling P-Cache on cpu %d.\n", + smp_processor_id()); + + __asm__ __volatile__("ldxa [%%g0] %1, %0" + : "=r" (dcr) + : "i" (ASI_DCU_CONTROL_REG)); + dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL); + __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (dcr), "i" (ASI_DCU_CONTROL_REG)); +} + /* Cheetah error trap handling. */ static unsigned long ecache_flush_physbase; static unsigned long ecache_flush_linesize; diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h index ad78ce6..9d7613e 100644 --- a/include/asm-sparc64/spitfire.h +++ b/include/asm-sparc64/spitfire.h @@ -48,6 +48,9 @@ enum ultra_tlb_layout { extern enum ultra_tlb_layout tlb_type; +extern int cheetah_pcache_forced_on; +extern void cheetah_enable_pcache(void); + #define sparc64_highest_locked_tlbent() \ (tlb_type == spitfire ? \ SPITFIRE_HIGHEST_LOCKED_TLBENT : \ -- cgit v1.1 From 187a1a94d629621d1471b42308e63573b1150773 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 23 May 2005 15:50:26 -0700 Subject: [PATCH] driver core: restore event order for device_add() As a result of the split of the kobject-registration and the corresponding hotplug event, the order of events for device_add() has changed. This restores the old order, cause it confused some userspace applications. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/base/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index d21eb77..fbc2234 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -245,6 +245,7 @@ int device_add(struct device *dev) if ((error = kobject_add(&dev->kobj))) goto Error; + kobject_hotplug(&dev->kobj, KOBJ_ADD); if ((error = device_pm_add(dev))) goto PMError; if ((error = bus_add_device(dev))) @@ -257,14 +258,13 @@ int device_add(struct device *dev) /* notify platform of device entry */ if (platform_notify) platform_notify(dev); - - kobject_hotplug(&dev->kobj, KOBJ_ADD); Done: put_device(dev); return error; BusError: device_pm_remove(dev); PMError: + kobject_hotplug(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); Error: if (parent) -- cgit v1.1 From 9092f46b5aed4515d9a427d5dab3be1584851f07 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 18 May 2005 13:41:33 -0400 Subject: [PATCH] tulip: add return to ULI526X clause in tulip_mdio_write The 'if' clause for ULI526X in tulip_mdio_write allows for spin_unlock_irqrestore to be called twice for tp->mii_lock. I believe this is caused by the unintentional omission of a return at the end of that clause. This patch adds that return. Signed-off-by: John W. Linville --- drivers/net/tulip/media.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index edae09a..919c40c 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -174,6 +174,7 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) break; } spin_unlock_irqrestore(&tp->mii_lock, flags); + return; } /* Establish sync by sending 32 logic ones. */ -- cgit v1.1 From 7e43c84e3e5423ae72ae31e4cd7bbccfd1605194 Mon Sep 17 00:00:00 2001 From: "blaisorblade@yahoo.it" Date: Wed, 25 May 2005 01:31:42 +0200 Subject: [PATCH] Cleanup DEFINE_WAIT Use LIST_HEAD_INIT rather than doing it by hand in DEFINE_WAIT. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds --- include/linux/wait.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/wait.h b/include/linux/wait.h index 17c874a..c9486c3 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -386,9 +386,7 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); wait_queue_t name = { \ .task = current, \ .func = autoremove_wake_function, \ - .task_list = { .next = &(name).task_list, \ - .prev = &(name).task_list, \ - }, \ + .task_list = LIST_HEAD_INIT((name).task_list), \ } #define DEFINE_WAIT_BIT(name, word, bit) \ -- cgit v1.1 From 6431e6a28e8df423e1ebcda065e9ff086198d2c6 Mon Sep 17 00:00:00 2001 From: Dominik Hackl Date: Tue, 24 May 2005 19:29:46 -0700 Subject: [PATCH] voyager_smp.c static inline fix This patch fixes a compile bug by moving a static inline function to the right place. The body of a static inline function has to be declared before the use of this function. Signed-off-by: Dominik Hackl Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mach-voyager/voyager_smp.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 903d739..a6e0ddd 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -97,7 +97,6 @@ static void ack_vic_irq(unsigned int irq); static void vic_enable_cpi(void); static void do_boot_cpu(__u8 cpuid); static void do_quad_bootstrap(void); -static inline void wrapper_smp_local_timer_interrupt(struct pt_regs *); int hard_smp_processor_id(void); @@ -126,6 +125,14 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi) } static inline void +wrapper_smp_local_timer_interrupt(struct pt_regs *regs) +{ + irq_enter(); + smp_local_timer_interrupt(regs); + irq_exit(); +} + +static inline void send_one_CPI(__u8 cpu, __u8 cpi) { if(voyager_quad_processors & (1< Date: Tue, 24 May 2005 19:29:47 -0700 Subject: [PATCH] sigkill priority fix If SIGKILL does not have priority, we cannot instantly kill task before it makes some unexpected job. It can be critical, but we were unable to reproduce this easily until Heiko Carstens reported this problem on LKML. Signed-Off-By: Kirill Korotaev Signed-Off-By: Alexey Kuznetsov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/signal.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/signal.c b/kernel/signal.c index 8f3debc..b3c24c7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -522,7 +522,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, { int sig = 0; - sig = next_signal(pending, mask); + /* SIGKILL must have priority, otherwise it is quite easy + * to create an unkillable process, sending sig < SIGKILL + * to self */ + if (unlikely(sigismember(&pending->signal, SIGKILL))) { + if (!sigismember(mask, SIGKILL)) + sig = SIGKILL; + } + + if (likely(!sig)) + sig = next_signal(pending, mask); if (sig) { if (current->notifier) { if (sigismember(current->notifier_mask, sig)) { -- cgit v1.1 From cafdd8ba08935d9b161bb781851dc4c0e6f70427 Mon Sep 17 00:00:00 2001 From: William Lee Irwin III Date: Tue, 24 May 2005 19:31:09 -0700 Subject: [PATCH] try_to_unmap_cluster() passes out-of-bounds pte to pte_unmap() try_to_unmap_cluster() does: for (pte = pte_offset_map(pmd, address); address < end; pte++, address += PAGE_SIZE) { ... } pte_unmap(pte); It may take a little staring to notice, but pte can actually fall off the end of the pte page in this iteration, which makes life difficult for kmap_atomic() and the users not expecting it to BUG(). Of course, we're somewhat lucky in that arithmetic elsewhere in the function guarantees that at least one iteration is made, lest this force larger rearrangements to be made. This issue and patch also apply to non-mm mainline and with trivial adjustments, at least two related kernels. Discovered during internal testing at Oracle. Signed-off-by: William Irwin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/rmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/rmap.c b/mm/rmap.c index a6203b4..9827409 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -626,7 +626,7 @@ static void try_to_unmap_cluster(unsigned long cursor, pgd_t *pgd; pud_t *pud; pmd_t *pmd; - pte_t *pte; + pte_t *pte, *original_pte; pte_t pteval; struct page *page; unsigned long address; @@ -658,7 +658,7 @@ static void try_to_unmap_cluster(unsigned long cursor, if (!pmd_present(*pmd)) goto out_unlock; - for (pte = pte_offset_map(pmd, address); + for (original_pte = pte = pte_offset_map(pmd, address); address < end; pte++, address += PAGE_SIZE) { if (!pte_present(*pte)) @@ -694,7 +694,7 @@ static void try_to_unmap_cluster(unsigned long cursor, (*mapcount)--; } - pte_unmap(pte); + pte_unmap(original_pte); out_unlock: spin_unlock(&mm->page_table_lock); } -- cgit v1.1 From 558ac33e094f3a47c74a3a66b19cd3616f183184 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 24 May 2005 19:31:10 -0700 Subject: [PATCH] saa6752hs build fix For older gcc's. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa6752hs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index fe6abe3..1db0226 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -43,15 +43,15 @@ enum saa6752hs_videoformat { static const struct v4l2_format v4l2_format_table[] = { [SAA6752HS_VF_D1] = { - .fmt.pix.width = 720, .fmt.pix.height = 576 }, + .fmt = { .pix = { .width = 720, .height = 576 }, }, }, [SAA6752HS_VF_2_3_D1] = { - .fmt.pix.width = 480, .fmt.pix.height = 576 }, + .fmt = { .pix = { .width = 480, .height = 576 }, }, }, [SAA6752HS_VF_1_2_D1] = { - .fmt.pix.width = 352, .fmt.pix.height = 576 }, + .fmt = { .pix = { .width = 352, .height = 576 }, }, }, [SAA6752HS_VF_SIF] = { - .fmt.pix.width = 352, .fmt.pix.height = 288 }, + .fmt = { .pix = { .width = 352, .height = 288 }, }, }, [SAA6752HS_VF_UNKNOWN] = { - .fmt.pix.width = 0, .fmt.pix.height = 0}, + .fmt = { .pix = { .width = 0, .height = 0 }, }, }, }; struct saa6752hs_state { -- cgit v1.1 From d981289627a7e2d8ef62dfcaa11fb60da68f30c6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 24 May 2005 19:31:10 -0700 Subject: [PATCH] aic7xxx_osm build fix Fix a c99ism. Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index f90efa2..c13e563 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -659,8 +659,11 @@ ahc_linux_slave_alloc(struct scsi_device *device) ahc_lock(ahc, &flags); targ = ahc->platform_data->targets[target_offset]; if (targ == NULL) { - targ = ahc_linux_alloc_target(ahc, starget->channel, starget->id); - struct seeprom_config *sc = ahc->seep_config; + struct seeprom_config *sc; + + targ = ahc_linux_alloc_target(ahc, starget->channel, + starget->id); + sc = ahc->seep_config; if (targ == NULL) goto out; -- cgit v1.1 From 2a24ab628aa7b190be32f63dfb6d96f3fb61580a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 24 May 2005 20:31:20 -0700 Subject: Linux 2.6.12-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1bb0283..c11a317 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 12 -EXTRAVERSION =-rc4 +EXTRAVERSION =-rc5 NAME=Woozy Numbat # *DOCUMENTATION* -- cgit v1.1 From 8f80e5c911465743ccd3a328f992c7d8aaebf1e8 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 25 May 2005 13:41:26 +1000 Subject: [PATCH] ppc64: fix initialisation of gettimeofday calculations On PPC64, we keep track of when we need to update jiffies (and the variables used to calculate the time of day) based on the time base. If the time base frequence is sufficiently high compared to the processor clock frequency, then it is possible for the time of day variables to be corrupted at the time of the first decrementer interrupt we take. This became obvious on a legacy iSeries where the time base frequency is the same as the processor clock. This one line patch fixes the initialisation so that the time of day variables and the indicator we use to tell when updates are due are better synchronised. Signed-off-by: Stephen Rothwell Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/time.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 772a465..3d54745 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -515,6 +515,7 @@ void __init time_init(void) do_gtod.varp = &do_gtod.vars[0]; do_gtod.var_idx = 0; do_gtod.varp->tb_orig_stamp = tb_last_stamp; + get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy; do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; do_gtod.varp->tb_to_xs = tb_to_xs; -- cgit v1.1 From d0e8e29100c9866878d43bbb40ca17e8fe429851 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 25 May 2005 16:29:26 +1000 Subject: [PATCH] ppc64 iSeries: fix boot time setting For quite a while, there has existed a hypervisor bug on legacy iSeries which means that we do not get the boot time set in the kernel. This patch works around that bug. This was most noticable when the root partition needed to be checked at every boot as the kernel thought it was some time in 1905 until user mode reset the time correctly. Signed-off-by: Stephen Rothwell Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/mf.c | 85 ++++++++++++++++++++++++++++++++---------- arch/ppc64/kernel/rtc.c | 39 +------------------ include/asm-ppc64/iSeries/mf.h | 1 + 3 files changed, 67 insertions(+), 58 deletions(-) diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c index 1bd52ec..5aca7e8 100644 --- a/arch/ppc64/kernel/mf.c +++ b/arch/ppc64/kernel/mf.c @@ -1,7 +1,7 @@ /* * mf.c * Copyright (C) 2001 Troy D. Armstrong IBM Corporation - * Copyright (C) 2004 Stephen Rothwell IBM Corporation + * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation * * This modules exists as an interface between a Linux secondary partition * running on an iSeries and the primary partition's Virtual Service @@ -36,10 +36,12 @@ #include #include +#include #include #include #include #include +#include /* * This is the structure layout for the Machine Facilites LPAR event @@ -696,36 +698,23 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) complete(&rtc->com); } -int mf_get_rtc(struct rtc_time *tm) +static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) { - struct ce_msg_comp_data ce_complete; - struct rtc_time_data rtc_data; - int rc; - - memset(&ce_complete, 0, sizeof(ce_complete)); - memset(&rtc_data, 0, sizeof(rtc_data)); - init_completion(&rtc_data.com); - ce_complete.handler = &get_rtc_time_complete; - ce_complete.token = &rtc_data; - rc = signal_ce_msg_simple(0x40, &ce_complete); - if (rc) - return rc; - wait_for_completion(&rtc_data.com); tm->tm_wday = 0; tm->tm_yday = 0; tm->tm_isdst = 0; - if (rtc_data.rc) { + if (rc) { tm->tm_sec = 0; tm->tm_min = 0; tm->tm_hour = 0; tm->tm_mday = 15; tm->tm_mon = 5; tm->tm_year = 52; - return rtc_data.rc; + return rc; } - if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) || - (rtc_data.ce_msg.ce_msg[2] == 0xaf)) { + if ((ce_msg[2] == 0xa9) || + (ce_msg[2] == 0xaf)) { /* TOD clock is not set */ tm->tm_sec = 1; tm->tm_min = 1; @@ -736,7 +725,6 @@ int mf_get_rtc(struct rtc_time *tm) mf_set_rtc(tm); } { - u8 *ce_msg = rtc_data.ce_msg.ce_msg; u8 year = ce_msg[5]; u8 sec = ce_msg[6]; u8 min = ce_msg[7]; @@ -765,6 +753,63 @@ int mf_get_rtc(struct rtc_time *tm) return 0; } +int mf_get_rtc(struct rtc_time *tm) +{ + struct ce_msg_comp_data ce_complete; + struct rtc_time_data rtc_data; + int rc; + + memset(&ce_complete, 0, sizeof(ce_complete)); + memset(&rtc_data, 0, sizeof(rtc_data)); + init_completion(&rtc_data.com); + ce_complete.handler = &get_rtc_time_complete; + ce_complete.token = &rtc_data; + rc = signal_ce_msg_simple(0x40, &ce_complete); + if (rc) + return rc; + wait_for_completion(&rtc_data.com); + return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); +} + +struct boot_rtc_time_data { + int busy; + struct ce_msg_data ce_msg; + int rc; +}; + +static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) +{ + struct boot_rtc_time_data *rtc = token; + + memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg)); + rtc->rc = 0; + rtc->busy = 0; +} + +int mf_get_boot_rtc(struct rtc_time *tm) +{ + struct ce_msg_comp_data ce_complete; + struct boot_rtc_time_data rtc_data; + int rc; + + memset(&ce_complete, 0, sizeof(ce_complete)); + memset(&rtc_data, 0, sizeof(rtc_data)); + rtc_data.busy = 1; + ce_complete.handler = &get_boot_rtc_time_complete; + ce_complete.token = &rtc_data; + rc = signal_ce_msg_simple(0x40, &ce_complete); + if (rc) + return rc; + /* We need to poll here as we are not yet taking interrupts */ + while (rtc_data.busy) { + extern unsigned long lpevent_count; + struct ItLpQueue *lpq = get_paca()->lpqueue_ptr; + if (lpq && ItLpQueue_isLpIntPending(lpq)) + lpevent_count += ItLpQueue_process(lpq, NULL); + } + return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); +} + int mf_set_rtc(struct rtc_time *tm) { char ce_time[12]; diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c index 3e70b91..6798905 100644 --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c @@ -292,47 +292,10 @@ int iSeries_set_rtc_time(struct rtc_time *tm) void iSeries_get_boot_time(struct rtc_time *tm) { - unsigned long time; - static unsigned long lastsec = 1; - - u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart)); - u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1); - int year = 1970; - int year1 = ( dataWord1 >> 24 ) & 0x000000FF; - int year2 = ( dataWord1 >> 16 ) & 0x000000FF; - int sec = ( dataWord1 >> 8 ) & 0x000000FF; - int min = dataWord1 & 0x000000FF; - int hour = ( dataWord2 >> 24 ) & 0x000000FF; - int day = ( dataWord2 >> 8 ) & 0x000000FF; - int mon = dataWord2 & 0x000000FF; - if ( piranha_simulator ) return; - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year1); - BCD_TO_BIN(year2); - year = year1 * 100 + year2; - - time = mktime(year, mon, day, hour, min, sec); - time += ( jiffies / HZ ); - - /* Now THIS is a nasty hack! - * It ensures that the first two calls get different answers. - * That way the loop in init_time (time.c) will not think - * the clock is stuck. - */ - if ( lastsec ) { - time -= lastsec; - --lastsec; - } - - to_tm(time, tm); - tm->tm_year -= 1900; + mf_get_boot_rtc(tm); tm->tm_mon -= 1; } #endif diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h index 2e59a8e..db333e1 100644 --- a/include/asm-ppc64/iSeries/mf.h +++ b/include/asm-ppc64/iSeries/mf.h @@ -52,6 +52,7 @@ extern void mf_clear_src(void); extern void mf_init(void); extern int mf_get_rtc(struct rtc_time *tm); +extern int mf_get_boot_rtc(struct rtc_time *tm); extern int mf_set_rtc(struct rtc_time *tm); #endif /* _ASM_PPC64_ISERIES_MF_H */ -- cgit v1.1 From 0e15850200437c60b969025500e466383ec51ed8 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 25 May 2005 09:49:13 +0100 Subject: [PATCH] Speedtouch resync after lost signal. There's a bigger Speedtouch update coming your way after 2.6.12 but in the meantime, let's at least make it automatically resync if the DSL signal is lost. Signed-off-by: David Woodhouse Signed-off-by: Linus Torvalds --- drivers/usb/atm/speedtch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 233f922..2a1697b 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -386,6 +386,8 @@ static void speedtch_poll_status(struct speedtch_instance_data *instance) if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) { instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; printk(KERN_NOTICE "ADSL line is down\n"); + /* It'll never resync again unless we ask it to... */ + speedtch_start_synchro(instance); } break; -- cgit v1.1 From 384f1fcd2db8bc5a15f20f10793d8e1c82acd6c5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 25 May 2005 17:00:15 +0200 Subject: [PATCH] relax ide-cd dma restrictions This has been sitting for a while, and is causing lots of grief for people burning CDs. It relaxes the dma restriction for ide-cd, requiring only the length to be 32-byte aligned, address should be fine at normal double word alignment. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 33a020f..4f7ce70 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1933,7 +1933,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) /* * check if dma is safe */ - if ((rq->data_len & mask) || (addr & mask)) + if ((rq->data_len & 3) || (addr & mask)) info->dma = 0; } -- cgit v1.1 From 5daf05fbf73fc199e7a93a818e504856d07c5586 Mon Sep 17 00:00:00 2001 From: Gerd Knorr Date: Wed, 25 May 2005 12:31:26 -0700 Subject: [PATCH] v4l: bttv i2c oops fix Don't try to access the i2c bus if the register wasn't successful. Signed-off-by: Gerd Knorr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-i2c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index e3f477d..c2368bc 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -363,6 +363,9 @@ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, /* read EEPROM content */ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) { + memset(eedata, 0, 256); + if (0 != btv->i2c_rc) + return; btv->i2c_client.addr = addr >> 1; tveeprom_read(&btv->i2c_client, eedata, 256); } -- cgit v1.1 From dca79a046b93a81496bb30ca01177fb17f37ab72 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 25 May 2005 12:31:27 -0700 Subject: [PATCH] ipmi build fix It looks like the recent IPMI patches had some -mm-onlyisms. Signed-off-by: Neil Horman Cc: Corey Minyard Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 4bb9af7..6dc765d 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -520,7 +520,7 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" " interface. Other values will set the major device number" " to that value."); -static struct class *ipmi_class; +static struct class_simple *ipmi_class; static void ipmi_new_smi(int if_num) { @@ -534,7 +534,7 @@ static void ipmi_new_smi(int if_num) static void ipmi_smi_gone(int if_num) { - class_simple_device_remove(ipmi_class, MKDEV(ipmi_major, if_num)); + class_simple_device_remove(MKDEV(ipmi_major, if_num)); devfs_remove("ipmidev/%d", if_num); } -- cgit v1.1 From 4f60fdf613536402e3313c5019b3ae6060b2ae4a Mon Sep 17 00:00:00 2001 From: Alexander Nyberg Date: Wed, 25 May 2005 12:31:28 -0700 Subject: [PATCH] x86_64: CONFIG_BUG=n fixes Fixes some !CONFIG_BUG warnings: include/asm/mmu_context.h: I funktion `switch_mm': include/asm/mmu_context.h:57: varning: implicit declaration of function `out_of_line_bug' Signed-off-by: Alexander Nyberg Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/traps.c | 2 ++ arch/x86_64/kernel/x8664_ksyms.c | 3 ++- include/asm-x86_64/bug.h | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 65a37f5..3dfec8f 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -332,10 +332,12 @@ void handle_BUG(struct pt_regs *regs) printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line); } +#ifdef CONFIG_BUG void out_of_line_bug(void) { BUG(); } +#endif static DEFINE_SPINLOCK(die_lock); static int die_owner = -1; diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index a43dedb..68ec030 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -193,8 +193,9 @@ EXPORT_SYMBOL(smp_num_siblings); extern void do_softirq_thunk(void); EXPORT_SYMBOL(do_softirq_thunk); -void out_of_line_bug(void); +#ifdef CONFIG_BUG EXPORT_SYMBOL(out_of_line_bug); +#endif EXPORT_SYMBOL(init_level4_pgt); diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h index bdbf66e..3d2a666 100644 --- a/include/asm-x86_64/bug.h +++ b/include/asm-x86_64/bug.h @@ -21,6 +21,8 @@ struct bug_frame { asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \ "i"(__LINE__), "i" (__stringify(__FILE__))) void out_of_line_bug(void); +#else +static inline void out_of_line_bug(void) { } #endif #include -- cgit v1.1 From e4f50f003dc568f6fc3904d451c562007bd09640 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 25 May 2005 12:31:29 -0700 Subject: [PATCH] IB: allow NULL sa_query callbacks Check if a client passes a NULL callback into an SA query, and if so, never call back. This fixes an oops if someone unloads ib_ipoib and ib_sa in rapid succession. ib_ipoib does an MCMember delete with a NULL callback and 0 timeout on unload, which is usually fine since the delete completes successfully. However, if ib_sa is unloaded immediately afterwards, the delete will be canceled and ib_sa will try to call the (now already unloaded) ib_ipoib module back with the cancel completion, which triggers the oops. Signed-off-by: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/core/sa_query.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index d4233ee..276e1a5 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -587,7 +587,7 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, init_mad(query->sa_query.mad, agent); - query->sa_query.callback = ib_sa_path_rec_callback; + query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL; query->sa_query.release = ib_sa_path_rec_release; query->sa_query.port = port; query->sa_query.mad->mad_hdr.method = IB_MGMT_METHOD_GET; @@ -663,7 +663,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, init_mad(query->sa_query.mad, agent); - query->sa_query.callback = ib_sa_mcmember_rec_callback; + query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL; query->sa_query.release = ib_sa_mcmember_rec_release; query->sa_query.port = port; query->sa_query.mad->mad_hdr.method = method; @@ -698,20 +698,21 @@ static void send_handler(struct ib_mad_agent *agent, if (!query) return; - switch (mad_send_wc->status) { - case IB_WC_SUCCESS: - /* No callback -- already got recv */ - break; - case IB_WC_RESP_TIMEOUT_ERR: - query->callback(query, -ETIMEDOUT, NULL); - break; - case IB_WC_WR_FLUSH_ERR: - query->callback(query, -EINTR, NULL); - break; - default: - query->callback(query, -EIO, NULL); - break; - } + if (query->callback) + switch (mad_send_wc->status) { + case IB_WC_SUCCESS: + /* No callback -- already got recv */ + break; + case IB_WC_RESP_TIMEOUT_ERR: + query->callback(query, -ETIMEDOUT, NULL); + break; + case IB_WC_WR_FLUSH_ERR: + query->callback(query, -EINTR, NULL); + break; + default: + query->callback(query, -EIO, NULL); + break; + } dma_unmap_single(agent->device->dma_device, pci_unmap_addr(query, mapping), @@ -736,7 +737,7 @@ static void recv_handler(struct ib_mad_agent *mad_agent, query = idr_find(&query_idr, mad_recv_wc->wc->wr_id); spin_unlock_irqrestore(&idr_lock, flags); - if (query) { + if (query && query->callback) { if (mad_recv_wc->wc->status == IB_WC_SUCCESS) query->callback(query, mad_recv_wc->recv_buf.mad->mad_hdr.status ? -- cgit v1.1 From 561e148ea972a6e8d2c8f7aecc658b3a64f7a6de Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 25 May 2005 12:31:30 -0700 Subject: [PATCH] IB: fix potential ib_umad leak Free all unclaimed MAD receive buffers when userspace closes our file so we don't leak memory. Signed-off-by: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/core/user_mad.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 56b9c2f..9d912d6 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -499,6 +499,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp) static int ib_umad_close(struct inode *inode, struct file *filp) { struct ib_umad_file *file = filp->private_data; + struct ib_umad_packet *packet, *tmp; int i; for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) @@ -507,6 +508,9 @@ static int ib_umad_close(struct inode *inode, struct file *filp) ib_unregister_mad_agent(file->agent[i]); } + list_for_each_entry_safe(packet, tmp, &file->recv_list, list) + kfree(packet); + kfree(file); return 0; -- cgit v1.1 From 3bf4fb820d7382318d178bd765c20028415466ab Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 25 May 2005 12:31:31 -0700 Subject: [PATCH] IB: fix endianness of path record MTU field Make MTU field in SA PathRecord and MCMemberRecord a u8 rather than an enum to avoid complications with endianness. Signed-off-by: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/include/ib_sa.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/include/ib_sa.h b/drivers/infiniband/include/ib_sa.h index f4f7477..0022228 100644 --- a/drivers/infiniband/include/ib_sa.h +++ b/drivers/infiniband/include/ib_sa.h @@ -147,7 +147,7 @@ struct ib_sa_path_rec { /* reserved */ u8 sl; u8 mtu_selector; - enum ib_mtu mtu; + u8 mtu; u8 rate_selector; u8 rate; u8 packet_life_time_selector; @@ -180,7 +180,7 @@ struct ib_sa_mcmember_rec { u32 qkey; u16 mlid; u8 mtu_selector; - enum ib_mtu mtu; + u8 mtu; u8 traffic_class; u16 pkey; u8 rate_selector; -- cgit v1.1 From a8bacec09352b86bd389cc93a20008577fa14764 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Wed, 25 May 2005 12:31:34 -0700 Subject: [PATCH] Make sure therm_adt746x only handles known hardware This patch limits therm_adt746x to currently existing fan controllers in Apple laptops. It may avoid problems with future hardware. Signed-off-by: Colin Leroy Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/macintosh/therm_adt746x.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index e0ac63e..c7e84ab 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -545,6 +545,12 @@ thermostat_init(void) else return -ENODEV; + prop = (u32 *)get_property(np, "hwsensor-params-version", NULL); + printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop, + (*prop == 1)?"":"un"); + if (*prop != 1) + return -ENODEV; + prop = (u32 *)get_property(np, "reg", NULL); if (!prop) return -ENODEV; -- cgit v1.1 From d20c507f28dbee33086e8212b98f9ddc5372cd81 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Wed, 25 May 2005 12:31:35 -0700 Subject: [PATCH] therm_adt746x: show correct sensor locations This patch shows the correct locations of the heat sensors present in iBook and PowerBooks G4, instead of displaying them as being on CPU and GPU (which is not always the case). Signed-off-by: Colin Leroy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/macintosh/therm_adt746x.c | 119 ++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index c7e84ab..d09308f 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -39,15 +39,16 @@ #define MANUAL_MASK 0xe0 #define AUTO_MASK 0x20 -static u8 TEMP_REG[3] = {0x26, 0x25, 0x27}; /* local, cpu, gpu */ -static u8 LIMIT_REG[3] = {0x6b, 0x6a, 0x6c}; /* local, cpu, gpu */ +static u8 TEMP_REG[3] = {0x26, 0x25, 0x27}; /* local, sensor1, sensor2 */ +static u8 LIMIT_REG[3] = {0x6b, 0x6a, 0x6c}; /* local, sensor1, sensor2 */ static u8 MANUAL_MODE[2] = {0x5c, 0x5d}; static u8 REM_CONTROL[2] = {0x00, 0x40}; static u8 FAN_SPEED[2] = {0x28, 0x2a}; static u8 FAN_SPD_SET[2] = {0x30, 0x31}; -static u8 default_limits_local[3] = {70, 50, 70}; /* local, cpu, gpu */ -static u8 default_limits_chip[3] = {80, 65, 80}; /* local, cpu, gpu */ +static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */ +static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */ +static char *sensor_location[3] = {NULL, NULL, NULL}; static int limit_adjust = 0; static int fan_speed = -1; @@ -58,7 +59,7 @@ MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and " MODULE_LICENSE("GPL"); module_param(limit_adjust, int, 0644); -MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) " +MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 sensor1, 70 sensor2) " "by N degrees."); module_param(fan_speed, int, 0644); @@ -213,10 +214,10 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) if (th->last_speed[fan] != speed) { if (speed == -1) printk(KERN_DEBUG "adt746x: Setting speed to automatic " - "for %s fan.\n", fan?"GPU":"CPU"); + "for %s fan.\n", sensor_location[fan+1]); else printk(KERN_DEBUG "adt746x: Setting speed to %d " - "for %s fan.\n", speed, fan?"GPU":"CPU"); + "for %s fan.\n", speed, sensor_location[fan+1]); } else return; @@ -300,11 +301,11 @@ static void update_fans_speed (struct thermostat *th) printk(KERN_DEBUG "adt746x: setting fans speed to %d " "(limit exceeded by %d on %s) \n", new_speed, var, - fan_number?"GPU/pwr":"CPU"); + sensor_location[fan_number+1]); write_both_fan_speed(th, new_speed); th->last_var[fan_number] = var; } else if (var < -2) { - /* don't stop fan if GPU/power is cold and CPU is not + /* don't stop fan if sensor2 is cold and sensor1 is not * so cold (lastvar >= -1) */ if (i == 2 && lastvar < -1) { if (th->last_speed[fan_number] != 0) @@ -318,7 +319,7 @@ static void update_fans_speed (struct thermostat *th) if (started) return; /* we don't want to re-stop the fan - * if CPU is heating and GPU/power is not */ + * if sensor1 is heating and sensor2 is not */ } } @@ -353,7 +354,7 @@ static int monitor_task(void *arg) static void set_limit(struct thermostat *th, int i) { - /* Set CPU limit higher to avoid powerdowns */ + /* Set sensor1 limit higher to avoid powerdowns */ th->limits[i] = default_limits_chip[i] + limit_adjust; write_reg(th, LIMIT_REG[i], th->limits[i]); @@ -461,6 +462,12 @@ static ssize_t show_##name(struct device *dev, char *buf) \ return sprintf(buf, "%d\n", data); \ } +#define BUILD_SHOW_FUNC_STR(name, data) \ +static ssize_t show_##name(struct device *dev, char *buf) \ +{ \ + return sprintf(buf, "%s\n", data); \ +} + #define BUILD_SHOW_FUNC_FAN(name, data) \ static ssize_t show_##name(struct device *dev, char *buf) \ { \ @@ -476,7 +483,7 @@ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \ int val; \ int i; \ val = simple_strtol(buf, NULL, 10); \ - printk(KERN_INFO "Adjusting limits by %d°C\n", val); \ + printk(KERN_INFO "Adjusting limits by %d degrees\n", val); \ limit_adjust = val; \ for (i=0; i < 3; i++) \ set_limit(thermostat, i); \ @@ -495,35 +502,41 @@ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \ return n; \ } -BUILD_SHOW_FUNC_INT(cpu_temperature, (read_reg(thermostat, TEMP_REG[1]))) -BUILD_SHOW_FUNC_INT(gpu_temperature, (read_reg(thermostat, TEMP_REG[2]))) -BUILD_SHOW_FUNC_INT(cpu_limit, thermostat->limits[1]) -BUILD_SHOW_FUNC_INT(gpu_limit, thermostat->limits[2]) +BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(thermostat, TEMP_REG[1]))) +BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(thermostat, TEMP_REG[2]))) +BUILD_SHOW_FUNC_INT(sensor1_limit, thermostat->limits[1]) +BUILD_SHOW_FUNC_INT(sensor2_limit, thermostat->limits[2]) +BUILD_SHOW_FUNC_STR(sensor1_location, sensor_location[1]) +BUILD_SHOW_FUNC_STR(sensor2_location, sensor_location[2]) BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed) -BUILD_SHOW_FUNC_FAN(cpu_fan_speed, 0) -BUILD_SHOW_FUNC_FAN(gpu_fan_speed, 1) +BUILD_SHOW_FUNC_FAN(sensor1_fan_speed, 0) +BUILD_SHOW_FUNC_FAN(sensor2_fan_speed, 1) BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed) BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust) BUILD_STORE_FUNC_DEG(limit_adjust, thermostat) -static DEVICE_ATTR(cpu_temperature, S_IRUGO, - show_cpu_temperature,NULL); -static DEVICE_ATTR(gpu_temperature, S_IRUGO, - show_gpu_temperature,NULL); -static DEVICE_ATTR(cpu_limit, S_IRUGO, - show_cpu_limit, NULL); -static DEVICE_ATTR(gpu_limit, S_IRUGO, - show_gpu_limit, NULL); +static DEVICE_ATTR(sensor1_temperature, S_IRUGO, + show_sensor1_temperature,NULL); +static DEVICE_ATTR(sensor2_temperature, S_IRUGO, + show_sensor2_temperature,NULL); +static DEVICE_ATTR(sensor1_limit, S_IRUGO, + show_sensor1_limit, NULL); +static DEVICE_ATTR(sensor2_limit, S_IRUGO, + show_sensor2_limit, NULL); +static DEVICE_ATTR(sensor1_location, S_IRUGO, + show_sensor1_location, NULL); +static DEVICE_ATTR(sensor2_location, S_IRUGO, + show_sensor2_location, NULL); static DEVICE_ATTR(specified_fan_speed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, show_specified_fan_speed,store_specified_fan_speed); -static DEVICE_ATTR(cpu_fan_speed, S_IRUGO, - show_cpu_fan_speed, NULL); -static DEVICE_ATTR(gpu_fan_speed, S_IRUGO, - show_gpu_fan_speed, NULL); +static DEVICE_ATTR(sensor1_fan_speed, S_IRUGO, + show_sensor1_fan_speed, NULL); +static DEVICE_ATTR(sensor2_fan_speed, S_IRUGO, + show_sensor2_fan_speed, NULL); static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, show_limit_adjust, store_limit_adjust); @@ -534,6 +547,7 @@ thermostat_init(void) { struct device_node* np; u32 *prop; + int i = 0, offset = 0; np = of_find_node_by_name(NULL, "fan"); if (!np) @@ -569,6 +583,23 @@ thermostat_init(void) "limit_adjust: %d, fan_speed: %d\n", therm_bus, therm_address, limit_adjust, fan_speed); + if (get_property(np, "hwsensor-location", NULL)) { + for (i = 0; i < 3; i++) { + sensor_location[i] = get_property(np, + "hwsensor-location", NULL) + offset; + + if (sensor_location[i] == NULL) + sensor_location[i] = ""; + + printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]); + offset += strlen(sensor_location[i]) + 1; + } + } else { + sensor_location[0] = "?"; + sensor_location[1] = "?"; + sensor_location[2] = "?"; + } + of_dev = of_platform_device_create(np, "temperatures"); if (of_dev == NULL) { @@ -576,15 +607,17 @@ thermostat_init(void) return -ENODEV; } - device_create_file(&of_dev->dev, &dev_attr_cpu_temperature); - device_create_file(&of_dev->dev, &dev_attr_gpu_temperature); - device_create_file(&of_dev->dev, &dev_attr_cpu_limit); - device_create_file(&of_dev->dev, &dev_attr_gpu_limit); + device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature); + device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature); + device_create_file(&of_dev->dev, &dev_attr_sensor1_limit); + device_create_file(&of_dev->dev, &dev_attr_sensor2_limit); + device_create_file(&of_dev->dev, &dev_attr_sensor1_location); + device_create_file(&of_dev->dev, &dev_attr_sensor2_location); device_create_file(&of_dev->dev, &dev_attr_limit_adjust); device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed); - device_create_file(&of_dev->dev, &dev_attr_cpu_fan_speed); + device_create_file(&of_dev->dev, &dev_attr_sensor1_fan_speed); if(therm_type == ADT7460) - device_create_file(&of_dev->dev, &dev_attr_gpu_fan_speed); + device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); #ifndef CONFIG_I2C_KEYWEST request_module("i2c-keywest"); @@ -597,17 +630,19 @@ static void __exit thermostat_exit(void) { if (of_dev) { - device_remove_file(&of_dev->dev, &dev_attr_cpu_temperature); - device_remove_file(&of_dev->dev, &dev_attr_gpu_temperature); - device_remove_file(&of_dev->dev, &dev_attr_cpu_limit); - device_remove_file(&of_dev->dev, &dev_attr_gpu_limit); + device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature); + device_remove_file(&of_dev->dev, &dev_attr_sensor2_temperature); + device_remove_file(&of_dev->dev, &dev_attr_sensor1_limit); + device_remove_file(&of_dev->dev, &dev_attr_sensor2_limit); + device_remove_file(&of_dev->dev, &dev_attr_sensor1_location); + device_remove_file(&of_dev->dev, &dev_attr_sensor2_location); device_remove_file(&of_dev->dev, &dev_attr_limit_adjust); device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed); - device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed); + device_remove_file(&of_dev->dev, &dev_attr_sensor1_fan_speed); if(therm_type == ADT7460) device_remove_file(&of_dev->dev, - &dev_attr_gpu_fan_speed); + &dev_attr_sensor2_fan_speed); of_device_unregister(of_dev); } -- cgit v1.1 From 525a099771d348a25d12ef9c47aa8680c7317e35 Mon Sep 17 00:00:00 2001 From: NAKAMURA Kenta Date: Wed, 25 May 2005 19:28:38 -0400 Subject: [PATCH] sata_sil: new ID 1002:437A for ATI IXP400 --- drivers/scsi/sata_sil.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index f0489dc..2b2ff48 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -82,6 +82,7 @@ static struct pci_device_id sil_pci_tbl[] = { { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { } /* terminate list */ }; -- cgit v1.1 From 4c3a53d4108367f639e5e0fe9366dfd7679c5514 Mon Sep 17 00:00:00 2001 From: Francisco Javier Date: Wed, 25 May 2005 19:29:37 -0400 Subject: [PATCH] sata_promise: add PCI ID for FastTrak TX2200 2-ports --- drivers/scsi/sata_promise.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 19a13e3..c4e9e02 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -151,6 +151,8 @@ static struct ata_port_info pdc_port_info[] = { static struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, -- cgit v1.1 From 32529e0128923e42126b5d14e444c18295a452ba Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 26 May 2005 03:49:42 -0400 Subject: [PATCH] libata: Fix zero sg_dma_len() on 64-bit platform When testing ATAPI PIO data transfer on the ppc64 platform, __atapi_pio_bytes() got zero when sg_dma_len() is used. I checked the , the struct scatterlist is defined as: struct scatterlist { struct page *page; unsigned int offset; unsigned int length; /* For TCE support */ u32 dma_address; u32 dma_length; }; #define sg_dma_address(sg) ((sg)->dma_address) #define sg_dma_len(sg) ((sg)->dma_length) So, if the scatterlist is not DMA mapped, sg_dma_len() will return zero on ppc64. The same problem should occur on the x86-64 platform. On the i386 platform, sg_dma_len() returns sg->length, that's why the problem does not occur on an i386. Changes: - Use sg->length if the scatterlist is not DMA mapped (yet). Signed-off-by: Albert Lee --- drivers/scsi/libata-core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ee9b96d..63d3f70 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2071,7 +2071,7 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) sg = qc->sg; sg->page = virt_to_page(buf); sg->offset = (unsigned long) buf & ~PAGE_MASK; - sg_dma_len(sg) = buflen; + sg->length = buflen; } void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, @@ -2101,11 +2101,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) dma_addr_t dma_address; dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, - sg_dma_len(sg), dir); + sg->length, dir); if (dma_mapping_error(dma_address)) return -1; sg_dma_address(sg) = dma_address; + sg_dma_len(sg) = sg->length; DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg), qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); @@ -2310,7 +2311,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) qc->cursect++; qc->cursg_ofs++; - if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { + if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) { qc->cursg++; qc->cursg_ofs = 0; } @@ -2347,7 +2348,7 @@ next_page: page = nth_page(page, (offset >> PAGE_SHIFT)); offset %= PAGE_SIZE; - count = min(sg_dma_len(sg) - qc->cursg_ofs, bytes); + count = min(sg->length - qc->cursg_ofs, bytes); /* don't cross page boundaries */ count = min(count, (unsigned int)PAGE_SIZE - offset); @@ -2358,7 +2359,7 @@ next_page: qc->curbytes += count; qc->cursg_ofs += count; - if (qc->cursg_ofs == sg_dma_len(sg)) { + if (qc->cursg_ofs == sg->length) { qc->cursg++; qc->cursg_ofs = 0; } @@ -2371,7 +2372,7 @@ next_page: kunmap(page); if (bytes) { - if (qc->cursg_ofs < sg_dma_len(sg)) + if (qc->cursg_ofs < sg->length) goto next_page; goto next_sg; } -- cgit v1.1 From 8604affde9d4f52f04342d6a37c77d95fa167e7a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 May 2005 14:55:34 +0200 Subject: [PATCH] convert IDE device drivers to driver-model * add ide_bus_match() and export ide_bus_type * split ide_remove_driver_from_hwgroup() out of ide_unregister() * move device cleanup from ide_unregister() to drive_release_dev() * convert ide_driver_t->name to driver->name * convert ide_driver_t->{attach,cleanup} to driver->{probe,remove} * remove ide_driver_t->busy as ide_bus_type->subsys.rwsem protects against concurrent ->{probe,remove} calls * make ide_{un}register_driver() void as it cannot fail now * use driver_{un}register() directly, remove ide_{un}register_driver() * use device_register() instead of ata_attach(), remove ata_attach() * add proc_print_driver() and ide_drivers_show(), remove ide_drivers_op * fix ide_replace_subdriver() and move it to ide-proc.c * remove ide_driver_t->drives, ide_drives and drives_lock * remove ide_driver_t->drivers, drivers and drivers_lock * remove ide_drive_t->driver and DRIVER() macro Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 47 +++----- drivers/ide/ide-disk.c | 41 +++---- drivers/ide/ide-floppy.c | 42 +++---- drivers/ide/ide-probe.c | 47 +++++++- drivers/ide/ide-proc.c | 52 +++++++- drivers/ide/ide-tape.c | 51 +++----- drivers/ide/ide.c | 307 ++++------------------------------------------- drivers/scsi/ide-scsi.c | 58 ++++----- include/linux/ide.h | 20 +-- 9 files changed, 216 insertions(+), 449 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 4f7ce70..f0bd242 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3255,16 +3255,12 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) return capacity * sectors_per_frame; } -static -int ide_cdrom_cleanup(ide_drive_t *drive) +static int ide_cd_remove(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info = drive->driver_data; - if (ide_unregister_subdriver(drive)) { - printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n", - __FUNCTION__, drive->name); - return 1; - } + ide_unregister_subdriver(drive, info->driver); del_gendisk(info->disk); @@ -3297,7 +3293,7 @@ static void ide_cd_release(struct kref *kref) kfree(info); } -static int ide_cdrom_attach (ide_drive_t *drive); +static int ide_cd_probe(struct device *); #ifdef CONFIG_PROC_FS static int proc_idecd_read_capacity @@ -3320,19 +3316,20 @@ static ide_proc_entry_t idecd_proc[] = { static ide_driver_t ide_cdrom_driver = { .owner = THIS_MODULE, - .name = "ide-cdrom", + .gen_driver = { + .name = "ide-cdrom", + .bus = &ide_bus_type, + .probe = ide_cd_probe, + .remove = ide_cd_remove, + }, .version = IDECD_VERSION, .media = ide_cdrom, - .busy = 0, .supports_dsc_overlap = 1, - .cleanup = ide_cdrom_cleanup, .do_request = ide_do_rw_cdrom, .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, .proc = idecd_proc, - .attach = ide_cdrom_attach, - .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives), }; static int idecd_open(struct inode * inode, struct file * file) @@ -3418,8 +3415,9 @@ static char *ignore = NULL; module_param(ignore, charp, 0400); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -static int ide_cdrom_attach (ide_drive_t *drive) +static int ide_cd_probe(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info; struct gendisk *g; struct request_sense sense; @@ -3453,11 +3451,8 @@ static int ide_cdrom_attach (ide_drive_t *drive) ide_init_disk(g, drive); - if (ide_register_subdriver(drive, &ide_cdrom_driver)) { - printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", - drive->name); - goto out_put_disk; - } + ide_register_subdriver(drive, &ide_cdrom_driver); + memset(info, 0, sizeof (struct cdrom_info)); kref_init(&info->kref); @@ -3470,7 +3465,6 @@ static int ide_cdrom_attach (ide_drive_t *drive) drive->driver_data = info; - DRIVER(drive)->busy++; g->minors = 1; snprintf(g->devfs_name, sizeof(g->devfs_name), "%s/cd", drive->devfs_name); @@ -3478,8 +3472,7 @@ static int ide_cdrom_attach (ide_drive_t *drive) g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; - DRIVER(drive)->busy--; - ide_unregister_subdriver(drive); + ide_unregister_subdriver(drive, &ide_cdrom_driver); if (info->buffer != NULL) kfree(info->buffer); if (info->toc != NULL) @@ -3492,7 +3485,6 @@ static int ide_cdrom_attach (ide_drive_t *drive) drive->driver_data = NULL; goto failed; } - DRIVER(drive)->busy--; cdrom_read_toc(drive, &sense); g->fops = &idecd_ops; @@ -3500,23 +3492,20 @@ static int ide_cdrom_attach (ide_drive_t *drive) add_disk(g); return 0; -out_put_disk: - put_disk(g); out_free_cd: kfree(info); failed: - return 1; + return -ENODEV; } static void __exit ide_cdrom_exit(void) { - ide_unregister_driver(&ide_cdrom_driver); + driver_unregister(&ide_cdrom_driver.gen_driver); } static int ide_cdrom_init(void) { - ide_register_driver(&ide_cdrom_driver); - return 0; + return driver_register(&ide_cdrom_driver.gen_driver); } module_init(ide_cdrom_init); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 5d54f77..3302cd8 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t *drive) printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); } -static int idedisk_cleanup (ide_drive_t *drive) +static int ide_disk_remove(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = idkp->disk; ide_cacheflush_p(drive); - if (ide_unregister_subdriver(drive)) - return 1; + + ide_unregister_subdriver(drive, idkp->driver); + del_gendisk(g); ide_disk_put(idkp); @@ -1052,7 +1054,7 @@ static void ide_disk_release(struct kref *kref) kfree(idkp); } -static int idedisk_attach(ide_drive_t *drive); +static int ide_disk_probe(struct device *dev); static void ide_device_shutdown(struct device *dev) { @@ -1082,27 +1084,23 @@ static void ide_device_shutdown(struct device *dev) dev->bus->suspend(dev, PMSG_SUSPEND); } -/* - * IDE subdriver functions, registered with ide.c - */ static ide_driver_t idedisk_driver = { .owner = THIS_MODULE, .gen_driver = { + .name = "ide-disk", + .bus = &ide_bus_type, + .probe = ide_disk_probe, + .remove = ide_disk_remove, .shutdown = ide_device_shutdown, }, - .name = "ide-disk", .version = IDEDISK_VERSION, .media = ide_disk, - .busy = 0, .supports_dsc_overlap = 0, - .cleanup = idedisk_cleanup, .do_request = ide_do_rw_disk, .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, .proc = idedisk_proc, - .attach = idedisk_attach, - .drives = LIST_HEAD_INIT(idedisk_driver.drives), }; static int idedisk_open(struct inode *inode, struct file *filp) @@ -1199,8 +1197,9 @@ static struct block_device_operations idedisk_ops = { MODULE_DESCRIPTION("ATA DISK Driver"); -static int idedisk_attach(ide_drive_t *drive) +static int ide_disk_probe(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct ide_disk_obj *idkp; struct gendisk *g; @@ -1222,10 +1221,7 @@ static int idedisk_attach(ide_drive_t *drive) ide_init_disk(g, drive); - if (ide_register_subdriver(drive, &idedisk_driver)) { - printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); - goto out_put_disk; - } + ide_register_subdriver(drive, &idedisk_driver); memset(idkp, 0, sizeof(*idkp)); @@ -1239,7 +1235,6 @@ static int idedisk_attach(ide_drive_t *drive) drive->driver_data = idkp; - DRIVER(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", @@ -1247,7 +1242,7 @@ static int idedisk_attach(ide_drive_t *drive) drive->attach = 0; } else drive->attach = 1; - DRIVER(drive)->busy--; + g->minors = 1 << PARTN_BITS; strcpy(g->devfs_name, drive->devfs_name); g->driverfs_dev = &drive->gendev; @@ -1257,22 +1252,20 @@ static int idedisk_attach(ide_drive_t *drive) add_disk(g); return 0; -out_put_disk: - put_disk(g); out_free_idkp: kfree(idkp); failed: - return 1; + return -ENODEV; } static void __exit idedisk_exit (void) { - ide_unregister_driver(&idedisk_driver); + driver_unregister(&idedisk_driver.gen_driver); } static int idedisk_init (void) { - return ide_register_driver(&idedisk_driver); + return driver_register(&idedisk_driver.gen_driver); } module_init(idedisk_init); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 36c0b74..c949e98 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) idefloppy_add_settings(drive); } -static int idefloppy_cleanup (ide_drive_t *drive) +static int ide_floppy_remove(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; - if (ide_unregister_subdriver(drive)) - return 1; + ide_unregister_subdriver(drive, floppy->driver); del_gendisk(g); @@ -1916,26 +1916,24 @@ static ide_proc_entry_t idefloppy_proc[] = { #endif /* CONFIG_PROC_FS */ -static int idefloppy_attach(ide_drive_t *drive); +static int ide_floppy_probe(struct device *); -/* - * IDE subdriver functions, registered with ide.c - */ static ide_driver_t idefloppy_driver = { .owner = THIS_MODULE, - .name = "ide-floppy", + .gen_driver = { + .name = "ide-floppy", + .bus = &ide_bus_type, + .probe = ide_floppy_probe, + .remove = ide_floppy_remove, + }, .version = IDEFLOPPY_VERSION, .media = ide_floppy, - .busy = 0, .supports_dsc_overlap = 0, - .cleanup = idefloppy_cleanup, .do_request = idefloppy_do_request, .end_request = idefloppy_do_end_request, .error = __ide_error, .abort = __ide_abort, .proc = idefloppy_proc, - .attach = idefloppy_attach, - .drives = LIST_HEAD_INIT(idefloppy_driver.drives), }; static int idefloppy_open(struct inode *inode, struct file *filp) @@ -2122,8 +2120,9 @@ static struct block_device_operations idefloppy_ops = { .revalidate_disk= idefloppy_revalidate_disk }; -static int idefloppy_attach (ide_drive_t *drive) +static int ide_floppy_probe(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); idefloppy_floppy_t *floppy; struct gendisk *g; @@ -2152,10 +2151,7 @@ static int idefloppy_attach (ide_drive_t *drive) ide_init_disk(g, drive); - if (ide_register_subdriver(drive, &idefloppy_driver)) { - printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); - goto out_put_disk; - } + ide_register_subdriver(drive, &idefloppy_driver); memset(floppy, 0, sizeof(*floppy)); @@ -2169,9 +2165,8 @@ static int idefloppy_attach (ide_drive_t *drive) drive->driver_data = floppy; - DRIVER(drive)->busy++; idefloppy_setup (drive, floppy); - DRIVER(drive)->busy--; + g->minors = 1 << PARTN_BITS; g->driverfs_dev = &drive->gendev; strcpy(g->devfs_name, drive->devfs_name); @@ -2181,19 +2176,17 @@ static int idefloppy_attach (ide_drive_t *drive) add_disk(g); return 0; -out_put_disk: - put_disk(g); out_free_floppy: kfree(floppy); failed: - return 1; + return -ENODEV; } MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); static void __exit idefloppy_exit (void) { - ide_unregister_driver(&idefloppy_driver); + driver_unregister(&idefloppy_driver.gen_driver); } /* @@ -2202,8 +2195,7 @@ static void __exit idefloppy_exit (void) static int idefloppy_init (void) { printk("ide-floppy driver " IDEFLOPPY_VERSION "\n"); - ide_register_driver(&idefloppy_driver); - return 0; + return driver_register(&idefloppy_driver.gen_driver); } module_init(idefloppy_init); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 554473a..53b84a8 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -918,7 +919,7 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif) want them on default or a new "empty" class for hotplug reprobing ? */ if (drive->present) { - ata_attach(drive); + device_register(&drive->gendev); } } } @@ -1279,10 +1280,51 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_init_disk); +static void ide_remove_drive_from_hwgroup(ide_drive_t *drive) +{ + ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; + + if (drive == drive->next) { + /* special case: last drive from hwgroup. */ + BUG_ON(hwgroup->drive != drive); + hwgroup->drive = NULL; + } else { + ide_drive_t *walk; + + walk = hwgroup->drive; + while (walk->next != drive) + walk = walk->next; + walk->next = drive->next; + if (hwgroup->drive == drive) { + hwgroup->drive = drive->next; + hwgroup->hwif = hwgroup->drive->hwif; + } + } + BUG_ON(hwgroup->drive == drive); +} + static void drive_release_dev (struct device *dev) { ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); + spin_lock_irq(&ide_lock); + if (drive->devfs_name[0] != '\0') { + devfs_remove(drive->devfs_name); + drive->devfs_name[0] = '\0'; + } + ide_remove_drive_from_hwgroup(drive); + if (drive->id != NULL) { + kfree(drive->id); + drive->id = NULL; + } + drive->present = 0; + /* Messed up locking ... */ + spin_unlock_irq(&ide_lock); + blk_cleanup_queue(drive->queue); + spin_lock_irq(&ide_lock); + drive->queue = NULL; + spin_unlock_irq(&ide_lock); + up(&drive->gendev_rel_sem); } @@ -1306,7 +1348,6 @@ static void init_gendisk (ide_hwif_t *hwif) drive->gendev.driver_data = drive; drive->gendev.release = drive_release_dev; if (drive->present) { - device_register(&drive->gendev); sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d", (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, @@ -1412,7 +1453,7 @@ int ideprobe_init (void) hwif->chipset = ide_generic; for (unit = 0; unit < MAX_DRIVES; ++unit) if (hwif->drives[unit].present) - ata_attach(&hwif->drives[unit]); + device_register(&hwif->drives[unit].gendev); } } return 0; diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 4b1e43b..4063d2c 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -307,17 +307,41 @@ static int proc_ide_read_driver (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; - ide_driver_t *driver = drive->driver; + struct device *dev = &drive->gendev; + ide_driver_t *ide_drv; int len; - if (driver) { + down_read(&dev->bus->subsys.rwsem); + if (dev->driver) { + ide_drv = container_of(dev->driver, ide_driver_t, gen_driver); len = sprintf(page, "%s version %s\n", - driver->name, driver->version); + dev->driver->name, ide_drv->version); } else len = sprintf(page, "ide-default version 0.9.newide\n"); + up_read(&dev->bus->subsys.rwsem); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) +{ + struct device *dev = &drive->gendev; + int ret = 1; + + down_write(&dev->bus->subsys.rwsem); + device_release_driver(dev); + /* FIXME: device can still be in use by previous driver */ + strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); + device_attach(dev); + drive->driver_req[0] = 0; + if (dev->driver == NULL) + device_attach(dev); + if (dev->driver && !strcmp(dev->driver->name, driver)) + ret = 0; + up_write(&dev->bus->subsys.rwsem); + + return ret; +} + static int proc_ide_write_driver (struct file *file, const char __user *buffer, unsigned long count, void *data) { @@ -488,16 +512,32 @@ void destroy_proc_ide_interface(ide_hwif_t *hwif) } } -extern struct seq_operations ide_drivers_op; +static int proc_print_driver(struct device_driver *drv, void *data) +{ + ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver); + struct seq_file *s = data; + + seq_printf(s, "%s version %s\n", drv->name, ide_drv->version); + + return 0; +} + +static int ide_drivers_show(struct seq_file *s, void *p) +{ + bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver); + return 0; +} + static int ide_drivers_open(struct inode *inode, struct file *file) { - return seq_open(file, &ide_drivers_op); + return single_open(file, &ide_drivers_show, NULL); } + static struct file_operations ide_drivers_operations = { .open = ide_drivers_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; void proc_ide_create(void) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 4825448..5a3dc46 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4681,21 +4681,12 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) idetape_add_settings(drive); } -static int idetape_cleanup (ide_drive_t *drive) +static int ide_tape_remove(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); - if (test_bit(IDETAPE_BUSY, &tape->flags) || drive->usage || - tape->first_stage != NULL || tape->merge_stage_size) { - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } - spin_unlock_irqrestore(&ide_lock, flags); - DRIVER(drive)->busy = 0; - (void) ide_unregister_subdriver(drive); + ide_unregister_subdriver(drive, tape->driver); ide_unregister_region(tape->disk); @@ -4710,6 +4701,8 @@ static void ide_tape_release(struct kref *kref) ide_drive_t *drive = tape->drive; struct gendisk *g = tape->disk; + BUG_ON(tape->first_stage != NULL || tape->merge_stage_size); + drive->dsc_overlap = 0; drive->driver_data = NULL; devfs_remove("%s/mt", drive->devfs_name); @@ -4747,26 +4740,24 @@ static ide_proc_entry_t idetape_proc[] = { #endif -static int idetape_attach(ide_drive_t *drive); +static int ide_tape_probe(struct device *); -/* - * IDE subdriver functions, registered with ide.c - */ static ide_driver_t idetape_driver = { .owner = THIS_MODULE, - .name = "ide-tape", + .gen_driver = { + .name = "ide-tape", + .bus = &ide_bus_type, + .probe = ide_tape_probe, + .remove = ide_tape_remove, + }, .version = IDETAPE_VERSION, .media = ide_tape, - .busy = 1, .supports_dsc_overlap = 1, - .cleanup = idetape_cleanup, .do_request = idetape_do_request, .end_request = idetape_end_request, .error = __ide_error, .abort = __ide_abort, .proc = idetape_proc, - .attach = idetape_attach, - .drives = LIST_HEAD_INIT(idetape_driver.drives), }; /* @@ -4829,8 +4820,9 @@ static struct block_device_operations idetape_block_ops = { .ioctl = idetape_ioctl, }; -static int idetape_attach (ide_drive_t *drive) +static int ide_tape_probe(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); idetape_tape_t *tape; struct gendisk *g; int minor; @@ -4865,10 +4857,7 @@ static int idetape_attach (ide_drive_t *drive) ide_init_disk(g, drive); - if (ide_register_subdriver(drive, &idetape_driver)) { - printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); - goto out_put_disk; - } + ide_register_subdriver(drive, &idetape_driver); memset(tape, 0, sizeof(*tape)); @@ -4902,12 +4891,11 @@ static int idetape_attach (ide_drive_t *drive) ide_register_region(g); return 0; -out_put_disk: - put_disk(g); + out_free_tape: kfree(tape); failed: - return 1; + return -ENODEV; } MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver"); @@ -4915,7 +4903,7 @@ MODULE_LICENSE("GPL"); static void __exit idetape_exit (void) { - ide_unregister_driver(&idetape_driver); + driver_unregister(&idetape_driver.gen_driver); unregister_chrdev(IDETAPE_MAJOR, "ht"); } @@ -4928,8 +4916,7 @@ static int idetape_init (void) printk(KERN_ERR "ide-tape: Failed to register character device interface\n"); return -EBUSY; } - ide_register_driver(&idetape_driver); - return 0; + return driver_register(&idetape_driver.gen_driver); } module_init(idetape_init); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 973dec7..dae1bd5 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -196,8 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ EXPORT_SYMBOL(ide_hwifs); -static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives); - /* * Do not even *think* about calling this! */ @@ -358,54 +356,6 @@ static int ide_system_bus_speed(void) return system_bus_speed; } -/* - * drives_lock protects the list of drives, drivers_lock the - * list of drivers. Currently nobody takes both at once. - */ - -static DEFINE_SPINLOCK(drives_lock); -static DEFINE_SPINLOCK(drivers_lock); -static LIST_HEAD(drivers); - -/* Iterator for the driver list. */ - -static void *m_start(struct seq_file *m, loff_t *pos) -{ - struct list_head *p; - loff_t l = *pos; - spin_lock(&drivers_lock); - list_for_each(p, &drivers) - if (!l--) - return list_entry(p, ide_driver_t, drivers); - return NULL; -} - -static void *m_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct list_head *p = ((ide_driver_t *)v)->drivers.next; - (*pos)++; - return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers); -} - -static void m_stop(struct seq_file *m, void *v) -{ - spin_unlock(&drivers_lock); -} - -static int show_driver(struct seq_file *m, void *v) -{ - ide_driver_t *driver = v; - seq_printf(m, "%s version %s\n", driver->name, driver->version); - return 0; -} - -struct seq_operations ide_drivers_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_driver -}; - #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_ide_root; #endif @@ -630,7 +580,7 @@ void ide_unregister(unsigned int index) ide_hwif_t *hwif, *g; static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */ ide_hwgroup_t *hwgroup; - int irq_count = 0, unit, i; + int irq_count = 0, unit; BUG_ON(index >= MAX_HWIFS); @@ -643,23 +593,22 @@ void ide_unregister(unsigned int index) goto abort; for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; - if (!drive->present) + if (!drive->present) { + if (drive->devfs_name[0] != '\0') { + devfs_remove(drive->devfs_name); + drive->devfs_name[0] = '\0'; + } continue; - if (drive->usage || DRIVER(drive)->busy) - goto abort; - drive->dead = 1; + } + spin_unlock_irq(&ide_lock); + device_unregister(&drive->gendev); + down(&drive->gendev_rel_sem); + spin_lock_irq(&ide_lock); } hwif->present = 0; spin_unlock_irq(&ide_lock); - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - DRIVER(drive)->cleanup(drive); - } - destroy_proc_ide_interface(hwif); hwgroup = hwif->hwgroup; @@ -687,44 +636,6 @@ void ide_unregister(unsigned int index) * Remove us from the hwgroup, and free * the hwgroup if we were the only member */ - for (i = 0; i < MAX_DRIVES; ++i) { - drive = &hwif->drives[i]; - if (drive->devfs_name[0] != '\0') { - devfs_remove(drive->devfs_name); - drive->devfs_name[0] = '\0'; - } - if (!drive->present) - continue; - if (drive == drive->next) { - /* special case: last drive from hwgroup. */ - BUG_ON(hwgroup->drive != drive); - hwgroup->drive = NULL; - } else { - ide_drive_t *walk; - - walk = hwgroup->drive; - while (walk->next != drive) - walk = walk->next; - walk->next = drive->next; - if (hwgroup->drive == drive) { - hwgroup->drive = drive->next; - hwgroup->hwif = HWIF(hwgroup->drive); - } - } - BUG_ON(hwgroup->drive == drive); - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } - drive->present = 0; - /* Messed up locking ... */ - spin_unlock_irq(&ide_lock); - blk_cleanup_queue(drive->queue); - device_unregister(&drive->gendev); - down(&drive->gendev_rel_sem); - spin_lock_irq(&ide_lock); - drive->queue = NULL; - } if (hwif->next == hwif) { BUG_ON(hwgroup->hwif != hwif); kfree(hwgroup); @@ -1304,73 +1215,6 @@ int system_bus_clock (void) EXPORT_SYMBOL(system_bus_clock); -/* - * Locking is badly broken here - since way back. That sucker is - * root-only, but that's not an excuse... The real question is what - * exclusion rules do we want here. - */ -int ide_replace_subdriver (ide_drive_t *drive, const char *driver) -{ - if (!drive->present || drive->usage || drive->dead) - goto abort; - if (DRIVER(drive)->cleanup(drive)) - goto abort; - strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); - if (ata_attach(drive)) { - spin_lock(&drives_lock); - list_del_init(&drive->list); - spin_unlock(&drives_lock); - drive->driver_req[0] = 0; - ata_attach(drive); - } else { - drive->driver_req[0] = 0; - } - if (drive->driver && !strcmp(drive->driver->name, driver)) - return 0; -abort: - return 1; -} - -/** - * ata_attach - attach an ATA/ATAPI device - * @drive: drive to attach - * - * Takes a drive that is as yet not assigned to any midlayer IDE - * driver (or is assigned to the default driver) and figures out - * which driver would like to own it. If nobody claims the drive - * then it is automatically attached to the default driver used for - * unclaimed objects. - * - * A return of zero indicates attachment to a driver, of one - * attachment to the default driver. - * - * Takes drivers_lock. - */ - -int ata_attach(ide_drive_t *drive) -{ - struct list_head *p; - spin_lock(&drivers_lock); - list_for_each(p, &drivers) { - ide_driver_t *driver = list_entry(p, ide_driver_t, drivers); - if (!try_module_get(driver->owner)) - continue; - spin_unlock(&drivers_lock); - if (driver->attach(drive) == 0) { - module_put(driver->owner); - drive->gendev.driver = &driver->gen_driver; - return 0; - } - spin_lock(&drivers_lock); - module_put(driver->owner); - } - drive->gendev.driver = NULL; - spin_unlock(&drivers_lock); - if (ide_register_subdriver(drive, NULL)) - panic("ide: default attach failed"); - return 1; -} - static int generic_ide_suspend(struct device *dev, pm_message_t state) { ide_drive_t *drive = dev->driver_data; @@ -2013,27 +1857,11 @@ static void __init probe_for_hwifs (void) #endif } -int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) +void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); - if (!drive->present || drive->driver != NULL || - drive->usage || drive->dead) { - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } - drive->driver = driver; - spin_unlock_irqrestore(&ide_lock, flags); - spin_lock(&drives_lock); - list_add_tail(&drive->list, driver ? &driver->drives : &ide_drives); - spin_unlock(&drives_lock); -// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name); #ifdef CONFIG_PROC_FS - if (driver) - ide_add_proc_entries(drive->proc, driver->proc, drive); + ide_add_proc_entries(drive->proc, driver->proc, drive); #endif - return 0; } EXPORT_SYMBOL(ide_register_subdriver); @@ -2041,136 +1869,51 @@ EXPORT_SYMBOL(ide_register_subdriver); /** * ide_unregister_subdriver - disconnect drive from driver * @drive: drive to unplug + * @driver: driver * * Disconnect a drive from the driver it was attached to and then * clean up the various proc files and other objects attached to it. * - * Takes ide_setting_sem, ide_lock and drives_lock. + * Takes ide_setting_sem and ide_lock. * Caller must hold none of the locks. - * - * No locking versus subdriver unload because we are moving to the - * default driver anyway. Wants double checking. */ -int ide_unregister_subdriver (ide_drive_t *drive) +void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; down(&ide_setting_sem); spin_lock_irqsave(&ide_lock, flags); - if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return 1; - } #ifdef CONFIG_PROC_FS - ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); + ide_remove_proc_entries(drive->proc, driver->proc); #endif auto_remove_settings(drive); - drive->driver = NULL; spin_unlock_irqrestore(&ide_lock, flags); up(&ide_setting_sem); - spin_lock(&drives_lock); - list_del_init(&drive->list); - spin_unlock(&drives_lock); - /* drive will be added to &ide_drives in ata_attach() */ - return 0; } EXPORT_SYMBOL(ide_unregister_subdriver); -static int ide_drive_remove(struct device * dev) -{ - ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); - DRIVER(drive)->cleanup(drive); - return 0; -} - -/** - * ide_register_driver - register IDE device driver - * @driver: the IDE device driver - * - * Register a new device driver and then scan the devices - * on the IDE bus in case any should be attached to the - * driver we have just registered. If so attach them. - * - * Takes drivers_lock and drives_lock. - */ - -int ide_register_driver(ide_driver_t *driver) -{ - struct list_head list; - struct list_head *list_loop; - struct list_head *tmp_storage; - - spin_lock(&drivers_lock); - list_add(&driver->drivers, &drivers); - spin_unlock(&drivers_lock); - - INIT_LIST_HEAD(&list); - spin_lock(&drives_lock); - list_splice_init(&ide_drives, &list); - spin_unlock(&drives_lock); - - list_for_each_safe(list_loop, tmp_storage, &list) { - ide_drive_t *drive = container_of(list_loop, ide_drive_t, list); - list_del_init(&drive->list); - if (drive->present) - ata_attach(drive); - } - driver->gen_driver.name = (char *) driver->name; - driver->gen_driver.bus = &ide_bus_type; - driver->gen_driver.remove = ide_drive_remove; - return driver_register(&driver->gen_driver); -} - -EXPORT_SYMBOL(ide_register_driver); - -/** - * ide_unregister_driver - unregister IDE device driver - * @driver: the IDE device driver - * - * Called when a driver module is being unloaded. We reattach any - * devices to whatever driver claims them next (typically the default - * driver). - * - * Takes drivers_lock and called functions will take ide_setting_sem. - */ - -void ide_unregister_driver(ide_driver_t *driver) -{ - ide_drive_t *drive; - - spin_lock(&drivers_lock); - list_del(&driver->drivers); - spin_unlock(&drivers_lock); - - driver_unregister(&driver->gen_driver); - - while(!list_empty(&driver->drives)) { - drive = list_entry(driver->drives.next, ide_drive_t, list); - if (driver->cleanup(drive)) { - printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); - BUG(); - } - ata_attach(drive); - } -} - -EXPORT_SYMBOL(ide_unregister_driver); - /* * Probe module */ EXPORT_SYMBOL(ide_lock); +static int ide_bus_match(struct device *dev, struct device_driver *drv) +{ + return 1; +} + struct bus_type ide_bus_type = { .name = "ide", + .match = ide_bus_match, .suspend = generic_ide_suspend, .resume = generic_ide_resume, }; +EXPORT_SYMBOL_GPL(ide_bus_type); + /* * This is gets invoked once during initialization, to set *everything* up */ diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 2e2486b..d80c4c9 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -713,7 +713,6 @@ static void idescsi_add_settings(ide_drive_t *drive) */ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) { - DRIVER(drive)->busy++; if (drive->id && (drive->id->config & 0x0060) == 0x20) set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); set_bit(IDESCSI_TRANSFORM, &scsi->transform); @@ -722,17 +721,16 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) set_bit(IDESCSI_LOG_CMD, &scsi->log); #endif /* IDESCSI_DEBUG_LOG */ idescsi_add_settings(drive); - DRIVER(drive)->busy--; } -static int idescsi_cleanup (ide_drive_t *drive) +static int ide_scsi_remove(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct Scsi_Host *scsihost = drive->driver_data; struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct gendisk *g = scsi->disk; - if (ide_unregister_subdriver(drive)) - return 1; + ide_unregister_subdriver(drive, scsi->driver); ide_unregister_region(g); @@ -746,7 +744,7 @@ static int idescsi_cleanup (ide_drive_t *drive) return 0; } -static int idescsi_attach(ide_drive_t *drive); +static int ide_scsi_probe(struct device *); #ifdef CONFIG_PROC_FS static ide_proc_entry_t idescsi_proc[] = { @@ -757,24 +755,22 @@ static ide_proc_entry_t idescsi_proc[] = { # define idescsi_proc NULL #endif -/* - * IDE subdriver functions, registered with ide.c - */ static ide_driver_t idescsi_driver = { .owner = THIS_MODULE, - .name = "ide-scsi", + .gen_driver = { + .name = "ide-scsi", + .bus = &ide_bus_type, + .probe = ide_scsi_probe, + .remove = ide_scsi_remove, + }, .version = IDESCSI_VERSION, .media = ide_scsi, - .busy = 0, .supports_dsc_overlap = 0, .proc = idescsi_proc, - .attach = idescsi_attach, - .cleanup = idescsi_cleanup, .do_request = idescsi_do_request, .end_request = idescsi_end_request, .error = idescsi_atapi_error, .abort = idescsi_atapi_abort, - .drives = LIST_HEAD_INIT(idescsi_driver.drives), }; static int idescsi_ide_open(struct inode *inode, struct file *filp) @@ -821,8 +817,6 @@ static struct block_device_operations idescsi_ops = { .ioctl = idescsi_ide_ioctl, }; -static int idescsi_attach(ide_drive_t *drive); - static int idescsi_slave_configure(struct scsi_device * sdp) { /* Configure detected device */ @@ -1095,8 +1089,9 @@ static struct scsi_host_template idescsi_template = { .proc_name = "ide-scsi", }; -static int idescsi_attach(ide_drive_t *drive) +static int ide_scsi_probe(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); idescsi_scsi_t *idescsi; struct Scsi_Host *host; struct gendisk *g; @@ -1112,7 +1107,7 @@ static int idescsi_attach(ide_drive_t *drive) !drive->present || drive->media == ide_disk || !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) - return 1; + return -ENODEV; g = alloc_disk(1 << PARTN_BITS); if (!g) @@ -1138,20 +1133,19 @@ static int idescsi_attach(ide_drive_t *drive) idescsi->host = host; idescsi->disk = g; g->private_data = &idescsi->driver; - err = ide_register_subdriver(drive, &idescsi_driver); + ide_register_subdriver(drive, &idescsi_driver); + err = 0; + idescsi_setup(drive, idescsi); + g->fops = &idescsi_ops; + ide_register_region(g); + err = scsi_add_host(host, &drive->gendev); if (!err) { - idescsi_setup (drive, idescsi); - g->fops = &idescsi_ops; - ide_register_region(g); - err = scsi_add_host(host, &drive->gendev); - if (!err) { - scsi_scan_host(host); - return 0; - } - /* fall through on error */ - ide_unregister_region(g); - ide_unregister_subdriver(drive); + scsi_scan_host(host); + return 0; } + /* fall through on error */ + ide_unregister_region(g); + ide_unregister_subdriver(drive, &idescsi_driver); put_disk(g); out_host_put: @@ -1161,12 +1155,12 @@ out_host_put: static int __init init_idescsi_module(void) { - return ide_register_driver(&idescsi_driver); + return driver_register(&idescsi_driver.gen_driver); } static void __exit exit_idescsi_module(void) { - ide_unregister_driver(&idescsi_driver); + driver_unregister(&idescsi_driver.gen_driver); } module_init(init_idescsi_module); diff --git a/include/linux/ide.h b/include/linux/ide.h index 9cfc099..336d6e5 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -664,7 +664,6 @@ typedef struct ide_drive_s { struct request *rq; /* current request */ struct ide_drive_s *next; /* circular list of hwgroup drives */ - struct ide_driver_s *driver;/* (ide_driver_t *) */ void *driver_data; /* extra driver data */ struct hd_driveid *id; /* drive model identification info */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ @@ -758,6 +757,8 @@ typedef struct ide_drive_s { struct semaphore gendev_rel_sem; /* to deal with device release() */ } ide_drive_t; +#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev) + #define IDE_CHIPSET_PCI_MASK \ ((1<> (c)) & 1) @@ -1086,28 +1087,20 @@ enum { */ typedef struct ide_driver_s { struct module *owner; - const char *name; const char *version; u8 media; - unsigned busy : 1; unsigned supports_dsc_overlap : 1; - int (*cleanup)(ide_drive_t *); ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t); int (*end_request)(ide_drive_t *, int, int); ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8); ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); ide_proc_entry_t *proc; - int (*attach)(ide_drive_t *); void (*ata_prebuilder)(ide_drive_t *); void (*atapi_prebuilder)(ide_drive_t *); struct device_driver gen_driver; - struct list_head drives; - struct list_head drivers; } ide_driver_t; -#define DRIVER(drive) ((drive)->driver) - int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); /* @@ -1328,8 +1321,6 @@ extern void ide_init_subdrivers(void); void ide_init_disk(struct gendisk *, ide_drive_t *); -extern int ata_attach(ide_drive_t *); - extern int ideprobe_init(void); extern void ide_scan_pcibus(int scan_direction) __init; @@ -1342,11 +1333,8 @@ extern void default_hwif_iops(ide_hwif_t *); extern void default_hwif_mmiops(ide_hwif_t *); extern void default_hwif_transport(ide_hwif_t *); -int ide_register_driver(ide_driver_t *driver); -void ide_unregister_driver(ide_driver_t *driver); -int ide_register_subdriver(ide_drive_t *, ide_driver_t *); -int ide_unregister_subdriver (ide_drive_t *drive); -int ide_replace_subdriver(ide_drive_t *drive, const char *driver); +void ide_register_subdriver(ide_drive_t *, ide_driver_t *); +void ide_unregister_subdriver(ide_drive_t *, ide_driver_t *); #define ON_BOARD 1 #define NEVER_BOARD 0 -- cgit v1.1 From 41bb4c43b34bcde7eb62cf19acdcf9f2eb13801d Mon Sep 17 00:00:00 2001 From: Stuart Hayes Date: Thu, 26 May 2005 15:38:45 +0200 Subject: [PATCH] ide-scsi: kmap scatter/gather before doing PIO From: Stuart Hayes The system can panic with a null pointer dereference using ide-scsi if PIO is being done on scatter gather pages that are in high memory, because page_address() returns 0. We are actually seeing this using a tape drive. This patch will kmap_atomic() the pages before performing PIO. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/scsi/ide-scsi.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index d80c4c9..83f062e 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -179,8 +179,18 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne return; } count = min(pc->sg->length - pc->b_count, bcount); - buf = page_address(pc->sg->page) + pc->sg->offset; - drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); + if (PageHighMem(pc->sg->page)) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset; + drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); + kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(pc->sg->page) + pc->sg->offset; + drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); + } bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; @@ -201,8 +211,18 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign return; } count = min(pc->sg->length - pc->b_count, bcount); - buf = page_address(pc->sg->page) + pc->sg->offset; - drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); + if (PageHighMem(pc->sg->page)) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset; + drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); + kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(pc->sg->page) + pc->sg->offset; + drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); + } bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; -- cgit v1.1 From 284e423811495f632a7a334b2b93caba07d4f778 Mon Sep 17 00:00:00 2001 From: Marcello Maggioni Date: Thu, 26 May 2005 15:47:35 +0200 Subject: [PATCH] timeout at boottime with NEC3500A (and possibly others) when inserted a CD in it From: Marcello Maggioni Problem: Some drives (NEC 3500, TDK 1616N, Mad-dog MD-16XDVD9, RICOH MP5163DA, Memorex DVD9 drive and IO-DATA's too for sure), if a CD/DVD is inserted into the tray when the system is booted and if before the OS bootup the BIOS checked for the presence of a bootable CD/DVD into the drive, during the IDE probe phase the drive may result busy and remain so for the next 25/30 seconds . This cause the drive to be skipped during the booting phase and not begin usable until the next reboot (if the reboot goes well and the drive doesn't timeout again). Solution: Rising the timeout time from 10 seconds to 35 seconds (during these 35 seconds every drive should wake up for sure according to the tests I've done). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 53b84a8..5d876f5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -697,13 +697,13 @@ static int wait_hwif_ready(ide_hwif_t *hwif) SELECT_DRIVE(&hwif->drives[0]); hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); mdelay(2); - rc = ide_wait_not_busy(hwif, 10000); + rc = ide_wait_not_busy(hwif, 35000); if (rc) return rc; SELECT_DRIVE(&hwif->drives[1]); hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); mdelay(2); - rc = ide_wait_not_busy(hwif, 10000); + rc = ide_wait_not_busy(hwif, 35000); /* Exit function with master reselected (let's be sane) */ SELECT_DRIVE(&hwif->drives[0]); -- cgit v1.1 From d11cf326bd5e785cc5a3f5a3d3f4e3a5522f4fb7 Mon Sep 17 00:00:00 2001 From: Zhang Yanmin Date: Sun, 22 May 2005 17:47:00 -0700 Subject: [IA64] sys_mmap doesn't follow posix.1 when parameter len=0 In IA64 kernel, sys_mmap calls do_mmap2 and do_mmap2 returns addr if len=0, which means the mmap sys call succeeds. Posix.1 says: The mmap() function shall fail if: [EINVAL] The value of len is zero. Here is a patch to fix it. Signed-off-by: Zhang Yanmin Acked-by: David Mosberger Signed-off-by: Tony Luck --- arch/ia64/kernel/sys_ia64.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index a8cf6d8..770fab3 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -182,13 +182,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un } } - /* - * A zero mmap always succeeds in Linux, independent of whether or not the - * remaining arguments are valid. - */ - if (len == 0) - goto out; - /* Careful about overflows.. */ len = PAGE_ALIGN(len); if (!len || len > TASK_SIZE) { -- cgit v1.1 From 0afb51e72855971dba83b3c6b70c547c2d1161fd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 May 2005 12:53:49 -0700 Subject: [PKT_SCHED]: netem: reinsert for duplication Handle duplication of packets in netem by re-inserting at top of qdisc tree. This avoid problems with qlen accounting with nested qdisc. This recursion requires no additional locking but will potentially increase stack depth. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/sch_netem.c | 53 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index e0c9fbe..5c0f0c2 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -203,42 +203,47 @@ static int netem_run(struct Qdisc *sch) return 0; } +/* + * Insert one skb into qdisc. + * Note: parent depends on return value to account for queue length. + * NET_XMIT_DROP: queue length didn't change. + * NET_XMIT_SUCCESS: one skb was queued. + */ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); + struct sk_buff *skb2; int ret; + int count = 1; pr_debug("netem_enqueue skb=%p\n", skb); + /* Random duplication */ + if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) + ++count; + /* Random packet drop 0 => none, ~0 => all */ - if (q->loss && q->loss >= get_crandom(&q->loss_cor)) { - pr_debug("netem_enqueue: random loss\n"); + if (q->loss && q->loss >= get_crandom(&q->loss_cor)) + --count; + + if (count == 0) { sch->qstats.drops++; kfree_skb(skb); - return 0; /* lie about loss so TCP doesn't know */ + return NET_XMIT_DROP; } - /* Random duplication */ - if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) { - struct sk_buff *skb2; - - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 && netem_delay(sch, skb2) == NET_XMIT_SUCCESS) { - struct Qdisc *qp; - - /* Since one packet can generate two packets in the - * queue, the parent's qlen accounting gets confused, - * so fix it. - */ - qp = qdisc_lookup(sch->dev, TC_H_MAJ(sch->parent)); - if (qp) - qp->q.qlen++; - - sch->q.qlen++; - sch->bstats.bytes += skb2->len; - sch->bstats.packets++; - } else - sch->qstats.drops++; + /* + * If we need to duplicate packet, then re-insert at top of the + * qdisc tree, since parent queuer expects that only one + * skb will be queued. + */ + if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { + struct Qdisc *rootq = sch->dev->qdisc; + u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ + q->duplicate = 0; + + rootq->enqueue(skb2, rootq); + q->duplicate = dupsave; } /* If doing simple delay then gap == 0 so all packets -- cgit v1.1 From 0f9f32ac65ee4a452a912a8440cebbc4dff73852 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 May 2005 12:55:01 -0700 Subject: [PKT_SCHED] netem: use only inner qdisc -- no private skbuff queue Netem works better if there if packets are just queued in the inner discipline rather than having a separate delayed queue. Change to use the dequeue/requeue to peek like TBF does. By doing this potential qlen problems with the old method are avoided. The problems happened when the netem_run that moved packets from the inner discipline to the nested discipline failed (because inner queue was full). This happened in dequeue, so the effective qlen of the netem would be decreased (because of the drop), but there was no way to keep the outer qdisc (caller of netem dequeue) in sync. The problem window is still there since this patch doesn't address the issue of requeue failing in netem_dequeue, but that shouldn't happen since the sequence dequeue/requeue should always work. Long term correct fix is to implement qdisc->peek in all the qdisc's to allow for this (needed by several other qdisc's as well). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/sch_netem.c | 124 +++++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 88 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 5c0f0c2..48360f7 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -53,7 +53,6 @@ struct netem_sched_data { struct Qdisc *qdisc; - struct sk_buff_head delayed; struct timer_list timer; u32 latency; @@ -137,72 +136,6 @@ static long tabledist(unsigned long mu, long sigma, return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu; } -/* Put skb in the private delayed queue. */ -static int netem_delay(struct Qdisc *sch, struct sk_buff *skb) -{ - struct netem_sched_data *q = qdisc_priv(sch); - psched_tdiff_t td; - psched_time_t now; - - PSCHED_GET_TIME(now); - td = tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist); - - /* Always queue at tail to keep packets in order */ - if (likely(q->delayed.qlen < q->limit)) { - struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb; - - PSCHED_TADD2(now, td, cb->time_to_send); - - pr_debug("netem_delay: skb=%p now=%llu tosend=%llu\n", skb, - now, cb->time_to_send); - - __skb_queue_tail(&q->delayed, skb); - return NET_XMIT_SUCCESS; - } - - pr_debug("netem_delay: queue over limit %d\n", q->limit); - sch->qstats.overlimits++; - kfree_skb(skb); - return NET_XMIT_DROP; -} - -/* - * Move a packet that is ready to send from the delay holding - * list to the underlying qdisc. - */ -static int netem_run(struct Qdisc *sch) -{ - struct netem_sched_data *q = qdisc_priv(sch); - struct sk_buff *skb; - psched_time_t now; - - PSCHED_GET_TIME(now); - - skb = skb_peek(&q->delayed); - if (skb) { - const struct netem_skb_cb *cb - = (const struct netem_skb_cb *)skb->cb; - long delay - = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now)); - pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay); - - /* if more time remaining? */ - if (delay > 0) { - mod_timer(&q->timer, jiffies + delay); - return 1; - } - - __skb_unlink(skb, &q->delayed); - - if (q->qdisc->enqueue(skb, q->qdisc)) { - sch->q.qlen--; - sch->qstats.drops++; - } - } - - return 0; -} - /* * Insert one skb into qdisc. * Note: parent depends on return value to account for queue length. @@ -212,6 +145,7 @@ static int netem_run(struct Qdisc *sch) static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); + struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb; struct sk_buff *skb2; int ret; int count = 1; @@ -246,18 +180,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->duplicate = dupsave; } - /* If doing simple delay then gap == 0 so all packets - * go into the delayed holding queue - * otherwise if doing out of order only "1 out of gap" - * packets will be delayed. + /* + * Do re-ordering by putting one out of N packets at the front + * of the queue. + * gap == 0 is special case for no-reordering. */ - if (q->counter < q->gap) { + if (q->gap == 0 || q->counter != q->gap) { + psched_time_t now; + PSCHED_GET_TIME(now); + PSCHED_TADD2(now, + tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist), + cb->time_to_send); + ++q->counter; ret = q->qdisc->enqueue(skb, q->qdisc); } else { q->counter = 0; - ret = netem_delay(sch, skb); - netem_run(sch); + PSCHED_GET_TIME(cb->time_to_send); + ret = q->qdisc->ops->requeue(skb, q->qdisc); } if (likely(ret == NET_XMIT_SUCCESS)) { @@ -301,22 +241,33 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; - int pending; - - pending = netem_run(sch); skb = q->qdisc->dequeue(q->qdisc); if (skb) { - pr_debug("netem_dequeue: return skb=%p\n", skb); - sch->q.qlen--; - sch->flags &= ~TCQ_F_THROTTLED; - } - else if (pending) { - pr_debug("netem_dequeue: throttling\n"); + const struct netem_skb_cb *cb + = (const struct netem_skb_cb *)skb->cb; + psched_time_t now; + long delay; + + /* if more time remaining? */ + PSCHED_GET_TIME(now); + delay = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now)); + pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay); + if (delay <= 0) { + pr_debug("netem_dequeue: return skb=%p\n", skb); + sch->q.qlen--; + sch->flags &= ~TCQ_F_THROTTLED; + return skb; + } + + mod_timer(&q->timer, jiffies + delay); sch->flags |= TCQ_F_THROTTLED; - } - return skb; + if (q->qdisc->ops->requeue(skb, q->qdisc) != 0) + sch->qstats.drops++; + } + + return NULL; } static void netem_watchdog(unsigned long arg) @@ -333,8 +284,6 @@ static void netem_reset(struct Qdisc *sch) struct netem_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); - skb_queue_purge(&q->delayed); - sch->q.qlen = 0; sch->flags &= ~TCQ_F_THROTTLED; del_timer_sync(&q->timer); @@ -460,7 +409,6 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) if (!opt) return -EINVAL; - skb_queue_head_init(&q->delayed); init_timer(&q->timer); q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; -- cgit v1.1 From 0dca51d362b8e4af6b0dbc9e54d1e5165341918a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 May 2005 12:55:48 -0700 Subject: [PKT_SCHED] netem: allow random reordering (with fix) Here is a fixed up version of the reorder feature of netem. It is the same as the earlier patch plus with the bugfix from Julio merged in. Has expected backwards compatibility behaviour. Go ahead and merge this one, the TCP strangeness I was seeing was due to the reordering bug, and previous version of TSO patch. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/pkt_sched.h | 9 +++++++- net/sched/sch_netem.c | 54 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 73d84c0..1d9da36 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -427,6 +427,7 @@ enum TCA_NETEM_UNSPEC, TCA_NETEM_CORR, TCA_NETEM_DELAY_DIST, + TCA_NETEM_REORDER, __TCA_NETEM_MAX, }; @@ -437,7 +438,7 @@ struct tc_netem_qopt __u32 latency; /* added delay (us) */ __u32 limit; /* fifo limit (packets) */ __u32 loss; /* random packet loss (0=none ~0=100%) */ - __u32 gap; /* re-ordering gap (0 for delay all) */ + __u32 gap; /* re-ordering gap (0 for none) */ __u32 duplicate; /* random packet dup (0=none ~0=100%) */ __u32 jitter; /* random jitter in latency (us) */ }; @@ -449,6 +450,12 @@ struct tc_netem_corr __u32 dup_corr; /* duplicate correlation */ }; +struct tc_netem_reorder +{ + __u32 probability; + __u32 correlation; +}; + #define NETEM_DIST_SCALE 8192 #endif diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 48360f7..bb9bf8d 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -62,11 +62,12 @@ struct netem_sched_data { u32 gap; u32 jitter; u32 duplicate; + u32 reorder; struct crndstate { unsigned long last; unsigned long rho; - } delay_cor, loss_cor, dup_cor; + } delay_cor, loss_cor, dup_cor, reorder_cor; struct disttable { u32 size; @@ -180,23 +181,23 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->duplicate = dupsave; } - /* - * Do re-ordering by putting one out of N packets at the front - * of the queue. - * gap == 0 is special case for no-reordering. - */ - if (q->gap == 0 || q->counter != q->gap) { + if (q->gap == 0 /* not doing reordering */ + || q->counter < q->gap /* inside last reordering gap */ + || q->reorder < get_crandom(&q->reorder_cor)) { psched_time_t now; PSCHED_GET_TIME(now); - PSCHED_TADD2(now, - tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist), + PSCHED_TADD2(now, tabledist(q->latency, q->jitter, + &q->delay_cor, q->delay_dist), cb->time_to_send); - ++q->counter; ret = q->qdisc->enqueue(skb, q->qdisc); } else { - q->counter = 0; + /* + * Do re-ordering by putting one out of N packets at the front + * of the queue. + */ PSCHED_GET_TIME(cb->time_to_send); + q->counter = 0; ret = q->qdisc->ops->requeue(skb, q->qdisc); } @@ -351,6 +352,19 @@ static int get_correlation(struct Qdisc *sch, const struct rtattr *attr) return 0; } +static int get_reorder(struct Qdisc *sch, const struct rtattr *attr) +{ + struct netem_sched_data *q = qdisc_priv(sch); + const struct tc_netem_reorder *r = RTA_DATA(attr); + + if (RTA_PAYLOAD(attr) != sizeof(*r)) + return -EINVAL; + + q->reorder = r->probability; + init_crandom(&q->reorder_cor, r->correlation); + return 0; +} + static int netem_change(struct Qdisc *sch, struct rtattr *opt) { struct netem_sched_data *q = qdisc_priv(sch); @@ -371,9 +385,15 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) q->jitter = qopt->jitter; q->limit = qopt->limit; q->gap = qopt->gap; + q->counter = 0; q->loss = qopt->loss; q->duplicate = qopt->duplicate; + /* for compatiablity with earlier versions. + * if gap is set, need to assume 100% probablity + */ + q->reorder = ~0; + /* Handle nested options after initial queue options. * Should have put all options in nested format but too late now. */ @@ -395,6 +415,11 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) if (ret) return ret; } + if (tb[TCA_NETEM_REORDER-1]) { + ret = get_reorder(sch, tb[TCA_NETEM_REORDER-1]); + if (ret) + return ret; + } } @@ -412,7 +437,6 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) init_timer(&q->timer); q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; - q->counter = 0; q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); if (!q->qdisc) { @@ -444,6 +468,7 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) struct rtattr *rta = (struct rtattr *) b; struct tc_netem_qopt qopt; struct tc_netem_corr cor; + struct tc_netem_reorder reorder; qopt.latency = q->latency; qopt.jitter = q->jitter; @@ -457,6 +482,11 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) cor.loss_corr = q->loss_cor.rho; cor.dup_corr = q->dup_cor.rho; RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor); + + reorder.probability = q->reorder; + reorder.correlation = q->reorder_cor.rho; + RTA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder); + rta->rta_len = skb->tail - b; return skb->len; -- cgit v1.1 From 2f872f0401d4b470990864fbf99c19130f25ad4d Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Thu, 26 May 2005 12:56:59 -0700 Subject: [BONDING]: bonding using arp_ip_target may stay down with active path Correcting the list traversal makes the problem go away. Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 770e28f..269a5e4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3037,7 +3037,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev) bond_set_slave_inactive_flags(bond->current_arp_slave); /* search for next candidate */ - bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave) { + bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave->next) { if (IS_UP(slave->dev)) { slave->link = BOND_LINK_BACK; bond_set_slave_active_flags(slave); -- cgit v1.1 From 92d63decc0b6a5d600f792fcf5f3ff9718c09a3d Mon Sep 17 00:00:00 2001 From: Hideaki YOSHIFUJI Date: Thu, 26 May 2005 12:58:04 -0700 Subject: From: Kazunori Miyazawa [XFRM] Call dst_check() with appropriate cookie This fixes infinite loop issue with IPv6 tunnel mode. Signed-off-by: Kazunori Miyazawa Signed-off-by: Hideaki YOSHIFUJI Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 ++ net/ipv6/xfrm6_policy.c | 4 ++++ net/xfrm/xfrm_policy.c | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e142a25..d675836 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -515,6 +515,8 @@ struct xfrm_dst struct dst_entry *route; u32 route_mtu_cached; u32 child_mtu_cached; + u32 route_cookie; + u32 path_cookie; }; static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 4429b1a..cf1d91e 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -113,6 +113,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int xdst = (struct xfrm_dst *)dst1; xdst->route = &rt->u.dst; + if (rt->rt6i_node) + xdst->route_cookie = rt->rt6i_node->fn_sernum; dst1->next = dst_prev; dst_prev = dst1; @@ -137,6 +139,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int dst_prev->child = &rt->u.dst; dst->path = &rt->u.dst; + if (rt->rt6i_node) + ((struct xfrm_dst *)dst)->path_cookie = rt->rt6i_node->fn_sernum; *dst_p = dst; dst = dst_prev; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 55ed979..d07f5ce 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1136,7 +1136,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) struct xfrm_dst *last; u32 mtu; - if (!dst_check(dst->path, 0) || + if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) || (dst->dev && !netif_running(dst->dev))) return 0; @@ -1156,7 +1156,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) xdst->child_mtu_cached = mtu; } - if (!dst_check(xdst->route, 0)) + if (!dst_check(xdst->route, xdst->route_cookie)) return 0; mtu = dst_mtu(xdst->route); if (xdst->route_mtu_cached != mtu) { -- cgit v1.1 From c6b3365391c626206f6789354794a81a010cb7a1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 26 May 2005 12:59:05 -0700 Subject: [TOKENRING]: be'ify trh_hdr, trllc, rif_cache_s Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/linux/if_tr.h | 6 +++--- net/802/tr.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h index a2b01e1e..6688b41 100644 --- a/include/linux/if_tr.h +++ b/include/linux/if_tr.h @@ -36,8 +36,8 @@ struct trh_hdr { __u8 fc; /* frame control field */ __u8 daddr[TR_ALEN]; /* destination address */ __u8 saddr[TR_ALEN]; /* source address */ - __u16 rcf; /* route control field */ - __u16 rseg[8]; /* routing registers */ + __be16 rcf; /* route control field */ + __be16 rseg[8]; /* routing registers */ }; #ifdef __KERNEL__ @@ -55,7 +55,7 @@ struct trllc { __u8 ssap; /* source SAP */ __u8 llc; /* LLC control field */ __u8 protid[3]; /* protocol id */ - __u16 ethertype; /* ether type field */ + __be16 ethertype; /* ether type field */ }; /* Token-Ring statistics collection data. */ diff --git a/net/802/tr.c b/net/802/tr.c index 85293cc..3bfb862 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -50,8 +50,8 @@ static void rif_check_expire(unsigned long dummy); struct rif_cache_s { unsigned char addr[TR_ALEN]; int iface; - __u16 rcf; - __u16 rseg[8]; + __be16 rcf; + __be16 rseg[8]; struct rif_cache_s *next; unsigned long last_used; unsigned char local_ring; -- cgit v1.1 From c8b35d2a29ec3c93e3b9c1e70d649a77a214b1c1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 26 May 2005 12:59:42 -0700 Subject: [TOKENRING]: net/802/tr.c: s/struct rif_cache_s/struct rif_cache/ "_s" suffix is certainly of hungarian origin. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/802/tr.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/802/tr.c b/net/802/tr.c index 3bfb862..a755e88 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -47,12 +47,12 @@ static void rif_check_expire(unsigned long dummy); * Each RIF entry we learn is kept this way */ -struct rif_cache_s { +struct rif_cache { unsigned char addr[TR_ALEN]; int iface; __be16 rcf; __be16 rseg[8]; - struct rif_cache_s *next; + struct rif_cache *next; unsigned long last_used; unsigned char local_ring; }; @@ -64,7 +64,7 @@ struct rif_cache_s { * up a lot. */ -static struct rif_cache_s *rif_table[RIF_TABLE_SIZE]; +static struct rif_cache *rif_table[RIF_TABLE_SIZE]; static DEFINE_SPINLOCK(rif_lock); @@ -249,7 +249,7 @@ void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device * { int slack; unsigned int hash; - struct rif_cache_s *entry; + struct rif_cache *entry; unsigned char *olddata; static const unsigned char mcast_func_addr[] = {0xC0,0x00,0x00,0x04,0x00,0x00}; @@ -337,7 +337,7 @@ printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0], static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev) { unsigned int hash, rii_p = 0; - struct rif_cache_s *entry; + struct rif_cache *entry; spin_lock_bh(&rif_lock); @@ -373,7 +373,7 @@ printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", * FIXME: We ought to keep some kind of cache size * limiting and adjust the timers to suit. */ - entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC); + entry=kmalloc(sizeof(struct rif_cache),GFP_ATOMIC); if(!entry) { @@ -435,7 +435,7 @@ static void rif_check_expire(unsigned long dummy) spin_lock_bh(&rif_lock); for(i =0; i < RIF_TABLE_SIZE; i++) { - struct rif_cache_s *entry, **pentry; + struct rif_cache *entry, **pentry; pentry = rif_table+i; while((entry=*pentry) != NULL) { @@ -467,10 +467,10 @@ static void rif_check_expire(unsigned long dummy) #ifdef CONFIG_PROC_FS -static struct rif_cache_s *rif_get_idx(loff_t pos) +static struct rif_cache *rif_get_idx(loff_t pos) { int i; - struct rif_cache_s *entry; + struct rif_cache *entry; loff_t off = 0; for(i = 0; i < RIF_TABLE_SIZE; i++) @@ -493,7 +493,7 @@ static void *rif_seq_start(struct seq_file *seq, loff_t *pos) static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos) { int i; - struct rif_cache_s *ent = v; + struct rif_cache *ent = v; ++*pos; @@ -522,7 +522,7 @@ static void rif_seq_stop(struct seq_file *seq, void *v) static int rif_seq_show(struct seq_file *seq, void *v) { int j, rcf_len, segment, brdgnmb; - struct rif_cache_s *entry = v; + struct rif_cache *entry = v; if (v == SEQ_START_TOKEN) seq_puts(seq, -- cgit v1.1 From b6016b767397258b58163494a869f8f1199e6897 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 26 May 2005 13:03:09 -0700 Subject: [BNX2]: New Broadcom gigabit network driver. A new driver bnx2 for Broadcom bcm5706 is available. The patch also includes new 1000BASE-X advertisement bit definitions in mii.h Thanks to David Miller and Jeff Garzik for reviewing and their valuable feedback. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/Kconfig | 9 + drivers/net/Makefile | 1 + drivers/net/bnx2.c | 5530 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/bnx2.h | 4352 +++++++++++++++++++++++++++++++++++++ drivers/net/bnx2_fw.h | 2468 +++++++++++++++++++++ include/linux/mii.h | 8 + include/linux/pci_ids.h | 2 + 7 files changed, 12370 insertions(+) create mode 100644 drivers/net/bnx2.c create mode 100644 drivers/net/bnx2.h create mode 100644 drivers/net/bnx2_fw.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3a0a55b..9e6501d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2031,6 +2031,15 @@ config TIGON3 To compile this driver as a module, choose M here: the module will be called tg3. This is recommended. +config BNX2 + tristate "Broadcom NetXtremeII support" + depends on PCI + help + This driver supports Broadcom NetXtremeII gigabit Ethernet cards. + + To compile this driver as a module, choose M here: the module + will be called bnx2. This is recommended. + config GIANFAR tristate "Gianfar Ethernet" depends on 85xx || 83xx diff --git a/drivers/net/Makefile b/drivers/net/Makefile index e038d55..30c7567 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_NS83820) += ns83820.o obj-$(CONFIG_STNIC) += stnic.o 8390.o obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_TIGON3) += tg3.o +obj-$(CONFIG_BNX2) += bnx2.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SK98LIN) += sk98lin/ obj-$(CONFIG_SKFP) += skfp/ diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c new file mode 100644 index 0000000..8acc655 --- /dev/null +++ b/drivers/net/bnx2.c @@ -0,0 +1,5530 @@ +/* bnx2.c: Broadcom NX2 network driver. + * + * Copyright (c) 2004, 2005 Broadcom Corporation + * + * 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. + * + * Written by: Michael Chan (mchan@broadcom.com) + */ + +#include "bnx2.h" +#include "bnx2_fw.h" + +#define DRV_MODULE_NAME "bnx2" +#define PFX DRV_MODULE_NAME ": " +#define DRV_MODULE_VERSION "1.2.19" +#define DRV_MODULE_RELDATE "May 23, 2005" + +#define RUN_AT(x) (jiffies + (x)) + +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (5*HZ) + +static char version[] __devinitdata = + "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + +MODULE_AUTHOR("Michael Chan "); +MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706 Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_MODULE_VERSION); + +static int disable_msi = 0; + +module_param(disable_msi, int, 0); +MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); + +typedef enum { + BCM5706 = 0, + NC370T, + NC370I, + BCM5706S, + NC370F, +} board_t; + +/* indexed by board_t, above */ +static struct { + char *name; +} board_info[] __devinitdata = { + { "Broadcom NetXtreme II BCM5706 1000Base-T" }, + { "HP NC370T Multifunction Gigabit Server Adapter" }, + { "HP NC370i Multifunction Gigabit Server Adapter" }, + { "Broadcom NetXtreme II BCM5706 1000Base-SX" }, + { "HP NC370F Multifunction Gigabit Server Adapter" }, + { 0 }, + }; + +static struct pci_device_id bnx2_pci_tbl[] = { + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, + PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, + PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, + PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S }, + { 0, } +}; + +static struct flash_spec flash_table[] = +{ + /* Slow EEPROM */ + {0x00000000, 0x40030380, 0x009f0081, 0xa184a053, 0xaf000400, + 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, + SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, + "EEPROM - slow"}, + /* Fast EEPROM */ + {0x02000000, 0x62008380, 0x009f0081, 0xa184a053, 0xaf000400, + 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, + SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, + "EEPROM - fast"}, + /* ATMEL AT45DB011B (buffered flash) */ + {0x02000003, 0x6e008173, 0x00570081, 0x68848353, 0xaf000400, + 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, + "Buffered flash"}, + /* Saifun SA25F005 (non-buffered flash) */ + /* strap, cfg1, & write1 need updates */ + {0x01000003, 0x5f008081, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, + "Non-buffered flash (64kB)"}, + /* Saifun SA25F010 (non-buffered flash) */ + /* strap, cfg1, & write1 need updates */ + {0x00000001, 0x47008081, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, + "Non-buffered flash (128kB)"}, + /* Saifun SA25F020 (non-buffered flash) */ + /* strap, cfg1, & write1 need updates */ + {0x00000003, 0x4f008081, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, + "Non-buffered flash (256kB)"}, +}; + +MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); + +static u32 +bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset) +{ + REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); + return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW)); +} + +static void +bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) +{ + REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); + REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val); +} + +static void +bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) +{ + offset += cid_addr; + REG_WR(bp, BNX2_CTX_DATA_ADR, offset); + REG_WR(bp, BNX2_CTX_DATA, val); +} + +static int +bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val) +{ + u32 val1; + int i, ret; + + if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { + val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL; + + REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + REG_RD(bp, BNX2_EMAC_MDIO_MODE); + + udelay(40); + } + + val1 = (bp->phy_addr << 21) | (reg << 16) | + BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT | + BNX2_EMAC_MDIO_COMM_START_BUSY; + REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); + + for (i = 0; i < 50; i++) { + udelay(10); + + val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); + if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) { + udelay(5); + + val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); + val1 &= BNX2_EMAC_MDIO_COMM_DATA; + + break; + } + } + + if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) { + *val = 0x0; + ret = -EBUSY; + } + else { + *val = val1; + ret = 0; + } + + if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { + val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL; + + REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + REG_RD(bp, BNX2_EMAC_MDIO_MODE); + + udelay(40); + } + + return ret; +} + +static int +bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val) +{ + u32 val1; + int i, ret; + + if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { + val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL; + + REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + REG_RD(bp, BNX2_EMAC_MDIO_MODE); + + udelay(40); + } + + val1 = (bp->phy_addr << 21) | (reg << 16) | val | + BNX2_EMAC_MDIO_COMM_COMMAND_WRITE | + BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT; + REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); + + for (i = 0; i < 50; i++) { + udelay(10); + + val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); + if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) { + udelay(5); + break; + } + } + + if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) + ret = -EBUSY; + else + ret = 0; + + if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) { + val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL; + + REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + REG_RD(bp, BNX2_EMAC_MDIO_MODE); + + udelay(40); + } + + return ret; +} + +static void +bnx2_disable_int(struct bnx2 *bp) +{ + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); +} + +static void +bnx2_enable_int(struct bnx2 *bp) +{ + u32 val; + + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx); + + val = REG_RD(bp, BNX2_HC_COMMAND); + REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); +} + +static void +bnx2_disable_int_sync(struct bnx2 *bp) +{ + atomic_inc(&bp->intr_sem); + bnx2_disable_int(bp); + synchronize_irq(bp->pdev->irq); +} + +static void +bnx2_netif_stop(struct bnx2 *bp) +{ + bnx2_disable_int_sync(bp); + if (netif_running(bp->dev)) { + netif_poll_disable(bp->dev); + netif_tx_disable(bp->dev); + bp->dev->trans_start = jiffies; /* prevent tx timeout */ + } +} + +static void +bnx2_netif_start(struct bnx2 *bp) +{ + if (atomic_dec_and_test(&bp->intr_sem)) { + if (netif_running(bp->dev)) { + netif_wake_queue(bp->dev); + netif_poll_enable(bp->dev); + bnx2_enable_int(bp); + } + } +} + +static void +bnx2_free_mem(struct bnx2 *bp) +{ + if (bp->stats_blk) { + pci_free_consistent(bp->pdev, sizeof(struct statistics_block), + bp->stats_blk, bp->stats_blk_mapping); + bp->stats_blk = NULL; + } + if (bp->status_blk) { + pci_free_consistent(bp->pdev, sizeof(struct status_block), + bp->status_blk, bp->status_blk_mapping); + bp->status_blk = NULL; + } + if (bp->tx_desc_ring) { + pci_free_consistent(bp->pdev, + sizeof(struct tx_bd) * TX_DESC_CNT, + bp->tx_desc_ring, bp->tx_desc_mapping); + bp->tx_desc_ring = NULL; + } + if (bp->tx_buf_ring) { + kfree(bp->tx_buf_ring); + bp->tx_buf_ring = NULL; + } + if (bp->rx_desc_ring) { + pci_free_consistent(bp->pdev, + sizeof(struct rx_bd) * RX_DESC_CNT, + bp->rx_desc_ring, bp->rx_desc_mapping); + bp->rx_desc_ring = NULL; + } + if (bp->rx_buf_ring) { + kfree(bp->rx_buf_ring); + bp->rx_buf_ring = NULL; + } +} + +static int +bnx2_alloc_mem(struct bnx2 *bp) +{ + bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT, + GFP_KERNEL); + if (bp->tx_buf_ring == NULL) + return -ENOMEM; + + memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT); + bp->tx_desc_ring = pci_alloc_consistent(bp->pdev, + sizeof(struct tx_bd) * + TX_DESC_CNT, + &bp->tx_desc_mapping); + if (bp->tx_desc_ring == NULL) + goto alloc_mem_err; + + bp->rx_buf_ring = kmalloc(sizeof(struct sw_bd) * RX_DESC_CNT, + GFP_KERNEL); + if (bp->rx_buf_ring == NULL) + goto alloc_mem_err; + + memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT); + bp->rx_desc_ring = pci_alloc_consistent(bp->pdev, + sizeof(struct rx_bd) * + RX_DESC_CNT, + &bp->rx_desc_mapping); + if (bp->rx_desc_ring == NULL) + goto alloc_mem_err; + + bp->status_blk = pci_alloc_consistent(bp->pdev, + sizeof(struct status_block), + &bp->status_blk_mapping); + if (bp->status_blk == NULL) + goto alloc_mem_err; + + memset(bp->status_blk, 0, sizeof(struct status_block)); + + bp->stats_blk = pci_alloc_consistent(bp->pdev, + sizeof(struct statistics_block), + &bp->stats_blk_mapping); + if (bp->stats_blk == NULL) + goto alloc_mem_err; + + memset(bp->stats_blk, 0, sizeof(struct statistics_block)); + + return 0; + +alloc_mem_err: + bnx2_free_mem(bp); + return -ENOMEM; +} + +static void +bnx2_report_link(struct bnx2 *bp) +{ + if (bp->link_up) { + netif_carrier_on(bp->dev); + printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name); + + printk("%d Mbps ", bp->line_speed); + + if (bp->duplex == DUPLEX_FULL) + printk("full duplex"); + else + printk("half duplex"); + + if (bp->flow_ctrl) { + if (bp->flow_ctrl & FLOW_CTRL_RX) { + printk(", receive "); + if (bp->flow_ctrl & FLOW_CTRL_TX) + printk("& transmit "); + } + else { + printk(", transmit "); + } + printk("flow control ON"); + } + printk("\n"); + } + else { + netif_carrier_off(bp->dev); + printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); + } +} + +static void +bnx2_resolve_flow_ctrl(struct bnx2 *bp) +{ + u32 local_adv, remote_adv; + + bp->flow_ctrl = 0; + if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != + (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { + + if (bp->duplex == DUPLEX_FULL) { + bp->flow_ctrl = bp->req_flow_ctrl; + } + return; + } + + if (bp->duplex != DUPLEX_FULL) { + return; + } + + bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); + bnx2_read_phy(bp, MII_LPA, &remote_adv); + + if (bp->phy_flags & PHY_SERDES_FLAG) { + u32 new_local_adv = 0; + u32 new_remote_adv = 0; + + if (local_adv & ADVERTISE_1000XPAUSE) + new_local_adv |= ADVERTISE_PAUSE_CAP; + if (local_adv & ADVERTISE_1000XPSE_ASYM) + new_local_adv |= ADVERTISE_PAUSE_ASYM; + if (remote_adv & ADVERTISE_1000XPAUSE) + new_remote_adv |= ADVERTISE_PAUSE_CAP; + if (remote_adv & ADVERTISE_1000XPSE_ASYM) + new_remote_adv |= ADVERTISE_PAUSE_ASYM; + + local_adv = new_local_adv; + remote_adv = new_remote_adv; + } + + /* See Table 28B-3 of 802.3ab-1999 spec. */ + if (local_adv & ADVERTISE_PAUSE_CAP) { + if(local_adv & ADVERTISE_PAUSE_ASYM) { + if (remote_adv & ADVERTISE_PAUSE_CAP) { + bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; + } + else if (remote_adv & ADVERTISE_PAUSE_ASYM) { + bp->flow_ctrl = FLOW_CTRL_RX; + } + } + else { + if (remote_adv & ADVERTISE_PAUSE_CAP) { + bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX; + } + } + } + else if (local_adv & ADVERTISE_PAUSE_ASYM) { + if ((remote_adv & ADVERTISE_PAUSE_CAP) && + (remote_adv & ADVERTISE_PAUSE_ASYM)) { + + bp->flow_ctrl = FLOW_CTRL_TX; + } + } +} + +static int +bnx2_serdes_linkup(struct bnx2 *bp) +{ + u32 bmcr, local_adv, remote_adv, common; + + bp->link_up = 1; + bp->line_speed = SPEED_1000; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + if (bmcr & BMCR_FULLDPLX) { + bp->duplex = DUPLEX_FULL; + } + else { + bp->duplex = DUPLEX_HALF; + } + + if (!(bmcr & BMCR_ANENABLE)) { + return 0; + } + + bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); + bnx2_read_phy(bp, MII_LPA, &remote_adv); + + common = local_adv & remote_adv; + if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) { + + if (common & ADVERTISE_1000XFULL) { + bp->duplex = DUPLEX_FULL; + } + else { + bp->duplex = DUPLEX_HALF; + } + } + + return 0; +} + +static int +bnx2_copper_linkup(struct bnx2 *bp) +{ + u32 bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + if (bmcr & BMCR_ANENABLE) { + u32 local_adv, remote_adv, common; + + bnx2_read_phy(bp, MII_CTRL1000, &local_adv); + bnx2_read_phy(bp, MII_STAT1000, &remote_adv); + + common = local_adv & (remote_adv >> 2); + if (common & ADVERTISE_1000FULL) { + bp->line_speed = SPEED_1000; + bp->duplex = DUPLEX_FULL; + } + else if (common & ADVERTISE_1000HALF) { + bp->line_speed = SPEED_1000; + bp->duplex = DUPLEX_HALF; + } + else { + bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); + bnx2_read_phy(bp, MII_LPA, &remote_adv); + + common = local_adv & remote_adv; + if (common & ADVERTISE_100FULL) { + bp->line_speed = SPEED_100; + bp->duplex = DUPLEX_FULL; + } + else if (common & ADVERTISE_100HALF) { + bp->line_speed = SPEED_100; + bp->duplex = DUPLEX_HALF; + } + else if (common & ADVERTISE_10FULL) { + bp->line_speed = SPEED_10; + bp->duplex = DUPLEX_FULL; + } + else if (common & ADVERTISE_10HALF) { + bp->line_speed = SPEED_10; + bp->duplex = DUPLEX_HALF; + } + else { + bp->line_speed = 0; + bp->link_up = 0; + } + } + } + else { + if (bmcr & BMCR_SPEED100) { + bp->line_speed = SPEED_100; + } + else { + bp->line_speed = SPEED_10; + } + if (bmcr & BMCR_FULLDPLX) { + bp->duplex = DUPLEX_FULL; + } + else { + bp->duplex = DUPLEX_HALF; + } + } + + return 0; +} + +static int +bnx2_set_mac_link(struct bnx2 *bp) +{ + u32 val; + + REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620); + if (bp->link_up && (bp->line_speed == SPEED_1000) && + (bp->duplex == DUPLEX_HALF)) { + REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff); + } + + /* Configure the EMAC mode register. */ + val = REG_RD(bp, BNX2_EMAC_MODE); + + val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | + BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK); + + if (bp->link_up) { + if (bp->line_speed != SPEED_1000) + val |= BNX2_EMAC_MODE_PORT_MII; + else + val |= BNX2_EMAC_MODE_PORT_GMII; + } + else { + val |= BNX2_EMAC_MODE_PORT_GMII; + } + + /* Set the MAC to operate in the appropriate duplex mode. */ + if (bp->duplex == DUPLEX_HALF) + val |= BNX2_EMAC_MODE_HALF_DUPLEX; + REG_WR(bp, BNX2_EMAC_MODE, val); + + /* Enable/disable rx PAUSE. */ + bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN; + + if (bp->flow_ctrl & FLOW_CTRL_RX) + bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN; + REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode); + + /* Enable/disable tx PAUSE. */ + val = REG_RD(bp, BNX2_EMAC_TX_MODE); + val &= ~BNX2_EMAC_TX_MODE_FLOW_EN; + + if (bp->flow_ctrl & FLOW_CTRL_TX) + val |= BNX2_EMAC_TX_MODE_FLOW_EN; + REG_WR(bp, BNX2_EMAC_TX_MODE, val); + + /* Acknowledge the interrupt. */ + REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE); + + return 0; +} + +static int +bnx2_set_link(struct bnx2 *bp) +{ + u32 bmsr; + u8 link_up; + + if (bp->loopback == MAC_LOOPBACK) { + bp->link_up = 1; + return 0; + } + + link_up = bp->link_up; + + bnx2_read_phy(bp, MII_BMSR, &bmsr); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (CHIP_NUM(bp) == CHIP_NUM_5706)) { + u32 val; + + val = REG_RD(bp, BNX2_EMAC_STATUS); + if (val & BNX2_EMAC_STATUS_LINK) + bmsr |= BMSR_LSTATUS; + else + bmsr &= ~BMSR_LSTATUS; + } + + if (bmsr & BMSR_LSTATUS) { + bp->link_up = 1; + + if (bp->phy_flags & PHY_SERDES_FLAG) { + bnx2_serdes_linkup(bp); + } + else { + bnx2_copper_linkup(bp); + } + bnx2_resolve_flow_ctrl(bp); + } + else { + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (bp->autoneg & AUTONEG_SPEED)) { + + u32 bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + if (!(bmcr & BMCR_ANENABLE)) { + bnx2_write_phy(bp, MII_BMCR, bmcr | + BMCR_ANENABLE); + } + } + bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; + bp->link_up = 0; + } + + if (bp->link_up != link_up) { + bnx2_report_link(bp); + } + + bnx2_set_mac_link(bp); + + return 0; +} + +static int +bnx2_reset_phy(struct bnx2 *bp) +{ + int i; + u32 reg; + + bnx2_write_phy(bp, MII_BMCR, BMCR_RESET); + +#define PHY_RESET_MAX_WAIT 100 + for (i = 0; i < PHY_RESET_MAX_WAIT; i++) { + udelay(10); + + bnx2_read_phy(bp, MII_BMCR, ®); + if (!(reg & BMCR_RESET)) { + udelay(20); + break; + } + } + if (i == PHY_RESET_MAX_WAIT) { + return -EBUSY; + } + return 0; +} + +static u32 +bnx2_phy_get_pause_adv(struct bnx2 *bp) +{ + u32 adv = 0; + + if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) == + (FLOW_CTRL_RX | FLOW_CTRL_TX)) { + + if (bp->phy_flags & PHY_SERDES_FLAG) { + adv = ADVERTISE_1000XPAUSE; + } + else { + adv = ADVERTISE_PAUSE_CAP; + } + } + else if (bp->req_flow_ctrl & FLOW_CTRL_TX) { + if (bp->phy_flags & PHY_SERDES_FLAG) { + adv = ADVERTISE_1000XPSE_ASYM; + } + else { + adv = ADVERTISE_PAUSE_ASYM; + } + } + else if (bp->req_flow_ctrl & FLOW_CTRL_RX) { + if (bp->phy_flags & PHY_SERDES_FLAG) { + adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; + } + else { + adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + } + } + return adv; +} + +static int +bnx2_setup_serdes_phy(struct bnx2 *bp) +{ + u32 adv, bmcr; + u32 new_adv = 0; + + if (!(bp->autoneg & AUTONEG_SPEED)) { + u32 new_bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + new_bmcr = bmcr & ~BMCR_ANENABLE; + new_bmcr |= BMCR_SPEED1000; + if (bp->req_duplex == DUPLEX_FULL) { + new_bmcr |= BMCR_FULLDPLX; + } + else { + new_bmcr &= ~BMCR_FULLDPLX; + } + if (new_bmcr != bmcr) { + /* Force a link down visible on the other side */ + if (bp->link_up) { + bnx2_read_phy(bp, MII_ADVERTISE, &adv); + adv &= ~(ADVERTISE_1000XFULL | + ADVERTISE_1000XHALF); + bnx2_write_phy(bp, MII_ADVERTISE, adv); + bnx2_write_phy(bp, MII_BMCR, bmcr | + BMCR_ANRESTART | BMCR_ANENABLE); + + bp->link_up = 0; + netif_carrier_off(bp->dev); + } + bnx2_write_phy(bp, MII_BMCR, new_bmcr); + } + return 0; + } + + if (bp->advertising & ADVERTISED_1000baseT_Full) + new_adv |= ADVERTISE_1000XFULL; + + new_adv |= bnx2_phy_get_pause_adv(bp); + + bnx2_read_phy(bp, MII_ADVERTISE, &adv); + bnx2_read_phy(bp, MII_BMCR, &bmcr); + + bp->serdes_an_pending = 0; + if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { + /* Force a link down visible on the other side */ + if (bp->link_up) { + int i; + + bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); + for (i = 0; i < 110; i++) { + udelay(100); + } + } + + bnx2_write_phy(bp, MII_ADVERTISE, new_adv); + bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | + BMCR_ANENABLE); + bp->serdes_an_pending = SERDES_AN_TIMEOUT / bp->timer_interval; + } + + return 0; +} + +#define ETHTOOL_ALL_FIBRE_SPEED \ + (ADVERTISED_1000baseT_Full) + +#define ETHTOOL_ALL_COPPER_SPEED \ + (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ + ADVERTISED_1000baseT_Full) + +#define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA) + +#define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) + +static int +bnx2_setup_copper_phy(struct bnx2 *bp) +{ + u32 bmcr; + u32 new_bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + + if (bp->autoneg & AUTONEG_SPEED) { + u32 adv_reg, adv1000_reg; + u32 new_adv_reg = 0; + u32 new_adv1000_reg = 0; + + bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg); + adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + + bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg); + adv1000_reg &= PHY_ALL_1000_SPEED; + + if (bp->advertising & ADVERTISED_10baseT_Half) + new_adv_reg |= ADVERTISE_10HALF; + if (bp->advertising & ADVERTISED_10baseT_Full) + new_adv_reg |= ADVERTISE_10FULL; + if (bp->advertising & ADVERTISED_100baseT_Half) + new_adv_reg |= ADVERTISE_100HALF; + if (bp->advertising & ADVERTISED_100baseT_Full) + new_adv_reg |= ADVERTISE_100FULL; + if (bp->advertising & ADVERTISED_1000baseT_Full) + new_adv1000_reg |= ADVERTISE_1000FULL; + + new_adv_reg |= ADVERTISE_CSMA; + + new_adv_reg |= bnx2_phy_get_pause_adv(bp); + + if ((adv1000_reg != new_adv1000_reg) || + (adv_reg != new_adv_reg) || + ((bmcr & BMCR_ANENABLE) == 0)) { + + bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg); + bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg); + bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART | + BMCR_ANENABLE); + } + else if (bp->link_up) { + /* Flow ctrl may have changed from auto to forced */ + /* or vice-versa. */ + + bnx2_resolve_flow_ctrl(bp); + bnx2_set_mac_link(bp); + } + return 0; + } + + new_bmcr = 0; + if (bp->req_line_speed == SPEED_100) { + new_bmcr |= BMCR_SPEED100; + } + if (bp->req_duplex == DUPLEX_FULL) { + new_bmcr |= BMCR_FULLDPLX; + } + if (new_bmcr != bmcr) { + u32 bmsr; + int i = 0; + + bnx2_read_phy(bp, MII_BMSR, &bmsr); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + + if (bmsr & BMSR_LSTATUS) { + /* Force link down */ + bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); + do { + udelay(100); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + i++; + } while ((bmsr & BMSR_LSTATUS) && (i < 620)); + } + + bnx2_write_phy(bp, MII_BMCR, new_bmcr); + + /* Normally, the new speed is setup after the link has + * gone down and up again. In some cases, link will not go + * down so we need to set up the new speed here. + */ + if (bmsr & BMSR_LSTATUS) { + bp->line_speed = bp->req_line_speed; + bp->duplex = bp->req_duplex; + bnx2_resolve_flow_ctrl(bp); + bnx2_set_mac_link(bp); + } + } + return 0; +} + +static int +bnx2_setup_phy(struct bnx2 *bp) +{ + if (bp->loopback == MAC_LOOPBACK) + return 0; + + if (bp->phy_flags & PHY_SERDES_FLAG) { + return (bnx2_setup_serdes_phy(bp)); + } + else { + return (bnx2_setup_copper_phy(bp)); + } +} + +static int +bnx2_init_serdes_phy(struct bnx2 *bp) +{ + bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; + + if (CHIP_NUM(bp) == CHIP_NUM_5706) { + REG_WR(bp, BNX2_MISC_UNUSED0, 0x300); + } + + if (bp->dev->mtu > 1500) { + u32 val; + + /* Set extended packet length bit */ + bnx2_write_phy(bp, 0x18, 0x7); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, (val & 0xfff8) | 0x4000); + + bnx2_write_phy(bp, 0x1c, 0x6c00); + bnx2_read_phy(bp, 0x1c, &val); + bnx2_write_phy(bp, 0x1c, (val & 0x3ff) | 0xec02); + } + else { + u32 val; + + bnx2_write_phy(bp, 0x18, 0x7); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, val & ~0x4007); + + bnx2_write_phy(bp, 0x1c, 0x6c00); + bnx2_read_phy(bp, 0x1c, &val); + bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00); + } + + return 0; +} + +static int +bnx2_init_copper_phy(struct bnx2 *bp) +{ + bp->phy_flags |= PHY_CRC_FIX_FLAG; + + if (bp->phy_flags & PHY_CRC_FIX_FLAG) { + bnx2_write_phy(bp, 0x18, 0x0c00); + bnx2_write_phy(bp, 0x17, 0x000a); + bnx2_write_phy(bp, 0x15, 0x310b); + bnx2_write_phy(bp, 0x17, 0x201f); + bnx2_write_phy(bp, 0x15, 0x9506); + bnx2_write_phy(bp, 0x17, 0x401f); + bnx2_write_phy(bp, 0x15, 0x14e2); + bnx2_write_phy(bp, 0x18, 0x0400); + } + + if (bp->dev->mtu > 1500) { + u32 val; + + /* Set extended packet length bit */ + bnx2_write_phy(bp, 0x18, 0x7); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, val | 0x4000); + + bnx2_read_phy(bp, 0x10, &val); + bnx2_write_phy(bp, 0x10, val | 0x1); + } + else { + u32 val; + + bnx2_write_phy(bp, 0x18, 0x7); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, val & ~0x4007); + + bnx2_read_phy(bp, 0x10, &val); + bnx2_write_phy(bp, 0x10, val & ~0x1); + } + + return 0; +} + + +static int +bnx2_init_phy(struct bnx2 *bp) +{ + u32 val; + int rc = 0; + + bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG; + bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG; + + REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); + + bnx2_reset_phy(bp); + + bnx2_read_phy(bp, MII_PHYSID1, &val); + bp->phy_id = val << 16; + bnx2_read_phy(bp, MII_PHYSID2, &val); + bp->phy_id |= val & 0xffff; + + if (bp->phy_flags & PHY_SERDES_FLAG) { + rc = bnx2_init_serdes_phy(bp); + } + else { + rc = bnx2_init_copper_phy(bp); + } + + bnx2_setup_phy(bp); + + return rc; +} + +static int +bnx2_set_mac_loopback(struct bnx2 *bp) +{ + u32 mac_mode; + + mac_mode = REG_RD(bp, BNX2_EMAC_MODE); + mac_mode &= ~BNX2_EMAC_MODE_PORT; + mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK; + REG_WR(bp, BNX2_EMAC_MODE, mac_mode); + bp->link_up = 1; + return 0; +} + +static int +bnx2_fw_sync(struct bnx2 *bp, u32 msg_data) +{ + int i; + u32 val; + + if (bp->fw_timed_out) + return -EBUSY; + + bp->fw_wr_seq++; + msg_data |= bp->fw_wr_seq; + + REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_MB, msg_data); + + /* wait for an acknowledgement. */ + for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) { + udelay(5); + + val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_FW_MB); + + if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) + break; + } + + /* If we timed out, inform the firmware that this is the case. */ + if (((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) && + ((msg_data & BNX2_DRV_MSG_DATA) != BNX2_DRV_MSG_DATA_WAIT0)) { + + msg_data &= ~BNX2_DRV_MSG_CODE; + msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; + + REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_MB, msg_data); + + bp->fw_timed_out = 1; + + return -EBUSY; + } + + return 0; +} + +static void +bnx2_init_context(struct bnx2 *bp) +{ + u32 vcid; + + vcid = 96; + while (vcid) { + u32 vcid_addr, pcid_addr, offset; + + vcid--; + + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + u32 new_vcid; + + vcid_addr = GET_PCID_ADDR(vcid); + if (vcid & 0x8) { + new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7); + } + else { + new_vcid = vcid; + } + pcid_addr = GET_PCID_ADDR(new_vcid); + } + else { + vcid_addr = GET_CID_ADDR(vcid); + pcid_addr = vcid_addr; + } + + REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00); + REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + + /* Zero out the context. */ + for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) { + CTX_WR(bp, 0x00, offset, 0); + } + + REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr); + REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + } +} + +static int +bnx2_alloc_bad_rbuf(struct bnx2 *bp) +{ + u16 *good_mbuf; + u32 good_mbuf_cnt; + u32 val; + + good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); + if (good_mbuf == NULL) { + printk(KERN_ERR PFX "Failed to allocate memory in " + "bnx2_alloc_bad_rbuf\n"); + return -ENOMEM; + } + + REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, + BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE); + + good_mbuf_cnt = 0; + + /* Allocate a bunch of mbufs and save the good ones in an array. */ + val = REG_RD_IND(bp, BNX2_RBUF_STATUS1); + while (val & BNX2_RBUF_STATUS1_FREE_COUNT) { + REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ); + + val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC); + + val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE; + + /* The addresses with Bit 9 set are bad memory blocks. */ + if (!(val & (1 << 9))) { + good_mbuf[good_mbuf_cnt] = (u16) val; + good_mbuf_cnt++; + } + + val = REG_RD_IND(bp, BNX2_RBUF_STATUS1); + } + + /* Free the good ones back to the mbuf pool thus discarding + * all the bad ones. */ + while (good_mbuf_cnt) { + good_mbuf_cnt--; + + val = good_mbuf[good_mbuf_cnt]; + val = (val << 9) | val | 1; + + REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val); + } + kfree(good_mbuf); + return 0; +} + +static void +bnx2_set_mac_addr(struct bnx2 *bp) +{ + u32 val; + u8 *mac_addr = bp->dev->dev_addr; + + val = (mac_addr[0] << 8) | mac_addr[1]; + + REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val); + + val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | + (mac_addr[4] << 8) | mac_addr[5]; + + REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val); +} + +static inline int +bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) +{ + struct sk_buff *skb; + struct sw_bd *rx_buf = &bp->rx_buf_ring[index]; + dma_addr_t mapping; + struct rx_bd *rxbd = &bp->rx_desc_ring[index]; + unsigned long align; + + skb = dev_alloc_skb(bp->rx_buf_size); + if (skb == NULL) { + return -ENOMEM; + } + + if (unlikely((align = (unsigned long) skb->data & 0x7))) { + skb_reserve(skb, 8 - align); + } + + skb->dev = bp->dev; + mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size, + PCI_DMA_FROMDEVICE); + + rx_buf->skb = skb; + pci_unmap_addr_set(rx_buf, mapping, mapping); + + rxbd->rx_bd_haddr_hi = (u64) mapping >> 32; + rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff; + + bp->rx_prod_bseq += bp->rx_buf_use_size; + + return 0; +} + +static void +bnx2_phy_int(struct bnx2 *bp) +{ + u32 new_link_state, old_link_state; + + new_link_state = bp->status_blk->status_attn_bits & + STATUS_ATTN_BITS_LINK_STATE; + old_link_state = bp->status_blk->status_attn_bits_ack & + STATUS_ATTN_BITS_LINK_STATE; + if (new_link_state != old_link_state) { + if (new_link_state) { + REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, + STATUS_ATTN_BITS_LINK_STATE); + } + else { + REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, + STATUS_ATTN_BITS_LINK_STATE); + } + bnx2_set_link(bp); + } +} + +static void +bnx2_tx_int(struct bnx2 *bp) +{ + u16 hw_cons, sw_cons, sw_ring_cons; + int tx_free_bd = 0; + + hw_cons = bp->status_blk->status_tx_quick_consumer_index0; + if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { + hw_cons++; + } + sw_cons = bp->tx_cons; + + while (sw_cons != hw_cons) { + struct sw_bd *tx_buf; + struct sk_buff *skb; + int i, last; + + sw_ring_cons = TX_RING_IDX(sw_cons); + + tx_buf = &bp->tx_buf_ring[sw_ring_cons]; + skb = tx_buf->skb; +#ifdef BCM_TSO + /* partial BD completions possible with TSO packets */ + if (skb_shinfo(skb)->tso_size) { + u16 last_idx, last_ring_idx; + + last_idx = sw_cons + + skb_shinfo(skb)->nr_frags + 1; + last_ring_idx = sw_ring_cons + + skb_shinfo(skb)->nr_frags + 1; + if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) { + last_idx++; + } + if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) { + break; + } + } +#endif + pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping), + skb_headlen(skb), PCI_DMA_TODEVICE); + + tx_buf->skb = NULL; + last = skb_shinfo(skb)->nr_frags; + + for (i = 0; i < last; i++) { + sw_cons = NEXT_TX_BD(sw_cons); + + pci_unmap_page(bp->pdev, + pci_unmap_addr( + &bp->tx_buf_ring[TX_RING_IDX(sw_cons)], + mapping), + skb_shinfo(skb)->frags[i].size, + PCI_DMA_TODEVICE); + } + + sw_cons = NEXT_TX_BD(sw_cons); + + tx_free_bd += last + 1; + + dev_kfree_skb_irq(skb); + + hw_cons = bp->status_blk->status_tx_quick_consumer_index0; + if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { + hw_cons++; + } + } + + atomic_add(tx_free_bd, &bp->tx_avail_bd); + + if (unlikely(netif_queue_stopped(bp->dev))) { + unsigned long flags; + + spin_lock_irqsave(&bp->tx_lock, flags); + if ((netif_queue_stopped(bp->dev)) && + (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)) { + + netif_wake_queue(bp->dev); + } + spin_unlock_irqrestore(&bp->tx_lock, flags); + } + + bp->tx_cons = sw_cons; + +} + +static inline void +bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, + u16 cons, u16 prod) +{ + struct sw_bd *cons_rx_buf = &bp->rx_buf_ring[cons]; + struct sw_bd *prod_rx_buf = &bp->rx_buf_ring[prod]; + struct rx_bd *cons_bd = &bp->rx_desc_ring[cons]; + struct rx_bd *prod_bd = &bp->rx_desc_ring[prod]; + + pci_dma_sync_single_for_device(bp->pdev, + pci_unmap_addr(cons_rx_buf, mapping), + bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE); + + prod_rx_buf->skb = cons_rx_buf->skb; + pci_unmap_addr_set(prod_rx_buf, mapping, + pci_unmap_addr(cons_rx_buf, mapping)); + + memcpy(prod_bd, cons_bd, 8); + + bp->rx_prod_bseq += bp->rx_buf_use_size; + +} + +static int +bnx2_rx_int(struct bnx2 *bp, int budget) +{ + u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; + struct l2_fhdr *rx_hdr; + int rx_pkt = 0; + + hw_cons = bp->status_blk->status_rx_quick_consumer_index0; + if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) { + hw_cons++; + } + sw_cons = bp->rx_cons; + sw_prod = bp->rx_prod; + + /* Memory barrier necessary as speculative reads of the rx + * buffer can be ahead of the index in the status block + */ + rmb(); + while (sw_cons != hw_cons) { + unsigned int len; + u16 status; + struct sw_bd *rx_buf; + struct sk_buff *skb; + + sw_ring_cons = RX_RING_IDX(sw_cons); + sw_ring_prod = RX_RING_IDX(sw_prod); + + rx_buf = &bp->rx_buf_ring[sw_ring_cons]; + skb = rx_buf->skb; + pci_dma_sync_single_for_cpu(bp->pdev, + pci_unmap_addr(rx_buf, mapping), + bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE); + + rx_hdr = (struct l2_fhdr *) skb->data; + len = rx_hdr->l2_fhdr_pkt_len - 4; + + if (rx_hdr->l2_fhdr_errors & + (L2_FHDR_ERRORS_BAD_CRC | + L2_FHDR_ERRORS_PHY_DECODE | + L2_FHDR_ERRORS_ALIGNMENT | + L2_FHDR_ERRORS_TOO_SHORT | + L2_FHDR_ERRORS_GIANT_FRAME)) { + + goto reuse_rx; + } + + /* Since we don't have a jumbo ring, copy small packets + * if mtu > 1500 + */ + if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) { + struct sk_buff *new_skb; + + new_skb = dev_alloc_skb(len + 2); + if (new_skb == NULL) + goto reuse_rx; + + /* aligned copy */ + memcpy(new_skb->data, + skb->data + bp->rx_offset - 2, + len + 2); + + skb_reserve(new_skb, 2); + skb_put(new_skb, len); + new_skb->dev = bp->dev; + + bnx2_reuse_rx_skb(bp, skb, + sw_ring_cons, sw_ring_prod); + + skb = new_skb; + } + else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) { + pci_unmap_single(bp->pdev, + pci_unmap_addr(rx_buf, mapping), + bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); + + skb_reserve(skb, bp->rx_offset); + skb_put(skb, len); + } + else { +reuse_rx: + bnx2_reuse_rx_skb(bp, skb, + sw_ring_cons, sw_ring_prod); + goto next_rx; + } + + skb->protocol = eth_type_trans(skb, bp->dev); + + if ((len > (bp->dev->mtu + ETH_HLEN)) && + (htons(skb->protocol) != 0x8100)) { + + dev_kfree_skb_irq(skb); + goto next_rx; + + } + + status = rx_hdr->l2_fhdr_status; + skb->ip_summed = CHECKSUM_NONE; + if (bp->rx_csum && + (status & (L2_FHDR_STATUS_TCP_SEGMENT | + L2_FHDR_STATUS_UDP_DATAGRAM))) { + + u16 cksum = rx_hdr->l2_fhdr_tcp_udp_xsum; + + if (cksum == 0xffff) + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + +#ifdef BCM_VLAN + if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && (bp->vlgrp != 0)) { + vlan_hwaccel_receive_skb(skb, bp->vlgrp, + rx_hdr->l2_fhdr_vlan_tag); + } + else +#endif + netif_receive_skb(skb); + + bp->dev->last_rx = jiffies; + rx_pkt++; + +next_rx: + rx_buf->skb = NULL; + + sw_cons = NEXT_RX_BD(sw_cons); + sw_prod = NEXT_RX_BD(sw_prod); + + if ((rx_pkt == budget)) + break; + } + bp->rx_cons = sw_cons; + bp->rx_prod = sw_prod; + + REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, sw_prod); + + REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq); + + mmiowb(); + + return rx_pkt; + +} + +/* MSI ISR - The only difference between this and the INTx ISR + * is that the MSI interrupt is always serviced. + */ +static irqreturn_t +bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *dev = dev_instance; + struct bnx2 *bp = dev->priv; + + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | + BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + + /* Return here if interrupt is disabled. */ + if (unlikely(atomic_read(&bp->intr_sem) != 0)) { + return IRQ_RETVAL(1); + } + + if (netif_rx_schedule_prep(dev)) { + __netif_rx_schedule(dev); + } + + return IRQ_RETVAL(1); +} + +static irqreturn_t +bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *dev = dev_instance; + struct bnx2 *bp = dev->priv; + + /* When using INTx, it is possible for the interrupt to arrive + * at the CPU before the status block posted prior to the + * interrupt. Reading a register will flush the status block. + * When using MSI, the MSI message will always complete after + * the status block write. + */ + if ((bp->status_blk->status_idx == bp->last_status_idx) || + (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & + BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) + return IRQ_RETVAL(0); + + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | + BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + + /* Return here if interrupt is shared and is disabled. */ + if (unlikely(atomic_read(&bp->intr_sem) != 0)) { + return IRQ_RETVAL(1); + } + + if (netif_rx_schedule_prep(dev)) { + __netif_rx_schedule(dev); + } + + return IRQ_RETVAL(1); +} + +static int +bnx2_poll(struct net_device *dev, int *budget) +{ + struct bnx2 *bp = dev->priv; + int rx_done = 1; + + bp->last_status_idx = bp->status_blk->status_idx; + + rmb(); + if ((bp->status_blk->status_attn_bits & + STATUS_ATTN_BITS_LINK_STATE) != + (bp->status_blk->status_attn_bits_ack & + STATUS_ATTN_BITS_LINK_STATE)) { + + unsigned long flags; + + spin_lock_irqsave(&bp->phy_lock, flags); + bnx2_phy_int(bp); + spin_unlock_irqrestore(&bp->phy_lock, flags); + } + + if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) { + bnx2_tx_int(bp); + } + + if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) { + int orig_budget = *budget; + int work_done; + + if (orig_budget > dev->quota) + orig_budget = dev->quota; + + work_done = bnx2_rx_int(bp, orig_budget); + *budget -= work_done; + dev->quota -= work_done; + + if (work_done >= orig_budget) { + rx_done = 0; + } + } + + if (rx_done) { + netif_rx_complete(dev); + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bp->last_status_idx); + return 0; + } + + return 1; +} + +/* Called with rtnl_lock from vlan functions and also dev->xmit_lock + * from set_multicast. + */ +static void +bnx2_set_rx_mode(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + u32 rx_mode, sort_mode; + int i; + unsigned long flags; + + spin_lock_irqsave(&bp->phy_lock, flags); + + rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS | + BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG); + sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN; +#ifdef BCM_VLAN + if (!bp->vlgrp) { + rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; + } +#else + rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; +#endif + if (dev->flags & IFF_PROMISC) { + /* Promiscuous mode. */ + rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS; + sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN; + } + else if (dev->flags & IFF_ALLMULTI) { + for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { + REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), + 0xffffffff); + } + sort_mode |= BNX2_RPM_SORT_USER0_MC_EN; + } + else { + /* Accept one or more multicast(s). */ + struct dev_mc_list *mclist; + u32 mc_filter[NUM_MC_HASH_REGISTERS]; + u32 regidx; + u32 bit; + u32 crc; + + memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS); + + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + + crc = ether_crc_le(ETH_ALEN, mclist->dmi_addr); + bit = crc & 0xff; + regidx = (bit & 0xe0) >> 5; + bit &= 0x1f; + mc_filter[regidx] |= (1 << bit); + } + + for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { + REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), + mc_filter[i]); + } + + sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN; + } + + if (rx_mode != bp->rx_mode) { + bp->rx_mode = rx_mode; + REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode); + } + + REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0); + REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode); + REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA); + + spin_unlock_irqrestore(&bp->phy_lock, flags); +} + +static void +load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, + u32 rv2p_proc) +{ + int i; + u32 val; + + + for (i = 0; i < rv2p_code_len; i += 8) { + REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code); + rv2p_code++; + REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code); + rv2p_code++; + + if (rv2p_proc == RV2P_PROC1) { + val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR; + REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val); + } + else { + val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR; + REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val); + } + } + + /* Reset the processor, un-stall is done later. */ + if (rv2p_proc == RV2P_PROC1) { + REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET); + } + else { + REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET); + } +} + +static void +load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) +{ + u32 offset; + u32 val; + + /* Halt the CPU. */ + val = REG_RD_IND(bp, cpu_reg->mode); + val |= cpu_reg->mode_value_halt; + REG_WR_IND(bp, cpu_reg->mode, val); + REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear); + + /* Load the Text area. */ + offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base); + if (fw->text) { + int j; + + for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { + REG_WR_IND(bp, offset, fw->text[j]); + } + } + + /* Load the Data area. */ + offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base); + if (fw->data) { + int j; + + for (j = 0; j < (fw->data_len / 4); j++, offset += 4) { + REG_WR_IND(bp, offset, fw->data[j]); + } + } + + /* Load the SBSS area. */ + offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base); + if (fw->sbss) { + int j; + + for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) { + REG_WR_IND(bp, offset, fw->sbss[j]); + } + } + + /* Load the BSS area. */ + offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base); + if (fw->bss) { + int j; + + for (j = 0; j < (fw->bss_len/4); j++, offset += 4) { + REG_WR_IND(bp, offset, fw->bss[j]); + } + } + + /* Load the Read-Only area. */ + offset = cpu_reg->spad_base + + (fw->rodata_addr - cpu_reg->mips_view_base); + if (fw->rodata) { + int j; + + for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) { + REG_WR_IND(bp, offset, fw->rodata[j]); + } + } + + /* Clear the pre-fetch instruction. */ + REG_WR_IND(bp, cpu_reg->inst, 0); + REG_WR_IND(bp, cpu_reg->pc, fw->start_addr); + + /* Start the CPU. */ + val = REG_RD_IND(bp, cpu_reg->mode); + val &= ~cpu_reg->mode_value_halt; + REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear); + REG_WR_IND(bp, cpu_reg->mode, val); +} + +static void +bnx2_init_cpus(struct bnx2 *bp) +{ + struct cpu_reg cpu_reg; + struct fw_info fw; + + /* Initialize the RV2P processor. */ + load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1); + load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2); + + /* Initialize the RX Processor. */ + cpu_reg.mode = BNX2_RXP_CPU_MODE; + cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT; + cpu_reg.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA; + cpu_reg.state = BNX2_RXP_CPU_STATE; + cpu_reg.state_value_clear = 0xffffff; + cpu_reg.gpr0 = BNX2_RXP_CPU_REG_FILE; + cpu_reg.evmask = BNX2_RXP_CPU_EVENT_MASK; + cpu_reg.pc = BNX2_RXP_CPU_PROGRAM_COUNTER; + cpu_reg.inst = BNX2_RXP_CPU_INSTRUCTION; + cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT; + cpu_reg.spad_base = BNX2_RXP_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + + fw.ver_major = bnx2_RXP_b06FwReleaseMajor; + fw.ver_minor = bnx2_RXP_b06FwReleaseMinor; + fw.ver_fix = bnx2_RXP_b06FwReleaseFix; + fw.start_addr = bnx2_RXP_b06FwStartAddr; + + fw.text_addr = bnx2_RXP_b06FwTextAddr; + fw.text_len = bnx2_RXP_b06FwTextLen; + fw.text_index = 0; + fw.text = bnx2_RXP_b06FwText; + + fw.data_addr = bnx2_RXP_b06FwDataAddr; + fw.data_len = bnx2_RXP_b06FwDataLen; + fw.data_index = 0; + fw.data = bnx2_RXP_b06FwData; + + fw.sbss_addr = bnx2_RXP_b06FwSbssAddr; + fw.sbss_len = bnx2_RXP_b06FwSbssLen; + fw.sbss_index = 0; + fw.sbss = bnx2_RXP_b06FwSbss; + + fw.bss_addr = bnx2_RXP_b06FwBssAddr; + fw.bss_len = bnx2_RXP_b06FwBssLen; + fw.bss_index = 0; + fw.bss = bnx2_RXP_b06FwBss; + + fw.rodata_addr = bnx2_RXP_b06FwRodataAddr; + fw.rodata_len = bnx2_RXP_b06FwRodataLen; + fw.rodata_index = 0; + fw.rodata = bnx2_RXP_b06FwRodata; + + load_cpu_fw(bp, &cpu_reg, &fw); + + /* Initialize the TX Processor. */ + cpu_reg.mode = BNX2_TXP_CPU_MODE; + cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT; + cpu_reg.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA; + cpu_reg.state = BNX2_TXP_CPU_STATE; + cpu_reg.state_value_clear = 0xffffff; + cpu_reg.gpr0 = BNX2_TXP_CPU_REG_FILE; + cpu_reg.evmask = BNX2_TXP_CPU_EVENT_MASK; + cpu_reg.pc = BNX2_TXP_CPU_PROGRAM_COUNTER; + cpu_reg.inst = BNX2_TXP_CPU_INSTRUCTION; + cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT; + cpu_reg.spad_base = BNX2_TXP_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + + fw.ver_major = bnx2_TXP_b06FwReleaseMajor; + fw.ver_minor = bnx2_TXP_b06FwReleaseMinor; + fw.ver_fix = bnx2_TXP_b06FwReleaseFix; + fw.start_addr = bnx2_TXP_b06FwStartAddr; + + fw.text_addr = bnx2_TXP_b06FwTextAddr; + fw.text_len = bnx2_TXP_b06FwTextLen; + fw.text_index = 0; + fw.text = bnx2_TXP_b06FwText; + + fw.data_addr = bnx2_TXP_b06FwDataAddr; + fw.data_len = bnx2_TXP_b06FwDataLen; + fw.data_index = 0; + fw.data = bnx2_TXP_b06FwData; + + fw.sbss_addr = bnx2_TXP_b06FwSbssAddr; + fw.sbss_len = bnx2_TXP_b06FwSbssLen; + fw.sbss_index = 0; + fw.sbss = bnx2_TXP_b06FwSbss; + + fw.bss_addr = bnx2_TXP_b06FwBssAddr; + fw.bss_len = bnx2_TXP_b06FwBssLen; + fw.bss_index = 0; + fw.bss = bnx2_TXP_b06FwBss; + + fw.rodata_addr = bnx2_TXP_b06FwRodataAddr; + fw.rodata_len = bnx2_TXP_b06FwRodataLen; + fw.rodata_index = 0; + fw.rodata = bnx2_TXP_b06FwRodata; + + load_cpu_fw(bp, &cpu_reg, &fw); + + /* Initialize the TX Patch-up Processor. */ + cpu_reg.mode = BNX2_TPAT_CPU_MODE; + cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT; + cpu_reg.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA; + cpu_reg.state = BNX2_TPAT_CPU_STATE; + cpu_reg.state_value_clear = 0xffffff; + cpu_reg.gpr0 = BNX2_TPAT_CPU_REG_FILE; + cpu_reg.evmask = BNX2_TPAT_CPU_EVENT_MASK; + cpu_reg.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER; + cpu_reg.inst = BNX2_TPAT_CPU_INSTRUCTION; + cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT; + cpu_reg.spad_base = BNX2_TPAT_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + + fw.ver_major = bnx2_TPAT_b06FwReleaseMajor; + fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor; + fw.ver_fix = bnx2_TPAT_b06FwReleaseFix; + fw.start_addr = bnx2_TPAT_b06FwStartAddr; + + fw.text_addr = bnx2_TPAT_b06FwTextAddr; + fw.text_len = bnx2_TPAT_b06FwTextLen; + fw.text_index = 0; + fw.text = bnx2_TPAT_b06FwText; + + fw.data_addr = bnx2_TPAT_b06FwDataAddr; + fw.data_len = bnx2_TPAT_b06FwDataLen; + fw.data_index = 0; + fw.data = bnx2_TPAT_b06FwData; + + fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr; + fw.sbss_len = bnx2_TPAT_b06FwSbssLen; + fw.sbss_index = 0; + fw.sbss = bnx2_TPAT_b06FwSbss; + + fw.bss_addr = bnx2_TPAT_b06FwBssAddr; + fw.bss_len = bnx2_TPAT_b06FwBssLen; + fw.bss_index = 0; + fw.bss = bnx2_TPAT_b06FwBss; + + fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr; + fw.rodata_len = bnx2_TPAT_b06FwRodataLen; + fw.rodata_index = 0; + fw.rodata = bnx2_TPAT_b06FwRodata; + + load_cpu_fw(bp, &cpu_reg, &fw); + + /* Initialize the Completion Processor. */ + cpu_reg.mode = BNX2_COM_CPU_MODE; + cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT; + cpu_reg.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA; + cpu_reg.state = BNX2_COM_CPU_STATE; + cpu_reg.state_value_clear = 0xffffff; + cpu_reg.gpr0 = BNX2_COM_CPU_REG_FILE; + cpu_reg.evmask = BNX2_COM_CPU_EVENT_MASK; + cpu_reg.pc = BNX2_COM_CPU_PROGRAM_COUNTER; + cpu_reg.inst = BNX2_COM_CPU_INSTRUCTION; + cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT; + cpu_reg.spad_base = BNX2_COM_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + + fw.ver_major = bnx2_COM_b06FwReleaseMajor; + fw.ver_minor = bnx2_COM_b06FwReleaseMinor; + fw.ver_fix = bnx2_COM_b06FwReleaseFix; + fw.start_addr = bnx2_COM_b06FwStartAddr; + + fw.text_addr = bnx2_COM_b06FwTextAddr; + fw.text_len = bnx2_COM_b06FwTextLen; + fw.text_index = 0; + fw.text = bnx2_COM_b06FwText; + + fw.data_addr = bnx2_COM_b06FwDataAddr; + fw.data_len = bnx2_COM_b06FwDataLen; + fw.data_index = 0; + fw.data = bnx2_COM_b06FwData; + + fw.sbss_addr = bnx2_COM_b06FwSbssAddr; + fw.sbss_len = bnx2_COM_b06FwSbssLen; + fw.sbss_index = 0; + fw.sbss = bnx2_COM_b06FwSbss; + + fw.bss_addr = bnx2_COM_b06FwBssAddr; + fw.bss_len = bnx2_COM_b06FwBssLen; + fw.bss_index = 0; + fw.bss = bnx2_COM_b06FwBss; + + fw.rodata_addr = bnx2_COM_b06FwRodataAddr; + fw.rodata_len = bnx2_COM_b06FwRodataLen; + fw.rodata_index = 0; + fw.rodata = bnx2_COM_b06FwRodata; + + load_cpu_fw(bp, &cpu_reg, &fw); + +} + +static int +bnx2_set_power_state(struct bnx2 *bp, int state) +{ + u16 pmcsr; + + pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); + + switch (state) { + case 0: { + u32 val; + + pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, + (pmcsr & ~PCI_PM_CTRL_STATE_MASK) | + PCI_PM_CTRL_PME_STATUS); + + if (pmcsr & PCI_PM_CTRL_STATE_MASK) + /* delay required during transition out of D3hot */ + msleep(20); + + val = REG_RD(bp, BNX2_EMAC_MODE); + val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD; + val &= ~BNX2_EMAC_MODE_MPKT; + REG_WR(bp, BNX2_EMAC_MODE, val); + + val = REG_RD(bp, BNX2_RPM_CONFIG); + val &= ~BNX2_RPM_CONFIG_ACPI_ENA; + REG_WR(bp, BNX2_RPM_CONFIG, val); + break; + } + case 3: { + int i; + u32 val, wol_msg; + + if (bp->wol) { + u32 advertising; + u8 autoneg; + + autoneg = bp->autoneg; + advertising = bp->advertising; + + bp->autoneg = AUTONEG_SPEED; + bp->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_Autoneg; + + bnx2_setup_copper_phy(bp); + + bp->autoneg = autoneg; + bp->advertising = advertising; + + bnx2_set_mac_addr(bp); + + val = REG_RD(bp, BNX2_EMAC_MODE); + + /* Enable port mode. */ + val &= ~BNX2_EMAC_MODE_PORT; + val |= BNX2_EMAC_MODE_PORT_MII | + BNX2_EMAC_MODE_MPKT_RCVD | + BNX2_EMAC_MODE_ACPI_RCVD | + BNX2_EMAC_MODE_FORCE_LINK | + BNX2_EMAC_MODE_MPKT; + + REG_WR(bp, BNX2_EMAC_MODE, val); + + /* receive all multicast */ + for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { + REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), + 0xffffffff); + } + REG_WR(bp, BNX2_EMAC_RX_MODE, + BNX2_EMAC_RX_MODE_SORT_MODE); + + val = 1 | BNX2_RPM_SORT_USER0_BC_EN | + BNX2_RPM_SORT_USER0_MC_EN; + REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0); + REG_WR(bp, BNX2_RPM_SORT_USER0, val); + REG_WR(bp, BNX2_RPM_SORT_USER0, val | + BNX2_RPM_SORT_USER0_ENA); + + /* Need to enable EMAC and RPM for WOL. */ + REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, + BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE | + BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE | + BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE); + + val = REG_RD(bp, BNX2_RPM_CONFIG); + val &= ~BNX2_RPM_CONFIG_ACPI_ENA; + REG_WR(bp, BNX2_RPM_CONFIG, val); + + wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL; + } + else { + wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; + } + + bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg); + + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; + if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || + (CHIP_ID(bp) == CHIP_ID_5706_A1)) { + + if (bp->wol) + pmcsr |= 3; + } + else { + pmcsr |= 3; + } + if (bp->wol) { + pmcsr |= PCI_PM_CTRL_PME_ENABLE; + } + pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, + pmcsr); + + /* No more memory access after this point until + * device is brought back to D0. + */ + udelay(50); + break; + } + default: + return -EINVAL; + } + return 0; +} + +static int +bnx2_acquire_nvram_lock(struct bnx2 *bp) +{ + u32 val; + int j; + + /* Request access to the flash interface. */ + REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2); + for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { + val = REG_RD(bp, BNX2_NVM_SW_ARB); + if (val & BNX2_NVM_SW_ARB_ARB_ARB2) + break; + + udelay(5); + } + + if (j >= NVRAM_TIMEOUT_COUNT) + return -EBUSY; + + return 0; +} + +static int +bnx2_release_nvram_lock(struct bnx2 *bp) +{ + int j; + u32 val; + + /* Relinquish nvram interface. */ + REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2); + + for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { + val = REG_RD(bp, BNX2_NVM_SW_ARB); + if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2)) + break; + + udelay(5); + } + + if (j >= NVRAM_TIMEOUT_COUNT) + return -EBUSY; + + return 0; +} + + +static int +bnx2_enable_nvram_write(struct bnx2 *bp) +{ + u32 val; + + val = REG_RD(bp, BNX2_MISC_CFG); + REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI); + + if (!bp->flash_info->buffered) { + int j; + + REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + REG_WR(bp, BNX2_NVM_COMMAND, + BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT); + + for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { + udelay(5); + + val = REG_RD(bp, BNX2_NVM_COMMAND); + if (val & BNX2_NVM_COMMAND_DONE) + break; + } + + if (j >= NVRAM_TIMEOUT_COUNT) + return -EBUSY; + } + return 0; +} + +static void +bnx2_disable_nvram_write(struct bnx2 *bp) +{ + u32 val; + + val = REG_RD(bp, BNX2_MISC_CFG); + REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN); +} + + +static void +bnx2_enable_nvram_access(struct bnx2 *bp) +{ + u32 val; + + val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); + /* Enable both bits, even on read. */ + REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, + val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN); +} + +static void +bnx2_disable_nvram_access(struct bnx2 *bp) +{ + u32 val; + + val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); + /* Disable both bits, even after read. */ + REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, + val & ~(BNX2_NVM_ACCESS_ENABLE_EN | + BNX2_NVM_ACCESS_ENABLE_WR_EN)); +} + +static int +bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset) +{ + u32 cmd; + int j; + + if (bp->flash_info->buffered) + /* Buffered flash, no erase needed */ + return 0; + + /* Build an erase command */ + cmd = BNX2_NVM_COMMAND_ERASE | BNX2_NVM_COMMAND_WR | + BNX2_NVM_COMMAND_DOIT; + + /* Need to clear DONE bit separately. */ + REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + + /* Address of the NVRAM to read from. */ + REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); + + /* Issue an erase command. */ + REG_WR(bp, BNX2_NVM_COMMAND, cmd); + + /* Wait for completion. */ + for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { + u32 val; + + udelay(5); + + val = REG_RD(bp, BNX2_NVM_COMMAND); + if (val & BNX2_NVM_COMMAND_DONE) + break; + } + + if (j >= NVRAM_TIMEOUT_COUNT) + return -EBUSY; + + return 0; +} + +static int +bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags) +{ + u32 cmd; + int j; + + /* Build the command word. */ + cmd = BNX2_NVM_COMMAND_DOIT | cmd_flags; + + /* Calculate an offset of a buffered flash. */ + if (bp->flash_info->buffered) { + offset = ((offset / bp->flash_info->page_size) << + bp->flash_info->page_bits) + + (offset % bp->flash_info->page_size); + } + + /* Need to clear DONE bit separately. */ + REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + + /* Address of the NVRAM to read from. */ + REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); + + /* Issue a read command. */ + REG_WR(bp, BNX2_NVM_COMMAND, cmd); + + /* Wait for completion. */ + for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { + u32 val; + + udelay(5); + + val = REG_RD(bp, BNX2_NVM_COMMAND); + if (val & BNX2_NVM_COMMAND_DONE) { + val = REG_RD(bp, BNX2_NVM_READ); + + val = be32_to_cpu(val); + memcpy(ret_val, &val, 4); + break; + } + } + if (j >= NVRAM_TIMEOUT_COUNT) + return -EBUSY; + + return 0; +} + + +static int +bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags) +{ + u32 cmd, val32; + int j; + + /* Build the command word. */ + cmd = BNX2_NVM_COMMAND_DOIT | BNX2_NVM_COMMAND_WR | cmd_flags; + + /* Calculate an offset of a buffered flash. */ + if (bp->flash_info->buffered) { + offset = ((offset / bp->flash_info->page_size) << + bp->flash_info->page_bits) + + (offset % bp->flash_info->page_size); + } + + /* Need to clear DONE bit separately. */ + REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + + memcpy(&val32, val, 4); + val32 = cpu_to_be32(val32); + + /* Write the data. */ + REG_WR(bp, BNX2_NVM_WRITE, val32); + + /* Address of the NVRAM to write to. */ + REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); + + /* Issue the write command. */ + REG_WR(bp, BNX2_NVM_COMMAND, cmd); + + /* Wait for completion. */ + for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { + udelay(5); + + if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE) + break; + } + if (j >= NVRAM_TIMEOUT_COUNT) + return -EBUSY; + + return 0; +} + +static int +bnx2_init_nvram(struct bnx2 *bp) +{ + u32 val; + int j, entry_count, rc; + struct flash_spec *flash; + + /* Determine the selected interface. */ + val = REG_RD(bp, BNX2_NVM_CFG1); + + entry_count = sizeof(flash_table) / sizeof(struct flash_spec); + + rc = 0; + if (val & 0x40000000) { + + /* Flash interface has been reconfigured */ + for (j = 0, flash = &flash_table[0]; j < entry_count; + j++, flash++) { + + if (val == flash->config1) { + bp->flash_info = flash; + break; + } + } + } + else { + /* Not yet been reconfigured */ + + for (j = 0, flash = &flash_table[0]; j < entry_count; + j++, flash++) { + + if ((val & FLASH_STRAP_MASK) == flash->strapping) { + bp->flash_info = flash; + + /* Request access to the flash interface. */ + if ((rc = bnx2_acquire_nvram_lock(bp)) != 0) + return rc; + + /* Enable access to flash interface */ + bnx2_enable_nvram_access(bp); + + /* Reconfigure the flash interface */ + REG_WR(bp, BNX2_NVM_CFG1, flash->config1); + REG_WR(bp, BNX2_NVM_CFG2, flash->config2); + REG_WR(bp, BNX2_NVM_CFG3, flash->config3); + REG_WR(bp, BNX2_NVM_WRITE1, flash->write1); + + /* Disable access to flash interface */ + bnx2_disable_nvram_access(bp); + bnx2_release_nvram_lock(bp); + + break; + } + } + } /* if (val & 0x40000000) */ + + if (j == entry_count) { + bp->flash_info = NULL; + printk(KERN_ALERT "Unknown flash/EEPROM type.\n"); + rc = -ENODEV; + } + + return rc; +} + +static int +bnx2_nvram_read(struct bnx2 *bp, u32 offset, u8 *ret_buf, + int buf_size) +{ + int rc = 0; + u32 cmd_flags, offset32, len32, extra; + + if (buf_size == 0) + return 0; + + /* Request access to the flash interface. */ + if ((rc = bnx2_acquire_nvram_lock(bp)) != 0) + return rc; + + /* Enable access to flash interface */ + bnx2_enable_nvram_access(bp); + + len32 = buf_size; + offset32 = offset; + extra = 0; + + cmd_flags = 0; + + if (offset32 & 3) { + u8 buf[4]; + u32 pre_len; + + offset32 &= ~3; + pre_len = 4 - (offset & 3); + + if (pre_len >= len32) { + pre_len = len32; + cmd_flags = BNX2_NVM_COMMAND_FIRST | + BNX2_NVM_COMMAND_LAST; + } + else { + cmd_flags = BNX2_NVM_COMMAND_FIRST; + } + + rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags); + + if (rc) + return rc; + + memcpy(ret_buf, buf + (offset & 3), pre_len); + + offset32 += 4; + ret_buf += pre_len; + len32 -= pre_len; + } + if (len32 & 3) { + extra = 4 - (len32 & 3); + len32 = (len32 + 4) & ~3; + } + + if (len32 == 4) { + u8 buf[4]; + + if (cmd_flags) + cmd_flags = BNX2_NVM_COMMAND_LAST; + else + cmd_flags = BNX2_NVM_COMMAND_FIRST | + BNX2_NVM_COMMAND_LAST; + + rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags); + + memcpy(ret_buf, buf, 4 - extra); + } + else if (len32 > 0) { + u8 buf[4]; + + /* Read the first word. */ + if (cmd_flags) + cmd_flags = 0; + else + cmd_flags = BNX2_NVM_COMMAND_FIRST; + + rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, cmd_flags); + + /* Advance to the next dword. */ + offset32 += 4; + ret_buf += 4; + len32 -= 4; + + while (len32 > 4 && rc == 0) { + rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, 0); + + /* Advance to the next dword. */ + offset32 += 4; + ret_buf += 4; + len32 -= 4; + } + + if (rc) + return rc; + + cmd_flags = BNX2_NVM_COMMAND_LAST; + rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags); + + memcpy(ret_buf, buf, 4 - extra); + } + + /* Disable access to flash interface */ + bnx2_disable_nvram_access(bp); + + bnx2_release_nvram_lock(bp); + + return rc; +} + +static int +bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, + int buf_size) +{ + u32 written, offset32, len32; + u8 *buf, start[4], end[4]; + int rc = 0; + int align_start, align_end; + + buf = data_buf; + offset32 = offset; + len32 = buf_size; + align_start = align_end = 0; + + if ((align_start = (offset32 & 3))) { + offset32 &= ~3; + len32 += align_start; + if ((rc = bnx2_nvram_read(bp, offset32, start, 4))) + return rc; + } + + if (len32 & 3) { + if ((len32 > 4) || !align_start) { + align_end = 4 - (len32 & 3); + len32 += align_end; + if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, + end, 4))) { + return rc; + } + } + } + + if (align_start || align_end) { + buf = kmalloc(len32, GFP_KERNEL); + if (buf == 0) + return -ENOMEM; + if (align_start) { + memcpy(buf, start, 4); + } + if (align_end) { + memcpy(buf + len32 - 4, end, 4); + } + memcpy(buf + align_start, data_buf, buf_size); + } + + written = 0; + while ((written < len32) && (rc == 0)) { + u32 page_start, page_end, data_start, data_end; + u32 addr, cmd_flags; + int i; + u8 flash_buffer[264]; + + /* Find the page_start addr */ + page_start = offset32 + written; + page_start -= (page_start % bp->flash_info->page_size); + /* Find the page_end addr */ + page_end = page_start + bp->flash_info->page_size; + /* Find the data_start addr */ + data_start = (written == 0) ? offset32 : page_start; + /* Find the data_end addr */ + data_end = (page_end > offset32 + len32) ? + (offset32 + len32) : page_end; + + /* Request access to the flash interface. */ + if ((rc = bnx2_acquire_nvram_lock(bp)) != 0) + goto nvram_write_end; + + /* Enable access to flash interface */ + bnx2_enable_nvram_access(bp); + + cmd_flags = BNX2_NVM_COMMAND_FIRST; + if (bp->flash_info->buffered == 0) { + int j; + + /* Read the whole page into the buffer + * (non-buffer flash only) */ + for (j = 0; j < bp->flash_info->page_size; j += 4) { + if (j == (bp->flash_info->page_size - 4)) { + cmd_flags |= BNX2_NVM_COMMAND_LAST; + } + rc = bnx2_nvram_read_dword(bp, + page_start + j, + &flash_buffer[j], + cmd_flags); + + if (rc) + goto nvram_write_end; + + cmd_flags = 0; + } + } + + /* Enable writes to flash interface (unlock write-protect) */ + if ((rc = bnx2_enable_nvram_write(bp)) != 0) + goto nvram_write_end; + + /* Erase the page */ + if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0) + goto nvram_write_end; + + /* Re-enable the write again for the actual write */ + bnx2_enable_nvram_write(bp); + + /* Loop to write back the buffer data from page_start to + * data_start */ + i = 0; + if (bp->flash_info->buffered == 0) { + for (addr = page_start; addr < data_start; + addr += 4, i += 4) { + + rc = bnx2_nvram_write_dword(bp, addr, + &flash_buffer[i], cmd_flags); + + if (rc != 0) + goto nvram_write_end; + + cmd_flags = 0; + } + } + + /* Loop to write the new data from data_start to data_end */ + for (addr = data_start; addr < data_end; addr += 4, i++) { + if ((addr == page_end - 4) || + ((bp->flash_info->buffered) && + (addr == data_end - 4))) { + + cmd_flags |= BNX2_NVM_COMMAND_LAST; + } + rc = bnx2_nvram_write_dword(bp, addr, buf, + cmd_flags); + + if (rc != 0) + goto nvram_write_end; + + cmd_flags = 0; + buf += 4; + } + + /* Loop to write back the buffer data from data_end + * to page_end */ + if (bp->flash_info->buffered == 0) { + for (addr = data_end; addr < page_end; + addr += 4, i += 4) { + + if (addr == page_end-4) { + cmd_flags = BNX2_NVM_COMMAND_LAST; + } + rc = bnx2_nvram_write_dword(bp, addr, + &flash_buffer[i], cmd_flags); + + if (rc != 0) + goto nvram_write_end; + + cmd_flags = 0; + } + } + + /* Disable writes to flash interface (lock write-protect) */ + bnx2_disable_nvram_write(bp); + + /* Disable access to flash interface */ + bnx2_disable_nvram_access(bp); + bnx2_release_nvram_lock(bp); + + /* Increment written */ + written += data_end - data_start; + } + +nvram_write_end: + if (align_start || align_end) + kfree(buf); + return rc; +} + +static int +bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) +{ + u32 val; + int i, rc = 0; + + /* Wait for the current PCI transaction to complete before + * issuing a reset. */ + REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, + BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); + val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); + udelay(5); + + /* Deposit a driver reset signature so the firmware knows that + * this is a soft reset. */ + REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_RESET_SIGNATURE, + BNX2_DRV_RESET_SIGNATURE_MAGIC); + + bp->fw_timed_out = 0; + + /* Wait for the firmware to tell us it is ok to issue a reset. */ + bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code); + + /* Do a dummy read to force the chip to complete all current transaction + * before we issue a reset. */ + val = REG_RD(bp, BNX2_MISC_ID); + + val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | + BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; + + /* Chip reset. */ + REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); + + if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || + (CHIP_ID(bp) == CHIP_ID_5706_A1)) + msleep(15); + + /* Reset takes approximate 30 usec */ + for (i = 0; i < 10; i++) { + val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG); + if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | + BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) { + break; + } + udelay(10); + } + + if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | + BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { + printk(KERN_ERR PFX "Chip reset did not complete\n"); + return -EBUSY; + } + + /* Make sure byte swapping is properly configured. */ + val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0); + if (val != 0x01020304) { + printk(KERN_ERR PFX "Chip not in correct endian mode\n"); + return -ENODEV; + } + + bp->fw_timed_out = 0; + + /* Wait for the firmware to finish its initialization. */ + bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code); + + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + /* Adjust the voltage regular to two steps lower. The default + * of this register is 0x0000000e. */ + REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa); + + /* Remove bad rbuf memory from the free pool. */ + rc = bnx2_alloc_bad_rbuf(bp); + } + + return rc; +} + +static int +bnx2_init_chip(struct bnx2 *bp) +{ + u32 val; + + /* Make sure the interrupt is not active. */ + REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + + val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP | + BNX2_DMA_CONFIG_DATA_WORD_SWAP | +#ifdef __BIG_ENDIAN + BNX2_DMA_CONFIG_CNTL_BYTE_SWAP | +#endif + BNX2_DMA_CONFIG_CNTL_WORD_SWAP | + DMA_READ_CHANS << 12 | + DMA_WRITE_CHANS << 16; + + val |= (0x2 << 20) | (1 << 11); + + if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz = 133)) + val |= (1 << 23); + + if ((CHIP_NUM(bp) == CHIP_NUM_5706) && + (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & PCIX_FLAG)) + val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA; + + REG_WR(bp, BNX2_DMA_CONFIG, val); + + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + val = REG_RD(bp, BNX2_TDMA_CONFIG); + val |= BNX2_TDMA_CONFIG_ONE_DMA; + REG_WR(bp, BNX2_TDMA_CONFIG, val); + } + + if (bp->flags & PCIX_FLAG) { + u16 val16; + + pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD, + &val16); + pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD, + val16 & ~PCI_X_CMD_ERO); + } + + REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, + BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE | + BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE | + BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE); + + /* Initialize context mapping and zero out the quick contexts. The + * context block must have already been enabled. */ + bnx2_init_context(bp); + + bnx2_init_cpus(bp); + bnx2_init_nvram(bp); + + bnx2_set_mac_addr(bp); + + val = REG_RD(bp, BNX2_MQ_CONFIG); + val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE; + val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256; + REG_WR(bp, BNX2_MQ_CONFIG, val); + + val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE); + REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val); + REG_WR(bp, BNX2_MQ_KNL_WIND_END, val); + + val = (BCM_PAGE_BITS - 8) << 24; + REG_WR(bp, BNX2_RV2P_CONFIG, val); + + /* Configure page size. */ + val = REG_RD(bp, BNX2_TBDR_CONFIG); + val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE; + val |= (BCM_PAGE_BITS - 8) << 24 | 0x40; + REG_WR(bp, BNX2_TBDR_CONFIG, val); + + val = bp->mac_addr[0] + + (bp->mac_addr[1] << 8) + + (bp->mac_addr[2] << 16) + + bp->mac_addr[3] + + (bp->mac_addr[4] << 8) + + (bp->mac_addr[5] << 16); + REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val); + + /* Program the MTU. Also include 4 bytes for CRC32. */ + val = bp->dev->mtu + ETH_HLEN + 4; + if (val > (MAX_ETHERNET_PACKET_SIZE + 4)) + val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA; + REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val); + + bp->last_status_idx = 0; + bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE; + + /* Set up how to generate a link change interrupt. */ + REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); + + REG_WR(bp, BNX2_HC_STATUS_ADDR_L, + (u64) bp->status_blk_mapping & 0xffffffff); + REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32); + + REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L, + (u64) bp->stats_blk_mapping & 0xffffffff); + REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H, + (u64) bp->stats_blk_mapping >> 32); + + REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, + (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); + + REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP, + (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip); + + REG_WR(bp, BNX2_HC_COMP_PROD_TRIP, + (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip); + + REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks); + + REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks); + + REG_WR(bp, BNX2_HC_COM_TICKS, + (bp->com_ticks_int << 16) | bp->com_ticks); + + REG_WR(bp, BNX2_HC_CMD_TICKS, + (bp->cmd_ticks_int << 16) | bp->cmd_ticks); + + REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); + REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ + + if (CHIP_ID(bp) == CHIP_ID_5706_A1) + REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS); + else { + REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE | + BNX2_HC_CONFIG_TX_TMR_MODE | + BNX2_HC_CONFIG_COLLECT_STATS); + } + + /* Clear internal stats counters. */ + REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); + + REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE); + + /* Initialize the receive filter. */ + bnx2_set_rx_mode(bp->dev); + + bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET); + + REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); + REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); + + udelay(20); + + return 0; +} + + +static void +bnx2_init_tx_ring(struct bnx2 *bp) +{ + struct tx_bd *txbd; + u32 val; + + txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT]; + + txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32; + txbd->tx_bd_haddr_lo = (u64) bp->tx_desc_mapping & 0xffffffff; + + bp->tx_prod = 0; + bp->tx_cons = 0; + bp->tx_prod_bseq = 0; + atomic_set(&bp->tx_avail_bd, bp->tx_ring_size); + + val = BNX2_L2CTX_TYPE_TYPE_L2; + val |= BNX2_L2CTX_TYPE_SIZE_L2; + CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val); + + val = BNX2_L2CTX_CMD_TYPE_TYPE_L2; + val |= 8 << 16; + CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val); + + val = (u64) bp->tx_desc_mapping >> 32; + CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, val); + + val = (u64) bp->tx_desc_mapping & 0xffffffff; + CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val); +} + +static void +bnx2_init_rx_ring(struct bnx2 *bp) +{ + struct rx_bd *rxbd; + int i; + u16 prod, ring_prod; + u32 val; + + /* 8 for CRC and VLAN */ + bp->rx_buf_use_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8; + /* 8 for alignment */ + bp->rx_buf_size = bp->rx_buf_use_size + 8; + + ring_prod = prod = bp->rx_prod = 0; + bp->rx_cons = 0; + bp->rx_prod_bseq = 0; + + rxbd = &bp->rx_desc_ring[0]; + for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { + rxbd->rx_bd_len = bp->rx_buf_use_size; + rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; + } + + rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping >> 32; + rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff; + + val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE; + val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2; + val |= 0x02 << 8; + CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val); + + val = (u64) bp->rx_desc_mapping >> 32; + CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val); + + val = (u64) bp->rx_desc_mapping & 0xffffffff; + CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val); + + for ( ;ring_prod < bp->rx_ring_size; ) { + if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) { + break; + } + prod = NEXT_RX_BD(prod); + ring_prod = RX_RING_IDX(prod); + } + bp->rx_prod = prod; + + REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, prod); + + REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq); +} + +static void +bnx2_free_tx_skbs(struct bnx2 *bp) +{ + int i; + + if (bp->tx_buf_ring == NULL) + return; + + for (i = 0; i < TX_DESC_CNT; ) { + struct sw_bd *tx_buf = &bp->tx_buf_ring[i]; + struct sk_buff *skb = tx_buf->skb; + int j, last; + + if (skb == NULL) { + i++; + continue; + } + + pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping), + skb_headlen(skb), PCI_DMA_TODEVICE); + + tx_buf->skb = NULL; + + last = skb_shinfo(skb)->nr_frags; + for (j = 0; j < last; j++) { + tx_buf = &bp->tx_buf_ring[i + j + 1]; + pci_unmap_page(bp->pdev, + pci_unmap_addr(tx_buf, mapping), + skb_shinfo(skb)->frags[j].size, + PCI_DMA_TODEVICE); + } + dev_kfree_skb_any(skb); + i += j + 1; + } + +} + +static void +bnx2_free_rx_skbs(struct bnx2 *bp) +{ + int i; + + if (bp->rx_buf_ring == NULL) + return; + + for (i = 0; i < RX_DESC_CNT; i++) { + struct sw_bd *rx_buf = &bp->rx_buf_ring[i]; + struct sk_buff *skb = rx_buf->skb; + + if (skb == 0) + continue; + + pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping), + bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); + + rx_buf->skb = NULL; + + dev_kfree_skb_any(skb); + } +} + +static void +bnx2_free_skbs(struct bnx2 *bp) +{ + bnx2_free_tx_skbs(bp); + bnx2_free_rx_skbs(bp); +} + +static int +bnx2_reset_nic(struct bnx2 *bp, u32 reset_code) +{ + int rc; + + rc = bnx2_reset_chip(bp, reset_code); + bnx2_free_skbs(bp); + if (rc) + return rc; + + bnx2_init_chip(bp); + bnx2_init_tx_ring(bp); + bnx2_init_rx_ring(bp); + return 0; +} + +static int +bnx2_init_nic(struct bnx2 *bp) +{ + int rc; + + if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0) + return rc; + + bnx2_init_phy(bp); + bnx2_set_link(bp); + return 0; +} + +static int +bnx2_test_registers(struct bnx2 *bp) +{ + int ret; + int i; + static struct { + u16 offset; + u16 flags; + u32 rw_mask; + u32 ro_mask; + } reg_tbl[] = { + { 0x006c, 0, 0x00000000, 0x0000003f }, + { 0x0090, 0, 0xffffffff, 0x00000000 }, + { 0x0094, 0, 0x00000000, 0x00000000 }, + + { 0x0404, 0, 0x00003f00, 0x00000000 }, + { 0x0418, 0, 0x00000000, 0xffffffff }, + { 0x041c, 0, 0x00000000, 0xffffffff }, + { 0x0420, 0, 0x00000000, 0x80ffffff }, + { 0x0424, 0, 0x00000000, 0x00000000 }, + { 0x0428, 0, 0x00000000, 0x00000001 }, + { 0x0450, 0, 0x00000000, 0x0000ffff }, + { 0x0454, 0, 0x00000000, 0xffffffff }, + { 0x0458, 0, 0x00000000, 0xffffffff }, + + { 0x0808, 0, 0x00000000, 0xffffffff }, + { 0x0854, 0, 0x00000000, 0xffffffff }, + { 0x0868, 0, 0x00000000, 0x77777777 }, + { 0x086c, 0, 0x00000000, 0x77777777 }, + { 0x0870, 0, 0x00000000, 0x77777777 }, + { 0x0874, 0, 0x00000000, 0x77777777 }, + + { 0x0c00, 0, 0x00000000, 0x00000001 }, + { 0x0c04, 0, 0x00000000, 0x03ff0001 }, + { 0x0c08, 0, 0x0f0ff073, 0x00000000 }, + { 0x0c0c, 0, 0x00ffffff, 0x00000000 }, + { 0x0c30, 0, 0x00000000, 0xffffffff }, + { 0x0c34, 0, 0x00000000, 0xffffffff }, + { 0x0c38, 0, 0x00000000, 0xffffffff }, + { 0x0c3c, 0, 0x00000000, 0xffffffff }, + { 0x0c40, 0, 0x00000000, 0xffffffff }, + { 0x0c44, 0, 0x00000000, 0xffffffff }, + { 0x0c48, 0, 0x00000000, 0x0007ffff }, + { 0x0c4c, 0, 0x00000000, 0xffffffff }, + { 0x0c50, 0, 0x00000000, 0xffffffff }, + { 0x0c54, 0, 0x00000000, 0xffffffff }, + { 0x0c58, 0, 0x00000000, 0xffffffff }, + { 0x0c5c, 0, 0x00000000, 0xffffffff }, + { 0x0c60, 0, 0x00000000, 0xffffffff }, + { 0x0c64, 0, 0x00000000, 0xffffffff }, + { 0x0c68, 0, 0x00000000, 0xffffffff }, + { 0x0c6c, 0, 0x00000000, 0xffffffff }, + { 0x0c70, 0, 0x00000000, 0xffffffff }, + { 0x0c74, 0, 0x00000000, 0xffffffff }, + { 0x0c78, 0, 0x00000000, 0xffffffff }, + { 0x0c7c, 0, 0x00000000, 0xffffffff }, + { 0x0c80, 0, 0x00000000, 0xffffffff }, + { 0x0c84, 0, 0x00000000, 0xffffffff }, + { 0x0c88, 0, 0x00000000, 0xffffffff }, + { 0x0c8c, 0, 0x00000000, 0xffffffff }, + { 0x0c90, 0, 0x00000000, 0xffffffff }, + { 0x0c94, 0, 0x00000000, 0xffffffff }, + { 0x0c98, 0, 0x00000000, 0xffffffff }, + { 0x0c9c, 0, 0x00000000, 0xffffffff }, + { 0x0ca0, 0, 0x00000000, 0xffffffff }, + { 0x0ca4, 0, 0x00000000, 0xffffffff }, + { 0x0ca8, 0, 0x00000000, 0x0007ffff }, + { 0x0cac, 0, 0x00000000, 0xffffffff }, + { 0x0cb0, 0, 0x00000000, 0xffffffff }, + { 0x0cb4, 0, 0x00000000, 0xffffffff }, + { 0x0cb8, 0, 0x00000000, 0xffffffff }, + { 0x0cbc, 0, 0x00000000, 0xffffffff }, + { 0x0cc0, 0, 0x00000000, 0xffffffff }, + { 0x0cc4, 0, 0x00000000, 0xffffffff }, + { 0x0cc8, 0, 0x00000000, 0xffffffff }, + { 0x0ccc, 0, 0x00000000, 0xffffffff }, + { 0x0cd0, 0, 0x00000000, 0xffffffff }, + { 0x0cd4, 0, 0x00000000, 0xffffffff }, + { 0x0cd8, 0, 0x00000000, 0xffffffff }, + { 0x0cdc, 0, 0x00000000, 0xffffffff }, + { 0x0ce0, 0, 0x00000000, 0xffffffff }, + { 0x0ce4, 0, 0x00000000, 0xffffffff }, + { 0x0ce8, 0, 0x00000000, 0xffffffff }, + { 0x0cec, 0, 0x00000000, 0xffffffff }, + { 0x0cf0, 0, 0x00000000, 0xffffffff }, + { 0x0cf4, 0, 0x00000000, 0xffffffff }, + { 0x0cf8, 0, 0x00000000, 0xffffffff }, + { 0x0cfc, 0, 0x00000000, 0xffffffff }, + { 0x0d00, 0, 0x00000000, 0xffffffff }, + { 0x0d04, 0, 0x00000000, 0xffffffff }, + + { 0x1000, 0, 0x00000000, 0x00000001 }, + { 0x1004, 0, 0x00000000, 0x000f0001 }, + { 0x1044, 0, 0x00000000, 0xffc003ff }, + { 0x1080, 0, 0x00000000, 0x0001ffff }, + { 0x1084, 0, 0x00000000, 0xffffffff }, + { 0x1088, 0, 0x00000000, 0xffffffff }, + { 0x108c, 0, 0x00000000, 0xffffffff }, + { 0x1090, 0, 0x00000000, 0xffffffff }, + { 0x1094, 0, 0x00000000, 0xffffffff }, + { 0x1098, 0, 0x00000000, 0xffffffff }, + { 0x109c, 0, 0x00000000, 0xffffffff }, + { 0x10a0, 0, 0x00000000, 0xffffffff }, + + { 0x1408, 0, 0x01c00800, 0x00000000 }, + { 0x149c, 0, 0x8000ffff, 0x00000000 }, + { 0x14a8, 0, 0x00000000, 0x000001ff }, + { 0x14ac, 0, 0x4fffffff, 0x10000000 }, + { 0x14b0, 0, 0x00000002, 0x00000001 }, + { 0x14b8, 0, 0x00000000, 0x00000000 }, + { 0x14c0, 0, 0x00000000, 0x00000009 }, + { 0x14c4, 0, 0x00003fff, 0x00000000 }, + { 0x14cc, 0, 0x00000000, 0x00000001 }, + { 0x14d0, 0, 0xffffffff, 0x00000000 }, + { 0x1500, 0, 0x00000000, 0xffffffff }, + { 0x1504, 0, 0x00000000, 0xffffffff }, + { 0x1508, 0, 0x00000000, 0xffffffff }, + { 0x150c, 0, 0x00000000, 0xffffffff }, + { 0x1510, 0, 0x00000000, 0xffffffff }, + { 0x1514, 0, 0x00000000, 0xffffffff }, + { 0x1518, 0, 0x00000000, 0xffffffff }, + { 0x151c, 0, 0x00000000, 0xffffffff }, + { 0x1520, 0, 0x00000000, 0xffffffff }, + { 0x1524, 0, 0x00000000, 0xffffffff }, + { 0x1528, 0, 0x00000000, 0xffffffff }, + { 0x152c, 0, 0x00000000, 0xffffffff }, + { 0x1530, 0, 0x00000000, 0xffffffff }, + { 0x1534, 0, 0x00000000, 0xffffffff }, + { 0x1538, 0, 0x00000000, 0xffffffff }, + { 0x153c, 0, 0x00000000, 0xffffffff }, + { 0x1540, 0, 0x00000000, 0xffffffff }, + { 0x1544, 0, 0x00000000, 0xffffffff }, + { 0x1548, 0, 0x00000000, 0xffffffff }, + { 0x154c, 0, 0x00000000, 0xffffffff }, + { 0x1550, 0, 0x00000000, 0xffffffff }, + { 0x1554, 0, 0x00000000, 0xffffffff }, + { 0x1558, 0, 0x00000000, 0xffffffff }, + { 0x1600, 0, 0x00000000, 0xffffffff }, + { 0x1604, 0, 0x00000000, 0xffffffff }, + { 0x1608, 0, 0x00000000, 0xffffffff }, + { 0x160c, 0, 0x00000000, 0xffffffff }, + { 0x1610, 0, 0x00000000, 0xffffffff }, + { 0x1614, 0, 0x00000000, 0xffffffff }, + { 0x1618, 0, 0x00000000, 0xffffffff }, + { 0x161c, 0, 0x00000000, 0xffffffff }, + { 0x1620, 0, 0x00000000, 0xffffffff }, + { 0x1624, 0, 0x00000000, 0xffffffff }, + { 0x1628, 0, 0x00000000, 0xffffffff }, + { 0x162c, 0, 0x00000000, 0xffffffff }, + { 0x1630, 0, 0x00000000, 0xffffffff }, + { 0x1634, 0, 0x00000000, 0xffffffff }, + { 0x1638, 0, 0x00000000, 0xffffffff }, + { 0x163c, 0, 0x00000000, 0xffffffff }, + { 0x1640, 0, 0x00000000, 0xffffffff }, + { 0x1644, 0, 0x00000000, 0xffffffff }, + { 0x1648, 0, 0x00000000, 0xffffffff }, + { 0x164c, 0, 0x00000000, 0xffffffff }, + { 0x1650, 0, 0x00000000, 0xffffffff }, + { 0x1654, 0, 0x00000000, 0xffffffff }, + + { 0x1800, 0, 0x00000000, 0x00000001 }, + { 0x1804, 0, 0x00000000, 0x00000003 }, + { 0x1840, 0, 0x00000000, 0xffffffff }, + { 0x1844, 0, 0x00000000, 0xffffffff }, + { 0x1848, 0, 0x00000000, 0xffffffff }, + { 0x184c, 0, 0x00000000, 0xffffffff }, + { 0x1850, 0, 0x00000000, 0xffffffff }, + { 0x1900, 0, 0x7ffbffff, 0x00000000 }, + { 0x1904, 0, 0xffffffff, 0x00000000 }, + { 0x190c, 0, 0xffffffff, 0x00000000 }, + { 0x1914, 0, 0xffffffff, 0x00000000 }, + { 0x191c, 0, 0xffffffff, 0x00000000 }, + { 0x1924, 0, 0xffffffff, 0x00000000 }, + { 0x192c, 0, 0xffffffff, 0x00000000 }, + { 0x1934, 0, 0xffffffff, 0x00000000 }, + { 0x193c, 0, 0xffffffff, 0x00000000 }, + { 0x1944, 0, 0xffffffff, 0x00000000 }, + { 0x194c, 0, 0xffffffff, 0x00000000 }, + { 0x1954, 0, 0xffffffff, 0x00000000 }, + { 0x195c, 0, 0xffffffff, 0x00000000 }, + { 0x1964, 0, 0xffffffff, 0x00000000 }, + { 0x196c, 0, 0xffffffff, 0x00000000 }, + { 0x1974, 0, 0xffffffff, 0x00000000 }, + { 0x197c, 0, 0xffffffff, 0x00000000 }, + { 0x1980, 0, 0x0700ffff, 0x00000000 }, + + { 0x1c00, 0, 0x00000000, 0x00000001 }, + { 0x1c04, 0, 0x00000000, 0x00000003 }, + { 0x1c08, 0, 0x0000000f, 0x00000000 }, + { 0x1c40, 0, 0x00000000, 0xffffffff }, + { 0x1c44, 0, 0x00000000, 0xffffffff }, + { 0x1c48, 0, 0x00000000, 0xffffffff }, + { 0x1c4c, 0, 0x00000000, 0xffffffff }, + { 0x1c50, 0, 0x00000000, 0xffffffff }, + { 0x1d00, 0, 0x7ffbffff, 0x00000000 }, + { 0x1d04, 0, 0xffffffff, 0x00000000 }, + { 0x1d0c, 0, 0xffffffff, 0x00000000 }, + { 0x1d14, 0, 0xffffffff, 0x00000000 }, + { 0x1d1c, 0, 0xffffffff, 0x00000000 }, + { 0x1d24, 0, 0xffffffff, 0x00000000 }, + { 0x1d2c, 0, 0xffffffff, 0x00000000 }, + { 0x1d34, 0, 0xffffffff, 0x00000000 }, + { 0x1d3c, 0, 0xffffffff, 0x00000000 }, + { 0x1d44, 0, 0xffffffff, 0x00000000 }, + { 0x1d4c, 0, 0xffffffff, 0x00000000 }, + { 0x1d54, 0, 0xffffffff, 0x00000000 }, + { 0x1d5c, 0, 0xffffffff, 0x00000000 }, + { 0x1d64, 0, 0xffffffff, 0x00000000 }, + { 0x1d6c, 0, 0xffffffff, 0x00000000 }, + { 0x1d74, 0, 0xffffffff, 0x00000000 }, + { 0x1d7c, 0, 0xffffffff, 0x00000000 }, + { 0x1d80, 0, 0x0700ffff, 0x00000000 }, + + { 0x2004, 0, 0x00000000, 0x0337000f }, + { 0x2008, 0, 0xffffffff, 0x00000000 }, + { 0x200c, 0, 0xffffffff, 0x00000000 }, + { 0x2010, 0, 0xffffffff, 0x00000000 }, + { 0x2014, 0, 0x801fff80, 0x00000000 }, + { 0x2018, 0, 0x000003ff, 0x00000000 }, + + { 0x2800, 0, 0x00000000, 0x00000001 }, + { 0x2804, 0, 0x00000000, 0x00003f01 }, + { 0x2808, 0, 0x0f3f3f03, 0x00000000 }, + { 0x2810, 0, 0xffff0000, 0x00000000 }, + { 0x2814, 0, 0xffff0000, 0x00000000 }, + { 0x2818, 0, 0xffff0000, 0x00000000 }, + { 0x281c, 0, 0xffff0000, 0x00000000 }, + { 0x2834, 0, 0xffffffff, 0x00000000 }, + { 0x2840, 0, 0x00000000, 0xffffffff }, + { 0x2844, 0, 0x00000000, 0xffffffff }, + { 0x2848, 0, 0xffffffff, 0x00000000 }, + { 0x284c, 0, 0xf800f800, 0x07ff07ff }, + + { 0x2c00, 0, 0x00000000, 0x00000011 }, + { 0x2c04, 0, 0x00000000, 0x00030007 }, + + { 0x3000, 0, 0x00000000, 0x00000001 }, + { 0x3004, 0, 0x00000000, 0x007007ff }, + { 0x3008, 0, 0x00000003, 0x00000000 }, + { 0x300c, 0, 0xffffffff, 0x00000000 }, + { 0x3010, 0, 0xffffffff, 0x00000000 }, + { 0x3014, 0, 0xffffffff, 0x00000000 }, + { 0x3034, 0, 0xffffffff, 0x00000000 }, + { 0x3038, 0, 0xffffffff, 0x00000000 }, + { 0x3050, 0, 0x00000001, 0x00000000 }, + + { 0x3c00, 0, 0x00000000, 0x00000001 }, + { 0x3c04, 0, 0x00000000, 0x00070000 }, + { 0x3c08, 0, 0x00007f71, 0x07f00000 }, + { 0x3c0c, 0, 0x1f3ffffc, 0x00000000 }, + { 0x3c10, 0, 0xffffffff, 0x00000000 }, + { 0x3c14, 0, 0x00000000, 0xffffffff }, + { 0x3c18, 0, 0x00000000, 0xffffffff }, + { 0x3c1c, 0, 0xfffff000, 0x00000000 }, + { 0x3c20, 0, 0xffffff00, 0x00000000 }, + { 0x3c24, 0, 0xffffffff, 0x00000000 }, + { 0x3c28, 0, 0xffffffff, 0x00000000 }, + { 0x3c2c, 0, 0xffffffff, 0x00000000 }, + { 0x3c30, 0, 0xffffffff, 0x00000000 }, + { 0x3c34, 0, 0xffffffff, 0x00000000 }, + { 0x3c38, 0, 0xffffffff, 0x00000000 }, + { 0x3c3c, 0, 0xffffffff, 0x00000000 }, + { 0x3c40, 0, 0xffffffff, 0x00000000 }, + { 0x3c44, 0, 0xffffffff, 0x00000000 }, + { 0x3c48, 0, 0xffffffff, 0x00000000 }, + { 0x3c4c, 0, 0xffffffff, 0x00000000 }, + { 0x3c50, 0, 0xffffffff, 0x00000000 }, + { 0x3c54, 0, 0xffffffff, 0x00000000 }, + { 0x3c58, 0, 0xffffffff, 0x00000000 }, + { 0x3c5c, 0, 0xffffffff, 0x00000000 }, + { 0x3c60, 0, 0xffffffff, 0x00000000 }, + { 0x3c64, 0, 0xffffffff, 0x00000000 }, + { 0x3c68, 0, 0xffffffff, 0x00000000 }, + { 0x3c6c, 0, 0xffffffff, 0x00000000 }, + { 0x3c70, 0, 0xffffffff, 0x00000000 }, + { 0x3c74, 0, 0x0000003f, 0x00000000 }, + { 0x3c78, 0, 0x00000000, 0x00000000 }, + { 0x3c7c, 0, 0x00000000, 0x00000000 }, + { 0x3c80, 0, 0x3fffffff, 0x00000000 }, + { 0x3c84, 0, 0x0000003f, 0x00000000 }, + { 0x3c88, 0, 0x00000000, 0xffffffff }, + { 0x3c8c, 0, 0x00000000, 0xffffffff }, + + { 0x4000, 0, 0x00000000, 0x00000001 }, + { 0x4004, 0, 0x00000000, 0x00030000 }, + { 0x4008, 0, 0x00000ff0, 0x00000000 }, + { 0x400c, 0, 0xffffffff, 0x00000000 }, + { 0x4088, 0, 0x00000000, 0x00070303 }, + + { 0x4400, 0, 0x00000000, 0x00000001 }, + { 0x4404, 0, 0x00000000, 0x00003f01 }, + { 0x4408, 0, 0x7fff00ff, 0x00000000 }, + { 0x440c, 0, 0xffffffff, 0x00000000 }, + { 0x4410, 0, 0xffff, 0x0000 }, + { 0x4414, 0, 0xffff, 0x0000 }, + { 0x4418, 0, 0xffff, 0x0000 }, + { 0x441c, 0, 0xffff, 0x0000 }, + { 0x4428, 0, 0xffffffff, 0x00000000 }, + { 0x442c, 0, 0xffffffff, 0x00000000 }, + { 0x4430, 0, 0xffffffff, 0x00000000 }, + { 0x4434, 0, 0xffffffff, 0x00000000 }, + { 0x4438, 0, 0xffffffff, 0x00000000 }, + { 0x443c, 0, 0xffffffff, 0x00000000 }, + { 0x4440, 0, 0xffffffff, 0x00000000 }, + { 0x4444, 0, 0xffffffff, 0x00000000 }, + + { 0x4c00, 0, 0x00000000, 0x00000001 }, + { 0x4c04, 0, 0x00000000, 0x0000003f }, + { 0x4c08, 0, 0xffffffff, 0x00000000 }, + { 0x4c0c, 0, 0x0007fc00, 0x00000000 }, + { 0x4c10, 0, 0x80003fe0, 0x00000000 }, + { 0x4c14, 0, 0xffffffff, 0x00000000 }, + { 0x4c44, 0, 0x00000000, 0x9fff9fff }, + { 0x4c48, 0, 0x00000000, 0xb3009fff }, + { 0x4c4c, 0, 0x00000000, 0x77f33b30 }, + { 0x4c50, 0, 0x00000000, 0xffffffff }, + + { 0x5004, 0, 0x00000000, 0x0000007f }, + { 0x5008, 0, 0x0f0007ff, 0x00000000 }, + { 0x500c, 0, 0xf800f800, 0x07ff07ff }, + + { 0x5400, 0, 0x00000008, 0x00000001 }, + { 0x5404, 0, 0x00000000, 0x0000003f }, + { 0x5408, 0, 0x0000001f, 0x00000000 }, + { 0x540c, 0, 0xffffffff, 0x00000000 }, + { 0x5410, 0, 0xffffffff, 0x00000000 }, + { 0x5414, 0, 0x0000ffff, 0x00000000 }, + { 0x5418, 0, 0x0000ffff, 0x00000000 }, + { 0x541c, 0, 0x0000ffff, 0x00000000 }, + { 0x5420, 0, 0x0000ffff, 0x00000000 }, + { 0x5428, 0, 0x000000ff, 0x00000000 }, + { 0x542c, 0, 0xff00ffff, 0x00000000 }, + { 0x5430, 0, 0x001fff80, 0x00000000 }, + { 0x5438, 0, 0xffffffff, 0x00000000 }, + { 0x543c, 0, 0xffffffff, 0x00000000 }, + { 0x5440, 0, 0xf800f800, 0x07ff07ff }, + + { 0x5c00, 0, 0x00000000, 0x00000001 }, + { 0x5c04, 0, 0x00000000, 0x0003000f }, + { 0x5c08, 0, 0x00000003, 0x00000000 }, + { 0x5c0c, 0, 0x0000fff8, 0x00000000 }, + { 0x5c10, 0, 0x00000000, 0xffffffff }, + { 0x5c80, 0, 0x00000000, 0x0f7113f1 }, + { 0x5c84, 0, 0x00000000, 0x0000f333 }, + { 0x5c88, 0, 0x00000000, 0x00077373 }, + { 0x5c8c, 0, 0x00000000, 0x0007f737 }, + + { 0x6808, 0, 0x0000ff7f, 0x00000000 }, + { 0x680c, 0, 0xffffffff, 0x00000000 }, + { 0x6810, 0, 0xffffffff, 0x00000000 }, + { 0x6814, 0, 0xffffffff, 0x00000000 }, + { 0x6818, 0, 0xffffffff, 0x00000000 }, + { 0x681c, 0, 0xffffffff, 0x00000000 }, + { 0x6820, 0, 0x00ff00ff, 0x00000000 }, + { 0x6824, 0, 0x00ff00ff, 0x00000000 }, + { 0x6828, 0, 0x00ff00ff, 0x00000000 }, + { 0x682c, 0, 0x03ff03ff, 0x00000000 }, + { 0x6830, 0, 0x03ff03ff, 0x00000000 }, + { 0x6834, 0, 0x03ff03ff, 0x00000000 }, + { 0x6838, 0, 0x03ff03ff, 0x00000000 }, + { 0x683c, 0, 0x0000ffff, 0x00000000 }, + { 0x6840, 0, 0x00000ff0, 0x00000000 }, + { 0x6844, 0, 0x00ffff00, 0x00000000 }, + { 0x684c, 0, 0xffffffff, 0x00000000 }, + { 0x6850, 0, 0x7f7f7f7f, 0x00000000 }, + { 0x6854, 0, 0x7f7f7f7f, 0x00000000 }, + { 0x6858, 0, 0x7f7f7f7f, 0x00000000 }, + { 0x685c, 0, 0x7f7f7f7f, 0x00000000 }, + { 0x6908, 0, 0x00000000, 0x0001ff0f }, + { 0x690c, 0, 0x00000000, 0x0ffe00f0 }, + + { 0xffff, 0, 0x00000000, 0x00000000 }, + }; + + ret = 0; + for (i = 0; reg_tbl[i].offset != 0xffff; i++) { + u32 offset, rw_mask, ro_mask, save_val, val; + + offset = (u32) reg_tbl[i].offset; + rw_mask = reg_tbl[i].rw_mask; + ro_mask = reg_tbl[i].ro_mask; + + save_val = readl((u8 *) bp->regview + offset); + + writel(0, (u8 *) bp->regview + offset); + + val = readl((u8 *) bp->regview + offset); + if ((val & rw_mask) != 0) { + goto reg_test_err; + } + + if ((val & ro_mask) != (save_val & ro_mask)) { + goto reg_test_err; + } + + writel(0xffffffff, (u8 *) bp->regview + offset); + + val = readl((u8 *) bp->regview + offset); + if ((val & rw_mask) != rw_mask) { + goto reg_test_err; + } + + if ((val & ro_mask) != (save_val & ro_mask)) { + goto reg_test_err; + } + + writel(save_val, (u8 *) bp->regview + offset); + continue; + +reg_test_err: + writel(save_val, (u8 *) bp->regview + offset); + ret = -ENODEV; + break; + } + return ret; +} + +static int +bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size) +{ + static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555, + 0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa }; + int i; + + for (i = 0; i < sizeof(test_pattern) / 4; i++) { + u32 offset; + + for (offset = 0; offset < size; offset += 4) { + + REG_WR_IND(bp, start + offset, test_pattern[i]); + + if (REG_RD_IND(bp, start + offset) != + test_pattern[i]) { + return -ENODEV; + } + } + } + return 0; +} + +static int +bnx2_test_memory(struct bnx2 *bp) +{ + int ret = 0; + int i; + static struct { + u32 offset; + u32 len; + } mem_tbl[] = { + { 0x60000, 0x4000 }, + { 0xa0000, 0x4000 }, + { 0xe0000, 0x4000 }, + { 0x120000, 0x4000 }, + { 0x1a0000, 0x4000 }, + { 0x160000, 0x4000 }, + { 0xffffffff, 0 }, + }; + + for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { + if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset, + mem_tbl[i].len)) != 0) { + return ret; + } + } + + return ret; +} + +static int +bnx2_test_loopback(struct bnx2 *bp) +{ + unsigned int pkt_size, num_pkts, i; + struct sk_buff *skb, *rx_skb; + unsigned char *packet; + u16 rx_start_idx, rx_idx, send_idx; + u32 send_bseq, val; + dma_addr_t map; + struct tx_bd *txbd; + struct sw_bd *rx_buf; + struct l2_fhdr *rx_hdr; + int ret = -ENODEV; + + if (!netif_running(bp->dev)) + return -ENODEV; + + bp->loopback = MAC_LOOPBACK; + bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_DIAG); + bnx2_set_mac_loopback(bp); + + pkt_size = 1514; + skb = dev_alloc_skb(pkt_size); + packet = skb_put(skb, pkt_size); + memcpy(packet, bp->mac_addr, 6); + memset(packet + 6, 0x0, 8); + for (i = 14; i < pkt_size; i++) + packet[i] = (unsigned char) (i & 0xff); + + map = pci_map_single(bp->pdev, skb->data, pkt_size, + PCI_DMA_TODEVICE); + + val = REG_RD(bp, BNX2_HC_COMMAND); + REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); + + udelay(5); + rx_start_idx = bp->status_blk->status_rx_quick_consumer_index0; + + send_idx = 0; + send_bseq = 0; + num_pkts = 0; + + txbd = &bp->tx_desc_ring[send_idx]; + + txbd->tx_bd_haddr_hi = (u64) map >> 32; + txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff; + txbd->tx_bd_mss_nbytes = pkt_size; + txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END; + + num_pkts++; + send_idx = NEXT_TX_BD(send_idx); + + send_bseq += pkt_size; + + REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, send_idx); + REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, send_bseq); + + + udelay(100); + + val = REG_RD(bp, BNX2_HC_COMMAND); + REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + REG_RD(bp, BNX2_HC_COMMAND); + + udelay(5); + + pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + + if (bp->status_blk->status_tx_quick_consumer_index0 != send_idx) { + goto loopback_test_done; + } + + rx_idx = bp->status_blk->status_rx_quick_consumer_index0; + if (rx_idx != rx_start_idx + num_pkts) { + goto loopback_test_done; + } + + rx_buf = &bp->rx_buf_ring[rx_start_idx]; + rx_skb = rx_buf->skb; + + rx_hdr = (struct l2_fhdr *) rx_skb->data; + skb_reserve(rx_skb, bp->rx_offset); + + pci_dma_sync_single_for_cpu(bp->pdev, + pci_unmap_addr(rx_buf, mapping), + bp->rx_buf_size, PCI_DMA_FROMDEVICE); + + if (rx_hdr->l2_fhdr_errors & + (L2_FHDR_ERRORS_BAD_CRC | + L2_FHDR_ERRORS_PHY_DECODE | + L2_FHDR_ERRORS_ALIGNMENT | + L2_FHDR_ERRORS_TOO_SHORT | + L2_FHDR_ERRORS_GIANT_FRAME)) { + + goto loopback_test_done; + } + + if ((rx_hdr->l2_fhdr_pkt_len - 4) != pkt_size) { + goto loopback_test_done; + } + + for (i = 14; i < pkt_size; i++) { + if (*(rx_skb->data + i) != (unsigned char) (i & 0xff)) { + goto loopback_test_done; + } + } + + ret = 0; + +loopback_test_done: + bp->loopback = 0; + return ret; +} + +#define NVRAM_SIZE 0x200 +#define CRC32_RESIDUAL 0xdebb20e3 + +static int +bnx2_test_nvram(struct bnx2 *bp) +{ + u32 buf[NVRAM_SIZE / 4]; + u8 *data = (u8 *) buf; + int rc = 0; + u32 magic, csum; + + if ((rc = bnx2_nvram_read(bp, 0, data, 4)) != 0) + goto test_nvram_done; + + magic = be32_to_cpu(buf[0]); + if (magic != 0x669955aa) { + rc = -ENODEV; + goto test_nvram_done; + } + + if ((rc = bnx2_nvram_read(bp, 0x100, data, NVRAM_SIZE)) != 0) + goto test_nvram_done; + + csum = ether_crc_le(0x100, data); + if (csum != CRC32_RESIDUAL) { + rc = -ENODEV; + goto test_nvram_done; + } + + csum = ether_crc_le(0x100, data + 0x100); + if (csum != CRC32_RESIDUAL) { + rc = -ENODEV; + } + +test_nvram_done: + return rc; +} + +static int +bnx2_test_link(struct bnx2 *bp) +{ + u32 bmsr; + + spin_lock_irq(&bp->phy_lock); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + spin_unlock_irq(&bp->phy_lock); + + if (bmsr & BMSR_LSTATUS) { + return 0; + } + return -ENODEV; +} + +static int +bnx2_test_intr(struct bnx2 *bp) +{ + int i; + u32 val; + u16 status_idx; + + if (!netif_running(bp->dev)) + return -ENODEV; + + status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; + + /* This register is not touched during run-time. */ + val = REG_RD(bp, BNX2_HC_COMMAND); + REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW); + REG_RD(bp, BNX2_HC_COMMAND); + + for (i = 0; i < 10; i++) { + if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) != + status_idx) { + + break; + } + + msleep_interruptible(10); + } + if (i < 10) + return 0; + + return -ENODEV; +} + +static void +bnx2_timer(unsigned long data) +{ + struct bnx2 *bp = (struct bnx2 *) data; + u32 msg; + + if (atomic_read(&bp->intr_sem) != 0) + goto bnx2_restart_timer; + + msg = (u32) ++bp->fw_drv_pulse_wr_seq; + REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_PULSE_MB, msg); + + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (CHIP_NUM(bp) == CHIP_NUM_5706)) { + unsigned long flags; + + spin_lock_irqsave(&bp->phy_lock, flags); + if (bp->serdes_an_pending) { + bp->serdes_an_pending--; + } + else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { + u32 bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + + if (bmcr & BMCR_ANENABLE) { + u32 phy1, phy2; + + bnx2_write_phy(bp, 0x1c, 0x7c00); + bnx2_read_phy(bp, 0x1c, &phy1); + + bnx2_write_phy(bp, 0x17, 0x0f01); + bnx2_read_phy(bp, 0x15, &phy2); + bnx2_write_phy(bp, 0x17, 0x0f01); + bnx2_read_phy(bp, 0x15, &phy2); + + if ((phy1 & 0x10) && /* SIGNAL DETECT */ + !(phy2 & 0x20)) { /* no CONFIG */ + + bmcr &= ~BMCR_ANENABLE; + bmcr |= BMCR_SPEED1000 | + BMCR_FULLDPLX; + bnx2_write_phy(bp, MII_BMCR, bmcr); + bp->phy_flags |= + PHY_PARALLEL_DETECT_FLAG; + } + } + } + else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) && + (bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)) { + u32 phy2; + + bnx2_write_phy(bp, 0x17, 0x0f01); + bnx2_read_phy(bp, 0x15, &phy2); + if (phy2 & 0x20) { + u32 bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + bmcr |= BMCR_ANENABLE; + bnx2_write_phy(bp, MII_BMCR, bmcr); + + bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; + + } + } + + spin_unlock_irqrestore(&bp->phy_lock, flags); + } + +bnx2_restart_timer: + bp->timer.expires = RUN_AT(bp->timer_interval); + + add_timer(&bp->timer); +} + +/* Called with rtnl_lock */ +static int +bnx2_open(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + int rc; + + bnx2_set_power_state(bp, 0); + bnx2_disable_int(bp); + + rc = bnx2_alloc_mem(bp); + if (rc) + return rc; + + if ((CHIP_ID(bp) != CHIP_ID_5706_A0) && + (CHIP_ID(bp) != CHIP_ID_5706_A1) && + !disable_msi) { + + if (pci_enable_msi(bp->pdev) == 0) { + bp->flags |= USING_MSI_FLAG; + rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name, + dev); + } + else { + rc = request_irq(bp->pdev->irq, bnx2_interrupt, + SA_SHIRQ, dev->name, dev); + } + } + else { + rc = request_irq(bp->pdev->irq, bnx2_interrupt, SA_SHIRQ, + dev->name, dev); + } + if (rc) { + bnx2_free_mem(bp); + return rc; + } + + rc = bnx2_init_nic(bp); + + if (rc) { + free_irq(bp->pdev->irq, dev); + if (bp->flags & USING_MSI_FLAG) { + pci_disable_msi(bp->pdev); + bp->flags &= ~USING_MSI_FLAG; + } + bnx2_free_skbs(bp); + bnx2_free_mem(bp); + return rc; + } + + init_timer(&bp->timer); + + bp->timer.expires = RUN_AT(bp->timer_interval); + bp->timer.data = (unsigned long) bp; + bp->timer.function = bnx2_timer; + add_timer(&bp->timer); + + atomic_set(&bp->intr_sem, 0); + + bnx2_enable_int(bp); + + if (bp->flags & USING_MSI_FLAG) { + /* Test MSI to make sure it is working + * If MSI test fails, go back to INTx mode + */ + if (bnx2_test_intr(bp) != 0) { + printk(KERN_WARNING PFX "%s: No interrupt was generated" + " using MSI, switching to INTx mode. Please" + " report this failure to the PCI maintainer" + " and include system chipset information.\n", + bp->dev->name); + + bnx2_disable_int(bp); + free_irq(bp->pdev->irq, dev); + pci_disable_msi(bp->pdev); + bp->flags &= ~USING_MSI_FLAG; + + rc = bnx2_init_nic(bp); + + if (!rc) { + rc = request_irq(bp->pdev->irq, bnx2_interrupt, + SA_SHIRQ, dev->name, dev); + } + if (rc) { + bnx2_free_skbs(bp); + bnx2_free_mem(bp); + del_timer_sync(&bp->timer); + return rc; + } + bnx2_enable_int(bp); + } + } + if (bp->flags & USING_MSI_FLAG) { + printk(KERN_INFO PFX "%s: using MSI\n", dev->name); + } + + netif_start_queue(dev); + + return 0; +} + +static void +bnx2_reset_task(void *data) +{ + struct bnx2 *bp = data; + + bnx2_netif_stop(bp); + + bnx2_init_nic(bp); + + atomic_set(&bp->intr_sem, 1); + bnx2_netif_start(bp); +} + +static void +bnx2_tx_timeout(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + + /* This allows the netif to be shutdown gracefully before resetting */ + schedule_work(&bp->reset_task); +} + +#ifdef BCM_VLAN +/* Called with rtnl_lock */ +static void +bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) +{ + struct bnx2 *bp = dev->priv; + + bnx2_netif_stop(bp); + + bp->vlgrp = vlgrp; + bnx2_set_rx_mode(dev); + + bnx2_netif_start(bp); +} + +/* Called with rtnl_lock */ +static void +bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) +{ + struct bnx2 *bp = dev->priv; + + bnx2_netif_stop(bp); + + if (bp->vlgrp) + bp->vlgrp->vlan_devices[vid] = NULL; + bnx2_set_rx_mode(dev); + + bnx2_netif_start(bp); +} +#endif + +/* Called with dev->xmit_lock. + * hard_start_xmit is pseudo-lockless - a lock is only required when + * the tx queue is full. This way, we get the benefit of lockless + * operations most of the time without the complexities to handle + * netif_stop_queue/wake_queue race conditions. + */ +static int +bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + dma_addr_t mapping; + struct tx_bd *txbd; + struct sw_bd *tx_buf; + u32 len, vlan_tag_flags, last_frag, mss; + u16 prod, ring_prod; + int i; + + if (unlikely(atomic_read(&bp->tx_avail_bd) < + (skb_shinfo(skb)->nr_frags + 1))) { + + netif_stop_queue(dev); + printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n", + dev->name); + + return NETDEV_TX_BUSY; + } + len = skb_headlen(skb); + prod = bp->tx_prod; + ring_prod = TX_RING_IDX(prod); + + vlan_tag_flags = 0; + if (skb->ip_summed == CHECKSUM_HW) { + vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; + } + + if (bp->vlgrp != 0 && vlan_tx_tag_present(skb)) { + vlan_tag_flags |= + (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); + } +#ifdef BCM_TSO + if ((mss = skb_shinfo(skb)->tso_size) && + (skb->len > (bp->dev->mtu + ETH_HLEN))) { + u32 tcp_opt_len, ip_tcp_len; + + if (skb_header_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + + tcp_opt_len = ((skb->h.th->doff - 5) * 4); + vlan_tag_flags |= TX_BD_FLAGS_SW_LSO; + + tcp_opt_len = 0; + if (skb->h.th->doff > 5) { + tcp_opt_len = (skb->h.th->doff - 5) << 2; + } + ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr); + + skb->nh.iph->check = 0; + skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); + skb->h.th->check = + ~csum_tcpudp_magic(skb->nh.iph->saddr, + skb->nh.iph->daddr, + 0, IPPROTO_TCP, 0); + + if (tcp_opt_len || (skb->nh.iph->ihl > 5)) { + vlan_tag_flags |= ((skb->nh.iph->ihl - 5) + + (tcp_opt_len >> 2)) << 8; + } + } + else +#endif + { + mss = 0; + } + + mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); + + tx_buf = &bp->tx_buf_ring[ring_prod]; + tx_buf->skb = skb; + pci_unmap_addr_set(tx_buf, mapping, mapping); + + txbd = &bp->tx_desc_ring[ring_prod]; + + txbd->tx_bd_haddr_hi = (u64) mapping >> 32; + txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff; + txbd->tx_bd_mss_nbytes = len | (mss << 16); + txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START; + + last_frag = skb_shinfo(skb)->nr_frags; + + for (i = 0; i < last_frag; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + prod = NEXT_TX_BD(prod); + ring_prod = TX_RING_IDX(prod); + txbd = &bp->tx_desc_ring[ring_prod]; + + len = frag->size; + mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset, + len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(&bp->tx_buf_ring[ring_prod], + mapping, mapping); + + txbd->tx_bd_haddr_hi = (u64) mapping >> 32; + txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff; + txbd->tx_bd_mss_nbytes = len | (mss << 16); + txbd->tx_bd_vlan_tag_flags = vlan_tag_flags; + + } + txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; + + prod = NEXT_TX_BD(prod); + bp->tx_prod_bseq += skb->len; + + atomic_sub(last_frag + 1, &bp->tx_avail_bd); + + REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod); + REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq); + + mmiowb(); + + bp->tx_prod = prod; + dev->trans_start = jiffies; + + if (unlikely(atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS)) { + unsigned long flags; + + spin_lock_irqsave(&bp->tx_lock, flags); + if (atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS) { + netif_stop_queue(dev); + + if (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS) + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&bp->tx_lock, flags); + } + + return NETDEV_TX_OK; +} + +/* Called with rtnl_lock */ +static int +bnx2_close(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + u32 reset_code; + + flush_scheduled_work(); + bnx2_netif_stop(bp); + del_timer_sync(&bp->timer); + if (bp->wol) + reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; + else + reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; + bnx2_reset_chip(bp, reset_code); + free_irq(bp->pdev->irq, dev); + if (bp->flags & USING_MSI_FLAG) { + pci_disable_msi(bp->pdev); + bp->flags &= ~USING_MSI_FLAG; + } + bnx2_free_skbs(bp); + bnx2_free_mem(bp); + bp->link_up = 0; + netif_carrier_off(bp->dev); + bnx2_set_power_state(bp, 3); + return 0; +} + +#define GET_NET_STATS64(ctr) \ + (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \ + (unsigned long) (ctr##_lo) + +#define GET_NET_STATS32(ctr) \ + (ctr##_lo) + +#if (BITS_PER_LONG == 64) +#define GET_NET_STATS GET_NET_STATS64 +#else +#define GET_NET_STATS GET_NET_STATS32 +#endif + +static struct net_device_stats * +bnx2_get_stats(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + struct statistics_block *stats_blk = bp->stats_blk; + struct net_device_stats *net_stats = &bp->net_stats; + + if (bp->stats_blk == NULL) { + return net_stats; + } + net_stats->rx_packets = + GET_NET_STATS(stats_blk->stat_IfHCInUcastPkts) + + GET_NET_STATS(stats_blk->stat_IfHCInMulticastPkts) + + GET_NET_STATS(stats_blk->stat_IfHCInBroadcastPkts); + + net_stats->tx_packets = + GET_NET_STATS(stats_blk->stat_IfHCOutUcastPkts) + + GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts) + + GET_NET_STATS(stats_blk->stat_IfHCOutBroadcastPkts); + + net_stats->rx_bytes = + GET_NET_STATS(stats_blk->stat_IfHCInOctets); + + net_stats->tx_bytes = + GET_NET_STATS(stats_blk->stat_IfHCOutOctets); + + net_stats->multicast = + GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts); + + net_stats->collisions = + (unsigned long) stats_blk->stat_EtherStatsCollisions; + + net_stats->rx_length_errors = + (unsigned long) (stats_blk->stat_EtherStatsUndersizePkts + + stats_blk->stat_EtherStatsOverrsizePkts); + + net_stats->rx_over_errors = + (unsigned long) stats_blk->stat_IfInMBUFDiscards; + + net_stats->rx_frame_errors = + (unsigned long) stats_blk->stat_Dot3StatsAlignmentErrors; + + net_stats->rx_crc_errors = + (unsigned long) stats_blk->stat_Dot3StatsFCSErrors; + + net_stats->rx_errors = net_stats->rx_length_errors + + net_stats->rx_over_errors + net_stats->rx_frame_errors + + net_stats->rx_crc_errors; + + net_stats->tx_aborted_errors = + (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions + + stats_blk->stat_Dot3StatsLateCollisions); + + if (CHIP_NUM(bp) == CHIP_NUM_5706) + net_stats->tx_carrier_errors = 0; + else { + net_stats->tx_carrier_errors = + (unsigned long) + stats_blk->stat_Dot3StatsCarrierSenseErrors; + } + + net_stats->tx_errors = + (unsigned long) + stats_blk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors + + + net_stats->tx_aborted_errors + + net_stats->tx_carrier_errors; + + return net_stats; +} + +/* All ethtool functions called with rtnl_lock */ + +static int +bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bnx2 *bp = dev->priv; + + cmd->supported = SUPPORTED_Autoneg; + if (bp->phy_flags & PHY_SERDES_FLAG) { + cmd->supported |= SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE; + + cmd->port = PORT_FIBRE; + } + else { + cmd->supported |= SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_TP; + + cmd->port = PORT_TP; + } + + cmd->advertising = bp->advertising; + + if (bp->autoneg & AUTONEG_SPEED) { + cmd->autoneg = AUTONEG_ENABLE; + } + else { + cmd->autoneg = AUTONEG_DISABLE; + } + + if (netif_carrier_ok(dev)) { + cmd->speed = bp->line_speed; + cmd->duplex = bp->duplex; + } + else { + cmd->speed = -1; + cmd->duplex = -1; + } + + cmd->transceiver = XCVR_INTERNAL; + cmd->phy_address = bp->phy_addr; + + return 0; +} + +static int +bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bnx2 *bp = dev->priv; + u8 autoneg = bp->autoneg; + u8 req_duplex = bp->req_duplex; + u16 req_line_speed = bp->req_line_speed; + u32 advertising = bp->advertising; + + if (cmd->autoneg == AUTONEG_ENABLE) { + autoneg |= AUTONEG_SPEED; + + cmd->advertising &= ETHTOOL_ALL_COPPER_SPEED; + + /* allow advertising 1 speed */ + if ((cmd->advertising == ADVERTISED_10baseT_Half) || + (cmd->advertising == ADVERTISED_10baseT_Full) || + (cmd->advertising == ADVERTISED_100baseT_Half) || + (cmd->advertising == ADVERTISED_100baseT_Full)) { + + if (bp->phy_flags & PHY_SERDES_FLAG) + return -EINVAL; + + advertising = cmd->advertising; + + } + else if (cmd->advertising == ADVERTISED_1000baseT_Full) { + advertising = cmd->advertising; + } + else if (cmd->advertising == ADVERTISED_1000baseT_Half) { + return -EINVAL; + } + else { + if (bp->phy_flags & PHY_SERDES_FLAG) { + advertising = ETHTOOL_ALL_FIBRE_SPEED; + } + else { + advertising = ETHTOOL_ALL_COPPER_SPEED; + } + } + advertising |= ADVERTISED_Autoneg; + } + else { + if (bp->phy_flags & PHY_SERDES_FLAG) { + if ((cmd->speed != SPEED_1000) || + (cmd->duplex != DUPLEX_FULL)) { + return -EINVAL; + } + } + else if (cmd->speed == SPEED_1000) { + return -EINVAL; + } + autoneg &= ~AUTONEG_SPEED; + req_line_speed = cmd->speed; + req_duplex = cmd->duplex; + advertising = 0; + } + + bp->autoneg = autoneg; + bp->advertising = advertising; + bp->req_line_speed = req_line_speed; + bp->req_duplex = req_duplex; + + spin_lock_irq(&bp->phy_lock); + + bnx2_setup_phy(bp); + + spin_unlock_irq(&bp->phy_lock); + + return 0; +} + +static void +bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct bnx2 *bp = dev->priv; + + strcpy(info->driver, DRV_MODULE_NAME); + strcpy(info->version, DRV_MODULE_VERSION); + strcpy(info->bus_info, pci_name(bp->pdev)); + info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0'; + info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0'; + info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0'; + info->fw_version[6] = (bp->fw_ver & 0xff) + '0'; + info->fw_version[1] = info->fw_version[3] = info->fw_version[5] = '.'; + info->fw_version[7] = 0; +} + +static void +bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct bnx2 *bp = dev->priv; + + if (bp->flags & NO_WOL_FLAG) { + wol->supported = 0; + wol->wolopts = 0; + } + else { + wol->supported = WAKE_MAGIC; + if (bp->wol) + wol->wolopts = WAKE_MAGIC; + else + wol->wolopts = 0; + } + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} + +static int +bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct bnx2 *bp = dev->priv; + + if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + + if (wol->wolopts & WAKE_MAGIC) { + if (bp->flags & NO_WOL_FLAG) + return -EINVAL; + + bp->wol = 1; + } + else { + bp->wol = 0; + } + return 0; +} + +static int +bnx2_nway_reset(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + u32 bmcr; + + if (!(bp->autoneg & AUTONEG_SPEED)) { + return -EINVAL; + } + + spin_lock_irq(&bp->phy_lock); + + /* Force a link down visible on the other side */ + if (bp->phy_flags & PHY_SERDES_FLAG) { + bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); + spin_unlock_irq(&bp->phy_lock); + + msleep(20); + + spin_lock_irq(&bp->phy_lock); + if (CHIP_NUM(bp) == CHIP_NUM_5706) { + bp->serdes_an_pending = SERDES_AN_TIMEOUT / + bp->timer_interval; + } + } + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + bmcr &= ~BMCR_LOOPBACK; + bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); + + spin_unlock_irq(&bp->phy_lock); + + return 0; +} + +static int +bnx2_get_eeprom_len(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + + if (bp->flash_info == 0) + return 0; + + return (int) bp->flash_info->total_size; +} + +static int +bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *eebuf) +{ + struct bnx2 *bp = dev->priv; + int rc; + + if (eeprom->offset > bp->flash_info->total_size) + return -EINVAL; + + if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size) + eeprom->len = bp->flash_info->total_size - eeprom->offset; + + rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len); + + return rc; +} + +static int +bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *eebuf) +{ + struct bnx2 *bp = dev->priv; + int rc; + + if (eeprom->offset > bp->flash_info->total_size) + return -EINVAL; + + if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size) + eeprom->len = bp->flash_info->total_size - eeprom->offset; + + rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); + + return rc; +} + +static int +bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) +{ + struct bnx2 *bp = dev->priv; + + memset(coal, 0, sizeof(struct ethtool_coalesce)); + + coal->rx_coalesce_usecs = bp->rx_ticks; + coal->rx_max_coalesced_frames = bp->rx_quick_cons_trip; + coal->rx_coalesce_usecs_irq = bp->rx_ticks_int; + coal->rx_max_coalesced_frames_irq = bp->rx_quick_cons_trip_int; + + coal->tx_coalesce_usecs = bp->tx_ticks; + coal->tx_max_coalesced_frames = bp->tx_quick_cons_trip; + coal->tx_coalesce_usecs_irq = bp->tx_ticks_int; + coal->tx_max_coalesced_frames_irq = bp->tx_quick_cons_trip_int; + + coal->stats_block_coalesce_usecs = bp->stats_ticks; + + return 0; +} + +static int +bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) +{ + struct bnx2 *bp = dev->priv; + + bp->rx_ticks = (u16) coal->rx_coalesce_usecs; + if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff; + + bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames; + if (bp->rx_quick_cons_trip > 0xff) bp->rx_quick_cons_trip = 0xff; + + bp->rx_ticks_int = (u16) coal->rx_coalesce_usecs_irq; + if (bp->rx_ticks_int > 0x3ff) bp->rx_ticks_int = 0x3ff; + + bp->rx_quick_cons_trip_int = (u16) coal->rx_max_coalesced_frames_irq; + if (bp->rx_quick_cons_trip_int > 0xff) + bp->rx_quick_cons_trip_int = 0xff; + + bp->tx_ticks = (u16) coal->tx_coalesce_usecs; + if (bp->tx_ticks > 0x3ff) bp->tx_ticks = 0x3ff; + + bp->tx_quick_cons_trip = (u16) coal->tx_max_coalesced_frames; + if (bp->tx_quick_cons_trip > 0xff) bp->tx_quick_cons_trip = 0xff; + + bp->tx_ticks_int = (u16) coal->tx_coalesce_usecs_irq; + if (bp->tx_ticks_int > 0x3ff) bp->tx_ticks_int = 0x3ff; + + bp->tx_quick_cons_trip_int = (u16) coal->tx_max_coalesced_frames_irq; + if (bp->tx_quick_cons_trip_int > 0xff) bp->tx_quick_cons_trip_int = + 0xff; + + bp->stats_ticks = coal->stats_block_coalesce_usecs; + if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00; + bp->stats_ticks &= 0xffff00; + + if (netif_running(bp->dev)) { + bnx2_netif_stop(bp); + bnx2_init_nic(bp); + bnx2_netif_start(bp); + } + + return 0; +} + +static void +bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + struct bnx2 *bp = dev->priv; + + ering->rx_max_pending = MAX_RX_DESC_CNT; + ering->rx_mini_max_pending = 0; + ering->rx_jumbo_max_pending = 0; + + ering->rx_pending = bp->rx_ring_size; + ering->rx_mini_pending = 0; + ering->rx_jumbo_pending = 0; + + ering->tx_max_pending = MAX_TX_DESC_CNT; + ering->tx_pending = bp->tx_ring_size; +} + +static int +bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + struct bnx2 *bp = dev->priv; + + if ((ering->rx_pending > MAX_RX_DESC_CNT) || + (ering->tx_pending > MAX_TX_DESC_CNT) || + (ering->tx_pending <= MAX_SKB_FRAGS)) { + + return -EINVAL; + } + bp->rx_ring_size = ering->rx_pending; + bp->tx_ring_size = ering->tx_pending; + + if (netif_running(bp->dev)) { + bnx2_netif_stop(bp); + bnx2_init_nic(bp); + bnx2_netif_start(bp); + } + + return 0; +} + +static void +bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) +{ + struct bnx2 *bp = dev->priv; + + epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0); + epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0); + epause->tx_pause = ((bp->flow_ctrl & FLOW_CTRL_TX) != 0); +} + +static int +bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) +{ + struct bnx2 *bp = dev->priv; + + bp->req_flow_ctrl = 0; + if (epause->rx_pause) + bp->req_flow_ctrl |= FLOW_CTRL_RX; + if (epause->tx_pause) + bp->req_flow_ctrl |= FLOW_CTRL_TX; + + if (epause->autoneg) { + bp->autoneg |= AUTONEG_FLOW_CTRL; + } + else { + bp->autoneg &= ~AUTONEG_FLOW_CTRL; + } + + spin_lock_irq(&bp->phy_lock); + + bnx2_setup_phy(bp); + + spin_unlock_irq(&bp->phy_lock); + + return 0; +} + +static u32 +bnx2_get_rx_csum(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + + return bp->rx_csum; +} + +static int +bnx2_set_rx_csum(struct net_device *dev, u32 data) +{ + struct bnx2 *bp = dev->priv; + + bp->rx_csum = data; + return 0; +} + +#define BNX2_NUM_STATS 45 + +struct { + char string[ETH_GSTRING_LEN]; +} bnx2_stats_str_arr[BNX2_NUM_STATS] = { + { "rx_bytes" }, + { "rx_error_bytes" }, + { "tx_bytes" }, + { "tx_error_bytes" }, + { "rx_ucast_packets" }, + { "rx_mcast_packets" }, + { "rx_bcast_packets" }, + { "tx_ucast_packets" }, + { "tx_mcast_packets" }, + { "tx_bcast_packets" }, + { "tx_mac_errors" }, + { "tx_carrier_errors" }, + { "rx_crc_errors" }, + { "rx_align_errors" }, + { "tx_single_collisions" }, + { "tx_multi_collisions" }, + { "tx_deferred" }, + { "tx_excess_collisions" }, + { "tx_late_collisions" }, + { "tx_total_collisions" }, + { "rx_fragments" }, + { "rx_jabbers" }, + { "rx_undersize_packets" }, + { "rx_oversize_packets" }, + { "rx_64_byte_packets" }, + { "rx_65_to_127_byte_packets" }, + { "rx_128_to_255_byte_packets" }, + { "rx_256_to_511_byte_packets" }, + { "rx_512_to_1023_byte_packets" }, + { "rx_1024_to_1522_byte_packets" }, + { "rx_1523_to_9022_byte_packets" }, + { "tx_64_byte_packets" }, + { "tx_65_to_127_byte_packets" }, + { "tx_128_to_255_byte_packets" }, + { "tx_256_to_511_byte_packets" }, + { "tx_512_to_1023_byte_packets" }, + { "tx_1024_to_1522_byte_packets" }, + { "tx_1523_to_9022_byte_packets" }, + { "rx_xon_frames" }, + { "rx_xoff_frames" }, + { "tx_xon_frames" }, + { "tx_xoff_frames" }, + { "rx_mac_ctrl_frames" }, + { "rx_filtered_packets" }, + { "rx_discards" }, +}; + +#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4) + +unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = { + STATS_OFFSET32(stat_IfHCInOctets_hi), + STATS_OFFSET32(stat_IfHCInBadOctets_hi), + STATS_OFFSET32(stat_IfHCOutOctets_hi), + STATS_OFFSET32(stat_IfHCOutBadOctets_hi), + STATS_OFFSET32(stat_IfHCInUcastPkts_hi), + STATS_OFFSET32(stat_IfHCInMulticastPkts_hi), + STATS_OFFSET32(stat_IfHCInBroadcastPkts_hi), + STATS_OFFSET32(stat_IfHCOutUcastPkts_hi), + STATS_OFFSET32(stat_IfHCOutMulticastPkts_hi), + STATS_OFFSET32(stat_IfHCOutBroadcastPkts_hi), + STATS_OFFSET32(stat_emac_tx_stat_dot3statsinternalmactransmiterrors), + STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors), + STATS_OFFSET32(stat_Dot3StatsFCSErrors), + STATS_OFFSET32(stat_Dot3StatsAlignmentErrors), + STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames), + STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames), + STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions), + STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions), + STATS_OFFSET32(stat_Dot3StatsLateCollisions), + STATS_OFFSET32(stat_EtherStatsCollisions), + STATS_OFFSET32(stat_EtherStatsFragments), + STATS_OFFSET32(stat_EtherStatsJabbers), + STATS_OFFSET32(stat_EtherStatsUndersizePkts), + STATS_OFFSET32(stat_EtherStatsOverrsizePkts), + STATS_OFFSET32(stat_EtherStatsPktsRx64Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx64Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets), + STATS_OFFSET32(stat_XonPauseFramesReceived), + STATS_OFFSET32(stat_XoffPauseFramesReceived), + STATS_OFFSET32(stat_OutXonSent), + STATS_OFFSET32(stat_OutXoffSent), + STATS_OFFSET32(stat_MacControlFramesReceived), + STATS_OFFSET32(stat_IfInFramesL2FilterDiscards), + STATS_OFFSET32(stat_IfInMBUFDiscards), +}; + +/* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are + * skipped because of errata. + */ +u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = { + 8,0,8,8,8,8,8,8,8,8, + 4,0,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4, +}; + +#define BNX2_NUM_TESTS 6 + +struct { + char string[ETH_GSTRING_LEN]; +} bnx2_tests_str_arr[BNX2_NUM_TESTS] = { + { "register_test (offline)" }, + { "memory_test (offline)" }, + { "loopback_test (offline)" }, + { "nvram_test (online)" }, + { "interrupt_test (online)" }, + { "link_test (online)" }, +}; + +static int +bnx2_self_test_count(struct net_device *dev) +{ + return BNX2_NUM_TESTS; +} + +static void +bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) +{ + struct bnx2 *bp = dev->priv; + + memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); + if (etest->flags & ETH_TEST_FL_OFFLINE) { + bnx2_netif_stop(bp); + bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); + bnx2_free_skbs(bp); + + if (bnx2_test_registers(bp) != 0) { + buf[0] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + if (bnx2_test_memory(bp) != 0) { + buf[1] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + if (bnx2_test_loopback(bp) != 0) { + buf[2] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + + if (!netif_running(bp->dev)) { + bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); + } + else { + bnx2_init_nic(bp); + bnx2_netif_start(bp); + } + + /* wait for link up */ + msleep_interruptible(3000); + if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG)) + msleep_interruptible(4000); + } + + if (bnx2_test_nvram(bp) != 0) { + buf[3] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + if (bnx2_test_intr(bp) != 0) { + buf[4] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + } + + if (bnx2_test_link(bp) != 0) { + buf[5] = 1; + etest->flags |= ETH_TEST_FL_FAILED; + + } +} + +static void +bnx2_get_strings(struct net_device *dev, u32 stringset, u8 *buf) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(buf, bnx2_stats_str_arr, + sizeof(bnx2_stats_str_arr)); + break; + case ETH_SS_TEST: + memcpy(buf, bnx2_tests_str_arr, + sizeof(bnx2_tests_str_arr)); + break; + } +} + +static int +bnx2_get_stats_count(struct net_device *dev) +{ + return BNX2_NUM_STATS; +} + +static void +bnx2_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *buf) +{ + struct bnx2 *bp = dev->priv; + int i; + u32 *hw_stats = (u32 *) bp->stats_blk; + u8 *stats_len_arr = 0; + + if (hw_stats == NULL) { + memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS); + return; + } + + if (CHIP_NUM(bp) == CHIP_NUM_5706) + stats_len_arr = bnx2_5706_stats_len_arr; + + for (i = 0; i < BNX2_NUM_STATS; i++) { + if (stats_len_arr[i] == 0) { + /* skip this counter */ + buf[i] = 0; + continue; + } + if (stats_len_arr[i] == 4) { + /* 4-byte counter */ + buf[i] = (u64) + *(hw_stats + bnx2_stats_offset_arr[i]); + continue; + } + /* 8-byte counter */ + buf[i] = (((u64) *(hw_stats + + bnx2_stats_offset_arr[i])) << 32) + + *(hw_stats + bnx2_stats_offset_arr[i] + 1); + } +} + +static int +bnx2_phys_id(struct net_device *dev, u32 data) +{ + struct bnx2 *bp = dev->priv; + int i; + u32 save; + + if (data == 0) + data = 2; + + save = REG_RD(bp, BNX2_MISC_CFG); + REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); + + for (i = 0; i < (data * 2); i++) { + if ((i % 2) == 0) { + REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE); + } + else { + REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | + BNX2_EMAC_LED_1000MB_OVERRIDE | + BNX2_EMAC_LED_100MB_OVERRIDE | + BNX2_EMAC_LED_10MB_OVERRIDE | + BNX2_EMAC_LED_TRAFFIC_OVERRIDE | + BNX2_EMAC_LED_TRAFFIC); + } + msleep_interruptible(500); + if (signal_pending(current)) + break; + } + REG_WR(bp, BNX2_EMAC_LED, 0); + REG_WR(bp, BNX2_MISC_CFG, save); + return 0; +} + +static struct ethtool_ops bnx2_ethtool_ops = { + .get_settings = bnx2_get_settings, + .set_settings = bnx2_set_settings, + .get_drvinfo = bnx2_get_drvinfo, + .get_wol = bnx2_get_wol, + .set_wol = bnx2_set_wol, + .nway_reset = bnx2_nway_reset, + .get_link = ethtool_op_get_link, + .get_eeprom_len = bnx2_get_eeprom_len, + .get_eeprom = bnx2_get_eeprom, + .set_eeprom = bnx2_set_eeprom, + .get_coalesce = bnx2_get_coalesce, + .set_coalesce = bnx2_set_coalesce, + .get_ringparam = bnx2_get_ringparam, + .set_ringparam = bnx2_set_ringparam, + .get_pauseparam = bnx2_get_pauseparam, + .set_pauseparam = bnx2_set_pauseparam, + .get_rx_csum = bnx2_get_rx_csum, + .set_rx_csum = bnx2_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef BCM_TSO + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +#endif + .self_test_count = bnx2_self_test_count, + .self_test = bnx2_self_test, + .get_strings = bnx2_get_strings, + .phys_id = bnx2_phys_id, + .get_stats_count = bnx2_get_stats_count, + .get_ethtool_stats = bnx2_get_ethtool_stats, +}; + +/* Called with rtnl_lock */ +static int +bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; + struct bnx2 *bp = dev->priv; + int err; + + switch(cmd) { + case SIOCGMIIPHY: + data->phy_id = bp->phy_addr; + + /* fallthru */ + case SIOCGMIIREG: { + u32 mii_regval; + + spin_lock_irq(&bp->phy_lock); + err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval); + spin_unlock_irq(&bp->phy_lock); + + data->val_out = mii_regval; + + return err; + } + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_irq(&bp->phy_lock); + err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in); + spin_unlock_irq(&bp->phy_lock); + + return err; + + default: + /* do nothing */ + break; + } + return -EOPNOTSUPP; +} + +/* Called with rtnl_lock */ +static int +bnx2_change_mac_addr(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + struct bnx2 *bp = dev->priv; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + if (netif_running(dev)) + bnx2_set_mac_addr(bp); + + return 0; +} + +/* Called with rtnl_lock */ +static int +bnx2_change_mtu(struct net_device *dev, int new_mtu) +{ + struct bnx2 *bp = dev->priv; + + if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) || + ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE)) + return -EINVAL; + + dev->mtu = new_mtu; + if (netif_running(dev)) { + bnx2_netif_stop(bp); + + bnx2_init_nic(bp); + + bnx2_netif_start(bp); + } + return 0; +} + +#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) +static void +poll_bnx2(struct net_device *dev) +{ + struct bnx2 *bp = dev->priv; + + disable_irq(bp->pdev->irq); + bnx2_interrupt(bp->pdev->irq, dev, NULL); + enable_irq(bp->pdev->irq); +} +#endif + +static int __devinit +bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) +{ + struct bnx2 *bp; + unsigned long mem_len; + int rc; + u32 reg; + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + bp = dev->priv; + + bp->flags = 0; + bp->phy_flags = 0; + + /* enable device (incl. PCI PM wakeup), and bus-mastering */ + rc = pci_enable_device(pdev); + if (rc) { + printk(KERN_ERR PFX "Cannot enable PCI device, aborting."); + goto err_out; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + printk(KERN_ERR PFX "Cannot find PCI device base address, " + "aborting.\n"); + rc = -ENODEV; + goto err_out_disable; + } + + rc = pci_request_regions(pdev, DRV_MODULE_NAME); + if (rc) { + printk(KERN_ERR PFX "Cannot obtain PCI resources, aborting.\n"); + goto err_out_disable; + } + + pci_set_master(pdev); + + bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (bp->pm_cap == 0) { + printk(KERN_ERR PFX "Cannot find power management capability, " + "aborting.\n"); + rc = -EIO; + goto err_out_release; + } + + bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); + if (bp->pcix_cap == 0) { + printk(KERN_ERR PFX "Cannot find PCIX capability, aborting.\n"); + rc = -EIO; + goto err_out_release; + } + + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { + bp->flags |= USING_DAC_FLAG; + if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) { + printk(KERN_ERR PFX "pci_set_consistent_dma_mask " + "failed, aborting.\n"); + rc = -EIO; + goto err_out_release; + } + } + else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) { + printk(KERN_ERR PFX "System does not support DMA, aborting.\n"); + rc = -EIO; + goto err_out_release; + } + + bp->dev = dev; + bp->pdev = pdev; + + spin_lock_init(&bp->phy_lock); + spin_lock_init(&bp->tx_lock); + INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); + + dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); + mem_len = MB_GET_CID_ADDR(17); + dev->mem_end = dev->mem_start + mem_len; + dev->irq = pdev->irq; + + bp->regview = ioremap_nocache(dev->base_addr, mem_len); + + if (!bp->regview) { + printk(KERN_ERR PFX "Cannot map register space, aborting.\n"); + rc = -ENOMEM; + goto err_out_release; + } + + /* Configure byte swap and enable write to the reg_window registers. + * Rely on CPU to do target byte swapping on big endian systems + * The chip's target access swapping will not swap all accesses + */ + pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, + BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); + + bnx2_set_power_state(bp, 0); + + bp->chip_id = REG_RD(bp, BNX2_MISC_ID); + + bp->phy_addr = 1; + + /* Get bus information. */ + reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); + if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { + u32 clkreg; + + bp->flags |= PCIX_FLAG; + + clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); + + clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; + switch (clkreg) { + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: + bp->bus_speed_mhz = 133; + break; + + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: + bp->bus_speed_mhz = 100; + break; + + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: + bp->bus_speed_mhz = 66; + break; + + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: + bp->bus_speed_mhz = 50; + break; + + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: + case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: + bp->bus_speed_mhz = 33; + break; + } + } + else { + if (reg & BNX2_PCICFG_MISC_STATUS_M66EN) + bp->bus_speed_mhz = 66; + else + bp->bus_speed_mhz = 33; + } + + if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET) + bp->flags |= PCI_32BIT_FLAG; + + /* 5706A0 may falsely detect SERR and PERR. */ + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + reg = REG_RD(bp, PCI_COMMAND); + reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + REG_WR(bp, PCI_COMMAND, reg); + } + else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) && + !(bp->flags & PCIX_FLAG)) { + + printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, " + "aborting.\n"); + goto err_out_unmap; + } + + bnx2_init_nvram(bp); + + /* Get the permanent MAC address. First we need to make sure the + * firmware is actually running. + */ + reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DEV_INFO_SIGNATURE); + + if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) != + BNX2_DEV_INFO_SIGNATURE_MAGIC) { + printk(KERN_ERR PFX "Firmware not running, aborting.\n"); + rc = -ENODEV; + goto err_out_unmap; + } + + bp->fw_ver = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_DEV_INFO_BC_REV); + + reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_MAC_UPPER); + bp->mac_addr[0] = (u8) (reg >> 8); + bp->mac_addr[1] = (u8) reg; + + reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_MAC_LOWER); + bp->mac_addr[2] = (u8) (reg >> 24); + bp->mac_addr[3] = (u8) (reg >> 16); + bp->mac_addr[4] = (u8) (reg >> 8); + bp->mac_addr[5] = (u8) reg; + + bp->tx_ring_size = MAX_TX_DESC_CNT; + bp->rx_ring_size = 100; + + bp->rx_csum = 1; + + bp->rx_offset = sizeof(struct l2_fhdr) + 2; + + bp->tx_quick_cons_trip_int = 20; + bp->tx_quick_cons_trip = 20; + bp->tx_ticks_int = 80; + bp->tx_ticks = 80; + + bp->rx_quick_cons_trip_int = 6; + bp->rx_quick_cons_trip = 6; + bp->rx_ticks_int = 18; + bp->rx_ticks = 18; + + bp->stats_ticks = 1000000 & 0xffff00; + + bp->timer_interval = HZ; + + /* Disable WOL support if we are running on a SERDES chip. */ + if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) { + bp->phy_flags |= PHY_SERDES_FLAG; + bp->flags |= NO_WOL_FLAG; + } + + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + bp->tx_quick_cons_trip_int = + bp->tx_quick_cons_trip; + bp->tx_ticks_int = bp->tx_ticks; + bp->rx_quick_cons_trip_int = + bp->rx_quick_cons_trip; + bp->rx_ticks_int = bp->rx_ticks; + bp->comp_prod_trip_int = bp->comp_prod_trip; + bp->com_ticks_int = bp->com_ticks; + bp->cmd_ticks_int = bp->cmd_ticks; + } + + bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; + bp->req_line_speed = 0; + if (bp->phy_flags & PHY_SERDES_FLAG) { + bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; + } + else { + bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; + } + + bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; + + return 0; + +err_out_unmap: + if (bp->regview) { + iounmap(bp->regview); + } + +err_out_release: + pci_release_regions(pdev); + +err_out_disable: + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + +err_out: + return rc; +} + +static int __devinit +bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int version_printed = 0; + struct net_device *dev = NULL; + struct bnx2 *bp; + int rc, i; + + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); + + /* dev zeroed in init_etherdev */ + dev = alloc_etherdev(sizeof(*bp)); + + if (!dev) + return -ENOMEM; + + rc = bnx2_init_board(pdev, dev); + if (rc < 0) { + free_netdev(dev); + return rc; + } + + dev->open = bnx2_open; + dev->hard_start_xmit = bnx2_start_xmit; + dev->stop = bnx2_close; + dev->get_stats = bnx2_get_stats; + dev->set_multicast_list = bnx2_set_rx_mode; + dev->do_ioctl = bnx2_ioctl; + dev->set_mac_address = bnx2_change_mac_addr; + dev->change_mtu = bnx2_change_mtu; + dev->tx_timeout = bnx2_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; +#ifdef BCM_VLAN + dev->vlan_rx_register = bnx2_vlan_rx_register; + dev->vlan_rx_kill_vid = bnx2_vlan_rx_kill_vid; +#endif + dev->poll = bnx2_poll; + dev->ethtool_ops = &bnx2_ethtool_ops; + dev->weight = 64; + + bp = dev->priv; + +#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) + dev->poll_controller = poll_bnx2; +#endif + + if ((rc = register_netdev(dev))) { + printk(KERN_ERR PFX "Cannot register net device\n"); + if (bp->regview) + iounmap(bp->regview); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + free_netdev(dev); + return rc; + } + + pci_set_drvdata(pdev, dev); + + memcpy(dev->dev_addr, bp->mac_addr, 6); + bp->name = board_info[ent->driver_data].name, + printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, " + "IRQ %d, ", + dev->name, + bp->name, + ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', + ((CHIP_ID(bp) & 0x0ff0) >> 4), + ((bp->flags & PCIX_FLAG) ? "-X" : ""), + ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"), + bp->bus_speed_mhz, + dev->base_addr, + bp->pdev->irq); + + printk("node addr "); + for (i = 0; i < 6; i++) + printk("%2.2x", dev->dev_addr[i]); + printk("\n"); + + dev->features |= NETIF_F_SG; + if (bp->flags & USING_DAC_FLAG) + dev->features |= NETIF_F_HIGHDMA; + dev->features |= NETIF_F_IP_CSUM; +#ifdef BCM_VLAN + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +#endif +#ifdef BCM_TSO + dev->features |= NETIF_F_TSO; +#endif + + netif_carrier_off(bp->dev); + + return 0; +} + +static void __devexit +bnx2_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2 *bp = dev->priv; + + unregister_netdev(dev); + + if (bp->regview) + iounmap(bp->regview); + + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +static int +bnx2_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2 *bp = dev->priv; + u32 reset_code; + + if (!netif_running(dev)) + return 0; + + bnx2_netif_stop(bp); + netif_device_detach(dev); + del_timer_sync(&bp->timer); + if (bp->wol) + reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; + else + reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; + bnx2_reset_chip(bp, reset_code); + bnx2_free_skbs(bp); + bnx2_set_power_state(bp, state); + return 0; +} + +static int +bnx2_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2 *bp = dev->priv; + + if (!netif_running(dev)) + return 0; + + bnx2_set_power_state(bp, 0); + netif_device_attach(dev); + bnx2_init_nic(bp); + bnx2_netif_start(bp); + return 0; +} + +static struct pci_driver bnx2_pci_driver = { + name: DRV_MODULE_NAME, + id_table: bnx2_pci_tbl, + probe: bnx2_init_one, + remove: __devexit_p(bnx2_remove_one), + suspend: bnx2_suspend, + resume: bnx2_resume, +}; + +static int __init bnx2_init(void) +{ + return pci_module_init(&bnx2_pci_driver); +} + +static void __exit bnx2_cleanup(void) +{ + pci_unregister_driver(&bnx2_pci_driver); +} + +module_init(bnx2_init); +module_exit(bnx2_cleanup); + + + diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h new file mode 100644 index 0000000..8214a28 --- /dev/null +++ b/drivers/net/bnx2.h @@ -0,0 +1,4352 @@ +/* bnx2.h: Broadcom NX2 network driver. + * + * Copyright (c) 2004, 2005 Broadcom Corporation + * + * 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. + * + * Written by: Michael Chan (mchan@broadcom.com) + */ + + +#ifndef BNX2_H +#define BNX2_H + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef NETIF_F_HW_VLAN_TX +#include +#define BCM_VLAN 1 +#endif +#ifdef NETIF_F_TSO +#include +#include +#include +#define BCM_TSO 1 +#endif +#include +#include + +/* Hardware data structures and register definitions automatically + * generated from RTL code. Do not modify. + */ + +/* + * tx_bd definition + */ +struct tx_bd { + u32 tx_bd_haddr_hi; + u32 tx_bd_haddr_lo; + u32 tx_bd_mss_nbytes; + u32 tx_bd_vlan_tag_flags; + #define TX_BD_FLAGS_CONN_FAULT (1<<0) + #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1) + #define TX_BD_FLAGS_IP_CKSUM (1<<2) + #define TX_BD_FLAGS_VLAN_TAG (1<<3) + #define TX_BD_FLAGS_COAL_NOW (1<<4) + #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5) + #define TX_BD_FLAGS_END (1<<6) + #define TX_BD_FLAGS_START (1<<7) + #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8) + #define TX_BD_FLAGS_SW_FLAGS (1<<13) + #define TX_BD_FLAGS_SW_SNAP (1<<14) + #define TX_BD_FLAGS_SW_LSO (1<<15) + +}; + + +/* + * rx_bd definition + */ +struct rx_bd { + u32 rx_bd_haddr_hi; + u32 rx_bd_haddr_lo; + u32 rx_bd_len; + u32 rx_bd_flags; + #define RX_BD_FLAGS_NOPUSH (1<<0) + #define RX_BD_FLAGS_DUMMY (1<<1) + #define RX_BD_FLAGS_END (1<<2) + #define RX_BD_FLAGS_START (1<<3) + +}; + + +/* + * status_block definition + */ +struct status_block { + u32 status_attn_bits; + #define STATUS_ATTN_BITS_LINK_STATE (1L<<0) + #define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT (1L<<1) + #define STATUS_ATTN_BITS_TX_BD_READ_ABORT (1L<<2) + #define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT (1L<<3) + #define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT (1L<<4) + #define STATUS_ATTN_BITS_TX_DMA_ABORT (1L<<5) + #define STATUS_ATTN_BITS_TX_PATCHUP_ABORT (1L<<6) + #define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT (1L<<7) + #define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT (1L<<8) + #define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT (1L<<9) + #define STATUS_ATTN_BITS_RX_MBUF_ABORT (1L<<10) + #define STATUS_ATTN_BITS_RX_LOOKUP_ABORT (1L<<11) + #define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT (1L<<12) + #define STATUS_ATTN_BITS_RX_V2P_ABORT (1L<<13) + #define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT (1L<<14) + #define STATUS_ATTN_BITS_RX_DMA_ABORT (1L<<15) + #define STATUS_ATTN_BITS_COMPLETION_ABORT (1L<<16) + #define STATUS_ATTN_BITS_HOST_COALESCE_ABORT (1L<<17) + #define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT (1L<<18) + #define STATUS_ATTN_BITS_CONTEXT_ABORT (1L<<19) + #define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT (1L<<20) + #define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT (1L<<21) + #define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT (1L<<22) + #define STATUS_ATTN_BITS_MAC_ABORT (1L<<23) + #define STATUS_ATTN_BITS_TIMER_ABORT (1L<<24) + #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25) + #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26) + #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27) + #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31) + + u32 status_attn_bits_ack; +#if defined(__BIG_ENDIAN) + u16 status_tx_quick_consumer_index0; + u16 status_tx_quick_consumer_index1; + u16 status_tx_quick_consumer_index2; + u16 status_tx_quick_consumer_index3; + u16 status_rx_quick_consumer_index0; + u16 status_rx_quick_consumer_index1; + u16 status_rx_quick_consumer_index2; + u16 status_rx_quick_consumer_index3; + u16 status_rx_quick_consumer_index4; + u16 status_rx_quick_consumer_index5; + u16 status_rx_quick_consumer_index6; + u16 status_rx_quick_consumer_index7; + u16 status_rx_quick_consumer_index8; + u16 status_rx_quick_consumer_index9; + u16 status_rx_quick_consumer_index10; + u16 status_rx_quick_consumer_index11; + u16 status_rx_quick_consumer_index12; + u16 status_rx_quick_consumer_index13; + u16 status_rx_quick_consumer_index14; + u16 status_rx_quick_consumer_index15; + u16 status_completion_producer_index; + u16 status_cmd_consumer_index; + u16 status_idx; + u16 status_unused; +#elif defined(__LITTLE_ENDIAN) + u16 status_tx_quick_consumer_index1; + u16 status_tx_quick_consumer_index0; + u16 status_tx_quick_consumer_index3; + u16 status_tx_quick_consumer_index2; + u16 status_rx_quick_consumer_index1; + u16 status_rx_quick_consumer_index0; + u16 status_rx_quick_consumer_index3; + u16 status_rx_quick_consumer_index2; + u16 status_rx_quick_consumer_index5; + u16 status_rx_quick_consumer_index4; + u16 status_rx_quick_consumer_index7; + u16 status_rx_quick_consumer_index6; + u16 status_rx_quick_consumer_index9; + u16 status_rx_quick_consumer_index8; + u16 status_rx_quick_consumer_index11; + u16 status_rx_quick_consumer_index10; + u16 status_rx_quick_consumer_index13; + u16 status_rx_quick_consumer_index12; + u16 status_rx_quick_consumer_index15; + u16 status_rx_quick_consumer_index14; + u16 status_cmd_consumer_index; + u16 status_completion_producer_index; + u16 status_unused; + u16 status_idx; +#endif +}; + + +/* + * statistics_block definition + */ +struct statistics_block { + u32 stat_IfHCInOctets_hi; + u32 stat_IfHCInOctets_lo; + u32 stat_IfHCInBadOctets_hi; + u32 stat_IfHCInBadOctets_lo; + u32 stat_IfHCOutOctets_hi; + u32 stat_IfHCOutOctets_lo; + u32 stat_IfHCOutBadOctets_hi; + u32 stat_IfHCOutBadOctets_lo; + u32 stat_IfHCInUcastPkts_hi; + u32 stat_IfHCInUcastPkts_lo; + u32 stat_IfHCInMulticastPkts_hi; + u32 stat_IfHCInMulticastPkts_lo; + u32 stat_IfHCInBroadcastPkts_hi; + u32 stat_IfHCInBroadcastPkts_lo; + u32 stat_IfHCOutUcastPkts_hi; + u32 stat_IfHCOutUcastPkts_lo; + u32 stat_IfHCOutMulticastPkts_hi; + u32 stat_IfHCOutMulticastPkts_lo; + u32 stat_IfHCOutBroadcastPkts_hi; + u32 stat_IfHCOutBroadcastPkts_lo; + u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors; + u32 stat_Dot3StatsCarrierSenseErrors; + u32 stat_Dot3StatsFCSErrors; + u32 stat_Dot3StatsAlignmentErrors; + u32 stat_Dot3StatsSingleCollisionFrames; + u32 stat_Dot3StatsMultipleCollisionFrames; + u32 stat_Dot3StatsDeferredTransmissions; + u32 stat_Dot3StatsExcessiveCollisions; + u32 stat_Dot3StatsLateCollisions; + u32 stat_EtherStatsCollisions; + u32 stat_EtherStatsFragments; + u32 stat_EtherStatsJabbers; + u32 stat_EtherStatsUndersizePkts; + u32 stat_EtherStatsOverrsizePkts; + u32 stat_EtherStatsPktsRx64Octets; + u32 stat_EtherStatsPktsRx65Octetsto127Octets; + u32 stat_EtherStatsPktsRx128Octetsto255Octets; + u32 stat_EtherStatsPktsRx256Octetsto511Octets; + u32 stat_EtherStatsPktsRx512Octetsto1023Octets; + u32 stat_EtherStatsPktsRx1024Octetsto1522Octets; + u32 stat_EtherStatsPktsRx1523Octetsto9022Octets; + u32 stat_EtherStatsPktsTx64Octets; + u32 stat_EtherStatsPktsTx65Octetsto127Octets; + u32 stat_EtherStatsPktsTx128Octetsto255Octets; + u32 stat_EtherStatsPktsTx256Octetsto511Octets; + u32 stat_EtherStatsPktsTx512Octetsto1023Octets; + u32 stat_EtherStatsPktsTx1024Octetsto1522Octets; + u32 stat_EtherStatsPktsTx1523Octetsto9022Octets; + u32 stat_XonPauseFramesReceived; + u32 stat_XoffPauseFramesReceived; + u32 stat_OutXonSent; + u32 stat_OutXoffSent; + u32 stat_FlowControlDone; + u32 stat_MacControlFramesReceived; + u32 stat_XoffStateEntered; + u32 stat_IfInFramesL2FilterDiscards; + u32 stat_IfInRuleCheckerDiscards; + u32 stat_IfInFTQDiscards; + u32 stat_IfInMBUFDiscards; + u32 stat_IfInRuleCheckerP4Hit; + u32 stat_CatchupInRuleCheckerDiscards; + u32 stat_CatchupInFTQDiscards; + u32 stat_CatchupInMBUFDiscards; + u32 stat_CatchupInRuleCheckerP4Hit; + u32 stat_GenStat00; + u32 stat_GenStat01; + u32 stat_GenStat02; + u32 stat_GenStat03; + u32 stat_GenStat04; + u32 stat_GenStat05; + u32 stat_GenStat06; + u32 stat_GenStat07; + u32 stat_GenStat08; + u32 stat_GenStat09; + u32 stat_GenStat10; + u32 stat_GenStat11; + u32 stat_GenStat12; + u32 stat_GenStat13; + u32 stat_GenStat14; + u32 stat_GenStat15; +}; + + +/* + * l2_fhdr definition + */ +struct l2_fhdr { +#if defined(__BIG_ENDIAN) + u16 l2_fhdr_errors; + u16 l2_fhdr_status; +#elif defined(__LITTLE_ENDIAN) + u16 l2_fhdr_status; + u16 l2_fhdr_errors; +#endif + #define L2_FHDR_ERRORS_BAD_CRC (1<<1) + #define L2_FHDR_ERRORS_PHY_DECODE (1<<2) + #define L2_FHDR_ERRORS_ALIGNMENT (1<<3) + #define L2_FHDR_ERRORS_TOO_SHORT (1<<4) + #define L2_FHDR_ERRORS_GIANT_FRAME (1<<5) + + #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0) + #define L2_FHDR_STATUS_RULE_P2 (1<<3) + #define L2_FHDR_STATUS_RULE_P3 (1<<4) + #define L2_FHDR_STATUS_RULE_P4 (1<<5) + #define L2_FHDR_STATUS_L2_VLAN_TAG (1<<6) + #define L2_FHDR_STATUS_L2_LLC_SNAP (1<<7) + #define L2_FHDR_STATUS_RSS_HASH (1<<8) + #define L2_FHDR_STATUS_IP_DATAGRAM (1<<13) + #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14) + #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15) + + u32 l2_fhdr_hash; +#if defined(__BIG_ENDIAN) + u16 l2_fhdr_pkt_len; + u16 l2_fhdr_vlan_tag; + u16 l2_fhdr_ip_xsum; + u16 l2_fhdr_tcp_udp_xsum; +#elif defined(__LITTLE_ENDIAN) + u16 l2_fhdr_vlan_tag; + u16 l2_fhdr_pkt_len; + u16 l2_fhdr_tcp_udp_xsum; + u16 l2_fhdr_ip_xsum; +#endif +}; + + +/* + * l2_context definition + */ +#define BNX2_L2CTX_TYPE 0x00000000 +#define BNX2_L2CTX_TYPE_SIZE_L2 ((0xc0/0x20)<<16) +#define BNX2_L2CTX_TYPE_TYPE (0xf<<28) +#define BNX2_L2CTX_TYPE_TYPE_EMPTY (0<<28) +#define BNX2_L2CTX_TYPE_TYPE_L2 (1<<28) + +#define BNX2_L2CTX_TX_HOST_BIDX 0x00000088 +#define BNX2_L2CTX_EST_NBD 0x00000088 +#define BNX2_L2CTX_CMD_TYPE 0x00000088 +#define BNX2_L2CTX_CMD_TYPE_TYPE (0xf<<24) +#define BNX2_L2CTX_CMD_TYPE_TYPE_L2 (0<<24) +#define BNX2_L2CTX_CMD_TYPE_TYPE_TCP (1<<24) + +#define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090 +#define BNX2_L2CTX_TSCH_BSEQ 0x00000094 +#define BNX2_L2CTX_TBDR_BSEQ 0x00000098 +#define BNX2_L2CTX_TBDR_BOFF 0x0000009c +#define BNX2_L2CTX_TBDR_BIDX 0x0000009c +#define BNX2_L2CTX_TBDR_BHADDR_HI 0x000000a0 +#define BNX2_L2CTX_TBDR_BHADDR_LO 0x000000a4 +#define BNX2_L2CTX_TXP_BOFF 0x000000a8 +#define BNX2_L2CTX_TXP_BIDX 0x000000a8 +#define BNX2_L2CTX_TXP_BSEQ 0x000000ac + + +/* + * l2_bd_chain_context definition + */ +#define BNX2_L2CTX_BD_PRE_READ 0x00000000 +#define BNX2_L2CTX_CTX_SIZE 0x00000000 +#define BNX2_L2CTX_CTX_TYPE 0x00000000 +#define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16) +#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28) +#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28) +#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28) + +#define BNX2_L2CTX_HOST_BDIDX 0x00000004 +#define BNX2_L2CTX_HOST_BSEQ 0x00000008 +#define BNX2_L2CTX_NX_BSEQ 0x0000000c +#define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010 +#define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014 +#define BNX2_L2CTX_NX_BDIDX 0x00000018 + + +/* + * pci_config_l definition + * offset: 0000 + */ +#define BNX2_PCICFG_MISC_CONFIG 0x00000068 +#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2) +#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3) +#define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5) +#define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6) +#define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7) +#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8) +#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9) +#define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16) +#define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24) +#define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28) + +#define BNX2_PCICFG_MISC_STATUS 0x0000006c +#define BNX2_PCICFG_MISC_STATUS_INTA_VALUE (1L<<0) +#define BNX2_PCICFG_MISC_STATUS_32BIT_DET (1L<<1) +#define BNX2_PCICFG_MISC_STATUS_M66EN (1L<<2) +#define BNX2_PCICFG_MISC_STATUS_PCIX_DET (1L<<3) +#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED (0x3L<<4) +#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66 (0L<<4) +#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4) +#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4) +#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4) + +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070 +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20) + +#define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078 +#define BNX2_PCICFG_REG_WINDOW 0x00000080 +#define BNX2_PCICFG_INT_ACK_CMD 0x00000084 +#define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0) +#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16) +#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17) +#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18) + +#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088 +#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c +#define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090 +#define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094 + + +/* + * pci_reg definition + * offset: 0x400 + */ +#define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400 +#define BNX2_PCI_GRC_WINDOW_ADDR_PCI_GRC_WINDOW_ADDR_VALUE (0x3ffffL<<8) + +#define BNX2_PCI_CONFIG_1 0x00000404 +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32 (2L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64 (3L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128 (4L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256 (5L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512 (6L<<8) +#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024 (7L<<8) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY (0x7L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF (0L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16 (1L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32 (2L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64 (3L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128 (4L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11) +#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11) + +#define BNX2_PCI_CONFIG_2 0x00000408 +#define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0) +#define BNX2_PCI_CONFIG_2_BAR1_64ENA (1L<<4) +#define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5) +#define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6) +#define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K (1L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K (2L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K (3L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K (4L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K (5L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K (6L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K (7L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K (8L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K (9L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K (10L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M (11L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M (12L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M (13L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M (14L<<8) +#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M (15L<<8) +#define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT (0x1fL<<16) +#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT (0x3L<<21) +#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512 (0L<<21) +#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K (1L<<21) +#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K (2L<<21) +#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K (3L<<21) +#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23) +#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24) +#define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25) + +#define BNX2_PCI_CONFIG_3 0x0000040c +#define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0) +#define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24) +#define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25) +#define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26) +#define BNX2_PCI_CONFIG_3_PM_STATE (0x3L<<27) +#define BNX2_PCI_CONFIG_3_VAUX_PRESET (1L<<30) +#define BNX2_PCI_CONFIG_3_PCI_POWER (1L<<31) + +#define BNX2_PCI_PM_DATA_A 0x00000410 +#define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG (0xffL<<0) +#define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG (0xffL<<8) +#define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG (0xffL<<16) +#define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG (0xffL<<24) + +#define BNX2_PCI_PM_DATA_B 0x00000414 +#define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG (0xffL<<0) +#define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG (0xffL<<8) +#define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG (0xffL<<16) +#define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG (0xffL<<24) + +#define BNX2_PCI_SWAP_DIAG0 0x00000418 +#define BNX2_PCI_SWAP_DIAG1 0x0000041c +#define BNX2_PCI_EXP_ROM_ADDR 0x00000420 +#define BNX2_PCI_EXP_ROM_ADDR_ADDRESS (0x3fffffL<<2) +#define BNX2_PCI_EXP_ROM_ADDR_REQ (1L<<31) + +#define BNX2_PCI_EXP_ROM_DATA 0x00000424 +#define BNX2_PCI_VPD_INTF 0x00000428 +#define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0) + +#define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c +#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fff<<2) +#define BNX2_PCI_VPD_ADDR_FLAG_WR (1<<15) + +#define BNX2_PCI_VPD_DATA 0x00000430 +#define BNX2_PCI_ID_VAL1 0x00000434 +#define BNX2_PCI_ID_VAL1_DEVICE_ID (0xffffL<<0) +#define BNX2_PCI_ID_VAL1_VENDOR_ID (0xffffL<<16) + +#define BNX2_PCI_ID_VAL2 0x00000438 +#define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID (0xffffL<<0) +#define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID (0xffffL<<16) + +#define BNX2_PCI_ID_VAL3 0x0000043c +#define BNX2_PCI_ID_VAL3_CLASS_CODE (0xffffffL<<0) +#define BNX2_PCI_ID_VAL3_REVISION_ID (0xffL<<24) + +#define BNX2_PCI_ID_VAL4 0x00000440 +#define BNX2_PCI_ID_VAL4_CAP_ENA (0xfL<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_0 (0L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_1 (1L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_2 (2L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_3 (3L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_4 (4L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_5 (5L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_6 (6L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_7 (7L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_8 (8L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_9 (9L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_10 (10L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_11 (11L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_12 (12L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0) +#define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0) +#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6) +#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6) +#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6) +#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6) +#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6) +#define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9) +#define BNX2_PCI_ID_VAL4_MSI_ADVERTIZE (0x7L<<12) +#define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15) +#define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16) +#define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17) +#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE (0x3L<<21) +#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE (0x7L<<23) +#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE (0x7L<<26) + +#define BNX2_PCI_ID_VAL5 0x00000444 +#define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0) +#define BNX2_PCI_ID_VAL5_D2_SUPPORT (1L<<1) +#define BNX2_PCI_ID_VAL5_PME_IN_D0 (1L<<2) +#define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3) +#define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4) +#define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5) + +#define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448 +#define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8) +#define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST (1L<<9) +#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS (0xfL<<16) +#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX (0xffL<<24) + +#define BNX2_PCI_ID_VAL6 0x0000044c +#define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0) +#define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8) +#define BNX2_PCI_ID_VAL6_BIST (0xffL<<16) + +#define BNX2_PCI_MSI_DATA 0x00000450 +#define BNX2_PCI_MSI_DATA_PCI_MSI_DATA (0xffffL<<0) + +#define BNX2_PCI_MSI_ADDR_H 0x00000454 +#define BNX2_PCI_MSI_ADDR_L 0x00000458 + + +/* + * misc_reg definition + * offset: 0x800 + */ +#define BNX2_MISC_COMMAND 0x00000800 +#define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0) +#define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1) +#define BNX2_MISC_COMMAND_CORE_RESET (1L<<4) +#define BNX2_MISC_COMMAND_HARD_RESET (1L<<5) +#define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8) +#define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16) + +#define BNX2_MISC_CFG 0x00000804 +#define BNX2_MISC_CFG_PCI_GRC_TMOUT (1L<<0) +#define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1) +#define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1) +#define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1) +#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW (2L<<1) +#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1) +#define BNX2_MISC_CFG_BIST_EN (1L<<3) +#define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4) +#define BNX2_MISC_CFG_BYPASS_BSCAN (1L<<5) +#define BNX2_MISC_CFG_BYPASS_EJTAG (1L<<6) +#define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7) +#define BNX2_MISC_CFG_LEDMODE (0x3L<<8) +#define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8) +#define BNX2_MISC_CFG_LEDMODE_GPHY1 (1L<<8) +#define BNX2_MISC_CFG_LEDMODE_GPHY2 (2L<<8) + +#define BNX2_MISC_ID 0x00000808 +#define BNX2_MISC_ID_BOND_ID (0xfL<<0) +#define BNX2_MISC_ID_CHIP_METAL (0xffL<<4) +#define BNX2_MISC_ID_CHIP_REV (0xfL<<12) +#define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16) + +#define BNX2_MISC_ENABLE_STATUS_BITS 0x0000080c +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE (1L<<0) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE (1L<<1) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE (1L<<2) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE (1L<<3) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE (1L<<4) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE (1L<<5) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE (1L<<7) +#define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE (1L<<8) +#define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE (1L<<9) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE (1L<<10) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE (1L<<12) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE (1L<<13) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE (1L<<14) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE (1L<<15) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE (1L<<16) +#define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE (1L<<17) +#define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE (1L<<18) +#define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE (1L<<19) +#define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) +#define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE (1L<<21) +#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE (1L<<22) +#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE (1L<<23) +#define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) +#define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25) +#define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26) +#define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27) + +#define BNX2_MISC_ENABLE_SET_BITS 0x00000810 +#define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0) +#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE (1L<<1) +#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE (1L<<2) +#define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE (1L<<3) +#define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE (1L<<4) +#define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE (1L<<5) +#define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) +#define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE (1L<<7) +#define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE (1L<<8) +#define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE (1L<<9) +#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE (1L<<10) +#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) +#define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE (1L<<12) +#define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE (1L<<13) +#define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE (1L<<14) +#define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE (1L<<15) +#define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE (1L<<16) +#define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE (1L<<17) +#define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE (1L<<18) +#define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE (1L<<19) +#define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) +#define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE (1L<<21) +#define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE (1L<<22) +#define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE (1L<<23) +#define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) +#define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25) +#define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26) +#define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27) + +#define BNX2_MISC_ENABLE_CLR_BITS 0x00000814 +#define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE (1L<<1) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE (1L<<2) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE (1L<<3) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE (1L<<4) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE (1L<<5) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE (1L<<7) +#define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE (1L<<8) +#define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE (1L<<9) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE (1L<<10) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE (1L<<12) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE (1L<<13) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE (1L<<14) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE (1L<<15) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE (1L<<16) +#define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE (1L<<17) +#define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE (1L<<18) +#define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE (1L<<19) +#define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) +#define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE (1L<<21) +#define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE (1L<<22) +#define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE (1L<<23) +#define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) +#define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25) +#define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26) +#define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27) + +#define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818 +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16) +#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18) +#define BNX2_MISC_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20) + +#define BNX2_MISC_GPIO 0x0000081c +#define BNX2_MISC_GPIO_VALUE (0xffL<<0) +#define BNX2_MISC_GPIO_SET (0xffL<<8) +#define BNX2_MISC_GPIO_CLR (0xffL<<16) +#define BNX2_MISC_GPIO_FLOAT (0xffL<<24) + +#define BNX2_MISC_GPIO_INT 0x00000820 +#define BNX2_MISC_GPIO_INT_INT_STATE (0xfL<<0) +#define BNX2_MISC_GPIO_INT_OLD_VALUE (0xfL<<8) +#define BNX2_MISC_GPIO_INT_OLD_SET (0xfL<<16) +#define BNX2_MISC_GPIO_INT_OLD_CLR (0xfL<<24) + +#define BNX2_MISC_CONFIG_LFSR 0x00000824 +#define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0) + +#define BNX2_MISC_LFSR_MASK_BITS 0x00000828 +#define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE (1L<<0) +#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE (1L<<1) +#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE (1L<<2) +#define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE (1L<<3) +#define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE (1L<<4) +#define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE (1L<<5) +#define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6) +#define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE (1L<<7) +#define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE (1L<<8) +#define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE (1L<<9) +#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE (1L<<10) +#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11) +#define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE (1L<<12) +#define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE (1L<<13) +#define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE (1L<<14) +#define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE (1L<<15) +#define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE (1L<<16) +#define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE (1L<<17) +#define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE (1L<<18) +#define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE (1L<<19) +#define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE (1L<<20) +#define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE (1L<<21) +#define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE (1L<<22) +#define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE (1L<<23) +#define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE (1L<<24) +#define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25) +#define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26) +#define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27) + +#define BNX2_MISC_ARB_REQ0 0x0000082c +#define BNX2_MISC_ARB_REQ1 0x00000830 +#define BNX2_MISC_ARB_REQ2 0x00000834 +#define BNX2_MISC_ARB_REQ3 0x00000838 +#define BNX2_MISC_ARB_REQ4 0x0000083c +#define BNX2_MISC_ARB_FREE0 0x00000840 +#define BNX2_MISC_ARB_FREE1 0x00000844 +#define BNX2_MISC_ARB_FREE2 0x00000848 +#define BNX2_MISC_ARB_FREE3 0x0000084c +#define BNX2_MISC_ARB_FREE4 0x00000850 +#define BNX2_MISC_ARB_REQ_STATUS0 0x00000854 +#define BNX2_MISC_ARB_REQ_STATUS1 0x00000858 +#define BNX2_MISC_ARB_REQ_STATUS2 0x0000085c +#define BNX2_MISC_ARB_REQ_STATUS3 0x00000860 +#define BNX2_MISC_ARB_REQ_STATUS4 0x00000864 +#define BNX2_MISC_ARB_GNT0 0x00000868 +#define BNX2_MISC_ARB_GNT0_0 (0x7L<<0) +#define BNX2_MISC_ARB_GNT0_1 (0x7L<<4) +#define BNX2_MISC_ARB_GNT0_2 (0x7L<<8) +#define BNX2_MISC_ARB_GNT0_3 (0x7L<<12) +#define BNX2_MISC_ARB_GNT0_4 (0x7L<<16) +#define BNX2_MISC_ARB_GNT0_5 (0x7L<<20) +#define BNX2_MISC_ARB_GNT0_6 (0x7L<<24) +#define BNX2_MISC_ARB_GNT0_7 (0x7L<<28) + +#define BNX2_MISC_ARB_GNT1 0x0000086c +#define BNX2_MISC_ARB_GNT1_8 (0x7L<<0) +#define BNX2_MISC_ARB_GNT1_9 (0x7L<<4) +#define BNX2_MISC_ARB_GNT1_10 (0x7L<<8) +#define BNX2_MISC_ARB_GNT1_11 (0x7L<<12) +#define BNX2_MISC_ARB_GNT1_12 (0x7L<<16) +#define BNX2_MISC_ARB_GNT1_13 (0x7L<<20) +#define BNX2_MISC_ARB_GNT1_14 (0x7L<<24) +#define BNX2_MISC_ARB_GNT1_15 (0x7L<<28) + +#define BNX2_MISC_ARB_GNT2 0x00000870 +#define BNX2_MISC_ARB_GNT2_16 (0x7L<<0) +#define BNX2_MISC_ARB_GNT2_17 (0x7L<<4) +#define BNX2_MISC_ARB_GNT2_18 (0x7L<<8) +#define BNX2_MISC_ARB_GNT2_19 (0x7L<<12) +#define BNX2_MISC_ARB_GNT2_20 (0x7L<<16) +#define BNX2_MISC_ARB_GNT2_21 (0x7L<<20) +#define BNX2_MISC_ARB_GNT2_22 (0x7L<<24) +#define BNX2_MISC_ARB_GNT2_23 (0x7L<<28) + +#define BNX2_MISC_ARB_GNT3 0x00000874 +#define BNX2_MISC_ARB_GNT3_24 (0x7L<<0) +#define BNX2_MISC_ARB_GNT3_25 (0x7L<<4) +#define BNX2_MISC_ARB_GNT3_26 (0x7L<<8) +#define BNX2_MISC_ARB_GNT3_27 (0x7L<<12) +#define BNX2_MISC_ARB_GNT3_28 (0x7L<<16) +#define BNX2_MISC_ARB_GNT3_29 (0x7L<<20) +#define BNX2_MISC_ARB_GNT3_30 (0x7L<<24) +#define BNX2_MISC_ARB_GNT3_31 (0x7L<<28) + +#define BNX2_MISC_PRBS_CONTROL 0x00000878 +#define BNX2_MISC_PRBS_CONTROL_EN (1L<<0) +#define BNX2_MISC_PRBS_CONTROL_RSTB (1L<<1) +#define BNX2_MISC_PRBS_CONTROL_INV (1L<<2) +#define BNX2_MISC_PRBS_CONTROL_ERR_CLR (1L<<3) +#define BNX2_MISC_PRBS_CONTROL_ORDER (0x3L<<4) +#define BNX2_MISC_PRBS_CONTROL_ORDER_7TH (0L<<4) +#define BNX2_MISC_PRBS_CONTROL_ORDER_15TH (1L<<4) +#define BNX2_MISC_PRBS_CONTROL_ORDER_23RD (2L<<4) +#define BNX2_MISC_PRBS_CONTROL_ORDER_31ST (3L<<4) + +#define BNX2_MISC_PRBS_STATUS 0x0000087c +#define BNX2_MISC_PRBS_STATUS_LOCK (1L<<0) +#define BNX2_MISC_PRBS_STATUS_STKY (1L<<1) +#define BNX2_MISC_PRBS_STATUS_ERRORS (0x3fffL<<2) +#define BNX2_MISC_PRBS_STATUS_STATE (0xfL<<16) + +#define BNX2_MISC_SM_ASF_CONTROL 0x00000880 +#define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0) +#define BNX2_MISC_SM_ASF_CONTROL_TSC_EN (1L<<1) +#define BNX2_MISC_SM_ASF_CONTROL_WG_TO (1L<<2) +#define BNX2_MISC_SM_ASF_CONTROL_HB_TO (1L<<3) +#define BNX2_MISC_SM_ASF_CONTROL_PA_TO (1L<<4) +#define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5) +#define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6) +#define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7) +#define BNX2_MISC_SM_ASF_CONTROL_RES (0xfL<<8) +#define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12) +#define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13) +#define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14) +#define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15) +#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x3fL<<16) +#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x3fL<<24) +#define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30) +#define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31) + +#define BNX2_MISC_SMB_IN 0x00000884 +#define BNX2_MISC_SMB_IN_DAT_IN (0xffL<<0) +#define BNX2_MISC_SMB_IN_RDY (1L<<8) +#define BNX2_MISC_SMB_IN_DONE (1L<<9) +#define BNX2_MISC_SMB_IN_FIRSTBYTE (1L<<10) +#define BNX2_MISC_SMB_IN_STATUS (0x7L<<11) +#define BNX2_MISC_SMB_IN_STATUS_OK (0x0L<<11) +#define BNX2_MISC_SMB_IN_STATUS_PEC (0x1L<<11) +#define BNX2_MISC_SMB_IN_STATUS_OFLOW (0x2L<<11) +#define BNX2_MISC_SMB_IN_STATUS_STOP (0x3L<<11) +#define BNX2_MISC_SMB_IN_STATUS_TIMEOUT (0x4L<<11) + +#define BNX2_MISC_SMB_OUT 0x00000888 +#define BNX2_MISC_SMB_OUT_DAT_OUT (0xffL<<0) +#define BNX2_MISC_SMB_OUT_RDY (1L<<8) +#define BNX2_MISC_SMB_OUT_START (1L<<9) +#define BNX2_MISC_SMB_OUT_LAST (1L<<10) +#define BNX2_MISC_SMB_OUT_ACC_TYPE (1L<<11) +#define BNX2_MISC_SMB_OUT_ENB_PEC (1L<<12) +#define BNX2_MISC_SMB_OUT_GET_RX_LEN (1L<<13) +#define BNX2_MISC_SMB_OUT_SMB_READ_LEN (0x3fL<<14) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (0x6L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24) +#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25) +#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26) +#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN (1L<<27) +#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN (1L<<28) + +#define BNX2_MISC_SMB_WATCHDOG 0x0000088c +#define BNX2_MISC_SMB_WATCHDOG_WATCHDOG (0xffffL<<0) + +#define BNX2_MISC_SMB_HEARTBEAT 0x00000890 +#define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT (0xffffL<<0) + +#define BNX2_MISC_SMB_POLL_ASF 0x00000894 +#define BNX2_MISC_SMB_POLL_ASF_POLL_ASF (0xffffL<<0) + +#define BNX2_MISC_SMB_POLL_LEGACY 0x00000898 +#define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY (0xffffL<<0) + +#define BNX2_MISC_SMB_RETRAN 0x0000089c +#define BNX2_MISC_SMB_RETRAN_RETRAN (0xffL<<0) + +#define BNX2_MISC_SMB_TIMESTAMP 0x000008a0 +#define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP (0xffffffffL<<0) + +#define BNX2_MISC_PERR_ENA0 0x000008a4 +#define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC (1L<<0) +#define BNX2_MISC_PERR_ENA0_COM_MISC_REGF (1L<<1) +#define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD (1L<<2) +#define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC (1L<<3) +#define BNX2_MISC_PERR_ENA0_CP_MISC_REGF (1L<<4) +#define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD (1L<<5) +#define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM (1L<<6) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0 (1L<<7) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1 (1L<<8) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2 (1L<<9) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3 (1L<<10) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4 (1L<<11) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5 (1L<<12) +#define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL (1L<<13) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0 (1L<<14) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1 (1L<<15) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2 (1L<<16) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3 (1L<<17) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4 (1L<<18) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0 (1L<<19) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1 (1L<<20) +#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2 (1L<<21) +#define BNX2_MISC_PERR_ENA0_HC_MISC_DMA (1L<<22) +#define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF (1L<<23) +#define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD (1L<<24) +#define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX (1L<<25) +#define BNX2_MISC_PERR_ENA0_RBDC_MISC (1L<<26) +#define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB (1L<<27) +#define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR (1L<<28) +#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29) +#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30) +#define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31) + +#define BNX2_MISC_PERR_ENA1 0x000008a8 +#define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0) +#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM (1L<<1) +#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM (1L<<2) +#define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC (1L<<3) +#define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF (1L<<4) +#define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD (1L<<5) +#define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC (1L<<6) +#define BNX2_MISC_PERR_ENA1_TBDC_MISC (1L<<7) +#define BNX2_MISC_PERR_ENA1_TDMA_MISC (1L<<8) +#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0 (1L<<9) +#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1 (1L<<10) +#define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF (1L<<11) +#define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD (1L<<12) +#define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB (1L<<13) +#define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR (1L<<14) +#define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC (1L<<15) +#define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF (1L<<16) +#define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD (1L<<17) +#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX (1L<<18) +#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX (1L<<19) +#define BNX2_MISC_PERR_ENA1_UMP_MISC_RX (1L<<20) +#define BNX2_MISC_PERR_ENA1_UMP_MISC_TX (1L<<21) +#define BNX2_MISC_PERR_ENA1_RDMAQ_MISC (1L<<22) +#define BNX2_MISC_PERR_ENA1_CSQ_MISC (1L<<23) +#define BNX2_MISC_PERR_ENA1_CPQ_MISC (1L<<24) +#define BNX2_MISC_PERR_ENA1_MCPQ_MISC (1L<<25) +#define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC (1L<<26) +#define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC (1L<<27) +#define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC (1L<<28) +#define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29) +#define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30) +#define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31) + +#define BNX2_MISC_PERR_ENA2 0x000008ac +#define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0) +#define BNX2_MISC_PERR_ENA2_COMXQ_MISC (1L<<1) +#define BNX2_MISC_PERR_ENA2_COMTQ_MISC (1L<<2) +#define BNX2_MISC_PERR_ENA2_TSCHQ_MISC (1L<<3) +#define BNX2_MISC_PERR_ENA2_TBDRQ_MISC (1L<<4) +#define BNX2_MISC_PERR_ENA2_TXPQ_MISC (1L<<5) +#define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6) +#define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7) +#define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8) + +#define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0 +#define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0) +#define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12) + +#define BNX2_MISC_VREG_CONTROL 0x000008b4 +#define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0) +#define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4) + +#define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8 +#define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6) + +#define BNX2_MISC_UNUSED0 0x000008bc + + +/* + * nvm_reg definition + * offset: 0x6400 + */ +#define BNX2_NVM_COMMAND 0x00006400 +#define BNX2_NVM_COMMAND_RST (1L<<0) +#define BNX2_NVM_COMMAND_DONE (1L<<3) +#define BNX2_NVM_COMMAND_DOIT (1L<<4) +#define BNX2_NVM_COMMAND_WR (1L<<5) +#define BNX2_NVM_COMMAND_ERASE (1L<<6) +#define BNX2_NVM_COMMAND_FIRST (1L<<7) +#define BNX2_NVM_COMMAND_LAST (1L<<8) +#define BNX2_NVM_COMMAND_WREN (1L<<16) +#define BNX2_NVM_COMMAND_WRDI (1L<<17) +#define BNX2_NVM_COMMAND_EWSR (1L<<18) +#define BNX2_NVM_COMMAND_WRSR (1L<<19) + +#define BNX2_NVM_STATUS 0x00006404 +#define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0) +#define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4) +#define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8) + +#define BNX2_NVM_WRITE 0x00006408 +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG (0L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK (1L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA (2L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK (4L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0) + +#define BNX2_NVM_ADDR 0x0000640c +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG (0L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK (1L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA (2L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK (4L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0) + +#define BNX2_NVM_READ 0x00006410 +#define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG (0L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_EECLK (1L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA (2L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK (4L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0) + +#define BNX2_NVM_CFG1 0x00006414 +#define BNX2_NVM_CFG1_FLASH_MODE (1L<<0) +#define BNX2_NVM_CFG1_BUFFER_MODE (1L<<1) +#define BNX2_NVM_CFG1_PASS_MODE (1L<<2) +#define BNX2_NVM_CFG1_BITBANG_MODE (1L<<3) +#define BNX2_NVM_CFG1_STATUS_BIT (0x7L<<4) +#define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4) +#define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4) +#define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7) +#define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11) +#define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24) +#define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25) +#define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31) + +#define BNX2_NVM_CFG2 0x00006418 +#define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0) +#define BNX2_NVM_CFG2_DUMMY (0xffL<<8) +#define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16) + +#define BNX2_NVM_CFG3 0x0000641c +#define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0) +#define BNX2_NVM_CFG3_WRITE_CMD (0xffL<<8) +#define BNX2_NVM_CFG3_BUFFER_WRITE_CMD (0xffL<<16) +#define BNX2_NVM_CFG3_READ_CMD (0xffL<<24) + +#define BNX2_NVM_SW_ARB 0x00006420 +#define BNX2_NVM_SW_ARB_ARB_REQ_SET0 (1L<<0) +#define BNX2_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1) +#define BNX2_NVM_SW_ARB_ARB_REQ_SET2 (1L<<2) +#define BNX2_NVM_SW_ARB_ARB_REQ_SET3 (1L<<3) +#define BNX2_NVM_SW_ARB_ARB_REQ_CLR0 (1L<<4) +#define BNX2_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5) +#define BNX2_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6) +#define BNX2_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7) +#define BNX2_NVM_SW_ARB_ARB_ARB0 (1L<<8) +#define BNX2_NVM_SW_ARB_ARB_ARB1 (1L<<9) +#define BNX2_NVM_SW_ARB_ARB_ARB2 (1L<<10) +#define BNX2_NVM_SW_ARB_ARB_ARB3 (1L<<11) +#define BNX2_NVM_SW_ARB_REQ0 (1L<<12) +#define BNX2_NVM_SW_ARB_REQ1 (1L<<13) +#define BNX2_NVM_SW_ARB_REQ2 (1L<<14) +#define BNX2_NVM_SW_ARB_REQ3 (1L<<15) + +#define BNX2_NVM_ACCESS_ENABLE 0x00006424 +#define BNX2_NVM_ACCESS_ENABLE_EN (1L<<0) +#define BNX2_NVM_ACCESS_ENABLE_WR_EN (1L<<1) + +#define BNX2_NVM_WRITE1 0x00006428 +#define BNX2_NVM_WRITE1_WREN_CMD (0xffL<<0) +#define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8) +#define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16) + + + +/* + * dma_reg definition + * offset: 0xc00 + */ +#define BNX2_DMA_COMMAND 0x00000c00 +#define BNX2_DMA_COMMAND_ENABLE (1L<<0) + +#define BNX2_DMA_STATUS 0x00000c04 +#define BNX2_DMA_STATUS_PAR_ERROR_STATE (1L<<0) +#define BNX2_DMA_STATUS_READ_TRANSFERS_STAT (1L<<16) +#define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT (1L<<17) +#define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT (1L<<18) +#define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT (1L<<19) +#define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT (1L<<20) +#define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT (1L<<21) +#define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT (1L<<22) +#define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23) +#define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24) +#define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25) + +#define BNX2_DMA_CONFIG 0x00000c08 +#define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0) +#define BNX2_DMA_CONFIG_DATA_WORD_SWAP (1L<<1) +#define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP (1L<<4) +#define BNX2_DMA_CONFIG_CNTL_WORD_SWAP (1L<<5) +#define BNX2_DMA_CONFIG_ONE_DMA (1L<<6) +#define BNX2_DMA_CONFIG_CNTL_TWO_DMA (1L<<7) +#define BNX2_DMA_CONFIG_CNTL_FPGA_MODE (1L<<8) +#define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA (1L<<10) +#define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY (1L<<11) +#define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE (0xfL<<12) +#define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE (0xfL<<16) +#define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS (0x7L<<20) +#define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP (1L<<23) +#define BNX2_DMA_CONFIG_BIG_SIZE (0xfL<<24) +#define BNX2_DMA_CONFIG_BIG_SIZE_NONE (0x0L<<24) +#define BNX2_DMA_CONFIG_BIG_SIZE_64 (0x1L<<24) +#define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24) +#define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24) +#define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24) + +#define BNX2_DMA_BLACKOUT 0x00000c0c +#define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0) +#define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8) +#define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16) + +#define BNX2_DMA_RCHAN_STAT 0x00000c30 +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_0 (0x7L<<0) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_0 (1L<<3) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_1 (0x7L<<4) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_1 (1L<<7) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_2 (0x7L<<8) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_2 (1L<<11) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_3 (0x7L<<12) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_3 (1L<<15) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_4 (0x7L<<16) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_4 (1L<<19) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_5 (0x7L<<20) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_5 (1L<<23) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_6 (0x7L<<24) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_6 (1L<<27) +#define BNX2_DMA_RCHAN_STAT_COMP_CODE_7 (0x7L<<28) +#define BNX2_DMA_RCHAN_STAT_PAR_ERR_7 (1L<<31) + +#define BNX2_DMA_WCHAN_STAT 0x00000c34 +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_0 (0x7L<<0) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_0 (1L<<3) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_1 (0x7L<<4) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_1 (1L<<7) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_2 (0x7L<<8) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_2 (1L<<11) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_3 (0x7L<<12) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_3 (1L<<15) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_4 (0x7L<<16) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_4 (1L<<19) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_5 (0x7L<<20) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_5 (1L<<23) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_6 (0x7L<<24) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_6 (1L<<27) +#define BNX2_DMA_WCHAN_STAT_COMP_CODE_7 (0x7L<<28) +#define BNX2_DMA_WCHAN_STAT_PAR_ERR_7 (1L<<31) + +#define BNX2_DMA_RCHAN_ASSIGNMENT 0x00000c38 +#define BNX2_DMA_RCHAN_ASSIGNMENT_0 (0xfL<<0) +#define BNX2_DMA_RCHAN_ASSIGNMENT_1 (0xfL<<4) +#define BNX2_DMA_RCHAN_ASSIGNMENT_2 (0xfL<<8) +#define BNX2_DMA_RCHAN_ASSIGNMENT_3 (0xfL<<12) +#define BNX2_DMA_RCHAN_ASSIGNMENT_4 (0xfL<<16) +#define BNX2_DMA_RCHAN_ASSIGNMENT_5 (0xfL<<20) +#define BNX2_DMA_RCHAN_ASSIGNMENT_6 (0xfL<<24) +#define BNX2_DMA_RCHAN_ASSIGNMENT_7 (0xfL<<28) + +#define BNX2_DMA_WCHAN_ASSIGNMENT 0x00000c3c +#define BNX2_DMA_WCHAN_ASSIGNMENT_0 (0xfL<<0) +#define BNX2_DMA_WCHAN_ASSIGNMENT_1 (0xfL<<4) +#define BNX2_DMA_WCHAN_ASSIGNMENT_2 (0xfL<<8) +#define BNX2_DMA_WCHAN_ASSIGNMENT_3 (0xfL<<12) +#define BNX2_DMA_WCHAN_ASSIGNMENT_4 (0xfL<<16) +#define BNX2_DMA_WCHAN_ASSIGNMENT_5 (0xfL<<20) +#define BNX2_DMA_WCHAN_ASSIGNMENT_6 (0xfL<<24) +#define BNX2_DMA_WCHAN_ASSIGNMENT_7 (0xfL<<28) + +#define BNX2_DMA_RCHAN_STAT_00 0x00000c40 +#define BNX2_DMA_RCHAN_STAT_00_RCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0) + +#define BNX2_DMA_RCHAN_STAT_01 0x00000c44 +#define BNX2_DMA_RCHAN_STAT_01_RCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0) + +#define BNX2_DMA_RCHAN_STAT_02 0x00000c48 +#define BNX2_DMA_RCHAN_STAT_02_LENGTH (0xffffL<<0) +#define BNX2_DMA_RCHAN_STAT_02_WORD_SWAP (1L<<16) +#define BNX2_DMA_RCHAN_STAT_02_BYTE_SWAP (1L<<17) +#define BNX2_DMA_RCHAN_STAT_02_PRIORITY_LVL (1L<<18) + +#define BNX2_DMA_RCHAN_STAT_10 0x00000c4c +#define BNX2_DMA_RCHAN_STAT_11 0x00000c50 +#define BNX2_DMA_RCHAN_STAT_12 0x00000c54 +#define BNX2_DMA_RCHAN_STAT_20 0x00000c58 +#define BNX2_DMA_RCHAN_STAT_21 0x00000c5c +#define BNX2_DMA_RCHAN_STAT_22 0x00000c60 +#define BNX2_DMA_RCHAN_STAT_30 0x00000c64 +#define BNX2_DMA_RCHAN_STAT_31 0x00000c68 +#define BNX2_DMA_RCHAN_STAT_32 0x00000c6c +#define BNX2_DMA_RCHAN_STAT_40 0x00000c70 +#define BNX2_DMA_RCHAN_STAT_41 0x00000c74 +#define BNX2_DMA_RCHAN_STAT_42 0x00000c78 +#define BNX2_DMA_RCHAN_STAT_50 0x00000c7c +#define BNX2_DMA_RCHAN_STAT_51 0x00000c80 +#define BNX2_DMA_RCHAN_STAT_52 0x00000c84 +#define BNX2_DMA_RCHAN_STAT_60 0x00000c88 +#define BNX2_DMA_RCHAN_STAT_61 0x00000c8c +#define BNX2_DMA_RCHAN_STAT_62 0x00000c90 +#define BNX2_DMA_RCHAN_STAT_70 0x00000c94 +#define BNX2_DMA_RCHAN_STAT_71 0x00000c98 +#define BNX2_DMA_RCHAN_STAT_72 0x00000c9c +#define BNX2_DMA_WCHAN_STAT_00 0x00000ca0 +#define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0) + +#define BNX2_DMA_WCHAN_STAT_01 0x00000ca4 +#define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0) + +#define BNX2_DMA_WCHAN_STAT_02 0x00000ca8 +#define BNX2_DMA_WCHAN_STAT_02_LENGTH (0xffffL<<0) +#define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP (1L<<16) +#define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP (1L<<17) +#define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL (1L<<18) + +#define BNX2_DMA_WCHAN_STAT_10 0x00000cac +#define BNX2_DMA_WCHAN_STAT_11 0x00000cb0 +#define BNX2_DMA_WCHAN_STAT_12 0x00000cb4 +#define BNX2_DMA_WCHAN_STAT_20 0x00000cb8 +#define BNX2_DMA_WCHAN_STAT_21 0x00000cbc +#define BNX2_DMA_WCHAN_STAT_22 0x00000cc0 +#define BNX2_DMA_WCHAN_STAT_30 0x00000cc4 +#define BNX2_DMA_WCHAN_STAT_31 0x00000cc8 +#define BNX2_DMA_WCHAN_STAT_32 0x00000ccc +#define BNX2_DMA_WCHAN_STAT_40 0x00000cd0 +#define BNX2_DMA_WCHAN_STAT_41 0x00000cd4 +#define BNX2_DMA_WCHAN_STAT_42 0x00000cd8 +#define BNX2_DMA_WCHAN_STAT_50 0x00000cdc +#define BNX2_DMA_WCHAN_STAT_51 0x00000ce0 +#define BNX2_DMA_WCHAN_STAT_52 0x00000ce4 +#define BNX2_DMA_WCHAN_STAT_60 0x00000ce8 +#define BNX2_DMA_WCHAN_STAT_61 0x00000cec +#define BNX2_DMA_WCHAN_STAT_62 0x00000cf0 +#define BNX2_DMA_WCHAN_STAT_70 0x00000cf4 +#define BNX2_DMA_WCHAN_STAT_71 0x00000cf8 +#define BNX2_DMA_WCHAN_STAT_72 0x00000cfc +#define BNX2_DMA_ARB_STAT_00 0x00000d00 +#define BNX2_DMA_ARB_STAT_00_MASTER (0xffffL<<0) +#define BNX2_DMA_ARB_STAT_00_MASTER_ENC (0xffL<<16) +#define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR (0xffL<<24) + +#define BNX2_DMA_ARB_STAT_01 0x00000d04 +#define BNX2_DMA_ARB_STAT_01_LPR_RPTR (0xfL<<0) +#define BNX2_DMA_ARB_STAT_01_LPR_WPTR (0xfL<<4) +#define BNX2_DMA_ARB_STAT_01_LPB_RPTR (0xfL<<8) +#define BNX2_DMA_ARB_STAT_01_LPB_WPTR (0xfL<<12) +#define BNX2_DMA_ARB_STAT_01_HPR_RPTR (0xfL<<16) +#define BNX2_DMA_ARB_STAT_01_HPR_WPTR (0xfL<<20) +#define BNX2_DMA_ARB_STAT_01_HPB_RPTR (0xfL<<24) +#define BNX2_DMA_ARB_STAT_01_HPB_WPTR (0xfL<<28) + +#define BNX2_DMA_FUSE_CTRL0_CMD 0x00000f00 +#define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE (1L<<0) +#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE (1L<<1) +#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT (1L<<2) +#define BNX2_DMA_FUSE_CTRL0_CMD_LOAD (1L<<3) +#define BNX2_DMA_FUSE_CTRL0_CMD_SEL (0xfL<<8) + +#define BNX2_DMA_FUSE_CTRL0_DATA 0x00000f04 +#define BNX2_DMA_FUSE_CTRL1_CMD 0x00000f08 +#define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE (1L<<0) +#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE (1L<<1) +#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT (1L<<2) +#define BNX2_DMA_FUSE_CTRL1_CMD_LOAD (1L<<3) +#define BNX2_DMA_FUSE_CTRL1_CMD_SEL (0xfL<<8) + +#define BNX2_DMA_FUSE_CTRL1_DATA 0x00000f0c +#define BNX2_DMA_FUSE_CTRL2_CMD 0x00000f10 +#define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE (1L<<0) +#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE (1L<<1) +#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT (1L<<2) +#define BNX2_DMA_FUSE_CTRL2_CMD_LOAD (1L<<3) +#define BNX2_DMA_FUSE_CTRL2_CMD_SEL (0xfL<<8) + +#define BNX2_DMA_FUSE_CTRL2_DATA 0x00000f14 + + +/* + * context_reg definition + * offset: 0x1000 + */ +#define BNX2_CTX_COMMAND 0x00001000 +#define BNX2_CTX_COMMAND_ENABLED (1L<<0) + +#define BNX2_CTX_STATUS 0x00001004 +#define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0) +#define BNX2_CTX_STATUS_READ_STAT (1L<<16) +#define BNX2_CTX_STATUS_WRITE_STAT (1L<<17) +#define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18) +#define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19) + +#define BNX2_CTX_VIRT_ADDR 0x00001008 +#define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6) + +#define BNX2_CTX_PAGE_TBL 0x0000100c +#define BNX2_CTX_PAGE_TBL_PAGE_TBL (0x3fffL<<6) + +#define BNX2_CTX_DATA_ADR 0x00001010 +#define BNX2_CTX_DATA_ADR_DATA_ADR (0x7ffffL<<2) + +#define BNX2_CTX_DATA 0x00001014 +#define BNX2_CTX_LOCK 0x00001018 +#define BNX2_CTX_LOCK_TYPE (0x7L<<0) +#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0) +#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0) +#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0) +#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0) +#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0) +#define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7) +#define BNX2_CTX_LOCK_GRANTED (1L<<26) +#define BNX2_CTX_LOCK_MODE (0x7L<<27) +#define BNX2_CTX_LOCK_MODE_UNLOCK (0x0L<<27) +#define BNX2_CTX_LOCK_MODE_IMMEDIATE (0x1L<<27) +#define BNX2_CTX_LOCK_MODE_SURE (0x2L<<27) +#define BNX2_CTX_LOCK_STATUS (1L<<30) +#define BNX2_CTX_LOCK_REQ (1L<<31) + +#define BNX2_CTX_ACCESS_STATUS 0x00001040 +#define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0) +#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10) +#define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12) +#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14) +#define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17) + +#define BNX2_CTX_DBG_LOCK_STATUS 0x00001044 +#define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0) +#define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22) + +#define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080 +#define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0) +#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14) +#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16) + +#define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084 +#define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088 +#define BNX2_CTX_CHNL_LOCK_STATUS_3 0x0000108c +#define BNX2_CTX_CHNL_LOCK_STATUS_4 0x00001090 +#define BNX2_CTX_CHNL_LOCK_STATUS_5 0x00001094 +#define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098 +#define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c +#define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0 + + +/* + * emac_reg definition + * offset: 0x1400 + */ +#define BNX2_EMAC_MODE 0x00001400 +#define BNX2_EMAC_MODE_RESET (1L<<0) +#define BNX2_EMAC_MODE_HALF_DUPLEX (1L<<1) +#define BNX2_EMAC_MODE_PORT (0x3L<<2) +#define BNX2_EMAC_MODE_PORT_NONE (0L<<2) +#define BNX2_EMAC_MODE_PORT_MII (1L<<2) +#define BNX2_EMAC_MODE_PORT_GMII (2L<<2) +#define BNX2_EMAC_MODE_PORT_UNDEF (3L<<2) +#define BNX2_EMAC_MODE_MAC_LOOP (1L<<4) +#define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7) +#define BNX2_EMAC_MODE_TX_BURST (1L<<8) +#define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9) +#define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10) +#define BNX2_EMAC_MODE_FORCE_LINK (1L<<11) +#define BNX2_EMAC_MODE_MPKT (1L<<18) +#define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19) +#define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20) + +#define BNX2_EMAC_STATUS 0x00001404 +#define BNX2_EMAC_STATUS_LINK (1L<<11) +#define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12) +#define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22) +#define BNX2_EMAC_STATUS_MI_INT (1L<<23) +#define BNX2_EMAC_STATUS_AP_ERROR (1L<<24) +#define BNX2_EMAC_STATUS_PARITY_ERROR_STATE (1L<<31) + +#define BNX2_EMAC_ATTENTION_ENA 0x00001408 +#define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11) +#define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22) +#define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23) +#define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24) + +#define BNX2_EMAC_LED 0x0000140c +#define BNX2_EMAC_LED_OVERRIDE (1L<<0) +#define BNX2_EMAC_LED_1000MB_OVERRIDE (1L<<1) +#define BNX2_EMAC_LED_100MB_OVERRIDE (1L<<2) +#define BNX2_EMAC_LED_10MB_OVERRIDE (1L<<3) +#define BNX2_EMAC_LED_TRAFFIC_OVERRIDE (1L<<4) +#define BNX2_EMAC_LED_BLNK_TRAFFIC (1L<<5) +#define BNX2_EMAC_LED_TRAFFIC (1L<<6) +#define BNX2_EMAC_LED_1000MB (1L<<7) +#define BNX2_EMAC_LED_100MB (1L<<8) +#define BNX2_EMAC_LED_10MB (1L<<9) +#define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10) +#define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19) +#define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31) + +#define BNX2_EMAC_MAC_MATCH0 0x00001410 +#define BNX2_EMAC_MAC_MATCH1 0x00001414 +#define BNX2_EMAC_MAC_MATCH2 0x00001418 +#define BNX2_EMAC_MAC_MATCH3 0x0000141c +#define BNX2_EMAC_MAC_MATCH4 0x00001420 +#define BNX2_EMAC_MAC_MATCH5 0x00001424 +#define BNX2_EMAC_MAC_MATCH6 0x00001428 +#define BNX2_EMAC_MAC_MATCH7 0x0000142c +#define BNX2_EMAC_MAC_MATCH8 0x00001430 +#define BNX2_EMAC_MAC_MATCH9 0x00001434 +#define BNX2_EMAC_MAC_MATCH10 0x00001438 +#define BNX2_EMAC_MAC_MATCH11 0x0000143c +#define BNX2_EMAC_MAC_MATCH12 0x00001440 +#define BNX2_EMAC_MAC_MATCH13 0x00001444 +#define BNX2_EMAC_MAC_MATCH14 0x00001448 +#define BNX2_EMAC_MAC_MATCH15 0x0000144c +#define BNX2_EMAC_MAC_MATCH16 0x00001450 +#define BNX2_EMAC_MAC_MATCH17 0x00001454 +#define BNX2_EMAC_MAC_MATCH18 0x00001458 +#define BNX2_EMAC_MAC_MATCH19 0x0000145c +#define BNX2_EMAC_MAC_MATCH20 0x00001460 +#define BNX2_EMAC_MAC_MATCH21 0x00001464 +#define BNX2_EMAC_MAC_MATCH22 0x00001468 +#define BNX2_EMAC_MAC_MATCH23 0x0000146c +#define BNX2_EMAC_MAC_MATCH24 0x00001470 +#define BNX2_EMAC_MAC_MATCH25 0x00001474 +#define BNX2_EMAC_MAC_MATCH26 0x00001478 +#define BNX2_EMAC_MAC_MATCH27 0x0000147c +#define BNX2_EMAC_MAC_MATCH28 0x00001480 +#define BNX2_EMAC_MAC_MATCH29 0x00001484 +#define BNX2_EMAC_MAC_MATCH30 0x00001488 +#define BNX2_EMAC_MAC_MATCH31 0x0000148c +#define BNX2_EMAC_BACKOFF_SEED 0x00001498 +#define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED (0x3ffL<<0) + +#define BNX2_EMAC_RX_MTU_SIZE 0x0000149c +#define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE (0xffffL<<0) +#define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31) + +#define BNX2_EMAC_SERDES_CNTL 0x000014a4 +#define BNX2_EMAC_SERDES_CNTL_RXR (0x7L<<0) +#define BNX2_EMAC_SERDES_CNTL_RXG (0x3L<<3) +#define BNX2_EMAC_SERDES_CNTL_RXCKSEL (1L<<6) +#define BNX2_EMAC_SERDES_CNTL_TXBIAS (0x7L<<7) +#define BNX2_EMAC_SERDES_CNTL_BGMAX (1L<<10) +#define BNX2_EMAC_SERDES_CNTL_BGMIN (1L<<11) +#define BNX2_EMAC_SERDES_CNTL_TXMODE (1L<<12) +#define BNX2_EMAC_SERDES_CNTL_TXEDGE (1L<<13) +#define BNX2_EMAC_SERDES_CNTL_SERDES_MODE (1L<<14) +#define BNX2_EMAC_SERDES_CNTL_PLLTEST (1L<<15) +#define BNX2_EMAC_SERDES_CNTL_CDET_EN (1L<<16) +#define BNX2_EMAC_SERDES_CNTL_TBI_LBK (1L<<17) +#define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK (1L<<18) +#define BNX2_EMAC_SERDES_CNTL_REV_PHASE (1L<<19) +#define BNX2_EMAC_SERDES_CNTL_REGCTL12 (0x3L<<20) +#define BNX2_EMAC_SERDES_CNTL_REGCTL25 (0x3L<<22) + +#define BNX2_EMAC_SERDES_STATUS 0x000014a8 +#define BNX2_EMAC_SERDES_STATUS_RX_STAT (0xffL<<0) +#define BNX2_EMAC_SERDES_STATUS_COMMA_DET (1L<<8) + +#define BNX2_EMAC_MDIO_COMM 0x000014ac +#define BNX2_EMAC_MDIO_COMM_DATA (0xffffL<<0) +#define BNX2_EMAC_MDIO_COMM_REG_ADDR (0x1fL<<16) +#define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21) +#define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26) +#define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28) +#define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29) +#define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30) + +#define BNX2_EMAC_MDIO_STATUS 0x000014b0 +#define BNX2_EMAC_MDIO_STATUS_LINK (1L<<0) +#define BNX2_EMAC_MDIO_STATUS_10MB (1L<<1) + +#define BNX2_EMAC_MDIO_MODE 0x000014b4 +#define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE (1L<<1) +#define BNX2_EMAC_MDIO_MODE_AUTO_POLL (1L<<4) +#define BNX2_EMAC_MDIO_MODE_BIT_BANG (1L<<8) +#define BNX2_EMAC_MDIO_MODE_MDIO (1L<<9) +#define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10) +#define BNX2_EMAC_MDIO_MODE_MDC (1L<<11) +#define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12) +#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16) + +#define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8 +#define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0) + +#define BNX2_EMAC_TX_MODE 0x000014bc +#define BNX2_EMAC_TX_MODE_RESET (1L<<0) +#define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) +#define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4) +#define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5) +#define BNX2_EMAC_TX_MODE_LONG_PAUSE (1L<<6) +#define BNX2_EMAC_TX_MODE_LINK_AWARE (1L<<7) + +#define BNX2_EMAC_TX_STATUS 0x000014c0 +#define BNX2_EMAC_TX_STATUS_XOFFED (1L<<0) +#define BNX2_EMAC_TX_STATUS_XOFF_SENT (1L<<1) +#define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2) +#define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3) +#define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4) + +#define BNX2_EMAC_TX_LENGTHS 0x000014c4 +#define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0) +#define BNX2_EMAC_TX_LENGTHS_IPG (0xfL<<8) +#define BNX2_EMAC_TX_LENGTHS_IPG_CRS (0x3L<<12) + +#define BNX2_EMAC_RX_MODE 0x000014c8 +#define BNX2_EMAC_RX_MODE_RESET (1L<<0) +#define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2) +#define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3) +#define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4) +#define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5) +#define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6) +#define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7) +#define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8) +#define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9) +#define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10) +#define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11) +#define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12) + +#define BNX2_EMAC_RX_STATUS 0x000014cc +#define BNX2_EMAC_RX_STATUS_FFED (1L<<0) +#define BNX2_EMAC_RX_STATUS_FF_RECEIVED (1L<<1) +#define BNX2_EMAC_RX_STATUS_N_RECEIVED (1L<<2) + +#define BNX2_EMAC_MULTICAST_HASH0 0x000014d0 +#define BNX2_EMAC_MULTICAST_HASH1 0x000014d4 +#define BNX2_EMAC_MULTICAST_HASH2 0x000014d8 +#define BNX2_EMAC_MULTICAST_HASH3 0x000014dc +#define BNX2_EMAC_MULTICAST_HASH4 0x000014e0 +#define BNX2_EMAC_MULTICAST_HASH5 0x000014e4 +#define BNX2_EMAC_MULTICAST_HASH6 0x000014e8 +#define BNX2_EMAC_MULTICAST_HASH7 0x000014ec +#define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500 +#define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504 +#define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508 +#define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS 0x0000150c +#define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS 0x00001510 +#define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS 0x00001514 +#define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS 0x00001518 +#define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS 0x0000151c +#define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS 0x00001520 +#define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED 0x00001524 +#define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED 0x00001528 +#define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED 0x0000152c +#define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED 0x00001530 +#define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG 0x00001534 +#define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS 0x00001538 +#define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS 0x0000153c +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS 0x00001540 +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x00001544 +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001548 +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550 +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554 +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001558 +#define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c +#define BNX2_EMAC_RXMAC_DEBUG1 0x00001560 +#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0) +#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE (1L<<1) +#define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC (1L<<2) +#define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR (1L<<3) +#define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR (1L<<4) +#define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA (1L<<5) +#define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START (1L<<6) +#define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT (0xffffL<<7) +#define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME (0xffL<<23) + +#define BNX2_EMAC_RXMAC_DEBUG2 0x00001564 +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE (0x7L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE (0x0L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD (0x1L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA (0x2L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP (0x3L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT (0x4L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP (0x5L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP (0x6L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC (0x7L<<0) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE (0xfL<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE (0x0L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0 (0x1L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1 (0x2L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2 (0x3L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3 (0x4L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT (0x5L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT (0x6L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS (0x7L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST (0x8L<<3) +#define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN (0xffL<<7) +#define BNX2_EMAC_RXMAC_DEBUG2_FALSEC (1L<<15) +#define BNX2_EMAC_RXMAC_DEBUG2_TAGGED (1L<<16) +#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE (1L<<18) +#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE (0L<<18) +#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED (1L<<18) +#define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER (0xfL<<19) +#define BNX2_EMAC_RXMAC_DEBUG2_QUANTA (0x1fL<<23) + +#define BNX2_EMAC_RXMAC_DEBUG3 0x00001568 +#define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR (0xffffL<<0) +#define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR (0xffffL<<16) + +#define BNX2_EMAC_RXMAC_DEBUG4 0x0000156c +#define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD (0xffffL<<0) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE (0x3fL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE (0x0L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3 (0xaL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1 (0xeL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2 (0xfL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK (0x10L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC (0x11L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2 (0x12L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3 (0x13L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1 (0x14L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2 (0x15L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3 (0x16L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE (0x17L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC (0x18L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE (0x19L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD (0x1aL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC (0x1bL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH (0x1cL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF (0x1dL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON (0x1eL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED (0x1fL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED (0x20L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE (0x21L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL (0x22L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1 (0x23L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2 (0x24L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3 (0x25L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE (0x26L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE (0x27L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL (0x28L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE (0x29L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP (0x2aL<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT (1L<<22) +#define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23) +#define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24) +#define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25) +#define BNX2_EMAC_RXMAC_DEBUG4_sfd_FOUND (1L<<26) +#define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27) +#define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28) + +#define BNX2_EMAC_RXMAC_DEBUG5 0x00001570 +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM (0x7L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE (0L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF (1L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT (2L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC (3L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE (4L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL (5L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT (6L<<0) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1 (0x7L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW (0x0L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT (0x1L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF (0x2L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF (0x3L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF (0x4L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF (0x6L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF (0x7L<<4) +#define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED (1L<<7) +#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0 (0x7L<<8) +#define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL (1L<<11) +#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE (1L<<12) +#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA (1L<<13) +#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT (1L<<14) +#define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT (1L<<15) +#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE (0x3L<<16) +#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19) +#define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20) + +#define BNX2_EMAC_RX_STAT_AC0 0x00001580 +#define BNX2_EMAC_RX_STAT_AC1 0x00001584 +#define BNX2_EMAC_RX_STAT_AC2 0x00001588 +#define BNX2_EMAC_RX_STAT_AC3 0x0000158c +#define BNX2_EMAC_RX_STAT_AC4 0x00001590 +#define BNX2_EMAC_RX_STAT_AC5 0x00001594 +#define BNX2_EMAC_RX_STAT_AC6 0x00001598 +#define BNX2_EMAC_RX_STAT_AC7 0x0000159c +#define BNX2_EMAC_RX_STAT_AC8 0x000015a0 +#define BNX2_EMAC_RX_STAT_AC9 0x000015a4 +#define BNX2_EMAC_RX_STAT_AC10 0x000015a8 +#define BNX2_EMAC_RX_STAT_AC11 0x000015ac +#define BNX2_EMAC_RX_STAT_AC12 0x000015b0 +#define BNX2_EMAC_RX_STAT_AC13 0x000015b4 +#define BNX2_EMAC_RX_STAT_AC14 0x000015b8 +#define BNX2_EMAC_RX_STAT_AC15 0x000015bc +#define BNX2_EMAC_RX_STAT_AC16 0x000015c0 +#define BNX2_EMAC_RX_STAT_AC17 0x000015c4 +#define BNX2_EMAC_RX_STAT_AC18 0x000015c8 +#define BNX2_EMAC_RX_STAT_AC19 0x000015cc +#define BNX2_EMAC_RX_STAT_AC20 0x000015d0 +#define BNX2_EMAC_RX_STAT_AC21 0x000015d4 +#define BNX2_EMAC_RX_STAT_AC22 0x000015d8 +#define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc +#define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600 +#define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604 +#define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608 +#define BNX2_EMAC_TX_STAT_OUTXONSENT 0x0000160c +#define BNX2_EMAC_TX_STAT_OUTXOFFSENT 0x00001610 +#define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE 0x00001614 +#define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES 0x00001618 +#define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES 0x0000161c +#define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS 0x00001620 +#define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS 0x00001624 +#define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS 0x00001628 +#define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS 0x0000162c +#define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS 0x00001630 +#define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS 0x00001634 +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS 0x00001638 +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x0000163c +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001640 +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644 +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648 +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001650 +#define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654 +#define BNX2_EMAC_TXMAC_DEBUG0 0x00001658 +#define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE (0xfL<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE (0x0L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0 (0x1L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0 (0x4L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1 (0x5L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2 (0x6L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3 (0x7L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0 (0x8L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1 (0x9L<<0) +#define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE (1L<<4) +#define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC (1L<<5) +#define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER (0xfL<<6) +#define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE (1L<<10) +#define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION (1L<<11) +#define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER (1L<<12) +#define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED (1L<<13) +#define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE (1L<<14) +#define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME (0xfL<<15) +#define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME (0xffL<<19) + +#define BNX2_EMAC_TXMAC_DEBUG2 0x00001660 +#define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF (0x3ffL<<0) +#define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT (0xffffL<<10) +#define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT (0x1fL<<26) +#define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT (1L<<31) + +#define BNX2_EMAC_TXMAC_DEBUG3 0x00001664 +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE (0xfL<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE (0x0L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1 (0x1L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2 (0x2L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD (0x3L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA (0x4L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1 (0x5L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2 (0x6L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT (0x7L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB (0x8L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG (0x9L<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM (0xaL<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM (0xbL<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM (0xcL<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT (0xdL<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF (0xeL<<0) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE (0x7L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE (0x0L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT (0x1L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI (0x2L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC (0x3L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2 (0x4L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3 (0x5L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC (0x6L<<4) +#define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE (1L<<7) +#define BNX2_EMAC_TXMAC_DEBUG3_XOFF (1L<<8) +#define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER (0xfL<<9) +#define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER (0x1fL<<13) + +#define BNX2_EMAC_TXMAC_DEBUG4 0x00001668 +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER (0xffffL<<0) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE (0xfL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20) +#define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21) +#define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22) +#define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER (1L<<23) +#define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND (1L<<24) +#define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING (1L<<25) +#define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC (1L<<26) +#define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING (1L<<27) +#define BNX2_EMAC_TXMAC_DEBUG4_COL_IN (1L<<28) +#define BNX2_EMAC_TXMAC_DEBUG4_BURSTING (1L<<29) +#define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE (1L<<30) +#define BNX2_EMAC_TXMAC_DEBUG4_GO (1L<<31) + +#define BNX2_EMAC_TX_STAT_AC0 0x00001680 +#define BNX2_EMAC_TX_STAT_AC1 0x00001684 +#define BNX2_EMAC_TX_STAT_AC2 0x00001688 +#define BNX2_EMAC_TX_STAT_AC3 0x0000168c +#define BNX2_EMAC_TX_STAT_AC4 0x00001690 +#define BNX2_EMAC_TX_STAT_AC5 0x00001694 +#define BNX2_EMAC_TX_STAT_AC6 0x00001698 +#define BNX2_EMAC_TX_STAT_AC7 0x0000169c +#define BNX2_EMAC_TX_STAT_AC8 0x000016a0 +#define BNX2_EMAC_TX_STAT_AC9 0x000016a4 +#define BNX2_EMAC_TX_STAT_AC10 0x000016a8 +#define BNX2_EMAC_TX_STAT_AC11 0x000016ac +#define BNX2_EMAC_TX_STAT_AC12 0x000016b0 +#define BNX2_EMAC_TX_STAT_AC13 0x000016b4 +#define BNX2_EMAC_TX_STAT_AC14 0x000016b8 +#define BNX2_EMAC_TX_STAT_AC15 0x000016bc +#define BNX2_EMAC_TX_STAT_AC16 0x000016c0 +#define BNX2_EMAC_TX_STAT_AC17 0x000016c4 +#define BNX2_EMAC_TX_STAT_AC18 0x000016c8 +#define BNX2_EMAC_TX_STAT_AC19 0x000016cc +#define BNX2_EMAC_TX_STAT_AC20 0x000016d0 +#define BNX2_EMAC_TX_STAT_AC21 0x000016d4 +#define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8 + + +/* + * rpm_reg definition + * offset: 0x1800 + */ +#define BNX2_RPM_COMMAND 0x00001800 +#define BNX2_RPM_COMMAND_ENABLED (1L<<0) +#define BNX2_RPM_COMMAND_OVERRUN_ABORT (1L<<4) + +#define BNX2_RPM_STATUS 0x00001804 +#define BNX2_RPM_STATUS_MBUF_WAIT (1L<<0) +#define BNX2_RPM_STATUS_FREE_WAIT (1L<<1) + +#define BNX2_RPM_CONFIG 0x00001808 +#define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM (1L<<0) +#define BNX2_RPM_CONFIG_ACPI_ENA (1L<<1) +#define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2) +#define BNX2_RPM_CONFIG_MP_KEEP (1L<<3) +#define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4) +#define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31) + +#define BNX2_RPM_VLAN_MATCH0 0x00001810 +#define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0) + +#define BNX2_RPM_VLAN_MATCH1 0x00001814 +#define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE (0xfffL<<0) + +#define BNX2_RPM_VLAN_MATCH2 0x00001818 +#define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE (0xfffL<<0) + +#define BNX2_RPM_VLAN_MATCH3 0x0000181c +#define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE (0xfffL<<0) + +#define BNX2_RPM_SORT_USER0 0x00001820 +#define BNX2_RPM_SORT_USER0_PM_EN (0xffffL<<0) +#define BNX2_RPM_SORT_USER0_BC_EN (1L<<16) +#define BNX2_RPM_SORT_USER0_MC_EN (1L<<17) +#define BNX2_RPM_SORT_USER0_MC_HSH_EN (1L<<18) +#define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19) +#define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20) +#define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24) +#define BNX2_RPM_SORT_USER0_ENA (1L<<31) + +#define BNX2_RPM_SORT_USER1 0x00001824 +#define BNX2_RPM_SORT_USER1_PM_EN (0xffffL<<0) +#define BNX2_RPM_SORT_USER1_BC_EN (1L<<16) +#define BNX2_RPM_SORT_USER1_MC_EN (1L<<17) +#define BNX2_RPM_SORT_USER1_MC_HSH_EN (1L<<18) +#define BNX2_RPM_SORT_USER1_PROM_EN (1L<<19) +#define BNX2_RPM_SORT_USER1_VLAN_EN (0xfL<<20) +#define BNX2_RPM_SORT_USER1_PROM_VLAN (1L<<24) +#define BNX2_RPM_SORT_USER1_ENA (1L<<31) + +#define BNX2_RPM_SORT_USER2 0x00001828 +#define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0) +#define BNX2_RPM_SORT_USER2_BC_EN (1L<<16) +#define BNX2_RPM_SORT_USER2_MC_EN (1L<<17) +#define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18) +#define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19) +#define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20) +#define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24) +#define BNX2_RPM_SORT_USER2_ENA (1L<<31) + +#define BNX2_RPM_SORT_USER3 0x0000182c +#define BNX2_RPM_SORT_USER3_PM_EN (0xffffL<<0) +#define BNX2_RPM_SORT_USER3_BC_EN (1L<<16) +#define BNX2_RPM_SORT_USER3_MC_EN (1L<<17) +#define BNX2_RPM_SORT_USER3_MC_HSH_EN (1L<<18) +#define BNX2_RPM_SORT_USER3_PROM_EN (1L<<19) +#define BNX2_RPM_SORT_USER3_VLAN_EN (0xfL<<20) +#define BNX2_RPM_SORT_USER3_PROM_VLAN (1L<<24) +#define BNX2_RPM_SORT_USER3_ENA (1L<<31) + +#define BNX2_RPM_STAT_L2_FILTER_DISCARDS 0x00001840 +#define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS 0x00001844 +#define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848 +#define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c +#define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850 +#define BNX2_RPM_STAT_AC0 0x00001880 +#define BNX2_RPM_STAT_AC1 0x00001884 +#define BNX2_RPM_STAT_AC2 0x00001888 +#define BNX2_RPM_STAT_AC3 0x0000188c +#define BNX2_RPM_STAT_AC4 0x00001890 +#define BNX2_RPM_RC_CNTL_0 0x00001900 +#define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0) +#define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8) +#define BNX2_RPM_RC_CNTL_0_PRIORITY (1L<<11) +#define BNX2_RPM_RC_CNTL_0_P4 (1L<<12) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE (0x7L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START (0L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP (1L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13) +#define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16) +#define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16) +#define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16) +#define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16) +#define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16) +#define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19) +#define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20) +#define BNX2_RPM_RC_CNTL_0_MAP (1L<<24) +#define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25) +#define BNX2_RPM_RC_CNTL_0_MASK (1L<<26) +#define BNX2_RPM_RC_CNTL_0_P1 (1L<<27) +#define BNX2_RPM_RC_CNTL_0_P2 (1L<<28) +#define BNX2_RPM_RC_CNTL_0_P3 (1L<<29) +#define BNX2_RPM_RC_CNTL_0_NBIT (1L<<30) + +#define BNX2_RPM_RC_VALUE_MASK_0 0x00001904 +#define BNX2_RPM_RC_VALUE_MASK_0_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_0_MASK (0xffffL<<16) + +#define BNX2_RPM_RC_CNTL_1 0x00001908 +#define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c +#define BNX2_RPM_RC_CNTL_2 0x00001910 +#define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_2 0x00001914 +#define BNX2_RPM_RC_CNTL_3 0x00001918 +#define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c +#define BNX2_RPM_RC_CNTL_4 0x00001920 +#define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_4 0x00001924 +#define BNX2_RPM_RC_CNTL_5 0x00001928 +#define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c +#define BNX2_RPM_RC_CNTL_6 0x00001930 +#define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_6 0x00001934 +#define BNX2_RPM_RC_CNTL_7 0x00001938 +#define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c +#define BNX2_RPM_RC_CNTL_8 0x00001940 +#define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_8 0x00001944 +#define BNX2_RPM_RC_CNTL_9 0x00001948 +#define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c +#define BNX2_RPM_RC_CNTL_10 0x00001950 +#define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_10 0x00001954 +#define BNX2_RPM_RC_CNTL_11 0x00001958 +#define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c +#define BNX2_RPM_RC_CNTL_12 0x00001960 +#define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_12 0x00001964 +#define BNX2_RPM_RC_CNTL_13 0x00001968 +#define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c +#define BNX2_RPM_RC_CNTL_14 0x00001970 +#define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_14 0x00001974 +#define BNX2_RPM_RC_CNTL_15 0x00001978 +#define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0) +#define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19) + +#define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c +#define BNX2_RPM_RC_CONFIG 0x00001980 +#define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0) +#define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24) + +#define BNX2_RPM_DEBUG0 0x00001984 +#define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0) +#define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD (1L<<16) +#define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD (1L<<17) +#define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD (1L<<18) +#define BNX2_RPM_DEBUG0_T_IP_OFST_VLD (1L<<19) +#define BNX2_RPM_DEBUG0_IP_MORE_FRGMT (1L<<20) +#define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR (1L<<21) +#define BNX2_RPM_DEBUG0_LLC_SNAP (1L<<22) +#define BNX2_RPM_DEBUG0_FM_STARTED (1L<<23) +#define BNX2_RPM_DEBUG0_DONE (1L<<24) +#define BNX2_RPM_DEBUG0_WAIT_4_DONE (1L<<25) +#define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM (1L<<26) +#define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM (1L<<27) +#define BNX2_RPM_DEBUG0_IGNORE_VLAN (1L<<28) +#define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE (1L<<31) + +#define BNX2_RPM_DEBUG1 0x00001988 +#define BNX2_RPM_DEBUG1_FSM_CUR_ST (0xffffL<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE (0L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL (1L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC (2L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP (4L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP (8L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START (16L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP (32L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP (64L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP (128L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH (256L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP (512L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD (1024L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA (2048L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY (0x2000L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT (0x4000L<<0) +#define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT (0x8000L<<0) +#define BNX2_RPM_DEBUG1_HDR_BCNT (0x7ffL<<16) +#define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D (1L<<28) +#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2 (1L<<29) +#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1 (1L<<30) +#define BNX2_RPM_DEBUG1_EOF_0XTRA_WD (1L<<31) + +#define BNX2_RPM_DEBUG2 0x0000198c +#define BNX2_RPM_DEBUG2_CMD_HIT_VEC (0xffffL<<0) +#define BNX2_RPM_DEBUG2_IP_BCNT (0xffL<<16) +#define BNX2_RPM_DEBUG2_THIS_CMD_M4 (1L<<24) +#define BNX2_RPM_DEBUG2_THIS_CMD_M3 (1L<<25) +#define BNX2_RPM_DEBUG2_THIS_CMD_M2 (1L<<26) +#define BNX2_RPM_DEBUG2_THIS_CMD_M1 (1L<<27) +#define BNX2_RPM_DEBUG2_IPIPE_EMPTY (1L<<28) +#define BNX2_RPM_DEBUG2_FM_DISCARD (1L<<29) +#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2 (1L<<30) +#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1 (1L<<31) + +#define BNX2_RPM_DEBUG3 0x00001990 +#define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR (0x1ffL<<0) +#define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT (1L<<9) +#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT (1L<<10) +#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT (1L<<11) +#define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ (1L<<12) +#define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ (1L<<13) +#define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL (1L<<14) +#define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP (1L<<15) +#define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT (0xfL<<16) +#define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL (1L<<21) +#define BNX2_RPM_DEBUG3_DROP_NXT_VLD (1L<<22) +#define BNX2_RPM_DEBUG3_DROP_NXT (1L<<23) +#define BNX2_RPM_DEBUG3_FTQ_FSM (0x3L<<24) +#define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE (0x0L<<24) +#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK (0x1L<<24) +#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE (0x2L<<24) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM (0x3L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF (0x0L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF (0x1L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA (0x2L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA (0x3L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF (0x4L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK (0x5L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD (0x6L<<26) +#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE (0x7L<<26) +#define BNX2_RPM_DEBUG3_MBFREE_FSM (1L<<29) +#define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE (0L<<29) +#define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK (1L<<29) +#define BNX2_RPM_DEBUG3_MBALLOC_FSM (1L<<30) +#define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF (0x0L<<30) +#define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF (0x1L<<30) +#define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR (1L<<31) + +#define BNX2_RPM_DEBUG4 0x00001994 +#define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER (0x1ffffffL<<0) +#define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE (0x7L<<25) +#define BNX2_RPM_DEBUG4_MBWRITE_FSM (0x7L<<28) +#define BNX2_RPM_DEBUG4_DFIFO_EMPTY (1L<<31) + +#define BNX2_RPM_DEBUG5 0x00001998 +#define BNX2_RPM_DEBUG5_RDROP_WPTR (0x1fL<<0) +#define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR (0x1fL<<5) +#define BNX2_RPM_DEBUG5_RDROP_MC_RPTR (0x1fL<<10) +#define BNX2_RPM_DEBUG5_RDROP_RC_RPTR (0x1fL<<15) +#define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY (1L<<20) +#define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY (1L<<21) +#define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR (1L<<22) +#define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT (1L<<23) +#define BNX2_RPM_DEBUG5_HOLDREG_DISCARD (1L<<24) +#define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL (1L<<25) +#define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY (1L<<26) +#define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY (1L<<27) +#define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY (1L<<28) +#define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY (1L<<29) +#define BNX2_RPM_DEBUG5_HOLDREG_FULL_T (1L<<30) +#define BNX2_RPM_DEBUG5_HOLDREG_RD (1L<<31) + +#define BNX2_RPM_DEBUG6 0x0000199c +#define BNX2_RPM_DEBUG6_ACPI_VEC (0xffffL<<0) +#define BNX2_RPM_DEBUG6_VEC (0xffffL<<16) + +#define BNX2_RPM_DEBUG7 0x000019a0 +#define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC (0xffffffffL<<0) + +#define BNX2_RPM_DEBUG8 0x000019a4 +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM (0xfL<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE (0L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR (1L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR (2L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR (3L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF (4L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA (5L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR (6L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR (7L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR (8L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR (9L<<0) +#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF (10L<<0) +#define BNX2_RPM_DEBUG8_COMPARE_AT_W0 (1L<<4) +#define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA (1L<<5) +#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT (1L<<6) +#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3 (1L<<7) +#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2 (1L<<8) +#define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES (1L<<9) +#define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES (1L<<10) +#define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES (1L<<11) +#define BNX2_RPM_DEBUG8_EOF_DET (1L<<12) +#define BNX2_RPM_DEBUG8_SOF_DET (1L<<13) +#define BNX2_RPM_DEBUG8_WAIT_4_SOF (1L<<14) +#define BNX2_RPM_DEBUG8_ALL_DONE (1L<<15) +#define BNX2_RPM_DEBUG8_THBUF_ADDR (0x7fL<<16) +#define BNX2_RPM_DEBUG8_BYTE_CTR (0xffL<<24) + +#define BNX2_RPM_DEBUG9 0x000019a8 +#define BNX2_RPM_DEBUG9_OUTFIFO_COUNT (0x7L<<0) +#define BNX2_RPM_DEBUG9_RDE_ACPI_RDY (1L<<3) +#define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT (0x7L<<4) +#define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED (1L<<28) +#define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29) +#define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30) +#define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31) + +#define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0 +#define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4 +#define BNX2_RPM_ACPI_DBG_BUF_W02 0x000019c8 +#define BNX2_RPM_ACPI_DBG_BUF_W03 0x000019cc +#define BNX2_RPM_ACPI_DBG_BUF_W10 0x000019d0 +#define BNX2_RPM_ACPI_DBG_BUF_W11 0x000019d4 +#define BNX2_RPM_ACPI_DBG_BUF_W12 0x000019d8 +#define BNX2_RPM_ACPI_DBG_BUF_W13 0x000019dc +#define BNX2_RPM_ACPI_DBG_BUF_W20 0x000019e0 +#define BNX2_RPM_ACPI_DBG_BUF_W21 0x000019e4 +#define BNX2_RPM_ACPI_DBG_BUF_W22 0x000019e8 +#define BNX2_RPM_ACPI_DBG_BUF_W23 0x000019ec +#define BNX2_RPM_ACPI_DBG_BUF_W30 0x000019f0 +#define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4 +#define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8 +#define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc + + +/* + * rbuf_reg definition + * offset: 0x200000 + */ +#define BNX2_RBUF_COMMAND 0x00200000 +#define BNX2_RBUF_COMMAND_ENABLED (1L<<0) +#define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1) +#define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2) +#define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4) +#define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5) + +#define BNX2_RBUF_STATUS1 0x00200004 +#define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0) + +#define BNX2_RBUF_STATUS2 0x00200008 +#define BNX2_RBUF_STATUS2_FREE_TAIL (0x3ffL<<0) +#define BNX2_RBUF_STATUS2_FREE_HEAD (0x3ffL<<16) + +#define BNX2_RBUF_CONFIG 0x0020000c +#define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0) +#define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16) + +#define BNX2_RBUF_FW_BUF_ALLOC 0x00200010 +#define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7) + +#define BNX2_RBUF_FW_BUF_FREE 0x00200014 +#define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0) +#define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7) +#define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16) + +#define BNX2_RBUF_FW_BUF_SEL 0x00200018 +#define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0) +#define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7) +#define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16) + +#define BNX2_RBUF_CONFIG2 0x0020001c +#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0) +#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16) + +#define BNX2_RBUF_CONFIG3 0x00200020 +#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0) +#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16) + +#define BNX2_RBUF_PKT_DATA 0x00208000 +#define BNX2_RBUF_CLIST_DATA 0x00210000 +#define BNX2_RBUF_BUF_DATA 0x00220000 + + +/* + * rv2p_reg definition + * offset: 0x2800 + */ +#define BNX2_RV2P_COMMAND 0x00002800 +#define BNX2_RV2P_COMMAND_ENABLED (1L<<0) +#define BNX2_RV2P_COMMAND_PROC1_INTRPT (1L<<1) +#define BNX2_RV2P_COMMAND_PROC2_INTRPT (1L<<2) +#define BNX2_RV2P_COMMAND_ABORT0 (1L<<4) +#define BNX2_RV2P_COMMAND_ABORT1 (1L<<5) +#define BNX2_RV2P_COMMAND_ABORT2 (1L<<6) +#define BNX2_RV2P_COMMAND_ABORT3 (1L<<7) +#define BNX2_RV2P_COMMAND_ABORT4 (1L<<8) +#define BNX2_RV2P_COMMAND_ABORT5 (1L<<9) +#define BNX2_RV2P_COMMAND_PROC1_RESET (1L<<16) +#define BNX2_RV2P_COMMAND_PROC2_RESET (1L<<17) +#define BNX2_RV2P_COMMAND_CTXIF_RESET (1L<<18) + +#define BNX2_RV2P_STATUS 0x00002804 +#define BNX2_RV2P_STATUS_ALWAYS_0 (1L<<0) +#define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT (1L<<8) +#define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT (1L<<9) +#define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT (1L<<10) +#define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT (1L<<11) +#define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT (1L<<12) +#define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT (1L<<13) + +#define BNX2_RV2P_CONFIG 0x00002808 +#define BNX2_RV2P_CONFIG_STALL_PROC1 (1L<<0) +#define BNX2_RV2P_CONFIG_STALL_PROC2 (1L<<1) +#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0 (1L<<8) +#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1 (1L<<9) +#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2 (1L<<10) +#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3 (1L<<11) +#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4 (1L<<12) +#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5 (1L<<13) +#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0 (1L<<16) +#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1 (1L<<17) +#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2 (1L<<18) +#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3 (1L<<19) +#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4 (1L<<20) +#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5 (1L<<21) +#define BNX2_RV2P_CONFIG_PAGE_SIZE (0xfL<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_256 (0L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_512 (1L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_1K (2L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_2K (3L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_4K (4L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_8K (5L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_16K (6L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_32K (7L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_64K (8L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_128K (9L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_256K (10L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_512K (11L<<24) +#define BNX2_RV2P_CONFIG_PAGE_SIZE_1M (12L<<24) + +#define BNX2_RV2P_GEN_BFR_ADDR_0 0x00002810 +#define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE (0xffffL<<16) + +#define BNX2_RV2P_GEN_BFR_ADDR_1 0x00002814 +#define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE (0xffffL<<16) + +#define BNX2_RV2P_GEN_BFR_ADDR_2 0x00002818 +#define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE (0xffffL<<16) + +#define BNX2_RV2P_GEN_BFR_ADDR_3 0x0000281c +#define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE (0xffffL<<16) + +#define BNX2_RV2P_INSTR_HIGH 0x00002830 +#define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0) + +#define BNX2_RV2P_INSTR_LOW 0x00002834 +#define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838 +#define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0) +#define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31) + +#define BNX2_RV2P_PROC2_ADDR_CMD 0x0000283c +#define BNX2_RV2P_PROC2_ADDR_CMD_ADD (0x3ffL<<0) +#define BNX2_RV2P_PROC2_ADDR_CMD_RDWR (1L<<31) + +#define BNX2_RV2P_PROC1_GRC_DEBUG 0x00002840 +#define BNX2_RV2P_PROC2_GRC_DEBUG 0x00002844 +#define BNX2_RV2P_GRC_PROC_DEBUG 0x00002848 +#define BNX2_RV2P_DEBUG_VECT_PEEK 0x0000284c +#define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_RV2P_PFTQ_DATA 0x00002b40 +#define BNX2_RV2P_PFTQ_CMD 0x00002b78 +#define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10) +#define BNX2_RV2P_PFTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_RV2P_PFTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_RV2P_PFTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_RV2P_PFTQ_CMD_RD_DATA (1L<<26) +#define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_RV2P_PFTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_RV2P_PFTQ_CMD_POP (1L<<30) +#define BNX2_RV2P_PFTQ_CMD_BUSY (1L<<31) + +#define BNX2_RV2P_PFTQ_CTL 0x00002b7c +#define BNX2_RV2P_PFTQ_CTL_INTERVENE (1L<<0) +#define BNX2_RV2P_PFTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_RV2P_TFTQ_DATA 0x00002b80 +#define BNX2_RV2P_TFTQ_CMD 0x00002bb8 +#define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10) +#define BNX2_RV2P_TFTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_RV2P_TFTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_RV2P_TFTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_RV2P_TFTQ_CMD_RD_DATA (1L<<26) +#define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_RV2P_TFTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_RV2P_TFTQ_CMD_POP (1L<<30) +#define BNX2_RV2P_TFTQ_CMD_BUSY (1L<<31) + +#define BNX2_RV2P_TFTQ_CTL 0x00002bbc +#define BNX2_RV2P_TFTQ_CTL_INTERVENE (1L<<0) +#define BNX2_RV2P_TFTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_RV2P_MFTQ_DATA 0x00002bc0 +#define BNX2_RV2P_MFTQ_CMD 0x00002bf8 +#define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10) +#define BNX2_RV2P_MFTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_RV2P_MFTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_RV2P_MFTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_RV2P_MFTQ_CMD_RD_DATA (1L<<26) +#define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_RV2P_MFTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_RV2P_MFTQ_CMD_POP (1L<<30) +#define BNX2_RV2P_MFTQ_CMD_BUSY (1L<<31) + +#define BNX2_RV2P_MFTQ_CTL 0x00002bfc +#define BNX2_RV2P_MFTQ_CTL_INTERVENE (1L<<0) +#define BNX2_RV2P_MFTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + + +/* + * mq_reg definition + * offset: 0x3c00 + */ +#define BNX2_MQ_COMMAND 0x00003c00 +#define BNX2_MQ_COMMAND_ENABLED (1L<<0) +#define BNX2_MQ_COMMAND_OVERFLOW (1L<<4) +#define BNX2_MQ_COMMAND_WR_ERROR (1L<<5) +#define BNX2_MQ_COMMAND_RD_ERROR (1L<<6) + +#define BNX2_MQ_STATUS 0x00003c04 +#define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16) +#define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17) +#define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18) + +#define BNX2_MQ_CONFIG 0x00003c08 +#define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0) +#define BNX2_MQ_CONFIG_HALT_DIS (1L<<1) +#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4) +#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4) +#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4) +#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K (2L<<4) +#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K (3L<<4) +#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K (4L<<4) +#define BNX2_MQ_CONFIG_MAX_DEPTH (0x7fL<<8) +#define BNX2_MQ_CONFIG_CUR_DEPTH (0x7fL<<20) + +#define BNX2_MQ_ENQUEUE1 0x00003c0c +#define BNX2_MQ_ENQUEUE1_OFFSET (0x3fL<<2) +#define BNX2_MQ_ENQUEUE1_CID (0x3fffL<<8) +#define BNX2_MQ_ENQUEUE1_BYTE_MASK (0xfL<<24) +#define BNX2_MQ_ENQUEUE1_KNL_MODE (1L<<28) + +#define BNX2_MQ_ENQUEUE2 0x00003c10 +#define BNX2_MQ_BAD_WR_ADDR 0x00003c14 +#define BNX2_MQ_BAD_RD_ADDR 0x00003c18 +#define BNX2_MQ_KNL_BYP_WIND_START 0x00003c1c +#define BNX2_MQ_KNL_BYP_WIND_START_VALUE (0xfffffL<<12) + +#define BNX2_MQ_KNL_WIND_END 0x00003c20 +#define BNX2_MQ_KNL_WIND_END_VALUE (0xffffffL<<8) + +#define BNX2_MQ_KNL_WRITE_MASK1 0x00003c24 +#define BNX2_MQ_KNL_TX_MASK1 0x00003c28 +#define BNX2_MQ_KNL_CMD_MASK1 0x00003c2c +#define BNX2_MQ_KNL_COND_ENQUEUE_MASK1 0x00003c30 +#define BNX2_MQ_KNL_RX_V2P_MASK1 0x00003c34 +#define BNX2_MQ_KNL_WRITE_MASK2 0x00003c38 +#define BNX2_MQ_KNL_TX_MASK2 0x00003c3c +#define BNX2_MQ_KNL_CMD_MASK2 0x00003c40 +#define BNX2_MQ_KNL_COND_ENQUEUE_MASK2 0x00003c44 +#define BNX2_MQ_KNL_RX_V2P_MASK2 0x00003c48 +#define BNX2_MQ_KNL_BYP_WRITE_MASK1 0x00003c4c +#define BNX2_MQ_KNL_BYP_TX_MASK1 0x00003c50 +#define BNX2_MQ_KNL_BYP_CMD_MASK1 0x00003c54 +#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1 0x00003c58 +#define BNX2_MQ_KNL_BYP_RX_V2P_MASK1 0x00003c5c +#define BNX2_MQ_KNL_BYP_WRITE_MASK2 0x00003c60 +#define BNX2_MQ_KNL_BYP_TX_MASK2 0x00003c64 +#define BNX2_MQ_KNL_BYP_CMD_MASK2 0x00003c68 +#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2 0x00003c6c +#define BNX2_MQ_KNL_BYP_RX_V2P_MASK2 0x00003c70 +#define BNX2_MQ_MEM_WR_ADDR 0x00003c74 +#define BNX2_MQ_MEM_WR_ADDR_VALUE (0x3fL<<0) + +#define BNX2_MQ_MEM_WR_DATA0 0x00003c78 +#define BNX2_MQ_MEM_WR_DATA0_VALUE (0xffffffffL<<0) + +#define BNX2_MQ_MEM_WR_DATA1 0x00003c7c +#define BNX2_MQ_MEM_WR_DATA1_VALUE (0xffffffffL<<0) + +#define BNX2_MQ_MEM_WR_DATA2 0x00003c80 +#define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0) + +#define BNX2_MQ_MEM_RD_ADDR 0x00003c84 +#define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0) + +#define BNX2_MQ_MEM_RD_DATA0 0x00003c88 +#define BNX2_MQ_MEM_RD_DATA0_VALUE (0xffffffffL<<0) + +#define BNX2_MQ_MEM_RD_DATA1 0x00003c8c +#define BNX2_MQ_MEM_RD_DATA1_VALUE (0xffffffffL<<0) + +#define BNX2_MQ_MEM_RD_DATA2 0x00003c90 +#define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0) + + + +/* + * tbdr_reg definition + * offset: 0x5000 + */ +#define BNX2_TBDR_COMMAND 0x00005000 +#define BNX2_TBDR_COMMAND_ENABLE (1L<<0) +#define BNX2_TBDR_COMMAND_SOFT_RST (1L<<1) +#define BNX2_TBDR_COMMAND_MSTR_ABORT (1L<<4) + +#define BNX2_TBDR_STATUS 0x00005004 +#define BNX2_TBDR_STATUS_DMA_WAIT (1L<<0) +#define BNX2_TBDR_STATUS_FTQ_WAIT (1L<<1) +#define BNX2_TBDR_STATUS_FIFO_OVERFLOW (1L<<2) +#define BNX2_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3) +#define BNX2_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4) +#define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5) +#define BNX2_TBDR_STATUS_BURST_CNT (1L<<6) + +#define BNX2_TBDR_CONFIG 0x00005008 +#define BNX2_TBDR_CONFIG_MAX_BDS (0xffL<<0) +#define BNX2_TBDR_CONFIG_SWAP_MODE (1L<<8) +#define BNX2_TBDR_CONFIG_PRIORITY (1L<<9) +#define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10) +#define BNX2_TBDR_CONFIG_PAGE_SIZE (0xfL<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24) +#define BNX2_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24) + +#define BNX2_TBDR_DEBUG_VECT_PEEK 0x0000500c +#define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_TBDR_FTQ_DATA 0x000053c0 +#define BNX2_TBDR_FTQ_CMD 0x000053f8 +#define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_TBDR_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_TBDR_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_TBDR_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_TBDR_FTQ_CMD_POP (1L<<30) +#define BNX2_TBDR_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_TBDR_FTQ_CTL 0x000053fc +#define BNX2_TBDR_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_TBDR_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + + +/* + * tdma_reg definition + * offset: 0x5c00 + */ +#define BNX2_TDMA_COMMAND 0x00005c00 +#define BNX2_TDMA_COMMAND_ENABLED (1L<<0) +#define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4) +#define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7) + +#define BNX2_TDMA_STATUS 0x00005c04 +#define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0) +#define BNX2_TDMA_STATUS_PAYLOAD_WAIT (1L<<1) +#define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2) +#define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3) +#define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16) +#define BNX2_TDMA_STATUS_BURST_CNT (1L<<17) + +#define BNX2_TDMA_CONFIG 0x00005c08 +#define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0) +#define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1) +#define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4) +#define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4) +#define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4) +#define BNX2_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4) +#define BNX2_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4) +#define BNX2_TDMA_CONFIG_LINE_SZ (0xfL<<8) +#define BNX2_TDMA_CONFIG_LINE_SZ_64 (0L<<8) +#define BNX2_TDMA_CONFIG_LINE_SZ_128 (4L<<8) +#define BNX2_TDMA_CONFIG_LINE_SZ_256 (6L<<8) +#define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8) +#define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15) +#define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16) +#define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20) + +#define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c +#define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3) + +#define BNX2_TDMA_DBG_WATCHDOG 0x00005c10 +#define BNX2_TDMA_DBG_TRIGGER 0x00005c14 +#define BNX2_TDMA_DMAD_FSM 0x00005c80 +#define BNX2_TDMA_DMAD_FSM_BD_INVLD (1L<<0) +#define BNX2_TDMA_DMAD_FSM_PUSH (0xfL<<4) +#define BNX2_TDMA_DMAD_FSM_ARB_TBDC (0x3L<<8) +#define BNX2_TDMA_DMAD_FSM_ARB_CTX (1L<<12) +#define BNX2_TDMA_DMAD_FSM_DR_INTF (1L<<16) +#define BNX2_TDMA_DMAD_FSM_DMAD (0x7L<<20) +#define BNX2_TDMA_DMAD_FSM_BD (0xfL<<24) + +#define BNX2_TDMA_DMAD_STATUS 0x00005c84 +#define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY (0x3L<<0) +#define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY (0x3L<<4) +#define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY (0x3L<<8) +#define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM (0xfL<<12) + +#define BNX2_TDMA_DR_INTF_FSM 0x00005c88 +#define BNX2_TDMA_DR_INTF_FSM_L2_COMP (0x3L<<0) +#define BNX2_TDMA_DR_INTF_FSM_TPATQ (0x7L<<4) +#define BNX2_TDMA_DR_INTF_FSM_TPBUF (0x3L<<8) +#define BNX2_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12) +#define BNX2_TDMA_DR_INTF_FSM_DMAD (0x7L<<16) + +#define BNX2_TDMA_DR_INTF_STATUS 0x00005c8c +#define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0) +#define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4) +#define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8) +#define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12) +#define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16) + +#define BNX2_TDMA_FTQ_DATA 0x00005fc0 +#define BNX2_TDMA_FTQ_CMD 0x00005ff8 +#define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_TDMA_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_TDMA_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_TDMA_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_TDMA_FTQ_CMD_POP (1L<<30) +#define BNX2_TDMA_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_TDMA_FTQ_CTL 0x00005ffc +#define BNX2_TDMA_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_TDMA_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_TDMA_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_TDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + + + +/* + * hc_reg definition + * offset: 0x6800 + */ +#define BNX2_HC_COMMAND 0x00006800 +#define BNX2_HC_COMMAND_ENABLE (1L<<0) +#define BNX2_HC_COMMAND_SKIP_ABORT (1L<<4) +#define BNX2_HC_COMMAND_COAL_NOW (1L<<16) +#define BNX2_HC_COMMAND_COAL_NOW_WO_INT (1L<<17) +#define BNX2_HC_COMMAND_STATS_NOW (1L<<18) +#define BNX2_HC_COMMAND_FORCE_INT (0x3L<<19) +#define BNX2_HC_COMMAND_FORCE_INT_NULL (0L<<19) +#define BNX2_HC_COMMAND_FORCE_INT_HIGH (1L<<19) +#define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19) +#define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19) +#define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21) + +#define BNX2_HC_STATUS 0x00006804 +#define BNX2_HC_STATUS_MASTER_ABORT (1L<<0) +#define BNX2_HC_STATUS_PARITY_ERROR_STATE (1L<<1) +#define BNX2_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16) +#define BNX2_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17) +#define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18) +#define BNX2_HC_STATUS_NUM_INT_GEN_STAT (1L<<19) +#define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20) +#define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT (1L<<23) +#define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT (1L<<24) +#define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT (1L<<25) + +#define BNX2_HC_CONFIG 0x00006808 +#define BNX2_HC_CONFIG_COLLECT_STATS (1L<<0) +#define BNX2_HC_CONFIG_RX_TMR_MODE (1L<<1) +#define BNX2_HC_CONFIG_TX_TMR_MODE (1L<<2) +#define BNX2_HC_CONFIG_COM_TMR_MODE (1L<<3) +#define BNX2_HC_CONFIG_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5) +#define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6) +#define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8) + +#define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c +#define BNX2_HC_STATUS_ADDR_L 0x00006810 +#define BNX2_HC_STATUS_ADDR_H 0x00006814 +#define BNX2_HC_STATISTICS_ADDR_L 0x00006818 +#define BNX2_HC_STATISTICS_ADDR_H 0x0000681c +#define BNX2_HC_TX_QUICK_CONS_TRIP 0x00006820 +#define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP 0x00006824 +#define BNX2_HC_COMP_PROD_TRIP_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP 0x00006828 +#define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS 0x0000682c +#define BNX2_HC_RX_TICKS_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS 0x00006830 +#define BNX2_HC_TX_TICKS_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS 0x00006834 +#define BNX2_HC_COM_TICKS_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS 0x00006838 +#define BNX2_HC_CMD_TICKS_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS 0x0000683c +#define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0) + +#define BNX2_HC_STAT_COLLECT_TICKS 0x00006840 +#define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4) + +#define BNX2_HC_STATS_TICKS 0x00006844 +#define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8) + +#define BNX2_HC_STAT_MEM_DATA 0x0000684c +#define BNX2_HC_STAT_GEN_SEL_0 0x00006850 +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3 (3L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4 (4L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5 (5L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6 (6L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7 (7L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8 (8L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9 (9L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10 (10L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11 (11L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0 (12L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1 (13L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2 (14L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3 (15L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4 (16L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5 (17L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6 (18L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7 (19L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0 (20L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1 (21L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2 (22L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3 (23L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4 (24L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5 (25L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6 (26L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7 (27L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8 (28L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9 (29L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10 (30L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11 (31L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0 (32L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1 (33L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2 (34L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3 (35L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0 (36L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1 (37L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2 (38L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3 (39L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4 (40L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5 (41L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6 (42L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7 (43L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0 (44L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1 (45L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2 (46L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3 (47L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4 (48L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5 (49L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6 (50L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7 (51L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT (52L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT (53L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS (54L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN (55L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR (56L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK (59L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK (60L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK (61L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT (62L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT (63L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT (64L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT (65L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT (75L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT (76L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT (77L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT (78L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT (79L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT (80L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT (81L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT (82L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT (83L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT (84L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT (85L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT (86L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT (87L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT (88L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT (89L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT (90L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT (91L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT (92L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT (93L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT (94L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64 (95L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64 (96L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS (97L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS (98L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT (99L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT (100L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT (101L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT (102L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT (103L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT (104L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT (105L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT (106L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT (107L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT (108L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT (109L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT (110L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT (111L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT (112L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT (113L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT (114L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0 (115L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1 (116L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2 (117L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3 (118L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4 (119L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5 (120L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS (121L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS (122L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT (127L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24) + +#define BNX2_HC_STAT_GEN_SEL_1 0x00006854 +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24) + +#define BNX2_HC_STAT_GEN_SEL_2 0x00006858 +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24) + +#define BNX2_HC_STAT_GEN_SEL_3 0x0000685c +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24) + +#define BNX2_HC_STAT_GEN_STAT0 0x00006888 +#define BNX2_HC_STAT_GEN_STAT1 0x0000688c +#define BNX2_HC_STAT_GEN_STAT2 0x00006890 +#define BNX2_HC_STAT_GEN_STAT3 0x00006894 +#define BNX2_HC_STAT_GEN_STAT4 0x00006898 +#define BNX2_HC_STAT_GEN_STAT5 0x0000689c +#define BNX2_HC_STAT_GEN_STAT6 0x000068a0 +#define BNX2_HC_STAT_GEN_STAT7 0x000068a4 +#define BNX2_HC_STAT_GEN_STAT8 0x000068a8 +#define BNX2_HC_STAT_GEN_STAT9 0x000068ac +#define BNX2_HC_STAT_GEN_STAT10 0x000068b0 +#define BNX2_HC_STAT_GEN_STAT11 0x000068b4 +#define BNX2_HC_STAT_GEN_STAT12 0x000068b8 +#define BNX2_HC_STAT_GEN_STAT13 0x000068bc +#define BNX2_HC_STAT_GEN_STAT14 0x000068c0 +#define BNX2_HC_STAT_GEN_STAT15 0x000068c4 +#define BNX2_HC_STAT_GEN_STAT_AC0 0x000068c8 +#define BNX2_HC_STAT_GEN_STAT_AC1 0x000068cc +#define BNX2_HC_STAT_GEN_STAT_AC2 0x000068d0 +#define BNX2_HC_STAT_GEN_STAT_AC3 0x000068d4 +#define BNX2_HC_STAT_GEN_STAT_AC4 0x000068d8 +#define BNX2_HC_STAT_GEN_STAT_AC5 0x000068dc +#define BNX2_HC_STAT_GEN_STAT_AC6 0x000068e0 +#define BNX2_HC_STAT_GEN_STAT_AC7 0x000068e4 +#define BNX2_HC_STAT_GEN_STAT_AC8 0x000068e8 +#define BNX2_HC_STAT_GEN_STAT_AC9 0x000068ec +#define BNX2_HC_STAT_GEN_STAT_AC10 0x000068f0 +#define BNX2_HC_STAT_GEN_STAT_AC11 0x000068f4 +#define BNX2_HC_STAT_GEN_STAT_AC12 0x000068f8 +#define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc +#define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900 +#define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904 +#define BNX2_HC_VIS 0x00006908 +#define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_START (1L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST (2L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64 (3L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32 (4L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE (5L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_DMA (6L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL (7L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW (8L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH (9L<<0) +#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA (10L<<0) +#define BNX2_HC_VIS_DMA_STAT_STATE (0xfL<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_IDLE (0L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM (1L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA (2L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP (3L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_COMP (4L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM (5L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA (6L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1 (7L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2 (8L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_WAIT (9L<<8) +#define BNX2_HC_VIS_DMA_STAT_STATE_ABORT (15L<<8) +#define BNX2_HC_VIS_DMA_MSI_STATE (0x7L<<12) +#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE (0x3L<<15) +#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE (0L<<15) +#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT (1L<<15) +#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START (2L<<15) + +#define BNX2_HC_VIS_1 0x0000690c +#define BNX2_HC_VIS_1_HW_INTACK_STATE (1L<<4) +#define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE (0L<<4) +#define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT (1L<<4) +#define BNX2_HC_VIS_1_SW_INTACK_STATE (1L<<5) +#define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE (0L<<5) +#define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT (1L<<5) +#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE (1L<<6) +#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE (0L<<6) +#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT (1L<<6) +#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE (1L<<7) +#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE (0L<<7) +#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT (1L<<7) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE (0xfL<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE (0L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA (1L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE (2L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN (3L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT (4L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE (5L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN (6L<<17) +#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT (7L<<17) +#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE (0x3L<<21) +#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL (0L<<21) +#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR (1L<<21) +#define BNX2_HC_VIS_1_INT_GEN_STATE (1L<<23) +#define BNX2_HC_VIS_1_INT_GEN_STATE_DLE (0L<<23) +#define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT (1L<<23) +#define BNX2_HC_VIS_1_STAT_CHAN_ID (0x7L<<24) +#define BNX2_HC_VIS_1_INT_B (1L<<27) + +#define BNX2_HC_DEBUG_VECT_PEEK 0x00006910 +#define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_HC_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + + + +/* + * txp_reg definition + * offset: 0x40000 + */ +#define BNX2_TXP_CPU_MODE 0x00045000 +#define BNX2_TXP_CPU_MODE_LOCAL_RST (1L<<0) +#define BNX2_TXP_CPU_MODE_STEP_ENA (1L<<1) +#define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) +#define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) +#define BNX2_TXP_CPU_MODE_MSG_BIT1 (1L<<6) +#define BNX2_TXP_CPU_MODE_INTERRUPT_ENA (1L<<7) +#define BNX2_TXP_CPU_MODE_SOFT_HALT (1L<<10) +#define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) +#define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) +#define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) +#define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + +#define BNX2_TXP_CPU_STATE 0x00045004 +#define BNX2_TXP_CPU_STATE_BREAKPOINT (1L<<0) +#define BNX2_TXP_CPU_STATE_BAD_INST_HALTED (1L<<2) +#define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) +#define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) +#define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) +#define BNX2_TXP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7) +#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) +#define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10) +#define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) +#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12) +#define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) +#define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15) +#define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31) + +#define BNX2_TXP_CPU_EVENT_MASK 0x00045008 +#define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) +#define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) +#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) +#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) +#define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) +#define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) +#define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) +#define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) +#define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) +#define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) +#define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + +#define BNX2_TXP_CPU_PROGRAM_COUNTER 0x0004501c +#define BNX2_TXP_CPU_INSTRUCTION 0x00045020 +#define BNX2_TXP_CPU_DATA_ACCESS 0x00045024 +#define BNX2_TXP_CPU_INTERRUPT_ENABLE 0x00045028 +#define BNX2_TXP_CPU_INTERRUPT_VECTOR 0x0004502c +#define BNX2_TXP_CPU_INTERRUPT_SAVED_PC 0x00045030 +#define BNX2_TXP_CPU_HW_BREAKPOINT 0x00045034 +#define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) +#define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK 0x00045038 +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_TXP_CPU_LAST_BRANCH_ADDR 0x00045048 +#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) +#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) +#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) +#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + +#define BNX2_TXP_CPU_REG_FILE 0x00045200 +#define BNX2_TXP_FTQ_DATA 0x000453c0 +#define BNX2_TXP_FTQ_CMD 0x000453f8 +#define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_TXP_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_TXP_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_TXP_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_TXP_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_TXP_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_TXP_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_TXP_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_TXP_FTQ_CMD_POP (1L<<30) +#define BNX2_TXP_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_TXP_FTQ_CTL 0x000453fc +#define BNX2_TXP_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_TXP_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_TXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_TXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_TXP_SCRATCH 0x00060000 + + +/* + * tpat_reg definition + * offset: 0x80000 + */ +#define BNX2_TPAT_CPU_MODE 0x00085000 +#define BNX2_TPAT_CPU_MODE_LOCAL_RST (1L<<0) +#define BNX2_TPAT_CPU_MODE_STEP_ENA (1L<<1) +#define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) +#define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA (1L<<3) +#define BNX2_TPAT_CPU_MODE_MSG_BIT1 (1L<<6) +#define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA (1L<<7) +#define BNX2_TPAT_CPU_MODE_SOFT_HALT (1L<<10) +#define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) +#define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) +#define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) +#define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + +#define BNX2_TPAT_CPU_STATE 0x00085004 +#define BNX2_TPAT_CPU_STATE_BREAKPOINT (1L<<0) +#define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED (1L<<2) +#define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) +#define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) +#define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) +#define BNX2_TPAT_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7) +#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8) +#define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10) +#define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11) +#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12) +#define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14) +#define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15) +#define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31) + +#define BNX2_TPAT_CPU_EVENT_MASK 0x00085008 +#define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) +#define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) +#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) +#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) +#define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) +#define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) +#define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) +#define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) +#define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) +#define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) +#define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + +#define BNX2_TPAT_CPU_PROGRAM_COUNTER 0x0008501c +#define BNX2_TPAT_CPU_INSTRUCTION 0x00085020 +#define BNX2_TPAT_CPU_DATA_ACCESS 0x00085024 +#define BNX2_TPAT_CPU_INTERRUPT_ENABLE 0x00085028 +#define BNX2_TPAT_CPU_INTERRUPT_VECTOR 0x0008502c +#define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC 0x00085030 +#define BNX2_TPAT_CPU_HW_BREAKPOINT 0x00085034 +#define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE (1L<<0) +#define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK 0x00085038 +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR 0x00085048 +#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) +#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) +#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) +#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + +#define BNX2_TPAT_CPU_REG_FILE 0x00085200 +#define BNX2_TPAT_FTQ_DATA 0x000853c0 +#define BNX2_TPAT_FTQ_CMD 0x000853f8 +#define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_TPAT_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_TPAT_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_TPAT_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_TPAT_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_TPAT_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_TPAT_FTQ_CMD_POP (1L<<30) +#define BNX2_TPAT_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_TPAT_FTQ_CTL 0x000853fc +#define BNX2_TPAT_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_TPAT_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_TPAT_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_TPAT_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_TPAT_SCRATCH 0x000a0000 + + +/* + * rxp_reg definition + * offset: 0xc0000 + */ +#define BNX2_RXP_CPU_MODE 0x000c5000 +#define BNX2_RXP_CPU_MODE_LOCAL_RST (1L<<0) +#define BNX2_RXP_CPU_MODE_STEP_ENA (1L<<1) +#define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) +#define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) +#define BNX2_RXP_CPU_MODE_MSG_BIT1 (1L<<6) +#define BNX2_RXP_CPU_MODE_INTERRUPT_ENA (1L<<7) +#define BNX2_RXP_CPU_MODE_SOFT_HALT (1L<<10) +#define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) +#define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) +#define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) +#define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + +#define BNX2_RXP_CPU_STATE 0x000c5004 +#define BNX2_RXP_CPU_STATE_BREAKPOINT (1L<<0) +#define BNX2_RXP_CPU_STATE_BAD_INST_HALTED (1L<<2) +#define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) +#define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) +#define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) +#define BNX2_RXP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7) +#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) +#define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10) +#define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) +#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12) +#define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) +#define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15) +#define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31) + +#define BNX2_RXP_CPU_EVENT_MASK 0x000c5008 +#define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) +#define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) +#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) +#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) +#define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) +#define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) +#define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) +#define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) +#define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) +#define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) +#define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + +#define BNX2_RXP_CPU_PROGRAM_COUNTER 0x000c501c +#define BNX2_RXP_CPU_INSTRUCTION 0x000c5020 +#define BNX2_RXP_CPU_DATA_ACCESS 0x000c5024 +#define BNX2_RXP_CPU_INTERRUPT_ENABLE 0x000c5028 +#define BNX2_RXP_CPU_INTERRUPT_VECTOR 0x000c502c +#define BNX2_RXP_CPU_INTERRUPT_SAVED_PC 0x000c5030 +#define BNX2_RXP_CPU_HW_BREAKPOINT 0x000c5034 +#define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) +#define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK 0x000c5038 +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_RXP_CPU_LAST_BRANCH_ADDR 0x000c5048 +#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) +#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) +#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) +#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + +#define BNX2_RXP_CPU_REG_FILE 0x000c5200 +#define BNX2_RXP_CFTQ_DATA 0x000c5380 +#define BNX2_RXP_CFTQ_CMD 0x000c53b8 +#define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10) +#define BNX2_RXP_CFTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_RXP_CFTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_RXP_CFTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_RXP_CFTQ_CMD_RD_DATA (1L<<26) +#define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_RXP_CFTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_RXP_CFTQ_CMD_POP (1L<<30) +#define BNX2_RXP_CFTQ_CMD_BUSY (1L<<31) + +#define BNX2_RXP_CFTQ_CTL 0x000c53bc +#define BNX2_RXP_CFTQ_CTL_INTERVENE (1L<<0) +#define BNX2_RXP_CFTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_RXP_FTQ_DATA 0x000c53c0 +#define BNX2_RXP_FTQ_CMD 0x000c53f8 +#define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_RXP_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_RXP_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_RXP_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_RXP_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_RXP_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_RXP_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_RXP_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_RXP_FTQ_CMD_POP (1L<<30) +#define BNX2_RXP_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_RXP_FTQ_CTL 0x000c53fc +#define BNX2_RXP_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_RXP_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_RXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_RXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_RXP_SCRATCH 0x000e0000 + + +/* + * com_reg definition + * offset: 0x100000 + */ +#define BNX2_COM_CPU_MODE 0x00105000 +#define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0) +#define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1) +#define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) +#define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA (1L<<3) +#define BNX2_COM_CPU_MODE_MSG_BIT1 (1L<<6) +#define BNX2_COM_CPU_MODE_INTERRUPT_ENA (1L<<7) +#define BNX2_COM_CPU_MODE_SOFT_HALT (1L<<10) +#define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) +#define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) +#define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) +#define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + +#define BNX2_COM_CPU_STATE 0x00105004 +#define BNX2_COM_CPU_STATE_BREAKPOINT (1L<<0) +#define BNX2_COM_CPU_STATE_BAD_INST_HALTED (1L<<2) +#define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) +#define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) +#define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) +#define BNX2_COM_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7) +#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8) +#define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10) +#define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11) +#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12) +#define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14) +#define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15) +#define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31) + +#define BNX2_COM_CPU_EVENT_MASK 0x00105008 +#define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) +#define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) +#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) +#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) +#define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) +#define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) +#define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) +#define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) +#define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) +#define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) +#define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + +#define BNX2_COM_CPU_PROGRAM_COUNTER 0x0010501c +#define BNX2_COM_CPU_INSTRUCTION 0x00105020 +#define BNX2_COM_CPU_DATA_ACCESS 0x00105024 +#define BNX2_COM_CPU_INTERRUPT_ENABLE 0x00105028 +#define BNX2_COM_CPU_INTERRUPT_VECTOR 0x0010502c +#define BNX2_COM_CPU_INTERRUPT_SAVED_PC 0x00105030 +#define BNX2_COM_CPU_HW_BREAKPOINT 0x00105034 +#define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE (1L<<0) +#define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + +#define BNX2_COM_CPU_DEBUG_VECT_PEEK 0x00105038 +#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_COM_CPU_LAST_BRANCH_ADDR 0x00105048 +#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) +#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) +#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) +#define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + +#define BNX2_COM_CPU_REG_FILE 0x00105200 +#define BNX2_COM_COMXQ_FTQ_DATA 0x00105340 +#define BNX2_COM_COMXQ_FTQ_CMD 0x00105378 +#define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_COM_COMXQ_FTQ_CMD_POP (1L<<30) +#define BNX2_COM_COMXQ_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_COM_COMXQ_FTQ_CTL 0x0010537c +#define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_COM_COMTQ_FTQ_DATA 0x00105380 +#define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8 +#define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_COM_COMTQ_FTQ_CMD_POP (1L<<30) +#define BNX2_COM_COMTQ_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_COM_COMTQ_FTQ_CTL 0x001053bc +#define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_COM_COMQ_FTQ_DATA 0x001053c0 +#define BNX2_COM_COMQ_FTQ_CMD 0x001053f8 +#define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_COM_COMQ_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_COM_COMQ_FTQ_CMD_POP (1L<<30) +#define BNX2_COM_COMQ_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_COM_COMQ_FTQ_CTL 0x001053fc +#define BNX2_COM_COMQ_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_COM_SCRATCH 0x00120000 + + +/* + * cp_reg definition + * offset: 0x180000 + */ +#define BNX2_CP_CPU_MODE 0x00185000 +#define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0) +#define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1) +#define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) +#define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) +#define BNX2_CP_CPU_MODE_MSG_BIT1 (1L<<6) +#define BNX2_CP_CPU_MODE_INTERRUPT_ENA (1L<<7) +#define BNX2_CP_CPU_MODE_SOFT_HALT (1L<<10) +#define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) +#define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) +#define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) +#define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + +#define BNX2_CP_CPU_STATE 0x00185004 +#define BNX2_CP_CPU_STATE_BREAKPOINT (1L<<0) +#define BNX2_CP_CPU_STATE_BAD_INST_HALTED (1L<<2) +#define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) +#define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) +#define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) +#define BNX2_CP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7) +#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) +#define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10) +#define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) +#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12) +#define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) +#define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15) +#define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31) + +#define BNX2_CP_CPU_EVENT_MASK 0x00185008 +#define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) +#define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) +#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) +#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) +#define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) +#define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) +#define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) +#define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) +#define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) +#define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) +#define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + +#define BNX2_CP_CPU_PROGRAM_COUNTER 0x0018501c +#define BNX2_CP_CPU_INSTRUCTION 0x00185020 +#define BNX2_CP_CPU_DATA_ACCESS 0x00185024 +#define BNX2_CP_CPU_INTERRUPT_ENABLE 0x00185028 +#define BNX2_CP_CPU_INTERRUPT_VECTOR 0x0018502c +#define BNX2_CP_CPU_INTERRUPT_SAVED_PC 0x00185030 +#define BNX2_CP_CPU_HW_BREAKPOINT 0x00185034 +#define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) +#define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + +#define BNX2_CP_CPU_DEBUG_VECT_PEEK 0x00185038 +#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_CP_CPU_LAST_BRANCH_ADDR 0x00185048 +#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) +#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) +#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) +#define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + +#define BNX2_CP_CPU_REG_FILE 0x00185200 +#define BNX2_CP_CPQ_FTQ_DATA 0x001853c0 +#define BNX2_CP_CPQ_FTQ_CMD 0x001853f8 +#define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_CP_CPQ_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_CP_CPQ_FTQ_CMD_POP (1L<<30) +#define BNX2_CP_CPQ_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_CP_CPQ_FTQ_CTL 0x001853fc +#define BNX2_CP_CPQ_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_CP_SCRATCH 0x001a0000 + + +/* + * mcp_reg definition + * offset: 0x140000 + */ +#define BNX2_MCP_CPU_MODE 0x00145000 +#define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0) +#define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1) +#define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2) +#define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA (1L<<3) +#define BNX2_MCP_CPU_MODE_MSG_BIT1 (1L<<6) +#define BNX2_MCP_CPU_MODE_INTERRUPT_ENA (1L<<7) +#define BNX2_MCP_CPU_MODE_SOFT_HALT (1L<<10) +#define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11) +#define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12) +#define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13) +#define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15) + +#define BNX2_MCP_CPU_STATE 0x00145004 +#define BNX2_MCP_CPU_STATE_BREAKPOINT (1L<<0) +#define BNX2_MCP_CPU_STATE_BAD_INST_HALTED (1L<<2) +#define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) +#define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) +#define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) +#define BNX2_MCP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7) +#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) +#define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10) +#define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11) +#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12) +#define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14) +#define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15) +#define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31) + +#define BNX2_MCP_CPU_EVENT_MASK 0x00145008 +#define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0) +#define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2) +#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3) +#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4) +#define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5) +#define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6) +#define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7) +#define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8) +#define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10) +#define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11) +#define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12) + +#define BNX2_MCP_CPU_PROGRAM_COUNTER 0x0014501c +#define BNX2_MCP_CPU_INSTRUCTION 0x00145020 +#define BNX2_MCP_CPU_DATA_ACCESS 0x00145024 +#define BNX2_MCP_CPU_INTERRUPT_ENABLE 0x00145028 +#define BNX2_MCP_CPU_INTERRUPT_VECTOR 0x0014502c +#define BNX2_MCP_CPU_INTERRUPT_SAVED_PC 0x00145030 +#define BNX2_MCP_CPU_HW_BREAKPOINT 0x00145034 +#define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE (1L<<0) +#define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2) + +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK 0x00145038 +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_MCP_CPU_LAST_BRANCH_ADDR 0x00145048 +#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1) +#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1) +#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1) +#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) + +#define BNX2_MCP_CPU_REG_FILE 0x00145200 +#define BNX2_MCP_MCPQ_FTQ_DATA 0x001453c0 +#define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8 +#define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10) +#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET (1L<<25) +#define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA (1L<<26) +#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA (1L<<28) +#define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BNX2_MCP_MCPQ_FTQ_CMD_POP (1L<<30) +#define BNX2_MCP_MCPQ_FTQ_CMD_BUSY (1L<<31) + +#define BNX2_MCP_MCPQ_FTQ_CTL 0x001453fc +#define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE (1L<<0) +#define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW (1L<<1) +#define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) + +#define BNX2_MCP_ROM 0x00150000 +#define BNX2_MCP_SCRATCH 0x00160000 + + +#define NUM_MC_HASH_REGISTERS 8 + + +/* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0. */ +#define PHY_BCM5706_PHY_ID 0x00206160 + +#define PHY_ID(id) ((id) & 0xfffffff0) +#define PHY_REV_ID(id) ((id) & 0xf) + +#define MIN_ETHERNET_PACKET_SIZE 60 +#define MAX_ETHERNET_PACKET_SIZE 1514 +#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014 + +#define RX_COPY_THRESH 92 + +#define DMA_READ_CHANS 5 +#define DMA_WRITE_CHANS 3 + +#define BCM_PAGE_BITS 12 +#define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS) + +#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd)) +#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1) + +#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd)) +#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1) + +#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \ + (MAX_TX_DESC_CNT - 1)) ? \ + (x) + 2 : (x) + 1 + +#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT) + +#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \ + (MAX_RX_DESC_CNT - 1)) ? \ + (x) + 2 : (x) + 1 + +#define RX_RING_IDX(x) ((x) & MAX_RX_DESC_CNT) + + +/* Context size. */ +#define CTX_SHIFT 7 +#define CTX_SIZE (1 << CTX_SHIFT) +#define CTX_MASK (CTX_SIZE - 1) +#define GET_CID_ADDR(_cid) ((_cid) << CTX_SHIFT) +#define GET_CID(_cid_addr) ((_cid_addr) >> CTX_SHIFT) + +#define PHY_CTX_SHIFT 6 +#define PHY_CTX_SIZE (1 << PHY_CTX_SHIFT) +#define PHY_CTX_MASK (PHY_CTX_SIZE - 1) +#define GET_PCID_ADDR(_pcid) ((_pcid) << PHY_CTX_SHIFT) +#define GET_PCID(_pcid_addr) ((_pcid_addr) >> PHY_CTX_SHIFT) + +#define MB_KERNEL_CTX_SHIFT 8 +#define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT) +#define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1) +#define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT)) + +#define MAX_CID_CNT 0x4000 +#define MAX_CID_ADDR (GET_CID_ADDR(MAX_CID_CNT)) +#define INVALID_CID_ADDR 0xffffffff + +#define TX_CID 16 +#define RX_CID 0 + +#define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID) +#define MB_RX_CID_ADDR MB_GET_CID_ADDR(RX_CID) + +struct sw_bd { + struct sk_buff *skb; + DECLARE_PCI_UNMAP_ADDR(mapping) +}; + +/* Buffered flash (Atmel: AT45DB011B) specific information */ +#define SEEPROM_PAGE_BITS 2 +#define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS) +#define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1) +#define SEEPROM_PAGE_SIZE 4 +#define SEEPROM_TOTAL_SIZE 65536 + +#define BUFFERED_FLASH_PAGE_BITS 9 +#define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS) +#define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1) +#define BUFFERED_FLASH_PAGE_SIZE 264 +#define BUFFERED_FLASH_TOTAL_SIZE 131072 + +#define SAIFUN_FLASH_PAGE_BITS 8 +#define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS) +#define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1) +#define SAIFUN_FLASH_PAGE_SIZE 256 +#define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536 + +#define NVRAM_TIMEOUT_COUNT 30000 + + +#define FLASH_STRAP_MASK (BNX2_NVM_CFG1_FLASH_MODE | \ + BNX2_NVM_CFG1_BUFFER_MODE | \ + BNX2_NVM_CFG1_PROTECT_MODE | \ + BNX2_NVM_CFG1_FLASH_SIZE) + +struct flash_spec { + u32 strapping; + u32 config1; + u32 config2; + u32 config3; + u32 write1; + u32 buffered; + u32 page_bits; + u32 page_size; + u32 addr_mask; + u32 total_size; + u8 *name; +}; + +struct bnx2 { + /* Fields used in the tx and intr/napi performance paths are grouped */ + /* together in the beginning of the structure. */ + void __iomem *regview; + + struct net_device *dev; + struct pci_dev *pdev; + + atomic_t intr_sem; + + struct status_block *status_blk; + u32 last_status_idx; + + atomic_t tx_avail_bd; + struct tx_bd *tx_desc_ring; + struct sw_bd *tx_buf_ring; + u32 tx_prod_bseq; + u16 tx_prod; + u16 tx_cons; + +#ifdef BCM_VLAN + struct vlan_group *vlgrp; +#endif + + u32 rx_offset; + u32 rx_buf_use_size; /* useable size */ + u32 rx_buf_size; /* with alignment */ + struct rx_bd *rx_desc_ring; + struct sw_bd *rx_buf_ring; + u32 rx_prod_bseq; + u16 rx_prod; + u16 rx_cons; + + u32 rx_csum; + + /* Only used to synchronize netif_stop_queue/wake_queue when tx */ + /* ring is full */ + spinlock_t tx_lock; + + /* End of fileds used in the performance code paths. */ + + char *name; + + int timer_interval; + struct timer_list timer; + struct work_struct reset_task; + + /* Used to synchronize phy accesses. */ + spinlock_t phy_lock; + + u32 flags; +#define PCIX_FLAG 1 +#define PCI_32BIT_FLAG 2 +#define ONE_TDMA_FLAG 4 /* no longer used */ +#define NO_WOL_FLAG 8 +#define USING_DAC_FLAG 0x10 +#define USING_MSI_FLAG 0x20 + + u32 phy_flags; +#define PHY_SERDES_FLAG 1 +#define PHY_CRC_FIX_FLAG 2 +#define PHY_PARALLEL_DETECT_FLAG 4 +#define PHY_INT_MODE_MASK_FLAG 0x300 +#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 +#define PHY_INT_MODE_LINK_READY_FLAG 0x200 + + u32 chip_id; + /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */ +#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) +#define CHIP_NUM_5706 0x57060000 + +#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) +#define CHIP_REV_Ax 0x00000000 +#define CHIP_REV_Bx 0x00001000 +#define CHIP_REV_Cx 0x00002000 + +#define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0) +#define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f) + +#define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) +#define CHIP_ID_5706_A0 0x57060000 +#define CHIP_ID_5706_A1 0x57060010 + +#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) + +/* A serdes chip will have the first bit of the bond id set. */ +#define CHIP_BOND_ID_SERDES_BIT 0x01 + + u32 phy_addr; + u32 phy_id; + + u16 bus_speed_mhz; + u8 wol; + + u8 fw_timed_out; + + u16 fw_wr_seq; + u16 fw_drv_pulse_wr_seq; + + int tx_ring_size; + dma_addr_t tx_desc_mapping; + + + int rx_ring_size; + dma_addr_t rx_desc_mapping; + + u16 tx_quick_cons_trip; + u16 tx_quick_cons_trip_int; + u16 rx_quick_cons_trip; + u16 rx_quick_cons_trip_int; + u16 comp_prod_trip; + u16 comp_prod_trip_int; + u16 tx_ticks; + u16 tx_ticks_int; + u16 com_ticks; + u16 com_ticks_int; + u16 cmd_ticks; + u16 cmd_ticks_int; + u16 rx_ticks; + u16 rx_ticks_int; + + u32 stats_ticks; + + dma_addr_t status_blk_mapping; + + struct statistics_block *stats_blk; + dma_addr_t stats_blk_mapping; + + u32 rx_mode; + + u16 req_line_speed; + u8 req_duplex; + + u8 link_up; + + u16 line_speed; + u8 duplex; + u8 flow_ctrl; /* actual flow ctrl settings */ + /* may be different from */ + /* req_flow_ctrl if autoneg */ +#define FLOW_CTRL_TX 1 +#define FLOW_CTRL_RX 2 + + u32 advertising; + + u8 req_flow_ctrl; /* flow ctrl advertisement */ + /* settings or forced */ + /* settings */ + u8 autoneg; +#define AUTONEG_SPEED 1 +#define AUTONEG_FLOW_CTRL 2 + + u8 loopback; +#define MAC_LOOPBACK 1 +#define PHY_LOOPBACK 2 + + u8 serdes_an_pending; +#define SERDES_AN_TIMEOUT (2 * HZ) + + u8 mac_addr[8]; + + u32 fw_ver; + + int pm_cap; + int pcix_cap; + + struct net_device_stats net_stats; + + struct flash_spec *flash_info; +}; + +static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); +static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val); + +#define REG_RD(bp, offset) \ + readl(bp->regview + offset) + +#define REG_WR(bp, offset, val) \ + writel(val, bp->regview + offset) + +#define REG_WR16(bp, offset, val) \ + writew(val, bp->regview + offset) + +#define REG_RD_IND(bp, offset) \ + bnx2_reg_rd_ind(bp, offset) + +#define REG_WR_IND(bp, offset, val) \ + bnx2_reg_wr_ind(bp, offset, val) + +/* Indirect context access. Unlike the MBQ_WR, these macros will not + * trigger a chip event. */ +static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val); + +#define CTX_WR(bp, cid_addr, offset, val) \ + bnx2_ctx_wr(bp, cid_addr, offset, val) + +struct cpu_reg { + u32 mode; + u32 mode_value_halt; + u32 mode_value_sstep; + + u32 state; + u32 state_value_clear; + + u32 gpr0; + u32 evmask; + u32 pc; + u32 inst; + u32 bp; + + u32 spad_base; + + u32 mips_view_base; +}; + +struct fw_info { + u32 ver_major; + u32 ver_minor; + u32 ver_fix; + + u32 start_addr; + + /* Text section. */ + u32 text_addr; + u32 text_len; + u32 text_index; + u32 *text; + + /* Data section. */ + u32 data_addr; + u32 data_len; + u32 data_index; + u32 *data; + + /* SBSS section. */ + u32 sbss_addr; + u32 sbss_len; + u32 sbss_index; + u32 *sbss; + + /* BSS section. */ + u32 bss_addr; + u32 bss_len; + u32 bss_index; + u32 *bss; + + /* Read-only section. */ + u32 rodata_addr; + u32 rodata_len; + u32 rodata_index; + u32 *rodata; +}; + +#define RV2P_PROC1 0 +#define RV2P_PROC2 1 + + +/* This value (in milliseconds) determines the frequency of the driver + * issuing the PULSE message code. The firmware monitors this periodic + * pulse to determine when to switch to an OS-absent mode. */ +#define DRV_PULSE_PERIOD_MS 250 + +/* This value (in milliseconds) determines how long the driver should + * wait for an acknowledgement from the firmware before timing out. Once + * the firmware has timed out, the driver will assume there is no firmware + * running and there won't be any firmware-driver synchronization during a + * driver reset. */ +#define FW_ACK_TIME_OUT_MS 50 + + +#define BNX2_DRV_RESET_SIGNATURE 0x00000000 +#define BNX2_DRV_RESET_SIGNATURE_MAGIC 0x4841564b /* HAVK */ +//#define DRV_RESET_SIGNATURE_MAGIC 0x47495352 /* RSIG */ + +#define BNX2_DRV_MB 0x00000004 +#define BNX2_DRV_MSG_CODE 0xff000000 +#define BNX2_DRV_MSG_CODE_RESET 0x01000000 +#define BNX2_DRV_MSG_CODE_UNLOAD 0x02000000 +#define BNX2_DRV_MSG_CODE_SHUTDOWN 0x03000000 +#define BNX2_DRV_MSG_CODE_SUSPEND_WOL 0x04000000 +#define BNX2_DRV_MSG_CODE_FW_TIMEOUT 0x05000000 +#define BNX2_DRV_MSG_CODE_PULSE 0x06000000 +#define BNX2_DRV_MSG_CODE_DIAG 0x07000000 +#define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000 + +#define BNX2_DRV_MSG_DATA 0x00ff0000 +#define BNX2_DRV_MSG_DATA_WAIT0 0x00010000 +#define BNX2_DRV_MSG_DATA_WAIT1 0x00020000 +#define BNX2_DRV_MSG_DATA_WAIT2 0x00030000 +#define BNX2_DRV_MSG_DATA_WAIT3 0x00040000 + +#define BNX2_DRV_MSG_SEQ 0x0000ffff + +#define BNX2_FW_MB 0x00000008 +#define BNX2_FW_MSG_ACK 0x0000ffff +#define BNX2_FW_MSG_STATUS_MASK 0x00ff0000 +#define BNX2_FW_MSG_STATUS_OK 0x00000000 +#define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000 + +#define BNX2_LINK_STATUS 0x0000000c + +#define BNX2_DRV_PULSE_MB 0x00000010 +#define BNX2_DRV_PULSE_SEQ_MASK 0x0000ffff + +/* Indicate to the firmware not to go into the + * OS absent when it is not getting driver pulse. + * This is used for debugging. */ +#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00010000 + +#define BNX2_DEV_INFO_SIGNATURE 0x00000020 +#define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 +#define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00 +#define BNX2_DEV_INFO_FEATURE_CFG_VALID 0x01 +#define BNX2_DEV_INFO_SECONDARY_PORT 0x80 +#define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE 0x40 + +#define BNX2_SHARED_HW_CFG_PART_NUM 0x00000024 + +#define BNX2_SHARED_HW_CFG_POWER_DISSIPATED 0x00000034 +#define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK 0xff000000 +#define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK 0xff0000 +#define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK 0xff00 +#define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK 0xff + +#define BNX2_SHARED_HW_CFG POWER_CONSUMED 0x00000038 +#define BNX2_SHARED_HW_CFG_CONFIG 0x0000003c +#define BNX2_SHARED_HW_CFG_DESIGN_NIC 0 +#define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1 +#define BNX2_SHARED_HW_CFG_PHY_COPPER 0 +#define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2 +#define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8 +#define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300 +#define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0 +#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100 +#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200 + +#define BNX2_DEV_INFO_BC_REV 0x0000004c + +#define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050 +#define BNX2_PORT_HW_CFG_UPPERMAC_MASK 0xffff + +#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054 +#define BNX2_PORT_HW_CFG_CONFIG 0x00000058 + +#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068 +#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c +#define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER 0x00000070 +#define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER 0x00000074 +#define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER 0x00000078 +#define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER 0x0000007c + +#define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2 0x000000b4 + +#define BNX2_DEV_INFO_FORMAT_REV 0x000000c4 +#define BNX2_DEV_INFO_FORMAT_REV_MASK 0xff000000 +#define BNX2_DEV_INFO_FORMAT_REV_ID ('A' << 24) + +#define BNX2_SHARED_FEATURE 0x000000c8 +#define BNX2_SHARED_FEATURE_MASK 0xffffffff + +#define BNX2_PORT_FEATURE 0x000000d8 +#define BNX2_PORT2_FEATURE 0x00000014c +#define BNX2_PORT_FEATURE_WOL_ENABLED 0x01000000 +#define BNX2_PORT_FEATURE_MBA_ENABLED 0x02000000 +#define BNX2_PORT_FEATURE_ASF_ENABLED 0x04000000 +#define BNX2_PORT_FEATURE_IMD_ENABLED 0x08000000 +#define BNX2_PORT_FEATURE_BAR1_SIZE_MASK 0xf +#define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED 0x0 +#define BNX2_PORT_FEATURE_BAR1_SIZE_64K 0x1 +#define BNX2_PORT_FEATURE_BAR1_SIZE_128K 0x2 +#define BNX2_PORT_FEATURE_BAR1_SIZE_256K 0x3 +#define BNX2_PORT_FEATURE_BAR1_SIZE_512K 0x4 +#define BNX2_PORT_FEATURE_BAR1_SIZE_1M 0x5 +#define BNX2_PORT_FEATURE_BAR1_SIZE_2M 0x6 +#define BNX2_PORT_FEATURE_BAR1_SIZE_4M 0x7 +#define BNX2_PORT_FEATURE_BAR1_SIZE_8M 0x8 +#define BNX2_PORT_FEATURE_BAR1_SIZE_16M 0x9 +#define BNX2_PORT_FEATURE_BAR1_SIZE_32M 0xa +#define BNX2_PORT_FEATURE_BAR1_SIZE_64M 0xb +#define BNX2_PORT_FEATURE_BAR1_SIZE_128M 0xc +#define BNX2_PORT_FEATURE_BAR1_SIZE_256M 0xd +#define BNX2_PORT_FEATURE_BAR1_SIZE_512M 0xe +#define BNX2_PORT_FEATURE_BAR1_SIZE_1G 0xf + +#define BNX2_PORT_FEATURE_WOL 0xdc +#define BNX2_PORT2_FEATURE_WOL 0x150 +#define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS 4 +#define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK 0x30 +#define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE 0 +#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC 0x10 +#define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI 0x20 +#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x30 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK 0xf +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG 0 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF 1 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL 2 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF 5 +#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL 6 +#define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000 0x40 +#define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400 +#define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP 0x800 + +#define BNX2_PORT_FEATURE_MBA 0xe0 +#define BNX2_PORT2_FEATURE_MBA 0x154 +#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS 0 +#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x3 +#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0 +#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 1 +#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 2 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS 2 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG 0 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF 0x4 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL 0x8 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF 0xc +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL 0x10 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF 0x14 +#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL 0x18 +#define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x40 +#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S 0 +#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x80 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS 8 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0xff00 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K 0x100 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x200 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x300 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x400 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x500 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x600 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x700 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x800 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x900 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0xa00 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0xb00 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0xc00 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0xd00 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0xe00 +#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0xf00 +#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS 16 +#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0xf0000 +#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS 20 +#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x300000 +#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0 +#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x100000 +#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x200000 +#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x300000 + +#define BNX2_PORT_FEATURE_IMD 0xe4 +#define BNX2_PORT2_FEATURE_IMD 0x158 +#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT 0 +#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE 1 + +#define BNX2_PORT_FEATURE_VLAN 0xe8 +#define BNX2_PORT2_FEATURE_VLAN 0x15c +#define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff +#define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000 + +#define BNX2_BC_STATE_RESET_TYPE 0x000001c0 +#define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254 +#define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff +#define BNX2_BC_STATE_RESET_TYPE_NONE (BNX2_BC_STATE_RESET_TYPE_SIG | \ + 0x00010000) +#define BNX2_BC_STATE_RESET_TYPE_PCI (BNX2_BC_STATE_RESET_TYPE_SIG | \ + 0x00020000) +#define BNX2_BC_STATE_RESET_TYPE_VAUX (BNX2_BC_STATE_RESET_TYPE_SIG | \ + 0x00030000) +#define BNX2_BC_STATE_RESET_TYPE_DRV_MASK DRV_MSG_CODE +#define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_RESET) +#define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_UNLOAD) +#define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_SHUTDOWN) +#define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_WOL) +#define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \ + DRV_MSG_CODE_DIAG) +#define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \ + (msg)) + +#define BNX2_BC_STATE 0x000001c4 +#define BNX2_BC_STATE_ERR_MASK 0x0000ff00 +#define BNX2_BC_STATE_SIGN 0x42530000 +#define BNX2_BC_STATE_SIGN_MASK 0xffff0000 +#define BNX2_BC_STATE_BC1_START (BNX2_BC_STATE_SIGN | 0x1) +#define BNX2_BC_STATE_GET_NVM_CFG1 (BNX2_BC_STATE_SIGN | 0x2) +#define BNX2_BC_STATE_PROG_BAR (BNX2_BC_STATE_SIGN | 0x3) +#define BNX2_BC_STATE_INIT_VID (BNX2_BC_STATE_SIGN | 0x4) +#define BNX2_BC_STATE_GET_NVM_CFG2 (BNX2_BC_STATE_SIGN | 0x5) +#define BNX2_BC_STATE_APPLY_WKARND (BNX2_BC_STATE_SIGN | 0x6) +#define BNX2_BC_STATE_LOAD_BC2 (BNX2_BC_STATE_SIGN | 0x7) +#define BNX2_BC_STATE_GOING_BC2 (BNX2_BC_STATE_SIGN | 0x8) +#define BNX2_BC_STATE_GOING_DIAG (BNX2_BC_STATE_SIGN | 0x9) +#define BNX2_BC_STATE_RT_FINAL_INIT (BNX2_BC_STATE_SIGN | 0x81) +#define BNX2_BC_STATE_RT_WKARND (BNX2_BC_STATE_SIGN | 0x82) +#define BNX2_BC_STATE_RT_DRV_PULSE (BNX2_BC_STATE_SIGN | 0x83) +#define BNX2_BC_STATE_RT_FIOEVTS (BNX2_BC_STATE_SIGN | 0x84) +#define BNX2_BC_STATE_RT_DRV_CMD (BNX2_BC_STATE_SIGN | 0x85) +#define BNX2_BC_STATE_RT_LOW_POWER (BNX2_BC_STATE_SIGN | 0x86) +#define BNX2_BC_STATE_RT_SET_WOL (BNX2_BC_STATE_SIGN | 0x87) +#define BNX2_BC_STATE_RT_OTHER_FW (BNX2_BC_STATE_SIGN | 0x88) +#define BNX2_BC_STATE_RT_GOING_D3 (BNX2_BC_STATE_SIGN | 0x89) +#define BNX2_BC_STATE_ERR_BAD_VERSION (BNX2_BC_STATE_SIGN | 0x0100) +#define BNX2_BC_STATE_ERR_BAD_BC2_CRC (BNX2_BC_STATE_SIGN | 0x0200) +#define BNX2_BC_STATE_ERR_BC1_LOOP (BNX2_BC_STATE_SIGN | 0x0300) +#define BNX2_BC_STATE_ERR_UNKNOWN_CMD (BNX2_BC_STATE_SIGN | 0x0400) +#define BNX2_BC_STATE_ERR_DRV_DEAD (BNX2_BC_STATE_SIGN | 0x0500) +#define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600) +#define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700) + +#define BNX2_BC_STATE_DEBUG_CMD 0x1dc +#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000 +#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000 +#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff +#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff + +#define HOST_VIEW_SHMEM_BASE 0x167c00 + +#endif diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h new file mode 100644 index 0000000..35f3a2a --- /dev/null +++ b/drivers/net/bnx2_fw.h @@ -0,0 +1,2468 @@ +/* bnx2_fw.h: Broadcom NX2 network driver. + * + * Copyright (c) 2004, 2005 Broadcom Corporation + * + * 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, except as noted below. + * + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2004, 2005 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + */ + + +static int bnx2_COM_b06FwReleaseMajor = 0x0; +static int bnx2_COM_b06FwReleaseMinor = 0x0; +static int bnx2_COM_b06FwReleaseFix = 0x0; +static u32 bnx2_COM_b06FwStartAddr = 0x080004a0; +static u32 bnx2_COM_b06FwTextAddr = 0x08000000; +static int bnx2_COM_b06FwTextLen = 0x4594; +static u32 bnx2_COM_b06FwDataAddr = 0x080045e0; +static int bnx2_COM_b06FwDataLen = 0x0; +static u32 bnx2_COM_b06FwRodataAddr = 0x08004598; +static int bnx2_COM_b06FwRodataLen = 0x18; +static u32 bnx2_COM_b06FwBssAddr = 0x08004600; +static int bnx2_COM_b06FwBssLen = 0x88; +static u32 bnx2_COM_b06FwSbssAddr = 0x080045e0; +static int bnx2_COM_b06FwSbssLen = 0x1c; +static u32 bnx2_COM_b06FwText[(0x4594/4) + 1] = { + 0x0a000128, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x302e362e, + 0x39000000, 0x00060902, 0x00000000, 0x00000003, 0x00000014, 0x00000032, + 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000002, 0x00000020, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, + 0x0000000d, 0x3c020800, 0x244245e0, 0x3c030800, 0x24634688, 0xac400000, + 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, + 0x3c100800, 0x261004a0, 0x3c1c0800, 0x279c45e0, 0x0e0001f2, 0x00000000, + 0x0000000d, 0x27bdffe8, 0x3c1a8000, 0x3c020008, 0x0342d825, 0x3c036010, + 0xafbf0010, 0x8c655000, 0x3c020800, 0x24470ac8, 0x3c040800, 0x24864600, + 0x2402ff7f, 0x00a22824, 0x34a5380c, 0xac655000, 0x00002821, 0x24020037, + 0x24030c80, 0xaf420008, 0xaf430024, 0xacc70000, 0x24a50001, 0x2ca20016, + 0x1440fffc, 0x24c60004, 0x24844600, 0x3c020800, 0x24420ad4, 0x3c030800, + 0x246309d4, 0xac820004, 0x3c020800, 0x24420618, 0x3c050800, 0x24a50ca0, + 0xac82000c, 0x3c020800, 0x24423100, 0xac830008, 0x3c030800, 0x246325c8, + 0xac820014, 0x3c020800, 0x24422b0c, 0xac830018, 0xac83001c, 0x3c030800, + 0x24630adc, 0xac820024, 0x3c020800, 0x24423040, 0xac83002c, 0x3c030800, + 0x24633060, 0xac820030, 0x3c020800, 0x24422f6c, 0xac830034, 0x3c030800, + 0x24632c60, 0xac82003c, 0x3c020800, 0x24420b6c, 0xac850010, 0xac850020, + 0xac830040, 0x0e000bd6, 0xac820050, 0x8fbf0010, 0x03e00008, 0x27bd0018, + 0x27bdffe0, 0xafb00010, 0x27500100, 0xafbf0018, 0xafb10014, 0x9203000b, + 0x24020003, 0x1462005b, 0x96110008, 0x32220001, 0x10400009, 0x27430080, + 0x8e020000, 0x96040014, 0x000211c2, 0x00021040, 0x00621821, 0xa4640000, + 0x0a0001cb, 0x3c020800, 0x3c020800, 0x8c430020, 0x1060002a, 0x3c030800, + 0x0e001006, 0x00000000, 0x97420108, 0x8f850018, 0x9743010c, 0x3042003e, + 0x00021400, 0x00621825, 0xaca30000, 0x8f840018, 0x8f420100, 0xac820004, + 0x97430116, 0x9742010e, 0x8f840018, 0x00031c00, 0x00431025, 0xac820008, + 0x97430110, 0x97440112, 0x8f850018, 0x00031c00, 0x00832025, 0xaca4000c, + 0x97420114, 0x8f840018, 0x3042ffff, 0xac820010, 0x8f830018, 0xac600014, + 0x8f820018, 0x3c030800, 0xac400018, 0x9462466e, 0x8f840018, 0x3c032000, + 0x00431025, 0xac82001c, 0x0e001044, 0x24040001, 0x3c030800, 0x8c620040, + 0x24420001, 0xac620040, 0x3c020800, 0x8c430044, 0x32240004, 0x24630001, + 0x10800017, 0xac430044, 0x8f4202b8, 0x04430007, 0x8e020020, 0x3c040800, + 0x8c830060, 0x24020001, 0x24630001, 0x0a0001ed, 0xac830060, 0x3c060800, + 0x8cc4005c, 0xaf420280, 0x96030016, 0x00001021, 0xa7430284, 0x8e050004, + 0x24840001, 0x3c031000, 0xaf450288, 0xaf4302b8, 0x0a0001ed, 0xacc4005c, + 0x32220002, 0x0a0001ed, 0x0002102b, 0x3c026000, 0xac400808, 0x0000000d, + 0x00001021, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, + 0x27bdffc8, 0xafbf0034, 0xafbe0030, 0xafb7002c, 0xafb60028, 0xafb50024, + 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0x0e00013f, 0xafb00010, + 0x24110020, 0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, + 0x3c170800, 0x3c160800, 0x8f820004, 0x3c040800, 0x8c830020, 0x10430004, + 0x00000000, 0xaf830004, 0x0e00110b, 0x00000000, 0x8f500000, 0x32020007, + 0x1040fff5, 0x32020001, 0x1040002b, 0x32020002, 0x8f420100, 0xaf420020, + 0x8f430104, 0xaf4300a8, 0x9342010b, 0x93630000, 0x306300ff, 0x10710005, + 0x304400ff, 0x10750006, 0x2c820016, 0x0a000227, 0x00000000, 0xaf940000, + 0x0a000228, 0x2c820016, 0xaf930000, 0x0a000228, 0x00000000, 0xaf800000, + 0x14400005, 0x00041880, 0x0e0002b2, 0x00000000, 0x0a000234, 0x00000000, + 0x3c020800, 0x24424600, 0x00621821, 0x8c620000, 0x0040f809, 0x00000000, + 0x10400005, 0x8fc20034, 0x8f420104, 0x3c016020, 0xac220014, 0x8fc20034, + 0xaf520138, 0x24420001, 0xafc20034, 0x32020002, 0x10400019, 0x32020004, + 0x8f420140, 0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, + 0x10750006, 0x00000000, 0x0a000250, 0x00000000, 0xaf940000, 0x0a000251, + 0x00000000, 0xaf930000, 0x0a000251, 0x00000000, 0xaf800000, 0x0e0008b9, + 0x00000000, 0x8ee20038, 0xaf520178, 0x24420001, 0xaee20038, 0x32020004, + 0x1040ffad, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff, + 0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a00026a, 0x00000000, + 0xaf940000, 0x0a00026b, 0x00000000, 0xaf930000, 0x0a00026b, 0x00000000, + 0xaf800000, 0x93620000, 0x14510004, 0x8ec2003c, 0x0e000835, 0x00000000, + 0x8ec2003c, 0xaf5201b8, 0x24420001, 0x0a000206, 0xaec2003c, 0x27bdffe8, + 0xafbf0010, 0x97420108, 0x24033000, 0x30447000, 0x10830012, 0x28823001, + 0x10400007, 0x24024000, 0x1080000b, 0x24022000, 0x1082001a, 0x24020001, + 0x0a000299, 0x00000000, 0x1082000c, 0x24025000, 0x1082000e, 0x00000000, + 0x0a000299, 0x00000000, 0x0000000d, 0x0a00029b, 0x00001021, 0x0e000300, + 0x00000000, 0x0a00029b, 0x00001021, 0x0e00048f, 0x00000000, 0x0a00029b, + 0x00001021, 0x0e000fdf, 0x00000000, 0x0a00029b, 0x00001021, 0x0000000d, + 0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020, + 0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0002af, + 0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008, + 0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000, + 0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100, + 0x94830008, 0x30620004, 0x10400017, 0x30620002, 0x8f4202b8, 0x04430007, + 0x8c820020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, 0x03e00008, + 0xac830060, 0xaf420280, 0x94830016, 0x3c060800, 0xa7430284, 0x8c850004, + 0x8cc4005c, 0x00001021, 0x3c031000, 0x24840001, 0xaf450288, 0xaf4302b8, + 0x03e00008, 0xacc4005c, 0x14400003, 0x3c040800, 0x03e00008, 0x00001021, + 0x8c830084, 0x24020001, 0x24630001, 0x03e00008, 0xac830084, 0x27450100, + 0x3c040800, 0x8c820088, 0x94a3000c, 0x24420001, 0x007a1821, 0xac820088, + 0x8ca40018, 0x90664000, 0xaf440038, 0x8ca2001c, 0x2403fff8, 0x00063600, + 0x00431024, 0x34420004, 0x3c030005, 0xaf42003c, 0xaf430030, 0x00000000, + 0x00000000, 0x00000000, 0xaf460404, 0x00000000, 0x00000000, 0x00000000, + 0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, + 0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000, + 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e, + 0xafbf0014, 0x0e001006, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000, + 0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, + 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, + 0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, + 0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, + 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffc8, 0xafb3001c, + 0x00009821, 0xafb7002c, 0x0000b821, 0xafbe0030, 0x0000f021, 0xafb50024, + 0x27550100, 0xafbf0034, 0xafb60028, 0xafb40020, 0xafb20018, 0xafb10014, + 0xafb00010, 0x96a20008, 0x8f540100, 0x8eb20018, 0x30420001, 0x10400037, + 0x02a0b021, 0x8f630054, 0x2642ffff, 0x00431023, 0x18400006, 0x00000000, + 0x0000000d, 0x00000000, 0x24000128, 0x0a000372, 0x00002021, 0x8f62004c, + 0x02421023, 0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, + 0x8c62008c, 0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, + 0xac62008c, 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, + 0x30420001, 0x00021023, 0x30420005, 0x0a000372, 0x34440004, 0x27660100, + 0x00041080, 0x00c21021, 0x8c430000, 0x02431823, 0x04600004, 0x24820001, + 0x30440007, 0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, + 0x8c620094, 0x24040005, 0x24420001, 0x0a000372, 0xac620094, 0x24040004, + 0x00809821, 0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, + 0x2c420001, 0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, + 0x38820014, 0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, + 0x14820002, 0x00001021, 0x24020001, 0x50400007, 0x8eb10020, 0x8ea20020, + 0x8f630040, 0x00408821, 0x00431023, 0x5c400001, 0x8f710040, 0x9343010b, + 0x24020004, 0x54620005, 0x36730080, 0x96a20008, 0x36730002, 0x24170001, + 0x305e0020, 0x2402fffb, 0x02628024, 0x1200002a, 0x3c030800, 0x8c620030, + 0x02021024, 0x10400026, 0x3c020800, 0x8c430020, 0x10600024, 0x32620004, + 0x0e001006, 0x00000000, 0x8f830018, 0x8f420100, 0xac620000, 0x8f840018, + 0x02201821, 0x32620002, 0xac900004, 0x8f840018, 0x50400001, 0x8ec30014, + 0xac830008, 0x8f830018, 0x8ec20020, 0xac62000c, 0x8f840018, 0x8f620040, + 0xac820010, 0x8f830018, 0x8ec20018, 0xac620014, 0x8f840018, 0x3c026000, + 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c024010, + 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x32620004, 0x10400076, + 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, 0x02821025, 0xa360007c, + 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, + 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, + 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, + 0x93620023, 0x3042007f, 0xa3620023, 0xaf720064, 0x3c023fff, 0x0a0003f1, + 0x3442ffff, 0x8f62005c, 0x02421023, 0x04400011, 0x00000000, 0x8f65005c, + 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf720064, 0x00a32823, + 0x00852821, 0x0045102b, 0x10400004, 0x02451021, 0x3c053fff, 0x34a5ffff, + 0x02451021, 0xaf62005c, 0x24070001, 0xaf72004c, 0x8f620054, 0x16420005, + 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, + 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, + 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, + 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, + 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, + 0x02821025, 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, + 0x00000000, 0x0e000f2a, 0x00000000, 0x00403821, 0x10e00017, 0x3c029000, + 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, + 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02821025, + 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, + 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x8ea30014, 0x8f620040, + 0x14430003, 0x00431023, 0x0a000443, 0x00001021, 0x28420001, 0x10400034, + 0x00000000, 0x8f620040, 0xaf630040, 0x9362003e, 0x30420001, 0x1440000b, + 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022, 0x3c020800, + 0x8c440098, 0x0064182b, 0x1460001e, 0x3c020800, 0x3c029000, 0x34420001, + 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, 0x02831825, + 0x34420001, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, + 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0x24020001, 0xaf4301f8, + 0xa7620012, 0x0a000476, 0xa3600022, 0x9743007a, 0x9444002a, 0x00641821, + 0x3063fffe, 0xa7630012, 0x0e000b68, 0x00000000, 0x12e00003, 0x00000000, + 0x0e000f27, 0x00000000, 0x53c00004, 0x96a20008, 0x0e000c10, 0x00000000, + 0x96a20008, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028, 0x8fb50024, + 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, + 0x30420001, 0x03e00008, 0x27bd0038, 0x27bdffe8, 0xafbf0010, 0x97420108, + 0x2403000b, 0x304400ff, 0x1083004e, 0x2882000c, 0x10400011, 0x24020006, + 0x1082003e, 0x28820007, 0x10400007, 0x28820008, 0x1080002b, 0x24020001, + 0x1082002e, 0x3c026000, 0x0a000504, 0x00000000, 0x14400061, 0x2882000a, + 0x1440002b, 0x00000000, 0x0a0004ec, 0x00000000, 0x2402001c, 0x1082004e, + 0x2882001d, 0x1040000e, 0x24020019, 0x10820041, 0x2882001a, 0x10400005, + 0x2402000e, 0x10820036, 0x00000000, 0x0a000504, 0x00000000, 0x2402001b, + 0x1082003c, 0x00000000, 0x0a000504, 0x00000000, 0x240200c1, 0x10820040, + 0x288200c2, 0x10400005, 0x24020080, 0x1082001f, 0x00000000, 0x0a000504, + 0x00000000, 0x240200c2, 0x1082003b, 0x00000000, 0x0a000504, 0x00000000, + 0x3c026000, 0x0e000c7d, 0xac400808, 0x0a000506, 0x8fbf0010, 0x8c444448, + 0x3c030800, 0xac640064, 0x0e000c7d, 0x00000000, 0x3c026000, 0x8c444448, + 0x3c030800, 0x0a000505, 0xac640068, 0x8f440100, 0x0e000508, 0x00000000, + 0x3c026000, 0x8c444448, 0x3c030800, 0x0a000505, 0xac64006c, 0x0e000cab, + 0x00000000, 0x0a000506, 0x8fbf0010, 0x8f440100, 0x0e000cd5, 0x00000000, + 0x0a000506, 0x8fbf0010, 0x0e000d1c, 0x00000000, 0x0a000506, 0x8fbf0010, + 0x0000000d, 0x0a000506, 0x8fbf0010, 0x0e0005d7, 0x00000000, 0x0a000506, + 0x8fbf0010, 0x8f440100, 0x0e000d7e, 0x00000000, 0x0a000506, 0x8fbf0010, + 0x0e000e95, 0x00000000, 0x0a000506, 0x8fbf0010, 0x0e000626, 0x00000000, + 0x0a000506, 0x8fbf0010, 0x0e000b68, 0x00000000, 0x0a000506, 0x8fbf0010, + 0x0000000d, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0x3c029000, + 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000, 0xafbf0014, + 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, + 0x34420001, 0xa3620005, 0x8f63004c, 0x8f620054, 0x10620019, 0x3c028000, + 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, + 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, + 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, + 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, + 0x34420001, 0x02021025, 0x0e000c7d, 0xaf420020, 0x3c029000, 0x34420001, + 0x3c038000, 0x02021025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, + 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02021025, 0xa363007d, + 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x8fbf0014, 0xaf5001c0, + 0x8fb00010, 0x24020002, 0x3c031000, 0xa34201c4, 0xaf4301f8, 0x03e00008, + 0x27bd0018, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014, + 0xafb00010, 0x93630005, 0x00809021, 0x24020030, 0x30630030, 0x14620072, + 0x00a09821, 0x3c020800, 0x8c430020, 0x1060006c, 0x00000000, 0x0e001006, + 0x00000000, 0x8f820018, 0xac520000, 0x9363003e, 0x9362003f, 0x8f840018, + 0x00031a00, 0x00431025, 0xac820004, 0x93630081, 0x93620082, 0x8f850018, + 0x00031e00, 0x00021400, 0x00621825, 0xaca30008, 0x8f840018, 0x8f620040, + 0xac82000c, 0x8f830018, 0x8f620048, 0xac620010, 0x8f840018, 0x8f62004c, + 0x3c110800, 0xac820014, 0x8f830018, 0x8f620050, 0x26304660, 0x00002021, + 0xac620018, 0x9602000e, 0x8f850018, 0x3c03c00b, 0x00431025, 0x0e001044, + 0xaca2001c, 0x8f830018, 0x8f620054, 0xac620000, 0x8f840018, 0x8f620058, + 0xac820004, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f840018, 0x8f620060, + 0xac82000c, 0x8f850018, 0x8f620064, 0xaca20010, 0x97630068, 0x9762006a, + 0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f830018, 0x00002021, + 0xac600018, 0x9602000e, 0x8f850018, 0x3c03c00c, 0x00431025, 0x0e001044, + 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000, 0x936200c4, 0x30420002, + 0x10400006, 0x00000000, 0x976200c8, 0x8f830018, 0x3042ffff, 0x0a0005b5, + 0xac620004, 0x8f820018, 0xac400004, 0x8f830018, 0x8f62006c, 0xac620008, + 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018, 0xac600010, 0x93620005, + 0x8f830018, 0x00021600, 0x00531025, 0xac620014, 0x8f850018, 0x3c026000, + 0x8c434448, 0x24040001, 0x26224660, 0xaca30018, 0x9443000e, 0x8f850018, + 0x3c02400d, 0x00621825, 0x0e001044, 0xaca3001c, 0x0e000d48, 0x02402021, + 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, + 0x27bd0028, 0x27bdffe0, 0xafb00010, 0x27500100, 0xafbf0018, 0xafb10014, + 0x9603000c, 0x240200c1, 0x5462001d, 0x8e040000, 0x3c029000, 0x8f440100, + 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, 0x8f420020, 0x00431024, + 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, 0x34630001, 0x3c058000, + 0x00831825, 0x34420004, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00451024, + 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, 0xa34201c4, 0xaf4301f8, + 0x0a000622, 0x8fbf0018, 0x8f65004c, 0x24060001, 0x0e000db5, 0x2407049f, + 0x3c020800, 0x8c430020, 0x9611000c, 0x1060001d, 0x8e100000, 0x0e001006, + 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x00111400, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f840018, 0x240204a2, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, + 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, + 0x00621825, 0x0e001044, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, + 0x03e00008, 0x27bd0020, 0x27bdffb0, 0xafb1002c, 0x27510100, 0xafbf004c, + 0xafbe0048, 0xafb70044, 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, + 0xafb20030, 0xafb00028, 0x8e350000, 0x9634000c, 0x3c026000, 0x8c434448, + 0x0000f021, 0xaf630170, 0x8f620040, 0x8e230014, 0x0000b821, 0x00431023, + 0x044001ec, 0x0000b021, 0x32820010, 0x1040002e, 0x3c026000, 0x9363003f, + 0x9222000e, 0x10430006, 0x2402000c, 0x9223000f, 0x10620003, 0x24020014, + 0x14620025, 0x3c026000, 0x32820004, 0x10400007, 0x241e0001, 0x8f620050, + 0x24420001, 0xaf620050, 0x8f630054, 0x24630001, 0xaf630054, 0x32830102, + 0x24020002, 0x5462000d, 0x9222000f, 0x8f620040, 0x24420001, 0xaf620040, + 0x8f630048, 0x8f620040, 0x24630001, 0x54620005, 0x9222000f, 0x8f620048, + 0x24420001, 0xaf620048, 0x9222000f, 0xa362003f, 0x9223000f, 0x24020012, + 0x14620007, 0x3c026000, 0x3c030800, 0x8c620074, 0x24420001, 0x0e000f6e, + 0xac620074, 0x3c026000, 0x8c434448, 0x32820040, 0xaf630174, 0x32830020, + 0xafa30010, 0x32830080, 0xafa30014, 0x32830001, 0xafa3001c, 0x32830008, + 0xafa30020, 0x32830100, 0x104000bb, 0xafa30018, 0x8e260010, 0x8f630054, + 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000, + 0x24000128, 0x0a0006b2, 0x00009021, 0x8f62004c, 0x00c21023, 0x18400028, + 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, + 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c, 0x3c040800, + 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023, + 0x30420005, 0x0a0006b2, 0x34520004, 0x27670100, 0x00041080, 0x00e21021, + 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, + 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24120005, + 0x24420001, 0x0a0006b2, 0xac620094, 0x24120004, 0x32420001, 0x10400020, + 0x3c020800, 0x8c430020, 0x8e300000, 0x1060001c, 0x8e330010, 0x0e001006, + 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024010, 0x00621825, + 0x0e001044, 0xaca3001c, 0x32420004, 0x10400060, 0x00003821, 0x3c029000, + 0x8e260010, 0x34420001, 0x3c038000, 0x02a21025, 0xa360007c, 0xaf420020, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x30420080, + 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, + 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, + 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff, 0x0a000702, 0x3442ffff, + 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, + 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064, 0x00a32823, 0x00852821, + 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff, 0x34a5ffff, 0x00c51021, + 0xaf62005c, 0x24070001, 0xaf66004c, 0x8f620054, 0x14c20005, 0x00000000, + 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, 0x00022880, + 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, + 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, + 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, + 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, 0x02a21025, + 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620005, 0x00e0b021, + 0x0e000f2a, 0x00000000, 0x00403821, 0x00e0b021, 0x8fa20010, 0x10400008, + 0x00000000, 0x8e220018, 0xaf620018, 0x8e23001c, 0xaf63001c, 0x8e220020, + 0x24160001, 0xaf620058, 0x13c00036, 0x32820004, 0x10400035, 0x8fa30014, + 0x93620023, 0x30420040, 0x10400031, 0x3c020800, 0x8c430020, 0x1060001c, + 0x8e300000, 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018, + 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, + 0xac400010, 0x8f830018, 0x24020587, 0xac620014, 0x8f850018, 0x3c026000, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, + 0x3c024019, 0x00621825, 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, + 0x02a21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001, 0x02a21025, + 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30014, 0x10600012, 0x8fa3001c, + 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a, 0x1462000b, + 0x8fa3001c, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b, 0x14400005, + 0x8fa3001c, 0x0e000f2a, 0x00000000, 0x02c2b025, 0x8fa3001c, 0x3062ffff, + 0x10400003, 0x32820200, 0x0a000793, 0x24170004, 0x10400003, 0x00000000, + 0x24170040, 0x24160001, 0x13c0005d, 0x32820002, 0x1040005c, 0x8fa20020, + 0x9222000a, 0x30420020, 0x10400033, 0x3c100800, 0x93620023, 0x30420040, + 0x1040002f, 0x8e020020, 0x1040001e, 0x3c029000, 0x0e001006, 0x00000000, + 0x8f820018, 0xac550000, 0x8f840018, 0x3c02008d, 0xac820004, 0x8f830018, + 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, + 0x240205bf, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, 0x00621825, + 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, 0x02a21025, 0xaf420020, + 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023, + 0x3c028000, 0x34420001, 0x02a21025, 0x306300bf, 0xa3630023, 0xaf420020, + 0x8e020020, 0x10400023, 0x8fa20020, 0x0e001006, 0x00000000, 0x8f840018, + 0x8e230000, 0xac830000, 0x9222000a, 0x8f830018, 0x00021600, 0xac620004, + 0x8f840018, 0x8f620040, 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, + 0x9362003f, 0x8f840018, 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, + 0xac600014, 0x8f850018, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, + 0x9443466e, 0x8f850018, 0x3c02401a, 0x00621825, 0x0e001044, 0xaca3001c, + 0x8fa20020, 0x1040000e, 0x8fa20018, 0x9222000a, 0xa3620082, 0x56e00005, + 0x36f70008, 0x8fa30018, 0x10600004, 0x00000000, 0x36f70008, 0x0a000801, + 0x24160001, 0x0e000de1, 0x02a02021, 0x8fa20018, 0x10400003, 0x00000000, + 0x36f70010, 0x24160001, 0x12c00019, 0x3c029000, 0x34420001, 0x02a21025, + 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, + 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, 0x02a31825, 0x02e21025, + 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, + 0x3c031000, 0xaf5501c0, 0xa34201c4, 0xaf4301f8, 0x9363003f, 0x24020012, + 0x14620004, 0x3c026000, 0x0e000f6e, 0x00000000, 0x3c026000, 0x8c434448, + 0xaf630178, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c, + 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008, + 0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184, + 0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824, + 0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b, + 0x3c020100, 0x1062000d, 0x00000000, 0x0a0008b4, 0x00000000, 0x10620027, + 0x3c020400, 0x1062003e, 0x02002021, 0x0a0008b4, 0x00000000, 0x0e000e1e, + 0x02002021, 0x0a0008b6, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e, + 0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, + 0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005, + 0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000553, + 0x24055854, 0x0a0008b6, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f, + 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, + 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c048000, 0x3c030800, + 0x304200fe, 0xa3620005, 0x8c620020, 0x34840001, 0x02042025, 0xaf440020, + 0x1040002d, 0x8fbf0014, 0x0a000894, 0x00000000, 0x00002821, 0x00003021, + 0x0e000f78, 0x240706a4, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014, + 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, + 0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008, + 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, + 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, + 0x9443466e, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e001044, 0xaca3001c, + 0x0a0008b6, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008, + 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93420148, 0x2444ffff, 0x2c830005, + 0x10600047, 0x3c020800, 0x24424598, 0x00041880, 0x00621821, 0x8c640000, + 0x00800008, 0x00000000, 0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, + 0xaf62000c, 0x0e000909, 0x00000000, 0x0a000907, 0x8fbf0010, 0x8f62000c, + 0x0a000900, 0x00000000, 0x97630010, 0x8f420144, 0x14430006, 0x24020001, + 0xa7620010, 0x0e000eeb, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620010, + 0x0a000900, 0x00000000, 0x97630012, 0x8f420144, 0x14430006, 0x24020001, + 0xa7620012, 0x0e000f06, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620012, + 0x0a000900, 0x00000000, 0x97630014, 0x8f420144, 0x14430006, 0x24020001, + 0xa7620014, 0x0e000f21, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620014, + 0x0a000900, 0x00000000, 0x97630016, 0x8f420144, 0x14430006, 0x24020001, + 0xa7620016, 0x0e000f24, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620016, + 0x14400006, 0x8fbf0010, 0x3c030800, 0x8c620070, 0x24420001, 0xac620070, + 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93620081, + 0x3c030800, 0x8c640048, 0x0044102b, 0x14400028, 0x3c029000, 0x8f460140, + 0x34420001, 0x3c038000, 0x00c21025, 0xaf420020, 0x8f420020, 0x00431024, + 0x1440fffd, 0x3c048000, 0x34840001, 0x3c059000, 0x34a50001, 0x3c078000, + 0x24020012, 0x24030080, 0x00c42025, 0x00c52825, 0xa362003f, 0xa3630082, + 0xaf440020, 0xaf450020, 0x8f420020, 0x00471024, 0x1440fffd, 0x3c038000, + 0x9362007d, 0x34630001, 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, + 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, + 0x0a00096d, 0xaf4601c0, 0x93620081, 0x24420001, 0x0e000f2a, 0xa3620081, + 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001, 0x97630068, + 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, + 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, + 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, + 0x10e0001a, 0x3c029000, 0x8f440140, 0x34420001, 0x3c038000, 0x00821025, + 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, + 0x9362007d, 0x34630001, 0x3c058000, 0x00831825, 0x34420004, 0xa362007d, + 0xaf430020, 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, + 0xaf4401c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, + 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024, 0xafb40020, 0xafb20018, + 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800, 0x8f520100, 0x30420001, + 0x104000cf, 0x00000000, 0x8e700018, 0x8f630054, 0x2602ffff, 0x00431023, + 0x18400006, 0x00000000, 0x0000000d, 0x00000000, 0x24000128, 0x0a0009b6, + 0x00008821, 0x8f62004c, 0x02021023, 0x18400028, 0x00008821, 0x93650120, + 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, 0x24420001, 0x30a500ff, + 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800, 0x8c830090, 0x24630001, + 0xac830090, 0x93620122, 0x30420001, 0x00021023, 0x30420005, 0x0a0009b6, + 0x34510004, 0x27660100, 0x00041080, 0x00c21021, 0x8c430000, 0x02031823, + 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, 0x00041080, 0x10870007, + 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005, 0x24420001, 0x0a0009b6, + 0xac620094, 0x24110004, 0x32220001, 0x1040001e, 0x8e820020, 0x1040001d, + 0x32220004, 0x0e001006, 0x00000000, 0x8f820018, 0xac520000, 0x8f840018, + 0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, + 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, + 0x3c024010, 0x00621825, 0x0e001044, 0xaca3001c, 0x32220004, 0x10400076, + 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, 0x02421025, 0xa360007c, + 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, + 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, + 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, + 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064, 0x3c023fff, 0x0a000a03, + 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011, 0x00000000, 0x8f65005c, + 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf700064, 0x00a32823, + 0x00852821, 0x0045102b, 0x10400004, 0x02051021, 0x3c053fff, 0x34a5ffff, + 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c, 0x8f620054, 0x16020005, + 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, + 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, + 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, + 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, + 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, + 0x02421025, 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, + 0x00000000, 0x0e000f2a, 0x00000000, 0x00403821, 0x10e00017, 0x3c029000, + 0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, + 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02421025, + 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, + 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b, 0x8e830020, + 0x27500100, 0x38420006, 0x10600029, 0x2c510001, 0x0e001006, 0x00000000, + 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x96020008, 0xac820004, + 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018, 0x3c026000, 0x8c434448, + 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f850018, 0x8e030020, + 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400, 0x00431025, + 0xac820018, 0x12200005, 0x3c020800, 0x9443466e, 0x8f840018, 0x0a000a78, + 0x3c024013, 0x9443466e, 0x8f840018, 0x3c024014, 0x00621825, 0xac83001c, + 0x0e001044, 0x24040001, 0x8e630014, 0x8f620040, 0x14430003, 0x00431023, + 0x0a000a83, 0x00001021, 0x28420001, 0x10400034, 0x00000000, 0x8f620040, + 0xaf630040, 0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, + 0x24420001, 0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, + 0x1460001e, 0x3c020800, 0x3c029000, 0x34420001, 0x02421025, 0xaf420020, + 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, + 0x9362007d, 0x34630001, 0x3c048000, 0x02431825, 0x34420001, 0xa362007d, + 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, + 0xaf5201c0, 0xa34201c4, 0x24020001, 0xaf4301f8, 0xa7620012, 0x0a000ab6, + 0xa3600022, 0x9743007a, 0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, + 0x0e000b68, 0x00000000, 0x97420108, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, + 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, 0x30420001, 0x03e00008, + 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800, 0x8e420020, 0xafb00010, + 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014, 0x0e001006, 0x00000000, + 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1, 0x936200c5, 0x8f850018, + 0x00031e00, 0x00021400, 0x34420100, 0x00621825, 0xaca30004, 0x8f840018, + 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048, 0xac62000c, 0x8f840018, + 0x96020012, 0xac820010, 0x8f830018, 0x8f620040, 0x24040001, 0xac620014, + 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, 0x24514660, 0xaca30018, + 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825, 0x0e001044, 0xaca3001c, + 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, + 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018, 0xac600004, + 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, + 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, + 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015, 0x00431025, 0x0e001044, + 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, + 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018, 0x3c120800, 0x8e420020, + 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041, 0xafb10014, 0x0e001006, + 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x24020100, + 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008, 0x8f840018, 0x8e020018, + 0xac82000c, 0x8f830018, 0x96020012, 0xac620010, 0x8f840018, 0x96020008, + 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, + 0x24514660, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024017, 0x00621825, + 0x0e001044, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, + 0x1040001a, 0x8e100000, 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, + 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, + 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000, + 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015, + 0x00431025, 0x0e001044, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, + 0x936200c4, 0x30420002, 0x10400019, 0x00000000, 0x936200c5, 0x936300b1, + 0x00431023, 0x304400ff, 0x30830080, 0x10600004, 0x00000000, 0x0000000d, + 0x00000000, 0x24000a6a, 0x93620004, 0x00441023, 0x304400ff, 0x30830080, + 0x10600004, 0x2482ffff, 0x8f650024, 0x0a000b82, 0x00000000, 0x00022b00, + 0x8f620024, 0x0045102b, 0x10400002, 0x00000000, 0x8f650024, 0x8f620048, + 0x8f630040, 0x00431823, 0x0065202b, 0x10800004, 0x00000000, 0x8f620040, + 0x00451021, 0xaf620048, 0x9762003c, 0x0062102b, 0x10400041, 0x8fbf0010, + 0x10a0003f, 0x3c029000, 0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, + 0x3c068000, 0x24630001, 0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, + 0x00461024, 0x1440fffd, 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, + 0x00a31825, 0x34420004, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, + 0x1440fffd, 0x24020002, 0x3c030800, 0xaf4501c0, 0xa34201c4, 0x8c640020, + 0x3c021000, 0xaf4201f8, 0x1080001f, 0x8fbf0010, 0x0e001006, 0x00000000, + 0x8f830018, 0x8f420100, 0xac620000, 0x8f840018, 0x8f620040, 0xac820004, + 0x8f850018, 0x8f620048, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, + 0xac400010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, + 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c0240c2, 0x00621825, + 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, + 0x3c020800, 0x24423958, 0xaf82000c, 0x03e00008, 0x00000000, 0x27bdffe8, + 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003, 0x3c020800, + 0x0000000d, 0x3c020800, 0x8c430020, 0x10600026, 0x00001021, 0x0e001006, + 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x8e02001c, + 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018, 0xac82000c, + 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c106000, 0xac600014, + 0x8f840018, 0x8e024448, 0x3c030800, 0xac820018, 0x9462466e, 0x8f840018, + 0x3c034012, 0x00431025, 0xac82001c, 0x0e001044, 0x24040001, 0x8e036800, + 0x00001021, 0x3c040001, 0x00641825, 0xae036800, 0x0a000c0d, 0x8fbf0014, + 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x97430078, + 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008, 0xa7630010, + 0x27450100, 0x8f640048, 0x8ca30018, 0x00641023, 0x18400021, 0x00000000, + 0xaf630048, 0x8f620040, 0x9763003c, 0x00821023, 0x0043102a, 0x1040001a, + 0x3c029000, 0x8ca40000, 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, + 0x34630001, 0x3c058000, 0x00831825, 0x34420004, 0xa362007d, 0xaf430020, + 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, + 0xa34201c4, 0xaf4301f8, 0x03e00008, 0x00001021, 0x8f420100, 0x34420001, + 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018, 0xafb10014, + 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020029, 0x00808821, 0x93620080, + 0x16020026, 0x00000000, 0x9362007f, 0x16020023, 0x00000000, 0x9362007a, + 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x24000771, 0x0e000f49, + 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825, 0xa370007a, + 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x3c028000, 0x9363007d, + 0x34420001, 0x3c048000, 0x02221025, 0xa363007d, 0xaf420020, 0x8f4201f8, + 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5101c0, 0xa34201c4, + 0xaf4301f8, 0x0a000c79, 0x8fbf0018, 0x0000000d, 0x00000000, 0x24000781, + 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, + 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014, + 0x0e001006, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, + 0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018, + 0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400, + 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, + 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, 0x8f850018, + 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, 0x8fbf0014, + 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, + 0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e001006, 0x00000000, + 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, + 0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400, + 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, + 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, 0x8f850018, + 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, 0x8fbf0014, + 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100, + 0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020, + 0x1060003a, 0x8fbf0014, 0x0e001006, 0x00000000, 0x8f840018, 0x8e030000, + 0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018, + 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, + 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, + 0xaca30018, 0x9443466e, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e001044, + 0xaca3001c, 0x0a000d19, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015, + 0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020, + 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001, + 0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000553, + 0xaf430020, 0x0a000d19, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, + 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, + 0x27500100, 0x10600022, 0xafbf0014, 0x0e001006, 0x00000000, 0x8f840018, + 0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00, + 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, + 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, + 0x3c02400e, 0x00621825, 0x0e001044, 0xaca3001c, 0x0e000d48, 0x8e040000, + 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278, + 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244, + 0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, + 0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c, + 0xafbf001c, 0x0e001006, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, + 0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, + 0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, + 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c024019, + 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100, + 0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620029, 0x00803021, 0x3c029000, + 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, + 0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000, + 0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020, + 0x8f420020, 0x00451024, 0x1440fffd, 0x3c038000, 0x9362007d, 0x34630001, + 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, 0xaf430020, 0x8f4201f8, + 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, + 0xaf4301f8, 0x0a000db3, 0x8fbf0010, 0x00c02021, 0x94a5000c, 0x24060001, + 0x0e000f78, 0x240706d8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, + 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021, 0xafb20018, 0x00a09021, + 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c, 0x0e001006, 0x00000000, + 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, + 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, + 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448, 0x3c020800, 0xac830018, + 0x9443466e, 0x8f840018, 0x3c024010, 0x00621825, 0xac83001c, 0x0e001044, + 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, + 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x93620005, 0x30420001, + 0x10400033, 0x00808021, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, + 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, + 0x3c048000, 0x3c030800, 0x304200fe, 0xa3620005, 0x8c620020, 0x34840001, + 0x02042025, 0xaf440020, 0x10400020, 0x8fbf0014, 0x0e001006, 0x00000000, + 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, + 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, + 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, + 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c02400a, + 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf0014, 0x8fb00010, + 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, + 0x9364003f, 0x24030012, 0x00021402, 0x1483001c, 0x304500ff, 0x3c029000, + 0x34420001, 0x3c038000, 0x00c21025, 0xa3650080, 0xa365007a, 0xaf420020, + 0x8f420020, 0x00431024, 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, + 0x3c048000, 0x00c21025, 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, + 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, + 0x0a000e54, 0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x93620080, + 0x1045000b, 0x00000000, 0xa3650080, 0x8f820000, 0x93660080, 0x8f440180, + 0x8f65004c, 0x8c430000, 0x0060f809, 0x00000000, 0x0a000e54, 0x8fbf0010, + 0xa3650080, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, + 0x27bdffe0, 0xafb10014, 0x00808821, 0xafb20018, 0x00a09021, 0xafb00010, + 0x30d000ff, 0x1060002f, 0xafbf001c, 0x0e001006, 0x00000000, 0x8f820018, + 0xac510000, 0x8f830018, 0xac700004, 0x8f820018, 0xac520008, 0x8f830018, + 0xac60000c, 0x8f820018, 0xac400010, 0x9763006a, 0x00032880, 0x50a00001, + 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, + 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, + 0x00c4182b, 0x54600001, 0x00c02021, 0x8f830018, 0x2402fffe, 0x00822824, + 0x3c026000, 0xac650014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, + 0x9443466e, 0x8f840018, 0x3c024011, 0x00621825, 0xac83001c, 0x0e001044, + 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, + 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f440100, 0x27500100, + 0x8f650050, 0x0e000c45, 0x9206001b, 0x3c020800, 0x8c430020, 0x1060001d, + 0x8e100018, 0x0e001006, 0x00000000, 0x8f840018, 0x8f420100, 0xac820000, + 0x8f830018, 0xac700004, 0x8f840018, 0x8f620050, 0xac820008, 0x8f830018, + 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0x3c026000, 0xac600014, + 0x8f850018, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, + 0x8f850018, 0x3c02401c, 0x00621825, 0x0e001044, 0xaca3001c, 0x8fbf0014, + 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c029000, 0x8f460140, 0x34420001, + 0x3c038000, 0x00c21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, + 0x3c048000, 0x34840001, 0x3c059000, 0x34a50001, 0x3c078000, 0x24020012, + 0x24030080, 0x00c42025, 0x00c52825, 0xa362003f, 0xa3630082, 0xaf440020, + 0xaf450020, 0x8f420020, 0x00471024, 0x1440fffd, 0x3c038000, 0x9362007d, + 0x34630001, 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, 0xaf430020, + 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, + 0xa34201c4, 0x03e00008, 0xaf4301f8, 0x8f430238, 0x3c020800, 0x04610013, + 0x8c44009c, 0x2406fffe, 0x3c050800, 0x3c038000, 0x2484ffff, 0x14800009, + 0x00000000, 0x97420078, 0x8ca3007c, 0x24420001, 0x00461024, 0x24630001, + 0xa7620010, 0x03e00008, 0xaca3007c, 0x8f420238, 0x00431024, 0x1440fff3, + 0x2484ffff, 0x8f420140, 0x3c031000, 0xaf420200, 0x03e00008, 0xaf430238, + 0x3c029000, 0x8f440140, 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, + 0x34630001, 0x3c058000, 0x00831825, 0x34420001, 0xa362007d, 0xaf430020, + 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, + 0xa34201c4, 0x03e00008, 0xaf4301f8, 0x0000000d, 0x03e00008, 0x00000000, + 0x0000000d, 0x03e00008, 0x00000000, 0x24020001, 0x03e00008, 0xa7620010, + 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, + 0x00621825, 0x14600003, 0x24020012, 0x14820003, 0x00000000, 0x03e00008, + 0x00001021, 0x9363007e, 0x9362007a, 0x14620006, 0x00000000, 0x9363007e, + 0x24020001, 0x24630001, 0x03e00008, 0xa363007e, 0x9363007e, 0x93620080, + 0x14620004, 0x24020001, 0xa362000b, 0x03e00008, 0x24020001, 0x03e00008, + 0x00001021, 0x9362000b, 0x10400021, 0x00001021, 0xa360000b, 0x9362003f, + 0x304400ff, 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, + 0x14600015, 0x00001821, 0x24020012, 0x10820012, 0x00000000, 0x9363007e, + 0x9362007a, 0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, + 0xa362007e, 0x03e00008, 0x00601021, 0x9363007e, 0x93620080, 0x14620004, + 0x00001821, 0x24020001, 0xa362000b, 0x24030001, 0x03e00008, 0x00601021, + 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc, 0x8f6200cc, + 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008, 0xa7640016, + 0x27bdffd8, 0xafb00010, 0x00808021, 0xafb3001c, 0x00c09821, 0xafbf0020, + 0xafb20018, 0xafb10014, 0x93620023, 0x00e09021, 0x30420040, 0x10400020, + 0x30b1ffff, 0x3c020800, 0x8c430020, 0x1060001c, 0x00000000, 0x0e001006, + 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac520014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, 0x00621825, + 0x0e001044, 0xaca3001c, 0x93620023, 0x30420020, 0x14400003, 0x3c020800, + 0x52600020, 0x3c029000, 0x8c430020, 0x1060001d, 0x3c029000, 0x0e001006, + 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x00111400, 0xac820004, + 0x8f830018, 0xac720008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c02401b, 0x00621825, + 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, + 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023, + 0x3c028000, 0x34420001, 0x02021025, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023, 0xaf420020, 0x03e00008, + 0x27bd0028, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, + 0x1060001d, 0xafbf0014, 0x0e001006, 0x00000000, 0x8f830018, 0x8e020004, + 0xac620000, 0x8f840018, 0x8e020018, 0xac820004, 0x8f850018, 0x8e020000, + 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, + 0xac600014, 0x8f820018, 0xac400018, 0x96030008, 0x3c020800, 0x9444466e, + 0x8f850018, 0x00031c00, 0x00641825, 0x24040001, 0x0e001044, 0xaca3001c, + 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c060800, 0x24c54660, + 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a, 0x00441023, 0x00021400, + 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d, 0x00000000, 0x2400005a, + 0x0a00101b, 0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, + 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400, 0x3c07000a, 0x3c020800, + 0x24454660, 0x94a9000a, 0x8f880014, 0x03471021, 0x94430006, 0x00402021, + 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023, 0x00021400, 0x00021403, + 0x04410006, 0x0048102b, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001036, + 0x24020001, 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, + 0x03471021, 0x24c44660, 0x8c820010, 0xaf420038, 0x8c830014, 0x3c020005, + 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018, 0x03e00008, 0x00000000, + 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800, 0x24e84660, 0xafbf001c, + 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a, 0x8d060014, 0x00009021, + 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020, 0x24630001, 0xaf820010, + 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000, 0x04c10007, 0xad030014, + 0x00621024, 0x14400005, 0x26224660, 0x8d020010, 0x24420001, 0xad020010, + 0x26224660, 0x9444000a, 0x94450018, 0x0010102b, 0x00a41826, 0x2c630001, + 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010, 0x24120001, 0x00021140, + 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x27450400, + 0x8f420000, 0x30420010, 0x1040fffd, 0x26224660, 0x9444000a, 0x94430018, + 0xaf800010, 0xaf850018, 0x14830012, 0x26274660, 0x0e0010d2, 0x00000000, + 0x1600000e, 0x26274660, 0x0e001006, 0x00000000, 0x0a00108f, 0x26274660, + 0x00041c00, 0x00031c03, 0x00051400, 0x00021403, 0x00621823, 0x18600002, + 0x3c026000, 0xac400808, 0x26274660, 0x94e2000e, 0x94e3000c, 0x24420001, + 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e, 0x12000005, 0x3c02000a, + 0x94e2000a, 0xa74200a2, 0x0a0010cc, 0x02401021, 0x03421821, 0x94640006, + 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4e40006, + 0x0000000d, 0x00000000, 0x2400005a, 0x0a0010ae, 0x24020001, 0x8f820014, + 0x0062102b, 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001b, + 0x3c020800, 0x3c06000a, 0x24454660, 0x94a8000a, 0x8f870014, 0x03461021, + 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01021023, + 0x00021400, 0x00021403, 0x04410006, 0x0047102b, 0x0000000d, 0x00000000, + 0x2400005a, 0x0a0010c8, 0x24020001, 0x14400002, 0x00001021, 0x24020001, + 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021, 0x8fbf001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x24454660, + 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0, 0x00832021, 0xaf44003c, + 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008, 0xaf420030, 0x00000000, + 0x00000000, 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x00000000, + 0x8f430400, 0x24c64660, 0xacc30010, 0x8f420404, 0x3c030020, 0xacc20014, + 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a, 0x94c5001e, 0x00832021, + 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002, 0xa4c40018, 0xa4c0001a, + 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006, 0x00021140, 0x00431025, + 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x27430400, 0x8f420000, + 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010, 0xaf830018, 0x03e00008, + 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800, 0x26104660, 0x3c05000a, + 0x02002021, 0x03452821, 0xafbf0014, 0x0e001128, 0x2406000a, 0x96020002, + 0x9603001e, 0x3042000f, 0x24420003, 0x00431804, 0x24027fff, 0x0043102b, + 0xaf830014, 0x10400004, 0x00000000, 0x0000000d, 0x00000000, 0x24000043, + 0x0e0010d2, 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, + 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, + 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a001137, 0x00a01021, + 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, + 0x00000000, 0x3c036000, 0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, + 0x00042302, 0x308403ff, 0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, + 0x00451025, 0x1440000d, 0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, + 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, + 0x3c020020, 0xaf420030, 0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, + 0x34420004, 0xaf440038, 0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, + 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, + 0x00000000, 0x00000000 }; + +static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_COM_b06FwRodata[(0x18/4) + 1] = { + 0x08002318, 0x08002348, 0x08002378, 0x080023a8, 0x080023d8, 0x00000000, + 0x00000000 }; + +static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x00000000 }; +static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x00000000 }; + +static int bnx2_RXP_b06FwReleaseMajor = 0x0; +static int bnx2_RXP_b06FwReleaseMinor = 0x0; +static int bnx2_RXP_b06FwReleaseFix = 0x0; +static u32 bnx2_RXP_b06FwStartAddr = 0x08000060; +static u32 bnx2_RXP_b06FwTextAddr = 0x08000000; +static int bnx2_RXP_b06FwTextLen = 0x20b8; +static u32 bnx2_RXP_b06FwDataAddr = 0x080020e0; +static int bnx2_RXP_b06FwDataLen = 0x0; +static u32 bnx2_RXP_b06FwRodataAddr = 0x00000000; +static int bnx2_RXP_b06FwRodataLen = 0x0; +static u32 bnx2_RXP_b06FwBssAddr = 0x08002100; +static int bnx2_RXP_b06FwBssLen = 0x239c; +static u32 bnx2_RXP_b06FwSbssAddr = 0x080020e0; +static int bnx2_RXP_b06FwSbssLen = 0x14; + +static u32 bnx2_RXP_b06FwText[(0x20b8/4) + 1] = { + 0x0a000018, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x302e362e, + 0x39000000, 0x00060903, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, + 0x244220e0, 0x3c030800, 0x2463449c, 0xac400000, 0x0043202b, 0x1480fffd, + 0x24420004, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100060, + 0x3c1c0800, 0x279c20e0, 0x0e000329, 0x00000000, 0x0000000d, 0x8f870008, + 0x2ce20080, 0x10400018, 0x3c030800, 0x24633490, 0x8f460100, 0x00072140, + 0x00831021, 0xac460000, 0x8f450104, 0x00641021, 0xac450004, 0x8f460108, + 0xac460008, 0x8f45010c, 0xac45000c, 0x8f460114, 0xac460010, 0x8f450118, + 0xac450014, 0x8f460124, 0xac460018, 0x8f450128, 0x00641821, 0x24e20001, + 0xaf820008, 0xac65001c, 0x03e00008, 0x00000000, 0x00804021, 0x8f830000, + 0x24070001, 0x3c020001, 0x00621024, 0x10400037, 0x00603021, 0x9742010e, + 0x3c038000, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x8f840004, 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, + 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000069, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x24020003, 0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc, + 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000, + 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, + 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, + 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x30c21000, + 0x1040000f, 0x00000000, 0x9742010c, 0x3042fc00, 0x5440000b, 0x24070005, + 0x3c021000, 0x00c21024, 0x10400007, 0x3c030dff, 0x3463ffff, 0x3c020e00, + 0x00c21024, 0x0062182b, 0x54600001, 0x24070005, 0x8f82000c, 0x30434000, + 0x10600016, 0x00404821, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000, + 0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b, + 0x3c020800, 0x24422100, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f, + 0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01044025, 0x11000037, + 0x3c021000, 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x8f840004, + 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0x10800005, 0xa745018e, + 0x9743011c, 0x9742011e, 0x0a0000cd, 0x00021400, 0x9743011e, 0x9742011c, + 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, + 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, + 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, + 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, + 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, + 0x00001021, 0x00c21024, 0x104000ba, 0x3c020800, 0x8c430030, 0x1060003e, + 0x31224000, 0x1040003c, 0x3c030f00, 0x00c31824, 0x3c020100, 0x0043102b, + 0x14400038, 0x3c030800, 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, + 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, + 0x8f840004, 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0x10800005, + 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000110, 0x00021400, 0x9743011e, + 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, + 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, + 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, + 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, + 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, + 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008, 0x1040003d, + 0x34e80002, 0x3c020f00, 0x00c21024, 0x5440003a, 0x3107ffff, 0x9742010c, + 0x30420200, 0x50400036, 0x3107ffff, 0x9742010e, 0x30e6fffb, 0x3c038000, + 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x8f840004, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, + 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000153, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x3107ffff, 0x8f820000, 0x3c068000, 0x9743010e, 0x00021442, + 0x30440780, 0x24630004, 0x3065ffff, 0x8f4201b8, 0x00461024, 0x1440fffd, + 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf440180, 0xa742018c, + 0x10600005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000189, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100, 0x104000ef, + 0x3c020800, 0x8c440024, 0x24030001, 0x14830036, 0x00404021, 0x9742010e, + 0x34e50002, 0x3c038000, 0x24420004, 0x3044ffff, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf400180, + 0xa742018c, 0x10600005, 0xa744018e, 0x9743011c, 0x9742011e, 0x0a0001c6, + 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, + 0x8f84000c, 0x30828000, 0x1040000c, 0xa7450188, 0x93420116, 0x304200fc, + 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, + 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, + 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, + 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x30820001, 0x10400035, + 0x30e90004, 0x9742010e, 0x30e6fffb, 0x3c038000, 0x24420004, 0x3044ffff, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, + 0x24020002, 0xaf400180, 0xa742018c, 0x10600005, 0xa744018e, 0x9743011c, + 0x9742011e, 0x0a0001fe, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, + 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, 0xa7470188, + 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, + 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, + 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, + 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x30c7ffff, 0x8d020024, + 0x30420004, 0x10400037, 0x8d020024, 0x9742010e, 0x30e6fffb, 0x3c038000, + 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x8f840004, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c, + 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000237, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x30c7ffff, 0x8d020024, 0x30420008, 0x10400034, 0x00000000, + 0x9742010e, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020003, 0xa342018b, 0x8f840004, 0x24020180, 0x24030002, + 0xaf420180, 0xa743018c, 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, + 0x0a00026f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, + 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, + 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, + 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, + 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, + 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x15200046, 0x00001021, 0x3c038000, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0x24032000, 0xa342018b, + 0xa7430188, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800, + 0x8c620024, 0x30420001, 0x10400035, 0x00001021, 0x9742010e, 0x34e50002, + 0x3c038000, 0x24420004, 0x3044ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf400180, 0xa742018c, + 0x10600005, 0xa744018e, 0x9743011c, 0x9742011e, 0x0a0002b5, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x30828000, 0x1040000c, 0xa7450188, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe0, 0xafbf0018, + 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, + 0x00621824, 0x3c024000, 0x1062000c, 0x0043102b, 0x14400006, 0x3c025000, + 0x3c023000, 0x1062000b, 0x3c024000, 0x0a00031f, 0x00000000, 0x10620034, + 0x3c024000, 0x0a00031f, 0x00000000, 0x0e00067c, 0x00000000, 0x0a00031f, + 0x3c024000, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff, + 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, 0x24020003, 0x0600001d, + 0x36053000, 0x0a00030a, 0x3c038000, 0x12020007, 0x00000000, 0x0a000317, + 0x00000000, 0x0e000423, 0x00000000, 0x0a000308, 0x00402021, 0x0e000435, + 0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, 0xa6240010, 0x8f420144, + 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00031f, 0x3c024000, 0x0000000d, + 0x00000000, 0x240001c3, 0x0a00031f, 0x3c024000, 0x0e0007f7, 0x00000000, + 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, + 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8, + 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, + 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, 0x3c040008, + 0xaf430008, 0x8e020808, 0x3c030800, 0xac600020, 0x3042fff0, 0x2c420001, + 0xaf820004, 0x0e000819, 0x0344d825, 0x0e000781, 0x00000000, 0x3c020400, + 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, + 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd, 0x32020001, + 0x10400004, 0x32020002, 0x0e0003bd, 0x00000000, 0x32020002, 0x1040fff6, + 0x00000000, 0x0e0002d4, 0x00000000, 0x0a00034a, 0x00000000, 0x27bdffe8, + 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, + 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, 0x3c040008, + 0xaf430008, 0x8e020808, 0x3c030800, 0xac600020, 0x3042fff0, 0x2c420001, + 0xaf820004, 0x0e000819, 0x0344d825, 0x0e000781, 0x00000000, 0x3c020400, + 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, + 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018, + 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, 0xaf440180, 0xa745018c, + 0x10600005, 0xa746018e, 0x9743011c, 0x9742011e, 0x0a000393, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, + 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, + 0xaf4201b8, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020002, 0x24032000, 0xa342018b, 0xa7430188, 0x3c021000, + 0xaf4201b8, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafbf0010, 0x8f460128, + 0xaf460020, 0x8f420104, 0x8f450100, 0x24030800, 0x3c040010, 0xaf820000, + 0x00441024, 0xaf85000c, 0xaf4301b8, 0x14400005, 0x3c02001f, 0x3c030800, + 0x8c620020, 0x0a0003d5, 0x00002021, 0x3442ff00, 0x14c20009, 0x2402bfff, + 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e00004c, 0xac620020, + 0x0a0003e4, 0x00000000, 0x00a21024, 0x14400006, 0x00000000, 0xaf400048, + 0x0e000448, 0xaf400040, 0x0a0003e4, 0x00000000, 0x0e000783, 0x00000000, + 0x10400005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000, + 0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, + 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, 0x3044ffff, + 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, + 0x24020003, 0x0600001d, 0x36053000, 0x0a00040e, 0x3c038000, 0x12020007, + 0x00000000, 0x0a00041b, 0x00000000, 0x0e000423, 0x00000000, 0x0a00040c, + 0x00402021, 0x0e000435, 0x00000000, 0x00402021, 0x36053000, 0x3c038000, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, + 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00041f, + 0x8fbf0018, 0x0000000d, 0x00000000, 0x240001c3, 0x8fbf0018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, 0x1040000d, + 0x00001021, 0x3c030800, 0x24632100, 0x00042942, 0x00052880, 0x00a32821, + 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, 0x03e00008, + 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, 0x1040000e, + 0x00001021, 0x3c030800, 0x24632100, 0x00042942, 0x00052880, 0x00a32821, + 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, 0x00832024, + 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0x3c026000, + 0xafbf0048, 0x8c434448, 0xaf630140, 0x93620005, 0x30420001, 0x14400005, + 0x00000000, 0x0e0007ed, 0x00000000, 0x0a00067a, 0x8fbf0048, 0x93420116, + 0x93430112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x1060000d, + 0x03426021, 0x8f430128, 0x27420180, 0xac430000, 0x8f650040, 0x24040008, + 0x240340c1, 0xa4430008, 0x24030002, 0xa043000b, 0x3c031000, 0x0a000563, + 0xa044000a, 0x8f420104, 0x3c030040, 0x00431024, 0x10400007, 0x00000000, + 0x8f430128, 0x27420180, 0xac430000, 0x8f650040, 0x0a00055c, 0x24040010, + 0xaf400048, 0xaf400054, 0xaf400040, 0x8f630048, 0x8f620040, 0x00624823, + 0x05210004, 0x00000000, 0x0000000d, 0x00000000, 0x24000132, 0x9742011a, + 0x3046ffff, 0x10c00004, 0x8d880004, 0x01061021, 0x0a000487, 0x2445ffff, + 0x01002821, 0x918a000d, 0xa7a00020, 0xafa00028, 0x9364003f, 0x3c026000, + 0x8c434448, 0x308700ff, 0x31420004, 0x10400033, 0xaf630144, 0x24090012, + 0x14e90006, 0x3c040800, 0x8c830028, 0x24020001, 0x24630001, 0x0a00054e, + 0xac830028, 0x8f620044, 0x15020012, 0x97a20020, 0x27a60010, 0x27450180, + 0x3442001a, 0xa7a20020, 0x8f630040, 0x3c048000, 0x24020020, 0xa3a70022, + 0xa3a90023, 0xa3a2001a, 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, + 0x00000000, 0x0a000533, 0x00000000, 0x8f620044, 0x01021023, 0x0440009e, + 0x24020001, 0x8f620048, 0x01021023, 0x0441009a, 0x24020001, 0x97a20020, + 0x27a60010, 0x34420001, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, + 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, + 0x00000000, 0x3c026000, 0x8c424448, 0xaf620148, 0x8f630040, 0x00685823, + 0x19600013, 0x00cb102a, 0x54400007, 0x314a00fe, 0x5566000c, 0x010b4021, + 0x31420001, 0x54400009, 0x010b4021, 0x314a00fe, 0x24020001, 0xa7a20020, + 0x8f630040, 0x00c05821, 0x00003021, 0x0a0004dd, 0xafa30028, 0x00cb1023, + 0x0a0004dd, 0x3046ffff, 0x00005821, 0x8f620048, 0x2442ffff, 0x00a21823, + 0x18600019, 0x0066102a, 0x14400013, 0x24020001, 0xa7a20020, 0x8f630040, + 0xafa30028, 0x8f620040, 0x55020005, 0x27a60010, 0x55200003, 0x27a60010, + 0x0a0004f6, 0x00c01821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, 0x8f650048, 0x00c31023, + 0x3046ffff, 0x314a00f6, 0x3c046000, 0x8c824448, 0x31430002, 0x1060001e, + 0xaf62014c, 0x8f620044, 0x1502000e, 0x97a20020, 0x27a60010, 0x34420200, + 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, 0xafa30028, 0x8f4201b8, + 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, 0x27a60010, + 0x34420001, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, 0xafa30028, + 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, + 0x3c026000, 0x8c424448, 0x31430010, 0xaf620150, 0x54600003, 0x8d890008, + 0x0a00054e, 0x24020001, 0x8f630054, 0x2522ffff, 0x00431023, 0x1840002a, + 0x24020001, 0x27a60010, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, + 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x8f420128, + 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a, + 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012, + 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024, + 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000, + 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a00067a, 0x8fbf0048, + 0x3c026000, 0x8c424448, 0x31430020, 0x10600019, 0xaf620154, 0x8f430128, + 0x27420180, 0xac430000, 0x8f650040, 0x24040004, 0x240340c1, 0xa4430008, + 0x24030002, 0xa044000a, 0x24040008, 0xa043000b, 0x3c031000, 0xa4440010, + 0xa0400012, 0xa0400013, 0xac400014, 0xac400024, 0xac400028, 0xac40002c, + 0xac450018, 0x0e0007ed, 0xaf4301b8, 0x0a00067a, 0x8fbf0048, 0x8f430104, + 0x8c824448, 0x38e3000a, 0x2c630001, 0xaf620158, 0x38e2000c, 0x2c420001, + 0x00621825, 0x14600003, 0x2402000e, 0x14e2002a, 0x00000000, 0x50c00008, + 0x9584000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a000583, 0x2445ffff, + 0x01002821, 0x9584000e, 0x93630035, 0x8f62004c, 0x00642004, 0x00892021, + 0x00821023, 0x1840001f, 0x3c026000, 0x8f620018, 0x01021023, 0x1c40000f, + 0x97a20020, 0x8f620018, 0x15020018, 0x3c026000, 0x8f62001c, 0x01221023, + 0x1c400008, 0x97a20020, 0x8f62001c, 0x15220011, 0x3c026000, 0x8f620058, + 0x00821023, 0x1840000c, 0x97a20020, 0xafa50028, 0xafa80034, 0xafa90038, + 0xafa4003c, 0x34420020, 0x0a0005a8, 0xa7a20020, 0x8f680040, 0x00003021, + 0x8f640058, 0x01002821, 0x3c026000, 0x8c434448, 0xaf63015c, 0x8f62004c, + 0x01221023, 0x18400009, 0x00000000, 0x8f620054, 0x01221023, 0x1c400005, + 0x97a20020, 0xafa50028, 0xafa90024, 0x0a0005c3, 0x34420040, 0x9742011a, + 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c, + 0x8f620054, 0x10620004, 0x97a20020, 0xafa50028, 0x34420080, 0xa7a20020, + 0x24020014, 0x10e2000a, 0x28e20015, 0x10400005, 0x2402000c, 0x10e20006, + 0x3c026000, 0x0a000600, 0x00000000, 0x24020016, 0x14e20031, 0x3c026000, + 0x8f620054, 0x24420001, 0x1522002d, 0x3c026000, 0x24020014, 0x10e2001e, + 0x28e20015, 0x10400005, 0x2402000c, 0x10e20008, 0x3c026000, 0x0a000600, + 0x00000000, 0x24020016, 0x10e2000c, 0x97a20020, 0x0a000600, 0x3c026000, + 0x97a30020, 0x2402000e, 0xafa50028, 0xa3a70022, 0xa3a20023, 0xafa90024, + 0x34630054, 0x0a0005ff, 0xa7a30020, 0x24030010, 0x24040002, 0xafa50028, + 0xa3a70022, 0xa3a30023, 0xa3a4001a, 0xafa90024, 0x0a0005fe, 0x3442005d, + 0x97a20020, 0x24030012, 0x24040002, 0xafa50028, 0xa3a70022, 0xa3a30023, + 0xa3a4001a, 0xafa90024, 0x3042fffe, 0x3442005c, 0xa7a20020, 0x3c026000, + 0x8c434448, 0x31420001, 0xaf630160, 0x1040002c, 0x2402000c, 0x10e20014, + 0x28e2000d, 0x10400005, 0x2402000a, 0x10e20008, 0x97a20020, 0x0a000631, + 0x3c026000, 0x2402000e, 0x10e20018, 0x3c026000, 0x0a000631, 0x00000000, + 0x24030008, 0x24040002, 0xafa50028, 0xa3a70022, 0xa3a30023, 0xa3a4001a, + 0x0a00062f, 0x34420013, 0x97a30020, 0x30620004, 0x1440000b, 0x97a20020, + 0x3462001b, 0xa7a20020, 0x24020016, 0x24030002, 0xafa50028, 0xa3a70022, + 0xa3a20023, 0x0a000630, 0xa3a3001a, 0x97a20020, 0x24030010, 0x24040002, + 0xafa50028, 0xa3a70022, 0xa3a30023, 0xa3a4001a, 0x3442001b, 0xa7a20020, + 0x3c026000, 0x8c434448, 0x31420009, 0x0002102b, 0x00021023, 0x30420007, + 0x34440003, 0xaf630164, 0x10c00016, 0x24030800, 0x8f820010, 0x27450180, + 0x24420001, 0xaf820010, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b, + 0x93440120, 0x3c031000, 0xa4a6000e, 0xaca90024, 0xaca80028, 0x008b2021, + 0xa4a4000c, 0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a000650, + 0xa7a20020, 0x24060001, 0x3c026000, 0x8c434448, 0xaf630168, 0x97a20020, + 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028, 0x240240c1, 0xa4a20008, + 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x97a20020, + 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023, 0xa0a20013, 0x8fa30024, + 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038, 0xaca30028, 0x8fa2003c, + 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x3c026000, 0x8c434448, 0x00c01021, + 0xaf63016c, 0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f460140, 0x8f470148, + 0x3c028000, 0x00e24024, 0x00072c02, 0x30a300ff, 0x2402000b, 0x1062008f, + 0x27440180, 0x2862000c, 0x10400011, 0x24020006, 0x1062005a, 0x28620007, + 0x10400007, 0x24020008, 0x10600024, 0x24020001, 0x10620037, 0x00000000, + 0x0a00077e, 0x00000000, 0x106200a9, 0x24020009, 0x106200bb, 0x00071c02, + 0x0a00077e, 0x00000000, 0x2402001b, 0x106200c7, 0x2862001c, 0x10400007, + 0x2402000e, 0x106200b1, 0x24020019, 0x106200c2, 0x00071c02, 0x0a00077e, + 0x00000000, 0x24020080, 0x10620060, 0x28620081, 0x10400005, 0x2402001c, + 0x10620094, 0x00071c02, 0x0a00077e, 0x00000000, 0x240200c2, 0x106200c5, + 0x00a01821, 0x0a00077e, 0x00000000, 0x00a01821, 0x3c058000, 0x8f4201b8, + 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac860000, + 0xac800004, 0xa082000a, 0xa083000b, 0xa4870010, 0x8f430144, 0x3c021000, + 0xac800028, 0xac830024, 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, + 0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0434490, 0x24424490, + 0xac460008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, + 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac860004, 0xa4830008, + 0xa082000a, 0xa082000b, 0xa4870010, 0xac800024, 0x8f420144, 0x3c031000, + 0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x00a01821, + 0x3c080800, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000, + 0xac860000, 0x91024490, 0x00002821, 0x10400002, 0x25064490, 0x8cc50008, + 0xac850004, 0xa4830008, 0x91034490, 0x24020002, 0xa082000b, 0xa4870010, + 0x34630001, 0xa083000a, 0x8f420144, 0xac820024, 0x91034490, 0x10600002, + 0x00001021, 0x8cc20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000, + 0xa1004490, 0x03e00008, 0xac400808, 0x00a01821, 0x3c058000, 0x8f4201b8, + 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b, 0xa4830008, 0xa4870010, + 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008, 0xaf4301b8, 0x30e2ffff, + 0x14400028, 0x00071c02, 0x93620005, 0x30420004, 0x14400020, 0x3c029000, + 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, + 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, 0x34630001, 0x00c31825, + 0x34420004, 0xa3620005, 0xaf430020, 0x93620005, 0x30420004, 0x14400003, + 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x24020005, 0x3c031000, 0xac860000, 0xa082000b, 0xaf4301b8, 0x0a00073d, + 0x00071c02, 0x0000000d, 0x03e00008, 0x00000000, 0x00071c02, 0x3c058000, + 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, + 0xac860000, 0xac800004, 0xa082000a, 0xa083000b, 0xa4870010, 0x8f430144, + 0x3c021000, 0xac800028, 0xac830024, 0x03e00008, 0xaf4201b8, 0x00071c02, + 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, + 0xac860004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4870010, 0xac800024, + 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8, 0x00071c02, + 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, + 0x24030002, 0xa082000a, 0x3c021000, 0xac860000, 0xac800004, 0xa083000b, + 0xa4870010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8, 0x3c058000, + 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xac860000, 0xac800004, + 0xa4830008, 0xa080000a, 0x0a000748, 0xa082000b, 0x0000000d, 0x03e00008, + 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011, + 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000, + 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040, + 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008, + 0x00000000, 0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000, + 0x3c028000, 0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x8f430128, + 0x27420180, 0xac430000, 0x8f650040, 0x240340c1, 0xa4430008, 0x24030002, + 0xa044000a, 0x24040008, 0xa043000b, 0x3c031000, 0xa4440010, 0xa0400012, + 0xa0400013, 0xac400014, 0xac400024, 0xac400028, 0xac40002c, 0xac450018, + 0x03e00008, 0xaf4301b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000, + 0x03e00008, 0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050, + 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, + 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, + 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, + 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c, + 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008, + 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e000326, 0x00000000, 0x00002021, + 0x0e00004c, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148, + 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02, + 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024, + 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005, + 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a000816, 0xa0a2000a, 0xa0a0000a, + 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007, + 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, + 0x24840004, 0x03e00008, 0x00000000, 0x0a00082a, 0x00a01021, 0xac860000, + 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, 0x00000000, + 0x00000000 }; + +static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_RXP_b06FwBss[(0x239c/4) + 1] = { 0x00000000 }; +static u32 bnx2_RXP_b06FwSbss[(0x14/4) + 1] = { 0x00000000 }; + +static u32 bnx2_rv2p_proc1[] = { + 0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004, + 0x00000010, 0x20bf002c, 0x00000010, 0x203f0143, 0x00000018, 0x8000fffd, + 0x00000010, 0xb1b8b017, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000, + 0x00000000, 0x2c380000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, + 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x00000008, 0x02000002, + 0x00000010, 0x91de0000, 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, + 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000008, 0x2d800150, + 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000010, 0x2c620002, + 0x00000018, 0x80000012, 0x0000000b, 0x2fdf0002, 0x0000000c, 0x1f800002, + 0x00000000, 0x2c070000, 0x00000018, 0x8000ffe6, 0x00000008, 0x02000002, + 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, 0x00000008, 0x2c8000b0, + 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, + 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000018, 0x80000004, + 0x0000000c, 0x1f800002, 0x00000000, 0x00000000, 0x00000018, 0x8000ffd9, + 0x0000000c, 0x29800002, 0x0000000c, 0x1f800002, 0x00000000, 0x2adf0000, + 0x00000008, 0x2a000005, 0x00000018, 0x8000ffd4, 0x00000008, 0x02240030, + 0x00000018, 0x00040000, 0x00000018, 0x80000015, 0x00000018, 0x80000017, + 0x00000018, 0x8000001b, 0x00000018, 0x8000004c, 0x00000018, 0x8000008c, + 0x00000018, 0x8000000f, 0x00000018, 0x8000000e, 0x00000018, 0x8000000d, + 0x00000018, 0x8000000c, 0x00000018, 0x800000c2, 0x00000018, 0x8000000a, + 0x00000018, 0x80000009, 0x00000018, 0x80000008, 0x00000018, 0x800000fd, + 0x00000018, 0x80000006, 0x00000018, 0x80000005, 0x00000018, 0x800000ff, + 0x00000018, 0x80000104, 0x00000018, 0x80000002, 0x00000018, 0x80000098, + 0x00000018, 0x80000000, 0x0000000c, 0x1f800001, 0x00000000, 0x00000000, + 0x00000018, 0x8000ffba, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, + 0x0000000c, 0x1f800001, 0x00000008, 0x2a000002, 0x00000018, 0x8000ffb5, + 0x00000010, 0xb1a0b012, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, + 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, 0x00000010, 0x91d40000, + 0x00000008, 0x2d80011c, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, + 0x0000000f, 0x47600008, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, + 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, + 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000018, 0x80000013, + 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, 0x00000008, 0x2c800000, + 0x00000008, 0x2d000000, 0x00000010, 0x91d40000, 0x00000008, 0x2d80011c, + 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, 0x00000000, 0x0f580000, + 0x00000010, 0x91de0000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, + 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000000, 0x02620000, + 0x0000000b, 0x2fdf0002, 0x00000000, 0x309a0000, 0x00000000, 0x31040000, + 0x00000000, 0x0c961800, 0x00000009, 0x0c99ffff, 0x00000004, 0xcc993400, + 0x00000010, 0xb1963202, 0x00000008, 0x0f800000, 0x0000000c, 0x29800001, + 0x00000010, 0x00220002, 0x0000000c, 0x29520001, 0x0000000c, 0x29520000, + 0x00000008, 0x22000001, 0x0000000c, 0x1f800001, 0x00000000, 0x2adf0000, + 0x00000008, 0x2a000003, 0x00000018, 0x8000ff83, 0x00000010, 0xb1a0b01d, + 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0, + 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, + 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, + 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000000, 0x00000000, + 0x00000010, 0x91de0000, 0x0000000f, 0x47600008, 0x00000000, 0x060e0000, + 0x00000010, 0x001f0000, 0x00000000, 0x0f580000, 0x00000010, 0x91de0000, + 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, + 0x00000000, 0x0d620000, 0x00000000, 0x0ce71800, 0x00000009, 0x0c99ffff, + 0x00000004, 0xcc993400, 0x00000010, 0xb1963220, 0x00000008, 0x0f800000, + 0x00000018, 0x8000001e, 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, + 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, + 0x00000008, 0x2d80012c, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, + 0x00000000, 0x0f580000, 0x00000010, 0x91de0000, 0x00000000, 0x0a640000, + 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, 0x00000000, 0x0d620000, + 0x00000000, 0x02630000, 0x0000000f, 0x47620010, 0x00000000, 0x0ce71800, + 0x0000000b, 0x2fdf0002, 0x00000000, 0x311a0000, 0x00000000, 0x31840000, + 0x0000000b, 0xc20000ff, 0x00000002, 0x42040000, 0x00000001, 0x31620800, + 0x0000000f, 0x020e0010, 0x00000002, 0x31620800, 0x00000009, 0x0c99ffff, + 0x00000004, 0xcc993400, 0x00000010, 0xb1963202, 0x00000008, 0x0f800000, + 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x0000000c, 0x61420006, + 0x00000008, 0x22000008, 0x00000000, 0x2adf0000, 0x00000008, 0x2a000004, + 0x00000018, 0x8000ff42, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, + 0x00000010, 0x91a0b008, 0x00000010, 0x91d40000, 0x0000000c, 0x31620018, + 0x00000008, 0x2d800001, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, + 0x00000008, 0xac000001, 0x00000018, 0x8000000e, 0x00000000, 0x0380b000, + 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c004000, 0x00000010, 0x91d40000, + 0x00000008, 0x2d800101, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, + 0x0000000c, 0x31620018, 0x00000008, 0x2d800001, 0x00000000, 0x00000000, + 0x00000010, 0x91de0000, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c000e00, + 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000008, 0x2a000007, + 0x00000018, 0x8000ff27, 0x00000010, 0xb1a0b016, 0x0000000b, 0x2fdf0002, + 0x00000000, 0x03d80000, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0, + 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, + 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, + 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000008, 0x07000001, + 0x00000010, 0xb5de1c00, 0x00000010, 0x2c620002, 0x00000018, 0x8000000a, + 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c070000, 0x0000000c, 0x1f800001, + 0x00000010, 0x91de0000, 0x00000018, 0x8000ff11, 0x00000008, 0x2c8000b0, + 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, + 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000010, 0x91de0000, + 0x00000000, 0x2adf0000, 0x00000008, 0x2a00000a, 0x00000018, 0x8000ff07, + 0x00000000, 0x82265600, 0x0000000f, 0x47220008, 0x00000009, 0x070e000f, + 0x00000008, 0x070e0008, 0x00000008, 0x02800001, 0x00000007, 0x02851c00, + 0x00000008, 0x82850001, 0x00000000, 0x02840a00, 0x00000007, 0x42851c00, + 0x00000003, 0xc3aa5200, 0x00000000, 0x03b10e00, 0x00000010, 0x001f0000, + 0x0000000f, 0x0f280007, 0x00000007, 0x4b071c00, 0x00000000, 0x00000000, + 0x0000000f, 0x0a960003, 0x00000000, 0x0a955c00, 0x00000000, 0x4a005a00, + 0x00000000, 0x0c960a00, 0x00000009, 0x0c99ffff, 0x00000008, 0x0d00ffff, + 0x00000010, 0xb1963202, 0x00000008, 0x0f800005, 0x00000010, 0x00220020, + 0x00000000, 0x02a70000, 0x00000010, 0xb1850002, 0x00000008, 0x82850200, + 0x00000000, 0x02000000, 0x00000000, 0x03a60000, 0x00000018, 0x8000004e, + 0x00000000, 0x072b0000, 0x00000001, 0x878c1c00, 0x00000000, 0x870e1e00, + 0x00000000, 0x860c1e00, 0x00000000, 0x03061e00, 0x00000010, 0xb18e0003, + 0x00000018, 0x80000047, 0x00000018, 0x8000fffa, 0x00000010, 0x918c0003, + 0x00000010, 0xb1870002, 0x00000018, 0x80000043, 0x00000010, 0x91d40000, + 0x0000000c, 0x29800001, 0x00000000, 0x2a860000, 0x00000000, 0x230c0000, + 0x00000000, 0x2b070000, 0x00000010, 0xb187000e, 0x00000008, 0x2a000008, + 0x00000018, 0x8000003b, 0x00000010, 0x91d40000, 0x00000000, 0x28d18c00, + 0x00000000, 0x2a860000, 0x00000000, 0x230c0000, 0x00000000, 0x2b070000, + 0x00000018, 0x8000fff8, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, + 0x00000000, 0x2aab0000, 0x00000000, 0xa3265600, 0x00000000, 0x2b000000, + 0x0000000c, 0x1f800001, 0x00000008, 0x2a000008, 0x00000018, 0x8000fec8, + 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, + 0x00000008, 0x2a000009, 0x00000018, 0x8000fec3, 0x00000010, 0x91d40000, + 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000000, 0x29420000, + 0x00000008, 0x2a000002, 0x00000018, 0x8000febd, 0x00000018, 0x8000febc, + 0x00000010, 0xb1bcb016, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000, + 0x00000000, 0x2c3c0000, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, + 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, 0x00000000, 0x00000000, + 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, + 0x00000008, 0x2d800108, 0x00000008, 0x07000001, 0x00000010, 0xb5de1c00, + 0x00000010, 0x2c620002, 0x00000018, 0x8000000a, 0x0000000b, 0x2fdf0002, + 0x00000000, 0x2c070000, 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, + 0x00000018, 0x8000fea6, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, + 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x0000000c, 0x29800000, + 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, 0x00000000, 0x2adf0000, + 0x00000008, 0x2a000006, 0x00000018, 0x8000fe9c, 0x00000008, 0x03050004, + 0x00000006, 0x83040c00, 0x00000008, 0x02850200, 0x00000000, 0x86050c00, + 0x00000001, 0x860c0e00, 0x00000008, 0x02040004, 0x00000000, 0x02041800, + 0x00000000, 0x83871800, 0x00000018, 0x00020000 }; + +static u32 bnx2_rv2p_proc2[] = { + 0x00000000, 0x2a000000, 0x00000010, 0xb1d40000, 0x00000008, 0x02540003, + 0x00000018, 0x00040000, 0x00000018, 0x8000000a, 0x00000018, 0x8000000a, + 0x00000018, 0x8000000e, 0x00000018, 0x80000056, 0x00000018, 0x800001b9, + 0x00000018, 0x800001e1, 0x00000018, 0x8000019b, 0x00000018, 0x800001f9, + 0x00000018, 0x8000019f, 0x00000018, 0x800001a6, 0x00000018, 0x80000000, + 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, 0x0000000c, 0x29800000, + 0x00000010, 0x20530000, 0x00000018, 0x8000ffee, 0x0000000c, 0x29800001, + 0x00000010, 0x91de0000, 0x00000010, 0x001f0000, 0x00000000, 0x2f80aa00, + 0x00000000, 0x2a000000, 0x00000000, 0x0d610000, 0x00000000, 0x03620000, + 0x00000000, 0x2c400000, 0x00000000, 0x02638c00, 0x00000000, 0x26460000, + 0x00000010, 0x00420002, 0x00000008, 0x02040012, 0x00000010, 0xb9060836, + 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, + 0x00000000, 0x0b660000, 0x00000000, 0x0c000000, 0x00000000, 0x0b800000, + 0x00000010, 0x00420009, 0x00000008, 0x0cc60012, 0x00000008, 0x0f800003, + 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000008, 0x27110012, + 0x00000000, 0x66900000, 0x00000008, 0xa31b0012, 0x00000018, 0x80000008, + 0x00000000, 0x0cc60000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000, + 0x00000010, 0x009f0000, 0x00000000, 0x27110000, 0x00000000, 0x66900000, + 0x00000000, 0x231b0000, 0x00000010, 0xb197320e, 0x00000000, 0x25960000, + 0x00000000, 0x021b0000, 0x00000010, 0x001f0000, 0x00000008, 0x0f800003, + 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000000, 0x22c50800, + 0x00000010, 0x009f0000, 0x00000000, 0x27002200, 0x00000000, 0x26802000, + 0x00000000, 0x231b0000, 0x0000000c, 0x69520001, 0x00000018, 0x8000fff3, + 0x00000010, 0x01130002, 0x00000010, 0xb1980003, 0x00000010, 0x001f0000, + 0x00000008, 0x0f800004, 0x00000008, 0x22000003, 0x00000008, 0x2c80000c, + 0x00000008, 0x2d00000c, 0x00000010, 0x009f0000, 0x00000000, 0x25960000, + 0x0000000c, 0x29800000, 0x00000000, 0x32140000, 0x00000000, 0x32950000, + 0x00000000, 0x33160000, 0x00000000, 0x31e32e00, 0x00000008, 0x2d800010, + 0x00000010, 0x20530000, 0x00000018, 0x8000ffac, 0x00000000, 0x23000000, + 0x00000000, 0x25e60000, 0x00000008, 0x2200000b, 0x0000000c, 0x69520000, + 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000018, 0x8000ffa5, + 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, + 0x00000010, 0x001f0000, 0x00000000, 0x02700000, 0x00000000, 0x0d620000, + 0x00000000, 0xbb630800, 0x00000000, 0x2a000000, 0x00000009, 0x076000ff, + 0x0000000f, 0x2c0e0007, 0x00000008, 0x2c800000, 0x00000008, 0x2d000064, + 0x00000008, 0x2d80011c, 0x00000009, 0x06420002, 0x0000000c, 0x61420001, + 0x00000000, 0x0f400000, 0x00000000, 0x02d08c00, 0x00000000, 0x23000000, + 0x00000004, 0x826da000, 0x00000000, 0x8304a000, 0x00000000, 0x22c50c00, + 0x00000000, 0x03760000, 0x00000004, 0x83860a00, 0x00000000, 0x83870c00, + 0x00000010, 0x91de0000, 0x00000000, 0x037c0000, 0x00000000, 0x837b0c00, + 0x00000001, 0x83060e00, 0x00000000, 0x83870c00, 0x00000000, 0x82850e00, + 0x00000010, 0xb1860016, 0x0000000f, 0x47610018, 0x00000000, 0x068e0000, + 0x0000000f, 0x47670010, 0x0000000f, 0x47e20010, 0x00000000, 0x870e1e00, + 0x00000010, 0xb70e1a10, 0x00000010, 0x0ce7000e, 0x00000008, 0x22000009, + 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400, + 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004, + 0x00000018, 0x8000023f, 0x00000000, 0x37ed0000, 0x0000000c, 0x73e7001a, + 0x00000010, 0x20530000, 0x00000008, 0x22000008, 0x0000000c, 0x61420004, + 0x00000000, 0x02f60000, 0x00000004, 0x82840a00, 0x00000010, 0xb1840a2b, + 0x00000010, 0x2d67000a, 0x00000010, 0xb96d0804, 0x00000004, 0xb6ed0a00, + 0x00000000, 0x37ed0000, 0x00000018, 0x80000029, 0x0000000c, 0x61420000, + 0x00000000, 0x37040000, 0x00000000, 0x37850000, 0x0000000c, 0x33e7001a, + 0x00000018, 0x80000024, 0x00000010, 0xb96d0809, 0x00000004, 0xb6ed0a00, + 0x00000000, 0x036d0000, 0x00000004, 0xb76e0c00, 0x00000010, 0x91ee0c1f, + 0x0000000c, 0x73e7001a, 0x00000004, 0xb6ef0c00, 0x00000000, 0x37ed0000, + 0x00000018, 0x8000001b, 0x0000000c, 0x61420000, 0x00000010, 0xb7ee0a05, + 0x00000010, 0xb96f0815, 0x00000003, 0xb76e0800, 0x00000004, 0xb7ef0a00, + 0x00000018, 0x80000015, 0x00000010, 0x0ce7000c, 0x00000008, 0x22000009, + 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400, + 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004, + 0x00000018, 0x80000215, 0x00000010, 0x20530000, 0x00000008, 0x22000008, + 0x0000000c, 0x61420004, 0x00000000, 0x37040000, 0x00000000, 0x37850000, + 0x00000000, 0x036d0000, 0x00000003, 0xb8f10c00, 0x00000018, 0x80000004, + 0x00000000, 0x02840000, 0x00000002, 0x21421800, 0x0000000c, 0x61420000, + 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, + 0x00000000, 0x23000000, 0x00000010, 0xb1840a3d, 0x00000010, 0x01420002, + 0x00000004, 0xb8f10a00, 0x00000003, 0x83760a00, 0x00000010, 0xb8040c39, + 0x00000010, 0xb7e6080a, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, + 0x00000009, 0x0c68ffff, 0x00000009, 0x0b67ffff, 0x00000000, 0x0be60000, + 0x00000000, 0x0c840000, 0x00000010, 0xb197320c, 0x00000008, 0x0f800002, + 0x00000018, 0x8000000a, 0x00000000, 0x0a6a0000, 0x00000000, 0x0aeb0000, + 0x00000000, 0x0c000000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0be90000, + 0x00000000, 0x0c840000, 0x00000010, 0xb1973203, 0x00000008, 0x0f800002, + 0x00000018, 0x80000001, 0x00000010, 0x001f0000, 0x00000000, 0x0c860000, + 0x00000000, 0x06980000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000, + 0x00000010, 0x009f0000, 0x00000010, 0xb1973210, 0x00000000, 0x231b0000, + 0x00000000, 0x02043600, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, + 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000, + 0x0000000c, 0x29000000, 0x00000018, 0x800001de, 0x00000000, 0x06980000, + 0x00000010, 0x20530000, 0x00000000, 0x22c58c00, 0x00000010, 0x001f0000, + 0x00000008, 0x0f800003, 0x00000018, 0x8000fff0, 0x00000000, 0x02043600, + 0x00000000, 0x231b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, + 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000, + 0x0000000c, 0x29000000, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, + 0x00000000, 0x32140000, 0x00000000, 0x32950000, 0x00000005, 0x73e72c00, + 0x00000005, 0x74683000, 0x00000000, 0x33170000, 0x00000018, 0x80000138, + 0x00000010, 0x91c60004, 0x00000008, 0x07000004, 0x00000010, 0xb1c41c02, + 0x00000010, 0x91840a04, 0x00000018, 0x800001c3, 0x00000010, 0x20530000, + 0x00000000, 0x22c58c00, 0x00000010, 0xb1840a8e, 0x0000000c, 0x21420006, + 0x00000010, 0x0ce7001a, 0x0000000f, 0x43680010, 0x00000000, 0x03f30c00, + 0x00000010, 0x91870850, 0x0000000f, 0x46ec0010, 0x00000010, 0xb68d0c4e, + 0x00000000, 0x838d0c00, 0x00000000, 0xa3050800, 0x00000001, 0xa3460e00, + 0x00000000, 0x02048c00, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, + 0x00000010, 0x001f0000, 0x00000008, 0x22000008, 0x00000003, 0x8384a000, + 0x0000000f, 0x65870010, 0x00000009, 0x2607ffff, 0x00000000, 0x27750c00, + 0x00000000, 0x66f40000, 0x0000000c, 0x29000000, 0x00000018, 0x800001aa, + 0x00000000, 0x03068c00, 0x00000003, 0xf4680c00, 0x00000010, 0x20530000, + 0x00000000, 0x22c58c00, 0x00000018, 0x8000ffe5, 0x00000000, 0x39760000, + 0x00000000, 0x39840000, 0x0000000c, 0x33e70019, 0x00000010, 0x001f0000, + 0x00000000, 0x031e0000, 0x00000000, 0x0760fe00, 0x0000000f, 0x0f0e0007, + 0x00000000, 0x83850800, 0x00000000, 0x0a7d0000, 0x00000000, 0x0afe0000, + 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, 0x00000000, 0x0c000000, + 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003, + 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff, + 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010, + 0x00000002, 0x33e70e00, 0x00000000, 0x28f30000, 0x00000010, 0x009f0000, + 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, + 0x00000008, 0x22000006, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000, + 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, + 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000, + 0x0000000c, 0x29000000, 0x00000018, 0x8000017e, 0x00000003, 0xf4683600, + 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400, + 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004, + 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000, + 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000, + 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000, + 0x00000000, 0x22c53600, 0x00000018, 0x8000ffac, 0x00000010, 0x001f0000, + 0x00000000, 0x031e0000, 0x00000000, 0x83850800, 0x00000009, 0x076000ff, + 0x0000000f, 0x0f0e0007, 0x00000000, 0x0c000000, 0x00000000, 0x0a7d0000, + 0x00000000, 0x0afe0000, 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, + 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003, + 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff, + 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010, + 0x00000002, 0x33e70e00, 0x00000000, 0x39840000, 0x00000003, 0xb9720800, + 0x00000000, 0x28f30000, 0x0000000f, 0x65680010, 0x00000010, 0x009f0000, + 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, + 0x00000008, 0x22000007, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000, + 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, + 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000, + 0x0000000c, 0x29000000, 0x00000018, 0x80000145, 0x00000003, 0xf4683600, + 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400, + 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004, + 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000, + 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000, + 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000, + 0x00000000, 0x22c53600, 0x00000018, 0x8000ff73, 0x00000010, 0x0ce70005, + 0x00000008, 0x2c80000c, 0x00000008, 0x2d000070, 0x00000008, 0x2d800010, + 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000018, 0x8000011d, + 0x00000000, 0x2c1e0000, 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, + 0x00000008, 0x2d800048, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, + 0x00000018, 0x8000fe5d, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, + 0x00000010, 0x001f0000, 0x00000000, 0x0f008000, 0x00000008, 0x0f800007, + 0x00000018, 0x80000006, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, + 0x00000010, 0x001f0000, 0x0000000f, 0x0f470007, 0x00000008, 0x0f800008, + 0x00000018, 0x80000119, 0x00000010, 0x20530000, 0x00000018, 0x8000fe4f, + 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, + 0x00000000, 0x2a000000, 0x00000009, 0x0261ffff, 0x0000000d, 0x70e10001, + 0x00000018, 0x80000101, 0x00000000, 0x2c400000, 0x00000008, 0x2c8000c4, + 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, 0x00000005, 0x70e10800, + 0x00000010, 0x91de0000, 0x00000018, 0x8000fe41, 0x0000000c, 0x29800001, + 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, + 0x00000000, 0x02700000, 0x00000000, 0x0d620000, 0x00000000, 0xbb630800, + 0x00000000, 0x2a000000, 0x00000000, 0x0f400000, 0x00000000, 0x2c400000, + 0x0000000c, 0x73e7001b, 0x00000010, 0x0ce7000e, 0x00000000, 0x286d0000, + 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, 0x00000018, 0x80000069, + 0x00000008, 0x02000004, 0x00000010, 0x91c40803, 0x00000018, 0x800000f6, + 0x00000010, 0x20530000, 0x00000018, 0x800000e5, 0x00000008, 0x2c8000b8, + 0x00000008, 0x2d000010, 0x00000008, 0x2d800048, 0x00000018, 0x80000005, + 0x00000008, 0x2c8000c4, 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, + 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800048, + 0x00000008, 0x2d000068, 0x00000008, 0x2d800104, 0x00000000, 0x00000000, + 0x00000010, 0x91de0000, 0x00000000, 0x27f60000, 0x00000010, 0xb87a9e04, + 0x00000008, 0x2200000d, 0x00000018, 0x800000e2, 0x00000010, 0x20530000, + 0x00000018, 0x8000fe18, 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, + 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, 0x00000000, 0x02700000, + 0x00000000, 0x0d620000, 0x00000000, 0xbb630800, 0x00000000, 0x2a000000, + 0x00000010, 0x0e670011, 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, + 0x00000009, 0x266dffff, 0x00000004, 0xb8f1a000, 0x00000000, 0x0f400000, + 0x0000000c, 0x73e7001c, 0x00000018, 0x80000040, 0x00000008, 0x02000004, + 0x00000010, 0x91c40802, 0x00000018, 0x800000cd, 0x00000000, 0x2c1e0000, + 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, 0x00000008, 0x2d800048, + 0x00000010, 0x20530000, 0x00000010, 0x91de0000, 0x00000018, 0x8000fdfe, + 0x0000000c, 0x29800001, 0x00000000, 0x03550000, 0x00000000, 0x06460000, + 0x00000000, 0x03d60000, 0x00000000, 0x2a000000, 0x0000000f, 0x0f480007, + 0x00000010, 0xb18c0027, 0x0000000f, 0x47420008, 0x00000009, 0x070e000f, + 0x00000008, 0x070e0008, 0x00000010, 0x001f0000, 0x00000008, 0x09000001, + 0x00000007, 0x09121c00, 0x00000003, 0xcbca9200, 0x00000000, 0x0b97a200, + 0x00000007, 0x4b171c00, 0x0000000f, 0x0a960003, 0x00000000, 0x0a959c00, + 0x00000000, 0x4a009a00, 0x00000008, 0x82120001, 0x00000001, 0x0c170800, + 0x00000000, 0x02180000, 0x00000000, 0x0c971800, 0x00000008, 0x0d00ffff, + 0x00000008, 0x0f800006, 0x0000000c, 0x29000000, 0x00000008, 0x22000001, + 0x00000000, 0x22c50c00, 0x00000010, 0x009f0000, 0x00000010, 0xb197320b, + 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000, + 0x00000018, 0x800000a4, 0x00000000, 0x02180000, 0x00000010, 0x20530000, + 0x00000000, 0x22c53600, 0x00000010, 0x001f0000, 0x00000008, 0x0f800006, + 0x00000018, 0x8000fff5, 0x00000010, 0x91870002, 0x00000008, 0x2200000a, + 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000, + 0x00000018, 0x80000098, 0x00000008, 0x0200000a, 0x00000010, 0x91c40804, + 0x00000010, 0x02c20003, 0x00000010, 0x001f0000, 0x00000008, 0x0f800008, + 0x00000010, 0x20530000, 0x00000018, 0x8000fdc9, 0x00000000, 0x06820000, + 0x00000010, 0x001f0000, 0x00000010, 0x0ce70028, 0x00000000, 0x03720000, + 0x00000000, 0xa8760c00, 0x00000000, 0x0cf60000, 0x00000010, 0xb8723224, + 0x00000000, 0x03440000, 0x00000008, 0x22000010, 0x00000000, 0x03ca0000, + 0x0000000f, 0x65680010, 0x00000000, 0x0bcf0000, 0x00000000, 0x27f20000, + 0x00000010, 0xb7ef3203, 0x0000000c, 0x21420004, 0x0000000c, 0x73e70019, + 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x8000007e, + 0x00000004, 0xb9723200, 0x00000010, 0x20530000, 0x00000000, 0x22060000, + 0x0000000c, 0x61420004, 0x00000000, 0x25070000, 0x00000000, 0x27970000, + 0x00000000, 0x290e0000, 0x00000010, 0x0ce70010, 0x00000010, 0xb873320f, + 0x0000000f, 0x436c0010, 0x00000000, 0x03f30c00, 0x00000000, 0x03f30000, + 0x00000000, 0x83990e00, 0x00000001, 0x83860e00, 0x00000000, 0x83060e00, + 0x00000003, 0xf66c0c00, 0x00000000, 0x39f30e00, 0x00000000, 0x3af50e00, + 0x00000000, 0x7a740000, 0x0000000f, 0x43680010, 0x00000001, 0x83860e00, + 0x00000000, 0x83060e00, 0x00000003, 0xf4680c00, 0x00000000, 0x286d0000, + 0x00000000, 0x03690000, 0x00000010, 0xb1f60c54, 0x00000000, 0x0a6a0000, + 0x00000000, 0x0aeb0000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0c000000, + 0x00000000, 0x0be90000, 0x00000003, 0x8cf6a000, 0x0000000c, 0x09800002, + 0x00000010, 0x009f0000, 0x00000010, 0xb8173209, 0x00000000, 0x35140000, + 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34970000, + 0x00000004, 0xb8f12e00, 0x00000010, 0x001f0000, 0x00000008, 0x0f800004, + 0x00000018, 0x8000fff7, 0x00000000, 0x03e90000, 0x00000010, 0xb8f6a01a, + 0x00000010, 0x20130019, 0x00000010, 0xb1f10e18, 0x00000000, 0x83973200, + 0x00000000, 0x38700e00, 0x00000000, 0xbb760e00, 0x00000000, 0x37d00000, + 0x0000000c, 0x73e7001a, 0x00000003, 0xb8f1a000, 0x00000000, 0x32140000, + 0x00000000, 0x32950000, 0x00000005, 0x73e72c00, 0x00000000, 0x33190000, + 0x00000005, 0x74680000, 0x00000010, 0x0ce7000d, 0x00000008, 0x22000009, + 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x0000000c, 0x73e70019, + 0x0000000f, 0x65680010, 0x0000000c, 0x21420004, 0x00000018, 0x8000003c, + 0x00000010, 0x20530000, 0x0000000c, 0x61420004, 0x00000000, 0x290e0000, + 0x00000018, 0x80000002, 0x00000010, 0x91973206, 0x00000000, 0x35140000, + 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34990000, + 0x00000004, 0xb8f13200, 0x00000000, 0x83690c00, 0x00000010, 0xb1860013, + 0x00000000, 0x28e90000, 0x00000008, 0x22000004, 0x00000000, 0x23ec0000, + 0x00000000, 0x03690000, 0x00000010, 0xb8660c07, 0x00000009, 0x036cffff, + 0x00000000, 0x326a0000, 0x00000000, 0x32eb0000, 0x00000005, 0x73e70c00, + 0x00000000, 0x33690000, 0x00000005, 0x74680000, 0x0000000c, 0x73e7001c, + 0x00000000, 0x03690000, 0x00000010, 0xb1f60c12, 0x00000010, 0xb1d00c11, + 0x0000000c, 0x21420005, 0x0000000c, 0x33e7001c, 0x00000018, 0x8000000e, + 0x00000010, 0x2e67000d, 0x00000000, 0x03690000, 0x00000010, 0xb1f60c0b, + 0x00000010, 0xb1d00c0a, 0x00000000, 0x03440000, 0x00000008, 0x2200000c, + 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x80000015, + 0x0000000c, 0x33e7001c, 0x00000010, 0x20530000, 0x00000000, 0x22060000, + 0x00000000, 0x290e0000, 0x00000018, 0x000d0000, 0x00000000, 0x06820000, + 0x00000010, 0x2de7000d, 0x00000010, 0x0ce7000c, 0x00000000, 0x27f20000, + 0x00000010, 0xb96d9e0a, 0x00000000, 0xa86d9e00, 0x00000009, 0x0361ffff, + 0x00000010, 0xb7500c07, 0x00000008, 0x2200000f, 0x0000000f, 0x65680010, + 0x00000000, 0x29000000, 0x00000018, 0x80000004, 0x0000000c, 0x33e7001b, + 0x00000010, 0x20530000, 0x00000018, 0x000d0000, 0x00000000, 0x2b820000, + 0x00000010, 0x20d2002f, 0x00000010, 0x0052002e, 0x00000009, 0x054e0007, + 0x00000010, 0xb18a002c, 0x00000000, 0x050a8c00, 0x00000008, 0x850a0008, + 0x00000010, 0x918a0029, 0x00000003, 0xc5008800, 0x00000008, 0xa3460001, + 0x00000010, 0xb1c60007, 0x00000008, 0x22000001, 0x0000000c, 0x29800000, + 0x00000010, 0x20530000, 0x00000000, 0x274e8c00, 0x00000000, 0x66cd0000, + 0x00000000, 0x22c58c00, 0x00000008, 0x22000014, 0x00000003, 0x22c58e00, + 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00, + 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000, + 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x0000000c, 0x69520000, + 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000003, 0x22c58e00, + 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00, + 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000, + 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x00000000, 0xa2c58c00, + 0x00000000, 0xa74e8c00, 0x00000000, 0xe6cd0000, 0x0000000f, 0x620a0010, + 0x00000008, 0x23460001, 0x0000000c, 0x29800000, 0x00000010, 0x20530000, + 0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000, + 0x00000018, 0x00570000 }; + +static int bnx2_TPAT_b06FwReleaseMajor = 0x0; +static int bnx2_TPAT_b06FwReleaseMinor = 0x0; +static int bnx2_TPAT_b06FwReleaseFix = 0x0; +static u32 bnx2_TPAT_b06FwStartAddr = 0x08000858; +static u32 bnx2_TPAT_b06FwTextAddr = 0x08000800; +static int bnx2_TPAT_b06FwTextLen = 0x1314; +static u32 bnx2_TPAT_b06FwDataAddr = 0x08001b40; +static int bnx2_TPAT_b06FwDataLen = 0x0; +static u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000; +static int bnx2_TPAT_b06FwRodataLen = 0x0; +static u32 bnx2_TPAT_b06FwBssAddr = 0x08001b90; +static int bnx2_TPAT_b06FwBssLen = 0x80; +static u32 bnx2_TPAT_b06FwSbssAddr = 0x08001b40; +static int bnx2_TPAT_b06FwSbssLen = 0x48; + +static u32 bnx2_TPAT_b06FwText[(0x1314/4) + 1] = { + 0x0a000216, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20302e36, + 0x2e390000, 0x00060901, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000003, + 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24421b40, 0x3c030800, + 0x24631c10, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, + 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100858, 0x3c1c0800, 0x279c1b40, + 0x0e00051f, 0x00000000, 0x0000000d, 0x8f820024, 0x27bdffe8, 0xafbf0014, + 0x10400004, 0xafb00010, 0x0000000d, 0x00000000, 0x2400015f, 0x8f82001c, + 0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140, + 0x8f820034, 0x30420001, 0x10400006, 0x3070ffff, 0x24020002, 0x2603fffe, + 0xa7420146, 0x0a000246, 0xa7430148, 0xa7400146, 0x8f850034, 0x30a20020, + 0x0002102b, 0x00021023, 0x30460009, 0x30a30c00, 0x24020400, 0x14620002, + 0x34c40001, 0x34c40005, 0xa744014a, 0x3c020800, 0x8c440820, 0x3c030048, + 0x24020002, 0x00832025, 0x30a30006, 0x1062000d, 0x2c620003, 0x50400005, + 0x24020004, 0x10600012, 0x3c020001, 0x0a000271, 0x00000000, 0x10620007, + 0x24020006, 0x1462000f, 0x3c020111, 0x0a000269, 0x00821025, 0x0a000268, + 0x3c020101, 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830030, + 0x0a000271, 0x00000000, 0x00821025, 0xaf421000, 0xaf800030, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x8f830030, 0x1060003f, 0x3c048000, + 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039, 0x00000000, + 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000, 0x97421014, + 0x14400031, 0x00000000, 0x97421008, 0x8f84001c, 0x24420006, 0x00024082, + 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001, 0x10400004, + 0x00000000, 0x0000000d, 0x0a0002b0, 0x00081080, 0x5460000f, 0x30a5ffff, + 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b, 0x00621824, + 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fc, 0x8ce20000, + 0x0a0002af, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b, 0x00621824, + 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000206, 0x8ce20000, + 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000, 0x8c620840, + 0x24420001, 0xac620840, 0x8f820008, 0x10400003, 0x00000000, 0x0e000660, + 0x00000000, 0x8f840028, 0x02002821, 0x24820008, 0x30421fff, 0x24434000, + 0x0343d821, 0x30a30007, 0xaf840018, 0xaf820028, 0xaf420084, 0x10600002, + 0x24a20007, 0x3045fff8, 0x8f820044, 0x8f840004, 0x00451821, 0xaf82002c, + 0x0064102b, 0xaf830044, 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, + 0x34028000, 0x8fbf0014, 0x8fb00010, 0x00821021, 0x03421821, 0x3c021000, + 0xaf83001c, 0xaf440080, 0xaf420178, 0x03e00008, 0x27bd0018, 0x8f820024, + 0x27bdffe8, 0xafbf0014, 0x10400004, 0xafb00010, 0x0000000d, 0x00000000, + 0x24000249, 0x8f85001c, 0x24020001, 0xaf820024, 0x8ca70008, 0xa3800023, + 0x8f620004, 0x3c100800, 0x26041b90, 0x00021402, 0xa3820010, 0x304600ff, + 0x24c60005, 0x0e00064a, 0x00063082, 0x8f640004, 0x8f430108, 0x3c021000, + 0x00621824, 0xa7840020, 0x10600008, 0x00000000, 0x97420104, 0x93830023, + 0x2442ffec, 0x34630002, 0xa3830023, 0x0a000304, 0x3045ffff, 0x97420104, + 0x2442fff0, 0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x14400004, + 0x00000000, 0x93820023, 0x34420001, 0xa3820023, 0x93830023, 0x24020001, + 0x10620009, 0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, + 0x1062000a, 0x00000000, 0x0a000325, 0x00000000, 0x8f82001c, 0x8c43000c, + 0x3c04ffff, 0x00641824, 0x00651825, 0x0a000325, 0xac43000c, 0x8f82001c, + 0x8c430010, 0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, + 0x3042ffff, 0x24420002, 0x00021083, 0xa3820038, 0x304500ff, 0x8f82001c, + 0x3c04ffff, 0x00052880, 0x00a22821, 0x8ca70000, 0x97820020, 0x97430104, + 0x00e42024, 0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x93840038, + 0x26061b90, 0x00041080, 0x00461021, 0x90430000, 0x3063000f, 0x00832021, + 0xa3840022, 0x308200ff, 0x3c04fff6, 0x24420003, 0x00021080, 0x00461021, + 0x8c450000, 0x93830022, 0x8f82001c, 0x3484ffff, 0x00a43824, 0x00031880, + 0x00621821, 0xaf850000, 0xac67000c, 0x93820022, 0x93830022, 0x8f84001c, + 0x24420003, 0x00021080, 0x00461021, 0x24630004, 0x00031880, 0xac470000, + 0x93820022, 0x00661821, 0x94670002, 0x00021080, 0x00441021, 0xac670000, + 0x24030010, 0xac470010, 0xa7430140, 0x24030002, 0xa7400142, 0xa7400144, + 0xa7430146, 0x97420104, 0x8f840034, 0x24030001, 0x2442fffe, 0x30840006, + 0xa7420148, 0x24020002, 0xa743014a, 0x1082000d, 0x2c820003, 0x10400005, + 0x24020004, 0x10800011, 0x3c020009, 0x0a000383, 0x00000000, 0x10820007, + 0x24020006, 0x1482000d, 0x3c020119, 0x0a00037d, 0x24030001, 0x0a00037c, + 0x3c020109, 0x3c020019, 0x24030001, 0xaf421000, 0xaf830030, 0x0a000383, + 0x00000000, 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x93820010, 0x24030008, 0x8f840030, 0x24420002, 0x30420007, + 0x00621823, 0x30630007, 0xaf83000c, 0x10800005, 0x3c038000, 0x8f421000, + 0x00431024, 0x1040fffd, 0x00000000, 0x8f820028, 0xaf820018, 0x24420010, + 0x30421fff, 0xaf820028, 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, + 0x3063ffff, 0x30620007, 0x10400002, 0x24620007, 0x3043fff8, 0x8f820044, + 0x8f840004, 0x00431821, 0xaf82002c, 0x0064102b, 0xaf830044, 0x14400002, + 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, 0x8fbf0014, 0x8fb00010, + 0x00821021, 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0xaf420178, + 0x03e00008, 0x27bd0018, 0x8f820024, 0x27bdffe8, 0xafbf0014, 0x14400004, + 0xafb00010, 0x0000000d, 0x00000000, 0x240002db, 0x8f620004, 0x04410009, + 0x3c050800, 0x93820022, 0x8f830000, 0x24a41b90, 0xaf800024, 0x24420003, + 0x00021080, 0x00441021, 0xac430000, 0x93820038, 0x24a51b90, 0x93860010, + 0x3c040001, 0x27700008, 0x24420001, 0x00021080, 0x00451021, 0x8c430000, + 0x24c60005, 0x00063082, 0x00641821, 0x02002021, 0x0e00064a, 0xac430000, + 0x93840022, 0x3c057fff, 0x8f620004, 0x00042080, 0x00902021, 0x8c830004, + 0x34a5ffff, 0x00451024, 0x00621821, 0xac830004, 0x93850038, 0x3c07ffff, + 0x93840010, 0x00052880, 0x00b02821, 0x8ca30000, 0x97420104, 0x97860020, + 0x00671824, 0x00441021, 0x00461023, 0x3042ffff, 0x00621825, 0xaca30000, + 0x93830023, 0x24020001, 0x10620009, 0x28620002, 0x1440001a, 0x24020002, + 0x10620018, 0x24020003, 0x1062000d, 0x00000000, 0x0a000411, 0x00000000, + 0x93820010, 0x97430104, 0x8e04000c, 0x00621821, 0x2463fff2, 0x3063ffff, + 0x00872024, 0x00832025, 0x0a000411, 0xae04000c, 0x93820010, 0x97430104, + 0x8e040010, 0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, + 0xae040010, 0x9783000e, 0x8f840034, 0x2402000a, 0xa7420140, 0xa7430142, + 0x93820010, 0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, + 0xa7430148, 0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, + 0x24020004, 0x10800011, 0x3c020041, 0x0a000437, 0x00000000, 0x10820007, + 0x24020006, 0x1482000d, 0x3c020151, 0x0a000431, 0x24030001, 0x0a000430, + 0x3c020141, 0x3c020051, 0x24030001, 0xaf421000, 0xaf830030, 0x0a000437, + 0x00000000, 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x8f820030, 0x93840010, 0x8f850028, 0x10400005, 0x3c038000, + 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x2483000a, 0x30620007, + 0x10400002, 0x24620007, 0x304303f8, 0x00a31021, 0x30421fff, 0xaf850018, + 0xaf820028, 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, + 0x30620007, 0x10400002, 0x24620007, 0x3043fff8, 0x8f820044, 0x8f840004, + 0x00431821, 0xaf82002c, 0x0064102b, 0xaf830044, 0x14400002, 0x00641023, + 0xaf820044, 0x8f840044, 0x34028000, 0x8fbf0014, 0x8fb00010, 0x00821021, + 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0xaf420178, 0x03e00008, + 0x27bd0018, 0x3c026000, 0x8c444448, 0x3c030800, 0xac64082c, 0x8f620000, + 0x97430104, 0x3c048000, 0x3046ffff, 0x3067ffff, 0x8f420178, 0x00441024, + 0x1440fffd, 0x2402000a, 0x30c30007, 0xa7420140, 0x24020008, 0x00431023, + 0x30420007, 0x24c3fffe, 0xa7420142, 0xa7430144, 0xa7400146, 0xa7470148, + 0x8f420108, 0x3c036000, 0x8f850034, 0x30420020, 0x0002102b, 0x00021023, + 0x30420009, 0x34420001, 0xa742014a, 0x8c644448, 0x3c020800, 0x30a50006, + 0xac440830, 0x24020002, 0x10a2000d, 0x2ca20003, 0x10400005, 0x24020004, + 0x10a00011, 0x3c020041, 0x0a0004a8, 0x00000000, 0x10a20007, 0x24020006, + 0x14a2000d, 0x3c020151, 0x0a0004a2, 0x24030001, 0x0a0004a1, 0x3c020141, + 0x3c020051, 0x24030001, 0xaf421000, 0xaf830030, 0x0a0004a8, 0x00000000, + 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8f820030, 0x24c30008, 0x10400006, 0x30e6ffff, 0x3c048000, 0x8f421000, + 0x00441024, 0x1040fffd, 0x00000000, 0x3c026000, 0x8c444448, 0x3065ffff, + 0x3c020800, 0x30a30007, 0x10600003, 0xac440834, 0x24a20007, 0x3045fff8, + 0x8f840028, 0x00851021, 0x30421fff, 0x24434000, 0x0343d821, 0x30c30007, + 0xaf840018, 0xaf820028, 0xaf420084, 0x10600002, 0x24c20007, 0x3046fff8, + 0x8f820044, 0x8f840004, 0x00461821, 0xaf82002c, 0x0064102b, 0xaf830044, + 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, 0x3c030800, + 0x8c650844, 0x00821021, 0x03421821, 0xaf83001c, 0xaf440080, 0x10a00006, + 0x2402000e, 0x93830043, 0x14620004, 0x3c021000, 0x2402043f, 0xa7420148, + 0x3c021000, 0x3c036000, 0xaf420178, 0x8c644448, 0x3c020800, 0x03e00008, + 0xac440838, 0x8f820034, 0x30424000, 0x10400005, 0x24020800, 0x0000000d, + 0x00000000, 0x24000405, 0x24020800, 0xaf420178, 0x97440104, 0x3c030008, + 0xaf430140, 0x8f820034, 0x30420001, 0x10400006, 0x3085ffff, 0x24020002, + 0x24a3fffe, 0xa7420146, 0x0a0004ff, 0xa7430148, 0xa7400146, 0x8f840028, + 0x2402000d, 0xa742014a, 0x24830008, 0x30631fff, 0x24624000, 0x0342d821, + 0x30a20007, 0xaf840018, 0xaf830028, 0xaf430084, 0x10400002, 0x24a20007, + 0x3045fff8, 0x8f820044, 0x8f840004, 0x00451821, 0xaf82002c, 0x0064102b, + 0xaf830044, 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, + 0x00821021, 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0x03e00008, + 0xaf420178, 0x27bdffe8, 0x3c046008, 0xafbf0014, 0xafb00010, 0x8c825000, + 0x3c1a8000, 0x2403ff7f, 0x375b4000, 0x00431024, 0x3442380c, 0xac825000, + 0x8f430008, 0x3c100800, 0x37428000, 0x34630001, 0xaf430008, 0xaf82001c, + 0x3c02601c, 0xaf800028, 0xaf400080, 0xaf400084, 0x8c450008, 0x3c036000, + 0x8c620808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0, 0x38420010, + 0x2c420001, 0xaf850004, 0xaf820008, 0x0e00062f, 0x00000000, 0x8f420000, + 0x30420001, 0x1040fffb, 0x00000000, 0x8f440108, 0x30822000, 0xaf840034, + 0x10400004, 0x8e02083c, 0x24420001, 0x0a00059d, 0xae02083c, 0x30820200, + 0x10400027, 0x00000000, 0x97420104, 0x1040001c, 0x30824000, 0x14400005, + 0x00000000, 0x0e00022d, 0x00000000, 0x0a000592, 0x00000000, 0x8f620008, + 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007, 0x28620031, + 0x14400031, 0x24020040, 0x10620007, 0x00000000, 0x0a000592, 0x00000000, + 0x0e0002dd, 0x00000000, 0x0a000592, 0x00000000, 0x0e0003b8, 0x00000000, + 0x0a000592, 0x00000000, 0x30820040, 0x1440002d, 0x00000000, 0x0000000d, + 0x00000000, 0x240004a6, 0x0a00059d, 0x00000000, 0x8f430100, 0x24020d00, + 0x1462000f, 0x30820006, 0x97420104, 0x10400005, 0x30820040, 0x0e0004e9, + 0x00000000, 0x0a000592, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, + 0x00000000, 0x240004b8, 0x0a00059d, 0x00000000, 0x1040000e, 0x30821000, + 0x10400005, 0x00000000, 0x0e00065d, 0x00000000, 0x0a000592, 0x00000000, + 0x0e00046b, 0x00000000, 0x8f820040, 0x24420001, 0xaf820040, 0x0a00059d, + 0x00000000, 0x30820040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, + 0x240004cf, 0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a00053f, + 0x00000000, 0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, + 0x00621824, 0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, + 0x34420001, 0xaf420008, 0x37428000, 0xaf800028, 0xaf82001c, 0xaf400080, + 0xaf400084, 0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, + 0x3042fff0, 0x38420010, 0x2c420001, 0xaf860004, 0xaf820008, 0x03e00008, + 0x00000000, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, + 0x8f820028, 0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf820018, + 0xaf830028, 0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, + 0x24820007, 0x3044fff8, 0x8f820044, 0x8f830004, 0x00442021, 0xaf82002c, + 0x0083102b, 0xaf840044, 0x14400002, 0x00831023, 0xaf820044, 0x8f820044, + 0x34038000, 0x00431821, 0x03432021, 0xaf84001c, 0x03e00008, 0xaf420080, + 0x8f830034, 0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, + 0x24020004, 0x10600012, 0x3c020001, 0x0a000601, 0x00000000, 0x10620007, + 0x24020006, 0x1462000f, 0x3c020111, 0x0a0005f9, 0x00821025, 0x0a0005f8, + 0x3c020101, 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830030, + 0x0a000601, 0x00000000, 0x00821025, 0xaf421000, 0xaf800030, 0x00000000, + 0x00000000, 0x00000000, 0x03e00008, 0x00000000, 0x8f820030, 0x10400005, + 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, + 0x00000000, 0x8f820034, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, + 0x0e00022d, 0x00000000, 0x0a00062d, 0x8fbf0010, 0x8f620008, 0x8f630000, + 0x24020030, 0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, + 0x8fbf0010, 0x24020040, 0x10620007, 0x00000000, 0x0a00062d, 0x00000000, + 0x0e0002dd, 0x00000000, 0x0a00062d, 0x8fbf0010, 0x0e0003b8, 0x00000000, + 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f84003c, 0x1080000f, 0x3c026000, + 0x8c430c3c, 0x30630fff, 0xaf830014, 0x14600011, 0x3082000f, 0x10400005, + 0x308200f0, 0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, + 0x00000000, 0x2400050e, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, + 0x24000513, 0x03e00008, 0x00000000, 0xaf83003c, 0x03e00008, 0x00000000, + 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, + 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a000659, 0x00a01021, + 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, + 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x3c040800, 0x8c82084c, + 0x54400007, 0xac80084c, 0x8f820034, 0x24030400, 0x30420c00, 0x1443005b, + 0x00000000, 0xac80084c, 0x0000000d, 0x00000000, 0x2400003c, 0x3c026000, + 0x8c444448, 0x3c030800, 0xac640850, 0x24000043, 0x97420104, 0x3045ffff, + 0x000530c2, 0x24a2007f, 0x000239c2, 0x2400004e, 0x3c046020, 0x24030020, + 0xac830000, 0x8c820000, 0x30420020, 0x10400005, 0x3c036020, 0x8c620000, + 0x30420020, 0x1440fffd, 0x00000000, 0x3c026020, 0x8c430010, 0x24040001, + 0x0087102b, 0x30ea007f, 0x24abfffe, 0x10400010, 0x00034240, 0x3c056020, + 0x24090020, 0xaca90000, 0x8ca20000, 0x30420020, 0x10400006, 0x24840001, + 0x3c036020, 0x8c620000, 0x30420020, 0x1440fffd, 0x00000000, 0x0087102b, + 0x1440fff4, 0x00000000, 0x8f85001c, 0x3c026020, 0x8c430010, 0x3c046020, + 0x34848000, 0x006a1825, 0x01034025, 0x2400006b, 0x10c0000b, 0x00000000, + 0x8ca30000, 0x24a50004, 0x8ca20000, 0x24a50004, 0x24c6ffff, 0xac820000, + 0x24840004, 0xac830000, 0x14c0fff7, 0x24840004, 0x24000077, 0x3c020007, + 0x34427700, 0x3c036000, 0xac6223c8, 0xac6b23cc, 0xac6823e4, 0x24000086, + 0x3c046000, 0x3c038000, 0x8c8223f8, 0x00431024, 0x1440fffd, 0x3c021000, + 0x3c056000, 0x24030019, 0xaca223f8, 0xa743014a, 0x8ca44448, 0x3c020800, + 0xac440854, 0x03e00008, 0x00000000, 0x00000000 }; + +static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_TPAT_b06FwBss[(0x80/4) + 1] = { 0x00000000 }; +static u32 bnx2_TPAT_b06FwSbss[(0x48/4) + 1] = { 0x00000000 }; + +static int bnx2_TXP_b06FwReleaseMajor = 0x0; +static int bnx2_TXP_b06FwReleaseMinor = 0x0; +static int bnx2_TXP_b06FwReleaseFix = 0x0; +static u32 bnx2_TXP_b06FwStartAddr = 0x08002090; +static u32 bnx2_TXP_b06FwTextAddr = 0x08000000; +static int bnx2_TXP_b06FwTextLen = 0x3ffc; +static u32 bnx2_TXP_b06FwDataAddr = 0x08004020; +static int bnx2_TXP_b06FwDataLen = 0x0; +static u32 bnx2_TXP_b06FwRodataAddr = 0x00000000; +static int bnx2_TXP_b06FwRodataLen = 0x0; +static u32 bnx2_TXP_b06FwBssAddr = 0x08004060; +static int bnx2_TXP_b06FwBssLen = 0x194; +static u32 bnx2_TXP_b06FwSbssAddr = 0x08004020; +static int bnx2_TXP_b06FwSbssLen = 0x34; +static u32 bnx2_TXP_b06FwText[(0x3ffc/4) + 1] = { + 0x0a000824, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x302e362e, + 0x39000000, 0x00060900, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, + 0x0000000d, 0x3c020800, 0x24424020, 0x3c030800, 0x246341f4, 0xac400000, + 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, + 0x3c100800, 0x26102090, 0x3c1c0800, 0x279c4020, 0x0e000a0e, 0x00000000, + 0x0000000d, 0x8f840014, 0x27bdffe8, 0xafb00010, 0x8f460104, 0x8f830008, + 0x8c8500ac, 0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, + 0x8c8200ac, 0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0xa7420e16, + 0x8f430e18, 0x00005021, 0x00c53023, 0x10c001a3, 0xaf430e1c, 0x240f0800, + 0x3c0e1000, 0x2419fff8, 0x24100010, 0x3c188100, 0x93620008, 0x10400009, + 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000, 0x97620010, + 0x3042ffff, 0x0a000862, 0xaf420e00, 0xaf460e00, 0x8f420000, 0x30420008, + 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff, 0x30820001, + 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a0009e6, 0x00000000, + 0x0000000d, 0x3083a040, 0x24020040, 0x14620049, 0x3082a000, 0x8f87000c, + 0x30880036, 0x30890008, 0xaf4f0178, 0x00e01821, 0x9742008a, 0x00431023, + 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa, 0x00000000, 0x8f830018, + 0x00a05021, 0x00c53023, 0x24e24000, 0x03422821, 0x306b00ff, 0x24630001, + 0xaf830018, 0x93840012, 0x000b1400, 0x3c030100, 0x00431025, 0xaca20000, + 0x8f820018, 0x30840007, 0x00042240, 0x34870001, 0x00e83825, 0x1120000f, + 0xaca20004, 0x97430e0a, 0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, + 0xaf430160, 0x25430006, 0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, + 0xaf84000c, 0x0a0008a9, 0x00000000, 0x8f83000c, 0x25420002, 0xa7420158, + 0x24630008, 0x30631fff, 0xaf83000c, 0x54c0000c, 0x8f420e14, 0x97420e10, + 0x97430e12, 0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, + 0x8f420e18, 0x34e70040, 0xaca200ac, 0x8f420e14, 0x8f430e1c, 0xaf420144, + 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a0009f1, 0xaf4e0178, 0x10400128, + 0x00000000, 0x97620010, 0x00a2102b, 0x10400003, 0x30820040, 0x10400122, + 0x00000000, 0xafa60008, 0xa7840010, 0xaf850004, 0x93620008, 0x1440005e, + 0x27ac0008, 0xaf60000c, 0x97820010, 0x30424000, 0x10400002, 0x2403000e, + 0x24030016, 0xa363000a, 0x24034007, 0xaf630014, 0x93820012, 0x8f630014, + 0x30420007, 0x00021240, 0x00621825, 0xaf630014, 0x97820010, 0x8f630014, + 0x30420010, 0x00621825, 0xaf630014, 0x97820010, 0x30420008, 0x5040000e, + 0x00002821, 0x8f620014, 0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, + 0x00781825, 0xaf630004, 0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, + 0x0a0008f2, 0xa363000a, 0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, + 0x30421f00, 0x00021182, 0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, + 0xa7620010, 0x93630009, 0x24020008, 0x24630002, 0x30630007, 0x00431023, + 0x30420007, 0xa362000b, 0x93640009, 0x97620010, 0x8f890004, 0x97830010, + 0x00441021, 0x00a21021, 0x30630040, 0x10600006, 0x3045ffff, 0x15250005, + 0x0125102b, 0x3c068000, 0x0a000925, 0x00005821, 0x0125102b, 0x144000c8, + 0x00005021, 0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, + 0xaf420e18, 0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, + 0x97420e08, 0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, + 0xaf830004, 0x97620010, 0x0a000936, 0x304dffff, 0x8f890004, 0x97820010, + 0x30420040, 0x10400004, 0x01206821, 0x3c068000, 0x0a000936, 0x00005821, + 0x97630010, 0x8f820004, 0x144300a7, 0x00005021, 0x00003021, 0x240b0001, + 0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040, + 0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025, + 0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003f, + 0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000, + 0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7, + 0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000, + 0x03422821, 0x00605021, 0x24630001, 0x314200ff, 0x00021400, 0xaf830018, + 0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00, + 0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008, + 0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c, + 0x8f660004, 0x8f670014, 0xaf4f0178, 0x3063ffff, 0xa7430144, 0x97420e16, + 0xa7420146, 0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, + 0xaf460160, 0xa7480158, 0xaf470154, 0xaf4e0178, 0x00501021, 0x30421fff, + 0xaf82000c, 0x0a0009c5, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, + 0x2463000a, 0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, + 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, + 0x1440fff7, 0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, + 0x24424000, 0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, + 0x310200ff, 0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, + 0xaca40000, 0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, + 0x8f450e1c, 0x8f660004, 0x8f670014, 0xaf4f0178, 0x3063ffff, 0xa7430144, + 0x97420e16, 0x308400ff, 0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, + 0x25420007, 0x00591024, 0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, + 0xaf4e0178, 0x00621821, 0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, + 0x00000000, 0x8f620014, 0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, + 0x004d1021, 0xaf62000c, 0x93630008, 0x14600008, 0x00000000, 0x11600006, + 0x00000000, 0x8f630014, 0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, + 0xa36b0008, 0x01205021, 0x15400016, 0x8fa60008, 0x97420e14, 0x97430e16, + 0x8f850014, 0x00021400, 0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, + 0x0a0009f3, 0xac8200ac, 0x97420e14, 0x97430e16, 0x8f840014, 0x00021400, + 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c, 0x00005021, 0x0a0009f3, + 0xaca200ac, 0x14c0fe64, 0x00000000, 0x55400018, 0x8fb00010, 0x3c038000, + 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97430e14, 0x8f440e1c, + 0x24020800, 0xaf420178, 0x3063ffff, 0xa7430144, 0x97420e16, 0x3c031000, + 0xa7420146, 0x24020240, 0xaf440148, 0xa3400152, 0xa740015a, 0xaf400160, + 0xa7400158, 0xaf420154, 0xaf430178, 0x8fb00010, 0x03e00008, 0x27bd0018, + 0x27bdffd8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, 0x03421821, + 0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, + 0xaf440e00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3c0200ff, 0x3442fffd, 0x3c046004, 0xaf420e00, 0x8c835000, 0x24130d00, + 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c, 0x24020009, + 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e000fa1, 0x00000000, + 0x0e000a96, 0x00000000, 0x3c020800, 0x24504080, 0x8f420000, 0x30420001, + 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020, 0x93430108, + 0xa3830012, 0x93820012, 0x30420001, 0x10400008, 0x00000000, 0x93820012, + 0x30420006, 0x00021100, 0x0e00083b, 0x0050d821, 0x0a000a52, 0x00000000, + 0x14930005, 0x00000000, 0x0e00083b, 0x265b4100, 0x0a000a52, 0x00000000, + 0x0e000ba3, 0x00000000, 0xaf510138, 0x0a000a36, 0x00000000, 0x27bdfff8, + 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c, 0x9743008a, 0x3063ffff, + 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, + 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082, 0x00021080, 0x24424000, + 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff, 0x8f82000c, 0x24840007, + 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c, 0x03e00008, 0x00000000, + 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, 0x03421821, + 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, 0x3c046004, 0xaf420e00, + 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c, 0x24030009, 0xac825000, + 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e000fa1, 0x00000000, 0x0e000a96, + 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0x3c02000a, + 0x03421821, 0x3c040800, 0x24844120, 0x24050018, 0xafbf0010, 0xaf830024, + 0x0e000fad, 0x00003021, 0x3c050800, 0x3c020800, 0x24423d60, 0xaca24180, + 0x24a54180, 0x3c020800, 0x24423e18, 0x3c030800, 0x24633e2c, 0x3c040800, + 0xaca20004, 0x3c020800, 0x24423d68, 0xaca30008, 0xac824190, 0x24844190, + 0x3c020800, 0x24423da4, 0x3c070800, 0x24e73de4, 0x3c060800, 0x24c63e40, + 0x3c050800, 0x24a52b28, 0x3c030800, 0xac820004, 0x3c020800, 0x24423e48, + 0xac870008, 0xac86000c, 0xac850010, 0xac6241b0, 0x246341b0, 0x8fbf0010, + 0x3c020800, 0x24423e60, 0xac620004, 0xac670008, 0xac66000c, 0xac650010, + 0x03e00008, 0x27bd0018, 0x27bdffc8, 0x3c020800, 0x24424120, 0xafbf0030, + 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x90470021, 0x8c510008, + 0x8c45001c, 0x8f900020, 0x3c060800, 0x3c038000, 0x8f420178, 0x00431024, + 0x1440fffd, 0x8cc2414c, 0x24c3414c, 0x2473ffd4, 0xaf420144, 0x8e620030, + 0x30b22000, 0xaf420148, 0x3c021000, 0xaf50014c, 0xa3470152, 0xa7510158, + 0xaf450154, 0xaf420178, 0x12400004, 0x3c030800, 0x8c620030, 0x24420001, + 0xac620030, 0x93420109, 0x9344010a, 0x00111c00, 0xafa30018, 0x00071a00, + 0xafa50014, 0x8cc5414c, 0x00021600, 0x00042400, 0x00441025, 0x00431025, + 0xafa20010, 0x8f440100, 0x8e660030, 0x0e000fe1, 0x02003821, 0x1640000e, + 0x8fbf0030, 0x8f820000, 0x8e630030, 0x8c44017c, 0x02031823, 0x00711823, + 0x00641823, 0x2c630002, 0x14600006, 0x8fb3002c, 0x0000000d, 0x00000000, + 0x240000ca, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, + 0x03e00008, 0x27bd0038, 0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, + 0xad020004, 0x8f4309e0, 0xad030008, 0x934409d9, 0x24020001, 0x30840003, + 0x1082001f, 0x30a900ff, 0x28820002, 0x10400005, 0x24020002, 0x10800009, + 0x3c0a0800, 0x0a000b64, 0x93420934, 0x1082000b, 0x24020003, 0x10820026, + 0x3c0a0800, 0x0a000b64, 0x93420934, 0x974209e4, 0x00021400, 0x34420800, + 0xad02000c, 0x0a000b63, 0x25080010, 0x974209e4, 0x00021400, 0x34428100, + 0xad02000c, 0x974309e8, 0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, + 0x0a000b63, 0x25080014, 0x974409e4, 0x3c050800, 0x24a24120, 0x94430018, + 0x94460010, 0x9447000c, 0x00a05021, 0x24020800, 0xad000010, 0xad020014, + 0x00042400, 0x00661821, 0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, + 0x0a000b63, 0x25080018, 0x974209e4, 0x3c050800, 0x00021400, 0x34428100, + 0xad02000c, 0x974409e8, 0x24a24120, 0x94430018, 0x94460010, 0x9447000c, + 0x00a05021, 0x24020800, 0xad000014, 0xad020018, 0x00042400, 0x00661821, + 0x00671823, 0x2463ffee, 0x00832025, 0xad040010, 0x2508001c, 0x93420934, + 0x93450921, 0x3c074000, 0x25444120, 0x94830014, 0x94860010, 0x00021082, + 0x00021600, 0x00052c00, 0x00a72825, 0x00451025, 0x00661821, 0x00431025, + 0xad020000, 0x97830028, 0x974209ea, 0x00621821, 0x00031c00, 0xad030004, + 0x97820028, 0x24420001, 0x30427fff, 0xa7820028, 0x93430920, 0x3c020006, + 0x00031e00, 0x00621825, 0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, + 0xad030010, 0x8f440938, 0x25080014, 0xad040000, 0x8f820020, 0x11200004, + 0xad020004, 0x8f420940, 0x0a000b8d, 0x2442ffff, 0x8f420940, 0xad020008, + 0x8f440948, 0x8f420940, 0x93430936, 0x00822823, 0x00652806, 0x3402ffff, + 0x0045102b, 0x54400001, 0x3405ffff, 0x93420937, 0x25444120, 0x90830020, + 0xad000010, 0x00021700, 0x34630010, 0x00031c00, 0x00431025, 0x00451025, + 0xad02000c, 0x03e00008, 0x25020014, 0x27bdffb0, 0x3c020008, 0x03421821, + 0xafbf004c, 0xafbe0048, 0xafb70044, 0xafb60040, 0xafb5003c, 0xafb40038, + 0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028, 0xaf830000, 0x24020040, + 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954, 0x8f45095c, + 0xaf820030, 0xaf830020, 0xaf84001c, 0xaf85002c, 0x93430900, 0x24020020, + 0x10620005, 0x24020030, 0x10620022, 0x3c030800, 0x0a000bf1, 0x8c62002c, + 0x24020088, 0xaf420818, 0x3c020800, 0x24424180, 0xafa20020, 0x93430109, + 0x3c020800, 0x10600009, 0x24574190, 0x3c026000, 0x24030100, 0xac43081c, + 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x2400031d, 0x9342010a, + 0x30420080, 0x1440001c, 0x00000000, 0x3c026000, 0x24030100, 0xac43081c, + 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x24000324, 0x0a000bf4, + 0x00000000, 0x93430109, 0x3063007f, 0x00031140, 0x000318c0, 0x00431021, + 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800, 0x244241d0, 0x3c030800, + 0x247741e0, 0x0a000bf4, 0xafa20020, 0x24420001, 0x0a000f4c, 0xac62002c, + 0x8f840000, 0x8f850020, 0x24020800, 0xaf420178, 0x8f4209a4, 0x8c83017c, + 0x00a21023, 0x00431023, 0x2c420002, 0x14400004, 0x00000000, 0x0000000d, + 0x00000000, 0x24000349, 0x8f420104, 0x8f430988, 0x00431023, 0x58400005, + 0x8f4209a0, 0x0000000d, 0x00000000, 0x2400034d, 0x8f4209a0, 0x3c100800, + 0xae02414c, 0x8f4309a4, 0x2604414c, 0x2491ffd4, 0xae230030, 0x8f420104, + 0xae250024, 0x00431023, 0xac82ffd4, 0x8fa30020, 0x8c620000, 0x0040f809, + 0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024, + 0x8e22001c, 0x32500040, 0x2403ffbf, 0x00431024, 0x0a000f13, 0xae22001c, + 0x32420020, 0x10400002, 0x3c020800, 0x245741b0, 0x32420001, 0x14400007, + 0x00000000, 0x8f820008, 0xaf420080, 0x8ec3414c, 0xaf430e10, 0x8e220030, + 0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff, + 0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100, + 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x24000384, + 0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32500040, 0x24072000, + 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec2414c, + 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030100, 0xaf420148, + 0x24020047, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, 0xa7430158, + 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, 0x24630001, + 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, 0x00021600, + 0x00031c00, 0x00431025, 0x34424700, 0xafa20010, 0x8f440100, 0x0e000fe1, + 0x3c070100, 0x3c030800, 0x24624120, 0x0a000d01, 0x8c43001c, 0x32820002, + 0x10400047, 0x3c039000, 0x34630001, 0x8f820008, 0x32500040, 0x3c048000, + 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, + 0x8f830000, 0x90620005, 0x3c058000, 0x34420008, 0xa0620005, 0x8f860000, + 0x34a50001, 0x8f840008, 0x8cc20074, 0x3c038000, 0x00852025, 0x00431025, + 0xacc20074, 0xaf440020, 0x90c3007b, 0x9342010a, 0x14620028, 0x3c040800, + 0x24072000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, + 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030100, + 0xaf420148, 0x24020046, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, + 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, + 0x24630001, 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, + 0x00021600, 0x00031c00, 0x00431025, 0x34424600, 0xafa20010, 0x8f440100, + 0x0e000fe1, 0x3c070100, 0x3c040800, 0x24824120, 0x0a000d01, 0x8c43001c, + 0x93420108, 0x30420010, 0x50400050, 0x9343093f, 0x8f860000, 0x90c3007f, + 0x90c2007e, 0x90c40080, 0x306800ff, 0x00021600, 0x00081c00, 0x00431025, + 0x00042200, 0x90c3007a, 0x90c5000a, 0x00441025, 0x11050028, 0x00623825, + 0xa0c8000a, 0x24086000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, + 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, + 0x00001821, 0xaf420148, 0x24020052, 0xaf47014c, 0xa3420152, 0x3c021000, + 0xa7430158, 0xaf480154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, + 0x24630001, 0xad230030, 0x93420109, 0x9343010a, 0xafa80014, 0xafa00018, + 0x00021600, 0x00031c00, 0x00431025, 0x34425200, 0xafa20010, 0x0e000fe1, + 0x8f440100, 0x0a000cfb, 0x00000000, 0x3c026000, 0x24030100, 0xac43081c, + 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003cd, 0x16800009, + 0x3c040800, 0x3c030800, 0x24624120, 0x8c43001c, 0x32500040, 0x2404ffbf, + 0x00641824, 0x0a000f13, 0xac43001c, 0x8c824120, 0x10400005, 0x3c030800, + 0x8c620034, 0xac804120, 0x24420001, 0xac620034, 0x9343093f, 0x24020012, + 0x1462000f, 0x329e0038, 0x17c0000c, 0x3c030800, 0x8f830000, 0x8c62004c, + 0xac62005c, 0x3c020800, 0x24444120, 0x8c82001c, 0x32500040, 0x2403ffbf, + 0x00431024, 0x0a000f13, 0xac82001c, 0xac604120, 0x97420908, 0x000211c0, + 0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c, + 0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa7820028, 0x3c020800, 0x24444120, + 0xac830028, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830014, + 0x934209d8, 0x00621821, 0xa4830016, 0x934209d8, 0x93430934, 0x00809821, + 0x00431021, 0x24420010, 0xa4820012, 0x0000a821, 0x24020006, 0x13c00003, + 0xae62001c, 0x0a000d82, 0x24120008, 0x8f420958, 0x8f830020, 0x8f84002c, + 0x00431023, 0x00832023, 0x04800003, 0xae620004, 0x04410003, 0x0082102b, + 0x0a000d4e, 0xae600004, 0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, + 0x00000000, 0x00409021, 0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, + 0x1060002b, 0x3c02c000, 0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, + 0x1040fffd, 0x00000000, 0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, + 0xaf830004, 0x8f840004, 0x0044102b, 0x1040000b, 0x24150001, 0x24020100, + 0x3c016000, 0xac22081c, 0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, + 0x00000000, 0x24000449, 0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, + 0x02429025, 0x32420002, 0x5040001d, 0x8f470940, 0x12a00006, 0x8ec2414c, + 0x8f830000, 0xac6200a8, 0x8f840000, 0x8e620030, 0xac8200ac, 0x32420004, + 0x50400013, 0x8f470940, 0x3c020800, 0x3283007d, 0x106000fe, 0x245741b0, + 0x32820001, 0x50400006, 0x36520002, 0x8f830030, 0x8f420940, 0x106200f7, + 0x00000000, 0x36520002, 0x24020008, 0xa660000c, 0xa662000e, 0xae600008, + 0xa2600020, 0x8f470940, 0x3c030800, 0x24684120, 0x8d020028, 0x8d050008, + 0x9504000c, 0x9506000a, 0x95030022, 0x00451021, 0x00862021, 0x00641821, + 0xaf870030, 0xad020028, 0x32820030, 0x10400006, 0xa5030010, 0x91020020, + 0x32910040, 0x34420004, 0x0a000dd4, 0xa1020020, 0x93420923, 0x30420040, + 0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023, + 0x0442000a, 0x3c039000, 0x95020010, 0x8c630084, 0x00821021, 0x00621823, + 0x1c600004, 0x3c039000, 0x91020020, 0x34420001, 0xa1020020, 0x34630001, + 0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, + 0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a, + 0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014, + 0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, + 0x3c040800, 0x24904120, 0x9602000c, 0x96030016, 0x9604000e, 0x00431021, + 0x00442021, 0x24840002, 0x3084ffff, 0x0e000a55, 0xa6020018, 0x8f850018, + 0x00a01821, 0xa2030021, 0x8ee60008, 0x00402021, 0x24a50001, 0xaf850018, + 0x00c0f809, 0x00000000, 0x00402021, 0x0e000b12, 0x02202821, 0x8ee3000c, + 0x0060f809, 0x00402021, 0x96040018, 0x9602000e, 0x00822021, 0x24840002, + 0x0e000a6b, 0x3084ffff, 0x3c030800, 0x8c624120, 0x8e030008, 0x3c040800, + 0x00431023, 0x14400012, 0xac824120, 0x54600006, 0x8e02001c, 0x3243004a, + 0x24020002, 0x14620005, 0x00000000, 0x8e02001c, 0x34420040, 0x0a000e0b, + 0xae02001c, 0x52a00006, 0x36520002, 0x8e02002c, 0xaf420e10, 0x8e030030, + 0xaf430e18, 0x36520002, 0x52a00008, 0x96670010, 0x8f830000, 0x8f420e10, + 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670010, 0x92680020, + 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821, 0x00621023, + 0xaf830020, 0x58400005, 0x8f42095c, 0x8f820000, 0xaf83001c, 0xac430054, + 0x8f42095c, 0x31030008, 0xaf82002c, 0x1060001a, 0x00000000, 0x8f840000, + 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007, 0x24020007, + 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122, 0x8f850000, + 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001, 0x30630007, + 0xac440000, 0x0a000e40, 0xa0a30120, 0x90820122, 0x34420001, 0xa0820122, + 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000, 0x8c43000c, + 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008, 0x34420001, + 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, + 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018, 0x00000000, + 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068, 0x90e40081, + 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, + 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001, 0x00c02021, + 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c, 0x8f830008, + 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f830020, 0x3c020800, + 0x24504120, 0xae030024, 0x8ee20010, 0x0040f809, 0x00000000, 0x12a00005, + 0x00000000, 0x8f420e10, 0xae02002c, 0x8f430e18, 0xae030030, 0x1220feba, + 0x0000a821, 0x8f870024, 0x97860028, 0x8f830000, 0x8f820030, 0x8f840020, + 0x8f85001c, 0x32500040, 0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, + 0xac650054, 0x1040007a, 0x32820020, 0x10400027, 0x32910010, 0x24072000, + 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec2414c, + 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030400, 0xaf420148, + 0x24020041, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, 0xa7430158, + 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, 0x24630001, + 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, 0x00021600, + 0x00031c00, 0x00431025, 0x34424100, 0xafa20010, 0x8f440100, 0x0e000fe1, + 0x3c070400, 0x12200028, 0x24072000, 0x3c090800, 0x3c038000, 0x8f420178, + 0x00431024, 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, + 0x8c820030, 0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0x00001821, + 0xa3420152, 0x3c021000, 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, + 0x8d230030, 0x8c860030, 0x24630001, 0xad230030, 0x93420109, 0x9343010a, + 0xafa70014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, 0x34424e00, + 0xafa20010, 0x8f440100, 0x0e000fe1, 0x3c070300, 0x0a000f0b, 0x8fa30024, + 0x32820008, 0x10400026, 0x3c090800, 0x24072000, 0x3c038000, 0x8f420178, + 0x00431024, 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, + 0x8c820030, 0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0x00001821, + 0xa3420152, 0x3c021000, 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, + 0x8d230030, 0x8c860030, 0x24630001, 0xad230030, 0x93420109, 0x9343010a, + 0xafa70014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, 0x34424b00, + 0xafa20010, 0x8f440100, 0x0e000fe1, 0x3c070200, 0x8fa30024, 0x14600004, + 0x8fa40020, 0x32420010, 0x10400004, 0x00000000, 0x8c820004, 0x0040f809, + 0x00000000, 0x12000006, 0x8fa30020, 0x8c620008, 0x0040f809, 0x00000000, + 0x0a000f4d, 0x8fbf004c, 0x3c030800, 0x8c62413c, 0x30420040, 0x1440002f, + 0x8fbf004c, 0x24040040, 0x8f910020, 0x3c038000, 0x8f420178, 0x00431024, + 0x1440fffd, 0x8ec2414c, 0x26d0414c, 0x2610ffd4, 0xaf420144, 0x8e020030, + 0x00001821, 0xaf420148, 0x24020049, 0xaf51014c, 0xa3420152, 0x3c021000, + 0xa7430158, 0xaf440154, 0xaf420178, 0x8ec5414c, 0x8e060030, 0x93420109, + 0x9343010a, 0xafa40014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, + 0x34424900, 0xafa20010, 0x8f440100, 0x0e000fe1, 0x02203821, 0x8f830000, + 0x8e020030, 0x8c64017c, 0x02221023, 0x00441023, 0x2c420002, 0x14400005, + 0x8fbf004c, 0x0000000d, 0x00000000, 0x240000ca, 0x8fbf004c, 0x8fbe0048, + 0x8fb70044, 0x8fb60040, 0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030, + 0x8fb1002c, 0x8fb00028, 0x03e00008, 0x27bd0050, 0x03e00008, 0x00001021, + 0x3c030800, 0x24654120, 0x8ca40004, 0x8c634120, 0x0064102b, 0x54400001, + 0x00602021, 0x9743093c, 0x0083102b, 0x54400001, 0x00801821, 0x00001021, + 0xaca30008, 0x03e00008, 0xa4a00022, 0x8f850004, 0x97840010, 0x3c030800, + 0x24634120, 0x24020008, 0xa462000e, 0x8f820004, 0xa460000c, 0x000420c2, + 0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008, + 0xa0640020, 0x3c020800, 0x24424120, 0x90450021, 0x94430018, 0x3c021100, + 0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008, + 0x03e00008, 0xac850000, 0x0000000d, 0x00000000, 0x2400016f, 0x03e00008, + 0x00000000, 0x0000000d, 0x00000000, 0x2400017b, 0x03e00008, 0x00000000, + 0x03e00008, 0x00000000, 0x3c020800, 0x24424120, 0xac400008, 0xa4400022, + 0x03e00008, 0x24020001, 0x3c020800, 0x24424120, 0x24030008, 0xac400008, + 0xa440000c, 0xa443000e, 0xa0400020, 0x03e00008, 0x24020004, 0x03e00008, + 0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, + 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a000fb2, + 0x00a01021, 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, + 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068, 0x3c050800, 0x24a51090, + 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04, 0x00a61021, 0xac440004, + 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00, 0x00431025, 0xac820008, + 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14, 0xac440010, 0x8f430e18, + 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff, 0x25290001, 0xac470018, + 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000, 0x24630001, 0xace3006c, + 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068, 0x00042600, 0x00681824, + 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010, 0x8fad0014, 0x8fae0018, + 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080078, 0x000a4940, 0x01281021, + 0x01091821, 0xac440000, 0x00601021, 0xac650004, 0xac460008, 0xac67000c, + 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018, 0x8c654448, 0x3c040800, + 0x8c820064, 0x254a0001, 0x314a007f, 0x01094021, 0xad6a0060, 0x24420001, + 0xac820064, 0x03e00008, 0xad05001c, 0x00000000 }; + +static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x00000000 }; +static u32 bnx2_TXP_b06FwBss[(0x194/4) + 1] = { 0x00000000 }; +static u32 bnx2_TXP_b06FwSbss[(0x34/4) + 1] = { 0x00000000 }; + diff --git a/include/linux/mii.h b/include/linux/mii.h index 20971fe..374b615 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -65,9 +65,13 @@ #define ADVERTISE_SLCT 0x001f /* Selector bits */ #define ADVERTISE_CSMA 0x0001 /* Only selector supported */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */ #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */ #define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ #define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ #define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */ @@ -84,9 +88,13 @@ /* Link partner ability register. */ #define LPA_SLCT 0x001f /* Same as advertise selector */ #define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ +#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */ #define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */ +#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */ #define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */ +#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */ #define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ +#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/ #define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */ #define LPA_PAUSE_CAP 0x0400 /* Can pause */ #define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 7b9720e..7ccbc2e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2071,6 +2071,7 @@ #define PCI_DEVICE_ID_TIGON3_5703 0x1647 #define PCI_DEVICE_ID_TIGON3_5704 0x1648 #define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 +#define PCI_DEVICE_ID_NX2_5706 0x164a #define PCI_DEVICE_ID_TIGON3_5702FE 0x164d #define PCI_DEVICE_ID_TIGON3_5705 0x1653 #define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 @@ -2090,6 +2091,7 @@ #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 +#define PCI_DEVICE_ID_NX2_5706S 0x16aa #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5781 0x16dd -- cgit v1.1 From d68b8622ccbee8a18e495ad1650c3306f2eeb0d6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 26 May 2005 15:21:13 -0700 Subject: [PATCH] i386: fix prevent_tail_call We fixed this bug before, but it didn't take. It may have been the case that the problem was first noticed to occur in a CONFIG_REGPARM compile. But it's not regparm functions that need not to make tail calls, it's asmlinkage functions called with a user pt_regs frame on the stack supplying their arguments. prevent_tail_call probably doesn't do anything at all in regparm functions (your argument registers are going to be clobbered, period). It was a braino to conditionalize that definition in the first place. Signed-off-by: Roland McGrath Signed-off-by: Linus Torvalds --- include/asm-i386/linkage.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/asm-i386/linkage.h b/include/asm-i386/linkage.h index af3d857..f4a6eba 100644 --- a/include/asm-i386/linkage.h +++ b/include/asm-i386/linkage.h @@ -5,9 +5,7 @@ #define FASTCALL(x) x __attribute__((regparm(3))) #define fastcall __attribute__((regparm(3))) -#ifdef CONFIG_REGPARM -# define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret)) -#endif +#define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret)) #ifdef CONFIG_X86_ALIGNMENT_16 #define __ALIGN .align 16,0x90 -- cgit v1.1 From aa8f0dc6c3dbf1cf3ff58f3e945c981be134814d Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 26 May 2005 21:54:27 -0400 Subject: libata: Fix use-after-iounmap Jens Axboe pointed out that the iounmap() call in libata was occurring too early, and some drivers (ahci, probably others) were using ioremap'd memory after it had been unmapped. The patch should address that problem by way of improving the libata driver API: * move ->host_stop() call after all ->port_stop() calls have occurred. * create default helper function ata_host_stop(), and move iounmap() call there. * add ->host_stop_prewalk() hook, use it in sata_qstor.c (hi Mark). sata_qstor appears to require the host-stop-before-port-stop ordering that existed prior to applying the attached patch. --- drivers/scsi/ahci.c | 2 ++ drivers/scsi/ata_piix.c | 2 ++ drivers/scsi/libata-core.c | 15 +++++++++++---- drivers/scsi/sata_nv.c | 2 ++ drivers/scsi/sata_promise.c | 1 + drivers/scsi/sata_qstor.c | 2 ++ drivers/scsi/sata_sil.c | 1 + drivers/scsi/sata_sis.c | 1 + drivers/scsi/sata_svw.c | 1 + drivers/scsi/sata_sx4.c | 2 ++ drivers/scsi/sata_uli.c | 1 + drivers/scsi/sata_via.c | 1 + drivers/scsi/sata_vsc.c | 1 + include/linux/libata.h | 1 + 14 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index da5bd33..8b468a6 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -289,6 +289,8 @@ static void ahci_host_stop(struct ata_host_set *host_set) { struct ahci_host_priv *hpriv = host_set->private_data; kfree(hpriv); + + ata_host_stop(host_set); } static int ahci_port_start(struct ata_port *ap) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 3867f91..54c5234 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -153,6 +153,7 @@ static struct ata_port_operations piix_pata_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_operations piix_sata_ops = { @@ -180,6 +181,7 @@ static struct ata_port_operations piix_sata_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info piix_port_info[] = { diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ee9b96d..2b41cd3 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3321,6 +3321,13 @@ void ata_port_stop (struct ata_port *ap) dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } +void ata_host_stop (struct ata_host_set *host_set) +{ + if (host_set->mmio_base) + iounmap(host_set->mmio_base); +} + + /** * ata_host_remove - Unregister SCSI host structure with upper layers * @ap: Port to unregister @@ -3877,10 +3884,6 @@ void ata_pci_remove_one (struct pci_dev *pdev) } free_irq(host_set->irq, host_set); - if (host_set->ops->host_stop) - host_set->ops->host_stop(host_set); - if (host_set->mmio_base) - iounmap(host_set->mmio_base); for (i = 0; i < host_set->n_ports; i++) { ap = host_set->ports[i]; @@ -3899,6 +3902,9 @@ void ata_pci_remove_one (struct pci_dev *pdev) scsi_host_put(ap->host); } + if (host_set->ops->host_stop) + host_set->ops->host_stop(host_set); + kfree(host_set); pci_release_regions(pdev); @@ -3996,6 +4002,7 @@ EXPORT_SYMBOL_GPL(ata_chk_err); EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); +EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 69009f8..b0403cc 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -329,6 +329,8 @@ static void nv_host_stop (struct ata_host_set *host_set) host->host_desc->disable_hotplug(host_set); kfree(host); + + ata_host_stop(host_set); } static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index c4e9e02..b18c905 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -122,6 +122,7 @@ static struct ata_port_operations pdc_ata_ops = { .scr_write = pdc_sata_scr_write, .port_start = pdc_port_start, .port_stop = pdc_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info pdc_port_info[] = { diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index dfd3621..1383e8a 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -536,6 +536,8 @@ static void qs_host_stop(struct ata_host_set *host_set) writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ + + ata_host_stop(host_set); } static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe) diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 2b2ff48..238580d 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -161,6 +161,7 @@ static struct ata_port_operations sil_ops = { .scr_write = sil_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info sil_port_info[] = { diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 5105ddd..e418b89 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -114,6 +114,7 @@ static struct ata_port_operations sis_ops = { .scr_write = sis_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info sis_port_info = { diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 05075bd..edef1fa 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -313,6 +313,7 @@ static struct ata_port_operations k2_sata_ops = { .scr_write = k2_sata_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base) diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 7011865..140cea0 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -245,6 +245,8 @@ static void pdc20621_host_stop(struct ata_host_set *host_set) iounmap(dimm_mmio); kfree(hpriv); + + ata_host_stop(host_set); } static int pdc_port_start(struct ata_port *ap) diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 0bff4f4..a71fb54 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -113,6 +113,7 @@ static struct ata_port_operations uli_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info uli_port_info = { diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 3a78306..f43183c 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -134,6 +134,7 @@ static struct ata_port_operations svia_sata_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static struct ata_port_info svia_port_info = { diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 2c28f0a..f67c343 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -230,6 +230,7 @@ static struct ata_port_operations vsc_sata_ops = { .scr_write = vsc_sata_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, + .host_stop = ata_host_stop, }; static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base) diff --git a/include/linux/libata.h b/include/linux/libata.h index 1f7e203..e74f301 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -410,6 +410,7 @@ extern u8 ata_chk_err(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); +extern void ata_host_stop (struct ata_host_set *host_set); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); -- cgit v1.1 From 66f5507133f97088e553b1c8f8d341a0efd438f9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 27 May 2005 01:17:08 -0700 Subject: [XFS] remove an over-zealous WARN_ON --- fs/xfs/linux-2.6/xfs_aops.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 9278e9a..93ce257 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -886,7 +886,6 @@ xfs_page_state_convert( SetPageUptodate(page); if (startio) { - WARN_ON(page_dirty); xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty); } -- cgit v1.1 From 5d9e4ea55ae19f9083b9c2c97cc912b823ee7ab4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 27 May 2005 07:36:17 -0700 Subject: ide-cd: revert DMA mask test change The change to require the DMA length to be only word-aligned was not safe. --- drivers/ide/ide-cd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index f0bd242..78e3e7b 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1932,8 +1932,11 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) /* * check if dma is safe + * + * NOTE! The "len" and "addr" checks should possibly have + * separate masks. */ - if ((rq->data_len & 3) || (addr & mask)) + if ((rq->data_len & mask) || (addr & mask)) info->dma = 0; } -- cgit v1.1 From 88c1834633341bbb94e315433067496338bff4ad Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 27 May 2005 13:40:53 +0100 Subject: [PATCH] remove non-cleanroom pwc driver compression The original pwc author raised some questions about the reverse engineering of the decompressor algorithms used in the pwc driver. Having done some detailed investigation it appears those concerns that clean room policy was not followed are reasonable. I've also had a friendly discussion with Philips to ask their view on this. This removes the problem items of code which reduces the pwc functionality in the kernel a little but leaves all the framework for setup that will be needed for decompressors in user space (where they eventually belong). This change set is designed to be the minimal risk change set given that 2.6.12 is hopefully close to hand, with a view to merging the much updated pwc code in 2.6.13 series kernels. Someone else can then redo the decompressors properly (clean room) in user space. Note that while its easy to say that it should have been caught earlier, but the violation was really only obvious to someone who had access to both the proprietary source and the 'GPL' source. --- drivers/usb/media/pwc/Makefile | 2 +- drivers/usb/media/pwc/pwc-ctrl.c | 12 +- drivers/usb/media/pwc/pwc-dec1.c | 42 -- drivers/usb/media/pwc/pwc-dec1.h | 36 - drivers/usb/media/pwc/pwc-dec23.c | 623 ------------------ drivers/usb/media/pwc/pwc-dec23.h | 58 -- drivers/usb/media/pwc/pwc-if.c | 9 +- drivers/usb/media/pwc/pwc-kiara.c | 573 ---------------- drivers/usb/media/pwc/pwc-timon.c | 1130 -------------------------------- drivers/usb/media/pwc/pwc-uncompress.c | 2 + 10 files changed, 14 insertions(+), 2473 deletions(-) delete mode 100644 drivers/usb/media/pwc/pwc-dec1.c delete mode 100644 drivers/usb/media/pwc/pwc-dec1.h delete mode 100644 drivers/usb/media/pwc/pwc-dec23.c delete mode 100644 drivers/usb/media/pwc/pwc-dec23.h diff --git a/drivers/usb/media/pwc/Makefile b/drivers/usb/media/pwc/Makefile index e0b41ed..2d93a77 100644 --- a/drivers/usb/media/pwc/Makefile +++ b/drivers/usb/media/pwc/Makefile @@ -1,6 +1,6 @@ ifneq ($(KERNELRELEASE),) -pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o +pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o obj-$(CONFIG_USB_PWC) += pwc.o diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c index 42ec468..3e1e4fe 100644 --- a/drivers/usb/media/pwc/pwc-ctrl.c +++ b/drivers/usb/media/pwc/pwc-ctrl.c @@ -246,7 +246,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra switch(pdev->type) { case 645: case 646: - pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); +/* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ break; case 675: @@ -256,7 +256,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra case 730: case 740: case 750: - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); +/* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ break; } } @@ -318,8 +318,8 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr if (ret < 0) return ret; - if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); +/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) + pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ pdev->cmd_len = 13; memcpy(pdev->cmd_buf, buf, 13); @@ -397,8 +397,8 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr if (ret < 0) return ret; - if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); +/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) + pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ pdev->cmd_len = 12; memcpy(pdev->cmd_buf, buf, 12); diff --git a/drivers/usb/media/pwc/pwc-dec1.c b/drivers/usb/media/pwc/pwc-dec1.c deleted file mode 100644 index 57d03d9..0000000 --- a/drivers/usb/media/pwc/pwc-dec1.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Linux driver for Philips webcam - Decompression for chipset version 1 - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - - -#include "pwc-dec1.h" - - -void pwc_dec1_init(int type, int release, void *buffer, void *table) -{ - -} - -void pwc_dec1_exit(void) -{ - - - -} - diff --git a/drivers/usb/media/pwc/pwc-dec1.h b/drivers/usb/media/pwc/pwc-dec1.h deleted file mode 100644 index a7ffd9c..0000000 --- a/drivers/usb/media/pwc/pwc-dec1.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - - -#ifndef PWC_DEC1_H -#define PWC_DEC1_H - -void pwc_dec1_init(int type, int release, void *buffer, void *private_data); -void pwc_dec1_exit(void); - -#endif - - - diff --git a/drivers/usb/media/pwc/pwc-dec23.c b/drivers/usb/media/pwc/pwc-dec23.c deleted file mode 100644 index 98fa3f7..0000000 --- a/drivers/usb/media/pwc/pwc-dec23.c +++ /dev/null @@ -1,623 +0,0 @@ -/* Linux driver for Philips webcam - Decompression for chipset version 2 et 3 - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "pwc-timon.h" -#include "pwc-kiara.h" -#include "pwc-dec23.h" -#include "pwc-ioctl.h" - -#include - -/**** - * - * - * - */ - - -static void fill_table_a000(unsigned int *p) -{ - static unsigned int initial_values[12] = { - 0xFFAD9B00, 0xFFDDEE00, 0x00221200, 0x00526500, - 0xFFC21E00, 0x003DE200, 0xFF924B80, 0xFFD2A300, - 0x002D5D00, 0x006DB480, 0xFFED3E00, 0x0012C200 - }; - static unsigned int values_derivated[12] = { - 0x0000A4CA, 0x00004424, 0xFFFFBBDC, 0xFFFF5B36, - 0x00007BC4, 0xFFFF843C, 0x0000DB69, 0x00005ABA, - 0xFFFFA546, 0xFFFF2497, 0x00002584, 0xFFFFDA7C - }; - unsigned int temp_values[12]; - int i,j; - - memcpy(temp_values,initial_values,sizeof(initial_values)); - for (i=0;i<256;i++) - { - for (j=0;j<12;j++) - { - *p++ = temp_values[j]; - temp_values[j] += values_derivated[j]; - } - } -} - -static void fill_table_d000(unsigned char *p) -{ - int bit,byte; - - for (bit=0; bit<8; bit++) - { - unsigned char bitpower = 1<=1 && k<3) - bit=(table[0]>>15)&7; - else if (k>=3 && k<6) - bit=(table[0]>>12)&7; - else if (k>=6 && k<10) - bit=(table[0]>>9)&7; - else if (k>=10 && k<13) - bit=(table[0]>>6)&7; - else if (k>=13 && k<15) - bit=(table[0]>>3)&7; - else - bit=(table[0])&7; - if (k == 0) - *(unsigned char *)p8++ = 8; - else - *(unsigned char *)p8++ = j - bit; - *(unsigned char *)p8++ = bit; - - pw = 1<xx + pdev->yy) - * - */ -static void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800) -{ - int i; - unsigned int offset1, offset2; - - for(i=0,offset1=0x4000, offset2=0; i<256 ; i++,offset1+=0x7BC4, offset2+=0x7BC4) - { - unsigned int msb = offset1 >> 15; - - if ( msb > 255) - { - if (msb) - msb=0; - else - msb=255; - } - - *pdc00++ = msb << precision; - *pd800++ = offset2; - } - -} - -/* - * struct { - * unsigned char op; // operation to execute - * unsigned char bits; // bits use to perform operation - * unsigned char offset1; // offset to add to access in the table_0004 % 16 - * unsigned char offset2; // offset to add to access in the table_0004 - * } - * - */ -static unsigned int table_ops[] = { -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x30, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x10, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x70, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x50, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40, -0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00 -}; - -/* - * TODO: multiply by 4 all values - * - */ -static unsigned int MulIdx[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, - 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, - 6, 7, 8, 9, 7,10,11, 8, 8,11,10, 7, 9, 8, 7, 6, - 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, - 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, - 0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3, - 0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3, - 1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2, - 7,10,11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8,11,10, 7, - 4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4, - 7, 9, 6, 8,10, 8, 7,11,11, 7, 8,10, 8, 6, 9, 7, - 1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2, - 1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2, -10, 8, 7,11, 8, 6, 9, 7, 7, 9, 6, 8,11, 7, 8,10 -}; - - - -void pwc_dec23_init(int type, int release, unsigned char *mode, void *data) -{ - int flags; - struct pwc_dec23_private *pdev = data; - release = release; - - switch (type) - { - case 720: - case 730: - case 740: - case 750: - flags = mode[2]&0x18; /* our: flags = 8, mode[2]==e8 */ - if (flags==8) - pdev->zz = 7; - else if (flags==0x10) - pdev->zz = 8; - else - pdev->zz = 6; - flags = mode[2]>>5; /* our: 7 */ - - fill_table_color(flags, (unsigned int *)KiaraRomTable, pdev->table_0004, pdev->table_8004); - break; - - - case 675: - case 680: - case 690: - flags = mode[2]&6; - if (flags==2) - pdev->zz = 7; - else if (flags==4) - pdev->zz = 8; - else - pdev->zz = 6; - flags = mode[2]>>3; - - fill_table_color(flags, (unsigned int *)TimonRomTable, pdev->table_0004, pdev->table_8004); - break; - - default: - /* Not supported */ - return; - } - - /* * * * ** */ - pdev->xx = 8 - pdev->zz; - pdev->yy = 15 - pdev->xx; - pdev->zzmask = 0xFF>>pdev->xx; - //pdev->zzmask = (1U<zz)-1; - - - fill_table_dc00_d800(pdev->xx + pdev->yy, pdev->table_dc00, pdev->table_d800); - fill_table_a000(pdev->table_a004); - fill_table_d000(pdev->table_d004); -} - - -/* - * To manage the stream, we keep in a 32 bits variables, - * the next bits in the stream. fill_reservoir() add to - * the reservoir at least wanted nbits. - * - * - */ -#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ - while (nbits_in_reservoir>= nbits_wanted; \ - nbits_in_reservoir -= nbits_wanted; \ -} while(0); - - - -static void DecompressBand23(const struct pwc_dec23_private *pdev, - const unsigned char *rawyuv, - unsigned char *planar_y, - unsigned char *planar_u, - unsigned char *planar_v, - unsigned int image_x, /* aka number of pixels wanted ??? */ - unsigned int pixels_per_line, /* aka number of pixels per line */ - int flags) -{ - - - unsigned int reservoir, nbits_in_reservoir; - int first_4_bits; - unsigned int bytes_per_channel; - int line_size; /* size of the line (4Y+U+V) */ - int passes; - const unsigned char *ptable0004, *ptable8004; - - int even_line; - unsigned int temp_colors[16]; - int nblocks; - - const unsigned char *stream; - unsigned char *dest_y, *dest_u=NULL, *dest_v=NULL; - unsigned int offset_to_plane_u, offset_to_plane_v; - - int i; - - - reservoir = 0; - nbits_in_reservoir = 0; - stream = rawyuv+1; /* The first byte of the stream is skipped */ - even_line = 1; - - get_nbits(reservoir,nbits_in_reservoir,stream,4,first_4_bits); - - line_size = pixels_per_line*3; - - for (passes=0;passes<2;passes++) - { - if (passes==0) - { - bytes_per_channel = pixels_per_line; - dest_y = planar_y; - nblocks = image_x/4; - } - else - { - /* Format planar: All Y, then all U, then all V */ - bytes_per_channel = pixels_per_line/2; - dest_u = planar_u; - dest_v = planar_v; - dest_y = dest_u; - nblocks = image_x/8; - } - - offset_to_plane_u = bytes_per_channel*2; - offset_to_plane_v = bytes_per_channel*3; - /* - printf("bytes_per_channel = %d\n",bytes_per_channel); - printf("offset_to_plane_u = %d\n",offset_to_plane_u); - printf("offset_to_plane_v = %d\n",offset_to_plane_v); - */ - - while (nblocks-->0) - { - unsigned int gray_index; - - fill_nbits(reservoir,nbits_in_reservoir,stream,16); - gray_index = reservoir & pdev->zzmask; - reservoir >>= pdev->zz; - nbits_in_reservoir -= pdev->zz; - - fill_nbits(reservoir,nbits_in_reservoir,stream,2); - - if ( (reservoir & 3) == 0) - { - reservoir>>=2; - nbits_in_reservoir-=2; - for (i=0;i<16;i++) - temp_colors[i] = pdev->table_dc00[gray_index]; - - } - else - { - unsigned int channel_v, offset1; - - /* swap bit 0 and 2 of offset_OR */ - channel_v = ((reservoir & 1) << 2) | (reservoir & 2) | ((reservoir & 4)>>2); - reservoir>>=3; - nbits_in_reservoir-=3; - - for (i=0;i<16;i++) - temp_colors[i] = pdev->table_d800[gray_index]; - - ptable0004 = pdev->table_0004 + (passes*16384) + (first_4_bits*1024) + (channel_v*128); - ptable8004 = pdev->table_8004 + (passes*4096) + (first_4_bits*256) + (channel_v*32); - - offset1 = 0; - while(1) - { - unsigned int index_in_table_ops, op, rows=0; - fill_nbits(reservoir,nbits_in_reservoir,stream,16); - - /* mode is 0,1 or 2 */ - index_in_table_ops = (reservoir&0x3F); - op = table_ops[ index_in_table_ops*4 ]; - if (op == 2) - { - reservoir >>= 2; - nbits_in_reservoir -= 2; - break; /* exit the while(1) */ - } - if (op == 0) - { - unsigned int shift; - - offset1 = (offset1 + table_ops[index_in_table_ops*4+2]) & 0x0F; - shift = table_ops[ index_in_table_ops*4+1 ]; - reservoir >>= shift; - nbits_in_reservoir -= shift; - rows = ptable0004[ offset1 + table_ops[index_in_table_ops*4+3] ]; - } - if (op == 1) - { - /* 10bits [ xxxx xxxx yyyy 000 ] - * yyy => offset in the table8004 - * xxx => offset in the tabled004 - */ - unsigned int mask, shift; - unsigned int col1, row1, total_bits; - - offset1 = (offset1 + ((reservoir>>3)&0x0F)+1) & 0x0F; - - col1 = (reservoir>>7) & 0xFF; - row1 = ptable8004 [ offset1*2 ]; - - /* Bit mask table */ - mask = pdev->table_d004[ (row1<<8) + col1 ]; - shift = ptable8004 [ offset1*2 + 1]; - rows = ((mask << shift) + 0x80) & 0xFF; - - total_bits = row1 + 8; - reservoir >>= total_bits; - nbits_in_reservoir -= total_bits; - } - { - const unsigned int *table_a004 = pdev->table_a004 + rows*12; - unsigned int *poffset = MulIdx + offset1*16; /* 64/4 (int) */ - for (i=0;i<16;i++) - { - temp_colors[i] += table_a004[ *poffset ]; - poffset++; - } - } - } - } -#define USE_SIGNED_INT_FOR_COLOR -#ifdef USE_SIGNED_INT_FOR_COLOR -# define CLAMP(x) ((x)>255?255:((x)<0?0:x)) -#else -# define CLAMP(x) ((x)>255?255:x) -#endif - - if (passes == 0) - { -#ifdef USE_SIGNED_INT_FOR_COLOR - const int *c = temp_colors; -#else - const unsigned int *c = temp_colors; -#endif - unsigned char *d; - - d = dest_y; - for (i=0;i<4;i++,c++) - *d++ = CLAMP((*c) >> pdev->yy); - - d = dest_y + bytes_per_channel; - for (i=0;i<4;i++,c++) - *d++ = CLAMP((*c) >> pdev->yy); - - d = dest_y + offset_to_plane_u; - for (i=0;i<4;i++,c++) - *d++ = CLAMP((*c) >> pdev->yy); - - d = dest_y + offset_to_plane_v; - for (i=0;i<4;i++,c++) - *d++ = CLAMP((*c) >> pdev->yy); - - dest_y += 4; - } - else if (passes == 1) - { -#ifdef USE_SIGNED_INT_FOR_COLOR - int *c1 = temp_colors; - int *c2 = temp_colors+4; -#else - unsigned int *c1 = temp_colors; - unsigned int *c2 = temp_colors+4; -#endif - unsigned char *d; - - d = dest_y; - for (i=0;i<4;i++,c1++,c2++) - { - *d++ = CLAMP((*c1) >> pdev->yy); - *d++ = CLAMP((*c2) >> pdev->yy); - } - c1 = temp_colors+12; - //c2 = temp_colors+8; - d = dest_y + bytes_per_channel; - for (i=0;i<4;i++,c1++,c2++) - { - *d++ = CLAMP((*c1) >> pdev->yy); - *d++ = CLAMP((*c2) >> pdev->yy); - } - - if (even_line) /* Each line, swap u/v */ - { - even_line=0; - dest_y = dest_v; - dest_u += 8; - } - else - { - even_line=1; - dest_y = dest_u; - dest_v += 8; - } - } - - } /* end of while (nblocks-->0) */ - - } /* end of for (passes=0;passes<2;passes++) */ - -} - - -/** - * - * image: size of the image wanted - * view : size of the image returned by the camera - * offset: (x,y) to displayer image in the view - * - * src: raw data - * dst: image output - * flags: PWCX_FLAG_PLANAR - * pdev: private buffer - * bandlength: - * - */ -void pwc_dec23_decompress(const struct pwc_coord *image, - const struct pwc_coord *view, - const struct pwc_coord *offset, - const void *src, - void *dst, - int flags, - const void *data, - int bandlength) -{ - const struct pwc_dec23_private *pdev = data; - unsigned char *pout, *pout_planar_y=NULL, *pout_planar_u=NULL, *pout_planar_v=NULL; - int i,n,stride,pixel_size; - - - if (flags & PWCX_FLAG_BAYER) - { - pout = dst + (view->x * offset->y) + offset->x; - pixel_size = view->x * 4; - } - else - { - n = view->x * view->y; - - /* offset in Y plane */ - stride = view->x * offset->y; - pout_planar_y = dst + stride + offset->x; - - /* offsets in U/V planes */ - stride = (view->x * offset->y)/4 + offset->x/2; - pout_planar_u = dst + n + + stride; - pout_planar_v = dst + n + n/4 + stride; - - pixel_size = view->x * 4; - } - - - for (i=0;iy;i+=4) - { - if (flags & PWCX_FLAG_BAYER) - { - //TODO: - //DecompressBandBayer(pdev,src,pout,image.x,view->x,flags); - src += bandlength; - pout += pixel_size; - } - else - { - DecompressBand23(pdev,src,pout_planar_y,pout_planar_u,pout_planar_v,image->x,view->x,flags); - src += bandlength; - pout_planar_y += pixel_size; - pout_planar_u += view->x; - pout_planar_v += view->x; - } - } -} - -void pwc_dec23_exit(void) -{ - /* Do nothing */ - -} - diff --git a/drivers/usb/media/pwc/pwc-dec23.h b/drivers/usb/media/pwc/pwc-dec23.h deleted file mode 100644 index 5b2aacd..0000000 --- a/drivers/usb/media/pwc/pwc-dec23.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) - - NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx - driver and thus may have bugs that are not present in the original version. - Please send bug reports and support requests to . - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef PWC_DEC23_H -#define PWC_DEC23_H - -struct pwc_dec23_private -{ - unsigned char xx,yy,zz,zzmask; - - unsigned char table_0004[2*0x4000]; - unsigned char table_8004[2*0x1000]; - unsigned int table_a004[256*12]; - - unsigned char table_d004[8*256]; - unsigned int table_d800[256]; - unsigned int table_dc00[256]; -}; - - -void pwc_dec23_init(int type, int release, unsigned char *buffer, void *private_data); -void pwc_dec23_exit(void); -void pwc_dec23_decompress(const struct pwc_coord *image, - const struct pwc_coord *view, - const struct pwc_coord *offset, - const void *src, - void *dst, - int flags, - const void *data, - int bandlength); - - - -#endif - - - diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index cca47f4..5429ff3 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -68,8 +68,6 @@ #include "pwc-ioctl.h" #include "pwc-kiara.h" #include "pwc-timon.h" -#include "pwc-dec23.h" -#include "pwc-dec1.h" #include "pwc-uncompress.h" /* Function prototypes and driver templates */ @@ -322,6 +320,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) case 730: case 740: case 750: +#if 0 Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ break; @@ -330,6 +329,8 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) /* TODO & FIXME */ kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); break; +#endif + ; } if (kbuf == NULL) { Err("Failed to allocate decompress table.\n"); @@ -1131,11 +1132,11 @@ static int pwc_video_close(struct inode *inode, struct file *file) case 730: case 740: case 750: - pwc_dec23_exit(); /* Timon & Kiara */ +/* pwc_dec23_exit(); *//* Timon & Kiara */ break; case 645: case 646: - pwc_dec1_exit(); +/* pwc_dec1_exit(); */ break; } diff --git a/drivers/usb/media/pwc/pwc-kiara.c b/drivers/usb/media/pwc/pwc-kiara.c index 5485800..c498c68 100644 --- a/drivers/usb/media/pwc/pwc-kiara.c +++ b/drivers/usb/media/pwc/pwc-kiara.c @@ -316,576 +316,3 @@ const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = }, }; - -/* - * Rom table for kiara chips - * - * 32 roms tables (one for each resolution ?) - * 2 tables per roms (one for each passes) (Y, and U&V) - * 128 bytes per passes - */ - -const unsigned int KiaraRomTable [8][2][16][8] = -{ - { /* version 0 */ - { /* version 0, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x0000124a,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009292,0x00009292,0x00009493,0x000124db}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x0000a493,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x000124db,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 0, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000001,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000049,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009252,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009292,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009292, - 0x00009492,0x00009493,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009252,0x00009493, - 0x000126dc,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 1 */ - { /* version 1, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009252,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009252, - 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 1, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000049,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000000}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000049,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x0000924a,0x0000924a, - 0x00009492,0x00009493,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 2 */ - { /* version 2, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x0000a49b}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 2, passes 1 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x0000a49b,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 3 */ - { /* version 3, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 3, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 4 */ - { /* version 4, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009252,0x00009493, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 4, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000049,0x00000049,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00000249,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 5 */ - { /* version 5, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 5, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x00009252,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 6 */ - { /* version 6, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000126db, - 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 6, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 7 */ - { /* version 7, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x000124db}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 7, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x00009492,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - } -}; - diff --git a/drivers/usb/media/pwc/pwc-timon.c b/drivers/usb/media/pwc/pwc-timon.c index f950a4e..dee9671 100644 --- a/drivers/usb/media/pwc/pwc-timon.c +++ b/drivers/usb/media/pwc/pwc-timon.c @@ -314,1133 +314,3 @@ const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = }, }; -/* - * 16 versions: - * 2 tables (one for Y, and one for U&V) - * 16 levels of details per tables - * 8 blocs - */ - -const unsigned int TimonRomTable [16][2][16][8] = -{ - { /* version 0 */ - { /* version 0, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000001,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000001, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000009,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x0000124a,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 0, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000001,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000001, - 0x00000001,0x00000009,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000009,0x00000049,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000009,0x00000049,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 1 */ - { /* version 1, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000009,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 1, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000001,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000049,0x00000249,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009252,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 2 */ - { /* version 2, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009252,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009252, - 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 2, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000049,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000000}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000049,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x0000924a,0x0000924a, - 0x00009492,0x00009493,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 3 */ - { /* version 3, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009252, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 3, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00000049,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009252,0x00009292,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009292, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 4 */ - { /* version 4, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x0000a49b}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 4, passes 1 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x0000a49b,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 5 */ - { /* version 5, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000126dc,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 5, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x00009493,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x000124db,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009493,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 6 */ - { /* version 6, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 6, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 7 */ - { /* version 7, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x0002496e}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x0001c96e,0x0002496e}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 7, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000136e4,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00012492,0x000126db, - 0x0001b724,0x0001b925,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 8 */ - { /* version 8, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x00024b76,0x00024b77}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x00024b76,0x00025bbf}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 8, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x0001b724,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x0002496d,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 9 */ - { /* version 9, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009252,0x00009493, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 9, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000049,0x00000049,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00000249,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 10 */ - { /* version 10, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000126dc,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 10, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00000249,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x00009493,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009493,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x00009492,0x00009493,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009493,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 11 */ - { /* version 11, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 11, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x00009252,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 12 */ - { /* version 12, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000126db, - 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 12, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 13 */ - { /* version 13, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x000124db}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 13, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x00009492,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 14 */ - { /* version 14, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000136e4,0x0001b725,0x000124db}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000126dc,0x0001b724,0x0001b92d,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x0002496d,0x00024b76,0x00024b77}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 14, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000136e4,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 15 */ - { /* version 15, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x0002496d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 15, passes 1 */ - {0x00000000,0x00000000,0x0000924a,0x0000924a, - 0x00009292,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000124db,0x0001b724,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x0001b724,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000136db, - 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001c924,0x0001b724,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001c924,0x0001b724,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b724,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x00024924,0x0002496d,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - } -}; diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c index c062e43..c596083 100644 --- a/drivers/usb/media/pwc/pwc-uncompress.c +++ b/drivers/usb/media/pwc/pwc-uncompress.c @@ -122,6 +122,7 @@ int pwc_decompress(struct pwc_device *pdev) switch (pdev->type) { +#if 0 case 675: case 680: case 690: @@ -137,6 +138,7 @@ int pwc_decompress(struct pwc_device *pdev) case 645: case 646: /* TODO & FIXME */ +#endif return -ENXIO; /* No such device or address: missing decompressor */ break; } -- cgit v1.1 From 2efe86b809d97debaaf9fcc13b041aedf15bd3d2 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Fri, 27 May 2005 02:02:43 -0700 Subject: [PATCH] cpuset exit NULL dereference fix There is a race in the kernel cpuset code, between the code to handle notify_on_release, and the code to remove a cpuset. The notify_on_release code can end up trying to access a cpuset that has been removed. In the most common case, this causes a NULL pointer dereference from the routine cpuset_path. However all manner of bad things are possible, in theory at least. The existing code decrements the cpuset use count, and if the count goes to zero, processes the notify_on_release request, if appropriate. However, once the count goes to zero, unless we are holding the global cpuset_sem semaphore, there is nothing to stop another task from immediately removing the cpuset entirely, and recycling its memory. The obvious fix would be to always hold the cpuset_sem semaphore while decrementing the use count and dealing with notify_on_release. However we don't want to force a global semaphore into the mainline task exit path, as that might create a scaling problem. The actual fix is almost as easy - since this is only an issue for cpusets using notify_on_release, which the top level big cpusets don't normally need to use, only take the cpuset_sem for cpusets using notify_on_release. This code has been run for hours without a hiccup, while running a cpuset create/destroy stress test that could crash the existing kernel in seconds. This patch applies to the current -linus git kernel. Signed-off-by: Paul Jackson Acked-by: Simon Derr Acked-by: Dinakar Guniguntala Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 961d740..00e8f25 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -166,9 +166,8 @@ static struct super_block *cpuset_sb = NULL; * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't * (usually) grab cpuset_sem. These are the two most performance * critical pieces of code here. The exception occurs on exit(), - * if the last task using a cpuset exits, and the cpuset was marked - * notify_on_release. In that case, the cpuset_sem is taken, the - * path to the released cpuset calculated, and a usermode call made + * when a task in a notify_on_release cpuset exits. Then cpuset_sem + * is taken, and if the cpuset count is zero, a usermode call made * to /sbin/cpuset_release_agent with the name of the cpuset (path * relative to the root of cpuset file system) as the argument. * @@ -1404,6 +1403,18 @@ void cpuset_fork(struct task_struct *tsk) * * Description: Detach cpuset from @tsk and release it. * + * Note that cpusets marked notify_on_release force every task + * in them to take the global cpuset_sem semaphore when exiting. + * This could impact scaling on very large systems. Be reluctant + * to use notify_on_release cpusets where very high task exit + * scaling is required on large systems. + * + * Don't even think about derefencing 'cs' after the cpuset use + * count goes to zero, except inside a critical section guarded + * by the cpuset_sem semaphore. If you don't hold cpuset_sem, + * then a zero cpuset use count is a license to any other task to + * nuke the cpuset immediately. + * **/ void cpuset_exit(struct task_struct *tsk) @@ -1415,10 +1426,13 @@ void cpuset_exit(struct task_struct *tsk) tsk->cpuset = NULL; task_unlock(tsk); - if (atomic_dec_and_test(&cs->count)) { + if (notify_on_release(cs)) { down(&cpuset_sem); - check_for_release(cs); + if (atomic_dec_and_test(&cs->count)) + check_for_release(cs); up(&cpuset_sem); + } else { + atomic_dec(&cs->count); } } -- cgit v1.1 From 25be5e6ccc5c9cab77012fabbb72520f9b6e4618 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 27 May 2005 04:21:50 -0400 Subject: [PATCH] VIA IRQ quirk Delete quirk_via_bridge(), restore quirk_via_irqpic() -- but now improved to be invoked upon device ENABLE, and now only for VIA devices -- not all devices behind VIA bridges. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/pci/irq.c | 5 ----- drivers/acpi/pci_irq.c | 4 ---- drivers/pci/quirks.c | 40 ++++++++++++++++++++++++---------------- include/linux/acpi.h | 5 ++++- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index d6598da..da21b1d 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -1029,7 +1029,6 @@ void pcibios_penalize_isa_irq(int irq) static int pirq_enable_irq(struct pci_dev *dev) { u8 pin; - extern int via_interrupt_line_quirk; struct pci_dev *temp_dev; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); @@ -1084,10 +1083,6 @@ static int pirq_enable_irq(struct pci_dev *dev) printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin, pci_name(dev), msg); } - /* VIA bridges use interrupt line for apic/pci steering across - the V-Link */ - else if (via_interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15); return 0; } diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 12b0eea..8093f2e 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -391,7 +391,6 @@ acpi_pci_irq_enable ( u8 pin = 0; int edge_level = ACPI_LEVEL_SENSITIVE; int active_high_low = ACPI_ACTIVE_LOW; - extern int via_interrupt_line_quirk; char *link = NULL; ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); @@ -444,9 +443,6 @@ acpi_pci_irq_enable ( } } - if (via_interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15); - dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 026aa04..afc9d29 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "pci.h" /* Deal with broken BIOS'es that neglect to enable passive release, @@ -467,9 +468,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, * non-x86 architectures (yes Via exists on PPC among other places), * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get * interrupts delivered properly. - * - * TODO: When we have device-specific interrupt routers, - * quirk_via_irqpic will go away from quirks. */ /* @@ -494,6 +492,29 @@ static void __devinit quirk_via_acpi(struct pci_dev *d) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); +static void __devinit quirk_via_irqpic(struct pci_dev *dev) +{ + u8 irq, new_irq; + +#ifdef CONFIG_X86_IO_APIC + if (nr_ioapics && !skip_ioapic_setup) + return; +#endif +#ifdef CONFIG_ACPI + if (acpi_irq_model != ACPI_IRQ_MODEL_PIC) + return; +#endif + new_irq = dev->irq & 0xf; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + if (new_irq != irq) { + printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n", + pci_name(dev), irq, new_irq); + udelay(15); /* unknown if delay really needed */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); + } +} +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic); + /* * PIIX3 USB: We have to disable USB interrupts that are * hardwired to PIRQD# and may be shared with an @@ -683,19 +704,6 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); -/* - * VIA northbridges care about PCI_INTERRUPT_LINE - */ -int via_interrupt_line_quirk; - -static void __devinit quirk_via_bridge(struct pci_dev *pdev) -{ - if(pdev->devfn == 0) { - printk(KERN_INFO "PCI: Via IRQ fixup\n"); - via_interrupt_line_quirk = 1; - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge ); /* * Serverworks CSB5 IDE does not fully support native mode diff --git a/include/linux/acpi.h b/include/linux/acpi.h index aefe6d0..d5a55bd 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -25,6 +25,8 @@ #ifndef _LINUX_ACPI_H #define _LINUX_ACPI_H +#ifdef CONFIG_ACPI + #ifndef _LINUX #define _LINUX #endif @@ -533,4 +535,5 @@ static inline int acpi_get_pxm(acpi_handle handle) extern int pnpacpi_disabled; -#endif /*_LINUX_ACPI_H*/ +#endif /* CONFIG_ACPI */ +#endif /*_LINUX_ACPI_H*/ -- cgit v1.1 From 9920e91450ee9b373dd4924f79d287a267b8f6a3 Mon Sep 17 00:00:00 2001 From: Alexander Nyberg Date: Fri, 27 May 2005 12:27:05 +0200 Subject: [PATCH] Fixup VIA IRQ quirk quirk_via_irqpic can't be __devinit for swsuspend Signed-off-by: Alexander Nyberg Signed-off-by: Linus Torvalds --- drivers/pci/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index afc9d29..637e949 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -492,7 +492,7 @@ static void __devinit quirk_via_acpi(struct pci_dev *d) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); -static void __devinit quirk_via_irqpic(struct pci_dev *dev) +static void quirk_via_irqpic(struct pci_dev *dev) { u8 irq, new_irq; -- cgit v1.1 From 3e11c3ce0a4ce3d30802babccb0e5f881778ccf1 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 27 May 2005 04:53:27 -0400 Subject: [PATCH] ACPI build fix Fix 2.6.12 CONFIG_ACPI=n build regression. CONFIG_ACPI_BOOT shall be set only if CONFIG_ACPI. Signed-off-by: Len Brown Signed-off-by: Linus Torvalds --- drivers/acpi/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 0400a52..670fdb5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -40,13 +40,12 @@ config ACPI available at: +if ACPI + config ACPI_BOOT bool - depends on ACPI || X86_HT default y -if ACPI - config ACPI_INTERPRETER bool depends on !IA64_SGI_SN -- cgit v1.1 From 8aadff7dd519800ce7c0e7fb75dcd4438b373134 Mon Sep 17 00:00:00 2001 From: Alexander Nyberg Date: Fri, 27 May 2005 12:48:50 +0200 Subject: [PATCH] Note on ACPI build fix Even after the previous fix you can still set CONFIG_ACPI_BOOT indirectly even without CONFIG_ACPI by choosing CONFIG_PCI and CONFIG_PCI_MMCONFIG. That doesn't build very well either. This makes PCI_MMCONFIG depend on ACPI, fixing that hole. [ I guess in theory Kconfig could follow the whole chain of dependencies for things that get selected, but that sounds insanely complicated, so we'll just fix up these things by hand. --Linus ] Signed-off-by: Alexander Nyberg Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 2 +- arch/x86_64/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index e382f32..dfd904f 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -1163,7 +1163,7 @@ config PCI_DIRECT config PCI_MMCONFIG bool - depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI)) + depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) select ACPI_BOOT default y diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 82cb2a3..0f430d9 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -421,7 +421,7 @@ config PCI_DIRECT config PCI_MMCONFIG bool "Support mmconfig PCI config space access" - depends on PCI + depends on PCI && ACPI select ACPI_BOOT config UNORDERED_IO -- cgit v1.1 From 7003c05d77593f567e9940e68a944d846228fd7a Mon Sep 17 00:00:00 2001 From: "domen@coderock.org" Date: Fri, 8 Apr 2005 09:53:09 +0200 Subject: [PATCH] drivers/scsi/sata_vsc: add #include req'd for DMA_32BIT_MASK constant The previous patch did not compile cleanly on all architectures so here's a fixed one which #includes . Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h when calling pci_set_dma_mask() or pci_set_consistent_dma_mask() This patch includes dma-mapping.h explicitly because it caused errors on some architectures otherwise. See http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for details Signed-off-by: Tobias Klauser Signed-off-by: Domen Puncer diff -puN drivers/scsi/sata_vsc.c~dma_mask-drivers_scsi_sata_vsc drivers/scsi/sata_vsc.c --- drivers/scsi/sata_vsc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 2c28f0a..05e0130 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "scsi.h" #include #include -- cgit v1.1 From 87507cfdd2cde397c9da8f6e7ec23b2b47ec53d6 Mon Sep 17 00:00:00 2001 From: "domen@coderock.org" Date: Fri, 8 Apr 2005 09:53:06 +0200 Subject: [PATCH] drivers/scsi/ahci: add #include req'd for the DMA_{64,32}BIT_MASK constants The previous patch did not compile cleanly on all architectures so here's a fixed one which #includes . Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h when calling pci_set_dma_mask() or pci_set_consistent_dma_mask() This patch includes dma-mapping.h explicitly because it caused errors on some architectures otherwise. See http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for details Signed-off-by: Tobias Klauser Signed-off-by: Domen Puncer diff -puN drivers/scsi/ahci.c~dma_mask-drivers_scsi_ahci drivers/scsi/ahci.c --- drivers/scsi/ahci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index da5bd33..8263b3a 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "scsi.h" #include #include -- cgit v1.1 From 271b74d0b886301f297407dd7ae11b99607f8089 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 28 May 2005 02:11:06 -0500 Subject: Input: Fix a warning in psmouse-base.c Signed-off-by: Andrew Morton Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cd85095..c9f8e16 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -972,7 +972,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) return -EINVAL; if (!strncmp(val, "any", 3)) { - *((unsigned int *)kp->arg) = -1UL; + *((unsigned int *)kp->arg) = -1U; return 0; } -- cgit v1.1 From 668d1e6093110f7534e661e2ff43d54c74659b6d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 28 May 2005 02:11:12 -0500 Subject: Input: This patch adds dummy gameport_register_port, gameport_unregister_port and gameport_set_phys functions to gameport.h for the case when a driver can't use gameport. This fixes the compilation of some OSS drivers with GAMEPORT=n without the need to #if inside every single driver. This patch also removes the non-working and now obsolete SOUND_GAMEPORT. This patch is also an alternative solution for ALSA drivers with similar problems (but #if's inside the drivers might have the advantage of saving some more bytes of gameport is not available). The only user-visible change is that for GAMEPORT=m the affected OSS drivers are now allowed to be built statically (but they won't have gameport support). Signed-off-by: Adrian Bunk Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/Kconfig | 20 -------------------- include/linux/gameport.h | 28 +++++++++++++++++++++++++--- sound/oss/Kconfig | 12 ++++++------ 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 6282f46..1d93f50 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig @@ -68,23 +68,3 @@ config GAMEPORT_CS461X depends on PCI endif - -# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on -# in every .config. Please don't touch it. It is here to handle an -# unusual dependency between GAMEPORT and sound drivers. -# -# Some sound drivers call gameport functions. If GAMEPORT is -# not selected, empty stubs are provided for the functions and all is -# well. -# If GAMEPORT is built in, everything is fine. -# If GAMEPORT is a module, however, it would need to be loaded for the -# sound driver to be able to link properly. Therefore, the sound -# driver must be a module as well in that case. Since there's no way -# to express that directly in Kconfig, we use SOUND_GAMEPORT to -# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm', -# anything that depends on SOUND_GAMEPORT must be 'm' as well. if -# GAMEPORT is 'y' or 'n', it can be anything". -config SOUND_GAMEPORT - tristate - default m if GAMEPORT=m - default y diff --git a/include/linux/gameport.h b/include/linux/gameport.h index b1272f8..cd623ec 100644 --- a/include/linux/gameport.h +++ b/include/linux/gameport.h @@ -67,6 +67,8 @@ int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mo void gameport_close(struct gameport *gameport); void gameport_rescan(struct gameport *gameport); +#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) + void __gameport_register_port(struct gameport *gameport, struct module *owner); static inline void gameport_register_port(struct gameport *gameport) { @@ -75,6 +77,29 @@ static inline void gameport_register_port(struct gameport *gameport) void gameport_unregister_port(struct gameport *gameport); +void gameport_set_phys(struct gameport *gameport, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#else + +static inline void gameport_register_port(struct gameport *gameport) +{ + return; +} + +static inline void gameport_unregister_port(struct gameport *gameport) +{ + return; +} + +static inline void gameport_set_phys(struct gameport *gameport, + const char *fmt, ...) +{ + return; +} + +#endif + static inline struct gameport *gameport_allocate_port(void) { struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL); @@ -92,9 +117,6 @@ static inline void gameport_set_name(struct gameport *gameport, const char *name strlcpy(gameport->name, name, sizeof(gameport->name)); } -void gameport_set_phys(struct gameport *gameport, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); - /* * Use the following fucntions to manipulate gameport's per-port * driver-specific data. diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index a9602f8..e537bd6 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -112,7 +112,7 @@ config SOUND_BCM_CS4297A config SOUND_ES1370 tristate "Ensoniq AudioPCI (ES1370)" - depends on SOUND_PRIME!=n && SOUND && PCI && SOUND_GAMEPORT + depends on SOUND_PRIME!=n && SOUND && PCI help Say Y or M if you have a PCI sound card utilizing the Ensoniq ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find @@ -125,7 +125,7 @@ config SOUND_ES1370 config SOUND_ES1371 tristate "Creative Ensoniq AudioPCI 97 (ES1371)" - depends on SOUND_PRIME!=n && SOUND && PCI && SOUND_GAMEPORT + depends on SOUND_PRIME!=n && SOUND && PCI help Say Y or M if you have a PCI sound card utilizing the Ensoniq ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if @@ -138,7 +138,7 @@ config SOUND_ES1371 config SOUND_ESSSOLO1 tristate "ESS Technology Solo1" - depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT && PCI + depends on SOUND_PRIME!=n && SOUND && PCI help Say Y or M if you have a PCI sound card utilizing the ESS Technology Solo1 chip. To find out if your sound card uses a @@ -179,7 +179,7 @@ config SOUND_HARMONY config SOUND_SONICVIBES tristate "S3 SonicVibes" - depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT + depends on SOUND_PRIME!=n && SOUND help Say Y or M if you have a PCI sound card utilizing the S3 SonicVibes chipset. To find out if your sound card uses a @@ -226,7 +226,7 @@ config SOUND_AU1550_AC97 config SOUND_TRIDENT tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core" - depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT + depends on SOUND_PRIME!=n && SOUND ---help--- Say Y or M if you have a PCI sound card utilizing the Trident 4DWave-DX/NX chipset or your mother board chipset has SiS 7018 @@ -739,7 +739,7 @@ config SOUND_NM256 config SOUND_MAD16 tristate "OPTi MAD16 and/or Mozart based cards" - depends on SOUND_OSS && SOUND_GAMEPORT + depends on SOUND_OSS ---help--- Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi 82C928 or 82C929 or 82C931) audio interface chip. These chips are -- cgit v1.1 From 39fa58007a54b09c91cb7bf3ce3cfcc4957f92ff Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 28 May 2005 02:11:16 -0500 Subject: Input: Add a missing KERN_INFO message designation, fix behavior when only a keyboard part of the controller is detected. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f648678..0327472 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -227,7 +227,7 @@ static int i8042_pnp_init(void) int result_kbd, result_aux; if (i8042_nopnp) { - printk("i8042: PNP detection disabled\n"); + printk(KERN_INFO "i8042: PNP detection disabled\n"); return 0; } @@ -265,7 +265,7 @@ static int i8042_pnp_init(void) i8042_pnp_kbd_irq = i8042_kbd_irq; } - if (result_aux > 0 && !i8042_pnp_aux_irq) { + if (!i8042_pnp_aux_irq) { printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq); i8042_pnp_aux_irq = i8042_aux_irq; } -- cgit v1.1 From be15692310ec0e93998d763931089cb21386a058 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 28 May 2005 02:11:19 -0500 Subject: Input: Remove (now) unused variable in i8042.c Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 8e63e46..8f5b123 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -802,8 +802,6 @@ static int i8042_controller_init(void) */ static void i8042_controller_reset(void) { - unsigned char param; - /* * Reset the controller if requested. */ -- cgit v1.1 From 2673c836ab9a44b02d45ae5c1c44c03df138dba4 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 28 May 2005 02:11:27 -0500 Subject: Input: Only write the CTR in i8042 resume function. Reading it is wrong, since it may (will) contain nonsensical data. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 48 ++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 8f5b123..5900de3 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -698,6 +698,26 @@ static void i8042_timer_func(unsigned long data) i8042_interrupt(0, NULL, NULL); } +static int i8042_ctl_test(void) +{ + unsigned char param; + + if (!i8042_reset) + return 0; + + if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { + printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); + return -1; + } + + if (param != I8042_RET_CTL_TEST) { + printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", + param, I8042_RET_CTL_TEST); + return -1; + } + + return 0; +} /* * i8042_controller init initializes the i8042 controller, and, @@ -719,21 +739,8 @@ static int i8042_controller_init(void) return -1; } - if (i8042_reset) { - - unsigned char param; - - if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { - printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); - return -1; - } - - if (param != I8042_RET_CTL_TEST) { - printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", - param, I8042_RET_CTL_TEST); - return -1; - } - } + if (i8042_ctl_test()) + return -1; /* * Save the CTR for restoral on unload / reboot. @@ -806,9 +813,7 @@ static void i8042_controller_reset(void) * Reset the controller if requested. */ - if (i8042_reset) - if (i8042_command(¶m, I8042_CMD_CTL_TEST)) - printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n"); + i8042_ctl_test(); /* * Disable MUX mode if present. @@ -920,8 +925,11 @@ static int i8042_resume(struct device *dev, u32 level) if (level != RESUME_ENABLE) return 0; - if (i8042_controller_init()) { - printk(KERN_ERR "i8042: resume failed\n"); + if (i8042_ctl_test()) + return -1; + + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { + printk(KERN_ERR "i8042: Can't write CTR\n"); return -1; } -- cgit v1.1 From 5a72afc03ccc29458502cf032f5c34e5ee004ae7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 28 May 2005 02:11:32 -0500 Subject: Input: Tone down the severity of a printk() in i386/ia64 arch code for i386, it's printed on many machines and usually is not a cause for worry. Signed-off-by: Dmitry Torokhov Signed-off-by: Vojtech Pavlik --- drivers/input/serio/i8042-x86ia64io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 0327472..819e477 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -241,7 +241,7 @@ static int i8042_pnp_init(void) #if defined(__ia64__) return -ENODEV; #else - printk(KERN_WARNING "PNP: No PS/2 controller found. Probing ports directly.\n"); + printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n"); return 0; #endif } -- cgit v1.1 From 74af42bb729651855f78ea27498250724689130e Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Sat, 28 May 2005 02:11:38 -0500 Subject: Input: Avoid double unregistering of i8042 PnP driver. This can happen when no i8042 controller (not PnP, not legacy) is present. From: Kurt Garloff Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 819e477..f4c5f77 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -215,11 +215,15 @@ static struct pnp_driver i8042_pnp_aux_driver = { static void i8042_pnp_exit(void) { - if (i8042_pnp_kbd_registered) + if (i8042_pnp_kbd_registered) { + i8042_pnp_kbd_registered = 0; pnp_unregister_driver(&i8042_pnp_kbd_driver); + } - if (i8042_pnp_aux_registered) + if (i8042_pnp_aux_registered) { + i8042_pnp_aux_registered = 0; pnp_unregister_driver(&i8042_pnp_aux_driver); + } } static int i8042_pnp_init(void) -- cgit v1.1 From 7741e9317137a7456baa9c09ad8308c80c23b8db Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 28 May 2005 02:11:42 -0500 Subject: Input: Workaround for Sunrex K8561 IR Keyboard/Mouse. The mouse sends an incorrect ID and wasn't recognized. Reported-by: Stefan Seyfried Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index c9f8e16..019034b 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -518,13 +518,16 @@ static int psmouse_probe(struct psmouse *psmouse) /* * First, we check if it's a mouse. It should send 0x00 or 0x03 * in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer. + * Sunrex K8561 IR Keyboard/Mouse reports 0xff on second and subsequent + * ID queries, probably due to a firmware bug. */ param[0] = 0xa5; if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) return -1; - if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04) + if (param[0] != 0x00 && param[0] != 0x03 && + param[0] != 0x04 && param[0] != 0xff) return -1; /* -- cgit v1.1 From f24949e8e0b9bed223ad9a435bf37e91ee8d0db7 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 28 May 2005 02:11:49 -0500 Subject: Input: Fix button mapping in joydev - BTN_TRIGGER was being mapped twice, resulting in it being the last (instead of first) button on a joystick. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/joydev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 7d7527f..627d343 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -422,7 +422,7 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct joydev->nkey++; } - for (i = 0; i < BTN_JOYSTICK - BTN_MISC + 1; i++) + for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++) if (test_bit(i + BTN_MISC, dev->keybit)) { joydev->keymap[i] = joydev->nkey; joydev->keypam[joydev->nkey] = i + BTN_MISC; -- cgit v1.1 From a07461ec0cffb105c7e7b7404520ea2c74129db0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 28 May 2005 02:12:00 -0500 Subject: Input: gunze - fix out-of-bound array access reported by Adrian Bunk. Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/gunze.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index c9d0a15..53a27e4 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -68,8 +68,7 @@ static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs) if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' || (gunze->data[0] != 'T' && gunze->data[0] != 'R')) { - gunze->data[10] = 0; - printk(KERN_WARNING "gunze.c: bad packet: >%s<\n", gunze->data); + printk(KERN_WARNING "gunze.c: bad packet: >%.*s<\n", GUNZE_MAX_LENGTH, gunze->data); return; } -- cgit v1.1 From 59311de3fb5f293b2e99d7f52e0ab5572759951d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 28 May 2005 02:12:05 -0500 Subject: Input: automatically disable MUX mode on Toshiba Satellite P10 because it interferes with ALPS touchpad detection and causes horrible death on reboot. Since P10 does not have external PS/2 ports MUX mode does not have any advantages over legacy mode anyway. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f4c5f77..c97ad98 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -88,9 +88,11 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }; /* - * Some Fujitsu notebooks are ahving trouble with touhcpads if + * Some Fujitsu notebooks are having trouble with touchpads if * active multiplexing mode is activated. Luckily they don't have * external PS/2 ports so we can safely disable it. + * ... apparently some Toshibas don't like MUX mode either and + * die horrible death on reboot. */ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { { @@ -121,6 +123,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"), }, }, + { + .ident = "Toshiba P10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), + }, + }, { } }; -- cgit v1.1 From b4ff99b60c5e17b1031deb20c9d7688ebe6c9659 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 28 May 2005 02:12:10 -0500 Subject: Input: yet another model that does not play nicely when i8042 is put in MUX mode - Fujitsu Lifebook S6230 Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index c97ad98..0487ecb 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -117,6 +117,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, }, { + .ident = "Fujitsu Lifebook S6230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), + }, + }, + { .ident = "Fujitsu T70H", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -- cgit v1.1 From 409b7506759430f7c3841d425ca1f8a31eeadece Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 28 May 2005 02:12:18 -0500 Subject: Input: synaptics - reduce verboseness of synaptics driver - there is no reason one driver should take 10 lines in dmesg. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 39 +++++---------------------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 69832f8..36c7212 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -143,39 +143,6 @@ static int synaptics_identify(struct psmouse *psmouse) return -1; } -static void print_ident(struct synaptics_data *priv) -{ - printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity)); - printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity), - SYN_ID_MINOR(priv->identity)); - if (SYN_MODEL_ROT180(priv->model_id)) - printk(KERN_INFO " 180 degree mounted touchpad\n"); - if (SYN_MODEL_PORTRAIT(priv->model_id)) - printk(KERN_INFO " portrait touchpad\n"); - printk(KERN_INFO " Sensor: %ld\n", SYN_MODEL_SENSOR(priv->model_id)); - if (SYN_MODEL_NEWABS(priv->model_id)) - printk(KERN_INFO " new absolute packet format\n"); - if (SYN_MODEL_PEN(priv->model_id)) - printk(KERN_INFO " pen detection\n"); - - if (SYN_CAP_EXTENDED(priv->capabilities)) { - printk(KERN_INFO " Touchpad has extended capability bits\n"); - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) - printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n", - (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))); - if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) - printk(KERN_INFO " -> middle button\n"); - if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) - printk(KERN_INFO " -> four buttons\n"); - if (SYN_CAP_MULTIFINGER(priv->capabilities)) - printk(KERN_INFO " -> multifinger detection\n"); - if (SYN_CAP_PALMDETECT(priv->capabilities)) - printk(KERN_INFO " -> palm detection\n"); - if (SYN_CAP_PASS_THROUGH(priv->capabilities)) - printk(KERN_INFO " -> pass-through port\n"); - } -} - static int synaptics_query_hardware(struct psmouse *psmouse) { int retries = 0; @@ -666,7 +633,11 @@ int synaptics_init(struct psmouse *psmouse) priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; - print_ident(priv); + printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n", + SYN_ID_MODEL(priv->identity), + SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), + priv->model_id, priv->capabilities, priv->ext_cap); + set_input_params(&psmouse->dev, priv); psmouse->protocol_handler = synaptics_process_byte; -- cgit v1.1 From dcefb396c2af4d52fba48dc58b4021794b042046 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 28 May 2005 00:51:24 -0400 Subject: [PATCH] Fix up pwc driver compilation. The neutering of the pwc driver was incomplete. It still references some now-dead files.. Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- drivers/usb/media/pwc/pwc-ctrl.c | 2 -- drivers/usb/media/pwc/pwc-uncompress.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c index 3e1e4fe..5309919 100644 --- a/drivers/usb/media/pwc/pwc-ctrl.c +++ b/drivers/usb/media/pwc/pwc-ctrl.c @@ -48,8 +48,6 @@ #include "pwc-uncompress.h" #include "pwc-kiara.h" #include "pwc-timon.h" -#include "pwc-dec1.h" -#include "pwc-dec23.h" /* Request types: video */ #define SET_LUM_CTL 0x01 diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c index c596083..bc3b163 100644 --- a/drivers/usb/media/pwc/pwc-uncompress.c +++ b/drivers/usb/media/pwc/pwc-uncompress.c @@ -29,8 +29,6 @@ #include "pwc.h" #include "pwc-uncompress.h" -#include "pwc-dec1.h" -#include "pwc-dec23.h" int pwc_decompress(struct pwc_device *pdev) { -- cgit v1.1 From c5924b7d97430657fa07ebf1a208c7e8cf135ef3 Mon Sep 17 00:00:00 2001 From: Oliver Korpilla Date: Fri, 27 May 2005 12:52:55 -0700 Subject: [PATCH] x86_64: signal.c build fix For unspecified reasons, arch/x86_64/kernel/signal.c apparently needs ia32_unistd.h. Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/signal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index 3fdcdba..429c026 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -28,6 +28,7 @@ #include #include #include +#include /* #define DEBUG_SIG 1 */ -- cgit v1.1 From d6649bc76a57523209a6b2ee4844c9078a4dd8bb Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 27 May 2005 12:52:56 -0700 Subject: [PATCH] ppc32: small cpufreq update This patch adds a missing attribute to pmac cpufreq so that "scaling_available_frequencies" works. It also cleans up the duplicate definitions for low and high speed constants. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: John Clemens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/pmac_cpufreq.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index f7fb278..48e482c 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -85,14 +85,11 @@ static int no_schedule; static int has_cpu_l2lve; -#define PMAC_CPU_LOW_SPEED 1 -#define PMAC_CPU_HIGH_SPEED 0 - /* There are only two frequency states for each processor. Values * are in kHz for the time being. */ -#define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED -#define CPUFREQ_LOW PMAC_CPU_LOW_SPEED +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 static struct cpufreq_frequency_table pmac_cpu_freqs[] = { {CPUFREQ_HIGH, 0}, @@ -100,6 +97,11 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = { {0, CPUFREQ_TABLE_END}, }; +static struct freq_attr* pmac_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + static inline void local_delay(unsigned long ms) { if (no_schedule) @@ -355,7 +357,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify) static unsigned long prev_l3cr; freqs.old = cur_freq; - freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; + freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; freqs.cpu = smp_processor_id(); if (freqs.old == freqs.new) @@ -363,7 +365,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify) if (notify) cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (speed_mode == PMAC_CPU_LOW_SPEED && + if (speed_mode == CPUFREQ_LOW && cpu_has_feature(CPU_FTR_L3CR)) { l3cr = _get_L3CR(); if (l3cr & L3CR_L3E) { @@ -371,8 +373,8 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify) _set_L3CR(0); } } - set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED); - if (speed_mode == PMAC_CPU_HIGH_SPEED && + set_speed_proc(speed_mode == CPUFREQ_LOW); + if (speed_mode == CPUFREQ_HIGH && cpu_has_feature(CPU_FTR_L3CR)) { l3cr = _get_L3CR(); if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) @@ -380,7 +382,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify) } if (notify) cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; + cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; return 0; } @@ -423,7 +425,8 @@ static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = cur_freq; - return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]); + cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); + return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); } static u32 __pmac read_gpio(struct device_node *np) @@ -457,7 +460,7 @@ static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state) no_schedule = 1; sleep_freq = cur_freq; if (cur_freq == low_freq) - do_set_cpu_speed(PMAC_CPU_HIGH_SPEED, 0); + do_set_cpu_speed(CPUFREQ_HIGH, 0); return 0; } @@ -473,8 +476,8 @@ static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy) * is that we force a switch to whatever it was, which is * probably high speed due to our suspend() routine */ - do_set_cpu_speed(sleep_freq == low_freq ? PMAC_CPU_LOW_SPEED - : PMAC_CPU_HIGH_SPEED, 0); + do_set_cpu_speed(sleep_freq == low_freq ? + CPUFREQ_LOW : CPUFREQ_HIGH, 0); no_schedule = 0; return 0; @@ -488,6 +491,7 @@ static struct cpufreq_driver pmac_cpufreq_driver = { .suspend = pmac_cpufreq_suspend, .resume = pmac_cpufreq_resume, .flags = CPUFREQ_PM_NO_WARN, + .attr = pmac_cpu_freqs_attr, .name = "powermac", .owner = THIS_MODULE, }; -- cgit v1.1 From 9ae250d175e1cbff82223ce2c07897c790c5b948 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 27 May 2005 12:52:57 -0700 Subject: [PATCH] ppc32: Fix Alsa PowerMac driver on old machines The g5 support code broke some earlier models unfortunately as those bail out early from the detect function, before the point where I added the code to locate the PCI device for use with DMA allocations. This patch fixes it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/ppc/pmac.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 32d9475..080ef39 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -876,7 +876,7 @@ static void __init detect_byte_swap(pmac_t *chip) */ static int __init snd_pmac_detect(pmac_t *chip) { - struct device_node *sound; + struct device_node *sound = NULL; unsigned int *prop, l; struct macio_chip* macio; @@ -906,20 +906,22 @@ static int __init snd_pmac_detect(pmac_t *chip) chip->is_pbook_G3 = 1; chip->node = find_devices("awacs"); if (chip->node) - return 0; /* ok */ + sound = chip->node; /* * powermac G3 models have a node called "davbus" * with a child called "sound". */ - chip->node = find_devices("davbus"); + if (!chip->node) + chip->node = find_devices("davbus"); /* * if we didn't find a davbus device, try 'i2s-a' since * this seems to be what iBooks have */ if (! chip->node) { chip->node = find_devices("i2s-a"); - if (chip->node && chip->node->parent && chip->node->parent->parent) { + if (chip->node && chip->node->parent && + chip->node->parent->parent) { if (device_is_compatible(chip->node->parent->parent, "K2-Keylargo")) chip->is_k2 = 1; @@ -928,9 +930,11 @@ static int __init snd_pmac_detect(pmac_t *chip) if (! chip->node) return -ENODEV; - sound = find_devices("sound"); - while (sound && sound->parent != chip->node) - sound = sound->next; + if (!sound) { + sound = find_devices("sound"); + while (sound && sound->parent != chip->node) + sound = sound->next; + } if (! sound) return -ENODEV; prop = (unsigned int *) get_property(sound, "sub-frame", NULL); @@ -1019,7 +1023,8 @@ static int __init snd_pmac_detect(pmac_t *chip) } } if (chip->pdev == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio PCI device !\n"); + printk(KERN_WARNING "snd-powermac: can't locate macio PCI" + " device !\n"); detect_byte_swap(chip); @@ -1027,7 +1032,8 @@ static int __init snd_pmac_detect(pmac_t *chip) are available */ prop = (unsigned int *) get_property(sound, "sample-rates", &l); if (! prop) - prop = (unsigned int *) get_property(sound, "output-frame-rates", &l); + prop = (unsigned int *) get_property(sound, + "output-frame-rates", &l); if (prop) { int i; chip->freqs_ok = 0; @@ -1054,7 +1060,8 @@ static int __init snd_pmac_detect(pmac_t *chip) /* * exported - boolean info callbacks for ease of programming */ -int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 2; @@ -1063,7 +1070,8 @@ int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * return 0; } -int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; -- cgit v1.1 From 9db29258893b08a838e5ecfa4a0933c9c1f2e305 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 27 May 2005 12:52:58 -0700 Subject: [PATCH] ppc64 iSeries: make virtual DVD-RAMs writable again It appears that another test has been added in the Uniform CDROM layer that must be passed before a DVD-RAM is considered writeable. This patch implements an emulation of the needed packet command for the viocd driver. Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cdrom/viocd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index fcca26c..38dd9ff 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -488,6 +488,20 @@ static int viocd_packet(struct cdrom_device_info *cdi, & (CDC_DVD_RAM | CDC_RAM)) != 0; } break; + case GPCMD_GET_CONFIGURATION: + if (cgc->cmd[3] == CDF_RWRT) { + struct rwrt_feature_desc *rfd = (struct rwrt_feature_desc *)(cgc->buffer + sizeof(struct feature_header)); + + if ((buflen >= + (sizeof(struct feature_header) + sizeof(*rfd))) && + (cdi->ops->capability & ~cdi->mask + & (CDC_DVD_RAM | CDC_RAM))) { + rfd->feature_code = cpu_to_be16(CDF_RWRT); + rfd->curr = 1; + ret = 0; + } + } + break; default: if (cgc->sense) { /* indicate Unknown code */ -- cgit v1.1 From 70ffc71c5c42c8ac62d951e80d9799bd5764f2f5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 27 May 2005 12:52:59 -0700 Subject: [PATCH] arch/i386/kernel/cpu/intel_cacheinfo.c: section fix num_cache_leaves is used in __devexit cache_remove_dev() and can therefore not be __devinit. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/intel_cacheinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index aeb5b4e..a710dc4 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -118,7 +118,7 @@ struct _cpuid4_info { }; #define MAX_CACHE_LEAVES 4 -static unsigned short __devinitdata num_cache_leaves; +static unsigned short num_cache_leaves; static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { -- cgit v1.1 From b60c1f6ffd88850079ae419aa933ab0eddbd5535 Mon Sep 17 00:00:00 2001 From: John Hawkes Date: Fri, 27 May 2005 12:53:00 -0700 Subject: [PATCH] drop note_interrupt() for per-CPU for proper scaling The "unhandled interrupts" catcher, note_interrupt(), increments a global desc->irq_count and grossly damages scaling of very large systems, e.g., >192p ia64 Altix, because of this highly contented cacheline, especially for timer interrupts. 384p is severely crippled, and 512p is unuseable. All calls to note_interrupt() can be disabled by booting with "noirqdebug", but this disables the useful interrupt checking for all interrupts. I propose eliminating note_interrupt() for all per-CPU interrupts. This was the behavior of linux-2.6.10 and earlier, but in 2.6.11 a code restructuring added a call to note_interrupt() for per-CPU interrupts. Besides, note_interrupt() is a bit racy for concurrent CPU calls anyway, as the desc->irq_count++ increment isn't atomic (which, if done, would make scaling even worse). Signed-off-by: John Hawkes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/irq/handle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 06b5a63..436c7d9 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -119,8 +119,6 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) */ desc->handler->ack(irq); action_ret = handle_IRQ_event(irq, regs, desc->action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); desc->handler->end(irq); return 1; } -- cgit v1.1 From 49f384b82b03416dd7e4fc77847a959fe3247362 Mon Sep 17 00:00:00 2001 From: "Siddha, Suresh B" Date: Fri, 27 May 2005 12:53:01 -0700 Subject: [PATCH] x86: fix smp_num_siblings on buggy BIOSes This fixes 'smp_num_siblings' value on the systems with a buggy bios, which sets number of siblings to '2' even when HT is disabled. (more details are at http://bugzilla.kernel.org/show_bug.cgi?id=4359) I am planning to do more cleanup in this area (like moving smp_num_siblings to per cpuinfo) shortly. Signed-off-by: Suresh Siddha Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smpboot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 35bfe13..bc1bb69 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1074,8 +1074,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpu_set(cpu, cpu_sibling_map[cpu]); } - if (siblings != smp_num_siblings) + if (siblings != smp_num_siblings) { printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); + smp_num_siblings = siblings; + } if (c->x86_num_cores > 1) { for (i = 0; i < NR_CPUS; i++) { -- cgit v1.1 From b16eeb47292597a8bf3ad53fdaf1f727f57bd8e4 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 27 May 2005 12:53:02 -0700 Subject: [PATCH] ppc32: Fix cpufreq vs. sleep issue Recent kernels occasionally trigger a PMU timeout on some mac laptops, typically on wakeup from sleep. This seem to be caused by either a too big latency caused by the cpufreq switch on wakeup from sleep or by an interrupt beeing lost due to the reset of the interrupt controller done during wakeup. This patch makes that code more robust by stopping PMU auto poll activity around cpufreq changes on machines that use the PMU for such changes (long latency switching involving a CPU hard reset and flush of all caches) and by removing the reset of the open pic interrupt controller on wakeup (that can cause the loss of an interrupt and Darwin doesn't do it, so it must not be necessary). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/pmac_cpufreq.c | 4 ++++ arch/ppc/syslib/open_pic.c | 4 +--- drivers/macintosh/via-pmu.c | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index 48e482c..937f46d 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -271,6 +271,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed) #ifdef DEBUG_FREQ printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); #endif + pmu_suspend(); + /* Disable all interrupt sources on openpic */ pic_prio = openpic_get_priority(); openpic_set_priority(0xf); @@ -345,6 +347,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed) debug_calc_bogomips(); #endif + pmu_resume(); + preempt_enable(); return 0; diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index 9d4ed68..000ba47 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -275,7 +275,7 @@ static void __init openpic_enable_sie(void) } #endif -#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM) +#if defined(CONFIG_EPIC_SERIAL_MODE) static void openpic_reset(void) { openpic_setfield(&OpenPIC->Global.Global_Configuration0, @@ -993,8 +993,6 @@ int openpic_resume(struct sys_device *sysdev) return 0; } - openpic_reset(); - /* OpenPIC sometimes seem to need some time to be fully back up... */ do { openpic_set_spurious(OPENPIC_VEC_SPURIOUS); diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index e654aa5..bb9f404 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2421,7 +2421,7 @@ pmac_wakeup_devices(void) /* Re-enable local CPU interrupts */ local_irq_enable(); - mdelay(100); + mdelay(10); preempt_enable(); /* Re-enable clock spreading on some machines */ @@ -2549,7 +2549,9 @@ powerbook_sleep_Core99(void) return ret; } - printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); + /* Stop environment and ADB interrupts */ + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0); + pmu_wait_complete(&req); /* Tell PMU what events will wake us up */ pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS, @@ -2611,8 +2613,6 @@ powerbook_sleep_Core99(void) pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); pmu_wait_complete(&req); - printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); - pmac_wakeup_devices(); return 0; -- cgit v1.1 From 8bd7f125e2f217c8aa3dff005ae291c81246c340 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 27 May 2005 12:53:03 -0700 Subject: [PATCH] swsusp: ahd_dv_0 can't be stopped This driver wants to set PF_NOFREEZE. Cc: James Bottomley Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/aic7xxx/aic79xx_osm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 550c992..7c02b7d 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2488,7 +2488,7 @@ ahd_linux_dv_thread(void *data) sprintf(current->comm, "ahd_dv_%d", ahd->unit); #else daemonize("ahd_dv_%d", ahd->unit); - current->flags |= PF_FREEZE; + current->flags |= PF_NOFREEZE; #endif unlock_kernel(); -- cgit v1.1 From c1e4c8d3ee3300f363a52fd4cf3d90fdf5098f5a Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 27 May 2005 12:53:03 -0700 Subject: [PATCH] fix jumpy mouse cursor on console Do not send empty events to gpm. (Keyboards are assumed to have scroll wheel these days, that makes them part-mouse. That means typing on keyboard generates empty mouse events). From: Dmitry Torokhov Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/mousedev.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 564974c..96fb987 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -101,6 +101,7 @@ struct mousedev_list { unsigned char ready, buffer, bufsiz; unsigned char imexseq, impsseq; enum mousedev_emul mode; + unsigned long last_buttons; }; #define MOUSEDEV_SEQ_LEN 6 @@ -224,7 +225,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h spin_lock_irqsave(&list->packet_lock, flags); p = &list->packets[list->head]; - if (list->ready && p->buttons != packet->buttons) { + if (list->ready && p->buttons != mousedev->packet.buttons) { unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN; if (new_head != list->tail) { p = &list->packets[list->head = new_head]; @@ -249,10 +250,13 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h p->dz += packet->dz; p->buttons = mousedev->packet.buttons; - list->ready = 1; + if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons) + list->ready = 1; spin_unlock_irqrestore(&list->packet_lock, flags); - kill_fasync(&list->fasync, SIGIO, POLL_IN); + + if (list->ready) + kill_fasync(&list->fasync, SIGIO, POLL_IN); } wake_up_interruptible(&mousedev->wait); @@ -477,9 +481,10 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) } if (!p->dx && !p->dy && !p->dz) { - if (list->tail == list->head) + if (list->tail == list->head) { list->ready = 0; - else + list->last_buttons = p->buttons; + } else list->tail = (list->tail + 1) % PACKET_QUEUE_LEN; } -- cgit v1.1 From 346e399b2a3a01b323fa74a0937e2d855479833b Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Sat, 28 May 2005 15:51:46 -0700 Subject: [PATCH] intelfb section fix On Nov 16 2004 a change to intelfbdrv.c was commited (as part of 0.9.2 it looks like) that added __initdata to all of the module param variables that seems to create the opportunity for an oops. I've recently been chasing an OOPS (http://marc.theaimsgroup.com/?l=linux-kernel&m=111552250920370&w=2) I created by reading every file on the /sys file system and I've traced it back to this code in the intelfbdrv. Though I had root privs in my initial problem report, it turns out they are un-necessary to generate the oops - all you've got to do is "cat /sys/module/intelfb/parameters/mode" enough times and eventually it will oops. This is because sysfs automatically exports all module_param declarations to the sysfs file system.. which means those variables can be dynamically evaluated at any later time, which of course means marking them __initdata is a bad idea ;).. when they happen to be char *'s it is an especially bad idea ;). Applying the patch below clears up the OOPS for me. Signed-off-by: Patrick McManus Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/intelfb/intelfbdrv.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 549e229..25f9a9a 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -228,17 +228,17 @@ MODULE_DESCRIPTION( MODULE_LICENSE("Dual BSD/GPL"); MODULE_DEVICE_TABLE(pci, intelfb_pci_table); -static int accel __initdata = 1; -static int vram __initdata = 4; -static int hwcursor __initdata = 1; -static int mtrr __initdata = 1; -static int fixed __initdata = 0; -static int noinit __initdata = 0; -static int noregister __initdata = 0; -static int probeonly __initdata = 0; -static int idonly __initdata = 0; -static int bailearly __initdata = 0; -static char *mode __initdata = NULL; +static int accel = 1; +static int vram = 4; +static int hwcursor = 1; +static int mtrr = 1; +static int fixed = 0; +static int noinit = 0; +static int noregister = 0; +static int probeonly = 0; +static int idonly = 0; +static int bailearly = 0; +static char *mode = NULL; module_param(accel, bool, S_IRUGO); MODULE_PARM_DESC(accel, "Enable console acceleration"); -- cgit v1.1 From 5212dd58e67e4b8009107d69a9de45dd2e687496 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 28 May 2005 15:51:47 -0700 Subject: [PATCH] input: Fix fast scrolling scancodes in atkbd.c Signed-off-by: Vojtech Pavlik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/keyboard/atkbd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 79c332f..af0446c 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -171,9 +171,9 @@ static struct { unsigned char set2; } atkbd_scroll_keys[] = { { ATKBD_SCR_1, 0xc5 }, - { ATKBD_SCR_2, 0xa9 }, - { ATKBD_SCR_4, 0xb6 }, - { ATKBD_SCR_8, 0xa7 }, + { ATKBD_SCR_2, 0x9d }, + { ATKBD_SCR_4, 0xa4 }, + { ATKBD_SCR_8, 0x9b }, { ATKBD_SCR_CLICK, 0xe0 }, { ATKBD_SCR_LEFT, 0xcb }, { ATKBD_SCR_RIGHT, 0xd2 }, -- cgit v1.1 From 203fe8b3d1f5b1b527e86f6dbe5b75960acb7f4f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 28 May 2005 15:51:48 -0700 Subject: [PATCH] dvb: Fix Mini DiSEqC bug The bug was visible as a warning with gcc-3.4.4 (prerelease) Message: drivers/media/dvb/bt8xx/dst.c:1349: warning: initialization from incompatible pointer type. Signed-off-by: Manu Abraham Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index d047e34..2efc6f1 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -915,13 +915,11 @@ static int dst_tone_power_cmd(struct dst_state* state) paket[2] = 0x02; else paket[2] = 0; - if (state->minicmd == SEC_MINI_A) - paket[3] = 0x02; - else - paket[3] = 0; + paket[3] = state->tx_tuna[3]; paket[7] = dst_check_sum (paket, 7); dst_command(state, paket, 8); + return 0; } @@ -1134,6 +1132,29 @@ static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) return 0; } +static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) +{ + struct dst_state *state = fe->demodulator_priv; + + if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) + return 0; + + state->minicmd = minicmd; + + switch (minicmd) { + case SEC_MINI_A: + state->tx_tuna[3] = 0x02; + break; + case SEC_MINI_B: + state->tx_tuna[3] = 0xff; + break; + } + dst_tone_power_cmd(state); + + return 0; +} + + static int dst_init(struct dvb_frontend* fe) { struct dst_state* state = (struct dst_state*) fe->demodulator_priv; @@ -1346,7 +1367,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = { .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, - .diseqc_send_burst = dst_set_tone, + .diseqc_send_burst = dst_send_burst, .diseqc_send_master_cmd = dst_set_diseqc, .set_voltage = dst_set_voltage, .set_tone = dst_set_tone, -- cgit v1.1 From 0eac3e486e1f246a9d59fee9251cc69e409cb58e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 28 May 2005 15:51:50 -0700 Subject: [PATCH] dvb: Remove unnecessary casts Cleanup unnecessary (and undesirable) casts, demodulator_priv is already a void*. Suggestion from Andrew Morton Signed-off-by: Manu Abraham Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 2efc6f1..e5e8c3e 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -978,7 +978,7 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage); static int dst_write_tuna(struct dvb_frontend* fe) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; int retval; u8 reply; @@ -1046,7 +1046,7 @@ static int dst_write_tuna(struct dvb_frontend* fe) static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; if (state->dst_type == DST_TYPE_IS_TERR) @@ -1064,7 +1064,7 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { u8 *val; int need_cmd; - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; state->voltage = voltage; @@ -1105,7 +1105,7 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { u8 *val; - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; state->tone = tone; @@ -1157,7 +1157,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) static int dst_init(struct dvb_frontend* fe) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 }; static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 }; static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; @@ -1189,7 +1189,7 @@ static int dst_init(struct dvb_frontend* fe) static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; *status = 0; if (state->diseq_flags & HAS_LOCK) { @@ -1203,7 +1203,7 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status) static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; dst_get_signal(state); *strength = state->decode_strength; @@ -1213,7 +1213,7 @@ static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength) static int dst_read_snr(struct dvb_frontend* fe, u16* snr) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; dst_get_signal(state); *snr = state->decode_snr; @@ -1223,7 +1223,7 @@ static int dst_read_snr(struct dvb_frontend* fe, u16* snr) static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; dst_set_freq(state, p->frequency); if (verbose > 4) @@ -1249,7 +1249,7 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; p->frequency = state->decode_freq; p->inversion = state->inversion; @@ -1269,7 +1269,7 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet static void dst_release(struct dvb_frontend* fe) { - struct dst_state* state = (struct dst_state*) fe->demodulator_priv; + struct dst_state* state = fe->demodulator_priv; kfree(state); } -- cgit v1.1 From 8f6da8f166228c1720d16216a9d82d630c58de57 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 28 May 2005 15:51:51 -0700 Subject: [PATCH] dvb: Fix LNB power switching Signed-off-by: Manu Abraham Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index e5e8c3e..33cca69d 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -906,10 +906,7 @@ static int dst_tone_power_cmd(struct dst_state* state) if (state->dst_type == DST_TYPE_IS_TERR) return 0; - if (state->voltage == SEC_VOLTAGE_OFF) - paket[4] = 0; - else - paket[4] = 1; + paket[4] = state->tx_tuna[4]; if (state->tone == SEC_TONE_ON) paket[2] = 0x02; @@ -1062,7 +1059,6 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { - u8 *val; int need_cmd; struct dst_state* state = fe->demodulator_priv; @@ -1072,29 +1068,23 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) return 0; need_cmd = 0; - val = &state->tx_tuna[0]; - val[8] &= ~0x40; switch (voltage) { - case SEC_VOLTAGE_13: - if ((state->diseq_flags & HAS_POWER) == 0) - need_cmd = 1; - state->diseq_flags |= HAS_POWER; - break; + case SEC_VOLTAGE_13: + case SEC_VOLTAGE_18: + if ((state->diseq_flags & HAS_POWER) == 0) + need_cmd = 1; + state->diseq_flags |= HAS_POWER; + state->tx_tuna[4] = 0x01; + break; - case SEC_VOLTAGE_18: - if ((state->diseq_flags & HAS_POWER) == 0) + case SEC_VOLTAGE_OFF: need_cmd = 1; - state->diseq_flags |= HAS_POWER; - val[8] |= 0x40; - break; - - case SEC_VOLTAGE_OFF: - need_cmd = 1; - state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); - break; + state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); + state->tx_tuna[4] = 0x00; + break; - default: - return -EINVAL; + default: + return -EINVAL; } if (need_cmd) dst_tone_power_cmd(state); -- cgit v1.1 From 86360a3edeb6b7b6230dc13ef6835d2851409502 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 28 May 2005 15:51:51 -0700 Subject: [PATCH] dvb: Fix 22k tone control Signed-off-by: Manu Abraham Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 33cca69d..8104240 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -907,12 +907,7 @@ static int dst_tone_power_cmd(struct dst_state* state) return 0; paket[4] = state->tx_tuna[4]; - - if (state->tone == SEC_TONE_ON) - paket[2] = 0x02; - else - paket[2] = 0; - + paket[2] = state->tx_tuna[2]; paket[3] = state->tx_tuna[3]; paket[7] = dst_check_sum (paket, 7); dst_command(state, paket, 8); @@ -1094,7 +1089,6 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - u8 *val; struct dst_state* state = fe->demodulator_priv; state->tone = tone; @@ -1102,20 +1096,17 @@ static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) if (state->dst_type == DST_TYPE_IS_TERR) return 0; - val = &state->tx_tuna[0]; - - val[8] &= ~0x1; - switch (tone) { - case SEC_TONE_OFF: - break; + case SEC_TONE_OFF: + state->tx_tuna[2] = 0xff; + break; - case SEC_TONE_ON: - val[8] |= 1; - break; + case SEC_TONE_ON: + state->tx_tuna[2] = 0x02; + break; - default: - return -EINVAL; + default: + return -EINVAL; } dst_tone_power_cmd(state); -- cgit v1.1 From 226d97ec3e47b54ecc13f6ea3c300dc6a1b290c3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 28 May 2005 15:51:52 -0700 Subject: [PATCH] dvb: Small cleanup Miscellaneous cleanup Signed-off-by: Manu Abraham Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 8104240..1339912 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1041,7 +1041,7 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* struct dst_state* state = fe->demodulator_priv; u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; - if (state->dst_type == DST_TYPE_IS_TERR) + if (state->dst_type != DST_TYPE_IS_SAT) return 0; if (cmd->msg_len == 0 || cmd->msg_len > 4) @@ -1059,7 +1059,7 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) state->voltage = voltage; - if (state->dst_type == DST_TYPE_IS_TERR) + if (state->dst_type != DST_TYPE_IS_SAT) return 0; need_cmd = 0; @@ -1093,7 +1093,7 @@ static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) state->tone = tone; - if (state->dst_type == DST_TYPE_IS_TERR) + if (state->dst_type != DST_TYPE_IS_SAT) return 0; switch (tone) { @@ -1117,7 +1117,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) { struct dst_state *state = fe->demodulator_priv; - if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) + if (state->dst_type != DST_TYPE_IS_SAT) return 0; state->minicmd = minicmd; -- cgit v1.1 From b9e0d0696c9e86d4e40b23039feefb8c377cb524 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 28 May 2005 15:51:53 -0700 Subject: [PATCH] uml: fix a couple of warnings Eliminate an unused variable warning in ptrace.c and a size mismatch warning by adding a cast to __pa. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/ptrace.c | 19 +++---------------- include/asm-um/page.h | 8 +++++++- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 2925e15..71af4d5 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -322,11 +322,9 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) UPT_SYSCALL_ARG2(regs), UPT_SYSCALL_ARG3(regs), UPT_SYSCALL_ARG4(regs)); - else { - int res = UPT_SYSCALL_RET(regs); - audit_syscall_exit(current, AUDITSC_RESULT(res), - res); - } + else audit_syscall_exit(current, + AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), + UPT_SYSCALL_RET(regs)); } /* Fake a debug trap */ @@ -356,14 +354,3 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) current->exit_code = 0; } } - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/include/asm-um/page.h b/include/asm-um/page.h index 504ea8e..5afee8a 100644 --- a/include/asm-um/page.h +++ b/include/asm-um/page.h @@ -98,7 +98,13 @@ extern unsigned long uml_physmem; extern unsigned long to_phys(void *virt); extern void *to_virt(unsigned long phys); -#define __pa(virt) to_phys((void *) virt) + +/* Cast to unsigned long before casting to void * to avoid a warning from + * mmap_kmem about cutting a long long down to a void *. Not sure that + * casting is the right thing, but 32-bit UML can't have 64-bit virtual + * addresses + */ +#define __pa(virt) to_phys((void *) (unsigned long) virt) #define __va(phys) to_virt((unsigned long) phys) #define page_to_pfn(page) ((page) - mem_map) -- cgit v1.1 From 6770cb61ff6d557613a8382b28f9b0a919fb112f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 28 May 2005 15:51:54 -0700 Subject: [PATCH] uml: turn off kmalloc always on a fatal signal We should turn off kmalloc when getting a fatal signal regardless of the mode we're in. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c index a17c497..939e3b7 100644 --- a/arch/um/kernel/main.c +++ b/arch/um/kernel/main.c @@ -71,7 +71,7 @@ static __init void do_uml_initcalls(void) static void last_ditch_exit(int sig) { - CHOOSE_MODE(kmalloc_ok = 0, (void) 0); + kmalloc_ok = 0; signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGHUP, SIG_DFL); -- cgit v1.1 From a2e4b972c99685d9d7b869c4bf8d8b258ff5b60c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 28 May 2005 15:51:54 -0700 Subject: [PATCH] uml: remove 2_5compat.h Remove old useless header that was used in Ye Olde Times during 2.4->2.5 porting to abstract differences. It's definitions are no more used anyway, so let's finally kill it. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ssl.c | 1 - arch/um/drivers/stdio_console.c | 1 - arch/um/drivers/ubd_kern.c | 1 - arch/um/include/2_5compat.h | 24 ------------------------ arch/um/kernel/exec_kern.c | 1 - arch/um/kernel/process_kern.c | 2 -- arch/um/kernel/trap_kern.c | 1 - fs/hostfs/hostfs_kern.c | 1 - 8 files changed, 32 deletions(-) delete mode 100644 arch/um/include/2_5compat.h diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index a2bac42..b32a770 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -22,7 +22,6 @@ #include "init.h" #include "irq_user.h" #include "mconsole_kern.h" -#include "2_5compat.h" static int ssl_version = 1; diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 361d0be..afbe1e7 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -28,7 +28,6 @@ #include "irq_user.h" #include "mconsole_kern.h" #include "init.h" -#include "2_5compat.h" #define MAX_TTYS (16) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 88f956c..7e98e3e 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -49,7 +49,6 @@ #include "irq_user.h" #include "irq_kern.h" #include "ubd_user.h" -#include "2_5compat.h" #include "os.h" #include "mem.h" #include "mem_kern.h" diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h deleted file mode 100644 index abdb015..0000000 --- a/arch/um/include/2_5compat.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __2_5_COMPAT_H__ -#define __2_5_COMPAT_H__ - -#define INIT_HARDSECT(arr, maj, sizes) - -#define SET_PRI(task) do ; while(0) - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 49ddabe..efd222f 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -16,7 +16,6 @@ #include "kern.h" #include "irq_user.h" #include "tlb.h" -#include "2_5compat.h" #include "os.h" #include "time_user.h" #include "choose-mode.h" diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index c1adf7b..ccb6dd6 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -43,7 +43,6 @@ #include "tlb.h" #include "frame_kern.h" #include "sigcontext.h" -#include "2_5compat.h" #include "os.h" #include "mode.h" #include "mode_kern.h" @@ -189,7 +188,6 @@ void default_idle(void) while(1){ /* endless idle loop with no priority at all */ - SET_PRI(current); /* * although we are an idle CPU, we do not want to diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 1de22d8..c20aef1 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -23,7 +23,6 @@ #include "kern.h" #include "chan_kern.h" #include "mconsole_kern.h" -#include "2_5compat.h" #include "mem.h" #include "mem_kern.h" diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 14a0d33..4bf43ea 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -23,7 +23,6 @@ #include "kern_util.h" #include "kern.h" #include "user_util.h" -#include "2_5compat.h" #include "init.h" struct hostfs_inode_info { -- cgit v1.1 From 0894e27e7999bdbad2e65734caa1d5de65e7d890 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 28 May 2005 15:51:55 -0700 Subject: [PATCH] uml: single-space a help message One of the ubd driver help strings was bust. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 7e98e3e..2a7f689 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -439,9 +439,9 @@ static int udb_setup(char *str) __setup("udb", udb_setup); __uml_help(udb_setup, "udb\n" -" This option is here solely to catch ubd -> udb typos, which can be\n\n" -" to impossible to catch visually unless you specifically look for\n\n" -" them. The only result of any option starting with 'udb' is an error\n\n" +" This option is here solely to catch ubd -> udb typos, which can be\n" +" to impossible to catch visually unless you specifically look for\n" +" them. The only result of any option starting with 'udb' is an error\n" " in the boot output.\n\n" ); -- cgit v1.1 From 92515da73a5df50db45111b8659ac463b4800236 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 28 May 2005 15:51:56 -0700 Subject: [PATCH] uml: fix segfault on exit with CONFIG_GCOV We need to disable signals on exit in all cases, not just when rebooting. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/main.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c index 939e3b7..e42e636 100644 --- a/arch/um/kernel/main.c +++ b/arch/um/kernel/main.c @@ -87,7 +87,7 @@ int main(int argc, char **argv, char **envp) { char **new_argv; sigset_t mask; - int ret, i; + int ret, i, err; /* Enable all signals except SIGIO - in some environments, we can * enter with some signals blocked @@ -160,27 +160,29 @@ int main(int argc, char **argv, char **envp) */ change_sig(SIGPROF, 0); - /* Reboot */ - if(ret){ - int err; - - printf("\n"); + /* This signal stuff used to be in the reboot case. However, + * sometimes a SIGVTALRM can come in when we're halting (reproducably + * when writing out gcov information, presumably because that takes + * some time) and cause a segfault. + */ - /* stop timers and set SIG*ALRM to be ignored */ - disable_timer(); + /* stop timers and set SIG*ALRM to be ignored */ + disable_timer(); - /* disable SIGIO for the fds and set SIGIO to be ignored */ - err = deactivate_all_fds(); - if(err) - printf("deactivate_all_fds failed, errno = %d\n", - -err); + /* disable SIGIO for the fds and set SIGIO to be ignored */ + err = deactivate_all_fds(); + if(err) + printf("deactivate_all_fds failed, errno = %d\n", -err); - /* Let any pending signals fire now. This ensures - * that they won't be delivered after the exec, when - * they are definitely not expected. - */ - unblock_signals(); + /* Let any pending signals fire now. This ensures + * that they won't be delivered after the exec, when + * they are definitely not expected. + */ + unblock_signals(); + /* Reboot */ + if(ret){ + printf("\n"); execvp(new_argv[0], new_argv); perror("Failed to exec kernel"); ret = 1; -- cgit v1.1 From 7590d3ec1cda7d504c25103bde0c9911f93810e9 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sat, 28 May 2005 15:51:57 -0700 Subject: [PATCH] uml: remove unused code This removes two now unused files and a couple of unused functions. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/initrd_kern.c | 59 ------------------------------------------- arch/um/kernel/initrd_user.c | 46 --------------------------------- arch/um/kernel/process_kern.c | 34 ------------------------- 3 files changed, 139 deletions(-) delete mode 100644 arch/um/kernel/initrd_kern.c delete mode 100644 arch/um/kernel/initrd_user.c diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd_kern.c deleted file mode 100644 index fc568af..0000000 --- a/arch/um/kernel/initrd_kern.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include "linux/init.h" -#include "linux/bootmem.h" -#include "linux/initrd.h" -#include "asm/types.h" -#include "user_util.h" -#include "kern_util.h" -#include "initrd.h" -#include "init.h" -#include "os.h" - -/* Changed by uml_initrd_setup, which is a setup */ -static char *initrd __initdata = NULL; - -static int __init read_initrd(void) -{ - void *area; - long long size; - int err; - - if(initrd == NULL) return 0; - err = os_file_size(initrd, &size); - if(err) return 0; - area = alloc_bootmem(size); - if(area == NULL) return 0; - if(load_initrd(initrd, area, size) == -1) return 0; - initrd_start = (unsigned long) area; - initrd_end = initrd_start + size; - return 0; -} - -__uml_postsetup(read_initrd); - -static int __init uml_initrd_setup(char *line, int *add) -{ - initrd = line; - return 0; -} - -__uml_setup("initrd=", uml_initrd_setup, -"initrd=\n" -" This is used to boot UML from an initrd image. The argument is the\n" -" name of the file containing the image.\n\n" -); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c deleted file mode 100644 index cb90681..0000000 --- a/arch/um/kernel/initrd_user.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include - -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "initrd.h" -#include "os.h" - -int load_initrd(char *filename, void *buf, int size) -{ - int fd, n; - - fd = os_open_file(filename, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Opening '%s' failed - err = %d\n", filename, -fd); - return(-1); - } - n = os_read_file(fd, buf, size); - if(n != size){ - printk("Read of %d bytes from '%s' failed, err = %d\n", size, - filename, -n); - return(-1); - } - - os_close_file(fd); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index ccb6dd6..804c6bb 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -54,18 +54,6 @@ */ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; -struct task_struct *get_task(int pid, int require) -{ - struct task_struct *ret; - - read_lock(&tasklist_lock); - ret = find_task_by_pid(pid); - read_unlock(&tasklist_lock); - - if(require && (ret == NULL)) panic("get_task couldn't find a task\n"); - return(ret); -} - int external_pid(void *t) { struct task_struct *task = t ? t : current; @@ -210,11 +198,6 @@ int page_size(void) return(PAGE_SIZE); } -unsigned long page_mask(void) -{ - return(PAGE_MASK); -} - void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out) { @@ -347,11 +330,6 @@ char *uml_strdup(char *string) return(new); } -void *get_init_task(void) -{ - return(&init_thread_union.thread_info.task); -} - int copy_to_user_proc(void __user *to, void *from, int size) { return(copy_to_user(to, from, size)); @@ -478,15 +456,3 @@ unsigned long arch_align_stack(unsigned long sp) return sp & ~0xf; } #endif - - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v1.1 From 34a1a63e37ee8d60bdb842476d9337cdff5413d9 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:51:57 -0700 Subject: [PATCH] uml: add modversions support Actually, the real support was added by some earlier patches. Now we simply re-enable the config. option. I've actually tested it and it works well. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index d920bae..a7660cc 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -442,7 +442,7 @@ config OBSOLETE_MODPARM config MODVERSIONS bool "Module versioning support (EXPERIMENTAL)" - depends on MODULES && EXPERIMENTAL && !UML + depends on MODULES && EXPERIMENTAL help Usually, you have to use modules compiled with your kernel. Saying Y here makes it sometimes possible to use modules -- cgit v1.1 From 567b56508f7367e161d6d861ef214a900ab45ce9 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:51:58 -0700 Subject: [PATCH] uml: add MOD_LICENSE to random driver Add a MODULE_LICENSE("GPL") to the driver, remove some unused macros and add the GPL license (it's GPL-licensed anyway since it's a GPL-derivative, apart that Jeff Dike releases GPL software, in case anybody is wondering). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index d43e9fa..f9e2219 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -1,5 +1,10 @@ -/* Much of this ripped from hw_random.c */ - +/* Copyright (C) 2005 Jeff Dike */ +/* Much of this ripped from drivers/char/hw_random.c, see there for other + * copyright. + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ #include #include #include @@ -12,8 +17,6 @@ */ #define RNG_VERSION "1.0.0" #define RNG_MODULE_NAME "random" -#define RNG_DRIVER_NAME RNG_MODULE_NAME " virtual driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " #define RNG_MISCDEV_MINOR 183 /* official */ @@ -98,7 +101,7 @@ static int __init rng_init (void) err = misc_register (&rng_miscdev); if (err) { - printk (KERN_ERR PFX "misc device register failed\n"); + printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); goto err_out_cleanup_hw; } @@ -120,3 +123,6 @@ static void __exit rng_cleanup (void) module_init (rng_init); module_exit (rng_cleanup); + +MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL"); -- cgit v1.1 From 37fce857bec00d26d0e8251c909da2bd8736c949 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:51:59 -0700 Subject: [PATCH] uml: split CONFIG_FRAME_POINTER from DEBUG_INFO Until now, FRAME_POINTER was set = DEBUG_INFO for UML. Change it to be the default way, so that it can be enabled alone (for instance to get better backtraces on crashes). The call-trace dumper which uses the frame pointer is not yet in, I'm going to introduce it in a separate patch. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig.debug | 4 ---- lib/Kconfig.debug | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index b89989d..bd41e42 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -2,10 +2,6 @@ menu "Kernel hacking" source "lib/Kconfig.debug" -config FRAME_POINTER - bool - default y if DEBUG_INFO - config PT_PROXY bool "Enable ptrace proxy" depends on XTERM_CHAN && DEBUG_INFO && MODE_TT diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ac23847..0c42129 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -151,7 +151,8 @@ config DEBUG_FS config FRAME_POINTER bool "Compile the kernel with frame pointers" - depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV) + depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML) + default y if DEBUG_INFO && UML help If you say Y here the resulting kernel image will be slightly larger and slower, but it will give very useful debugging information. -- cgit v1.1 From b3461034d7d46455060c8476910be22b6b0fc313 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:52:00 -0700 Subject: [PATCH] uml: stack dump fix Copy (and adapt) to UML the stack code dumper used in i386 when CONFIG_FRAME_POINTER is enabled. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sysrq.h | 3 +- arch/um/kernel/sysrq.c | 21 ++++++++---- arch/um/sys-i386/sysrq.c | 80 +++++++++++++++++++++++++++++++++++++++++++- arch/um/sys-ppc/sysrq.c | 14 +------- arch/um/sys-x86_64/sysrq.c | 11 +----- include/asm-um/thread_info.h | 7 ++-- 6 files changed, 100 insertions(+), 36 deletions(-) diff --git a/arch/um/include/sysrq.h b/arch/um/include/sysrq.h index 2ce9423..c8d332b 100644 --- a/arch/um/include/sysrq.h +++ b/arch/um/include/sysrq.h @@ -1,6 +1,7 @@ #ifndef __UM_SYSRQ_H #define __UM_SYSRQ_H -extern void show_trace(unsigned long *stack); +struct task_struct; +extern void show_trace(struct task_struct* task, unsigned long *stack); #endif diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index e630438..f808500 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -3,6 +3,7 @@ * Licensed under the GPL */ +#include "linux/config.h" #include "linux/sched.h" #include "linux/kernel.h" #include "linux/module.h" @@ -12,14 +13,14 @@ #include "sysrq.h" #include "user_util.h" -void show_trace(unsigned long * stack) +/* Catch non-i386 SUBARCH's. */ +#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) +void show_trace(struct task_struct *task, unsigned long * stack) { - /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from - * arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/ unsigned long addr; if (!stack) { - stack = (unsigned long*) &stack; + stack = (unsigned long*) &stack; WARN_ON(1); } @@ -35,6 +36,7 @@ void show_trace(unsigned long * stack) } printk("\n"); } +#endif /* * stack dumps generator - this is used by arch-independent code. @@ -44,7 +46,7 @@ void dump_stack(void) { unsigned long stack; - show_trace(&stack); + show_trace(current, &stack); } EXPORT_SYMBOL(dump_stack); @@ -59,7 +61,11 @@ void show_stack(struct task_struct *task, unsigned long *esp) int i; if (esp == NULL) { - if (task != current) { + if (task != current && task != NULL) { + /* XXX: Isn't this bogus? I.e. isn't this the + * *userspace* stack of this task? If not so, use this + * even when task == current (as in i386). + */ esp = (unsigned long *) KSTK_ESP(task); /* Which one? No actual difference - just coding style.*/ //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs); @@ -77,5 +83,6 @@ void show_stack(struct task_struct *task, unsigned long *esp) printk("%08lx ", *stack++); } - show_trace(esp); + printk("Call Trace: \n"); + show_trace(current, esp); } diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c index 281fc7b..e3706d1 100644 --- a/arch/um/sys-i386/sysrq.c +++ b/arch/um/sys-i386/sysrq.c @@ -3,12 +3,15 @@ * Licensed under the GPL */ +#include "linux/config.h" #include "linux/kernel.h" #include "linux/smp.h" #include "linux/sched.h" +#include "linux/kallsyms.h" #include "asm/ptrace.h" #include "sysrq.h" +/* This is declared by */ void show_regs(struct pt_regs *regs) { printk("\n"); @@ -31,5 +34,80 @@ void show_regs(struct pt_regs *regs) 0xffff & PT_REGS_DS(regs), 0xffff & PT_REGS_ES(regs)); - show_trace((unsigned long *) ®s); + show_trace(NULL, (unsigned long *) ®s); } + +/* Copied from i386. */ +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +{ + return p > (void *)tinfo && + p < (void *)tinfo + THREAD_SIZE - 3; +} + +/* Adapted from i386 (we also print the address we read from). */ +static inline unsigned long print_context_stack(struct thread_info *tinfo, + unsigned long *stack, unsigned long ebp) +{ + unsigned long addr; + +#ifdef CONFIG_FRAME_POINTER + while (valid_stack_ptr(tinfo, (void *)ebp)) { + addr = *(unsigned long *)(ebp + 4); + printk("%08lx: [<%08lx>]", ebp + 4, addr); + print_symbol(" %s", addr); + printk("\n"); + ebp = *(unsigned long *)ebp; + } +#else + while (valid_stack_ptr(tinfo, stack)) { + addr = *stack; + if (__kernel_text_address(addr)) { + printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); + print_symbol(" %s", addr); + printk("\n"); + } + stack++; + } +#endif + return ebp; +} + +void show_trace(struct task_struct* task, unsigned long * stack) +{ + unsigned long ebp; + struct thread_info *context; + + /* Turn this into BUG_ON if possible. */ + if (!stack) { + stack = (unsigned long*) &stack; + printk("show_trace: got NULL stack, implicit assumption task == current"); + WARN_ON(1); + } + + if (!task) + task = current; + + if (task != current) { + //ebp = (unsigned long) KSTK_EBP(task); + /* Which one? No actual difference - just coding style.*/ + ebp = (unsigned long) PT_REGS_EBP(&task->thread.regs); + } else { + asm ("movl %%ebp, %0" : "=r" (ebp) : ); + } + + context = (struct thread_info *) + ((unsigned long)stack & (~(THREAD_SIZE - 1))); + print_context_stack(context, stack, ebp); + + /*while (((long) stack & (THREAD_SIZE-1)) != 0) { + addr = *stack; + if (__kernel_text_address(addr)) { + printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); + print_symbol(" %s", addr); + printk("\n"); + } + stack++; + }*/ + printk("\n"); +} + diff --git a/arch/um/sys-ppc/sysrq.c b/arch/um/sys-ppc/sysrq.c index 82d6e93..2f816f1 100644 --- a/arch/um/sys-ppc/sysrq.c +++ b/arch/um/sys-ppc/sysrq.c @@ -27,17 +27,5 @@ void show_regs(struct pt_regs_subarch *regs) 0xffff & regs->xds, 0xffff & regs->xes); #endif - show_trace(®s->gpr[1]); + show_trace(current, ®s->gpr[1]); } - - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c index ddf7469..d0a25af 100644 --- a/arch/um/sys-x86_64/sysrq.c +++ b/arch/um/sys-x86_64/sysrq.c @@ -36,14 +36,5 @@ void __show_regs(struct pt_regs * regs) void show_regs(struct pt_regs *regs) { __show_regs(regs); - show_trace((unsigned long *) ®s); + show_trace(current, (unsigned long *) ®s); } - -/* Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index a10ea15..e4f0198 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h @@ -41,18 +41,17 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) +#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; - unsigned long mask = PAGE_SIZE * - (1 << CONFIG_KERNEL_STACK_ORDER) - 1; - ti = (struct thread_info *) (((unsigned long) &ti) & ~mask); + unsigned long mask = THREAD_SIZE - 1; + ti = (struct thread_info *) (((unsigned long) &ti) & ~mask); return ti; } /* thread information allocation */ -#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) #define alloc_thread_info(tsk) \ ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL)) #define free_thread_info(ti) kfree(ti) -- cgit v1.1 From affac4bcbba617d7329b04c7882bc49a9826e12f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:52:00 -0700 Subject: [PATCH] uml: fix PREEMPT_ACTIVE This is a continuation for UML of: http://linux.bkbits.net:8080/linux-2.5/cset@41791ab52lfMuF2i3V-eTIGRBbDYKQ Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Paul Mackerras Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/thread_info.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index e4f0198..1feaaf1 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h @@ -61,7 +61,7 @@ static inline struct thread_info *current_thread_info(void) #endif -#define PREEMPT_ACTIVE 0x4000000 +#define PREEMPT_ACTIVE 0x10000000 #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ #define TIF_SIGPENDING 1 /* signal pending */ -- cgit v1.1 From 37053cc84d51a790a6e5c3987665902cdab122a5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 28 May 2005 15:52:01 -0700 Subject: [PATCH] sh: PREEMPT_ACTIVE fix Port Paulus's ppc64 fix to sh: When the generic IRQ stuff went in, it seems that HARDIRQ_BITS got bumped from 9 (for ppc64) up to 12. Consequently, the PREEMPT_ACTIVE bit is now within HARDIRQ_MASK, and I get in_interrupt() falsely returning true when PREEMPT_ACTIVE is set, and thus a BUG_ON tripping in arch/ppc64/mm/tlb.c. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-sh/thread_info.h | 2 +- include/asm-sh64/thread_info.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index d82f883..4bbbd9f 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h @@ -27,7 +27,7 @@ struct thread_info { #endif -#define PREEMPT_ACTIVE 0x4000000 +#define PREEMPT_ACTIVE 0x10000000 /* * macros/functions for gaining access to the thread information structure diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h index e65f394..8a32d6b 100644 --- a/include/asm-sh64/thread_info.h +++ b/include/asm-sh64/thread_info.h @@ -73,7 +73,7 @@ static inline struct thread_info *current_thread_info(void) #define THREAD_SIZE 8192 -#define PREEMPT_ACTIVE 0x4000000 +#define PREEMPT_ACTIVE 0x10000000 /* thread information flags */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -- cgit v1.1 From 8f28e8fa46625310102aea06fac61ba04c8b5b88 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:52:02 -0700 Subject: [PATCH] irq code: Add coherence test for PREEMPT_ACTIVE After porting this fixlet to UML: http://linux.bkbits.net:8080/linux-2.5/cset@41791ab52lfMuF2i3V-eTIGRBbDYKQ , I've also added a warning which should refuse compilation with insane values for PREEMPT_ACTIVE... maybe we should simply move PREEMPT_ACTIVE out of architectures using GENERIC_IRQS. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/hardirq.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index ebc712e..8336dba 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -43,13 +43,17 @@ #define __IRQ_MASK(x) ((1UL << (x))-1) #define PREEMPT_MASK (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT) -#define HARDIRQ_MASK (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) #define SOFTIRQ_MASK (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) +#define HARDIRQ_MASK (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) #define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT) #define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT) #define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) +#if PREEMPT_ACTIVE < (1 << (HARDIRQ_SHIFT + HARDIRQ_BITS)) +#error PREEMPT_ACTIVE is too low! +#endif + #define hardirq_count() (preempt_count() & HARDIRQ_MASK) #define softirq_count() (preempt_count() & SOFTIRQ_MASK) #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK)) -- cgit v1.1 From f767b02f35a3db5c1b1c6454992c070510cef07f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:52:03 -0700 Subject: [PATCH] uml: fixlet for arch_prctl_skas Fix it a bit (after some cross checking with "man arch_prctl"). There were: *) typos FS/GS and back *) FS in place of FS_BASE (and the same for GS) *) the procedure used put_user on &addr, where addr was the parameter (i.e. changed its param with put_user, completely useless) rather than interpreting addr as a pointer, as requested in this case (see the man page). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/sys-x86_64/syscalls.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index d4a5965..6f44f40 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -133,23 +133,27 @@ static long arch_prctl_tt(int code, unsigned long addr) #ifdef CONFIG_MODE_SKAS +/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */ static long arch_prctl_skas(int code, unsigned long addr) { long ret = 0; switch(code){ - case ARCH_SET_GS: - current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; - break; case ARCH_SET_FS: current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr; break; + case ARCH_SET_GS: + current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; + break; case ARCH_GET_FS: - ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr); + ret = put_user(current->thread.regs.regs.skas. + regs[FS_BASE / sizeof(unsigned long)], + (unsigned long __user *)addr); break; case ARCH_GET_GS: - ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \ -long)], &addr); + ret = put_user(current->thread.regs.regs.skas. + regs[GS_BASE / sizeof(unsigned long)], + (unsigned long __user *)addr); break; default: ret = -EINVAL; -- cgit v1.1 From 8e21683bb458c73c6fe87844202a64eac730995e Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 28 May 2005 15:52:04 -0700 Subject: [PATCH] uml: remove jail mode + other leftovers This var is currently useless, as it's apparent from reading the code. Until 2.6.11 it was used in some code related to jail mode, in the same proc.: if(jail){ while(!reading) sched_yield(); } jail mode has been dropped, together with that use, so let's finish dropping this. Also, remove some other useless definitions I met. Acked-by: Jeff Dike Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/tt/process_kern.c | 8 +------- arch/um/kernel/um_arch.c | 6 ------ include/asm-um/pgtable.h | 8 -------- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index df810ca..776310f 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -32,10 +32,6 @@ void *switch_to_tt(void *prev, void *next, void *last) unsigned long flags; int err, vtalrm, alrm, prof, cpu; char c; - /* jailing and SMP are incompatible, so this doesn't need to be - * made per-cpu - */ - static int reading; from = prev; to = next; @@ -59,13 +55,11 @@ void *switch_to_tt(void *prev, void *next, void *last) c = 0; set_current(to); - reading = 0; err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) panic("write of switch_pipe failed, err = %d", -err); - reading = 1; - if(from->thread.mode.tt.switch_pipe[0] == -1) + if(from->thread.mode.tt.switch_pipe[0] == -1) os_kill_process(os_getpid(), 0); err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 4d10ec3..4184271 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -111,12 +111,6 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; -pte_t * __bad_pagetable(void) -{ - panic("Someone should implement __bad_pagetable"); - return(NULL); -} - /* Set in linux_main */ unsigned long host_task_size; unsigned long task_size; diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h index 510e513..a880409 100644 --- a/include/asm-um/pgtable.h +++ b/include/asm-um/pgtable.h @@ -114,17 +114,9 @@ extern unsigned long end_iomem; extern unsigned long pg0[1024]; /* - * BAD_PAGETABLE is used when we need a bogus page-table, while - * BAD_PAGE is used for a bogus page. - * * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. */ -extern pte_t __bad_page(void); -extern pte_t * __bad_pagetable(void); - -#define BAD_PAGETABLE __bad_pagetable() -#define BAD_PAGE __bad_page() #define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) -- cgit v1.1 From 94b9f46d61904422c498bf4cf9a90cc14398d311 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:05 -0700 Subject: [PATCH] ppc32: Fix uImage make target to report success correctly The existing make rule when building a uImage would check to see if the image file existed to report 'is ready' or 'not made'. However make appeared to compute the file list before the rule was executed. Signed-off-by: Chris Clark Signed-off-by: Kumar Gala Signed-off-by: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/images/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile index f850fb0..c9ac5f5 100644 --- a/arch/ppc/boot/images/Makefile +++ b/arch/ppc/boot/images/Makefile @@ -22,7 +22,8 @@ targets += uImage $(obj)/uImage: $(obj)/vmlinux.gz $(Q)rm -f $@ $(call if_changed,uimage) - @echo ' Image: $@' $(if $(wildcard $@),'is ready','not made') + @echo -n ' Image: $@ ' + @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi # Files generated that shall be removed upon make clean clean-files := sImage vmapus vmlinux* miboot* zImage* uImage -- cgit v1.1 From 252fcaed48fc5473b3fc3cafbf977244b0cbf670 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:06 -0700 Subject: [PATCH] ppc32: Fix some minor issues related to FSL Book-E KGDB support Some debug registers needed to be initialized early on to allow proper support for KGDB. Additionally, we need to setup the ppc.md_early_serial_map function pointer on boards that have serial support for KGDB. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/head_fsl_booke.S | 15 ++++++++++++++- arch/ppc/platforms/85xx/mpc8540_ads.c | 3 +++ arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 3 +++ arch/ppc/platforms/85xx/sbc8560.c | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index f22ddce..ce36e88 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -232,7 +232,8 @@ skpinv: addi r6,r6,1 /* Increment */ tlbwe /* 7. Jump to KERNELBASE mapping */ - li r7,0 + lis r7,MSR_KERNEL@h + ori r7,r7,MSR_KERNEL@l bl 1f /* Find our address */ 1: mflr r9 rlwimi r6,r9,0,20,31 @@ -293,6 +294,18 @@ skpinv: addi r6,r6,1 /* Increment */ mtspr SPRN_HID0, r2 #endif +#if !defined(CONFIG_BDI_SWITCH) + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ + lis r2,DBCR0_IDM@h + mtspr SPRN_DBCR0,r2 + /* clear any residual debug events */ + li r2,-1 + mtspr SPRN_DBSR,r2 +#endif + /* * This is where the main kernel code starts. */ diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 4d857d6..583838a 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -210,6 +210,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) ppc_md.progress = gen550_progress; #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB) + ppc_md.early_serial_map = mpc85xx_early_serial_map; +#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */ if (ppc_md.progress) ppc_md.progress("mpc8540ads_init(): exit", 0); diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 6c020d6..11fb758 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -459,6 +459,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) ppc_md.progress = gen550_progress; #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB) + ppc_md.early_serial_map = mpc85xx_early_serial_map; +#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */ if (ppc_md.progress) ppc_md.progress("mpc85xx_cds_init(): exit", 0); diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 9ab05e5..7b9e154 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -221,6 +221,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) ppc_md.progress = gen550_progress; #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB) + ppc_md.early_serial_map = sbc8560_early_serial_map; +#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */ if (ppc_md.progress) ppc_md.progress("sbc8560_init(): exit", 0); -- cgit v1.1 From ed36959621451da7195be83b87878b060ce64724 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:07 -0700 Subject: [PATCH] ppc32: Add VIA IDE support to MPC8555 CDS platform Add support for the VIA IDE controller that exists on the MPC8555 CDS system. Updated the config for the system to enable support by default. Signed-off-by: Scott Hall Signed-off-by: Kumar Gala Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/configs/mpc8555_cds_defconfig | 117 ++++++++++++++++++----- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 138 ++++++++++++++++++++++++++- arch/ppc/platforms/85xx/mpc85xx_cds_common.h | 3 + arch/ppc/syslib/Makefile | 2 +- arch/ppc/syslib/ppc85xx_setup.c | 16 ++++ 5 files changed, 248 insertions(+), 28 deletions(-) diff --git a/arch/ppc/configs/mpc8555_cds_defconfig b/arch/ppc/configs/mpc8555_cds_defconfig index 728bd9e..15abebf 100644 --- a/arch/ppc/configs/mpc8555_cds_defconfig +++ b/arch/ppc/configs/mpc8555_cds_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-rc1 -# Thu Jan 20 01:25:35 2005 +# Linux kernel version: 2.6.12-rc4 +# Tue May 17 11:56:01 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y @@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # # Code maturity level options @@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup @@ -29,12 +31,14 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y # CONFIG_EPOLL is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -62,10 +67,12 @@ CONFIG_CC_ALIGN_JUMPS=0 CONFIG_E500=y CONFIG_BOOKE=y CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set CONFIG_SPE=y CONFIG_MATH_EMULATION=y # CONFIG_CPU_FREQ is not set CONFIG_PPC_GEN550=y +# CONFIG_PM is not set CONFIG_85xx=y CONFIG_PPC_INDIRECT_PCI_BE=y @@ -76,6 +83,7 @@ CONFIG_PPC_INDIRECT_PCI_BE=y CONFIG_MPC8555_CDS=y # CONFIG_MPC8560_ADS is not set # CONFIG_SBC8560 is not set +# CONFIG_STX_GP3 is not set CONFIG_MPC8555=y CONFIG_85xx_PCI2=y @@ -90,6 +98,7 @@ CONFIG_CPM2=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_CMDLINE_BOOL is not set +CONFIG_ISA_DMA_API=y # # Bus options @@ -105,10 +114,6 @@ CONFIG_PCI_NAMES=y # CONFIG_PCCARD is not set # -# PC-card bridges -# - -# # Advanced setup # # CONFIG_ADVANCED_OPTIONS is not set @@ -180,7 +185,59 @@ CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support # -# CONFIG_IDE is not set +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# 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_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -220,7 +277,6 @@ CONFIG_NET=y # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -370,14 +426,6 @@ CONFIG_INPUT=y # CONFIG_INPUT_EVBUG is not set # -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set - -# # Input Device Drivers # # CONFIG_INPUT_KEYBOARD is not set @@ -387,6 +435,13 @@ CONFIG_SOUND_GAMEPORT=y # CONFIG_INPUT_MISC is not set # +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y + +# # Character devices # # CONFIG_VT is not set @@ -406,6 +461,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_CPM is not set +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -434,6 +490,11 @@ CONFIG_GEN_RTC=y # CONFIG_RAW_DRIVER is not set # +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# # I2C support # CONFIG_I2C=y @@ -456,11 +517,11 @@ CONFIG_I2C_CHARDEV=y # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set CONFIG_I2C_MPC=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_SCx200_ACB is not set @@ -483,7 +544,9 @@ CONFIG_I2C_MPC=y # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set @@ -494,9 +557,11 @@ CONFIG_I2C_MPC=y # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set @@ -506,10 +571,12 @@ CONFIG_I2C_MPC=y # # Other I2C Chip support # +# CONFIG_SENSORS_DS1337 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -538,7 +605,6 @@ CONFIG_I2C_MPC=y # Graphics support # # CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -548,13 +614,9 @@ CONFIG_I2C_MPC=y # # USB support # -# CONFIG_USB is not set CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information -# +# CONFIG_USB is not set # # USB Gadget Support @@ -585,6 +647,10 @@ CONFIG_JBD=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set + +# +# XFS support +# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -646,7 +712,6 @@ CONFIG_NFS_FS=y # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -698,7 +763,9 @@ CONFIG_CRC32=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_KGDB_CONSOLE is not set # CONFIG_SERIAL_TEXT_DEBUG is not set diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 11fb758..c2a5127 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,7 @@ void __init mpc85xx_cds_init_IRQ(void) { bd_t *binfo = (bd_t *) __res; + int i; /* Determine the Physical Address of the OpenPIC regs */ phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; @@ -198,6 +200,13 @@ mpc85xx_cds_init_IRQ(void) */ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); + openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq); + + for (i = 0; i < NUM_8259_INTERRUPTS; i++) + irq_desc[i].handler = &i8259_pic; + + i8259_init(0); + #ifdef CONFIG_CPM2 /* Setup CPM2 PIC */ cpm2_init_IRQ(); @@ -231,7 +240,7 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) * interrupt on slot */ { { 0, 1, 2, 3 }, /* 16 - PMC */ - { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */ + { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */ { 0, 1, 2, 3 }, /* 18 - Slot 1 */ { 1, 2, 3, 0 }, /* 19 - Slot 2 */ { 2, 3, 0, 1 }, /* 20 - Slot 3 */ @@ -280,13 +289,135 @@ mpc85xx_exclude_device(u_char bus, u_char devfn) return PCIBIOS_DEVICE_NOT_FOUND; #endif /* We explicitly do not go past the Tundra 320 Bridge */ - if (bus == 1) + if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) return PCIBIOS_DEVICE_NOT_FOUND; if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) return PCIBIOS_DEVICE_NOT_FOUND; else return PCIBIOS_SUCCESSFUL; } + +void __init +mpc85xx_cds_enable_via(struct pci_controller *hose) +{ + u32 pci_class; + u16 vid, did; + + early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class); + if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI) + return; + + /* Configure P2P so that we can reach bus 1 */ + early_write_config_byte(hose, 0, 0x88, PCI_PRIMARY_BUS, 0); + early_write_config_byte(hose, 0, 0x88, PCI_SECONDARY_BUS, 1); + early_write_config_byte(hose, 0, 0x88, PCI_SUBORDINATE_BUS, 0xff); + + early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid); + early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did); + + if ((vid != PCI_VENDOR_ID_VIA) || + (did != PCI_DEVICE_ID_VIA_82C686)) + return; + + /* Enable USB and IDE functions */ + early_write_config_byte(hose, 1, 0x10, 0x48, 0x08); +} + +void __init +mpc85xx_cds_fixup_via(struct pci_controller *hose) +{ + u32 pci_class; + u16 vid, did; + + early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class); + if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI) + return; + + /* + * Force the backplane P2P bridge to have a window + * open from 0x00000000-0x00001fff in PCI I/O space. + * This allows legacy I/O (i8259, etc) on the VIA + * southbridge to be accessed. + */ + early_write_config_byte(hose, 0, 0x88, PCI_IO_BASE, 0x00); + early_write_config_word(hose, 0, 0x88, PCI_IO_BASE_UPPER16, 0x0000); + early_write_config_byte(hose, 0, 0x88, PCI_IO_LIMIT, 0x10); + early_write_config_word(hose, 0, 0x88, PCI_IO_LIMIT_UPPER16, 0x0000); + + early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid); + early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did); + if ((vid != PCI_VENDOR_ID_VIA) || + (did != PCI_DEVICE_ID_VIA_82C686)) + return; + + /* + * Since the P2P window was forced to cover the fixed + * legacy I/O addresses, it is necessary to manually + * place the base addresses for the IDE and USB functions + * within this window. + */ + /* Function 1, IDE */ + early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_0, 0x1ff8); + early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_1, 0x1ff4); + early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_2, 0x1fe8); + early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_3, 0x1fe4); + early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_4, 0x1fd0); + + /* Function 2, USB ports 0-1 */ + early_write_config_dword(hose, 1, 0x12, PCI_BASE_ADDRESS_4, 0x1fa0); + + /* Function 3, USB ports 2-3 */ + early_write_config_dword(hose, 1, 0x13, PCI_BASE_ADDRESS_4, 0x1f80); + + /* Function 5, Power Management */ + early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_0, 0x1e00); + early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_1, 0x1dfc); + early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_2, 0x1df8); + + /* Function 6, AC97 Interface */ + early_write_config_dword(hose, 1, 0x16, PCI_BASE_ADDRESS_0, 0x1c00); +} + +void __init +mpc85xx_cds_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + u_char c; + + if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_1, NULL))) { + /* + * U-Boot does not set the enable bits + * for the IDE device. Force them on here. + */ + pci_read_config_byte(dev, 0x40, &c); + c |= 0x03; /* IDE: Chip Enable Bits */ + pci_write_config_byte(dev, 0x40, c); + + /* + * Since only primary interface works, force the + * IDE function to standard primary IDE interrupt + * w/ 8259 offset + */ + dev->irq = 14; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } + + /* + * Force legacy USB interrupt routing + */ + if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, NULL))) { + dev->irq = 10; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); + } + + if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev))) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + } +} #endif /* CONFIG_PCI */ TODC_ALLOC(); @@ -308,6 +439,9 @@ mpc85xx_cds_setup_arch(void) printk("mpc85xx_cds_setup_arch\n"); + /* VIA IDE configuration */ + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; + #ifdef CONFIG_CPM2 cpm2_reset(); #endif diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h index 7627d77..12b292c 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h @@ -77,4 +77,7 @@ #define MPC85XX_PCI2_IO_SIZE 0x01000000 +#define NR_8259_INTS 16 +#define CPM_IRQ_OFFSET NR_8259_INTS + #endif /* __MACH_MPC85XX_CDS_H__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index dd418ea..46cbb3e 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -97,7 +97,7 @@ obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_BOOKE) += dcr.o obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \ - ppc_sys.o mpc85xx_sys.o \ + ppc_sys.o i8259.o mpc85xx_sys.o \ mpc85xx_devices.o ifeq ($(CONFIG_85xx),y) obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index 152c3ef..f3277f4 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -132,6 +132,12 @@ mpc85xx_halt(void) } #ifdef CONFIG_PCI + +#if defined(CONFIG_MPC8555_CDS) +extern void mpc85xx_cds_enable_via(struct pci_controller *hose); +extern void mpc85xx_cds_fixup_via(struct pci_controller *hose); +#endif + static void __init mpc85xx_setup_pci1(struct pci_controller *hose) { @@ -302,8 +308,18 @@ mpc85xx_setup_hose(void) ppc_md.pci_exclude_device = mpc85xx_exclude_device; +#if defined(CONFIG_MPC8555_CDS) + /* Pre pciauto_bus_scan VIA init */ + mpc85xx_cds_enable_via(hose_a); +#endif + hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno); +#if defined(CONFIG_MPC8555_CDS) + /* Post pciauto_bus_scan VIA fixup */ + mpc85xx_cds_fixup_via(hose_a); +#endif + #ifdef CONFIG_85xx_PCI2 hose_b = pcibios_alloc_controller(); -- cgit v1.1 From a6dbba77a9d4b47c60d60c4f07fa79b3ca93a1d5 Mon Sep 17 00:00:00 2001 From: Vitaly Bordug Date: Sat, 28 May 2005 15:52:09 -0700 Subject: [PATCH] ppc32: Support for 82xx PQII on-chip PCI bridge This patch adds on-chip PCI bridge support for the PQ2 family. The incomplete existent code is updated with interrupt handling stuff and board-specific bits for 8272ADS and PQ2FADS; the related files were renamed (from m8260_pci to m82xx_pci) to be of more generic fashion. This is tested with 8266ADS and 8272ADS, should work on PQ2FADS as well. Signed-off-by: Vitaly Bordug Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/Kconfig | 4 +- arch/ppc/platforms/pq2ads.h | 41 ++-- arch/ppc/syslib/Makefile | 2 +- arch/ppc/syslib/m8260_pci.c | 193 ------------------ arch/ppc/syslib/m8260_pci.h | 76 ------- arch/ppc/syslib/m8260_pci_erratum9.c | 10 +- arch/ppc/syslib/m8260_setup.c | 11 +- arch/ppc/syslib/m82xx_pci.c | 383 +++++++++++++++++++++++++++++++++++ arch/ppc/syslib/m82xx_pci.h | 92 +++++++++ include/asm-ppc/cpm2.h | 46 +++++ include/asm-ppc/m8260_pci.h | 1 + include/asm-ppc/mpc8260.h | 2 +- 12 files changed, 558 insertions(+), 303 deletions(-) delete mode 100644 arch/ppc/syslib/m8260_pci.c delete mode 100644 arch/ppc/syslib/m8260_pci.h create mode 100644 arch/ppc/syslib/m82xx_pci.c create mode 100644 arch/ppc/syslib/m82xx_pci.h diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 600f23d..6e6377a 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1143,12 +1143,12 @@ config PCI_QSPAN config PCI_8260 bool - depends on PCI && 8260 && !8272 + depends on PCI && 8260 default y config 8260_PCI9 bool " Enable workaround for MPC826x erratum PCI 9" - depends on PCI_8260 + depends on PCI_8260 && !ADS8272 default y choice diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h index cf5e5dd..067d9a5 100644 --- a/arch/ppc/platforms/pq2ads.h +++ b/arch/ppc/platforms/pq2ads.h @@ -49,10 +49,10 @@ /* PCI interrupt controller */ #define PCI_INT_STAT_REG 0xF8200000 #define PCI_INT_MASK_REG 0xF8200004 -#define PIRQA (NR_SIU_INTS + 0) -#define PIRQB (NR_SIU_INTS + 1) -#define PIRQC (NR_SIU_INTS + 2) -#define PIRQD (NR_SIU_INTS + 3) +#define PIRQA (NR_CPM_INTS + 0) +#define PIRQB (NR_CPM_INTS + 1) +#define PIRQC (NR_CPM_INTS + 2) +#define PIRQD (NR_CPM_INTS + 3) /* * PCI memory map definitions for MPC8266ADS-PCI. @@ -68,28 +68,23 @@ * 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory */ -/* window for a PCI master to access MPC8266 memory */ -#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */ -#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */ +/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h + Here we should redefine what is unique for this board */ +#define M82xx_PCI_SLAVE_MEM_LOCAL 0x00000000 /* Local base */ +#define M82xx_PCI_SLAVE_MEM_BUS 0x00000000 /* PCI base */ +#define M82xx_PCI_SLAVE_MEM_SIZE 0x10000000 /* 256 Mb */ -/* window for the processor to access PCI memory with prefetching */ -#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */ -#define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */ -#define PCI_MSTR_MEM_SIZE 0x20000000 /* 512MB */ +#define M82xx_PCI_SLAVE_SEC_WND_SIZE ~(0x40000000 - 1U) /* 2 x 512Mb */ +#define M82xx_PCI_SLAVE_SEC_WND_BASE 0x80000000 /* PCI Memory base */ -/* window for the processor to access PCI memory without prefetching */ -#define PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */ -#define PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */ -#define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */ +#if defined(CONFIG_ADS8272) +#define PCI_INT_TO_SIU SIU_INT_IRQ2 +#elif defined(CONFIG_PQ2FADS) +#define PCI_INT_TO_SIU SIU_INT_IRQ6 +#else +#warning PCI Bridge will be without interrupts support +#endif -/* window for the processor to access PCI I/O */ -#define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */ -#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */ -#define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */ - -#define _IO_BASE PCI_MSTR_IO_LOCAL -#define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL -#define PCI_DRAM_OFFSET PCI_SLV_MEM_BUS #endif /* CONFIG_PCI */ #endif /* __MACH_ADS8260_DEFS */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 46cbb3e..96acf85 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -81,7 +81,7 @@ obj-$(CONFIG_SBC82xx) += todc_time.o obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \ todc_time.o obj-$(CONFIG_8260) += m8260_setup.o -obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o +obj-$(CONFIG_PCI_8260) += m82xx_pci.o indirect_pci.o pci_auto.o obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o ifeq ($(CONFIG_PPC_GEN550),y) diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c deleted file mode 100644 index 057cc3f..0000000 --- a/arch/ppc/syslib/m8260_pci.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2004 Red Hat, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "m8260_pci.h" - - -/* PCI bus configuration registers. - */ - -static void __init m8260_setup_pci(struct pci_controller *hose) -{ - volatile cpm2_map_t *immap = cpm2_immr; - unsigned long pocmr; - u16 tempShort; - -#ifndef CONFIG_ATC /* already done in U-Boot */ - /* - * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]), - * and local bus for PCI (SIUMCR [LBPC]). - */ - immap->im_siu_conf.siu_82xx.sc_siumcr = 0x00640000; -#endif - - /* Make PCI lowest priority */ - /* Each 4 bits is a device bus request and the MS 4bits - is highest priority */ - /* Bus 4bit value - --- ---------- - CPM high 0b0000 - CPM middle 0b0001 - CPM low 0b0010 - PCI reguest 0b0011 - Reserved 0b0100 - Reserved 0b0101 - Internal Core 0b0110 - External Master 1 0b0111 - External Master 2 0b1000 - External Master 3 0b1001 - The rest are reserved */ - immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893; - - /* Park bus on core while modifying PCI Bus accesses */ - immap->im_siu_conf.siu_82xx.sc_ppc_acr = 0x6; - - /* - * Set up master window that allows the CPU to access PCI space. This - * window is set up using the first SIU PCIBR registers. - */ - immap->im_memctl.memc_pcimsk0 = MPC826x_PCI_MASK; - immap->im_memctl.memc_pcibr0 = MPC826x_PCI_BASE | PCIBR_ENABLE; - - /* Disable machine check on no response or target abort */ - immap->im_pci.pci_emr = cpu_to_le32(0x1fe7); - /* Release PCI RST (by default the PCI RST signal is held low) */ - immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN); - - /* give it some time */ - mdelay(1); - - /* - * Set up master window that allows the CPU to access PCI Memory (prefetch) - * space. This window is set up using the first set of Outbound ATU registers. - */ - immap->im_pci.pci_potar0 = cpu_to_le32(MPC826x_PCI_LOWER_MEM >> 12); - immap->im_pci.pci_pobar0 = cpu_to_le32((MPC826x_PCI_LOWER_MEM - MPC826x_PCI_MEM_OFFSET) >> 12); - pocmr = ((MPC826x_PCI_UPPER_MEM - MPC826x_PCI_LOWER_MEM) >> 12) ^ 0xfffff; - immap->im_pci.pci_pocmr0 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PREFETCH_EN); - - /* - * Set up master window that allows the CPU to access PCI Memory (non-prefetch) - * space. This window is set up using the second set of Outbound ATU registers. - */ - immap->im_pci.pci_potar1 = cpu_to_le32(MPC826x_PCI_LOWER_MMIO >> 12); - immap->im_pci.pci_pobar1 = cpu_to_le32((MPC826x_PCI_LOWER_MMIO - MPC826x_PCI_MMIO_OFFSET) >> 12); - pocmr = ((MPC826x_PCI_UPPER_MMIO - MPC826x_PCI_LOWER_MMIO) >> 12) ^ 0xfffff; - immap->im_pci.pci_pocmr1 = cpu_to_le32(pocmr | POCMR_ENABLE); - - /* - * Set up master window that allows the CPU to access PCI IO space. This window - * is set up using the third set of Outbound ATU registers. - */ - immap->im_pci.pci_potar2 = cpu_to_le32(MPC826x_PCI_IO_BASE >> 12); - immap->im_pci.pci_pobar2 = cpu_to_le32(MPC826x_PCI_LOWER_IO >> 12); - pocmr = ((MPC826x_PCI_UPPER_IO - MPC826x_PCI_LOWER_IO) >> 12) ^ 0xfffff; - immap->im_pci.pci_pocmr2 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PCI_IO); - - /* - * Set up slave window that allows PCI masters to access MPC826x local memory. - * This window is set up using the first set of Inbound ATU registers - */ - - immap->im_pci.pci_pitar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_LOCAL >> 12); - immap->im_pci.pci_pibar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_BUS >> 12); - pocmr = ((MPC826x_PCI_SLAVE_MEM_SIZE-1) >> 12) ^ 0xfffff; - immap->im_pci.pci_picmr0 = cpu_to_le32(pocmr | PICMR_ENABLE | PICMR_PREFETCH_EN); - - /* See above for description - puts PCI request as highest priority */ - immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567; - - /* Park the bus on the PCI */ - immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI; - - /* Host mode - specify the bridge as a host-PCI bridge */ - early_write_config_word(hose, 0, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST); - - /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */ - early_read_config_word(hose, 0, 0, PCI_COMMAND, &tempShort); - early_write_config_word(hose, 0, 0, PCI_COMMAND, - tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); -} - -void __init m8260_find_bridges(void) -{ - extern int pci_assign_all_busses; - struct pci_controller * hose; - - pci_assign_all_busses = 1; - - hose = pcibios_alloc_controller(); - - if (!hose) - return; - - ppc_md.pci_swizzle = common_swizzle; - - hose->first_busno = 0; - hose->bus_offset = 0; - hose->last_busno = 0xff; - - setup_m8260_indirect_pci(hose, - (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr, - (unsigned long)&cpm2_immr->im_pci.pci_cfg_data); - - m8260_setup_pci(hose); - hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET; - - hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE, - MPC826x_PCI_IO_SIZE); - isa_io_base = (unsigned long) hose->io_base_virt; - - /* setup resources */ - pci_init_resource(&hose->mem_resources[0], - MPC826x_PCI_LOWER_MEM, - MPC826x_PCI_UPPER_MEM, - IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory"); - - pci_init_resource(&hose->mem_resources[1], - MPC826x_PCI_LOWER_MMIO, - MPC826x_PCI_UPPER_MMIO, - IORESOURCE_MEM, "PCI memory"); - - pci_init_resource(&hose->io_resource, - MPC826x_PCI_LOWER_IO, - MPC826x_PCI_UPPER_IO, - IORESOURCE_IO, "PCI I/O"); -} diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h deleted file mode 100644 index d1352120..0000000 --- a/arch/ppc/syslib/m8260_pci.h +++ /dev/null @@ -1,76 +0,0 @@ - -#ifndef _PPC_KERNEL_M8260_PCI_H -#define _PPC_KERNEL_M8260_PCI_H - -#include - -/* - * Local->PCI map (from CPU) controlled by - * MPC826x master window - * - * 0x80000000 - 0xBFFFFFFF Total CPU2PCI space PCIBR0 - * - * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1) - * 0xA0000000 - 0xAFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2) - * 0xB0000000 - 0xB0FFFFFF 32-bit PCI IO (Outbound ATU #3) - * - * PCI->Local map (from PCI) - * MPC826x slave window controlled by - * - * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1) - */ - -/* - * Slave window that allows PCI masters to access MPC826x local memory. - * This window is set up using the first set of Inbound ATU registers - */ - -#ifndef MPC826x_PCI_SLAVE_MEM_LOCAL -#define MPC826x_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart) -#define MPC826x_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart) -#define MPC826x_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize) -#endif - -/* - * This is the window that allows the CPU to access PCI address space. - * It will be setup with the SIU PCIBR0 register. All three PCI master - * windows, which allow the CPU to access PCI prefetch, non prefetch, - * and IO space (see below), must all fit within this window. - */ -#ifndef MPC826x_PCI_BASE -#define MPC826x_PCI_BASE 0x80000000 -#define MPC826x_PCI_MASK 0xc0000000 -#endif - -#ifndef MPC826x_PCI_LOWER_MEM -#define MPC826x_PCI_LOWER_MEM 0x80000000 -#define MPC826x_PCI_UPPER_MEM 0x9fffffff -#define MPC826x_PCI_MEM_OFFSET 0x00000000 -#endif - -#ifndef MPC826x_PCI_LOWER_MMIO -#define MPC826x_PCI_LOWER_MMIO 0xa0000000 -#define MPC826x_PCI_UPPER_MMIO 0xafffffff -#define MPC826x_PCI_MMIO_OFFSET 0x00000000 -#endif - -#ifndef MPC826x_PCI_LOWER_IO -#define MPC826x_PCI_LOWER_IO 0x00000000 -#define MPC826x_PCI_UPPER_IO 0x00ffffff -#define MPC826x_PCI_IO_BASE 0xb0000000 -#define MPC826x_PCI_IO_SIZE 0x01000000 -#endif - -#ifndef _IO_BASE -#define _IO_BASE isa_io_base -#endif - -#ifdef CONFIG_8260_PCI9 -struct pci_controller; -extern void setup_m8260_indirect_pci(struct pci_controller* hose, - u32 cfg_addr, u32 cfg_data); -#else -#define setup_m8260_indirect_pci setup_indirect_pci -#endif - -#endif /* _PPC_KERNEL_M8260_PCI_H */ diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c index 9c0582d..1dc7e4e 100644 --- a/arch/ppc/syslib/m8260_pci_erratum9.c +++ b/arch/ppc/syslib/m8260_pci_erratum9.c @@ -31,7 +31,7 @@ #include #include -#include "m8260_pci.h" +#include "m82xx_pci.h" #ifdef CONFIG_8260_PCI9 /*#include */ /* included in asm/io.h */ @@ -248,11 +248,11 @@ EXPORT_SYMBOL(idma_pci9_read_le); static inline int is_pci_mem(unsigned long addr) { - if (addr >= MPC826x_PCI_LOWER_MMIO && - addr <= MPC826x_PCI_UPPER_MMIO) + if (addr >= M82xx_PCI_LOWER_MMIO && + addr <= M82xx_PCI_UPPER_MMIO) return 1; - if (addr >= MPC826x_PCI_LOWER_MEM && - addr <= MPC826x_PCI_UPPER_MEM) + if (addr >= M82xx_PCI_LOWER_MEM && + addr <= M82xx_PCI_UPPER_MEM) return 1; return 0; } diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c index 23ea3f6..fda75d7 100644 --- a/arch/ppc/syslib/m8260_setup.c +++ b/arch/ppc/syslib/m8260_setup.c @@ -34,7 +34,8 @@ unsigned char __res[sizeof(bd_t)]; extern void cpm2_reset(void); -extern void m8260_find_bridges(void); +extern void pq2_find_bridges(void); +extern void pq2pci_init_irq(void); extern void idma_pci9_init(void); /* Place-holder for board-specific init */ @@ -56,7 +57,7 @@ m8260_setup_arch(void) idma_pci9_init(); #endif #ifdef CONFIG_PCI_8260 - m8260_find_bridges(); + pq2_find_bridges(); #endif #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) @@ -173,6 +174,12 @@ m8260_init_IRQ(void) * in case the boot rom changed something on us. */ cpm2_immr->im_intctl.ic_siprr = 0x05309770; + +#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS)) + /* Initialize stuff for the 82xx CPLD IC and install demux */ + pq2pci_init_irq(); +#endif + } /* diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c new file mode 100644 index 0000000..5e7a7ed --- /dev/null +++ b/arch/ppc/syslib/m82xx_pci.c @@ -0,0 +1,383 @@ +/* + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2004 Red Hat, Inc. + * + * 2005 (c) MontaVista Software, Inc. + * Vitaly Bordug + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m82xx_pci.h" + +/* + * Interrupt routing + */ + +static inline int +pq2pci_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { PIRQA, PIRQB, PIRQC, PIRQD }, /* IDSEL 22 - PCI slot 0 */ + { PIRQD, PIRQA, PIRQB, PIRQC }, /* IDSEL 23 - PCI slot 1 */ + { PIRQC, PIRQD, PIRQA, PIRQB }, /* IDSEL 24 - PCI slot 2 */ + }; + + const long min_idsel = 22, max_idsel = 24, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +static void +pq2pci_mask_irq(unsigned int irq) +{ + int bit = irq - NR_CPM_INTS; + + *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit)); + return; +} + +static void +pq2pci_unmask_irq(unsigned int irq) +{ + int bit = irq - NR_CPM_INTS; + + *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit)); + return; +} + +static void +pq2pci_mask_and_ack(unsigned int irq) +{ + int bit = irq - NR_CPM_INTS; + + *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit)); + return; +} + +static void +pq2pci_end_irq(unsigned int irq) +{ + int bit = irq - NR_CPM_INTS; + + *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit)); + return; +} + +struct hw_interrupt_type pq2pci_ic = { + "PQ2 PCI", + NULL, + NULL, + pq2pci_unmask_irq, + pq2pci_mask_irq, + pq2pci_mask_and_ack, + pq2pci_end_irq, + 0 +}; + +static irqreturn_t +pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long stat, mask, pend; + int bit; + + for(;;) { + stat = *(volatile unsigned long *) PCI_INT_STAT_REG; + mask = *(volatile unsigned long *) PCI_INT_MASK_REG; + pend = stat & ~mask & 0xf0000000; + if (!pend) + break; + for (bit = 0; pend != 0; ++bit, pend <<= 1) { + if (pend & 0x80000000) + __do_IRQ(NR_CPM_INTS + bit, regs); + } + } + + return IRQ_HANDLED; +} + +static struct irqaction pq2pci_irqaction = { + .handler = pq2pci_irq_demux, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "PQ2 PCI cascade", +}; + + +void +pq2pci_init_irq(void) +{ + int irq; + volatile cpm2_map_t *immap = cpm2_immr; +#if defined CONFIG_ADS8272 + /* configure chip select for PCI interrupt controller */ + immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801; + immap->im_memctl.memc_or3 = 0xffff8010; +#elif defined CONFIG_PQ2FADS + immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801; + immap->im_memctl.memc_or8 = 0xffff8010; +#endif + for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++) + irq_desc[irq].handler = &pq2pci_ic; + + /* make PCI IRQ level sensitive */ + immap->im_intctl.ic_siexr &= + ~(1 << (14 - (PCI_INT_TO_SIU - SIU_INT_IRQ1))); + + /* mask all PCI interrupts */ + *(volatile unsigned long *) PCI_INT_MASK_REG |= 0xfff00000; + + /* install the demultiplexer for the PCI cascade interrupt */ + setup_irq(PCI_INT_TO_SIU, &pq2pci_irqaction); + return; +} + +static int +pq2pci_exclude_device(u_char bus, u_char devfn) +{ + return PCIBIOS_SUCCESSFUL; +} + +/* PCI bus configuration registers. + */ +static void +pq2ads_setup_pci(struct pci_controller *hose) +{ + __u32 val; + volatile cpm2_map_t *immap = cpm2_immr; + bd_t* binfo = (bd_t*) __res; + u32 sccr = immap->im_clkrst.car_sccr; + uint pci_div,freq,time; + /* PCI int lowest prio */ + /* Each 4 bits is a device bus request and the MS 4bits + is highest priority */ + /* Bus 4bit value + --- ---------- + CPM high 0b0000 + CPM middle 0b0001 + CPM low 0b0010 + PCI reguest 0b0011 + Reserved 0b0100 + Reserved 0b0101 + Internal Core 0b0110 + External Master 1 0b0111 + External Master 2 0b1000 + External Master 3 0b1001 + The rest are reserved + */ + immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893; + /* park bus on core */ + immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_CORE; + /* + * Set up master windows that allow the CPU to access PCI space. These + * windows are set up using the two SIU PCIBR registers. + */ + + immap->im_memctl.memc_pcimsk0 = M82xx_PCI_PRIM_WND_SIZE; + immap->im_memctl.memc_pcibr0 = M82xx_PCI_PRIM_WND_BASE | PCIBR_ENABLE; + +#ifdef M82xx_PCI_SEC_WND_SIZE + immap->im_memctl.memc_pcimsk1 = M82xx_PCI_SEC_WND_SIZE; + immap->im_memctl.memc_pcibr1 = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE; +#endif + +#if defined CONFIG_ADS8272 + immap->im_siu_conf.siu_82xx.sc_siumcr = + (immap->im_siu_conf.siu_82xx.sc_siumcr & + ~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE | + SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 | + SIUMCR_LBPC11 | SIUMCR_APPC11 | + SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) | + SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 | + SIUMCR_APPC10 | SIUMCR_CS10PC00 | + SIUMCR_BCTLC00 | SIUMCR_MMR11 ; + +#elif defined CONFIG_PQ2FADS + /* + * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]), + * and local bus for PCI (SIUMCR [LBPC]). + */ + immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.sc_siumcr & + ~(SIUMCR_L2PC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) | + SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10; +#endif + /* Enable PCI */ + immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN); + + pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) * + ( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1); + freq = (uint)((2*binfo->bi_cpmfreq)/(pci_div)); + time = (int)666666/freq; + /* due to PCI Local Bus spec, some devices needs to wait such a long + time after RST deassertion. More specifically, 0.508s for 66MHz & twice more for 33 */ + printk("%s: The PCI bus is %d Mhz.\nWaiting %s after deasserting RST...\n",__FILE__,freq, + (time==1) ? "0.5 seconds":"1 second" ); + + { + int i; + for(i=0;i<(500*time);i++) + udelay(1000); + } + + /* setup ATU registers */ + immap->im_pci.pci_pocmr0 = cpu_to_le32(POCMR_ENABLE | POCMR_PCI_IO | + ((~(M82xx_PCI_IO_SIZE - 1U)) >> POTA_ADDR_SHIFT)); + immap->im_pci.pci_potar0 = cpu_to_le32(M82xx_PCI_LOWER_IO >> POTA_ADDR_SHIFT); + immap->im_pci.pci_pobar0 = cpu_to_le32(M82xx_PCI_IO_BASE >> POTA_ADDR_SHIFT); + + /* Set-up non-prefetchable window */ + immap->im_pci.pci_pocmr1 = cpu_to_le32(POCMR_ENABLE | ((~(M82xx_PCI_MMIO_SIZE-1U)) >> POTA_ADDR_SHIFT)); + immap->im_pci.pci_potar1 = cpu_to_le32(M82xx_PCI_LOWER_MMIO >> POTA_ADDR_SHIFT); + immap->im_pci.pci_pobar1 = cpu_to_le32((M82xx_PCI_LOWER_MMIO - M82xx_PCI_MMIO_OFFSET) >> POTA_ADDR_SHIFT); + + /* Set-up prefetchable window */ + immap->im_pci.pci_pocmr2 = cpu_to_le32(POCMR_ENABLE |POCMR_PREFETCH_EN | + (~(M82xx_PCI_MEM_SIZE-1U) >> POTA_ADDR_SHIFT)); + immap->im_pci.pci_potar2 = cpu_to_le32(M82xx_PCI_LOWER_MEM >> POTA_ADDR_SHIFT); + immap->im_pci.pci_pobar2 = cpu_to_le32((M82xx_PCI_LOWER_MEM - M82xx_PCI_MEM_OFFSET) >> POTA_ADDR_SHIFT); + + /* Inbound transactions from PCI memory space */ + immap->im_pci.pci_picmr0 = cpu_to_le32(PICMR_ENABLE | PICMR_PREFETCH_EN | + ((~(M82xx_PCI_SLAVE_MEM_SIZE-1U)) >> PITA_ADDR_SHIFT)); + immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS >> PITA_ADDR_SHIFT); + immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT); + +#if defined CONFIG_ADS8272 + /* PCI int highest prio */ + immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745; +#elif defined CONFIG_PQ2FADS + immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567; +#endif + /* park bus on PCI */ + immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI; + + /* Enable bus mastering and inbound memory transactions */ + early_read_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, &val); + val &= 0xffff0000; + val |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER; + early_write_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, val); + +} + +void __init pq2_find_bridges(void) +{ + extern int pci_assign_all_busses; + struct pci_controller * hose; + int host_bridge; + + pci_assign_all_busses = 1; + + hose = pcibios_alloc_controller(); + + if (!hose) + return; + + ppc_md.pci_swizzle = common_swizzle; + + hose->first_busno = 0; + hose->bus_offset = 0; + hose->last_busno = 0xff; + +#ifdef CONFIG_ADS8272 + hose->set_cfg_type = 1; +#endif + + setup_m8260_indirect_pci(hose, + (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr, + (unsigned long)&cpm2_immr->im_pci.pci_cfg_data); + + /* Make sure it is a supported bridge */ + early_read_config_dword(hose, + 0, + PCI_DEVFN(0,0), + PCI_VENDOR_ID, + &host_bridge); + switch (host_bridge) { + case PCI_DEVICE_ID_MPC8265: + break; + case PCI_DEVICE_ID_MPC8272: + break; + default: + printk("Attempting to use unrecognized host bridge ID" + " 0x%08x.\n", host_bridge); + break; + } + + pq2ads_setup_pci(hose); + + hose->io_space.start = M82xx_PCI_LOWER_IO; + hose->io_space.end = M82xx_PCI_UPPER_IO; + hose->mem_space.start = M82xx_PCI_LOWER_MEM; + hose->mem_space.end = M82xx_PCI_UPPER_MMIO; + hose->pci_mem_offset = M82xx_PCI_MEM_OFFSET; + + isa_io_base = + (unsigned long) ioremap(M82xx_PCI_IO_BASE, + M82xx_PCI_IO_SIZE); + hose->io_base_virt = (void *) isa_io_base; + + /* setup resources */ + pci_init_resource(&hose->mem_resources[0], + M82xx_PCI_LOWER_MEM, + M82xx_PCI_UPPER_MEM, + IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory"); + + pci_init_resource(&hose->mem_resources[1], + M82xx_PCI_LOWER_MMIO, + M82xx_PCI_UPPER_MMIO, + IORESOURCE_MEM, "PCI memory"); + + pci_init_resource(&hose->io_resource, + M82xx_PCI_LOWER_IO, + M82xx_PCI_UPPER_IO, + IORESOURCE_IO | 1, "PCI I/O"); + + ppc_md.pci_exclude_device = pq2pci_exclude_device; + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + + ppc_md.pci_map_irq = pq2pci_map_irq; + ppc_md.pcibios_fixup = NULL; + ppc_md.pcibios_fixup_bus = NULL; + +} diff --git a/arch/ppc/syslib/m82xx_pci.h b/arch/ppc/syslib/m82xx_pci.h new file mode 100644 index 0000000..924f73f --- /dev/null +++ b/arch/ppc/syslib/m82xx_pci.h @@ -0,0 +1,92 @@ + +#ifndef _PPC_KERNEL_M82XX_PCI_H +#define _PPC_KERNEL_M82XX_PCI_H + +#include +/* + * Local->PCI map (from CPU) controlled by + * MPC826x master window + * + * 0xF6000000 - 0xF7FFFFFF IO space + * 0x80000000 - 0xBFFFFFFF CPU2PCI memory space PCIBR0 + * + * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1) + * 0xA0000000 - 0xBFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2) + * 0xF6000000 - 0xF7FFFFFF 32-bit PCI IO (Outbound ATU #3) + * + * PCI->Local map (from PCI) + * MPC826x slave window controlled by + * + * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1) + */ + +/* + * Slave window that allows PCI masters to access MPC826x local memory. + * This window is set up using the first set of Inbound ATU registers + */ + +#ifndef M82xx_PCI_SLAVE_MEM_LOCAL +#define M82xx_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart) +#define M82xx_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart) +#define M82xx_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize) +#endif + +/* + * This is the window that allows the CPU to access PCI address space. + * It will be setup with the SIU PCIBR0 register. All three PCI master + * windows, which allow the CPU to access PCI prefetch, non prefetch, + * and IO space (see below), must all fit within this window. + */ + +#ifndef M82xx_PCI_LOWER_MEM +#define M82xx_PCI_LOWER_MEM 0x80000000 +#define M82xx_PCI_UPPER_MEM 0x9fffffff +#define M82xx_PCI_MEM_OFFSET 0x00000000 +#define M82xx_PCI_MEM_SIZE 0x20000000 +#endif + +#ifndef M82xx_PCI_LOWER_MMIO +#define M82xx_PCI_LOWER_MMIO 0xa0000000 +#define M82xx_PCI_UPPER_MMIO 0xafffffff +#define M82xx_PCI_MMIO_OFFSET 0x00000000 +#define M82xx_PCI_MMIO_SIZE 0x20000000 +#endif + +#ifndef M82xx_PCI_LOWER_IO +#define M82xx_PCI_LOWER_IO 0x00000000 +#define M82xx_PCI_UPPER_IO 0x01ffffff +#define M82xx_PCI_IO_BASE 0xf6000000 +#define M82xx_PCI_IO_SIZE 0x02000000 +#endif + +#ifndef M82xx_PCI_PRIM_WND_SIZE +#define M82xx_PCI_PRIM_WND_SIZE ~(M82xx_PCI_IO_SIZE - 1U) +#define M82xx_PCI_PRIM_WND_BASE (M82xx_PCI_IO_BASE) +#endif + +#ifndef M82xx_PCI_SEC_WND_SIZE +#define M82xx_PCI_SEC_WND_SIZE ~(M82xx_PCI_MEM_SIZE + M82xx_PCI_MMIO_SIZE - 1U) +#define M82xx_PCI_SEC_WND_BASE (M82xx_PCI_LOWER_MEM) +#endif + +#ifndef POTA_ADDR_SHIFT +#define POTA_ADDR_SHIFT 12 +#endif + +#ifndef PITA_ADDR_SHIFT +#define PITA_ADDR_SHIFT 12 +#endif + +#ifndef _IO_BASE +#define _IO_BASE isa_io_base +#endif + +#ifdef CONFIG_8260_PCI9 +struct pci_controller; +extern void setup_m8260_indirect_pci(struct pci_controller* hose, + u32 cfg_addr, u32 cfg_data); +#else +#define setup_m8260_indirect_pci setup_indirect_pci +#endif + +#endif /* _PPC_KERNEL_M8260_PCI_H */ diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h index 42fd106..c5883db 100644 --- a/include/asm-ppc/cpm2.h +++ b/include/asm-ppc/cpm2.h @@ -1039,6 +1039,52 @@ typedef struct im_idma { #define CMXSCR_TS4CS_CLK7 0x00000006 /* SCC4 Tx Clock Source is CLK7 */ #define CMXSCR_TS4CS_CLK8 0x00000007 /* SCC4 Tx Clock Source is CLK8 */ +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration Register 4-31 + */ +#define SIUMCR_BBD 0x80000000 /* Bus Busy Disable */ +#define SIUMCR_ESE 0x40000000 /* External Snoop Enable */ +#define SIUMCR_PBSE 0x20000000 /* Parity Byte Select Enable */ +#define SIUMCR_CDIS 0x10000000 /* Core Disable */ +#define SIUMCR_DPPC00 0x00000000 /* Data Parity Pins Configuration*/ +#define SIUMCR_DPPC01 0x04000000 /* - " - */ +#define SIUMCR_DPPC10 0x08000000 /* - " - */ +#define SIUMCR_DPPC11 0x0c000000 /* - " - */ +#define SIUMCR_L2CPC00 0x00000000 /* L2 Cache Pins Configuration */ +#define SIUMCR_L2CPC01 0x01000000 /* - " - */ +#define SIUMCR_L2CPC10 0x02000000 /* - " - */ +#define SIUMCR_L2CPC11 0x03000000 /* - " - */ +#define SIUMCR_LBPC00 0x00000000 /* Local Bus Pins Configuration */ +#define SIUMCR_LBPC01 0x00400000 /* - " - */ +#define SIUMCR_LBPC10 0x00800000 /* - " - */ +#define SIUMCR_LBPC11 0x00c00000 /* - " - */ +#define SIUMCR_APPC00 0x00000000 /* Address Parity Pins Configuration*/ +#define SIUMCR_APPC01 0x00100000 /* - " - */ +#define SIUMCR_APPC10 0x00200000 /* - " - */ +#define SIUMCR_APPC11 0x00300000 /* - " - */ +#define SIUMCR_CS10PC00 0x00000000 /* CS10 Pin Configuration */ +#define SIUMCR_CS10PC01 0x00040000 /* - " - */ +#define SIUMCR_CS10PC10 0x00080000 /* - " - */ +#define SIUMCR_CS10PC11 0x000c0000 /* - " - */ +#define SIUMCR_BCTLC00 0x00000000 /* Buffer Control Configuration */ +#define SIUMCR_BCTLC01 0x00010000 /* - " - */ +#define SIUMCR_BCTLC10 0x00020000 /* - " - */ +#define SIUMCR_BCTLC11 0x00030000 /* - " - */ +#define SIUMCR_MMR00 0x00000000 /* Mask Masters Requests */ +#define SIUMCR_MMR01 0x00004000 /* - " - */ +#define SIUMCR_MMR10 0x00008000 /* - " - */ +#define SIUMCR_MMR11 0x0000c000 /* - " - */ +#define SIUMCR_LPBSE 0x00002000 /* LocalBus Parity Byte Select Enable*/ + +/*----------------------------------------------------------------------- + * SCCR - System Clock Control Register 9-8 +*/ +#define SCCR_PCI_MODE 0x00000100 /* PCI Mode */ +#define SCCR_PCI_MODCK 0x00000080 /* Value of PCI_MODCK pin */ +#define SCCR_PCIDF_MSK 0x00000078 /* PCI division factor */ +#define SCCR_PCIDF_SHIFT 3 + + #endif /* __CPM2__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/m8260_pci.h b/include/asm-ppc/m8260_pci.h index 163a6b9..bf9e05d 100644 --- a/include/asm-ppc/m8260_pci.h +++ b/include/asm-ppc/m8260_pci.h @@ -19,6 +19,7 @@ * Define the vendor/device ID for the MPC8265. */ #define PCI_DEVICE_ID_MPC8265 ((0x18C0 << 16) | PCI_VENDOR_ID_MOTOROLA) +#define PCI_DEVICE_ID_MPC8272 ((0x18C1 << 16) | PCI_VENDOR_ID_MOTOROLA) #define M8265_PCIBR0 0x101ac #define M8265_PCIBR1 0x101b0 diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h index d820894..89eb8a2 100644 --- a/include/asm-ppc/mpc8260.h +++ b/include/asm-ppc/mpc8260.h @@ -41,7 +41,7 @@ #endif #ifdef CONFIG_PCI_8260 -#include +#include #endif /* Make sure the memory translation stuff is there if PCI not used. -- cgit v1.1 From 91f9855a7afbb160ba1709bf342858732138abad Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:12 -0700 Subject: [PATCH] ppc32: Fix building MPC8555 CDS when CONFIG_PCI is disabled The patch that introduced support for the VIA chipset broke building if CONFIG_PCI is disabled. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index c2a5127..3ac0321 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -439,9 +439,6 @@ mpc85xx_cds_setup_arch(void) printk("mpc85xx_cds_setup_arch\n"); - /* VIA IDE configuration */ - ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; - #ifdef CONFIG_CPM2 cpm2_reset(); #endif @@ -462,6 +459,9 @@ mpc85xx_cds_setup_arch(void) loops_per_jiffy = freq / HZ; #ifdef CONFIG_PCI + /* VIA IDE configuration */ + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; + /* setup PCI host bridges */ mpc85xx_setup_hose(); #endif -- cgit v1.1 From 92b4dc16257fef814ddf1c8d1d2a20f67f67ee4b Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:13 -0700 Subject: [PATCH] ppc32: Simplified load string emulation error checking The error checking for emulation of load string instructions was overly generous and would cause certain valid forms of the instructions to be treated as illegal. We drop the range checking since the architecture allows this to be boundedly undefined. Tests on CPUs that support these instructions appear not do cause illegal instruction traps on range errors and just allow the execution to occur. Thanks to Kim Phillips for debugging this and figuring out what real HW was doing. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/traps.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index f8e7e32..c65731e 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -408,12 +408,7 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) /* Early out if we are an invalid form of lswx */ if ((instword & INST_STRING_MASK) == INST_LSWX) - if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB)) - return -EINVAL; - - /* Early out if we are an invalid form of lswi */ - if ((instword & INST_STRING_MASK) == INST_LSWI) - if ((rA >= rT) || (rT == rA)) + if ((rT == rA) || (rT == NB_RB)) return -EINVAL; EA = (rA == 0) ? 0 : regs->gpr[rA]; -- cgit v1.1 From ff945023c6a455679165b14d298316e262ceeb1f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:14 -0700 Subject: [PATCH] ppc32: MPC834x BCSR_SIZE too small for use in a BAT. The call to io_block_mapping was creating an invalid BAT entry because the value of BCSR_SIZE (32K) is too small to be used in a BAT (128K min). This change removes the io_block_mapping call since these registers can easily be mapped using ioremap at the point of use. Signed-off-by: Randy Vinson Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/83xx/mpc834x_sys.c | 1 - arch/ppc/platforms/83xx/mpc834x_sys.h | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index b3b0f51..e6348b5 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -127,7 +127,6 @@ mpc834x_sys_map_io(void) { /* we steal the lowest ioremap addr for virt space */ io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO); - io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO); } int diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index f4d055a..49db0f4 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h @@ -26,7 +26,6 @@ #define VIRT_IMMRBAR ((uint)0xfe000000) #define BCSR_PHYS_ADDR ((uint)0xf8000000) -#define BCSR_VIRT_ADDR ((uint)0xfe100000) #define BCSR_SIZE ((uint)(32 * 1024)) #ifdef CONFIG_PCI -- cgit v1.1 From f9e4a005827ec0b33f0c61fec1634a5a3421decd Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:15 -0700 Subject: [PATCH] ppc32: Add soft reset to MPC834x This change allows mpc83xx_restart to issue a software reset. Signed-off-by: Randy Vinson Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/83xx/mpc834x_sys.h | 6 ++++++ arch/ppc/syslib/ppc83xx_setup.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index 49db0f4..a2f6e49 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h @@ -28,6 +28,12 @@ #define BCSR_PHYS_ADDR ((uint)0xf8000000) #define BCSR_SIZE ((uint)(32 * 1024)) +#define BCSR_MISC_REG2_OFF 0x07 +#define BCSR_MISC_REG2_PORESET 0x01 + +#define BCSR_MISC_REG3_OFF 0x08 +#define BCSR_MISC_REG3_CNFLOCK 0x80 + #ifdef CONFIG_PCI /* PCI interrupt controller */ #define PIRQA MPC83xx_IRQ_IRQ4 diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index c28f9d6..843cf88 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -117,7 +118,34 @@ mpc83xx_early_serial_map(void) void mpc83xx_restart(char *cmd) { + volatile unsigned char __iomem *reg; + unsigned char tmp; + + reg = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); + local_irq_disable(); + + /* + * Unlock the BCSR bits so a PRST will update the contents. + * Otherwise the reset asserts but doesn't clear. + */ + tmp = in_8(reg + BCSR_MISC_REG3_OFF); + tmp |= BCSR_MISC_REG3_CNFLOCK; /* low true, high false */ + out_8(reg + BCSR_MISC_REG3_OFF, tmp); + + /* + * Trigger a reset via a low->high transition of the + * PORESET bit. + */ + tmp = in_8(reg + BCSR_MISC_REG2_OFF); + tmp &= ~BCSR_MISC_REG2_PORESET; + out_8(reg + BCSR_MISC_REG2_OFF, tmp); + + udelay(1); + + tmp |= BCSR_MISC_REG2_PORESET; + out_8(reg + BCSR_MISC_REG2_OFF, tmp); + for(;;); } -- cgit v1.1 From 6cf2b3fc9934a56ceeb393ea5d0149e0bebc80fa Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 28 May 2005 15:52:15 -0700 Subject: [PATCH] ppc32: i8259 PIC should not be initialized if PCI is not configured Trying to initialize the i8259 PIC will not work if CONFIG_PCI is not enabled. The kernel hangs if the initialization is tried. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 3ac0321..e7cfa49 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -200,12 +200,14 @@ mpc85xx_cds_init_IRQ(void) */ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); +#ifdef CONFIG_PCI openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq); for (i = 0; i < NUM_8259_INTERRUPTS; i++) irq_desc[i].handler = &i8259_pic; i8259_init(0); +#endif #ifdef CONFIG_CPM2 /* Setup CPM2 PIC */ -- cgit v1.1 From 7d6064d44bc79e328f2794ee7322ba2676511e2b Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sun, 29 May 2005 01:27:44 -0500 Subject: Input: Fix fast scrolling scancodes in atkbd.c Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 79c332f..af0446c 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -171,9 +171,9 @@ static struct { unsigned char set2; } atkbd_scroll_keys[] = { { ATKBD_SCR_1, 0xc5 }, - { ATKBD_SCR_2, 0xa9 }, - { ATKBD_SCR_4, 0xb6 }, - { ATKBD_SCR_8, 0xa7 }, + { ATKBD_SCR_2, 0x9d }, + { ATKBD_SCR_4, 0xa4 }, + { ATKBD_SCR_8, 0x9b }, { ATKBD_SCR_CLICK, 0xe0 }, { ATKBD_SCR_LEFT, 0xcb }, { ATKBD_SCR_RIGHT, 0xd2 }, -- cgit v1.1 From 7238cfb3342078ad6d1dd06c7b567da428672476 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 29 May 2005 14:48:20 -0400 Subject: libata: bump version --- drivers/scsi/libata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 6518226..d90430b 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.10" /* must be exactly four chars */ +#define DRV_VERSION "1.11" /* must be exactly four chars */ struct ata_scsi_args { u16 *id; -- cgit v1.1 From d8a33ac435c43a1a404b2ec560ef1d1536710c36 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 May 2005 14:13:47 -0700 Subject: [BRIDGE]: features change notification Resend of earlier patch (no changes) from Catalin used to provide device feature change notification. Signed-off-by: Catalin BOIE Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + include/linux/notifier.h | 1 + net/core/dev.c | 12 ++++++++++++ net/core/ethtool.c | 8 +++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b25bd02..d8c65ec 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -913,6 +913,7 @@ extern void dev_mc_discard(struct net_device *dev); extern void dev_set_promiscuity(struct net_device *dev, int inc); extern void dev_set_allmulti(struct net_device *dev, int inc); extern void netdev_state_change(struct net_device *dev); +extern void netdev_features_change(struct net_device *dev); /* Load a device via the kmod */ extern void dev_load(const char *name); extern void dev_mcast_init(void); diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 9303a00..5937dd60 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -56,6 +56,7 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi #define NETDEV_CHANGEADDR 0x0008 #define NETDEV_GOING_DOWN 0x0009 #define NETDEV_CHANGENAME 0x000A +#define NETDEV_FEAT_CHANGE 0x000B #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN diff --git a/net/core/dev.c b/net/core/dev.c index d4d9e26..f15a3ff 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -761,6 +761,18 @@ int dev_change_name(struct net_device *dev, char *newname) } /** + * netdev_features_change - device changes fatures + * @dev: device to cause notification + * + * Called to indicate a device has changed features. + */ +void netdev_features_change(struct net_device *dev) +{ + notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); +} +EXPORT_SYMBOL(netdev_features_change); + +/** * netdev_state_change - device changes state * @dev: device to cause notification * diff --git a/net/core/ethtool.c b/net/core/ethtool.c index f05fde9..252bfc6 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -682,6 +682,7 @@ int dev_ethtool(struct ifreq *ifr) void __user *useraddr = ifr->ifr_data; u32 ethcmd; int rc; + int old_features; /* * XXX: This can be pushed down into the ethtool_* handlers that @@ -703,6 +704,8 @@ int dev_ethtool(struct ifreq *ifr) if ((rc = dev->ethtool_ops->begin(dev)) < 0) return rc; + old_features = dev->features; + switch (ethcmd) { case ETHTOOL_GSET: rc = ethtool_get_settings(dev, useraddr); @@ -712,7 +715,6 @@ int dev_ethtool(struct ifreq *ifr) break; case ETHTOOL_GDRVINFO: rc = ethtool_get_drvinfo(dev, useraddr); - break; case ETHTOOL_GREGS: rc = ethtool_get_regs(dev, useraddr); @@ -801,6 +803,10 @@ int dev_ethtool(struct ifreq *ifr) if(dev->ethtool_ops->complete) dev->ethtool_ops->complete(dev); + + if (old_features != dev->features) + netdev_features_change(dev); + return rc; ioctl: -- cgit v1.1 From 81e8157583c559c27aac75c708d40a35f563d734 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 May 2005 14:14:35 -0700 Subject: [BRIDGE]: make dev->features unsigned The features field in netdevice is really a bitmask, and bitmask's should be unsigned. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- net/core/ethtool.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d8c65ec..470af8c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -401,7 +401,7 @@ struct net_device } reg_state; /* Net device features */ - int features; + unsigned long features; #define NETIF_F_SG 1 /* Scatter/gather IO. */ #define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */ #define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */ diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 252bfc6..2a56a52 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -682,7 +682,7 @@ int dev_ethtool(struct ifreq *ifr) void __user *useraddr = ifr->ifr_data; u32 ethcmd; int rc; - int old_features; + unsigned long old_features; /* * XXX: This can be pushed down into the ethtool_* handlers that -- cgit v1.1 From 81d35307dd468b92fe8c58797abb13c62e3e64dd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 May 2005 14:15:17 -0700 Subject: [BRIDGE]: set features based on enslaved devices Make features of the bridge pseudo-device be a subset of the underlying devices. Motivated by Xen and others who use bridging to do failover. Signed-off-by: Catalin BOIE Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_device.c | 15 +++++++-------- net/bridge/br_if.c | 23 +++++++++++++++++++++++ net/bridge/br_notify.c | 9 +++++++++ net/bridge/br_private.h | 1 + 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index d9b72fd..f564ee9 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -21,10 +21,7 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev) { - struct net_bridge *br; - - br = dev->priv; - + struct net_bridge *br = netdev_priv(dev); return &br->statistics; } @@ -54,9 +51,11 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) static int br_dev_open(struct net_device *dev) { - netif_start_queue(dev); + struct net_bridge *br = netdev_priv(dev); - br_stp_enable_bridge(dev->priv); + br_features_recompute(br); + netif_start_queue(dev); + br_stp_enable_bridge(br); return 0; } @@ -67,7 +66,7 @@ static void br_dev_set_multicast_list(struct net_device *dev) static int br_dev_stop(struct net_device *dev) { - br_stp_disable_bridge(dev->priv); + br_stp_disable_bridge(netdev_priv(dev)); netif_stop_queue(dev); @@ -76,7 +75,7 @@ static int br_dev_stop(struct net_device *dev) static int br_change_mtu(struct net_device *dev, int new_mtu) { - if ((new_mtu < 68) || new_mtu > br_min_mtu(dev->priv)) + if (new_mtu < 68 || new_mtu > br_min_mtu(netdev_priv(dev))) return -EINVAL; dev->mtu = new_mtu; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 69872bf..91bb895 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -314,6 +314,28 @@ int br_min_mtu(const struct net_bridge *br) return mtu; } +/* + * Recomputes features using slave's features + */ +void br_features_recompute(struct net_bridge *br) +{ + struct net_bridge_port *p; + unsigned long features, checksum; + + features = NETIF_F_SG | NETIF_F_FRAGLIST + | NETIF_F_HIGHDMA | NETIF_F_TSO; + checksum = NETIF_F_IP_CSUM; /* least commmon subset */ + + list_for_each_entry(p, &br->port_list, list) { + if (!(p->dev->features + & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM))) + checksum = 0; + features &= p->dev->features; + } + + br->dev->features = features | checksum | NETIF_F_LLTX; +} + /* called with RTNL */ int br_add_if(struct net_bridge *br, struct net_device *dev) { @@ -368,6 +390,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); + br_features_recompute(br); spin_unlock_bh(&br->lock); return 0; diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index f8fb49e..917311c 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -65,6 +65,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v } break; + case NETDEV_FEAT_CHANGE: + if (br->dev->flags & IFF_UP) + br_features_recompute(br); + + /* could do recursive feature change notification + * but who would care?? + */ + break; + case NETDEV_DOWN: if (br->dev->flags & IFF_UP) br_stp_disable_port(p); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 54d63f13..bdf95a74 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -174,6 +174,7 @@ extern int br_add_if(struct net_bridge *br, extern int br_del_if(struct net_bridge *br, struct net_device *dev); extern int br_min_mtu(const struct net_bridge *br); +extern void br_features_recompute(struct net_bridge *br); /* br_input.c */ extern int br_handle_frame_finish(struct sk_buff *skb); -- cgit v1.1 From 85967bb46dd1f8f2c49b85a313866c00ac0c9b59 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 May 2005 14:15:55 -0700 Subject: [BRIDGE]: prevent bad forwarding table updates Avoid poisoning of the bridge forwarding table by frames that have been dropped by filtering. This prevents spoofed source addresses on hostile side of bridge from causing packet leakage, a small but possible security risk. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_input.c | 6 ++++-- net/bridge/br_stp_bpdu.c | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 2b1cce4..2aa5dda 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -54,6 +54,9 @@ int br_handle_frame_finish(struct sk_buff *skb) struct net_bridge_fdb_entry *dst; int passedup = 0; + /* insert into forwarding database after filtering to avoid spoofing */ + br_fdb_update(p->br, p, eth_hdr(skb)->h_source); + if (br->dev->flags & IFF_PROMISC) { struct sk_buff *skb2; @@ -108,8 +111,7 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) goto err; - if (p->state == BR_STATE_LEARNING || - p->state == BR_STATE_FORWARDING) + if (p->state == BR_STATE_LEARNING) br_fdb_update(p->br, p, eth_hdr(skb)->h_source); if (p->br->stp_enabled && diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index b91a875..d071f1c 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -140,6 +140,9 @@ int br_stp_handle_bpdu(struct sk_buff *skb) struct net_bridge *br = p->br; unsigned char *buf; + /* insert into forwarding database after filtering to avoid spoofing */ + br_fdb_update(p->br, p, eth_hdr(skb)->h_source); + /* need at least the 802 and STP headers */ if (!pskb_may_pull(skb, sizeof(header)+1) || memcmp(skb->data, header, sizeof(header))) -- cgit v1.1 From 7ce54e3f428b33af714271140601c87b8bf2c544 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 29 May 2005 14:16:48 -0700 Subject: [BRIDGE]: receive path optimization This improves the bridge local receive path by avoiding going through another softirq. The bridge receive path is already being called from a netif_receive_skb() there is no point in going through another receiveq round trip. Recursion is limited because bridge can never be a port of a bridge so handle_bridge() always returns. Signed-off-by: David S. Miller --- net/bridge/br_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 2aa5dda..8f5f2e7 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -26,7 +26,7 @@ static int br_pass_frame_up_finish(struct sk_buff *skb) #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 0; #endif - netif_rx(skb); + netif_receive_skb(skb); return 0; } -- cgit v1.1 From 4cafd3f533475c976879d85773735c004f09f576 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:56:34 -0700 Subject: [TG3]: Add basic selftest infrastructure Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f10dd74..088ed9f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -133,6 +133,8 @@ /* number of ETHTOOL_GSTATS u64's */ #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) +#define TG3_NUM_TEST 6 + static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -316,6 +318,17 @@ static struct { { "nic_tx_threshold_hit" } }; +static struct { + const char string[ETH_GSTRING_LEN]; +} ethtool_test_keys[TG3_NUM_TEST] = { + { "nvram test (online) " }, + { "link test (online) " }, + { "register test (offline)" }, + { "memory test (offline)" }, + { "loopback test (offline)" }, + { "interrupt test (offline)" }, +}; + static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) { if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { @@ -7199,12 +7212,20 @@ static int tg3_get_stats_count (struct net_device *dev) return TG3_NUM_STATS; } +static int tg3_get_test_count (struct net_device *dev) +{ + return TG3_NUM_TEST; +} + static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) { switch (stringset) { case ETH_SS_STATS: memcpy(buf, ðtool_stats_keys, sizeof(ethtool_stats_keys)); break; + case ETH_SS_TEST: + memcpy(buf, ðtool_test_keys, sizeof(ethtool_test_keys)); + break; default: WARN_ON(1); /* we need a WARN() */ break; @@ -7218,6 +7239,11 @@ static void tg3_get_ethtool_stats (struct net_device *dev, memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } +static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, + u64 *data) +{ +} + static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); @@ -7331,6 +7357,8 @@ static struct ethtool_ops tg3_ethtool_ops = { .get_tso = ethtool_op_get_tso, .set_tso = tg3_set_tso, #endif + .self_test_count = tg3_get_test_count, + .self_test = tg3_self_test, .get_strings = tg3_get_strings, .get_stats_count = tg3_get_stats_count, .get_ethtool_stats = tg3_get_ethtool_stats, -- cgit v1.1 From 566f86adb336637d03900f53b886d879aa5f5d56 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:56:58 -0700 Subject: [TG3]: Add nvram test Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 088ed9f..ab2fa21 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7239,9 +7239,59 @@ static void tg3_get_ethtool_stats (struct net_device *dev, memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } +#define NVRAM_TEST_SIZE 0x100 + +static int tg3_test_nvram(struct tg3 *tp) +{ + u32 *buf, csum; + int i, j, err = 0; + + buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) { + u32 val; + + if ((err = tg3_nvram_read(tp, i, &val)) != 0) + break; + buf[j] = cpu_to_le32(val); + } + if (i < NVRAM_TEST_SIZE) + goto out; + + err = -EIO; + if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) + goto out; + + /* Bootstrap checksum at offset 0x10 */ + csum = calc_crc((unsigned char *) buf, 0x10); + if(csum != cpu_to_le32(buf[0x10/4])) + goto out; + + /* Manufacturing block starts at offset 0x74, checksum at 0xfc */ + csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88); + if (csum != cpu_to_le32(buf[0xfc/4])) + goto out; + + err = 0; + +out: + kfree(buf); + return err; +} + static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *data) { + struct tg3 *tp = netdev_priv(dev); + + memset(data, 0, sizeof(u64) * TG3_NUM_TEST); + + if (tg3_test_nvram(tp) != 0) { + etest->flags |= ETH_TEST_FL_FAILED; + data[0] = 1; + } } static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -- cgit v1.1 From ca43007a92662621e5819912fc31c346e3a2eed8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:57:23 -0700 Subject: [TG3]: Add link test Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ab2fa21..30349c5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7281,6 +7281,32 @@ out: return err; } +#define TG3_SERDES_TIMEOUT_SEC 2 +#define TG3_COPPER_TIMEOUT_SEC 6 + +static int tg3_test_link(struct tg3 *tp) +{ + int i, max; + + if (!netif_running(tp->dev)) + return -ENODEV; + + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + max = TG3_SERDES_TIMEOUT_SEC; + else + max = TG3_COPPER_TIMEOUT_SEC; + + for (i = 0; i < max; i++) { + if (netif_carrier_ok(tp->dev)) + return 0; + + if (msleep_interruptible(1000)) + break; + } + + return -EIO; +} + static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *data) { @@ -7292,6 +7318,10 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, etest->flags |= ETH_TEST_FL_FAILED; data[0] = 1; } + if (tg3_test_link(tp) != 0) { + etest->flags |= ETH_TEST_FL_FAILED; + data[1] = 1; + } } static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -- cgit v1.1 From 944d980ecaabe44616a9e2d50101ce774f517bb6 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:57:48 -0700 Subject: [TG3]: Add parameter to tg3_halt Add a reset kind parameter to tg3_halt() so that the RESET_KIND_SUSPEND parameter can be passed to tg3_halt() before doing offline tests. All other calls to tg3_halt() will use the RESET_KIND_SHUTDOWN parameter. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 30349c5..73f6e96 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3083,7 +3083,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, } static int tg3_init_hw(struct tg3 *); -static int tg3_halt(struct tg3 *, int); +static int tg3_halt(struct tg3 *, int, int); #ifdef CONFIG_NET_POLL_CONTROLLER static void tg3_poll_controller(struct net_device *dev) @@ -3107,7 +3107,7 @@ static void tg3_reset_task(void *_data) restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; - tg3_halt(tp, 0); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); tg3_init_hw(tp); tg3_netif_start(tp); @@ -3453,7 +3453,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_set_mtu(dev, tp, new_mtu); @@ -4144,19 +4144,19 @@ static void tg3_stop_fw(struct tg3 *tp) } /* tp->lock is held. */ -static int tg3_halt(struct tg3 *tp, int silent) +static int tg3_halt(struct tg3 *tp, int kind, int silent) { int err; tg3_stop_fw(tp); - tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN); + tg3_write_sig_pre_reset(tp, kind); tg3_abort_hw(tp, silent); err = tg3_chip_reset(tp); - tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN); - tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + tg3_write_sig_legacy(tp, kind); + tg3_write_sig_post_reset(tp, kind); if (err) return err; @@ -5997,7 +5997,7 @@ static int tg3_test_msi(struct tg3 *tp) spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); err = tg3_init_hw(tp); spin_unlock(&tp->tx_lock); @@ -6073,7 +6073,7 @@ static int tg3_open(struct net_device *dev) err = tg3_init_hw(tp); if (err) { - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); } else { if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) @@ -6117,7 +6117,7 @@ static int tg3_open(struct net_device *dev) pci_disable_msi(tp->pdev); tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; } - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); tg3_free_consistent(tp); @@ -6390,7 +6390,7 @@ static int tg3_close(struct net_device *dev) tg3_disable_ints(tp); - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_free_rings(tp); tp->tg3_flags &= ~(TG3_FLAG_INIT_COMPLETE | @@ -7110,7 +7110,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e tp->tx_pending = ering->tx_pending; if (netif_running(dev)) { - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_init_hw(tp); tg3_netif_start(tp); } @@ -7153,7 +7153,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; if (netif_running(dev)) { - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_init_hw(tp); tg3_netif_start(tp); } @@ -9586,7 +9586,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); } err = tg3_test_dma(tp); @@ -9713,7 +9713,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); - tg3_halt(tp, 1); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); -- cgit v1.1 From a71116d1f3b85a69fe3a3acec9223fefb4b1fc66 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:58:11 -0700 Subject: [TG3]: Add register test Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 73f6e96..4589f8f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7307,6 +7307,219 @@ static int tg3_test_link(struct tg3 *tp) return -EIO; } +/* Only test the commonly used registers */ +static int tg3_test_registers(struct tg3 *tp) +{ + int i, is_5705; + u32 offset, read_mask, write_mask, val, save_val, read_val; + static struct { + u16 offset; + u16 flags; +#define TG3_FL_5705 0x1 +#define TG3_FL_NOT_5705 0x2 +#define TG3_FL_NOT_5788 0x4 + u32 read_mask; + u32 write_mask; + } reg_tbl[] = { + /* MAC Control Registers */ + { MAC_MODE, TG3_FL_NOT_5705, + 0x00000000, 0x00ef6f8c }, + { MAC_MODE, TG3_FL_5705, + 0x00000000, 0x01ef6b8c }, + { MAC_STATUS, TG3_FL_NOT_5705, + 0x03800107, 0x00000000 }, + { MAC_STATUS, TG3_FL_5705, + 0x03800100, 0x00000000 }, + { MAC_ADDR_0_HIGH, 0x0000, + 0x00000000, 0x0000ffff }, + { MAC_ADDR_0_LOW, 0x0000, + 0x00000000, 0xffffffff }, + { MAC_RX_MTU_SIZE, 0x0000, + 0x00000000, 0x0000ffff }, + { MAC_TX_MODE, 0x0000, + 0x00000000, 0x00000070 }, + { MAC_TX_LENGTHS, 0x0000, + 0x00000000, 0x00003fff }, + { MAC_RX_MODE, TG3_FL_NOT_5705, + 0x00000000, 0x000007fc }, + { MAC_RX_MODE, TG3_FL_5705, + 0x00000000, 0x000007dc }, + { MAC_HASH_REG_0, 0x0000, + 0x00000000, 0xffffffff }, + { MAC_HASH_REG_1, 0x0000, + 0x00000000, 0xffffffff }, + { MAC_HASH_REG_2, 0x0000, + 0x00000000, 0xffffffff }, + { MAC_HASH_REG_3, 0x0000, + 0x00000000, 0xffffffff }, + + /* Receive Data and Receive BD Initiator Control Registers. */ + { RCVDBDI_JUMBO_BD+0, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { RCVDBDI_JUMBO_BD+4, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { RCVDBDI_JUMBO_BD+8, TG3_FL_NOT_5705, + 0x00000000, 0x00000003 }, + { RCVDBDI_JUMBO_BD+0xc, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { RCVDBDI_STD_BD+0, 0x0000, + 0x00000000, 0xffffffff }, + { RCVDBDI_STD_BD+4, 0x0000, + 0x00000000, 0xffffffff }, + { RCVDBDI_STD_BD+8, 0x0000, + 0x00000000, 0xffff0002 }, + { RCVDBDI_STD_BD+0xc, 0x0000, + 0x00000000, 0xffffffff }, + + /* Receive BD Initiator Control Registers. */ + { RCVBDI_STD_THRESH, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { RCVBDI_STD_THRESH, TG3_FL_5705, + 0x00000000, 0x000003ff }, + { RCVBDI_JUMBO_THRESH, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + + /* Host Coalescing Control Registers. */ + { HOSTCC_MODE, TG3_FL_NOT_5705, + 0x00000000, 0x00000004 }, + { HOSTCC_MODE, TG3_FL_5705, + 0x00000000, 0x000000f6 }, + { HOSTCC_RXCOL_TICKS, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_RXCOL_TICKS, TG3_FL_5705, + 0x00000000, 0x000003ff }, + { HOSTCC_TXCOL_TICKS, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_TXCOL_TICKS, TG3_FL_5705, + 0x00000000, 0x000003ff }, + { HOSTCC_RXMAX_FRAMES, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_RXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788, + 0x00000000, 0x000000ff }, + { HOSTCC_TXMAX_FRAMES, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_TXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788, + 0x00000000, 0x000000ff }, + { HOSTCC_RXCOAL_TICK_INT, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_TXCOAL_TICK_INT, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788, + 0x00000000, 0x000000ff }, + { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788, + 0x00000000, 0x000000ff }, + { HOSTCC_STAT_COAL_TICKS, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_STATS_BLK_HOST_ADDR, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_STATS_BLK_HOST_ADDR+4, TG3_FL_NOT_5705, + 0x00000000, 0xffffffff }, + { HOSTCC_STATUS_BLK_HOST_ADDR, 0x0000, + 0x00000000, 0xffffffff }, + { HOSTCC_STATUS_BLK_HOST_ADDR+4, 0x0000, + 0x00000000, 0xffffffff }, + { HOSTCC_STATS_BLK_NIC_ADDR, 0x0000, + 0xffffffff, 0x00000000 }, + { HOSTCC_STATUS_BLK_NIC_ADDR, 0x0000, + 0xffffffff, 0x00000000 }, + + /* Buffer Manager Control Registers. */ + { BUFMGR_MB_POOL_ADDR, 0x0000, + 0x00000000, 0x007fff80 }, + { BUFMGR_MB_POOL_SIZE, 0x0000, + 0x00000000, 0x007fffff }, + { BUFMGR_MB_RDMA_LOW_WATER, 0x0000, + 0x00000000, 0x0000003f }, + { BUFMGR_MB_MACRX_LOW_WATER, 0x0000, + 0x00000000, 0x000001ff }, + { BUFMGR_MB_HIGH_WATER, 0x0000, + 0x00000000, 0x000001ff }, + { BUFMGR_DMA_DESC_POOL_ADDR, TG3_FL_NOT_5705, + 0xffffffff, 0x00000000 }, + { BUFMGR_DMA_DESC_POOL_SIZE, TG3_FL_NOT_5705, + 0xffffffff, 0x00000000 }, + + /* Mailbox Registers */ + { GRCMBOX_RCVSTD_PROD_IDX+4, 0x0000, + 0x00000000, 0x000001ff }, + { GRCMBOX_RCVJUMBO_PROD_IDX+4, TG3_FL_NOT_5705, + 0x00000000, 0x000001ff }, + { GRCMBOX_RCVRET_CON_IDX_0+4, 0x0000, + 0x00000000, 0x000007ff }, + { GRCMBOX_SNDHOST_PROD_IDX_0+4, 0x0000, + 0x00000000, 0x000001ff }, + + { 0xffff, 0x0000, 0x00000000, 0x00000000 }, + }; + + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + is_5705 = 1; + else + is_5705 = 0; + + for (i = 0; reg_tbl[i].offset != 0xffff; i++) { + if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705)) + continue; + + if (!is_5705 && (reg_tbl[i].flags & TG3_FL_5705)) + continue; + + if ((tp->tg3_flags2 & TG3_FLG2_IS_5788) && + (reg_tbl[i].flags & TG3_FL_NOT_5788)) + continue; + + offset = (u32) reg_tbl[i].offset; + read_mask = reg_tbl[i].read_mask; + write_mask = reg_tbl[i].write_mask; + + /* Save the original register content */ + save_val = tr32(offset); + + /* Determine the read-only value. */ + read_val = save_val & read_mask; + + /* Write zero to the register, then make sure the read-only bits + * are not changed and the read/write bits are all zeros. + */ + tw32(offset, 0); + + val = tr32(offset); + + /* Test the read-only and read/write bits. */ + if (((val & read_mask) != read_val) || (val & write_mask)) + goto out; + + /* Write ones to all the bits defined by RdMask and WrMask, then + * make sure the read-only bits are not changed and the + * read/write bits are all ones. + */ + tw32(offset, read_mask | write_mask); + + val = tr32(offset); + + /* Test the read-only bits. */ + if ((val & read_mask) != read_val) + goto out; + + /* Test the read/write bits. */ + if ((val & write_mask) != write_mask) + goto out; + + tw32(offset, save_val); + } + + return 0; + +out: + printk(KERN_ERR PFX "Register test failed at offset %x\n", offset); + tw32(offset, save_val); + return -EIO; +} + static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *data) { @@ -7322,6 +7535,34 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, etest->flags |= ETH_TEST_FL_FAILED; data[1] = 1; } + if (etest->flags & ETH_TEST_FL_OFFLINE) { + if (netif_running(dev)) + tg3_netif_stop(tp); + + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + + tg3_halt(tp, RESET_KIND_SUSPEND, 1); + tg3_nvram_lock(tp); + tg3_halt_cpu(tp, RX_CPU_BASE); + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + tg3_halt_cpu(tp, TX_CPU_BASE); + tg3_nvram_unlock(tp); + + if (tg3_test_registers(tp) != 0) { + etest->flags |= ETH_TEST_FL_FAILED; + data[2] = 1; + } + + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); + if (netif_running(dev)) { + tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; + tg3_init_hw(tp); + tg3_netif_start(tp); + } + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + } } static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -- cgit v1.1 From 7942e1dbd7252b480ed238096dca617189d293df Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:58:36 -0700 Subject: [TG3]: Add memory test Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4589f8f..49cb7b3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7520,6 +7520,62 @@ out: return -EIO; } +static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len) +{ + static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a }; + int i; + u32 j; + + for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) { + for (j = 0; j < len; j += 4) { + u32 val; + + tg3_write_mem(tp, offset + j, test_pattern[i]); + tg3_read_mem(tp, offset + j, &val); + if (val != test_pattern[i]) + return -EIO; + } + } + return 0; +} + +static int tg3_test_memory(struct tg3 *tp) +{ + static struct mem_entry { + u32 offset; + u32 len; + } mem_tbl_570x[] = { + { 0x00000000, 0x01000}, + { 0x00002000, 0x1c000}, + { 0xffffffff, 0x00000} + }, mem_tbl_5705[] = { + { 0x00000100, 0x0000c}, + { 0x00000200, 0x00008}, + { 0x00000b50, 0x00400}, + { 0x00004000, 0x00800}, + { 0x00006000, 0x01000}, + { 0x00008000, 0x02000}, + { 0x00010000, 0x0e000}, + { 0xffffffff, 0x00000} + }; + struct mem_entry *mem_tbl; + int err = 0; + int i; + + if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) + mem_tbl = mem_tbl_5705; + else + mem_tbl = mem_tbl_570x; + + for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { + if ((err = tg3_do_mem_test(tp, mem_tbl[i].offset, + mem_tbl[i].len)) != 0) + break; + } + + return err; +} + static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *data) { @@ -7553,6 +7609,10 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, etest->flags |= ETH_TEST_FL_FAILED; data[2] = 1; } + if (tg3_test_memory(tp) != 0) { + etest->flags |= ETH_TEST_FL_FAILED; + data[3] = 1; + } tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { -- cgit v1.1 From c76949a6826fc11efcd6bb1abdca1ae02761071d Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:58:59 -0700 Subject: [TG3]: Add loopback test The test will loopback one packet in MAC loopback mode and verify the packet data. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 49cb7b3..2a771fd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7576,6 +7576,117 @@ static int tg3_test_memory(struct tg3 *tp) return err; } +static int tg3_test_loopback(struct tg3 *tp) +{ + u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key; + u32 desc_idx; + struct sk_buff *skb, *rx_skb; + u8 *tx_data; + dma_addr_t map; + int num_pkts, tx_len, rx_len, i, err; + struct tg3_rx_buffer_desc *desc; + + if (!netif_running(tp->dev)) + return -ENODEV; + + err = -EIO; + + tg3_abort_hw(tp, 1); + + /* Clearing this flag to keep interrupts disabled */ + tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; + tg3_reset_hw(tp); + + mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | + MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | + MAC_MODE_PORT_MODE_GMII; + tw32(MAC_MODE, mac_mode); + + tx_len = 1514; + skb = dev_alloc_skb(tx_len); + tx_data = skb_put(skb, tx_len); + memcpy(tx_data, tp->dev->dev_addr, 6); + memset(tx_data + 6, 0x0, 8); + + tw32(MAC_RX_MTU_SIZE, tx_len + 4); + + for (i = 14; i < tx_len; i++) + tx_data[i] = (u8) (i & 0xff); + + map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE); + + tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | + HOSTCC_MODE_NOW); + + udelay(10); + + rx_start_idx = tp->hw_status->idx[0].rx_producer; + + send_idx = 0; + num_pkts = 0; + + tg3_set_txd(tp, send_idx, map, tx_len, 0, 1); + + send_idx++; + num_pkts++; + + tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx); + tr32(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW); + + udelay(10); + + for (i = 0; i < 10; i++) { + tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | + HOSTCC_MODE_NOW); + + udelay(10); + + tx_idx = tp->hw_status->idx[0].tx_consumer; + rx_idx = tp->hw_status->idx[0].rx_producer; + if ((tx_idx == send_idx) && + (rx_idx == (rx_start_idx + num_pkts))) + break; + } + + pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE); + dev_kfree_skb(skb); + + if (tx_idx != send_idx) + goto out; + + if (rx_idx != rx_start_idx + num_pkts) + goto out; + + desc = &tp->rx_rcb[rx_start_idx]; + desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; + opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; + if (opaque_key != RXD_OPAQUE_RING_STD) + goto out; + + if ((desc->err_vlan & RXD_ERR_MASK) != 0 && + (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) + goto out; + + rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; + if (rx_len != tx_len) + goto out; + + rx_skb = tp->rx_std_buffers[desc_idx].skb; + + map = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], mapping); + pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE); + + for (i = 14; i < tx_len; i++) { + if (*(rx_skb->data + i) != (u8) (i & 0xff)) + goto out; + } + err = 0; + + /* tg3_free_rings will unmap and free the rx_skb */ +out: + return err; +} + static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *data) { @@ -7613,6 +7724,10 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, etest->flags |= ETH_TEST_FL_FAILED; data[3] = 1; } + if (tg3_test_loopback(tp) != 0) { + etest->flags |= ETH_TEST_FL_FAILED; + data[4] = 1; + } tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { -- cgit v1.1 From d4bc3927d284784b3f0bff05b4eed2242cc3e226 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:59:20 -0700 Subject: [TG3]: Add interrupt test This test uses the previously added tg3_test_interrupt() to perform the test. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2a771fd..82afd26 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5894,6 +5894,9 @@ static int tg3_test_interrupt(struct tg3 *tp) int err, i; u32 int_mbox = 0; + if (!netif_running(dev)) + return -ENODEV; + tg3_disable_ints(tp); free_irq(tp->pdev->irq, dev); @@ -7729,6 +7732,15 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, data[4] = 1; } + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); + if (tg3_test_interrupt(tp) != 0) { + etest->flags |= ETH_TEST_FL_FAILED; + data[5] = 1; + } + spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); if (netif_running(dev)) { tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; -- cgit v1.1 From 1b62815193f6c20c60958e5347751155833e3d35 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 29 May 2005 14:59:49 -0700 Subject: [TG3]: Fix bug in tg3_load_firmware_cpu Add tg3_nvram_lock() and tg3_nvram_unlock() calls around tg3_halt_cpu(). It is possible that the bootcode may be loading code from nvram during this call and stopping the cpu without getting the lock may cause uncompleted nvram data to be left in the nvram data register. Subsequent calls to read/write nvram data will fail. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 82afd26..fc9b5cd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4370,7 +4370,12 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b */ tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; + /* It is possible that bootcode is still loading at this point. + * Get the nvram lock first before halting the cpu. + */ + tg3_nvram_lock(tp); err = tg3_halt_cpu(tp, cpu_base); + tg3_nvram_unlock(tp); if (err) goto out; -- cgit v1.1 From 8f937c6099858eee15fae14009dcbd05177fa91d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 29 May 2005 20:23:46 -0700 Subject: [IPV4]: Primary and secondary addresses Add an option to make secondary IP addresses get promoted when primary IP addresses are removed from the device. It defaults to off to preserve existing behavior. Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/inetdevice.h | 2 ++ include/linux/sysctl.h | 1 + net/ipv4/devinet.c | 34 +++++++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 6fafb27..7e1e15f 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -29,6 +29,7 @@ struct ipv4_devconf int no_xfrm; int no_policy; int force_igmp_version; + int promote_secondaries; void *sysctl; }; @@ -71,6 +72,7 @@ struct in_device #define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects) #define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag) #define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id) +#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries) #define IN_DEV_RX_REDIRECTS(in_dev) \ ((IN_DEV_FORWARD(in_dev) && \ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 7729981..23032d9 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -399,6 +399,7 @@ enum NET_IPV4_CONF_FORCE_IGMP_VERSION=17, NET_IPV4_CONF_ARP_ANNOUNCE=18, NET_IPV4_CONF_ARP_IGNORE=19, + NET_IPV4_CONF_PROMOTE_SECONDARIES=20, __NET_IPV4_CONF_MAX }; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 3cc9673..478a301 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -233,11 +233,14 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b) static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy) { + struct in_ifaddr *promote = NULL; struct in_ifaddr *ifa1 = *ifap; ASSERT_RTNL(); - /* 1. Deleting primary ifaddr forces deletion all secondaries */ + /* 1. Deleting primary ifaddr forces deletion all secondaries + * unless alias promotion is set + **/ if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { struct in_ifaddr *ifa; @@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, continue; } - *ifap1 = ifa->ifa_next; + if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) { + *ifap1 = ifa->ifa_next; - rtmsg_ifa(RTM_DELADDR, ifa); - notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); - inet_free_ifa(ifa); + rtmsg_ifa(RTM_DELADDR, ifa); + notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); + inet_free_ifa(ifa); + } else { + promote = ifa; + break; + } } } @@ -281,6 +289,13 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, if (!in_dev->ifa_list) inetdev_destroy(in_dev); } + + if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) { + /* not sure if we should send a delete notify first? */ + promote->ifa_flags &= ~IFA_F_SECONDARY; + rtmsg_ifa(RTM_NEWADDR, promote); + notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); + } } static int inet_insert_ifa(struct in_ifaddr *ifa) @@ -1384,6 +1399,15 @@ static struct devinet_sysctl_table { .proc_handler = &ipv4_doint_and_flush, .strategy = &ipv4_doint_and_flush_strategy, }, + { + .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES, + .procname = "promote_secondaries", + .data = &ipv4_devconf.promote_secondaries, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &ipv4_doint_and_flush, + .strategy = &ipv4_doint_and_flush_strategy, + }, }, .devinet_dev = { { -- cgit v1.1 From 79165121bc09c209451487d977df910c4ff6fc94 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Sun, 29 May 2005 20:24:30 -0700 Subject: [NET]: Add is_multicast_ether_addr() in include/linux/etherdevice.h This patch adds is_multicast_ether_addr() to go along with is_valid_ether_addr() and friends. It then changes is_valid_ether_addr() to use the new macro, and fixes up the comment on that function to move implementation details out of the API doco. Signed-off-by: Michael Ellerman Signed-off-by: David S. Miller --- include/linux/etherdevice.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 220748b..a147825 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -56,18 +56,32 @@ static inline int is_zero_ether_addr(const u8 *addr) } /** + * is_multicast_ether_addr - Determine if the given Ethernet address is a + * multicast address. + * + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is a multicast address. + */ +static inline int is_multicast_ether_addr(const u8 *addr) +{ + return addr[0] & 0x01; +} + +/** * is_valid_ether_addr - Determine if the given Ethernet address is valid * @addr: Pointer to a six-byte array containing the Ethernet address * * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not - * a multicast address, and is not FF:FF:FF:FF:FF:FF. The multicast - * and FF:FF:... tests are combined into the single test "!(addr[0]&1)". + * a multicast address, and is not FF:FF:FF:FF:FF:FF. * * Return true if the address is valid. */ static inline int is_valid_ether_addr(const u8 *addr) { - return !(addr[0]&1) && !is_zero_ether_addr(addr); + /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to + * explicitly check for it here. */ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); } /** @@ -83,6 +97,6 @@ static inline void random_ether_addr(u8 *addr) addr [0] &= 0xfe; /* clear multicast bit */ addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ } -#endif +#endif /* __KERNEL__ */ #endif /* _LINUX_ETHERDEVICE_H */ -- cgit v1.1 From 37e20a66db02eff9adbeee043af990cca85d0034 Mon Sep 17 00:00:00 2001 From: "Pravin B. Shelar" Date: Sun, 29 May 2005 20:26:44 -0700 Subject: [IPV4]: Kill MULTIPATHHOLDROUTE flag. It cannot work properly, so just ignore it in drr and rr multipath algorithms just like the random multipath algorithm does. Suggested by Herbert Xu. Signed-off by: Pravin B. Shelar Signed-off-by: David S. Miller --- include/net/route.h | 3 --- net/ipv4/multipath_drr.c | 18 +----------------- net/ipv4/multipath_rr.c | 20 -------------------- 3 files changed, 1 insertion(+), 40 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index efe92b2..d34ca8f 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -181,9 +181,6 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport, memcpy(&fl, &(*rp)->fl, sizeof(fl)); fl.fl_ip_sport = sport; fl.fl_ip_dport = dport; -#if defined(CONFIG_IP_ROUTE_MULTIPATH_CACHED) - fl.flags |= FLOWI_FLAG_MULTIPATHOLDROUTE; -#endif ip_rt_put(*rp); *rp = NULL; return ip_route_output_flow(rp, &fl, sk, 0); diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c index 9349686..cf2e6bc 100644 --- a/net/ipv4/multipath_drr.c +++ b/net/ipv4/multipath_drr.c @@ -57,7 +57,6 @@ struct multipath_device { static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES]; static DEFINE_SPINLOCK(state_lock); -static struct rtable *last_selection = NULL; static int inline __multipath_findslot(void) { @@ -111,11 +110,6 @@ struct notifier_block drr_dev_notifier = { .notifier_call = drr_dev_event, }; -static void drr_remove(struct rtable *rt) -{ - if (last_selection == rt) - last_selection = NULL; -} static void drr_safe_inc(atomic_t *usecount) { @@ -144,14 +138,6 @@ static void drr_select_route(const struct flowi *flp, int devidx = -1; int cur_min_devidx = -1; - /* if necessary and possible utilize the old alternative */ - if ((flp->flags & FLOWI_FLAG_MULTIPATHOLDROUTE) != 0 && - last_selection != NULL) { - result = last_selection; - *rp = result; - return; - } - /* 1. make sure all alt. nexthops have the same GC related data */ /* 2. determine the new candidate to be returned */ result = NULL; @@ -229,12 +215,10 @@ static void drr_select_route(const struct flowi *flp, } *rp = result; - last_selection = result; } static struct ip_mp_alg_ops drr_ops = { .mp_alg_select_route = drr_select_route, - .mp_alg_remove = drr_remove, }; static int __init drr_init(void) @@ -244,7 +228,7 @@ static int __init drr_init(void) if (err) return err; - err = multipath_alg_register(&drr_ops, IP_MP_ALG_RR); + err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR); if (err) goto fail; diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c index 554a825..061b6b2 100644 --- a/net/ipv4/multipath_rr.c +++ b/net/ipv4/multipath_rr.c @@ -47,29 +47,12 @@ #include #include -#define MULTIPATH_MAX_CANDIDATES 40 - -static struct rtable* last_used = NULL; - -static void rr_remove(struct rtable *rt) -{ - if (last_used == rt) - last_used = NULL; -} - static void rr_select_route(const struct flowi *flp, struct rtable *first, struct rtable **rp) { struct rtable *nh, *result, *min_use_cand = NULL; int min_use = -1; - /* if necessary and possible utilize the old alternative */ - if ((flp->flags & FLOWI_FLAG_MULTIPATHOLDROUTE) != 0 && - last_used != NULL) { - result = last_used; - goto out; - } - /* 1. make sure all alt. nexthops have the same GC related data * 2. determine the new candidate to be returned */ @@ -90,15 +73,12 @@ static void rr_select_route(const struct flowi *flp, if (!result) result = first; -out: - last_used = result; result->u.dst.__use++; *rp = result; } static struct ip_mp_alg_ops rr_ops = { .mp_alg_select_route = rr_select_route, - .mp_alg_remove = rr_remove, }; static int __init rr_init(void) -- cgit v1.1 From 69f6a0fafcdf0bfe85af182695d6d38f80f9d549 Mon Sep 17 00:00:00 2001 From: Jon Mason Date: Sun, 29 May 2005 20:27:24 -0700 Subject: [NET]: Add ethtool support for NETIF_F_HW_CSUM. Signed-off-by: Jon Mason Signed-off-by: David S. Miller --- include/linux/ethtool.h | 1 + net/core/ethtool.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c85b210..a0ab26a 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -256,6 +256,7 @@ struct net_device; u32 ethtool_op_get_link(struct net_device *dev); u32 ethtool_op_get_tx_csum(struct net_device *dev); int ethtool_op_set_tx_csum(struct net_device *dev, u32 data); +int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data); u32 ethtool_op_get_sg(struct net_device *dev); int ethtool_op_set_sg(struct net_device *dev, u32 data); u32 ethtool_op_get_tso(struct net_device *dev); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 2a56a52..8ec4848 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -29,7 +29,7 @@ u32 ethtool_op_get_link(struct net_device *dev) u32 ethtool_op_get_tx_csum(struct net_device *dev) { - return (dev->features & NETIF_F_IP_CSUM) != 0; + return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0; } int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) @@ -42,6 +42,15 @@ int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) return 0; } +int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= NETIF_F_HW_CSUM; + else + dev->features &= ~NETIF_F_HW_CSUM; + + return 0; +} u32 ethtool_op_get_sg(struct net_device *dev) { return (dev->features & NETIF_F_SG) != 0; @@ -823,3 +832,4 @@ EXPORT_SYMBOL(ethtool_op_get_tx_csum); EXPORT_SYMBOL(ethtool_op_set_sg); EXPORT_SYMBOL(ethtool_op_set_tso); EXPORT_SYMBOL(ethtool_op_set_tx_csum); +EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); -- cgit v1.1 From 6c94d3611be61e4cff33b311f1a626d93d1d3e92 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 29 May 2005 20:28:01 -0700 Subject: [IPV6]: Clear up user copy warning in flowlabel code. We are intentionally ignoring the copy_to_user() value, make it clear to the compiler too. Noted by Jeff Garzik. Signed-off-by: David S. Miller --- net/ipv6/ip6_flowlabel.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index a93f6dc..0e5f749 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -535,10 +535,12 @@ release: if (err) goto done; - /* Do not check for fault */ - if (!freq.flr_label) - copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label, - &fl->label, sizeof(fl->label)); + if (!freq.flr_label) { + if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label, + &fl->label, sizeof(fl->label))) { + /* Intentionally ignore fault. */ + } + } sfl1->fl = fl; sfl1->next = np->ipv6_fl_list; -- cgit v1.1 From d1102b59ca7b3a3c58912330a4ae38f549c8d569 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 29 May 2005 20:28:25 -0700 Subject: [NET]: Use %lx for netdev->features sysfs formatting. Signed-off-by: David S. Miller --- net/core/net-sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 060f703..910eb4c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -21,6 +21,7 @@ #define to_net_dev(class) container_of(class, struct net_device, class_dev) static const char fmt_hex[] = "%#x\n"; +static const char fmt_long_hex[] = "%#lx\n"; static const char fmt_dec[] = "%d\n"; static const char fmt_ulong[] = "%lu\n"; @@ -91,7 +92,7 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) \ NETDEVICE_ATTR(addr_len, fmt_dec); NETDEVICE_ATTR(iflink, fmt_dec); NETDEVICE_ATTR(ifindex, fmt_dec); -NETDEVICE_ATTR(features, fmt_hex); +NETDEVICE_ATTR(features, fmt_long_hex); NETDEVICE_ATTR(type, fmt_dec); /* use same locking rules as GIFHWADDR ioctl's */ -- cgit v1.1 From 9bb7bc942d3da606f184ac6a4dfc7e4d470c831b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 30 May 2005 15:35:26 -0700 Subject: [NETFILTER]: Fix deadlock with ip_queue and tcp local input path. When we have ip_queue being used from LOCAL_IN, then we end up with a situation where the verdicts coming back from userspace traverse the TCP input path from syscall context. While this seems to work most of the time, there's an ugly deadlock: syscall context is interrupted by the timer interrupt. When the timer interrupt leaves, the timer softirq get's scheduled and calls tcp_delack_timer() and alike. They themselves do bh_lock_sock(sk), which is already held from somewhere else -> boom. I've now tested the suggested solution by Patrick McHardy and Herbert Xu to simply use local_bh_{en,dis}able(). Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_queue.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index e5746b6..eda1fba 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -3,6 +3,7 @@ * communicating with userspace via netlink. * * (C) 2000-2002 James Morris + * (C) 2003-2005 Netfilter Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,6 +18,7 @@ * 2005-01-10: Added /proc counter for dropped packets; fixed so * packets aren't delivered to user space if they're going * to be dropped. + * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte) * */ #include @@ -71,7 +73,15 @@ static DECLARE_MUTEX(ipqnl_sem); static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) { + /* TCP input path (and probably other bits) assume to be called + * from softirq context, not from syscall, like ipq_issue_verdict is + * called. TCP input path deadlocks with locks taken from timer + * softirq, e.g. We therefore emulate this by local_bh_disable() */ + + local_bh_disable(); nf_reinject(entry->skb, entry->info, verdict); + local_bh_enable(); + kfree(entry); } -- cgit v1.1 From 208d89843b7b03978d8e748b8b991c1be81c4f43 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 30 May 2005 15:50:15 -0700 Subject: [IPV4]: Fix BUG() in 2.6.x, udp_poll(), fragments + CONFIG_HIGHMEM Steven Hand wrote: > > Reconstructed forward trace: > > net/ipv4/udp.c:1334 spin_lock_irq() > net/ipv4/udp.c:1336 udp_checksum_complete() > net/core/skbuff.c:1069 skb_shinfo(skb)->nr_frags > 1 > net/core/skbuff.c:1086 kunmap_skb_frag() > net/core/skbuff.h:1087 local_bh_enable() > kernel/softirq.c:0140 WARN_ON(irqs_disabled()); The receive queue lock is never taken in IRQs (and should never be) so we can simply substitute bh for irq. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/udp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4a6952e..7c24e64 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -738,7 +738,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) unsigned long amount; amount = 0; - spin_lock_irq(&sk->sk_receive_queue.lock); + spin_lock_bh(&sk->sk_receive_queue.lock); skb = skb_peek(&sk->sk_receive_queue); if (skb != NULL) { /* @@ -748,7 +748,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) */ amount = skb->len - sizeof(struct udphdr); } - spin_unlock_irq(&sk->sk_receive_queue.lock); + spin_unlock_bh(&sk->sk_receive_queue.lock); return put_user(amount, (int __user *)arg); } @@ -848,12 +848,12 @@ csum_copy_err: /* Clear queue. */ if (flags&MSG_PEEK) { int clear = 0; - spin_lock_irq(&sk->sk_receive_queue.lock); + spin_lock_bh(&sk->sk_receive_queue.lock); if (skb == skb_peek(&sk->sk_receive_queue)) { __skb_unlink(skb, &sk->sk_receive_queue); clear = 1; } - spin_unlock_irq(&sk->sk_receive_queue.lock); + spin_unlock_bh(&sk->sk_receive_queue.lock); if (clear) kfree_skb(skb); } @@ -1334,7 +1334,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) struct sk_buff_head *rcvq = &sk->sk_receive_queue; struct sk_buff *skb; - spin_lock_irq(&rcvq->lock); + spin_lock_bh(&rcvq->lock); while ((skb = skb_peek(rcvq)) != NULL) { if (udp_checksum_complete(skb)) { UDP_INC_STATS_BH(UDP_MIB_INERRORS); @@ -1345,7 +1345,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) break; } } - spin_unlock_irq(&rcvq->lock); + spin_unlock_bh(&rcvq->lock); /* nothing to see, move along */ if (skb == NULL) -- cgit v1.1 From 05fda3b1d88ebac1fc866fc3ed5b7ef5a4672fa6 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 31 May 2005 17:01:11 +1000 Subject: [PATCH] ppc64: actually call prom_send_capabilities When I sent in the patch adding the code for the kernel to tell the firmware about its capabilities on pSeries machines, I included the function to give the capabilities to firmware but somehow forgot the hunk that adds the call to the new function. This patch adds the call. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/prom_init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 6f79b7b..bc53967 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1881,6 +1881,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long &getprop_rval, sizeof(getprop_rval)); /* + * On pSeries, inform the firmware about our capabilities + */ + if (RELOC(of_platform) & PLATFORM_PSERIES) + prom_send_capabilities(); + + /* * On pSeries, copy the CPU hold code */ if (RELOC(of_platform) & PLATFORM_PSERIES) -- cgit v1.1 From 4e7c6816d680d1945916db047a47847afe4b9b02 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 May 2005 17:47:36 +0200 Subject: [PATCH] Relax idecd dma alignment check Only the address needs alignment of mask bits, length should work with a relaxed alignment check. Signed-off-by: Jens Axboe [ This is take 2: make the length check be for 16-byte alignment, not just word alignment. That should hopefully keep everybody happy, while still allowing CD writing with DMA ] Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 78e3e7b..39f3e91 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1936,7 +1936,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) * NOTE! The "len" and "addr" checks should possibly have * separate masks. */ - if ((rq->data_len & mask) || (addr & mask)) + if ((rq->data_len & 15) || (addr & mask)) info->dma = 0; } -- cgit v1.1 From fffcc150a21853651ea890a605832c5cccbb6279 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 31 May 2005 10:38:32 -0700 Subject: [IA64] Use "PER_CPU" form of EXPORT macro I was gently reminded that there are per-cpu forms of the EXPORT_SYMBOL macros. Signed-off-by: Tony Luck --- arch/ia64/kernel/perfmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 0e58ec7..6407bff 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -609,7 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info); DEFINE_PER_CPU(struct task_struct *, pmu_owner); DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); DEFINE_PER_CPU(unsigned long, pmu_activation_number); -EXPORT_SYMBOL_GPL(per_cpu__pfm_syst_info); +EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info); /* forward declaration */ -- cgit v1.1 From 4a4e5787e0b721021fe0a456ddc987a04cebfc8d Mon Sep 17 00:00:00 2001 From: "R.Marek@sh.cvut.cz" Date: Thu, 21 Apr 2005 09:07:56 +0000 Subject: [PATCH] I2C: ALI1563 SMBus driver fix This patch fixes "grave" bugs in i2c-ali1563 driver. It seems on recent chipset revisions the HSTS_DONE is set only for block transfers, so we must detect the end of ordinary transaction other way. Also due to missing and mask, setting other transfer modes was not possible. Moreover the continous byte mode transfer uses DAT0 for command rather than CMD command. All those changes were tested with help of Chunhao Huang from Winbond. I'm willing to maintain the driver. Second patch adds me as maintainer if this is neccessary. Signed-Off-By: Rudolf Marek Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 ++++++ drivers/i2c/busses/i2c-ali1563.c | 46 +++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 97bc927..65ad825 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net W: http://www.linux-usb.org/SpeedTouch/ S: Maintained +ALI1563 I2C DRIVER +P: Rudolf Marek +M: r.marek@sh.cvut.cz +L: sensors@stimpy.netroedge.com +S: Maintained + ALPHA PORT P: Richard Henderson M: rth@twiddle.net diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 3571081..fdd881a 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -2,6 +2,7 @@ * i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge * * Copyright (C) 2004 Patrick Mochel + * 2005 Rudolf Marek * * The 1563 southbridge is deceptively similar to the 1533, with a * few notable exceptions. One of those happens to be the fact they @@ -57,10 +58,11 @@ #define HST_CNTL2_BLOCK 0x05 +#define HST_CNTL2_SIZEMASK 0x38 static unsigned short ali1563_smba; -static int ali1563_transaction(struct i2c_adapter * a) +static int ali1563_transaction(struct i2c_adapter * a, int size) { u32 data; int timeout; @@ -73,7 +75,7 @@ static int ali1563_transaction(struct i2c_adapter * a) data = inb_p(SMB_HST_STS); if (data & HST_STS_BAD) { - dev_warn(&a->dev,"ali1563: Trying to reset busy device\n"); + dev_err(&a->dev, "ali1563: Trying to reset busy device\n"); outb_p(data | HST_STS_BAD,SMB_HST_STS); data = inb_p(SMB_HST_STS); if (data & HST_STS_BAD) @@ -94,19 +96,31 @@ static int ali1563_transaction(struct i2c_adapter * a) if (timeout && !(data & HST_STS_BAD)) return 0; - dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n", - timeout ? "Timeout " : "", - data & HST_STS_FAIL ? "Transaction Failed " : "", - data & HST_STS_BUSERR ? "No response or Bus Collision " : "", - data & HST_STS_DEVERR ? "Device Error " : "", - !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); - if (!(data & HST_STS_DONE)) + if (!timeout) { + dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n"); /* Issue 'kill' to host controller */ outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); - else - /* Issue timeout to reset all devices on bus */ + data = inb_p(SMB_HST_STS); + } + + /* device error - no response, ignore the autodetection case */ + if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) { + dev_err(&a->dev, "Device error!\n"); + } + + /* bus collision */ + if (data & HST_STS_BUSERR) { + dev_err(&a->dev, "Bus collision!\n"); + /* Issue timeout, hoping it helps */ outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1); + } + + if (data & HST_STS_FAIL) { + dev_err(&a->dev, "Cleaning fail after KILL!\n"); + outb_p(0x0,SMB_HST_CNTL2); + } + return -1; } @@ -149,7 +163,7 @@ static int ali1563_block_start(struct i2c_adapter * a) if (timeout && !(data & HST_STS_BAD)) return 0; - dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n", + dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n", timeout ? "Timeout " : "", data & HST_STS_FAIL ? "Transaction Failed " : "", data & HST_STS_BUSERR ? "No response or Bus Collision " : "", @@ -242,13 +256,15 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, } outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); - outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2); + outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2); /* Write the command register */ + switch(size) { case HST_CNTL2_BYTE: if (rw== I2C_SMBUS_WRITE) - outb_p(cmd, SMB_HST_CMD); + /* Beware it uses DAT0 register and not CMD! */ + outb_p(cmd, SMB_HST_DAT0); break; case HST_CNTL2_BYTE_DATA: outb_p(cmd, SMB_HST_CMD); @@ -268,7 +284,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, goto Done; } - if ((error = ali1563_transaction(a))) + if ((error = ali1563_transaction(a, size))) goto Done; if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK)) -- cgit v1.1 From 1e9a47b62f7daf5a94fdd74a94dd4e076f44909a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 26 May 2005 05:55:55 -0700 Subject: [PATCH] USB: sl811-hcd fixes Various fixes to the sl811-hcd driver: * Fix small glitches that crept in during recent evolution of usbcore's hcd glue layer, coupling endpoint state records to usbcore and active urbs. (As noted by folk whose boards weren't stuck on 2.6.9 kernels...) * Cope with various system-specific issues: - Some configurations (e.g. a CF-card uses this chip) have iospace addresses for the two registers, rather than memory mapped ones. - Some configurations do interesting things with IRQs; maybe the line is shared, or it doesn't support level triggering. - Not all boards can drive the chip reset line in software. * Address a potential race during unlinking. * Tweak probe/remove section info to handle the case where this segment of a platform bus is hotpluggable (e.g. CF card). (The basic problem is that CONFIG_HOTPLUG is global, which is wrong since not all busses can hotplug even on hotplug-friendly systems...) Also export the driver, so that the CF driver can depend on it. Also removed some annoying end-of-line whitespace. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/sl811-hcd.c | 146 ++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 65 deletions(-) diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index a374b76..99d43f7 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -2,8 +2,8 @@ * SL811HS HCD (Host Controller Driver) for USB. * * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) - * Copyright (C) 2004 David Brownell - * + * Copyright (C) 2004-2005 David Brownell + * * Periodic scheduling is based on Roman's OHCI code * Copyright (C) 1999 Roman Weissgaerber * @@ -15,7 +15,7 @@ * For documentation, see the SL811HS spec and the "SL811HS Embedded Host" * document (providing significant pieces missing from that spec); plus * the SL811S spec if you want peripheral side info. - */ + */ /* * Status: Passed basic stress testing, works with hubs, mice, keyboards, @@ -67,7 +67,7 @@ MODULE_DESCRIPTION("SL811HS USB Host Controller Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION "15 Dec 2004" +#define DRIVER_VERSION "19 May 2005" #ifndef DEBUG @@ -121,6 +121,10 @@ static void port_power(struct sl811 *sl811, int is_on) /* reset as thoroughly as we can */ if (sl811->board && sl811->board->reset) sl811->board->reset(hcd->self.controller); + else { + sl811_write(sl811, SL11H_CTLREG1, SL11H_CTL1MASK_SE0); + mdelay(20); + } sl811_write(sl811, SL11H_IRQ_ENABLE, 0); sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); @@ -443,6 +447,7 @@ static void finish_request( spin_lock(&urb->lock); if (urb->status == -EINPROGRESS) urb->status = status; + urb->hcpriv = NULL; spin_unlock(&urb->lock); spin_unlock(&sl811->lock); @@ -472,7 +477,7 @@ static void finish_request( if (*prev) *prev = ep->next; sl811->load[i] -= ep->load; - } + } ep->branch = PERIODIC_SIZE; sl811->periodic_count--; sl811_to_hcd(sl811)->self.bandwidth_allocated @@ -661,9 +666,9 @@ retry: #ifdef QUIRK2 /* this may no longer be necessary ... */ - if (irqstat == 0 && ret == IRQ_NONE) { + if (irqstat == 0) { irqstat = checkdone(sl811); - if (irqstat /* && irq != ~0 */ ) + if (irqstat) sl811->stat_lost++; } #endif @@ -722,7 +727,8 @@ retry: if (sl811->active_a) { sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); finish_request(sl811, sl811->active_a, - container_of(sl811->active_a->hep->urb_list.next, + container_of(sl811->active_a + ->hep->urb_list.next, struct urb, urb_list), NULL, -ESHUTDOWN); sl811->active_a = NULL; @@ -731,7 +737,8 @@ retry: if (sl811->active_b) { sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); finish_request(sl811, sl811->active_b, - container_of(sl811->active_b->hep->urb_list.next, + container_of(sl811->active_b + ->hep->urb_list.next, struct urb, urb_list), NULL, -ESHUTDOWN); sl811->active_b = NULL; @@ -761,7 +768,7 @@ retry: goto retry; } - if (sl811->periodic_count == 0 && list_empty(&sl811->async)) + if (sl811->periodic_count == 0 && list_empty(&sl811->async)) sofirq_off(sl811); sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); @@ -796,7 +803,7 @@ static int balance(struct sl811 *sl811, u16 period, u16 load) } if (j < PERIODIC_SIZE) continue; - branch = i; + branch = i; } } return branch; @@ -890,6 +897,7 @@ static int sl811h_urb_enqueue( break; } + ep->hep = hep; hep->hcpriv = ep; } @@ -961,15 +969,16 @@ fail: static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) { struct sl811 *sl811 = hcd_to_sl811(hcd); - struct usb_host_endpoint *hep = urb->hcpriv; + struct usb_host_endpoint *hep; unsigned long flags; struct sl811h_ep *ep; int retval = 0; + spin_lock_irqsave(&sl811->lock, flags); + hep = urb->hcpriv; if (!hep) - return -EINVAL; + goto fail; - spin_lock_irqsave(&sl811->lock, flags); ep = hep->hcpriv; if (ep) { /* finish right away if this urb can't be active ... @@ -1017,6 +1026,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) VDBG("dequeue, urb %p active %s; wait4irq\n", urb, (sl811->active_a == ep) ? "A" : "B"); } else +fail: retval = -EINVAL; spin_unlock_irqrestore(&sl811->lock, flags); return retval; @@ -1576,6 +1586,9 @@ sl811h_start(struct usb_hcd *hcd) if (sl811->board && sl811->board->power) hub_set_power_budget(udev, sl811->board->power * 2); + /* enable power and interupts */ + port_power(sl811, 1); + return 0; } @@ -1618,7 +1631,7 @@ static struct hc_driver sl811h_hc_driver = { /*-------------------------------------------------------------------------*/ -static int __init_or_module +static int __devexit sl811h_remove(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -1631,21 +1644,20 @@ sl811h_remove(struct device *dev) remove_debug_file(sl811); usb_remove_hcd(hcd); - iounmap(sl811->data_reg); + /* some platforms may use IORESOURCE_IO */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - release_mem_region(res->start, 1); + if (res) + iounmap(sl811->data_reg); - iounmap(sl811->addr_reg); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, 1); + if (res) + iounmap(sl811->addr_reg); usb_put_hcd(hcd); return 0; } -#define resource_len(r) (((r)->end - (r)->start) + 1) - -static int __init +static int __devinit sl811h_probe(struct device *dev) { struct usb_hcd *hcd; @@ -1656,7 +1668,7 @@ sl811h_probe(struct device *dev) void __iomem *addr_reg; void __iomem *data_reg; int retval; - u8 tmp; + u8 tmp, ioaddr = 0; /* basic sanity checks first. board-specific init logic should * have initialized these three resources and probably board @@ -1664,13 +1676,8 @@ sl811h_probe(struct device *dev) * minimal sanity checking. */ pdev = container_of(dev, struct platform_device, dev); - if (pdev->num_resources < 3) - return -ENODEV; - - addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data = platform_get_resource(pdev, IORESOURCE_MEM, 1); irq = platform_get_irq(pdev, 0); - if (!addr || !data || irq < 0) + if (pdev->num_resources < 3 || irq < 0) return -ENODEV; /* refuse to confuse usbcore */ @@ -1679,24 +1686,31 @@ sl811h_probe(struct device *dev) return -EINVAL; } - if (!request_mem_region(addr->start, 1, hcd_name)) { - retval = -EBUSY; - goto err1; - } - addr_reg = ioremap(addr->start, resource_len(addr)); - if (addr_reg == NULL) { - retval = -ENOMEM; - goto err2; - } + /* the chip may be wired for either kind of addressing */ + addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data = platform_get_resource(pdev, IORESOURCE_MEM, 1); + retval = -EBUSY; + if (!addr || !data) { + addr = platform_get_resource(pdev, IORESOURCE_IO, 0); + data = platform_get_resource(pdev, IORESOURCE_IO, 1); + if (!addr || !data) + return -ENODEV; + ioaddr = 1; + + addr_reg = (void __iomem *) addr->start; + data_reg = (void __iomem *) data->start; + } else { + addr_reg = ioremap(addr->start, 1); + if (addr_reg == NULL) { + retval = -ENOMEM; + goto err2; + } - if (!request_mem_region(data->start, 1, hcd_name)) { - retval = -EBUSY; - goto err3; - } - data_reg = ioremap(data->start, resource_len(addr)); - if (data_reg == NULL) { - retval = -ENOMEM; - goto err4; + data_reg = ioremap(data->start, 1); + if (data_reg == NULL) { + retval = -ENOMEM; + goto err4; + } } /* allocate and initialize hcd */ @@ -1737,12 +1751,14 @@ sl811h_probe(struct device *dev) goto err6; } - /* sl811s would need a different handler for this irq */ -#ifdef CONFIG_ARM - /* Cypress docs say the IRQ is IRQT_HIGH ... */ - set_irq_type(irq, IRQT_RISING); -#endif - retval = usb_add_hcd(hcd, irq, SA_INTERRUPT); + /* The chip's IRQ is level triggered, active high. A requirement + * for platform device setup is to cope with things like signal + * inverters (e.g. CF is active low) or working only with edge + * triggers (e.g. most ARM CPUs). Initial driver stress testing + * was on a system with single edge triggering, so most sorts of + * triggering arrangement should work. + */ + retval = usb_add_hcd(hcd, irq, SA_INTERRUPT | SA_SHIRQ); if (retval != 0) goto err6; @@ -1752,14 +1768,12 @@ sl811h_probe(struct device *dev) err6: usb_put_hcd(hcd); err5: - iounmap(data_reg); + if (!ioaddr) + iounmap(data_reg); err4: - release_mem_region(data->start, 1); - err3: - iounmap(addr_reg); + if (!ioaddr) + iounmap(addr_reg); err2: - release_mem_region(addr->start, 1); - err1: DBG("init error, %d\n", retval); return retval; } @@ -1767,7 +1781,7 @@ sl811h_probe(struct device *dev) #ifdef CONFIG_PM /* for this device there's no useful distinction between the controller - * and its root hub, except that the root hub only gets direct PM calls + * and its root hub, except that the root hub only gets direct PM calls * when CONFIG_USB_SUSPEND is enabled. */ @@ -1821,20 +1835,22 @@ sl811h_resume(struct device *dev, u32 phase) #endif -static struct device_driver sl811h_driver = { +/* this driver is exported so sl811_cs can depend on it */ +struct device_driver sl811h_driver = { .name = (char *) hcd_name, .bus = &platform_bus_type, .probe = sl811h_probe, - .remove = sl811h_remove, + .remove = __devexit_p(sl811h_remove), .suspend = sl811h_suspend, .resume = sl811h_resume, }; +EXPORT_SYMBOL(sl811h_driver); /*-------------------------------------------------------------------------*/ - -static int __init sl811h_init(void) + +static int __init sl811h_init(void) { if (usb_disabled()) return -ENODEV; @@ -1844,8 +1860,8 @@ static int __init sl811h_init(void) } module_init(sl811h_init); -static void __exit sl811h_cleanup(void) -{ +static void __exit sl811h_cleanup(void) +{ driver_unregister(&sl811h_driver); } module_exit(sl811h_cleanup); -- cgit v1.1 From c6de2b64eb575a3f9326969ec5fcdc6032b38e42 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 26 May 2005 05:55:55 -0700 Subject: [PATCH] USB: add sl811_cs support This adds support for a CF-card USB Host adapter, the Ratoc REX-CFU1U, by wrapping a PCMCIA driver around the existing "sl811-hcd" platform driver. This CF card is especially useful for PDAs, which currently tend to have no other solution for USB host capability. From: Botond Botyanszki Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 11 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/sl811_cs.c | 442 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 454 insertions(+) create mode 100644 drivers/usb/host/sl811_cs.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 3196c32..19e598c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -124,3 +124,14 @@ config USB_SL811_HCD To compile this driver as a module, choose M here: the module will be called sl811-hcd. +config USB_SL811_CS + tristate "CF/PCMCIA support for SL811HS HCD" + depends on USB_SL811_HCD && PCMCIA + default N + help + Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC + REX-CFU1U CF card (often used with PDAs). If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called "sl811_cs". + diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index a574ca0..5dbd3e7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o +obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c new file mode 100644 index 0000000..6e17326 --- /dev/null +++ b/drivers/usb/host/sl811_cs.c @@ -0,0 +1,442 @@ +/* + * PCMCIA driver for SL811HS (as found in REX-CFU1U) + * Filename: sl811_cs.c + * Author: Yukio Yamamoto + * + * Port to sl811-hcd and 2.6.x by + * Botond Botyanszki + * Simon Pickering + * + * Last update: 2005-05-12 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +MODULE_AUTHOR("Botond Botyanszki"); +MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); +MODULE_LICENSE("GPL"); + + +/*====================================================================*/ +/* MACROS */ +/*====================================================================*/ + +#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG) + +static int pc_debug = 0; +module_param(pc_debug, int, 0644); + +#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args) + +#else +#define DBG(n, args...) do{}while(0) +#endif /* no debugging */ + +#define INFO(args...) printk(KERN_INFO "sl811_cs: " args) + +#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) + +#define CS_CHECK(fn, ret) \ + do { \ + last_fn = (fn); \ + if ((last_ret = (ret)) != 0) \ + goto cs_failed; \ + } while (0) + +/*====================================================================*/ +/* VARIABLES */ +/*====================================================================*/ + +static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; + +static dev_link_t *dev_list = NULL; + +static int irq_list[4] = { -1 }; +static int irq_list_count; + +module_param_array(irq_list, int, &irq_list_count, 0444); + +INT_MODULE_PARM(irq_mask, 0xdeb8); + +typedef struct local_info_t { + dev_link_t link; + dev_node_t node; +} local_info_t; + +/*====================================================================*/ + +static void release_platform_dev(struct device * dev) +{ + DBG(0, "sl811_cs platform_dev release\n"); + dev->parent = NULL; +} + +static struct sl811_platform_data platform_data = { + .potpg = 100, + .power = 50, /* == 100mA */ + // .reset = ... FIXME: invoke CF reset on the card +}; + +static struct resource resources[] = { + [0] = { + .flags = IORESOURCE_IRQ, + }, + [1] = { + // .name = "address", + .flags = IORESOURCE_IO, + }, + [2] = { + // .name = "data", + .flags = IORESOURCE_IO, + }, +}; + +extern struct device_driver sl811h_driver; + +static struct platform_device platform_dev = { + .id = -1, + .dev = { + .platform_data = &platform_data, + .release = release_platform_dev, + }, + .resource = resources, + .num_resources = ARRAY_SIZE(resources), +}; + +static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) +{ + if (platform_dev.dev.parent) + return -EBUSY; + platform_dev.dev.parent = parent; + + /* finish seting up the platform device */ + resources[0].start = irq; + + resources[1].start = base_addr; + resources[1].end = base_addr; + + resources[2].start = base_addr + 1; + resources[2].end = base_addr + 1; + + /* The driver core will probe for us. We know sl811-hcd has been + * initialized already because of the link order dependency. + */ + platform_dev.name = sl811h_driver.name; + return platform_device_register(&platform_dev); +} + +/*====================================================================*/ + +static void sl811_cs_detach(dev_link_t *link) +{ + dev_link_t **linkp; + + DBG(0, "sl811_cs_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { + if (*linkp == link) + break; + } + if (*linkp == NULL) + return; + + /* Break the link with Card Services */ + if (link->handle) + pcmcia_deregister_client(link->handle); + + /* Unlink device structure, and free it */ + *linkp = link->next; + /* This points to the parent local_info_t struct */ + kfree(link->priv); +} + +static void sl811_cs_release(dev_link_t * link) +{ + + DBG(0, "sl811_cs_release(0x%p)\n", link); + + if (link->open) { + DBG(1, "sl811_cs: release postponed, '%s' still open\n", + link->dev->dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + /* Unlink the device chain */ + link->dev = NULL; + + platform_device_unregister(&platform_dev); + pcmcia_release_configuration(link->handle); + if (link->io.NumPorts1) + pcmcia_release_io(link->handle, &link->io); + if (link->irq.AssignedIRQ) + pcmcia_release_irq(link->handle, &link->irq); + link->state &= ~DEV_CONFIG; + + if (link->state & DEV_STALE_LINK) + sl811_cs_detach(link); +} + +static void sl811_cs_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + struct device *parent = &handle_to_dev(handle); + local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_fn, last_ret; + u_char buf[64]; + config_info_t conf; + cistpl_cftable_entry_t dflt = { 0 }; + + DBG(0, "sl811_cs_config(0x%p)\n", link); + + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Look up the current Vcc */ + CS_CHECK(GetConfigurationInfo, + pcmcia_get_configuration_info(handle, &conf)); + link->conf.Vcc = conf.Vcc; + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + + if (pcmcia_get_tuple_data(handle, &tuple) != 0 + || pcmcia_parse_tuple(handle, &tuple, &parse) + != 0) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { + dflt = *cfg; + } + + if (cfg->index == 0) + goto next_entry; + + link->conf.ConfigIndex = cfg->index; + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vcc.present & (1<vcc.param[CISTPL_POWER_VNOM]/10000 + != conf.Vcc) + goto next_entry; + } else if (dflt.vcc.present & (1<vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; + else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; + + /* we need an interrupt */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + + if (pcmcia_request_io(link->handle, &link->io) != 0) + goto next_entry; + } + break; + +next_entry: + if (link->io.NumPorts1) + pcmcia_release_io(link->handle, &link->io); + last_ret = pcmcia_get_next_tuple(handle, &tuple); + } + + /* require an IRQ and two registers */ + if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) + goto cs_failed; + if (link->conf.Attributes & CONF_ENABLE_IRQ) + CS_CHECK(RequestIRQ, + pcmcia_request_irq(link->handle, &link->irq)); + else + goto cs_failed; + + CS_CHECK(RequestConfiguration, + pcmcia_request_configuration(link->handle, &link->conf)); + + sprintf(dev->node.dev_name, driver_name); + dev->node.major = dev->node.minor = 0; + link->dev = &dev->node; + + printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", + dev->node.dev_name, link->conf.ConfigIndex, + link->conf.Vcc/10, link->conf.Vcc%10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(", irq %d", link->irq.AssignedIRQ); + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1+link->io.NumPorts1-1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + + if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) + < 0) { +cs_failed: + printk("sl811_cs_config failed\n"); + cs_error(link->handle, last_fn, last_ret); + sl811_cs_release(link); + link->state &= ~DEV_CONFIG_PENDING; + } +} + +static int +sl811_cs_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + + DBG(1, "sl811_cs_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) + sl811_cs_release(link); + break; + + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + sl811_cs_config(link); + break; + + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + break; + + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + pcmcia_request_configuration(link->handle, &link->conf); + DBG(0, "reset sl811-hcd here?\n"); + break; + } + return 0; +} + +static dev_link_t *sl811_cs_attach(void) +{ + local_info_t *local; + dev_link_t *link; + client_reg_t client_reg; + int ret, i; + + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) + return NULL; + memset(local, 0, sizeof(local_info_t)); + link = &local->link; + link->priv = local; + + /* Initialize */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < irq_list_count; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = NULL; + + link->conf.Attributes = 0; + link->conf.Vcc = 33; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = (dev_info_t *) &driver_name; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &sl811_cs_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = pcmcia_register_client(&link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + sl811_cs_detach(link); + return NULL; + } + + return link; +} + +static struct pcmcia_driver sl811_cs_driver = { + .owner = THIS_MODULE, + .drv = { + .name = (char *)driver_name, + }, + .attach = sl811_cs_attach, + .detach = sl811_cs_detach, +}; + +/*====================================================================*/ + +static int __init init_sl811_cs(void) +{ + return pcmcia_register_driver(&sl811_cs_driver); +} +module_init(init_sl811_cs); + +static void __exit exit_sl811_cs(void) +{ + pcmcia_unregister_driver(&sl811_cs_driver); +} +module_exit(exit_sl811_cs); -- cgit v1.1 From 47900743a56dc41a053107d64054aca3e1b42157 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 17 May 2005 15:12:13 +0100 Subject: [PATCH] USB: ftdi_sio: new PID for ELV UM100 ftdi_sio: Add PID for "ELV USB Module UM100". PID sent by Armin Laugher. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 52394f0..051c3a7 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -364,6 +364,7 @@ static struct usb_device_id id_table_8U232AM [] = { { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) }, { USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) }, { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) }, @@ -475,6 +476,7 @@ static struct usb_device_id id_table_FT232BM [] = { { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, @@ -618,6 +620,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, { USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index a52bb13..8866376 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -144,6 +144,8 @@ /* ELV USB Module UO100 (PID sent by Stefan Frings) */ #define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */ +/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */ +#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */ /* * Definitions for ID TECH (www.idt-net.com) devices -- cgit v1.1 From 06299db3e7f857a4985cf70dc1a5049ec12482c1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 26 May 2005 05:55:55 -0700 Subject: [PATCH] USB: fix usb-serial generic initialization At module load time, if a generic device is found, the tty information for the device is not set up properly (as the tty structures aren't initialized yet.) This can cause big problems for things like udev. This patch fixes this. Thanks to Kay Sievers for the original patch for this problem. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4536f63..5da76dd 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1297,13 +1297,6 @@ static int __init usb_serial_init(void) goto exit_bus; } - /* register the generic driver, if we should */ - result = usb_serial_generic_register(debug); - if (result < 0) { - err("%s - registering generic driver failed", __FUNCTION__); - goto exit_generic; - } - usb_serial_tty_driver->owner = THIS_MODULE; usb_serial_tty_driver->driver_name = "usbserial"; usb_serial_tty_driver->devfs_name = "usb/tts/"; @@ -1329,17 +1322,24 @@ static int __init usb_serial_init(void) goto exit_tty; } + /* register the generic driver, if we should */ + result = usb_serial_generic_register(debug); + if (result < 0) { + err("%s - registering generic driver failed", __FUNCTION__); + goto exit_generic; + } + info(DRIVER_DESC " " DRIVER_VERSION); return result; +exit_generic: + usb_deregister(&usb_serial_driver); + exit_tty: tty_unregister_driver(usb_serial_tty_driver); exit_reg_driver: - usb_serial_generic_deregister(); - -exit_generic: bus_unregister(&usb_serial_bus_type); exit_bus: -- cgit v1.1 From 7a8cb869f31de525bc34095f51f8c8a43ffcb6a9 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 23 May 2005 19:50:32 +0900 Subject: [PATCH] PCI Hotplug: shpchp driver doesn't program _HPP values properly Current shpchp driver doesn't seem to program _HPP values properly. The following patch fixes this issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchprm_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c index 243a51d..18aa65a 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/shpchprm_acpi.c @@ -1626,7 +1626,7 @@ int shpchprm_set_hpp( pci_bus->number = func->bus; devfn = PCI_DEVFN(func->device, func->function); - ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus); if (ab) { if (ab->_hpp) { -- cgit v1.1 From 2ac2610b26c9da72820443328ff2c56c7b8c87b8 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 27 May 2005 16:08:14 +0900 Subject: [PATCH] PCI Hotplug: SHPCHP driver doesn't enable PERR and SERR properly Current shpchp driver doesn't seem to program command register to enable PERR and SERR properly. The following patch fixes this issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchprm_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c index 18aa65a..7957cdc 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/shpchprm_acpi.c @@ -1681,7 +1681,7 @@ void shpchprm_enable_card( | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA; - ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus); if (ab) { if (ab->_hpp) { if (ab->_hpp->enable_perr) { -- cgit v1.1 From af00f9811e0ccbd3db84ddc4cffb0da942653393 Mon Sep 17 00:00:00 2001 From: Andy Currid Date: Mon, 23 May 2005 08:55:45 -0700 Subject: [PATCH] PCI: amd74xx patch for new NVIDIA device IDs Here's the 2.6 amd74xx patch for NVIDIA MCP51. Signed-off-by: Andy Currid Signed-off-by: Greg Kroah-Hartman --- drivers/ide/pci/amd74xx.c | 3 +++ include/linux/pci_ids.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 47225e3..4e0f13d 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -72,6 +72,7 @@ static struct amd_ide_chip { { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 }, + { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 }, { 0 } }; @@ -487,6 +488,7 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"), /* 13 */ DECLARE_NV_DEV("NFORCE-CK804"), /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"), + /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"), }; static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -521,6 +523,7 @@ static struct pci_device_id amd74xx_pci_tbl[] = { #endif { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 7ccbc2e..b0d6134 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1230,6 +1230,12 @@ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266 +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267 +#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268 +#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269 +#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282 -- cgit v1.1 From bcc488ab02254a6e60d749187a632dc3d642d4f8 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 27 May 2005 16:48:52 -0400 Subject: [PATCH] PCI Hotplug: more CPCI updates Here is my third attempt at a patch to further update the CompactPCI hotplug driver infrastructure to address the pci_enable_device issue discussed on the list as well as a few other issues I discovered during some more testing. This version addresses a few more issues pointed out by Prarit Bhargava. Changes include: - cpci_enable_device and its recursive calling of pci_enable_device on new devices removed. - Use list_rwsem to avoid slot status change races between disable_slot and check_slots. - Fixed oopsing in cpci_hp_unregister_bus caused by calling list_del on a slot after calling pci_hp_deregister. - Removed kfree calls in cleanup_slots since release_slot will have done it already. - Reworked init_slots a bit to fix latch and adapter file updating on subsequent calls to cpci_hp_start. - Improved sanity checking in cpci_hp_register_controller. - Now shut things down correctly in cpci_hotplug_exit. - Switch to pci_get_slot instead of deprecated pci_find_slot. - A bunch of CodingStyle fixes. Signed-off-by: Scott Murray Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/cpci_hotplug_core.c | 302 +++++++++++++++----------------- drivers/pci/hotplug/cpci_hotplug_pci.c | 144 ++++++--------- 2 files changed, 192 insertions(+), 254 deletions(-) diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 9e9dab7..8132d94 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -1,7 +1,7 @@ /* * CompactPCI Hot Plug Driver * - * Copyright (C) 2002 SOMA Networks, Inc. + * Copyright (C) 2002,2005 SOMA Networks, Inc. * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001 IBM Corp. * @@ -45,10 +45,10 @@ #define dbg(format, arg...) \ do { \ - if(cpci_debug) \ + if (cpci_debug) \ printk (KERN_DEBUG "%s: " format "\n", \ MY_NAME , ## arg); \ - } while(0) + } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) @@ -111,10 +111,8 @@ enable_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); - if(controller->ops->set_power) { + if (controller->ops->set_power) retval = controller->ops->set_power(slot, 1); - } - return retval; } @@ -126,37 +124,41 @@ disable_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); + down_write(&list_rwsem); + /* Unconfigure device */ dbg("%s - unconfiguring slot %s", __FUNCTION__, slot->hotplug_slot->name); - if((retval = cpci_unconfigure_slot(slot))) { + if ((retval = cpci_unconfigure_slot(slot))) { err("%s - could not unconfigure slot %s", __FUNCTION__, slot->hotplug_slot->name); - return retval; + goto disable_error; } dbg("%s - finished unconfiguring slot %s", __FUNCTION__, slot->hotplug_slot->name); /* Clear EXT (by setting it) */ - if(cpci_clear_ext(slot)) { + if (cpci_clear_ext(slot)) { err("%s - could not clear EXT for slot %s", __FUNCTION__, slot->hotplug_slot->name); retval = -ENODEV; + goto disable_error; } cpci_led_on(slot); - if(controller->ops->set_power) { - retval = controller->ops->set_power(slot, 0); - } + if (controller->ops->set_power) + if ((retval = controller->ops->set_power(slot, 0))) + goto disable_error; - if(update_adapter_status(slot->hotplug_slot, 0)) { + if (update_adapter_status(slot->hotplug_slot, 0)) warn("failure to update adapter file"); - } - if(slot->extracting) { + if (slot->extracting) { slot->extracting = 0; atomic_dec(&extracting); } +disable_error: + up_write(&list_rwsem); return retval; } @@ -165,9 +167,8 @@ cpci_get_power_status(struct slot *slot) { u8 power = 1; - if(controller->ops->get_power) { + if (controller->ops->get_power) power = controller->ops->get_power(slot); - } return power; } @@ -237,9 +238,8 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) int status = -ENOMEM; int i; - if(!(controller && bus)) { + if (!(controller && bus)) return -ENODEV; - } /* * Create a structure for each slot, and register that slot @@ -316,32 +316,30 @@ int cpci_hp_unregister_bus(struct pci_bus *bus) { struct slot *slot; - struct list_head *tmp; - struct list_head *next; - int status; + struct slot *tmp; + int status = 0; down_write(&list_rwsem); - if(!slots) { + if (!slots) { up_write(&list_rwsem); return -1; } - list_for_each_safe(tmp, next, &slot_list) { - slot = list_entry(tmp, struct slot, slot_list); - if(slot->bus == bus) { + list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { + if (slot->bus == bus) { + list_del(&slot->slot_list); + slots--; + dbg("deregistering slot %s", slot->hotplug_slot->name); status = pci_hp_deregister(slot->hotplug_slot); - if(status) { + if (status) { err("pci_hp_deregister failed with error %d", status); - return status; + break; } - - list_del(&slot->slot_list); - slots--; } } up_write(&list_rwsem); - return 0; + return status; } /* This is the interrupt mode interrupt handler */ @@ -351,7 +349,7 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs) dbg("entered cpci_hp_intr"); /* Check to see if it was our interrupt */ - if((controller->irq_flags & SA_SHIRQ) && + if ((controller->irq_flags & SA_SHIRQ) && !controller->ops->check_irq(controller->dev_id)) { dbg("exited cpci_hp_intr, not our interrupt"); return IRQ_NONE; @@ -373,38 +371,30 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs) * INS bits of the cold-inserted devices. */ static int -init_slots(void) +init_slots(int clear_ins) { struct slot *slot; - struct list_head *tmp; struct pci_dev* dev; dbg("%s - enter", __FUNCTION__); down_read(&list_rwsem); - if(!slots) { + if (!slots) { up_read(&list_rwsem); return -1; } - list_for_each(tmp, &slot_list) { - slot = list_entry(tmp, struct slot, slot_list); + list_for_each_entry(slot, &slot_list, slot_list) { dbg("%s - looking at slot %s", __FUNCTION__, slot->hotplug_slot->name); - if(cpci_check_and_clear_ins(slot)) { + if (clear_ins && cpci_check_and_clear_ins(slot)) dbg("%s - cleared INS for slot %s", __FUNCTION__, slot->hotplug_slot->name); - dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0)); - if(dev) { - if(update_adapter_status(slot->hotplug_slot, 1)) { - warn("failure to update adapter file"); - } - if(update_latch_status(slot->hotplug_slot, 1)) { - warn("failure to update latch file"); - } - slot->dev = dev; - } else { - err("%s - no driver attached to device in slot %s", - __FUNCTION__, slot->hotplug_slot->name); - } + dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); + if (dev) { + if (update_adapter_status(slot->hotplug_slot, 1)) + warn("failure to update adapter file"); + if (update_latch_status(slot->hotplug_slot, 1)) + warn("failure to update latch file"); + slot->dev = dev; } } up_read(&list_rwsem); @@ -416,26 +406,28 @@ static int check_slots(void) { struct slot *slot; - struct list_head *tmp; int extracted; int inserted; u16 hs_csr; down_read(&list_rwsem); - if(!slots) { + if (!slots) { up_read(&list_rwsem); err("no slots registered, shutting down"); return -1; } extracted = inserted = 0; - list_for_each(tmp, &slot_list) { - slot = list_entry(tmp, struct slot, slot_list); + list_for_each_entry(slot, &slot_list, slot_list) { dbg("%s - looking at slot %s", __FUNCTION__, slot->hotplug_slot->name); - if(cpci_check_and_clear_ins(slot)) { - /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */ - if(slot->dev) { - warn("slot %s already inserted", slot->hotplug_slot->name); + if (cpci_check_and_clear_ins(slot)) { + /* + * Some broken hardware (e.g. PLX 9054AB) asserts + * ENUM# twice... + */ + if (slot->dev) { + warn("slot %s already inserted", + slot->hotplug_slot->name); inserted++; continue; } @@ -452,7 +444,7 @@ check_slots(void) /* Configure device */ dbg("%s - configuring slot %s", __FUNCTION__, slot->hotplug_slot->name); - if(cpci_configure_slot(slot)) { + if (cpci_configure_slot(slot)) { err("%s - could not configure slot %s", __FUNCTION__, slot->hotplug_slot->name); continue; @@ -465,13 +457,11 @@ check_slots(void) dbg("%s - slot %s HS_CSR (2) = %04x", __FUNCTION__, slot->hotplug_slot->name, hs_csr); - if(update_latch_status(slot->hotplug_slot, 1)) { + if (update_latch_status(slot->hotplug_slot, 1)) warn("failure to update latch file"); - } - if(update_adapter_status(slot->hotplug_slot, 1)) { + if (update_adapter_status(slot->hotplug_slot, 1)) warn("failure to update adapter file"); - } cpci_led_off(slot); @@ -481,7 +471,7 @@ check_slots(void) __FUNCTION__, slot->hotplug_slot->name, hs_csr); inserted++; - } else if(cpci_check_ext(slot)) { + } else if (cpci_check_ext(slot)) { /* Process extraction request */ dbg("%s - slot %s extracted", __FUNCTION__, slot->hotplug_slot->name); @@ -491,27 +481,25 @@ check_slots(void) dbg("%s - slot %s HS_CSR = %04x", __FUNCTION__, slot->hotplug_slot->name, hs_csr); - if(!slot->extracting) { - if(update_latch_status(slot->hotplug_slot, 0)) { + if (!slot->extracting) { + if (update_latch_status(slot->hotplug_slot, 0)) { warn("failure to update latch file"); - } - atomic_inc(&extracting); slot->extracting = 1; + atomic_inc(&extracting); } extracted++; - } else if(slot->extracting) { + } else if (slot->extracting) { hs_csr = cpci_get_hs_csr(slot); - if(hs_csr == 0xffff) { + if (hs_csr == 0xffff) { /* * Hmmm, we're likely hosed at this point, should we * bother trying to tell the driver or not? */ err("card in slot %s was improperly removed", slot->hotplug_slot->name); - if(update_adapter_status(slot->hotplug_slot, 0)) { + if (update_adapter_status(slot->hotplug_slot, 0)) warn("failure to update adapter file"); - } slot->extracting = 0; atomic_dec(&extracting); } @@ -520,10 +508,9 @@ check_slots(void) up_read(&list_rwsem); dbg("inserted=%d, extracted=%d, extracting=%d", inserted, extracted, atomic_read(&extracting)); - if(inserted || extracted) { + if (inserted || extracted) return extracted; - } - else if(!atomic_read(&extracting)) { + else if (!atomic_read(&extracting)) { err("cannot find ENUM# source, shutting down"); return -1; } @@ -541,12 +528,12 @@ event_thread(void *data) unlock_kernel(); dbg("%s - event thread started", __FUNCTION__); - while(1) { + while (1) { dbg("event thread sleeping"); down_interruptible(&event_semaphore); dbg("event thread woken, thread_finished = %d", thread_finished); - if(thread_finished || signal_pending(current)) + if (thread_finished || signal_pending(current)) break; do { rc = check_slots(); @@ -558,7 +545,9 @@ event_thread(void *data) thread_finished = 1; break; } - } while(atomic_read(&extracting) != 0); + } while (atomic_read(&extracting) && !thread_finished); + if (thread_finished) + break; /* Re-enable ENUM# interrupt */ dbg("%s - re-enabling irq", __FUNCTION__); @@ -579,21 +568,21 @@ poll_thread(void *data) daemonize("cpci_hp_polld"); unlock_kernel(); - while(1) { - if(thread_finished || signal_pending(current)) + while (1) { + if (thread_finished || signal_pending(current)) break; - if(controller->ops->query_enum()) { + if (controller->ops->query_enum()) { do { rc = check_slots(); - if(rc > 0) { + if (rc > 0) { /* Give userspace a chance to handle extraction */ msleep(500); - } else if(rc < 0) { + } else if (rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; } - } while(atomic_read(&extracting) != 0); + } while (atomic_read(&extracting) && !thread_finished); } msleep(100); } @@ -612,12 +601,11 @@ cpci_start_thread(void) init_MUTEX_LOCKED(&thread_exit); thread_finished = 0; - if(controller->irq) { + if (controller->irq) pid = kernel_thread(event_thread, NULL, 0); - } else { + else pid = kernel_thread(poll_thread, NULL, 0); - } - if(pid < 0) { + if (pid < 0) { err("Can't start up our thread"); return -1; } @@ -630,9 +618,8 @@ cpci_stop_thread(void) { thread_finished = 1; dbg("thread finish command given"); - if(controller->irq) { + if (controller->irq) up(&event_semaphore); - } dbg("wait for thread to exit"); down(&thread_exit); } @@ -642,45 +629,67 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller) { int status = 0; - if(!controller) { - controller = new_controller; - if(controller->irq) { - if(request_irq(controller->irq, - cpci_hp_intr, - controller->irq_flags, - MY_NAME, controller->dev_id)) { - err("Can't get irq %d for the hotplug cPCI controller", controller->irq); - status = -ENODEV; - } - dbg("%s - acquired controller irq %d", __FUNCTION__, - controller->irq); + if (controller) + return -1; + if (!(new_controller && new_controller->ops)) + return -EINVAL; + if (new_controller->irq) { + if (!(new_controller->ops->enable_irq && + new_controller->ops->disable_irq)) + status = -EINVAL; + if (request_irq(new_controller->irq, + cpci_hp_intr, + new_controller->irq_flags, + MY_NAME, + new_controller->dev_id)) { + err("Can't get irq %d for the hotplug cPCI controller", + new_controller->irq); + status = -ENODEV; } - } else { - err("cPCI hotplug controller already registered"); - status = -1; + dbg("%s - acquired controller irq %d", + __FUNCTION__, new_controller->irq); } + if (!status) + controller = new_controller; return status; } +static void +cleanup_slots(void) +{ + struct slot *slot; + struct slot *tmp; + + /* + * Unregister all of our slots with the pci_hotplug subsystem, + * and free up all memory that we had allocated. + */ + down_write(&list_rwsem); + if (!slots) + goto cleanup_null; + list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { + list_del(&slot->slot_list); + pci_hp_deregister(slot->hotplug_slot); + } +cleanup_null: + up_write(&list_rwsem); + return; +} + int cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller) { int status = 0; - if(controller) { - if(atomic_read(&extracting) != 0) { - return -EBUSY; - } - if(!thread_finished) { + if (controller) { + if (!thread_finished) cpci_stop_thread(); - } - if(controller->irq) { + if (controller->irq) free_irq(controller->irq, controller->dev_id); - } controller = NULL; - } else { + cleanup_slots(); + } else status = -ENODEV; - } return status; } @@ -691,32 +700,28 @@ cpci_hp_start(void) int status; dbg("%s - enter", __FUNCTION__); - if(!controller) { + if (!controller) return -ENODEV; - } down_read(&list_rwsem); - if(list_empty(&slot_list)) { + if (list_empty(&slot_list)) { up_read(&list_rwsem); return -ENODEV; } up_read(&list_rwsem); - if(first) { - status = init_slots(); - if(status) { - return status; - } + status = init_slots(first); + if (first) first = 0; - } + if (status) + return status; status = cpci_start_thread(); - if(status) { + if (status) return status; - } dbg("%s - thread started", __FUNCTION__); - if(controller->irq) { + if (controller->irq) { /* Start enum interrupt processing */ dbg("%s - enabling irq", __FUNCTION__); controller->ops->enable_irq(); @@ -728,13 +733,9 @@ cpci_hp_start(void) int cpci_hp_stop(void) { - if(!controller) { + if (!controller) return -ENODEV; - } - if(atomic_read(&extracting) != 0) { - return -EBUSY; - } - if(controller->irq) { + if (controller->irq) { /* Stop enum interrupt processing */ dbg("%s - disabling irq", __FUNCTION__); controller->ops->disable_irq(); @@ -743,34 +744,6 @@ cpci_hp_stop(void) return 0; } -static void __exit -cleanup_slots(void) -{ - struct list_head *tmp; - struct slot *slot; - - /* - * Unregister all of our slots with the pci_hotplug subsystem, - * and free up all memory that we had allocated. - */ - down_write(&list_rwsem); - if(!slots) { - goto null_cleanup; - } - list_for_each(tmp, &slot_list) { - slot = list_entry(tmp, struct slot, slot_list); - list_del(&slot->slot_list); - pci_hp_deregister(slot->hotplug_slot); - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); - kfree(slot->hotplug_slot); - kfree(slot); - } - null_cleanup: - up_write(&list_rwsem); - return; -} - int __init cpci_hotplug_init(int debug) { @@ -784,7 +757,8 @@ cpci_hotplug_exit(void) /* * Clean everything up. */ - cleanup_slots(); + cpci_hp_stop(); + cpci_hp_unregister_controller(controller); } EXPORT_SYMBOL_GPL(cpci_hp_register_controller); diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 69eb4fc..c878028 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -1,7 +1,7 @@ /* * CompactPCI Hot Plug Driver PCI functions * - * Copyright (C) 2002 by SOMA Networks, Inc. + * Copyright (C) 2002,2005 by SOMA Networks, Inc. * * All rights reserved. * @@ -38,10 +38,10 @@ extern int cpci_debug; #define dbg(format, arg...) \ do { \ - if(cpci_debug) \ + if (cpci_debug) \ printk (KERN_DEBUG "%s: " format "\n", \ MY_NAME , ## arg); \ - } while(0) + } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) @@ -57,16 +57,15 @@ u8 cpci_get_attention_status(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return 0; - } - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return 0; - } + return hs_csr & 0x0008 ? 1 : 0; } @@ -78,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return 0; - } - - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return 0; - } - if(status) { + if (status) hs_csr |= HS_CSR_LOO; - } else { + else hs_csr &= ~HS_CSR_LOO; - } - if(pci_bus_write_config_word(slot->bus, + if (pci_bus_write_config_word(slot->bus, slot->devfn, hs_cap + 2, - hs_csr)) { + hs_csr)) return 0; - } return 1; } @@ -110,16 +104,13 @@ u16 cpci_get_hs_csr(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return 0xFFFF; - } - - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return 0xFFFF; - } return hs_csr; } @@ -132,24 +123,22 @@ int cpci_check_and_clear_ins(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return 0; - } - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return 0; - } - if(hs_csr & HS_CSR_INS) { + if (hs_csr & HS_CSR_INS) { /* Clear INS (by setting it) */ - if(pci_bus_write_config_word(slot->bus, + if (pci_bus_write_config_word(slot->bus, slot->devfn, hs_cap + 2, - hs_csr)) { + hs_csr)) ins = 0; - } - ins = 1; + else + ins = 1; } return ins; } @@ -163,18 +152,15 @@ int cpci_check_ext(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return 0; - } - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return 0; - } - if(hs_csr & HS_CSR_EXT) { + if (hs_csr & HS_CSR_EXT) ext = 1; - } return ext; } @@ -186,23 +172,20 @@ int cpci_clear_ext(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return -ENODEV; - } - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return -ENODEV; - } - if(hs_csr & HS_CSR_EXT) { + if (hs_csr & HS_CSR_EXT) { /* Clear EXT (by setting it) */ - if(pci_bus_write_config_word(slot->bus, + if (pci_bus_write_config_word(slot->bus, slot->devfn, hs_cap + 2, - hs_csr)) { + hs_csr)) return -ENODEV; - } } return 0; } @@ -215,18 +198,16 @@ int cpci_led_on(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return -ENODEV; - } - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return -ENODEV; - } - if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { + if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { hs_csr |= HS_CSR_LOO; - if(pci_bus_write_config_word(slot->bus, + if (pci_bus_write_config_word(slot->bus, slot->devfn, hs_cap + 2, hs_csr)) { @@ -246,18 +227,16 @@ int cpci_led_off(struct slot* slot) hs_cap = pci_bus_find_capability(slot->bus, slot->devfn, PCI_CAP_ID_CHSWP); - if(!hs_cap) { + if (!hs_cap) return -ENODEV; - } - if(pci_bus_read_config_word(slot->bus, + if (pci_bus_read_config_word(slot->bus, slot->devfn, hs_cap + 2, - &hs_csr)) { + &hs_csr)) return -ENODEV; - } - if(hs_csr & HS_CSR_LOO) { + if (hs_csr & HS_CSR_LOO) { hs_csr &= ~HS_CSR_LOO; - if(pci_bus_write_config_word(slot->bus, + if (pci_bus_write_config_word(slot->bus, slot->devfn, hs_cap + 2, hs_csr)) { @@ -274,19 +253,6 @@ int cpci_led_off(struct slot* slot) * Device configuration functions */ -static void cpci_enable_device(struct pci_dev *dev) -{ - struct pci_bus *bus; - - pci_enable_device(dev); - if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - bus = dev->subordinate; - list_for_each_entry(dev, &bus->devices, bus_list) { - cpci_enable_device(dev); - } - } -} - int cpci_configure_slot(struct slot* slot) { unsigned char busnr; @@ -294,14 +260,14 @@ int cpci_configure_slot(struct slot* slot) dbg("%s - enter", __FUNCTION__); - if(slot->dev == NULL) { + if (slot->dev == NULL) { dbg("pci_dev null, finding %02x:%02x:%x", slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); - slot->dev = pci_find_slot(slot->bus->number, slot->devfn); + slot->dev = pci_get_slot(slot->bus, slot->devfn); } /* Still NULL? Well then scan for it! */ - if(slot->dev == NULL) { + if (slot->dev == NULL) { int n; dbg("pci_dev still null"); @@ -311,10 +277,10 @@ int cpci_configure_slot(struct slot* slot) */ n = pci_scan_slot(slot->bus, slot->devfn); dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); - if(n > 0) + if (n > 0) pci_bus_add_devices(slot->bus); - slot->dev = pci_find_slot(slot->bus->number, slot->devfn); - if(slot->dev == NULL) { + slot->dev = pci_get_slot(slot->bus, slot->devfn); + if (slot->dev == NULL) { err("Could not find PCI device for slot %02x", slot->number); return 1; } @@ -329,8 +295,6 @@ int cpci_configure_slot(struct slot* slot) pci_bus_assign_resources(slot->dev->bus); - cpci_enable_device(slot->dev); - dbg("%s - exit", __FUNCTION__); return 0; } @@ -341,15 +305,15 @@ int cpci_unconfigure_slot(struct slot* slot) struct pci_dev *dev; dbg("%s - enter", __FUNCTION__); - if(!slot->dev) { + if (!slot->dev) { err("No device for slot %02x\n", slot->number); return -ENODEV; } for (i = 0; i < 8; i++) { - dev = pci_find_slot(slot->bus->number, + dev = pci_get_slot(slot->bus, PCI_DEVFN(PCI_SLOT(slot->devfn), i)); - if(dev) { + if (dev) { pci_remove_bus_device(dev); slot->dev = NULL; } -- cgit v1.1 From 8d91640606c47551771a9b27664f249f4b176613 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 31 May 2005 14:39:26 -0700 Subject: [PATCH] x86_64: More fixes for compilation without CONFIG_ACPI Suggested by Alexander Nyberg Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/io_apic.c | 1 + arch/x86_64/kernel/mpparse.c | 1 + arch/x86_64/kernel/time.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 80e9b49..afd87e6 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -37,6 +37,7 @@ #include #include #include +#include #define __apicdebuginit __init diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index f86d9db..61a63be 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Have we found an MP table */ int smp_found_config; diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 735b676..fb8c809 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -27,7 +27,9 @@ #include #include #include +#ifdef CONFIG_ACPI #include /* for PM timer frequency */ +#endif #include #include #include -- cgit v1.1 From 9c2be6a0fa186e2cb0cf14f41f20b08a5809a026 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 31 May 2005 14:39:26 -0700 Subject: [PATCH] x86_64 CONFIG_ACPI=n build fix Make CONFIG_X86_PM_TIMER dependent on CONFIG_ACPI Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 0f430d9..289f448 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -305,6 +305,7 @@ config HPET_TIMER config X86_PM_TIMER bool "PM timer" + depends on ACPI default y help Support the ACPI PM timer for time keeping. This is slow, -- cgit v1.1 From adaa765d76f58b47e10a4760f2c0bc86de5479b9 Mon Sep 17 00:00:00 2001 From: Alexander Nyberg Date: Tue, 31 May 2005 14:39:27 -0700 Subject: [PATCH] acpi build fix: x86 setup.c This is a neverending story linux/acpi.h contains empty declarations for acpi_boot_init() & acpi_boot_table_init() but they are nested inside #ifdef CONFIG_ACPI. So we'll have to #ifdef in arch/i386/kernel/setup.c: setup_arch() Signed-off-by: Alexander Nyberg Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 945ec73..2bfbdde 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1502,11 +1502,13 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled) efi_map_memmap(); +#ifdef CONFIG_ACPI_BOOT /* * Parse the ACPI tables for possible boot-time SMP configuration. */ acpi_boot_table_init(); acpi_boot_init(); +#endif #ifdef CONFIG_X86_LOCAL_APIC if (smp_found_config) -- cgit v1.1 From 2e214953295dd33fc62d43ac7ec91997afad75bb Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 31 May 2005 14:39:28 -0700 Subject: [PATCH] h8300 sleep problem h8300 appears to sleep (halt) when need_resched IS set. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/h8300/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 134aec1..b5f83e9 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void); void default_idle(void) { while(1) { - if (need_resched()) { + if (!need_resched()) { local_irq_enable(); __asm__("sleep"); local_irq_disable(); -- cgit v1.1 From f50734569c25c4e902bd3d0fb2e5bd93a200cc75 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 31 May 2005 14:39:29 -0700 Subject: [PATCH] ppc64: allow timer based profiling on iseries We used to have an iseries specific profiler that used /proc/profile. Now thats gone we can use the generic timer based stuff. Signed-off-by: Anton Blanchard Acked-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/time.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 3d54745..33364a7 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -325,9 +325,7 @@ int timer_interrupt(struct pt_regs * regs) irq_enter(); -#ifndef CONFIG_PPC_ISERIES profile_tick(CPU_PROFILING, regs); -#endif lpaca->lppaca.int_dword.fields.decr_int = 0; -- cgit v1.1 From ae92ef8a442421356950a0a8dfdc35e8e783000e Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 31 May 2005 14:39:29 -0700 Subject: [PATCH] flush icache in correct context flush_icache_range() is used in two different situation - in binfmt_elf.c & co for user space mappings and module.c for kernel modules. On m68k flush_icache_range() doesn't know which data to flush, as it has separate address spaces and the pointer argument can be valid in either address space. First I considered splitting flush_icache_range(), but this patch is simpler. Setting the correct context gives flush_icache_range() enough information to flush the correct data. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/module.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index 5734ab0..83b3d37 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1758,6 +1758,7 @@ sys_init_module(void __user *umod, const char __user *uargs) { struct module *mod; + mm_segment_t old_fs = get_fs(); int ret = 0; /* Must have permission */ @@ -1775,6 +1776,9 @@ sys_init_module(void __user *umod, return PTR_ERR(mod); } + /* flush the icache in correct context */ + set_fs(KERNEL_DS); + /* Flush the instruction cache, since we've played with text */ if (mod->module_init) flush_icache_range((unsigned long)mod->module_init, @@ -1783,6 +1787,8 @@ sys_init_module(void __user *umod, flush_icache_range((unsigned long)mod->module_core, (unsigned long)mod->module_core + mod->core_size); + set_fs(old_fs); + /* Now sew it into the lists. They won't access us, since strong_try_module_get() will fail. */ stop_machine_run(__link_module, mod, NR_CPUS); -- cgit v1.1 From 97d3a00f77fa527886d53dd943017654ce142186 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Tue, 31 May 2005 14:39:30 -0700 Subject: [PATCH] pcdp.c build fix In file included from drivers/firmware/pcdp.c:18: drivers/firmware/pcdp.h:48: error: field `addr' has incomplete type drivers/firmware/pcdp.c: In function `setup_serial_console': drivers/firmware/pcdp.c:27: error: `ACPI_ADR_SPACE_SYSTEM_MEMORY' undeclared (first use in this function) Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/pcdp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 6d5df6c..df1b721 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -11,6 +11,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include -- cgit v1.1 From e74d633dc5f56bf059f870370b2f36b021298652 Mon Sep 17 00:00:00 2001 From: Goffredo Baroncelli Date: Tue, 31 May 2005 14:39:31 -0700 Subject: [PATCH] UDF filesystem: array '__mon_yday' declared as not static in fs/udf/udftime.c the global array '__mon_yday' is not static, and it conflicts with the glibc one when the kernel is compiled as user mode. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/udf/udftime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index 457a8fe..85d8dbe 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c @@ -46,7 +46,7 @@ #endif /* How many days come before each month (0-12). */ -const unsigned short int __mon_yday[2][13] = +static const unsigned short int __mon_yday[2][13] = { /* Normal years. */ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, -- cgit v1.1 From 0451eb074eef30240c6c06dacf2911bee26831e1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 31 May 2005 15:15:58 -0700 Subject: [PKT_SCHED]: Fix dsmark to count ignored indices while walking Unused indices which are ignored while walking must still be counted to avoid dumping the same index twice. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/sched/sch_dsmark.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 8a3db9d..acbe9d2 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -163,14 +163,15 @@ static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker) return; for (i = 0; i < p->indices; i++) { if (p->mask[i] == 0xff && !p->value[i]) - continue; + goto ignore; if (walker->count >= walker->skip) { if (walker->fn(sch, i+1, walker) < 0) { walker->stop = 1; break; } } - walker->count++; +ignore: + walker->count++; } } -- cgit v1.1 From 486b53e59ca8cd07d91ad88375c1c884b15cc9bd Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 31 May 2005 15:16:52 -0700 Subject: [PKT_SCHED]: make dsmark try using pfifo instead of noop while grafting Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/sched/sch_dsmark.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index acbe9d2..a8c948f 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -73,8 +73,13 @@ static int dsmark_graft(struct Qdisc *sch,unsigned long arg, DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new, old); - if (!new) - new = &noop_qdisc; + + if (new == NULL) { + new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + if (new == NULL) + new = &noop_qdisc; + } + sch_tree_lock(sch); *old = xchg(&p->q,new); if (*old) -- cgit v1.1 From 08e9cd1fc559c00bc05df3fc551efe3b87c57ee3 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 31 May 2005 15:17:28 -0700 Subject: [PKT_SCHED]: Disable dsmark debugging messages by default Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/sched/sch_dsmark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index a8c948f..d8bd2a5 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -18,7 +18,7 @@ #include -#if 1 /* control */ +#if 0 /* control */ #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) #else #define DPRINTK(format,args...) -- cgit v1.1 From 7c963ad1d113790a8c723a178988b675868f3abe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 31 May 2005 16:57:59 -0700 Subject: [SPARC64]: Fix streaming buffer flushing on PCI and SBUS. Firstly, if the direction is TODEVICE, then dirty data in the streaming cache is impossible so we can elide the flush-flag synchronization in that case. Next, the context allocator is broken. It is highly likely that contexts get used multiple times for different dma mappings, which confuses the strbuf flushing code and makes it run inefficiently. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_iommu.c | 90 +++++++++++++++++++++++++++++++--------- arch/sparc64/kernel/pci_psycho.c | 2 +- arch/sparc64/kernel/pci_sabre.c | 2 +- arch/sparc64/kernel/pci_schizo.c | 2 +- arch/sparc64/kernel/sbus.c | 20 ++++++--- include/asm-sparc64/iommu.h | 2 + include/asm-sparc64/pbm.h | 8 ++-- 7 files changed, 94 insertions(+), 32 deletions(-) diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 33ca56c..1807876 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long return NULL; } +static int iommu_alloc_ctx(struct pci_iommu *iommu) +{ + int lowest = iommu->ctx_lowest_free; + int sz = IOMMU_NUM_CTXS - lowest; + int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest); + + if (unlikely(n == sz)) { + n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); + if (unlikely(n == lowest)) { + printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); + n = 0; + } + } + if (n) + __set_bit(n, iommu->ctx_bitmap); + + return n; +} + +static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) +{ + if (likely(ctx)) { + __clear_bit(ctx, iommu->ctx_bitmap); + if (ctx < iommu->ctx_lowest_free) + iommu->ctx_lowest_free = ctx; + } +} + /* Allocate and map kernel buffer of size SIZE using consistent mode * DMA for PCI device PDEV. Return non-NULL cpu-side address if * successful and set *DMA_ADDRP to the PCI side dma address. @@ -236,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad npages = size >> IO_PAGE_SHIFT; ctx = 0; if (iommu->iommu_ctxflush) - ctx = iommu->iommu_cur_ctx++; + ctx = iommu_alloc_ctx(iommu); first_page = __pa(first_page); while (npages--) { iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | @@ -317,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ } } + iommu_free_ctx(iommu, ctx); + spin_unlock_irqrestore(&iommu->lock, flags); order = get_order(size); @@ -360,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct base_paddr = __pa(oaddr & IO_PAGE_MASK); ctx = 0; if (iommu->iommu_ctxflush) - ctx = iommu->iommu_cur_ctx++; + ctx = iommu_alloc_ctx(iommu); if (strbuf->strbuf_enabled) iopte_protection = IOPTE_STREAMING(ctx); else @@ -380,39 +410,55 @@ bad: return PCI_DMA_ERROR_CODE; } -static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages) +static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) { int limit; - PCI_STC_FLUSHFLAG_INIT(strbuf); if (strbuf->strbuf_ctxflush && iommu->iommu_ctxflush) { unsigned long matchreg, flushreg; + u64 val; flushreg = strbuf->strbuf_ctxflush; matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); - limit = 100000; + if (pci_iommu_read(matchreg) == 0) + goto do_flush_sync; + pci_iommu_write(flushreg, ctx); - for(;;) { - if (((long)pci_iommu_read(matchreg)) >= 0L) - break; - limit--; - if (!limit) - break; - udelay(1); + if ((val = pci_iommu_read(matchreg)) == 0) + goto do_flush_sync; + + val &= 0xffff; + while (val) { + if (val & 0x1) + pci_iommu_write(flushreg, ctx); + val >>= 1; } - if (!limit) + val = pci_iommu_read(matchreg); + if (unlikely(val)) { printk(KERN_WARNING "pci_strbuf_flush: ctx flush " - "timeout vaddr[%08x] ctx[%lx]\n", - vaddr, ctx); + "timeout matchreg[%lx] ctx[%lx]\n", + val, ctx); + goto do_page_flush; + } } else { unsigned long i; + do_page_flush: for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } +do_flush_sync: + /* If the device could not have possibly put dirty data into + * the streaming cache, no flush-flag synchronization needs + * to be performed. + */ + if (direction == PCI_DMA_TODEVICE) + return; + + PCI_STC_FLUSHFLAG_INIT(strbuf); pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); (void) pci_iommu_read(iommu->write_complete_reg); @@ -466,7 +512,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); @@ -474,6 +520,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); + iommu_free_ctx(iommu, ctx); + spin_unlock_irqrestore(&iommu->lock, flags); } @@ -613,7 +661,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int /* Step 4: Choose a context if necessary. */ ctx = 0; if (iommu->iommu_ctxflush) - ctx = iommu->iommu_cur_ctx++; + ctx = iommu_alloc_ctx(iommu); /* Step 5: Create the mappings. */ if (strbuf->strbuf_enabled) @@ -678,7 +726,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); @@ -686,6 +734,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); + iommu_free_ctx(iommu, ctx); + spin_unlock_irqrestore(&iommu->lock, flags); } @@ -724,7 +774,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size } /* Step 2: Kick data out of streaming buffers. */ - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -768,7 +818,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i i--; npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 3567fa8..534320e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); - iommu->iommu_cur_ctx = 0; + iommu->ctx_lowest_free = 1; /* Register addresses. */ iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 5525d1e..53d333b 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); - iommu->iommu_cur_ctx = 0; + iommu->ctx_lowest_free = 1; /* Register addresses. */ iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e93fcad..5753175 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); - iommu->iommu_cur_ctx = 0; + iommu->ctx_lowest_free = 1; /* Register addresses, SCHIZO has iommu ctx flushing. */ iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 76ea645..89f5e01 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -117,17 +117,25 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages #define STRBUF_TAG_VALID 0x02UL -static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) +static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction) { unsigned long n; int limit; - iommu->strbuf_flushflag = 0UL; n = npages; while (n--) upa_writeq(base + (n << IO_PAGE_SHIFT), iommu->strbuf_regs + STRBUF_PFLUSH); + /* If the device could not have possibly put dirty data into + * the streaming cache, no flush-flag synchronization needs + * to be performed. + */ + if (direction == SBUS_DMA_TODEVICE) + return; + + iommu->strbuf_flushflag = 0UL; + /* Whoopee cushion! */ upa_writeq(__pa(&iommu->strbuf_flushflag), iommu->strbuf_regs + STRBUF_FSYNC); @@ -421,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, spin_lock_irqsave(&iommu->lock, flags); free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); - sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -584,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); - sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -596,7 +604,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -620,7 +628,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base; spin_lock_irqsave(&iommu->lock, flags); - sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); + sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction); spin_unlock_irqrestore(&iommu->lock, flags); } diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h index 5fd16e4..0de7a3d 100644 --- a/include/asm-sparc64/iommu.h +++ b/include/asm-sparc64/iommu.h @@ -16,4 +16,6 @@ #define IOPTE_CACHE 0x0000000000000010UL /* Cached (in UPA E-cache) */ #define IOPTE_WRITE 0x0000000000000002UL /* Writeable */ +#define IOMMU_NUM_CTXS 4096 + #endif /* !(_SPARC_IOMMU_H) */ diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 9299963..4c15610 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -15,6 +15,7 @@ #include #include #include +#include /* The abstraction used here is that there are PCI controllers, * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules @@ -40,9 +41,6 @@ struct pci_iommu { */ spinlock_t lock; - /* Context allocator. */ - unsigned int iommu_cur_ctx; - /* IOMMU page table, a linear array of ioptes. */ iopte_t *page_table; /* The page table itself. */ int page_table_sz_bits; /* log2 of ow many pages does it map? */ @@ -87,6 +85,10 @@ struct pci_iommu { u16 flush; } alloc_info[PBM_NCLUSTERS]; + /* CTX allocation. */ + unsigned long ctx_lowest_free; + unsigned long ctx_bitmap[IOMMU_NUM_CTXS / (sizeof(unsigned long) * 8)]; + /* Here a PCI controller driver describes the areas of * PCI memory space where DMA to/from physical memory * are addressed. Drivers interrogate the PCI layer -- cgit v1.1 From 36839836e8132731e0cadddce452423036a1d5b3 Mon Sep 17 00:00:00 2001 From: Edgar E Iglesias Date: Tue, 31 May 2005 17:08:05 -0700 Subject: [IPSEC]: Fix esp_decap_data size verification in esp4. Signed-off-by: Edgar E Iglesias Signed-off-by: David S. Miller --- net/ipv4/esp4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 053a883..eae84cc 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -478,7 +478,7 @@ static int __init esp4_init(void) { struct xfrm_decap_state decap; - if (sizeof(struct esp_decap_data) < + if (sizeof(struct esp_decap_data) > sizeof(decap.decap_data)) { extern void decap_data_too_small(void); -- cgit v1.1 From 7eb53d88230e23f83b2e20a78955e1412fa7bb26 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:42 -0700 Subject: [CPUFREQ] powernow-k7: don't print khz element of FSB. Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 913f652..80f01b0 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -592,7 +592,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) printk(KERN_WARNING PFX "can not determine bus frequency\n"); return -EINVAL; } - dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000); + dprintk("FSB: %3dMHz\n", fsb/1000); if (dmi_check_system(powernow_dmi_table) || acpi_force) { printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n"); -- cgit v1.1 From 78ee998fd46ed4cc647ee442d2a5492f389ee27a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:43 -0700 Subject: [CPUFREQ] cpufreq-core: reduce warning messages. cpufreq core is printing out messages at KERN_WARNING level that the core recovers from without intervention, and that the system administrator can do nothing about. Patch below reduces the severity of these messages to debug. Signed-off-by: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8e56131..03b5fb2 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -258,7 +258,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) (likely(cpufreq_cpu_data[freqs->cpu]->cur)) && (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) { - printk(KERN_WARNING "Warning: CPU frequency is %u, " + dprintk(KERN_WARNING "Warning: CPU frequency is %u, " "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur); freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; } @@ -814,7 +814,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne { struct cpufreq_freqs freqs; - printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing " + dprintk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing " "core thinks of %u, is %u kHz.\n", old_freq, new_freq); freqs.cpu = cpu; @@ -923,7 +923,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, u32 state) struct cpufreq_freqs freqs; if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) - printk(KERN_DEBUG "Warning: CPU frequency is %u, " + dprintk(KERN_DEBUG "Warning: CPU frequency is %u, " "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); @@ -1004,7 +1004,7 @@ static int cpufreq_resume(struct sys_device * sysdev) struct cpufreq_freqs freqs; if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) - printk(KERN_WARNING "Warning: CPU frequency" + dprintk(KERN_WARNING "Warning: CPU frequency" "is %u, cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); -- cgit v1.1 From 8282864a96ef0a7b88ee9e4b357e08504131394d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:43 -0700 Subject: [CPUFREQ] speedstep-centrino: Pentium 4 - M (HT) support The Pentium 4 - Ms (HT) with CPUID 0xF34 and 0xF41 seem to support centrino-like enhanced speedstep; however, no "table" support is possible. Therefore, put NULL entries into speedstep-centrino.c Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 07d5612..7dcbf70 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -54,6 +54,8 @@ enum { CPU_DOTHAN_A1, CPU_DOTHAN_A2, CPU_DOTHAN_B0, + CPU_MP4HT_D0, + CPU_MP4HT_E0, }; static const struct cpu_id cpu_ids[] = { @@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = { [CPU_DOTHAN_A1] = { 6, 13, 1 }, [CPU_DOTHAN_A2] = { 6, 13, 2 }, [CPU_DOTHAN_B0] = { 6, 13, 6 }, + [CPU_MP4HT_D0] = {15, 3, 4 }, + [CPU_MP4HT_E0] = {15, 4, 1 }, }; #define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0])) @@ -226,6 +230,8 @@ static struct cpu_model models[] = { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, + { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, + { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, { NULL, } }; -- cgit v1.1 From 6fe711658fcf92d39d84c0b7e6332ed6625dc520 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:44 -0700 Subject: [CPUFREQ] ondemand: trivial clean-ups Trivial ondemand governor clean-ups: - change from sampling_rate_in_HZ() to the official function usecs_to_jiffies(). - use for_each_online_cpu() to instead of using "if (cpu_online(i))" Signed-off-by: Eric Piel Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 8d83a21..0bc0bff 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -57,7 +57,6 @@ static unsigned int def_sampling_rate; #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define DEF_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -#define sampling_rate_in_HZ(x) (((x * HZ) < (1000 * 1000))?1:((x * HZ) / (1000 * 1000))) static void do_dbs_timer(void *data); @@ -281,7 +280,7 @@ static void dbs_check_cpu(int cpu) /* Scale idle ticks by 100 and compare with up and down ticks */ idle_ticks *= 100; up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * - sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate); + usecs_to_jiffies(dbs_tuners_ins.sampling_rate); if (idle_ticks < up_idle_ticks) { __cpufreq_driver_target(policy, policy->max, @@ -328,7 +327,7 @@ static void dbs_check_cpu(int cpu) freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * dbs_tuners_ins.sampling_down_factor; down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * - sampling_rate_in_HZ(freq_down_sampling_rate); + usecs_to_jiffies(freq_down_sampling_rate); if (idle_ticks > down_idle_ticks ) { freq_down_step = (5 * policy->max) / 100; @@ -348,11 +347,10 @@ static void do_dbs_timer(void *data) { int i; down(&dbs_sem); - for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i)) - dbs_check_cpu(i); + for_each_online_cpu(i) + dbs_check_cpu(i); schedule_delayed_work(&dbs_work, - sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate)); + usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); up(&dbs_sem); } @@ -360,7 +358,7 @@ static inline void dbs_timer_init(void) { INIT_WORK(&dbs_work, do_dbs_timer, NULL); schedule_delayed_work(&dbs_work, - sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate)); + usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); return; } -- cgit v1.1 From 6f4095af6df7aa365ecf18473c8b05c5f6c38a78 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:44 -0700 Subject: [CPUFREQ] speedstep-smi: it works on at least one P4M The speedstep-smi driver actually works on >=1 notebook with a Pentium 4-M CPU where all other cpufreq drivers fail. Therefore, allow speedstep-smi on P4Ms again, but warn users of likely failure Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 79440b3..b25fb6b 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -357,6 +357,9 @@ static int __init speedstep_init(void) case SPEEDSTEP_PROCESSOR_PIII_C: case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: break; + case SPEEDSTEP_PROCESSOR_P4M: + printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n"); + break; default: speedstep_processor = 0; } -- cgit v1.1 From 3310010818aa12145905faf97ffe3742acc842e2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:44 -0700 Subject: [CPUFREQ] Add warning comment about default governors. This comes up time and time again. Until its fixed, place this comment in the Kconfig which should stem the flow of resubmissions. Signed-off-by: Rob Weryk Signed-off-by: Dave Jones --- drivers/cpufreq/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 95882bb..3617e15 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -46,6 +46,10 @@ config CPU_FREQ_STAT_DETAILS This will show detail CPU frequency translation table in sysfs file system +# Note that it is not currently possible to set the other governors (such as ondemand) +# as the default, since if they fail to initialise, cpufreq will be +# left in an undefined state. + choice prompt "Default CPUFreq governor" default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110 -- cgit v1.1 From bf6fc9fd2d848d06b8f6c4caccef1dba9ef8c4c6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:45 -0700 Subject: [CPUFREQ] AMD Elan SC520 cpufreq driver. From: Sean Young Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/Kconfig | 14 ++- arch/i386/kernel/cpu/cpufreq/Makefile | 1 + arch/i386/kernel/cpu/cpufreq/sc520_freq.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 arch/i386/kernel/cpu/cpufreq/sc520_freq.c diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index f25ffd7..0f1eb50 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig @@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ If in doubt, say N. config ELAN_CPUFREQ - tristate "AMD Elan" + tristate "AMD Elan SC400 and SC410" select CPU_FREQ_TABLE depends on X86_ELAN ---help--- @@ -38,6 +38,18 @@ config ELAN_CPUFREQ If in doubt, say N. +config SC520_CPUFREQ + tristate "AMD Elan SC520" + select CPU_FREQ_TABLE + depends on X86_ELAN + ---help--- + This adds the CPUFreq driver for AMD Elan SC520 processor. + + For details, take a look at . + + If in doubt, say N. + + config X86_POWERNOW_K6 tristate "AMD Mobile K6-2/K6-3 PowerNow!" select CPU_FREQ_TABLE diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile index a922e97..2e894f1 100644 --- a/arch/i386/kernel/cpu/cpufreq/Makefile +++ b/arch/i386/kernel/cpu/cpufreq/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o obj-$(CONFIG_X86_LONGHAUL) += longhaul.o obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o +obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o obj-$(CONFIG_X86_LONGRUN) += longrun.o obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c new file mode 100644 index 0000000..ef457d5 --- /dev/null +++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c @@ -0,0 +1,186 @@ +/* + * sc520_freq.c: cpufreq driver for the AMD Elan sc520 + * + * Copyright (C) 2005 Sean Young + * + * 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. + * + * Based on elanfreq.c + * + * 2005-03-30: - initial revision + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define MMCR_BASE 0xfffef000 /* The default base address */ +#define OFFS_CPUCTL 0x2 /* CPU Control Register */ + +static __u8 __iomem *cpuctl; + +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg) + +static struct cpufreq_frequency_table sc520_freq_table[] = { + {0x01, 100000}, + {0x02, 133000}, + {0, CPUFREQ_TABLE_END}, +}; + +static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu) +{ + u8 clockspeed_reg = *cpuctl; + + switch (clockspeed_reg & 0x03) { + default: + printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg); + case 0x01: + return 100000; + case 0x02: + return 133000; + } +} + +static void sc520_freq_set_cpu_state (unsigned int state) +{ + + struct cpufreq_freqs freqs; + u8 clockspeed_reg; + + freqs.old = sc520_freq_get_cpu_frequency(0); + freqs.new = sc520_freq_table[state].frequency; + freqs.cpu = 0; /* AMD Elan is UP */ + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + dprintk("attempting to set frequency to %i kHz\n", + sc520_freq_table[state].frequency); + + local_irq_disable(); + + clockspeed_reg = *cpuctl & ~0x03; + *cpuctl = clockspeed_reg | sc520_freq_table[state].index; + + local_irq_enable(); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +}; + +static int sc520_freq_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]); +} + +static int sc520_freq_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate)) + return -EINVAL; + + sc520_freq_set_cpu_state(newstate); + + return 0; +} + + +/* + * Module init and exit code + */ + +static int sc520_freq_cpu_init(struct cpufreq_policy *policy) +{ + struct cpuinfo_x86 *c = cpu_data; + int result; + + /* capability check */ + if (c->x86_vendor != X86_VENDOR_AMD || + c->x86 != 4 || c->x86_model != 9) + return -ENODEV; + + /* cpuinfo and default policy values */ + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = 1000000; /* 1ms */ + policy->cur = sc520_freq_get_cpu_frequency(0); + + result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table); + if (result) + return (result); + + cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu); + + return 0; +} + + +static int sc520_freq_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + + +static struct freq_attr* sc520_freq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + + +static struct cpufreq_driver sc520_freq_driver = { + .get = sc520_freq_get_cpu_frequency, + .verify = sc520_freq_verify, + .target = sc520_freq_target, + .init = sc520_freq_cpu_init, + .exit = sc520_freq_cpu_exit, + .name = "sc520_freq", + .owner = THIS_MODULE, + .attr = sc520_freq_attr, +}; + + +static int __init sc520_freq_init(void) +{ + struct cpuinfo_x86 *c = cpu_data; + + /* Test if we have the right hardware */ + if(c->x86_vendor != X86_VENDOR_AMD || + c->x86 != 4 || c->x86_model != 9) { + dprintk("no Elan SC520 processor found!\n"); + return -ENODEV; + } + cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); + if(!cpuctl) { + printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); + return -ENOMEM; + } + + return cpufreq_register_driver(&sc520_freq_driver); +} + + +static void __exit sc520_freq_exit(void) +{ + cpufreq_unregister_driver(&sc520_freq_driver); + iounmap(cpuctl); +} + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sean Young "); +MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU"); + +module_init(sc520_freq_init); +module_exit(sc520_freq_exit); + -- cgit v1.1 From 91350ed49bf3613e243c2e216228cd4ae8f32516 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:45 -0700 Subject: [CPUFREQ] Recalibrate cpu_khz [1/2] We have to recalibrate cpu_khz in order to use the current FID instead the max FID since some BIOS do not put the processor at maximum frequency at POST. Also, some BIOS will change the processor frequency at our back after cpu_khz was calibrate. Finally, this will fix a long standing bug when we do something like this: # rmmod powernow-k7 # modprobe powernow-k7 Signed-off-by: Bruno Ducrot Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 80f01b0..5c53006 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -586,8 +587,12 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); - /* A K7 with powernow technology is set to max frequency by BIOS */ - fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID]; + /* recalibrate cpu_khz */ + result = recalibrate_cpu_khz(); + if (result) + return result; + + fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; if (!fsb) { printk(KERN_WARNING PFX "can not determine bus frequency\n"); return -EINVAL; -- cgit v1.1 From c5d28fb297efaa97c4b90e36f9dff3066e7f2778 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:46 -0700 Subject: [CPUFREQ] Recalibrate cpu_khz [2/2] Some cpufreq drivers (at that time, only powernow-k7) need to recalibrate the cpu_khz at runtime. Signed-off-by: Bruno Ducrot Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- arch/i386/kernel/timers/common.c | 6 ++++-- arch/i386/kernel/timers/timer_tsc.c | 20 ++++++++++++++++++++ include/asm-i386/timer.h | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c index f7f9000..8e20121 100644 --- a/arch/i386/kernel/timers/common.c +++ b/arch/i386/kernel/timers/common.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -24,7 +25,7 @@ #define CALIBRATE_TIME (5 * 1000020/HZ) -unsigned long __init calibrate_tsc(void) +unsigned long calibrate_tsc(void) { mach_prepare_counter(); @@ -139,7 +140,7 @@ bad_calibration: #endif /* calculate cpu_khz */ -void __init init_cpu_khz(void) +void init_cpu_khz(void) { if (cpu_has_tsc) { unsigned long tsc_quotient = calibrate_tsc(); @@ -158,3 +159,4 @@ void __init init_cpu_khz(void) } } } + diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 7926d96..180444d 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -320,6 +320,26 @@ core_initcall(cpufreq_tsc); static inline void cpufreq_delayed_get(void) { return; } #endif +int recalibrate_cpu_khz(void) +{ +#ifndef CONFIG_SMP + unsigned long cpu_khz_old = cpu_khz; + + if (cpu_has_tsc) { + init_cpu_khz(); + cpu_data[0].loops_per_jiffy = + cpufreq_scale(cpu_data[0].loops_per_jiffy, + cpu_khz_old, + cpu_khz); + return 0; + } else + return -ENODEV; +#else + return -ENODEV; +#endif +} +EXPORT_SYMBOL(recalibrate_cpu_khz); + static void mark_offset_tsc(void) { unsigned long lost,delay; diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h index 40c54f6..c347098 100644 --- a/include/asm-i386/timer.h +++ b/include/asm-i386/timer.h @@ -53,6 +53,7 @@ extern struct init_timer_opts timer_cyclone_init; extern unsigned long calibrate_tsc(void); extern void init_cpu_khz(void); +extern int recalibrate_cpu_khz(void); #ifdef CONFIG_HPET_TIMER extern struct init_timer_opts timer_hpet_init; extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr); -- cgit v1.1 From 7f335d4ef2d50a693fad70b8fa053d0382f4a45c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:46 -0700 Subject: [CPUFREQ] make cpufreq_gov_dbs static This patch makes a needlessly global and EXPORT_SYMBOL'ed struct static. Signed-off-by: Adrian Bunk Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 0bc0bff..84c6588 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -459,12 +459,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, return 0; } -struct cpufreq_governor cpufreq_gov_dbs = { +static struct cpufreq_governor cpufreq_gov_dbs = { .name = "ondemand", .governor = cpufreq_governor_dbs, .owner = THIS_MODULE, }; -EXPORT_SYMBOL(cpufreq_gov_dbs); static int __init cpufreq_gov_dbs_init(void) { -- cgit v1.1 From 065b807ca1f5bdbeb081e3cf75ac8de9be8ac212 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:46 -0700 Subject: [CPUFREQ] dual-core powernow-k8 With the release of the dual-core AMD Opterons last week, it's high time that cpufreq supported them. The attached patch applies cleanly to 2.6.12-rc3 and updates powernow-k8 to support the latest Athlon 64 and Opteron processors. Update the driver to version 1.40.0 and provide support for dual-core processors. Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 113 +++++++++++++++++++---------- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 15 ++++ 2 files changed, 91 insertions(+), 37 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index a65ff7e..10cc096 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -4,7 +4,7 @@ * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html * - * Support : paul.devriendt@amd.com + * Support : mark.langsdorf@amd.com * * Based on the powernow-k7.c module written by Dave Jones. * (C) 2003 Dave Jones on behalf of SuSE Labs @@ -15,12 +15,13 @@ * * Valuable input gratefully received from Dave Jones, Pavel Machek, * Dominik Brodowski, and others. + * Originally developed by Paul Devriendt. * Processor information obtained from Chapter 9 (Power and Thermal Management) * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD * Opteron Processors" available for download from www.amd.com * * Tables for specific CPUs can be infrerred from - * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf + * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf */ #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,7 +44,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.00.09e" +#define VERSION "version 1.40.2" #include "powernow-k8.h" /* serialize freq changes */ @@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem); static struct powernow_k8_data *powernow_data[NR_CPUS]; +#ifndef CONFIG_SMP +static cpumask_t cpu_core_map[1]; +#endif + /* Return a frequency in MHz, given an input fid */ static u32 find_freq_from_fid(u32 fid) { @@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid { u32 rvosteps = data->rvo; u32 savefid = data->currfid; + u32 maxvid, lo; dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n", smp_processor_id(), data->currfid, data->currvid, reqvid, data->rvo); + rdmsr(MSR_FIDVID_STATUS, lo, maxvid); + maxvid = 0x1f & (maxvid >> 16); + dprintk("ph1 maxvid=0x%x\n", maxvid); + if (reqvid < maxvid) /* lower numbers are higher voltages */ + reqvid = maxvid; + while (data->currvid > reqvid) { dprintk("ph1: curr 0x%x, req vid 0x%x\n", data->currvid, reqvid); @@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid return 1; } - while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { - if (data->currvid == 0) { + while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { + if (data->currvid == maxvid) { rvosteps = 0; } else { dprintk("ph1: changing vid for rvo, req 0x%x\n", @@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data) * BIOS and Kernel Developer's Guide, which is available on * www.amd.com */ - printk(KERN_ERR PFX "BIOS error - no PSB\n"); + printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n"); return -ENODEV; } @@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) struct cpufreq_frequency_table *powernow_table; if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { - dprintk("register performance failed\n"); + dprintk("register performance failed: bad ACPI data\n"); return -EIO; } @@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) continue; } - if (fid < HI_FID_TABLE_BOTTOM) { - if (cntlofreq) { - /* if both entries are the same, ignore this - * one... - */ - if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || - (powernow_table[i].index != powernow_table[cntlofreq].index)) { - printk(KERN_ERR PFX "Too many lo freq table entries\n"); - goto err_out_mem; - } - - dprintk("double low frequency table entry, ignoring it.\n"); - powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; - continue; - } else - cntlofreq = i; + /* verify only 1 entry from the lo frequency table */ + if (fid < HI_FID_TABLE_BOTTOM) { + if (cntlofreq) { + /* if both entries are the same, ignore this + * one... + */ + if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || + (powernow_table[i].index != powernow_table[cntlofreq].index)) { + printk(KERN_ERR PFX "Too many lo freq table entries\n"); + goto err_out_mem; + } + + dprintk("double low frequency table entry, ignoring it.\n"); + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; + } else + cntlofreq = i; } if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { @@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde { u32 fid; u32 vid; - int res; + int res, i; struct cpufreq_freqs freqs; dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); @@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde } if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { - printk("ignoring illegal change in lo freq table-%x to 0x%x\n", + printk(KERN_ERR PFX + "ignoring illegal change in lo freq table-%x to 0x%x\n", data->currfid, fid); return 1; } @@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde smp_processor_id(), fid, vid); freqs.cpu = data->cpu; - freqs.old = find_khz_freq_from_fid(data->currfid); freqs.new = find_khz_freq_from_fid(fid); - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + for_each_cpu_mask(i, cpu_core_map[data->cpu]) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } - down(&fidvid_sem); res = transition_fid_vid(data, fid, vid); - up(&fidvid_sem); freqs.new = find_khz_freq_from_fid(data->currfid); - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - + for_each_cpu_mask(i, cpu_core_map[data->cpu]) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } return res; } @@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi u32 checkvid = data->currvid; unsigned int newstate; int ret = -EIO; + int i; /* only run on specific CPU from here on */ oldmask = current->cpus_allowed; @@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi data->currfid, data->currvid); if ((checkvid != data->currvid) || (checkfid != data->currfid)) { - printk(KERN_ERR PFX - "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n", - checkfid, data->currfid, checkvid, data->currvid); + printk(KERN_INFO PFX + "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n", + checkfid, data->currfid, checkvid, data->currvid); } if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) goto err_out; + down(&fidvid_sem); + + for_each_cpu_mask(i, cpu_core_map[pol->cpu]) { + /* make sure the sibling is initialized */ + if (!powernow_data[i]) { + ret = 0; + up(&fidvid_sem); + goto err_out; + } + } + powernow_k8_acpi_pst_values(data, newstate); if (transition_frequency(data, newstate)) { printk(KERN_ERR PFX "transition frequency failed\n"); ret = 1; + up(&fidvid_sem); goto err_out; } + /* Update all the fid/vids of our siblings */ + for_each_cpu_mask(i, cpu_core_map[pol->cpu]) { + powernow_data[i]->currvid = data->currvid; + powernow_data[i]->currfid = data->currfid; + } + up(&fidvid_sem); + pol->cur = find_khz_freq_from_fid(data->currfid); ret = 0; @@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) */ if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { - printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n"); + printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); kfree(data); return -ENODEV; } @@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) schedule(); pol->governor = CPUFREQ_DEFAULT_GOVERNOR; + pol->cpus = cpu_core_map[pol->cpu]; /* Take a crude guess here. * That guess was in microseconds, so multiply with 1000 */ @@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu) return 0; } preempt_disable(); - + if (query_current_values_with_pending_wait(data)) goto out; @@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void) cpufreq_unregister_driver(&cpufreq_amd64_driver); } -MODULE_AUTHOR("Paul Devriendt "); +MODULE_AUTHOR("Paul Devriendt and Mark Langsdorf Date: Tue, 31 May 2005 19:03:47 -0700 Subject: [CPUFREQ] fix up comment in cpufreq.h Fix up comment in cpufreq.h stating transition latency should be passed in microseconds -- it was decided long ago to switch to nanoseconds. Signed-off-by: Dominik Brodowski Signed-off-by: Dave Jones --- include/linux/cpufreq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index f21af06..927daa8 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -49,7 +49,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); /* Frequency values here are CPU kHz so that hardware which doesn't run * with some frequencies can complain without having to guess what per * cent / per mille means. - * Maximum transition latency is in microseconds - if it's unknown, + * Maximum transition latency is in nanoseconds - if it's unknown, * CPUFREQ_ETERNAL shall be used. */ -- cgit v1.1 From b9170836d1aa4ded7cc1ac1cb8fbc7867061c98c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:47 -0700 Subject: [CPUFREQ] Conservative cpufreq governer A new cpufreq module, based on the ondemand one with my additional patches just posted. This one is more suitable for battery environments where its probably more appealing to have the cpu freq gracefully increase and decrease rather than flip between the min and max freq's. N.B. Bruno Ducrot pointed out that the amd64's "do have unacceptable latency between min and max freq transition, due to the step-by-step requirements (200MHz IIRC)"; so AMD64 users would probably benefit from this too. Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/Kconfig | 20 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq_conservative.c | 613 +++++++++++++++++++++++++++++++++ 3 files changed, 634 insertions(+) create mode 100644 drivers/cpufreq/cpufreq_conservative.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 3617e15..60c9be9 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -119,4 +119,24 @@ config CPU_FREQ_GOV_ONDEMAND If in doubt, say N. +config CPU_FREQ_GOV_CONSERVATIVE + tristate "'conservative' cpufreq governor" + depends on CPU_FREQ + help + 'conservative' - this driver is rather similar to the 'ondemand' + governor both in its source code and its purpose, the difference is + its optimisation for better suitability in a battery powered + environment. The frequency is gracefully increased and decreased + rather than jumping to 100% when speed is required. + + If you have a desktop machine then you should really be considering + the 'ondemand' governor instead, however if you are using a laptop, + PDA or even an AMD64 based computer (due to the unacceptable + step-by-step latency issues between the minimum and maximum frequency + transitions in the CPU) you will probably want to use this governor. + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + endif # CPU_FREQ diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 67b16e5..71fc3b4 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o +obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c new file mode 100644 index 0000000..dd2f5b2 --- /dev/null +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -0,0 +1,613 @@ +/* + * drivers/cpufreq/cpufreq_conservative.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * (C) 2004 Alexander Clouter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * dbs is used in this file as a shortform for demandbased switching + * It helps to keep variable names smaller, simpler + */ + +#define DEF_FREQUENCY_UP_THRESHOLD (80) +#define MIN_FREQUENCY_UP_THRESHOLD (0) +#define MAX_FREQUENCY_UP_THRESHOLD (100) + +#define DEF_FREQUENCY_DOWN_THRESHOLD (20) +#define MIN_FREQUENCY_DOWN_THRESHOLD (0) +#define MAX_FREQUENCY_DOWN_THRESHOLD (100) + +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +static unsigned int def_sampling_rate; +#define MIN_SAMPLING_RATE (def_sampling_rate / 2) +#define MAX_SAMPLING_RATE (500 * def_sampling_rate) +#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000) +#define DEF_SAMPLING_DOWN_FACTOR (5) +#define TRANSITION_LATENCY_LIMIT (10 * 1000) + +static void do_dbs_timer(void *data); + +struct cpu_dbs_info_s { + struct cpufreq_policy *cur_policy; + unsigned int prev_cpu_idle_up; + unsigned int prev_cpu_idle_down; + unsigned int enable; +}; +static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +static DECLARE_MUTEX (dbs_sem); +static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); + +struct dbs_tuners { + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int down_threshold; + unsigned int ignore_nice; + unsigned int freq_step; +}; + +static struct dbs_tuners dbs_tuners_ins = { + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, +}; + +/************************** sysfs interface ************************/ +static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", MAX_SAMPLING_RATE); +} + +static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); +} + +#define define_one_ro(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) + +define_one_ro(sampling_rate_max); +define_one_ro(sampling_rate_min); + +/* cpufreq_conservative Governor Tunables */ +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct cpufreq_policy *unused, char *buf) \ +{ \ + return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ +} +show_one(sampling_rate, sampling_rate); +show_one(sampling_down_factor, sampling_down_factor); +show_one(up_threshold, up_threshold); +show_one(down_threshold, down_threshold); +show_one(ignore_nice, ignore_nice); +show_one(freq_step, freq_step); + +static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + if (ret != 1 ) + return -EINVAL; + + down(&dbs_sem); + dbs_tuners_ins.sampling_down_factor = input; + up(&dbs_sem); + + return count; +} + +static ssize_t store_sampling_rate(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + + down(&dbs_sem); + if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) { + up(&dbs_sem); + return -EINVAL; + } + + dbs_tuners_ins.sampling_rate = input; + up(&dbs_sem); + + return count; +} + +static ssize_t store_up_threshold(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + + down(&dbs_sem); + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD || + input <= dbs_tuners_ins.down_threshold) { + up(&dbs_sem); + return -EINVAL; + } + + dbs_tuners_ins.up_threshold = input; + up(&dbs_sem); + + return count; +} + +static ssize_t store_down_threshold(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + + down(&dbs_sem); + if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || + input < MIN_FREQUENCY_DOWN_THRESHOLD || + input >= dbs_tuners_ins.up_threshold) { + up(&dbs_sem); + return -EINVAL; + } + + dbs_tuners_ins.down_threshold = input; + up(&dbs_sem); + + return count; +} + +static ssize_t store_ignore_nice(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + unsigned int j; + + ret = sscanf (buf, "%u", &input); + if ( ret != 1 ) + return -EINVAL; + + if ( input > 1 ) + input = 1; + + down(&dbs_sem); + if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ + up(&dbs_sem); + return count; + } + dbs_tuners_ins.ignore_nice = input; + + /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */ + for_each_cpu_mask(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(cpu_dbs_info, j); + j_dbs_info->cur_policy = policy; + + j_dbs_info->prev_cpu_idle_up = + kstat_cpu(j).cpustat.idle + + kstat_cpu(j).cpustat.iowait + + ( !dbs_tuners_ins.ignore_nice + ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; + } + up(&dbs_sem); + + return count; +} + +static ssize_t store_freq_step(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf (buf, "%u", &input); + + if ( ret != 1 ) + return -EINVAL; + + if ( input > 100 ) + input = 100; + + /* no need to test here if freq_step is zero as the user might actually + * want this, they would be crazy though :) */ + down(&dbs_sem); + dbs_tuners_ins.freq_step = input; + up(&dbs_sem); + + return count; +} + +#define define_one_rw(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) + +define_one_rw(sampling_rate); +define_one_rw(sampling_down_factor); +define_one_rw(up_threshold); +define_one_rw(down_threshold); +define_one_rw(ignore_nice); +define_one_rw(freq_step); + +static struct attribute * dbs_attributes[] = { + &sampling_rate_max.attr, + &sampling_rate_min.attr, + &sampling_rate.attr, + &sampling_down_factor.attr, + &up_threshold.attr, + &down_threshold.attr, + &ignore_nice.attr, + &freq_step.attr, + NULL +}; + +static struct attribute_group dbs_attr_group = { + .attrs = dbs_attributes, + .name = "conservative", +}; + +/************************** sysfs end ************************/ + +static void dbs_check_cpu(int cpu) +{ + unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; + unsigned int total_idle_ticks; + unsigned int freq_step; + unsigned int freq_down_sampling_rate; + static int down_skip[NR_CPUS]; + static int requested_freq[NR_CPUS]; + static unsigned short init_flag = 0; + struct cpu_dbs_info_s *this_dbs_info; + struct cpu_dbs_info_s *dbs_info; + + struct cpufreq_policy *policy; + unsigned int j; + + this_dbs_info = &per_cpu(cpu_dbs_info, cpu); + if (!this_dbs_info->enable) + return; + + policy = this_dbs_info->cur_policy; + + if ( init_flag == 0 ) { + for ( /* NULL */; init_flag < NR_CPUS; init_flag++ ) { + dbs_info = &per_cpu(cpu_dbs_info, init_flag); + requested_freq[cpu] = dbs_info->cur_policy->cur; + } + init_flag = 1; + } + + /* + * The default safe range is 20% to 80% + * Every sampling_rate, we check + * - If current idle time is less than 20%, then we try to + * increase frequency + * Every sampling_rate*sampling_down_factor, we check + * - If current idle time is more than 80%, then we try to + * decrease frequency + * + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% (default) of max_frequency + */ + + /* Check for frequency increase */ + total_idle_ticks = kstat_cpu(cpu).cpustat.idle + + kstat_cpu(cpu).cpustat.iowait; + /* consider 'nice' tasks as 'idle' time too if required */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(cpu).cpustat.nice; + idle_ticks = total_idle_ticks - + this_dbs_info->prev_cpu_idle_up; + this_dbs_info->prev_cpu_idle_up = total_idle_ticks; + + + for_each_cpu_mask(j, policy->cpus) { + unsigned int tmp_idle_ticks; + struct cpu_dbs_info_s *j_dbs_info; + + if (j == cpu) + continue; + + j_dbs_info = &per_cpu(cpu_dbs_info, j); + /* Check for frequency increase */ + total_idle_ticks = kstat_cpu(j).cpustat.idle + + kstat_cpu(j).cpustat.iowait; + /* consider 'nice' too? */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(j).cpustat.nice; + tmp_idle_ticks = total_idle_ticks - + j_dbs_info->prev_cpu_idle_up; + j_dbs_info->prev_cpu_idle_up = total_idle_ticks; + + if (tmp_idle_ticks < idle_ticks) + idle_ticks = tmp_idle_ticks; + } + + /* Scale idle ticks by 100 and compare with up and down ticks */ + idle_ticks *= 100; + up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * + usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + if (idle_ticks < up_idle_ticks) { + /* if we are already at full speed then break out early */ + if (requested_freq[cpu] == policy->max) + return; + + freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; + + /* max freq cannot be less than 100. But who knows.... */ + if (unlikely(freq_step == 0)) + freq_step = 5; + + requested_freq[cpu] += freq_step; + if (requested_freq[cpu] > policy->max) + requested_freq[cpu] = policy->max; + + __cpufreq_driver_target(policy, requested_freq[cpu], + CPUFREQ_RELATION_H); + down_skip[cpu] = 0; + this_dbs_info->prev_cpu_idle_down = total_idle_ticks; + return; + } + + /* Check for frequency decrease */ + down_skip[cpu]++; + if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) + return; + + total_idle_ticks = kstat_cpu(cpu).cpustat.idle + + kstat_cpu(cpu).cpustat.iowait; + /* consider 'nice' too? */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(cpu).cpustat.nice; + idle_ticks = total_idle_ticks - + this_dbs_info->prev_cpu_idle_down; + this_dbs_info->prev_cpu_idle_down = total_idle_ticks; + + for_each_cpu_mask(j, policy->cpus) { + unsigned int tmp_idle_ticks; + struct cpu_dbs_info_s *j_dbs_info; + + if (j == cpu) + continue; + + j_dbs_info = &per_cpu(cpu_dbs_info, j); + /* Check for frequency increase */ + total_idle_ticks = kstat_cpu(j).cpustat.idle + + kstat_cpu(j).cpustat.iowait; + /* consider 'nice' too? */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(j).cpustat.nice; + tmp_idle_ticks = total_idle_ticks - + j_dbs_info->prev_cpu_idle_down; + j_dbs_info->prev_cpu_idle_down = total_idle_ticks; + + if (tmp_idle_ticks < idle_ticks) + idle_ticks = tmp_idle_ticks; + } + + /* Scale idle ticks by 100 and compare with up and down ticks */ + idle_ticks *= 100; + down_skip[cpu] = 0; + + freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * + dbs_tuners_ins.sampling_down_factor; + down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * + usecs_to_jiffies(freq_down_sampling_rate); + + if (idle_ticks > down_idle_ticks ) { + /* if we are already at the lowest speed then break out early + * or if we 'cannot' reduce the speed as the user might want + * freq_step to be zero */ + if (requested_freq[cpu] == policy->min + || dbs_tuners_ins.freq_step == 0) + return; + + freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; + + /* max freq cannot be less than 100. But who knows.... */ + if (unlikely(freq_step == 0)) + freq_step = 5; + + requested_freq[cpu] -= freq_step; + if (requested_freq[cpu] < policy->min) + requested_freq[cpu] = policy->min; + + __cpufreq_driver_target(policy, + requested_freq[cpu], + CPUFREQ_RELATION_H); + return; + } +} + +static void do_dbs_timer(void *data) +{ + int i; + down(&dbs_sem); + for_each_online_cpu(i) + dbs_check_cpu(i); + schedule_delayed_work(&dbs_work, + usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); + up(&dbs_sem); +} + +static inline void dbs_timer_init(void) +{ + INIT_WORK(&dbs_work, do_dbs_timer, NULL); + schedule_delayed_work(&dbs_work, + usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); + return; +} + +static inline void dbs_timer_exit(void) +{ + cancel_delayed_work(&dbs_work); + return; +} + +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + struct cpu_dbs_info_s *this_dbs_info; + unsigned int j; + + this_dbs_info = &per_cpu(cpu_dbs_info, cpu); + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || + (!policy->cur)) + return -EINVAL; + + if (policy->cpuinfo.transition_latency > + (TRANSITION_LATENCY_LIMIT * 1000)) + return -EINVAL; + if (this_dbs_info->enable) /* Already enabled */ + break; + + down(&dbs_sem); + for_each_cpu_mask(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(cpu_dbs_info, j); + j_dbs_info->cur_policy = policy; + + j_dbs_info->prev_cpu_idle_up = + kstat_cpu(j).cpustat.idle + + kstat_cpu(j).cpustat.iowait + + ( !dbs_tuners_ins.ignore_nice + ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_down + = j_dbs_info->prev_cpu_idle_up; + } + this_dbs_info->enable = 1; + sysfs_create_group(&policy->kobj, &dbs_attr_group); + dbs_enable++; + /* + * Start the timerschedule work, when this governor + * is used for first time + */ + if (dbs_enable == 1) { + unsigned int latency; + /* policy latency is in nS. Convert it to uS first */ + + latency = policy->cpuinfo.transition_latency; + if (latency < 1000) + latency = 1000; + + def_sampling_rate = (latency / 1000) * + DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; + dbs_tuners_ins.sampling_rate = def_sampling_rate; + dbs_tuners_ins.ignore_nice = 0; + dbs_tuners_ins.freq_step = 5; + + dbs_timer_init(); + } + + up(&dbs_sem); + break; + + case CPUFREQ_GOV_STOP: + down(&dbs_sem); + this_dbs_info->enable = 0; + sysfs_remove_group(&policy->kobj, &dbs_attr_group); + dbs_enable--; + /* + * Stop the timerschedule work, when this governor + * is used for first time + */ + if (dbs_enable == 0) + dbs_timer_exit(); + + up(&dbs_sem); + + break; + + case CPUFREQ_GOV_LIMITS: + down(&dbs_sem); + if (policy->max < this_dbs_info->cur_policy->cur) + __cpufreq_driver_target( + this_dbs_info->cur_policy, + policy->max, CPUFREQ_RELATION_H); + else if (policy->min > this_dbs_info->cur_policy->cur) + __cpufreq_driver_target( + this_dbs_info->cur_policy, + policy->min, CPUFREQ_RELATION_L); + up(&dbs_sem); + break; + } + return 0; +} + +static struct cpufreq_governor cpufreq_gov_dbs = { + .name = "conservative", + .governor = cpufreq_governor_dbs, + .owner = THIS_MODULE, +}; + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_dbs); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + /* Make sure that the scheduled work is indeed not running */ + flush_scheduled_work(); + + cpufreq_unregister_governor(&cpufreq_gov_dbs); +} + + +MODULE_AUTHOR ("Alexander Clouter "); +MODULE_DESCRIPTION ("'cpufreq_conservative' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors " + "optimised for use in a battery environment"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_gov_dbs_init); +module_exit(cpufreq_gov_dbs_exit); -- cgit v1.1 From 3d5ee9e55d13de28d2fa58d6e13f2e4d3a5f8b1a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:47 -0700 Subject: [CPUFREQ] Add support to cpufreq_ondemand to ignore 'nice' cpu time Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 66 +++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 84c6588..7d72443 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -78,6 +78,7 @@ struct dbs_tuners { unsigned int sampling_down_factor; unsigned int up_threshold; unsigned int down_threshold; + unsigned int ignore_nice; }; static struct dbs_tuners dbs_tuners_ins = { @@ -115,6 +116,7 @@ show_one(sampling_rate, sampling_rate); show_one(sampling_down_factor, sampling_down_factor); show_one(up_threshold, up_threshold); show_one(down_threshold, down_threshold); +show_one(ignore_nice, ignore_nice); static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) @@ -193,6 +195,46 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, return count; } +static ssize_t store_ignore_nice(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + unsigned int j; + + ret = sscanf (buf, "%u", &input); + if ( ret != 1 ) + return -EINVAL; + + if ( input > 1 ) + input = 1; + + down(&dbs_sem); + if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ + up(&dbs_sem); + return count; + } + dbs_tuners_ins.ignore_nice = input; + + /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */ + for_each_cpu_mask(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(cpu_dbs_info, j); + j_dbs_info->cur_policy = policy; + + j_dbs_info->prev_cpu_idle_up = + kstat_cpu(j).cpustat.idle + + kstat_cpu(j).cpustat.iowait + + ( !dbs_tuners_ins.ignore_nice + ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; + } + up(&dbs_sem); + + return count; +} + #define define_one_rw(_name) \ static struct freq_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) @@ -201,6 +243,7 @@ define_one_rw(sampling_rate); define_one_rw(sampling_down_factor); define_one_rw(up_threshold); define_one_rw(down_threshold); +define_one_rw(ignore_nice); static struct attribute * dbs_attributes[] = { &sampling_rate_max.attr, @@ -209,6 +252,7 @@ static struct attribute * dbs_attributes[] = { &sampling_down_factor.attr, &up_threshold.attr, &down_threshold.attr, + &ignore_nice.attr, NULL }; @@ -253,6 +297,9 @@ static void dbs_check_cpu(int cpu) /* Check for frequency increase */ total_idle_ticks = kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait; + /* consider 'nice' tasks as 'idle' time too if required */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(cpu).cpustat.nice; idle_ticks = total_idle_ticks - this_dbs_info->prev_cpu_idle_up; this_dbs_info->prev_cpu_idle_up = total_idle_ticks; @@ -269,6 +316,9 @@ static void dbs_check_cpu(int cpu) /* Check for frequency increase */ total_idle_ticks = kstat_cpu(j).cpustat.idle + kstat_cpu(j).cpustat.iowait; + /* consider 'nice' too? */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(j).cpustat.nice; tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_up; j_dbs_info->prev_cpu_idle_up = total_idle_ticks; @@ -297,6 +347,9 @@ static void dbs_check_cpu(int cpu) total_idle_ticks = kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait; + /* consider 'nice' too? */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(cpu).cpustat.nice; idle_ticks = total_idle_ticks - this_dbs_info->prev_cpu_idle_down; this_dbs_info->prev_cpu_idle_down = total_idle_ticks; @@ -312,6 +365,9 @@ static void dbs_check_cpu(int cpu) /* Check for frequency increase */ total_idle_ticks = kstat_cpu(j).cpustat.idle + kstat_cpu(j).cpustat.iowait; + /* consider 'nice' too? */ + if (dbs_tuners_ins.ignore_nice == 0) + total_idle_ticks += kstat_cpu(j).cpustat.nice; tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_down; j_dbs_info->prev_cpu_idle_down = total_idle_ticks; @@ -397,10 +453,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info->prev_cpu_idle_up = kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait; - j_dbs_info->prev_cpu_idle_down = - kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait; + kstat_cpu(j).cpustat.iowait + + ( !dbs_tuners_ins.ignore_nice + ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_down + = j_dbs_info->prev_cpu_idle_up; } this_dbs_info->enable = 1; sysfs_create_group(&policy->kobj, &dbs_attr_group); @@ -420,6 +477,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, def_sampling_rate = (latency / 1000) * DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; dbs_tuners_ins.sampling_rate = def_sampling_rate; + dbs_tuners_ins.ignore_nice = 0; dbs_timer_init(); } -- cgit v1.1 From c11420a616039e2181e4ecbffb4d125d39e6877d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:48 -0700 Subject: [CPUFREQ] Prevents un-necessary cpufreq changes if we are already at min/max Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 7d72443..6dc8380 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -333,6 +333,10 @@ static void dbs_check_cpu(int cpu) usecs_to_jiffies(dbs_tuners_ins.sampling_rate); if (idle_ticks < up_idle_ticks) { + /* if we are already at full speed then break out early */ + if (policy->cur == policy->max) + return; + __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); down_skip[cpu] = 0; @@ -386,6 +390,10 @@ static void dbs_check_cpu(int cpu) usecs_to_jiffies(freq_down_sampling_rate); if (idle_ticks > down_idle_ticks ) { + /* if we are already at the lowest speed then break out early */ + if (policy->cur == policy->min) + return; + freq_down_step = (5 * policy->max) / 100; /* max freq cannot be less than 100. But who knows.... */ -- cgit v1.1 From 1206aaac285904e3e3995eecbf4129b6555a8973 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:48 -0700 Subject: [CPUFREQ] Allow ondemand stepping to be changed by user. Adds support so that the cpufreq change stepping is no longer fixed at 5% and can be changed dynamically by the user Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 42 ++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 6dc8380..0565916 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -79,6 +79,7 @@ struct dbs_tuners { unsigned int up_threshold; unsigned int down_threshold; unsigned int ignore_nice; + unsigned int freq_step; }; static struct dbs_tuners dbs_tuners_ins = { @@ -117,6 +118,7 @@ show_one(sampling_down_factor, sampling_down_factor); show_one(up_threshold, up_threshold); show_one(down_threshold, down_threshold); show_one(ignore_nice, ignore_nice); +show_one(freq_step, freq_step); static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) @@ -235,6 +237,29 @@ static ssize_t store_ignore_nice(struct cpufreq_policy *policy, return count; } +static ssize_t store_freq_step(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf (buf, "%u", &input); + + if ( ret != 1 ) + return -EINVAL; + + if ( input > 100 ) + input = 100; + + /* no need to test here if freq_step is zero as the user might actually + * want this, they would be crazy though :) */ + down(&dbs_sem); + dbs_tuners_ins.freq_step = input; + up(&dbs_sem); + + return count; +} + #define define_one_rw(_name) \ static struct freq_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) @@ -244,6 +269,7 @@ define_one_rw(sampling_down_factor); define_one_rw(up_threshold); define_one_rw(down_threshold); define_one_rw(ignore_nice); +define_one_rw(freq_step); static struct attribute * dbs_attributes[] = { &sampling_rate_max.attr, @@ -253,6 +279,7 @@ static struct attribute * dbs_attributes[] = { &up_threshold.attr, &down_threshold.attr, &ignore_nice.attr, + &freq_step.attr, NULL }; @@ -291,7 +318,7 @@ static void dbs_check_cpu(int cpu) * * Any frequency increase takes it to the maximum frequency. * Frequency reduction happens at minimum steps of - * 5% of max_frequency + * 5% (default) of max_frequency */ /* Check for frequency increase */ @@ -390,18 +417,20 @@ static void dbs_check_cpu(int cpu) usecs_to_jiffies(freq_down_sampling_rate); if (idle_ticks > down_idle_ticks ) { - /* if we are already at the lowest speed then break out early */ - if (policy->cur == policy->min) + /* if we are already at the lowest speed then break out early + * or if we 'cannot' reduce the speed as the user might want + * freq_step to be zero */ + if (policy->cur == policy->min || dbs_tuners_ins.freq_step == 0) return; - - freq_down_step = (5 * policy->max) / 100; + + freq_down_step = (dbs_tuners_ins.freq_step * policy->max) / 100; /* max freq cannot be less than 100. But who knows.... */ if (unlikely(freq_down_step == 0)) freq_down_step = 5; __cpufreq_driver_target(policy, - policy->cur - freq_down_step, + policy->cur - freq_down_step, CPUFREQ_RELATION_H); return; } @@ -486,6 +515,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_tuners_ins.ignore_nice = 0; + dbs_tuners_ins.freq_step = 5; dbs_timer_init(); } -- cgit v1.1 From dac1c1a56279b4545a822ec7bc770003c233e546 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:49 -0700 Subject: [CPUFREQ] ondemand,conservative minor bug-fix and cleanup [PATCH] [1/5] ondemand,conservative minor bug-fix and cleanup Attached patch fixes some minor issues with Alexander's patch and related cleanup in both ondemand and conservative governor. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 53 +++++++++++-------------------- drivers/cpufreq/cpufreq_ondemand.c | 58 ++++++++++++---------------------- 2 files changed, 38 insertions(+), 73 deletions(-) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index dd2f5b2..3082a3f 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -89,6 +89,15 @@ static struct dbs_tuners dbs_tuners_ins = { .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, }; +static inline unsigned int get_cpu_idle_time(unsigned int cpu) +{ + return kstat_cpu(cpu).cpustat.idle + + kstat_cpu(cpu).cpustat.iowait + + ( !dbs_tuners_ins.ignore_nice ? + kstat_cpu(cpu).cpustat.nice : + 0); +} + /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { @@ -221,16 +230,10 @@ static ssize_t store_ignore_nice(struct cpufreq_policy *policy, dbs_tuners_ins.ignore_nice = input; /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */ - for_each_cpu_mask(j, policy->cpus) { + for_each_online_cpu(j) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); - j_dbs_info->cur_policy = policy; - - j_dbs_info->prev_cpu_idle_up = - kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait + - ( !dbs_tuners_ins.ignore_nice - ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; } up(&dbs_sem); @@ -335,11 +338,7 @@ static void dbs_check_cpu(int cpu) */ /* Check for frequency increase */ - total_idle_ticks = kstat_cpu(cpu).cpustat.idle + - kstat_cpu(cpu).cpustat.iowait; - /* consider 'nice' tasks as 'idle' time too if required */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(cpu).cpustat.nice; + total_idle_ticks = get_cpu_idle_time(cpu); idle_ticks = total_idle_ticks - this_dbs_info->prev_cpu_idle_up; this_dbs_info->prev_cpu_idle_up = total_idle_ticks; @@ -354,11 +353,7 @@ static void dbs_check_cpu(int cpu) j_dbs_info = &per_cpu(cpu_dbs_info, j); /* Check for frequency increase */ - total_idle_ticks = kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait; - /* consider 'nice' too? */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(j).cpustat.nice; + total_idle_ticks = get_cpu_idle_time(j); tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_up; j_dbs_info->prev_cpu_idle_up = total_idle_ticks; @@ -373,6 +368,8 @@ static void dbs_check_cpu(int cpu) usecs_to_jiffies(dbs_tuners_ins.sampling_rate); if (idle_ticks < up_idle_ticks) { + down_skip[cpu] = 0; + this_dbs_info->prev_cpu_idle_down = total_idle_ticks; /* if we are already at full speed then break out early */ if (requested_freq[cpu] == policy->max) return; @@ -389,8 +386,6 @@ static void dbs_check_cpu(int cpu) __cpufreq_driver_target(policy, requested_freq[cpu], CPUFREQ_RELATION_H); - down_skip[cpu] = 0; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; return; } @@ -399,11 +394,7 @@ static void dbs_check_cpu(int cpu) if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) return; - total_idle_ticks = kstat_cpu(cpu).cpustat.idle + - kstat_cpu(cpu).cpustat.iowait; - /* consider 'nice' too? */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(cpu).cpustat.nice; + total_idle_ticks = this_dbs_info->prev_cpu_idle_up; idle_ticks = total_idle_ticks - this_dbs_info->prev_cpu_idle_down; this_dbs_info->prev_cpu_idle_down = total_idle_ticks; @@ -417,11 +408,7 @@ static void dbs_check_cpu(int cpu) j_dbs_info = &per_cpu(cpu_dbs_info, j); /* Check for frequency increase */ - total_idle_ticks = kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait; - /* consider 'nice' too? */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(j).cpustat.nice; + total_idle_ticks = j_dbs_info->prev_cpu_idle_up; tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_down; j_dbs_info->prev_cpu_idle_down = total_idle_ticks; @@ -516,11 +503,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - j_dbs_info->prev_cpu_idle_up = - kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait + - ( !dbs_tuners_ins.ignore_nice - ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; } diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 0565916..26cf54b 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -88,6 +88,15 @@ static struct dbs_tuners dbs_tuners_ins = { .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, }; +static inline unsigned int get_cpu_idle_time(unsigned int cpu) +{ + return kstat_cpu(cpu).cpustat.idle + + kstat_cpu(cpu).cpustat.iowait + + ( !dbs_tuners_ins.ignore_nice ? + kstat_cpu(cpu).cpustat.nice : + 0); +} + /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { @@ -220,16 +229,10 @@ static ssize_t store_ignore_nice(struct cpufreq_policy *policy, dbs_tuners_ins.ignore_nice = input; /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */ - for_each_cpu_mask(j, policy->cpus) { + for_each_online_cpu(j) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); - j_dbs_info->cur_policy = policy; - - j_dbs_info->prev_cpu_idle_up = - kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait + - ( !dbs_tuners_ins.ignore_nice - ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; } up(&dbs_sem); @@ -322,15 +325,10 @@ static void dbs_check_cpu(int cpu) */ /* Check for frequency increase */ - total_idle_ticks = kstat_cpu(cpu).cpustat.idle + - kstat_cpu(cpu).cpustat.iowait; - /* consider 'nice' tasks as 'idle' time too if required */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(cpu).cpustat.nice; + total_idle_ticks = get_cpu_idle_time(cpu); idle_ticks = total_idle_ticks - this_dbs_info->prev_cpu_idle_up; this_dbs_info->prev_cpu_idle_up = total_idle_ticks; - for_each_cpu_mask(j, policy->cpus) { unsigned int tmp_idle_ticks; @@ -341,11 +339,7 @@ static void dbs_check_cpu(int cpu) j_dbs_info = &per_cpu(cpu_dbs_info, j); /* Check for frequency increase */ - total_idle_ticks = kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait; - /* consider 'nice' too? */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(j).cpustat.nice; + total_idle_ticks = get_cpu_idle_time(j); tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_up; j_dbs_info->prev_cpu_idle_up = total_idle_ticks; @@ -360,14 +354,14 @@ static void dbs_check_cpu(int cpu) usecs_to_jiffies(dbs_tuners_ins.sampling_rate); if (idle_ticks < up_idle_ticks) { + down_skip[cpu] = 0; + this_dbs_info->prev_cpu_idle_down = total_idle_ticks; /* if we are already at full speed then break out early */ if (policy->cur == policy->max) return; __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - down_skip[cpu] = 0; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; return; } @@ -376,11 +370,7 @@ static void dbs_check_cpu(int cpu) if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) return; - total_idle_ticks = kstat_cpu(cpu).cpustat.idle + - kstat_cpu(cpu).cpustat.iowait; - /* consider 'nice' too? */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(cpu).cpustat.nice; + total_idle_ticks = this_dbs_info->prev_cpu_idle_up; idle_ticks = total_idle_ticks - this_dbs_info->prev_cpu_idle_down; this_dbs_info->prev_cpu_idle_down = total_idle_ticks; @@ -393,12 +383,8 @@ static void dbs_check_cpu(int cpu) continue; j_dbs_info = &per_cpu(cpu_dbs_info, j); - /* Check for frequency increase */ - total_idle_ticks = kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait; - /* consider 'nice' too? */ - if (dbs_tuners_ins.ignore_nice == 0) - total_idle_ticks += kstat_cpu(j).cpustat.nice; + /* Check for frequency decrease */ + total_idle_ticks = j_dbs_info->prev_cpu_idle_up; tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_down; j_dbs_info->prev_cpu_idle_down = total_idle_ticks; @@ -414,7 +400,7 @@ static void dbs_check_cpu(int cpu) freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * dbs_tuners_ins.sampling_down_factor; down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * - usecs_to_jiffies(freq_down_sampling_rate); + usecs_to_jiffies(freq_down_sampling_rate); if (idle_ticks > down_idle_ticks ) { /* if we are already at the lowest speed then break out early @@ -488,11 +474,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - j_dbs_info->prev_cpu_idle_up = - kstat_cpu(j).cpustat.idle + - kstat_cpu(j).cpustat.iowait + - ( !dbs_tuners_ins.ignore_nice - ? kstat_cpu(j).cpustat.nice : 0 ); + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; } -- cgit v1.1 From 790d76fa979f55bfc49a6901bb911778949b582d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:49 -0700 Subject: [CPUFREQ] ondemand,conservative governor store the idle ticks for all cpus [PATCH] [2/5] ondemand,conservative governor store the idle ticks for all cpus Ondemand, conservative governor did not store prev_cpu_idle_up into prev_cpu_idle_down for other CPUs than the current CPU. Signed-off-by: Eric Piel Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 8 +++++++- drivers/cpufreq/cpufreq_ondemand.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 3082a3f..c503ec1 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -369,7 +369,13 @@ static void dbs_check_cpu(int cpu) if (idle_ticks < up_idle_ticks) { down_skip[cpu] = 0; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; + for_each_cpu_mask(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + + j_dbs_info = &per_cpu(cpu_dbs_info, j); + j_dbs_info->prev_cpu_idle_down = + j_dbs_info->prev_cpu_idle_up; + } /* if we are already at full speed then break out early */ if (requested_freq[cpu] == policy->max) return; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 26cf54b..f239545 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -355,7 +355,13 @@ static void dbs_check_cpu(int cpu) if (idle_ticks < up_idle_ticks) { down_skip[cpu] = 0; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; + for_each_cpu_mask(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + + j_dbs_info = &per_cpu(cpu_dbs_info, j); + j_dbs_info->prev_cpu_idle_down = + j_dbs_info->prev_cpu_idle_up; + } /* if we are already at full speed then break out early */ if (policy->cur == policy->max) return; -- cgit v1.1 From 9c7d269b9b05440dd0fe92d96f4e5d7e73dd7238 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:49 -0700 Subject: [CPUFREQ] ondemand,conservative governor idle_tick clean-up [PATCH] [3/5] ondemand,conservative governor idle_tick clean-up Ondemand and conservative governor clean-up, it factorises the idle ticks measurement. Signed-off-by: Eric Piel Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 26 +++++--------------------- drivers/cpufreq/cpufreq_ondemand.c | 26 +++++--------------------- 2 files changed, 10 insertions(+), 42 deletions(-) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index c503ec1..e1df376 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -297,7 +297,6 @@ static struct attribute_group dbs_attr_group = { static void dbs_check_cpu(int cpu) { unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; - unsigned int total_idle_ticks; unsigned int freq_step; unsigned int freq_down_sampling_rate; static int down_skip[NR_CPUS]; @@ -338,19 +337,12 @@ static void dbs_check_cpu(int cpu) */ /* Check for frequency increase */ - total_idle_ticks = get_cpu_idle_time(cpu); - idle_ticks = total_idle_ticks - - this_dbs_info->prev_cpu_idle_up; - this_dbs_info->prev_cpu_idle_up = total_idle_ticks; - + idle_ticks = UINT_MAX; for_each_cpu_mask(j, policy->cpus) { - unsigned int tmp_idle_ticks; + unsigned int tmp_idle_ticks, total_idle_ticks; struct cpu_dbs_info_s *j_dbs_info; - if (j == cpu) - continue; - j_dbs_info = &per_cpu(cpu_dbs_info, j); /* Check for frequency increase */ total_idle_ticks = get_cpu_idle_time(j); @@ -400,20 +392,12 @@ static void dbs_check_cpu(int cpu) if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) return; - total_idle_ticks = this_dbs_info->prev_cpu_idle_up; - idle_ticks = total_idle_ticks - - this_dbs_info->prev_cpu_idle_down; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; - + idle_ticks = UINT_MAX; for_each_cpu_mask(j, policy->cpus) { - unsigned int tmp_idle_ticks; + unsigned int tmp_idle_ticks, total_idle_ticks; struct cpu_dbs_info_s *j_dbs_info; - if (j == cpu) - continue; - j_dbs_info = &per_cpu(cpu_dbs_info, j); - /* Check for frequency increase */ total_idle_ticks = j_dbs_info->prev_cpu_idle_up; tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_down; @@ -432,7 +416,7 @@ static void dbs_check_cpu(int cpu) down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * usecs_to_jiffies(freq_down_sampling_rate); - if (idle_ticks > down_idle_ticks ) { + if (idle_ticks > down_idle_ticks) { /* if we are already at the lowest speed then break out early * or if we 'cannot' reduce the speed as the user might want * freq_step to be zero */ diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index f239545..0482bd4 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -296,7 +296,6 @@ static struct attribute_group dbs_attr_group = { static void dbs_check_cpu(int cpu) { unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; - unsigned int total_idle_ticks; unsigned int freq_down_step; unsigned int freq_down_sampling_rate; static int down_skip[NR_CPUS]; @@ -325,20 +324,12 @@ static void dbs_check_cpu(int cpu) */ /* Check for frequency increase */ - total_idle_ticks = get_cpu_idle_time(cpu); - idle_ticks = total_idle_ticks - - this_dbs_info->prev_cpu_idle_up; - this_dbs_info->prev_cpu_idle_up = total_idle_ticks; - + idle_ticks = UINT_MAX; for_each_cpu_mask(j, policy->cpus) { - unsigned int tmp_idle_ticks; + unsigned int tmp_idle_ticks, total_idle_ticks; struct cpu_dbs_info_s *j_dbs_info; - if (j == cpu) - continue; - j_dbs_info = &per_cpu(cpu_dbs_info, j); - /* Check for frequency increase */ total_idle_ticks = get_cpu_idle_time(j); tmp_idle_ticks = total_idle_ticks - j_dbs_info->prev_cpu_idle_up; @@ -376,18 +367,11 @@ static void dbs_check_cpu(int cpu) if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) return; - total_idle_ticks = this_dbs_info->prev_cpu_idle_up; - idle_ticks = total_idle_ticks - - this_dbs_info->prev_cpu_idle_down; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; - + idle_ticks = UINT_MAX; for_each_cpu_mask(j, policy->cpus) { - unsigned int tmp_idle_ticks; + unsigned int tmp_idle_ticks, total_idle_ticks; struct cpu_dbs_info_s *j_dbs_info; - if (j == cpu) - continue; - j_dbs_info = &per_cpu(cpu_dbs_info, j); /* Check for frequency decrease */ total_idle_ticks = j_dbs_info->prev_cpu_idle_up; @@ -408,7 +392,7 @@ static void dbs_check_cpu(int cpu) down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * usecs_to_jiffies(freq_down_sampling_rate); - if (idle_ticks > down_idle_ticks ) { + if (idle_ticks > down_idle_ticks) { /* if we are already at the lowest speed then break out early * or if we 'cannot' reduce the speed as the user might want * freq_step to be zero */ -- cgit v1.1 From c29f1403098135bdef75b190a5037db514701031 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:50 -0700 Subject: [CPUFREQ] ondemand governor automatic downscaling [PATCH] [4/5] ondemand governor automatic downscaling Here is a change of policy for the ondemand governor. The modification concerns the frequency downscaling. Instead of decreasing to a lower frequency when the CPU usage is under 20%, this new policy automatically scales to the optimal frequency. The optimal frequency being the lowest frequency which provides enough power to not trigger the upscaling policy. Signed-off-by: Eric Piel Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 117 ++++++++----------------------------- 1 file changed, 25 insertions(+), 92 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 0482bd4..8bc38ab 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -34,13 +34,9 @@ */ #define DEF_FREQUENCY_UP_THRESHOLD (80) -#define MIN_FREQUENCY_UP_THRESHOLD (0) +#define MIN_FREQUENCY_UP_THRESHOLD (11) #define MAX_FREQUENCY_UP_THRESHOLD (100) -#define DEF_FREQUENCY_DOWN_THRESHOLD (20) -#define MIN_FREQUENCY_DOWN_THRESHOLD (0) -#define MAX_FREQUENCY_DOWN_THRESHOLD (100) - /* * The polling frequency of this governor depends on the capability of * the processor. Default polling frequency is 1000 times the transition @@ -77,14 +73,11 @@ struct dbs_tuners { unsigned int sampling_rate; unsigned int sampling_down_factor; unsigned int up_threshold; - unsigned int down_threshold; unsigned int ignore_nice; - unsigned int freq_step; }; static struct dbs_tuners dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, - .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, }; @@ -125,9 +118,7 @@ static ssize_t show_##file_name \ show_one(sampling_rate, sampling_rate); show_one(sampling_down_factor, sampling_down_factor); show_one(up_threshold, up_threshold); -show_one(down_threshold, down_threshold); show_one(ignore_nice, ignore_nice); -show_one(freq_step, freq_step); static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) @@ -173,8 +164,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, down(&dbs_sem); if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || - input < MIN_FREQUENCY_UP_THRESHOLD || - input <= dbs_tuners_ins.down_threshold) { + input < MIN_FREQUENCY_UP_THRESHOLD) { up(&dbs_sem); return -EINVAL; } @@ -185,27 +175,6 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_down_threshold(struct cpufreq_policy *unused, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - ret = sscanf (buf, "%u", &input); - - down(&dbs_sem); - if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || - input < MIN_FREQUENCY_DOWN_THRESHOLD || - input >= dbs_tuners_ins.up_threshold) { - up(&dbs_sem); - return -EINVAL; - } - - dbs_tuners_ins.down_threshold = input; - up(&dbs_sem); - - return count; -} - static ssize_t store_ignore_nice(struct cpufreq_policy *policy, const char *buf, size_t count) { @@ -240,29 +209,6 @@ static ssize_t store_ignore_nice(struct cpufreq_policy *policy, return count; } -static ssize_t store_freq_step(struct cpufreq_policy *policy, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - - ret = sscanf (buf, "%u", &input); - - if ( ret != 1 ) - return -EINVAL; - - if ( input > 100 ) - input = 100; - - /* no need to test here if freq_step is zero as the user might actually - * want this, they would be crazy though :) */ - down(&dbs_sem); - dbs_tuners_ins.freq_step = input; - up(&dbs_sem); - - return count; -} - #define define_one_rw(_name) \ static struct freq_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) @@ -270,9 +216,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name) define_one_rw(sampling_rate); define_one_rw(sampling_down_factor); define_one_rw(up_threshold); -define_one_rw(down_threshold); define_one_rw(ignore_nice); -define_one_rw(freq_step); static struct attribute * dbs_attributes[] = { &sampling_rate_max.attr, @@ -280,9 +224,7 @@ static struct attribute * dbs_attributes[] = { &sampling_rate.attr, &sampling_down_factor.attr, &up_threshold.attr, - &down_threshold.attr, &ignore_nice.attr, - &freq_step.attr, NULL }; @@ -295,8 +237,8 @@ static struct attribute_group dbs_attr_group = { static void dbs_check_cpu(int cpu) { - unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; - unsigned int freq_down_step; + unsigned int idle_ticks, up_idle_ticks, total_ticks; + unsigned int freq_next; unsigned int freq_down_sampling_rate; static int down_skip[NR_CPUS]; struct cpu_dbs_info_s *this_dbs_info; @@ -310,17 +252,15 @@ static void dbs_check_cpu(int cpu) policy = this_dbs_info->cur_policy; /* - * The default safe range is 20% to 80% - * Every sampling_rate, we check - * - If current idle time is less than 20%, then we try to - * increase frequency - * Every sampling_rate*sampling_down_factor, we check - * - If current idle time is more than 80%, then we try to - * decrease frequency + * Every sampling_rate, we check, if current idle time is less + * than 20% (default), then we try to increase frequency + * Every sampling_rate*sampling_down_factor, we look for a the lowest + * frequency which can sustain the load while keeping idle time over + * 30%. If such a frequency exist, we try to decrease to this frequency. * * Any frequency increase takes it to the maximum frequency. * Frequency reduction happens at minimum steps of - * 5% (default) of max_frequency + * 5% (default) of current frequency */ /* Check for frequency increase */ @@ -383,33 +323,27 @@ static void dbs_check_cpu(int cpu) idle_ticks = tmp_idle_ticks; } - /* Scale idle ticks by 100 and compare with up and down ticks */ - idle_ticks *= 100; down_skip[cpu] = 0; + /* if we cannot reduce the frequency anymore, break out early */ + if (policy->cur == policy->min) + return; + /* Compute how many ticks there are between two measurements */ freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * dbs_tuners_ins.sampling_down_factor; - down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * - usecs_to_jiffies(freq_down_sampling_rate); - - if (idle_ticks > down_idle_ticks) { - /* if we are already at the lowest speed then break out early - * or if we 'cannot' reduce the speed as the user might want - * freq_step to be zero */ - if (policy->cur == policy->min || dbs_tuners_ins.freq_step == 0) - return; + total_ticks = usecs_to_jiffies(freq_down_sampling_rate); - freq_down_step = (dbs_tuners_ins.freq_step * policy->max) / 100; - - /* max freq cannot be less than 100. But who knows.... */ - if (unlikely(freq_down_step == 0)) - freq_down_step = 5; + /* + * The optimal frequency is the frequency that is the lowest that + * can support the current CPU usage without triggering the up + * policy. To be safe, we focus 10 points under the threshold. + */ + freq_next = ((total_ticks - idle_ticks) * 100) / total_ticks; + freq_next = (freq_next * policy->cur) / + (dbs_tuners_ins.up_threshold - 10); - __cpufreq_driver_target(policy, - policy->cur - freq_down_step, - CPUFREQ_RELATION_H); - return; - } + if (freq_next <= ((policy->cur * 95) / 100)) + __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); } static void do_dbs_timer(void *data) @@ -487,7 +421,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_tuners_ins.ignore_nice = 0; - dbs_tuners_ins.freq_step = 5; dbs_timer_init(); } -- cgit v1.1 From e131832ca7d3a3e5f9c7624bb310a7747dc2b57c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:50 -0700 Subject: [CPUFREQ] ondemand governor default sampling downfactor as 1 [PATCH] [5/5] ondemand governor default sampling downfactor as 1 Make default sampling downfactor 1. This works better with earlier auto downscaling change in ondemand governor. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 8bc38ab..c1fc9c6 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -51,7 +51,8 @@ static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE (def_sampling_rate / 2) #define MAX_SAMPLING_RATE (500 * def_sampling_rate) #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) -#define DEF_SAMPLING_DOWN_FACTOR (10) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define MAX_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000) static void do_dbs_timer(void *data); @@ -129,6 +130,9 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, if (ret != 1 ) return -EINVAL; + if (input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + down(&dbs_sem); dbs_tuners_ins.sampling_down_factor = input; up(&dbs_sem); -- cgit v1.1 From 3be6a48f3c8df1b2fbbe57face95a03d167bda1b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:51 -0700 Subject: [CPUFREQ] longhaul - disable PCI mastering around transition. The spec states that we have to do this, which is *horrid*. Based on code from: Ken Staton Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 49 ++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index ab0f9f5..8ea545e 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul, unsigned int clock_ratio_index) { int version; + unsigned long flags; + struct pci_dev *dev; + int i; + u16 pci_cmd; + u16 cmd_state[64]; switch (cpu_model) { case CPU_EZRA_T: @@ -137,17 +143,52 @@ static void do_powersaver(union msr_longhaul *longhaul, longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; longhaul->bits.EnableSoftBusRatio = 1; longhaul->bits.RevisionKey = 0; - local_irq_disable(); - wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); + + preempt_disable(); + local_irq_save(flags); + + /* + * get current pci bus master state for all devices + * and clear bus master bit + */ + dev = NULL; + i = 0; + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (dev != NULL) { + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + cmd_state[i++] = pci_cmd; + pci_cmd &= ~PCI_COMMAND_MASTER; + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + } + } while (dev != NULL); + local_irq_enable(); + + __hlt(); + wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); __hlt(); + local_irq_disable(); + + /* restore pci bus master state for all devices */ + dev = NULL; + i = 0; + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (dev != NULL) { + pci_cmd = cmd_state[i++]; + pci_write_config_byte(dev, PCI_COMMAND, pci_cmd); + } + } while (dev != NULL); + local_irq_restore(flags); + preempt_enable(); + + /* disable bus ratio bit */ rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); longhaul->bits.EnableSoftBusRatio = 0; longhaul->bits.RevisionKey = version; - local_irq_disable(); wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); - local_irq_enable(); } /** -- cgit v1.1 From 1174631418fbb2c0c6946081b0b7d391f5d92861 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:51 -0700 Subject: [CPUFREQ] Longhaul: Magic timer frobbing. As mandated by the spec, disable timer around transitions. From code by : Ken Staton --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 8ea545e..48899f0 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -120,9 +120,10 @@ static int longhaul_get_cpu_mult(void) static void do_powersaver(union msr_longhaul *longhaul, unsigned int clock_ratio_index) { - int version; - unsigned long flags; struct pci_dev *dev; + unsigned long flags; + unsigned int tmp_mask; + int version; int i; u16 pci_cmd; u16 cmd_state[64]; @@ -163,6 +164,10 @@ static void do_powersaver(union msr_longhaul *longhaul, } } while (dev != NULL); + tmp_mask=inb(0x21); /* works on C3. save mask. */ + outb(0xFE,0x21); /* TMR0 only */ + outb(0xFF,0x80); /* delay */ + local_irq_enable(); __hlt(); @@ -171,6 +176,8 @@ static void do_powersaver(union msr_longhaul *longhaul, local_irq_disable(); + outb(tmp_mask,0x21); /* restore mask */ + /* restore pci bus master state for all devices */ dev = NULL; i = 0; -- cgit v1.1 From 6778bae0f2f1d4af1b8bb876c992ea094ee958b4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:51 -0700 Subject: [CPUFREQ] longhaul - adjust transition latency. From patch by: Ken Staton Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/longhaul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 48899f0..04e3563d 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -626,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) longhaul_setup_voltagescaling(); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cpuinfo.transition_latency = 200000; /* nsec */ policy->cur = calc_speed(longhaul_get_cpu_mult()); ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); -- cgit v1.1 From f94ea640a28230f82a4395c34e1290748a9f6586 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 May 2005 19:03:52 -0700 Subject: [CPUFREQ] Typos. cpfureq developers cant spel. Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index 8ba430a..d368b3f 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, if (!prev_speed) return -EIO; - dprintk("previous seped is %u\n", prev_speed); + dprintk("previous speed is %u\n", prev_speed); local_irq_save(flags); @@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, goto out; } - dprintk("low seped is %u\n", *low_speed); + dprintk("low speed is %u\n", *low_speed); /* switch to high state */ set_state(SPEEDSTEP_HIGH); @@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, goto out; } - dprintk("high seped is %u\n", *high_speed); + dprintk("high speed is %u\n", *high_speed); if (*low_speed == *high_speed) { ret = -ENODEV; -- cgit v1.1 From 58f1df25403988b73d7129fcd2c4d4c24017f1af Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 25 May 2005 14:46:50 -0700 Subject: [PATCH] cpufreq-stats driver updates Changes to the cpufreq stats driver: * Changes the way P-state transition table looks in /sysfs providing more clear output * Changes the time unit in the output from HZ to clock_t Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 47 ++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 2084593..741b6b1 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -19,6 +19,7 @@ #include #include #include +#include static spinlock_t cpufreq_stats_lock; @@ -29,20 +30,14 @@ static struct freq_attr _attr_##_name = {\ .show = _show,\ }; -static unsigned long -delta_time(unsigned long old, unsigned long new) -{ - return (old > new) ? (old - new): (new + ~old + 1); -} - struct cpufreq_stats { unsigned int cpu; unsigned int total_trans; - unsigned long long last_time; + unsigned long long last_time; unsigned int max_state; unsigned int state_num; unsigned int last_index; - unsigned long long *time_in_state; + cputime64_t *time_in_state; unsigned int *freq_table; #ifdef CONFIG_CPU_FREQ_STAT_DETAILS unsigned int *trans_table; @@ -60,12 +55,16 @@ static int cpufreq_stats_update (unsigned int cpu) { struct cpufreq_stats *stat; + unsigned long long cur_time; + + cur_time = get_jiffies_64(); spin_lock(&cpufreq_stats_lock); stat = cpufreq_stats_table[cpu]; if (stat->time_in_state) - stat->time_in_state[stat->last_index] += - delta_time(stat->last_time, jiffies); - stat->last_time = jiffies; + stat->time_in_state[stat->last_index] = + cputime64_add(stat->time_in_state[stat->last_index], + cputime_sub(cur_time, stat->last_time)); + stat->last_time = cur_time; spin_unlock(&cpufreq_stats_lock); return 0; } @@ -90,8 +89,8 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf) return 0; cpufreq_stats_update(stat->cpu); for (i = 0; i < stat->state_num; i++) { - len += sprintf(buf + len, "%u %llu\n", - stat->freq_table[i], stat->time_in_state[i]); + len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i], + (unsigned long long)cputime64_to_clock_t(stat->time_in_state[i])); } return len; } @@ -107,16 +106,30 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) if(!stat) return 0; cpufreq_stats_update(stat->cpu); + len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); + len += snprintf(buf + len, PAGE_SIZE - len, " : "); + for (i = 0; i < stat->state_num; i++) { + if (len >= PAGE_SIZE) + break; + len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", + stat->freq_table[i]); + } + if (len >= PAGE_SIZE) + return len; + + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + for (i = 0; i < stat->state_num; i++) { if (len >= PAGE_SIZE) break; - len += snprintf(buf + len, PAGE_SIZE - len, "%9u:\t", + + len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ", stat->freq_table[i]); for (j = 0; j < stat->state_num; j++) { if (len >= PAGE_SIZE) break; - len += snprintf(buf + len, PAGE_SIZE - len, "%u\t", + len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", stat->trans_table[i*stat->max_state+j]); } len += snprintf(buf + len, PAGE_SIZE - len, "\n"); @@ -197,7 +210,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, count++; } - alloc_size = count * sizeof(int) + count * sizeof(long long); + alloc_size = count * sizeof(int) + count * sizeof(cputime64_t); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS alloc_size += count * count * sizeof(int); @@ -224,7 +237,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, } stat->state_num = j; spin_lock(&cpufreq_stats_lock); - stat->last_time = jiffies; + stat->last_time = get_jiffies_64(); stat->last_index = freq_table_get_index(stat, policy->cur); spin_unlock(&cpufreq_stats_lock); cpufreq_cpu_put(data); -- cgit v1.1 From 21e3024cbddb712f6a078bf4132d7682d3c4e35e Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 25 May 2005 14:43:56 -0700 Subject: [PATCH] cpufreq-stats driver documentation Documentation for cpufreq stats. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- Documentation/cpu-freq/cpufreq-stats.txt | 128 +++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Documentation/cpu-freq/cpufreq-stats.txt diff --git a/Documentation/cpu-freq/cpufreq-stats.txt b/Documentation/cpu-freq/cpufreq-stats.txt new file mode 100644 index 0000000..e2d1e76 --- /dev/null +++ b/Documentation/cpu-freq/cpufreq-stats.txt @@ -0,0 +1,128 @@ + + CPU frequency and voltage scaling statictics in the Linux(TM) kernel + + + L i n u x c p u f r e q - s t a t s d r i v e r + + - information for users - + + + Venkatesh Pallipadi + +Contents +1. Introduction +2. Statistics Provided (with example) +3. Configuring cpufreq-stats + + +1. Introduction + +cpufreq-stats is a driver that provices CPU frequency statistics for each CPU. +This statistics is provided in /sysfs as a bunch of read_only interfaces. This +interface (when configured) will appear in a seperate directory under cpufreq +in /sysfs (/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU. +Various statistics will form read_only files under this directory. + +This driver is designed to be independent of any particular cpufreq_driver +that may be running on your CPU. So, it will work with any cpufreq_driver. + + +2. Statistics Provided (with example) + +cpufreq stats provides following statistics (explained in detail below). +- time_in_state +- total_trans +- trans_table + +All the statistics will be from the time the stats driver has been inserted +to the time when a read of a particular statistic is done. Obviously, stats +driver will not have any information about the the frequcny transitions before +the stats driver insertion. + +-------------------------------------------------------------------------------- +:/sys/devices/system/cpu/cpu0/cpufreq/stats # ls -l +total 0 +drwxr-xr-x 2 root root 0 May 14 16:06 . +drwxr-xr-x 3 root root 0 May 14 15:58 .. +-r--r--r-- 1 root root 4096 May 14 16:06 time_in_state +-r--r--r-- 1 root root 4096 May 14 16:06 total_trans +-r--r--r-- 1 root root 4096 May 14 16:06 trans_table +-------------------------------------------------------------------------------- + +- time_in_state +This gives the amount of time spent in each of the frequencies supported by +this CPU. The cat output will have "