http://linux.bkbits.net/linux-2.5 geert@linux-m68k.org[torvalds]|ChangeSet|20040620173930|01652 geert # This is a BitKeeper generated diff -Nru style patch. # # drivers/scsi/scsiiom.c # 2021/06/14 15:59:00-05:00 g.liakhovetski@gmx.de +1 -1 # tmscsim: 64-bit cleanup # # net/core/dev.c # 2004/06/17 12:11:17-07:00 davem@nuts.davemloft.net +2 -0 # [NET]: In unregister_netdevice(), do synchronize_net() before final dev_put(). # # This way we make sure that all destination cache updates # to remove references to this device are seen by entire # system before final destruction of the device. # # ChangeSet # 2004/06/20 10:39:30-07:00 geert@linux-m68k.org # [PATCH] m68k: I/O abstraction updates # # M68k I/O abstraction updates: # - Make I/O ports and addresses `unsigned long' # - Add casts to make operations warning-compatible with other archs # - Add {in,out}[wl]_p() and {in,out}l(), which are needed for some drivers # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # include/asm-m68k/io.h # 2004/04/12 04:56:00-07:00 geert@linux-m68k.org +32 -14 # m68k: I/O abstraction updates # # ChangeSet # 2004/06/20 10:39:19-07:00 geert@linux-m68k.org # [PATCH] m68k: atomic op fixups # # M68k: Add missing atomic operations (from Roman Zippel and me) and replace # `__inline__' by `inline' while we're at it. # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # include/asm-m68k/atomic.h # 2004/06/20 02:09:03-07:00 geert@linux-m68k.org +91 -7 # m68k: atomic op fixups # # ChangeSet # 2004/06/20 10:39:08-07:00 geert@linux-m68k.org # [PATCH] m68k: Mac IOP fix # # Mac IOP: Fix copy-and-paste bug (found by OPERA, reported by Zhenmin Li, # confirmed by Brad Boyer) # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # arch/m68k/mac/iop.c # 2004/05/26 05:49:09-07:00 geert@linux-m68k.org +1 -1 # m68k: Mac IOP fix # # ChangeSet # 2004/06/20 10:38:57-07:00 geert@linux-m68k.org # [PATCH] m68k: sparse infrastructure # # M68k: Make sparse work # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # arch/m68k/Makefile # 2004/06/20 01:49:05-07:00 geert@linux-m68k.org +2 -0 # m68k: sparse infrastructure # # ChangeSet # 2004/06/20 10:38:46-07:00 geert@linux-m68k.org # [PATCH] m68k: Mac Sonic Ethernet # # Mac Sonic Ethernet: Kill duplicate `MODULE_LICENSE("GPL");' (already defined in # included sonic.c) which causes a compile failure # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # drivers/net/macsonic.c # 2004/05/04 13:42:38-07:00 geert@linux-m68k.org +0 -1 # m68k: Mac Sonic Ethernet # # ChangeSet # 2004/06/20 10:38:35-07:00 geert@linux-m68k.org # [PATCH] affs remount fixes # # AFFS: Fix oops on write after remount (from Roman Zippel): # - Allocate/free bitmap as necessary # - Remove last uses of SF_READONLY # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # include/linux/affs_fs_sb.h # 2004/06/18 02:18:33-07:00 geert@linux-m68k.org +0 -1 # affs remount fixes # # include/linux/affs_fs.h # 2004/06/18 02:18:33-07:00 geert@linux-m68k.org +2 -1 # affs remount fixes # # fs/affs/super.c # 2004/06/18 02:17:49-07:00 geert@linux-m68k.org +12 -14 # affs remount fixes # # fs/affs/bitmap.c # 2004/06/18 02:17:49-07:00 geert@linux-m68k.org +21 -8 # affs remount fixes # # fs/affs/amigaffs.c # 2004/06/18 02:17:49-07:00 geert@linux-m68k.org +0 -1 # affs remount fixes # # ChangeSet # 2004/06/20 10:38:24-07:00 geert@linux-m68k.org # [PATCH] m68k: use set_page_count() # # M68k: From 2.6.7-rc1 on, it's no longer allowed to access page->count directly # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # arch/m68k/mm/memory.c # 2004/05/24 06:55:41-07:00 geert@linux-m68k.org +1 -1 # m68k: use set_page_count() # # ChangeSet # 2004/06/20 10:38:13-07:00 geert@linux-m68k.org # [PATCH] m68k: bus error handling # # M68k: Allow to catch a bus error via the exception mechanism (from Roman # Zippel) # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # arch/m68k/kernel/traps.c # 2004/05/23 01:55:54-07:00 geert@linux-m68k.org +4 -3 # m68k: bus error handling # # ChangeSet # 2004/06/20 10:38:02-07:00 geert@linux-m68k.org # [PATCH] m68k: new gcc optimizations # # M68k compiler updates from Roman Zippel: # - Fix various lvalue warnings from newer gcc # - Remove unnecessary volatile declarations # - Change some constraints from "a" to "m" to generate slightly better code # - Use "o" constraint for bitfield instructions # - Use generic bitmap functions for some of the ext2/minix bitmap functions # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # include/asm-m68k/string.h # 2004/05/23 01:56:37-07:00 geert@linux-m68k.org +8 -9 # m68k: new gcc optimizations # # include/asm-m68k/page.h # 2004/05/23 01:56:37-07:00 geert@linux-m68k.org +8 -10 # m68k: new gcc optimizations # # include/asm-m68k/bitops.h # 2004/05/23 10:50:20-07:00 geert@linux-m68k.org +54 -103 # m68k: new gcc optimizations # # include/asm-m68k/atomic.h # 2004/05/23 01:56:37-07:00 geert@linux-m68k.org +16 -12 # m68k: new gcc optimizations # # ChangeSet # 2004/06/20 10:37:51-07:00 geert@linux-m68k.org # [PATCH] m68k: handle new gcc's # # M68k: Fixes for when compiling with modern gcc (from Roman Zippel): # - Avoid warning 'use of memory input without lvalue in asm operand 0 is # deprecated' of newer gcc # - Replace some '%/' with offical '%%' to escape a '%' # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # include/asm-m68k/ucontext.h # 2004/05/23 01:56:37-07:00 geert@linux-m68k.org +2 -4 # m68k: handle new gcc's # # arch/m68k/kernel/signal.c # 2004/05/23 01:55:54-07:00 geert@linux-m68k.org +17 -17 # m68k: handle new gcc's # # ChangeSet # 2004/06/20 10:37:41-07:00 geert@linux-m68k.org # [PATCH] m68k: IFPSP060 update # # IFPSP060: Make sure that the destination address of a misaligned cas access is # properly mapped in, so the kernel won't oops in the emulation handler (from # Roman Zippel). # # Signed-off-by: Geert Uytterhoeven # Signed-off-by: Linus Torvalds # # arch/m68k/ifpsp060/iskeleton.S # 2004/05/23 01:55:54-07:00 geert@linux-m68k.org +47 -5 # m68k: IFPSP060 update # # ChangeSet # 2004/06/20 09:59:33-07:00 hirofumi@mail.parknet.co.jp # [PATCH] FAT: don't use "utf8" charset and NLS_DEFAULT # # Recently, some distributors have set "utf8" to NLS_DEFAULT, therefore, # FAT uses the "iocharset=utf8" as default. But, since "iocharset=utf8" # doesn't provide the function (lower <-> upper conversion) which FAT # needs, so FAT can't provide suitable behavior. # # This patch does: # # - doesn't recognize "utf8" as "iocharset" # - doesn't use NLS_DEFAULT as default "iocharset" # - instead of NLS_DEFAULT, adds FAT_DEFAULT_CODEPAGE and # FAT_DEFAULT_IOCHARSET # # NOTE: the following looks like buggy, so it's not recommended # # "codepage=437,iocharset=iso8859-1,utf8" # # however, some utf8 file name can handle. (in this case, it uses the # table of iso8859-1 for lower <-> upper conversion) # # # Sign-off-by: Jesse Barnes # Sign-off-by: OGAWA Hirofumi # Sign-off-by: Linus Torvalds # # fs/fat/inode.c # 2004/06/19 11:30:39-07:00 hirofumi@mail.parknet.co.jp +46 -42 # FAT: don't use "utf8" charset and NLS_DEFAULT # # fs/Kconfig # 2004/06/19 11:30:39-07:00 hirofumi@mail.parknet.co.jp +19 -0 # FAT: don't use "utf8" charset and NLS_DEFAULT # # ChangeSet # 2004/06/20 09:56:58-07:00 torvalds@ppc970.osdl.org # Follow 2.4.x semantics for in-kernel signal sending. # # kernel/signal.c # 2004/06/20 09:56:52-07:00 torvalds@ppc970.osdl.org +7 -0 # Follow 2.4.x semantics for in-kernel signal sending. # # ChangeSet # 2004/06/20 09:33:28-07:00 arjanv@redhat.com # [PATCH] fix amd64 boot breakage # # This fixes a bug that prevent my amd64 box from booting; # numa_default_policy was __init however it's called like this in # init/main.c: # # free_initmem(); # unlock_kernel(); # system_state = SYSTEM_RUNNING; # numa_default_policy(); # # # eg after free_initmem(). This resulted in it being reused/freed and that # gives a nasty oops. # # mm/mempolicy.c # 2004/06/20 02:29:33-07:00 arjanv@redhat.com +1 -1 # fix amd64 boot breakage # # ChangeSet # 2004/06/20 07:00:13-05:00 stevef@steveft21.ltcsamba # Do not kill cifsd thread until last smb session on tcp session is # SMBulogged off. Fixes umounting bug (pointed out by Nick Millington) # when multiple mounts with different userids are mounted to the same # server from the client. # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2004/06/20 06:59:52-05:00 stevef@steveft21.ltcsamba +18 -10 # Do not kill cifsd thread until last smb session on tcp session is # SMBulogged off. # # fs/cifs/cifssmb.c # 2004/06/20 06:59:51-05:00 stevef@steveft21.ltcsamba +1 -0 # return unique error, when last smb session on a tcp session is logged off. # # fs/cifs/CHANGES # 2004/06/20 06:59:51-05:00 stevef@steveft21.ltcsamba +3 -0 # update cifs change log # # fs/cifs/AUTHORS # 2004/06/20 06:59:51-05:00 stevef@steveft21.ltcsamba +1 -1 # update list of contributors of bug reports # # ChangeSet # 2004/06/19 17:45:27-04:00 ralf@linux-mips.org # [PATCH] hdlcdrv needs to stop queueing # # We better stop the queue in the close call. # # Signed-off-by: Ralf Baechle # # drivers/net/hamradio/hdlcdrv.c # 2004/05/10 10:13:02-04:00 ralf@linux-mips.org +2 -0 # hdlcdrv needs to stop queueing # # ChangeSet # 2004/06/19 17:45:19-04:00 ralf@linux-mips.org # [PATCH] Cosmetic cleanups to sb1250-mac.c # # Signed-off-by: Ralf Baechle # # drivers/net/sb1250-mac.c # 2004/06/09 08:33:56-04:00 ralf@linux-mips.org +2 -2 # Cosmetic cleanups to sb1250-mac.c # # ChangeSet # 2004/06/19 17:45:10-04:00 ralf@linux-mips.org # [PATCH] Reformat # # Pure microcosmetic. # # Signed-off-by: Ralf Baechle # # drivers/net/tc35815.c # 2004/04/21 20:35:51-04:00 ralf@linux-mips.org +1 -1 # Reformat # # ChangeSet # 2004/06/19 17:45:01-04:00 ralf@linux-mips.org # [PATCH] Use netdev_priv in sgiseeq # # The combined allocation of of receive and transmit rings and driver data # so far made the use of netdev_priv impossible. Split the allocation # and use netdev_priv to access the non-ring driver_private data. # # Signed-off-by: Ralf Baechle # # drivers/net/sgiseeq.c # 2004/05/10 10:13:02-04:00 ralf@linux-mips.org +75 -70 # Use netdev_priv in sgiseeq # # ChangeSet # 2004/06/19 17:41:19-04:00 arjanv@redhat.com # [PATCH] sk98lin pci id # # drivers/net/sk98lin/h/skdrv2nd.h # 2004/06/18 20:00:00-04:00 arjanv@redhat.com +2 -1 # sk98lin pci id # # ChangeSet # 2004/06/19 17:36:14-04:00 ryan@michonline.com # [PATCH] orinoco.c rate limit lost information frame message # # Rate limit a (apparently) harmless warning in orinoco.c # # (My laptop remained connected with active X applications running over # ssh while this message was hitting every second, since I patched my # driver to include this the problem hasn't recurred.) # # Signed-Off-By: Ryan Anderson # # drivers/net/wireless/orinoco.c # 2004/06/13 17:20:20-04:00 ryan@michonline.com +2 -1 # orinoco.c rate limit lost information frame message # # ChangeSet # 2004/06/19 17:12:57-04:00 brazilnut@us.ibm.com # [PATCH] pcnet32: cleanup IRQ limitation. # # Cleanup pcnet32 IRQ handling based on suggestions from Ralf Baechle # , and Brian Murphy # # Tested by myself and Brian Murphy. # # Please also apply to 2.4.27-pre6. # # Signed-off-by: Don Fry # # drivers/net/pcnet32.c # 2004/06/17 09:14:53-04:00 brazilnut@us.ibm.com +12 -14 # pcnet32: cleanup IRQ limitation. # # ChangeSet # 2004/06/19 17:12:48-04:00 brazilnut@us.ibm.com # [PATCH] pcnet32: recover after rx hang. # # This patch fixes a receive hang that occasionally occurs after a Tx # FIFO underrun. The receive dma remains in a hung state sometimes. The # transmit operations continue to occur, but no receive activity. # # This was reproduced on several ppc64 systems and the fix has been verified # there. The patch has been tested as well on an ia32 system, which did # not experience the hang because it did not have fifo underruns, which is # a preqrequisite for the hang. The memory barriers decreased the frequency # of occurrence. The final change to reset the chip instead of just stopping # it eliminated the last hangs. # # Please also apply against 2.4.7 (with offset of -1), tested ia32. # # Signed-off by: brazilnut@us.ibm.com # # drivers/net/pcnet32.c # 2004/06/15 06:00:17-04:00 brazilnut@us.ibm.com +30 -10 # pcnet32: recover after rx hang. # # ChangeSet # 2004/06/19 17:12:39-04:00 brazilnut@us.ibm.com # [PATCH] pcnet32: discard oversize rx packets # # This patch will discard received frames that are larger than one buffer. # This has been tested on ia32 and ppc64 systems. # # Please also apply to 2.4.7 (with offset of -3), tested ia32. # # Signed-off by: brazilnut@us.ibm.com # # drivers/net/pcnet32.c # 2004/06/15 05:36:43-04:00 brazilnut@us.ibm.com +10 -3 # pcnet32: discard oversize rx packets # # ChangeSet # 2004/06/19 17:09:31-04:00 davem@redhat.com # [PATCH] hamachi DMA # # Let's get this thing not using bus_to_virt() anymore, # as follows. # # Signed-off-by: David S. Miller # # ===== drivers/net/hamachi.c 1.35 vs edited ===== # # drivers/net/hamachi.c # 2004/06/16 14:15:20-04:00 davem@redhat.com +1 -3 # hamachi DMA # # ChangeSet # 2004/06/19 17:08:21-04:00 fenlason@redhat.com # [PATCH] sunhme patch # # Without this patch, insmod-ing the sunhme module crashes on my fc2 # box. # # -- JF # # drivers/net/sunhme.c # 2004/06/16 20:29:23-04:00 fenlason@redhat.com +2 -1 # hme patch # # ChangeSet # 2004/06/19 17:07:34-04:00 jeb.j.cramer@intel.com # [PATCH] e1000 management reset fix # # * Resetting the adapter blew away management settings. So we save the # important bits before performing a reset. # # drivers/net/e1000/e1000_main.c # 2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +9 -1 # e1000 management reset fix # # drivers/net/e1000/e1000_hw.h # 2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +2 -0 # e1000 management reset fix # # drivers/net/e1000/e1000_hw.c # 2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +35 -0 # e1000 management reset fix # # drivers/net/e1000/e1000.h # 2004/06/18 20:00:00-04:00 jeb.j.cramer@intel.com +1 -0 # e1000 management reset fix # # ChangeSet # 2004/06/19 17:07:25-04:00 shemminger@osdl.org # [PATCH] convert sk fddi driver to ANSI C # # Sparse does not handle K&R at all, and I think I saw Linus saying that # he has no intention of adding it to sparse while ago. So here is a blob # of patch to convert drivers/net/skfp/* from K&R to ANSI-C. Compile # tested with "make allmodconfig" on x86, as I obviously don't have the # HW. # # Mika # # Signed-off-by: Stephen Hemminger # # drivers/net/skfp/srf.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +11 -23 # convert sk fddi driver to ANSI C # # drivers/net/skfp/smttimer.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +9 -26 # convert sk fddi driver to ANSI C # # drivers/net/skfp/smtparse.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +9 -17 # convert sk fddi driver to ANSI C # # drivers/net/skfp/smtinit.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +5 -6 # convert sk fddi driver to ANSI C # # drivers/net/skfp/smtdef.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +10 -21 # convert sk fddi driver to ANSI C # # drivers/net/skfp/smt.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +142 -265 # convert sk fddi driver to ANSI C # # drivers/net/skfp/skfddi.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +2 -15 # convert sk fddi driver to ANSI C # # drivers/net/skfp/rmt.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +25 -45 # convert sk fddi driver to ANSI C # # drivers/net/skfp/queue.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +6 -18 # convert sk fddi driver to ANSI C # # drivers/net/skfp/pmf.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +24 -54 # convert sk fddi driver to ANSI C # # drivers/net/skfp/pcmplc.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +47 -117 # convert sk fddi driver to ANSI C # # drivers/net/skfp/lnkstat.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +5 -10 # convert sk fddi driver to ANSI C # # drivers/net/skfp/hwt.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +9 -18 # convert sk fddi driver to ANSI C # # drivers/net/skfp/hwmtm.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +99 -122 # convert sk fddi driver to ANSI C # # drivers/net/skfp/h/smtstate.h # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +6 -0 # convert sk fddi driver to ANSI C # # drivers/net/skfp/h/cmtdef.h # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +144 -178 # convert sk fddi driver to ANSI C # # drivers/net/skfp/fplustm.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +61 -129 # convert sk fddi driver to ANSI C # # drivers/net/skfp/ess.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +21 -41 # convert sk fddi driver to ANSI C # # drivers/net/skfp/ecm.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +11 -22 # convert sk fddi driver to ANSI C # # drivers/net/skfp/drvfbi.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +49 -132 # convert sk fddi driver to ANSI C # # drivers/net/skfp/cfm.c # 2004/06/17 17:49:49-04:00 shemminger@osdl.org +10 -25 # convert sk fddi driver to ANSI C # # ChangeSet # 2004/06/19 17:06:09-04:00 akpm@osdl.org # [PATCH] H8/300: smc9194 driver # # From: Yoshinori Sato # # - H8/300 target support # - fixed irq support # - high address (>0xffff) i/o fix # # Signed-off-by: Andrew Morton # # drivers/net/smc9194.c # 2004/06/18 01:19:59-04:00 akpm@osdl.org +65 -9 # H8/300: smc9194 driver # # ChangeSet # 2004/06/19 17:04:50-04:00 herbert@gondor.apana.org.au # [PATCH] Re: linux-2.6.7 Equalizer Load-balancer. eql.c. local non-privileged DoS # # Vitaly V. Bursov wrote: # > # > there are multiple vulns in drivers/net/eql.c # > # > if there is no such device, dev_get_by_name returns NULL and everything dies. # > Exploiting this is trivial. # # Thanks for the report. This patch should fix them. # # Signed-off-by: Herbert Xu # # Cheers, # -- # Visit Openswan at http://www.openswan.org/ # Email: Herbert Xu ~{PmV>HI~} # Home Page: http://gondor.apana.org.au/~herbert/ # PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt # -- # ===== drivers/net/eql.c 1.13 vs edited ===== # # drivers/net/eql.c # 2004/06/18 07:30:49-04:00 herbert@gondor.apana.org.au +4 -0 # Re: linux-2.6.7 Equalizer Load-balancer. eql.c. local non-privileged DoS # # ChangeSet # 2004/06/19 17:00:28-04:00 achirica@telefonica.net # [wireless airo] Clean initialization of Mini-PCI cards even from suspend # # drivers/net/wireless/airo.c # 2004/06/18 16:56:26-04:00 achirica@telefonica.net +28 -12 # Clean initialization of Mini-PCI cards even from suspend # # ChangeSet # 2004/06/19 12:48:23-07:00 davem@nuts.davemloft.net # [IPV6]: Export necessary xfrm6_tunnel functions. # # net/ipv6/xfrm6_tunnel.c # 2004/06/19 12:48:05-07:00 davem@nuts.davemloft.net +11 -0 # [IPV6]: Export necessary xfrm6_tunnel functions. # # ChangeSet # 2004/06/19 11:55:24-07:00 yoshfuji@linux-ipv6.org # [NET]: Fix some userland header bustage. # # include/linux/netfilter_ipv6/ip6_tables.h # 2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +3 -0 # [NET]: Fix some userland header bustage. # # include/linux/netfilter_ipv4/ip_tables.h # 2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +2 -1 # [NET]: Fix some userland header bustage. # # include/linux/netfilter_arp/arp_tables.h # 2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +1 -1 # [NET]: Fix some userland header bustage. # # include/linux/netfilter.h # 2004/06/19 11:55:10-07:00 yoshfuji@linux-ipv6.org +1 -0 # [NET]: Fix some userland header bustage. # # ChangeSet # 2004/06/19 11:36:58-07:00 akpm@osdl.org # [NET]: Fix econet build bustage. # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # net/econet/af_econet.c # 2004/06/19 11:36:43-07:00 akpm@osdl.org +2 -2 # [NET]: Fix econet build bustage. # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/19 07:50:55-07:00 mikulas@artax.karlin.mff.cuni.cz # [PATCH] HPFS fixes for 2.6.7 kernel # # This contains hpfs fixes from my source ported to 2.6.7 kernel: # # updates: # - allocator fragments files less # - OS/2 Warp Server filesystem can be mounted read/only # - added reschedule points so that it doesn't hog CPU # # bug fixes: # - filesystem error message when syncing or fsyncing deleted file (or when # system just writes it on its own) # - filesystem error on extremly fragmented files # - corrupted disk structures could possibly corrupt memory # # fs/hpfs/super.c # 2004/06/18 18:13:55-07:00 mikulas@artax.karlin.mff.cuni.cz +1 -0 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/map.c # 2004/06/18 18:09:05-07:00 mikulas@artax.karlin.mff.cuni.cz +4 -2 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/inode.c # 2004/06/18 18:13:20-07:00 mikulas@artax.karlin.mff.cuni.cz +9 -7 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/hpfs_fn.h # 2004/06/18 18:01:00-07:00 mikulas@artax.karlin.mff.cuni.cz +3 -2 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/hpfs.h # 2004/06/18 17:58:08-07:00 mikulas@artax.karlin.mff.cuni.cz +1 -1 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/ea.c # 2004/06/18 17:57:50-07:00 mikulas@artax.karlin.mff.cuni.cz +3 -5 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/buffer.c # 2004/06/18 17:55:53-07:00 mikulas@artax.karlin.mff.cuni.cz +8 -0 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/anode.c # 2004/06/18 17:49:38-07:00 mikulas@artax.karlin.mff.cuni.cz +1 -2 # HPFS fixes for 2.6.7 kernel # # fs/hpfs/alloc.c # 2004/06/18 18:44:32-07:00 mikulas@artax.karlin.mff.cuni.cz +44 -26 # HPFS fixes for 2.6.7 kernel # # Documentation/filesystems/hpfs.txt # 2004/06/18 18:17:43-07:00 mikulas@artax.karlin.mff.cuni.cz +10 -2 # HPFS fixes for 2.6.7 kernel # # ChangeSet # 2004/06/19 07:50:44-07:00 akpm@osdl.org # [PATCH] mptctl.c build fix # # drivers/message/fusion/mptctl.c:89:24: asm/compat.h: No such file or directory # # Signed-off-by: Andrew Morton # # drivers/message/fusion/mptctl.c # 2004/06/19 00:22:47-07:00 akpm@osdl.org +1 -1 # mptctl.c build fix # # ChangeSet # 2004/06/19 07:49:02-07:00 torvalds@ppc970.osdl.org # Merge http://lia64.bkbits.net/to-linus-2.5 # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # include/asm-ia64/pgtable.h # 2004/06/19 07:48:59-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # arch/ia64/kernel/iosapic.c # 2004/06/19 07:48:59-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # arch/ia64/ia32/ia32_entry.S # 2004/06/19 07:48:59-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/06/18 21:52:08-07:00 yanmin.zhang@intel.com # [PATCH] ia64: fix free_huge_page() call in hugetlb_prefault() # # In base kernel 2.6.7, there is bug in function hugetlb_prefault(). The # call to free_huge_page() is incorrect and should be replaced with a call # to page_cache_release(). # # Signed-off-by: David Mosberger # # arch/ia64/mm/hugetlbpage.c # 2004/06/18 00:26:02-07:00 yanmin.zhang@intel.com +1 -1 # ia64: fix free_huge_page() call in hugetlb_prefault() # # ChangeSet # 2004/06/18 21:49:12-07:00 eranian@hpl.hp.com # [PATCH] ia64: perfmon stack consumption fix # # This patch moves the pfm_ovfl_arg_t structure from the kernel stack # into the pfm_context_t structure. This minimizes kernel stack space # consumption. # # Signed-off-by: Stephane Eranian # Signed-off-by: David Mosberger # # arch/ia64/kernel/perfmon.c # 2004/06/18 09:17:04-07:00 eranian@hpl.hp.com +20 -18 # ia64: perfmon stack consumption fix # # ChangeSet # 2004/06/18 21:45:35-07:00 ashok.raj@intel.com # [PATCH] ia64: move move_irq() from iosapic.c to irq.c # # This patch moves move_irq() from ioaspic.c to irq.c to make this common # for ia64 subarches. # # Signed-off-by: Ashok Raj # Signed-off-by: David Mosberger # # include/asm-ia64/irq.h # 2004/06/18 15:22:57-07:00 ashok.raj@intel.com +6 -0 # ia64: move move_irq() from iosapic.c to irq.c # # arch/ia64/kernel/irq.c # 2004/06/18 15:22:57-07:00 ashok.raj@intel.com +16 -0 # ia64: move move_irq() from iosapic.c to irq.c # # arch/ia64/kernel/iosapic.c # 2004/06/18 15:22:57-07:00 ashok.raj@intel.com +0 -16 # ia64: move move_irq() from iosapic.c to irq.c # # ChangeSet # 2004/06/18 21:42:42-07:00 arun.sharma@intel.com # [PATCH] ia64: fix ia32 partial-page map support for overlapping mmaps # # - Handle the overlapping mmaps in the MAP_FIXED case # - Handle unmaps correctly i.e. call __ia32_delete_pp_range() # - There are now three clear entry points into the pp manipulation code # - ia32_set_pp # - ia32_unset_pp # - ia32_compare_pp # - Rename internal functions to __ia32_*pp_* # - Grab mmap_sem just once at the main entry point # # Signed-off-by: Gordon Jin # Signed-off-by: Arun Sharma # Signed-off-by: David Mosberger # # arch/ia64/ia32/sys_ia32.c # 2004/06/18 04:55:20-07:00 arun.sharma@intel.com +184 -134 # ia64: fix ia32 partial-page map support for overlapping mmaps # # ChangeSet # 2004/06/18 23:02:41-05:00 stevef@smfhome1.smfdom # check better for free files on writepage retry # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/file.c # 2004/06/18 23:02:34-05:00 stevef@smfhome1.smfdom +21 -7 # check better for free files on writepage retry # # ChangeSet # 2004/06/18 22:01:37-05:00 stevef@smfhome1.smfdom # Do not send junk in bcc area of oplock break SMB Lock request, and always let oplock break release # through even if requests are ahead of it waiting for responses to complete. # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/transport.c # 2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +20 -15 # do not count oplock breaks against in flight count # # fs/cifs/connect.c # 2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +1 -1 # do not reset inFlight count on reconnection so it does not go negative # # fs/cifs/cifssmb.c # 2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +14 -8 # Do not send junk in bcc area of oplock break SMB Lock request # # fs/cifs/CHANGES # 2004/06/18 22:01:30-05:00 stevef@smfhome1.smfdom +2 -1 # update cifs vfs change log for 1.19 # # ChangeSet # 2004/06/18 18:26:37-07:00 rddunlap@osdl.org # [PATCH] sparse: lib/string.c sparse fix # # A classic.. # # lib/string.c:165:19: warning: assignment expression in conditional # # From: Mika Kukkonen # Signed-off-by: Randy Dunlap # # lib/string.c # 2004/06/09 12:58:48-07:00 rddunlap@osdl.org +1 -1 # sparse: lib/string.c sparse fix # # ChangeSet # 2004/06/18 18:26:26-07:00 rddunlap@osdl.org # [PATCH] sparse: kernel/module.c sparse fix # # Add __user annotation for !CONFIG_MODULE_UNLOAD case. # # From: Mika Kukkonen # Signed-off-by: Randy Dunlap # # kernel/module.c # 2004/06/09 13:11:44-07:00 rddunlap@osdl.org +1 -1 # sparse: kernel/module.c sparse fix # # ChangeSet # 2004/06/18 16:46:25-07:00 viro@www.linux.org.uk # [PATCH] sparse: drivers/video/sis annotation # # drivers/video/sis/sis_main.c # 2004/06/18 09:43:52-07:00 viro@www.linux.org.uk +16 -15 # sparse: drivers/video/sis annotation # # ChangeSet # 2004/06/18 16:37:47-07:00 viro@www.linux.org.uk # [PATCH] sparse: drivers/video/aty annotation # # drivers/video/aty/radeon_base.c # 2004/06/18 09:36:48-07:00 viro@www.linux.org.uk +4 -4 # sparse: drivers/video/aty annotation # # ChangeSet # 2004/06/18 16:35:56-07:00 torvalds@ppc970.osdl.org # Merge ppc970.osdl.org:/home/torvalds/v2.6/v2.6.7 # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # include/linux/ipmi.h # 2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # include/linux/fb.h # 2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # fs/binfmt_aout.c # 2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/video/fbmem.c # 2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/char/ipmi/ipmi_watchdog.c # 2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/char/ipmi/ipmi_devintf.c # 2004/06/18 16:35:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/06/18 16:35:04-07:00 viro@www.linux.org.uk # [PATCH] sparse: autofs annotation # # fs/autofs/root.c # 2004/06/18 11:14:07-07:00 viro@www.linux.org.uk +7 -6 # sparse: autofs annotation # # ChangeSet # 2004/06/18 16:34:54-07:00 viro@www.linux.org.uk # [PATCH] sparse: synclinkmp annotation # # drivers/char/synclinkmp.c # 2004/06/18 11:19:11-07:00 viro@www.linux.org.uk +22 -21 # sparse: synclinkmp annotation # # ChangeSet # 2004/06/18 16:34:45-07:00 viro@www.linux.org.uk # [PATCH] sparse: cyclades annotation # # drivers/char/cyclades.c # 2004/06/18 11:16:10-07:00 viro@www.linux.org.uk +29 -30 # sparse: cyclades annotation # # ChangeSet # 2004/06/18 16:34:35-07:00 viro@www.linux.org.uk # [PATCH] sparse: ipmi annotation # # include/linux/ipmi.h # 2004/06/18 11:18:12-07:00 viro@www.linux.org.uk +2 -2 # sparse: ipmi annotation # # drivers/char/ipmi/ipmi_watchdog.c # 2004/06/18 11:18:46-07:00 viro@www.linux.org.uk +10 -13 # sparse: ipmi annotation # # drivers/char/ipmi/ipmi_devintf.c # 2004/06/18 11:18:33-07:00 viro@www.linux.org.uk +14 -13 # sparse: ipmi annotation # # ChangeSet # 2004/06/18 16:34:24-07:00 viro@www.linux.org.uk # [PATCH] sparse: amd64 bits # # - added define of __x86_64__ to sparse arguments on amd64 # - switched amd64 uaccess.h to __chk_user_ptr() # # include/asm-x86_64/uaccess.h # 2004/06/18 11:15:18-07:00 viro@www.linux.org.uk +34 -44 # sparse: amd64 bits # # arch/x86_64/Makefile # 2004/06/18 11:15:02-07:00 viro@www.linux.org.uk +2 -0 # sparse: amd64 bits # # ChangeSet # 2004/06/18 16:34:14-07:00 viro@www.linux.org.uk # [PATCH] sparse: applicom annotation # # drivers/char/applicom.c # 2004/06/18 11:19:50-07:00 viro@www.linux.org.uk +10 -9 # sparse: applicom annotation # # ChangeSet # 2004/06/18 16:34:03-07:00 viro@www.linux.org.uk # [PATCH] sparse: udf cleanups # # removed bogus externs from declarations in fs/udf/* # # fs/udf/misc.c # 2004/06/18 11:12:57-07:00 viro@www.linux.org.uk +6 -6 # sparse: udf cleanups # # fs/udf/crc.c # 2004/06/18 11:12:52-07:00 viro@www.linux.org.uk +1 -1 # sparse: udf cleanups # # ChangeSet # 2004/06/18 16:33:52-07:00 viro@www.linux.org.uk # [PATCH] sparse: drivers/video/matrox annotation # # drivers/video/matrox/matroxfb_crtc2.c # 2004/06/18 11:08:45-07:00 viro@www.linux.org.uk +5 -5 # sparse: drivers/video/matrox annotation # # drivers/video/matrox/matroxfb_base.c # 2004/06/18 11:08:34-07:00 viro@www.linux.org.uk +16 -15 # sparse: drivers/video/matrox annotation # # ChangeSet # 2004/06/18 16:33:41-07:00 viro@www.linux.org.uk # [PATCH] sparse: drivers/video/kyro annotation # # drivers/video/kyro/fbdev.c # 2004/06/18 11:07:54-07:00 viro@www.linux.org.uk +6 -6 # sparse: drivers/video/kyro annotation # # ChangeSet # 2004/06/18 16:33:31-07:00 viro@www.linux.org.uk # [PATCH] sparse: drivers/video partial annotation # # misc annotation in drivers/video/* (nowhere near complete) # # include/linux/fb.h # 2004/06/18 11:11:09-07:00 viro@www.linux.org.uk +2 -2 # sparse: drivers/video partial annotation # # drivers/video/sstfb.c # 2004/06/18 11:10:17-07:00 viro@www.linux.org.uk +2 -2 # sparse: drivers/video partial annotation # # drivers/video/radeonfb.c # 2004/06/18 11:10:06-07:00 viro@www.linux.org.uk +2 -2 # sparse: drivers/video partial annotation # # drivers/video/imsttfb.c # 2004/06/18 11:10:31-07:00 viro@www.linux.org.uk +10 -9 # sparse: drivers/video partial annotation # # drivers/video/fbmem.c # 2004/06/18 11:10:53-07:00 viro@www.linux.org.uk +2 -2 # sparse: drivers/video partial annotation # # ChangeSet # 2004/06/18 16:33:20-07:00 viro@www.linux.org.uk # [PATCH] sparse: nfs partial annotation # # include/linux/nfs4_mount.h # 2004/06/18 11:11:45-07:00 viro@www.linux.org.uk +3 -3 # sparse: nfs partial annotation # # fs/nfs/idmap.c # 2004/06/18 11:12:29-07:00 viro@www.linux.org.uk +6 -5 # sparse: nfs partial annotation # # fs/nfs/direct.c # 2004/06/18 11:12:14-07:00 viro@www.linux.org.uk +1 -1 # sparse: nfs partial annotation # # ChangeSet # 2004/06/18 16:33:09-07:00 viro@www.linux.org.uk # [PATCH] sparse: mwave annotation # # drivers/char/mwave/tp3780i.h # 2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +2 -2 # sparse: mwave annotation # # drivers/char/mwave/tp3780i.c # 2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +2 -2 # sparse: mwave annotation # # drivers/char/mwave/mwavedd.c # 2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +17 -20 # sparse: mwave annotation # # drivers/char/mwave/3780i.h # 2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +5 -5 # sparse: mwave annotation # # drivers/char/mwave/3780i.c # 2004/06/18 11:17:27-07:00 viro@www.linux.org.uk +10 -10 # sparse: mwave annotation # # ChangeSet # 2004/06/18 16:32:59-07:00 viro@www.linux.org.uk # [PATCH] sparse: binfmt_aout annotation # # fs/binfmt_aout.c # 2004/06/18 11:13:43-07:00 viro@www.linux.org.uk +13 -12 # sparse: binfmt_aout annotation # # ChangeSet # 2004/06/18 14:14:17-07:00 akpm@osdl.org # [NET]: Fix eql.c failed dev_get_by_name() return value check. # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/eql.c # 2004/06/18 14:14:03-07:00 akpm@osdl.org +5 -1 # [NET]: Fix eql.c failed dev_get_by_name() return value check. # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/18 14:12:29-07:00 yoshfuji@linux-ipv6.org # [IPV6]: Fix autoconf description in ip-sysctl.txt. # # Documentation/networking/ip-sysctl.txt # 2004/06/18 14:12:15-07:00 yoshfuji@linux-ipv6.org +4 -2 # [IPV6]: Fix autoconf description in ip-sysctl.txt. # # ChangeSet # 2004/06/18 14:11:36-07:00 wli@holomorphy.com # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # net/irda/irda_device.c # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +2 -2 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # include/net/irda/irda_device.h # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -1 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/w83977af_ir.h # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/w83977af_ir.c # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +19 -12 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/via-ircc.h # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/via-ircc.c # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +18 -10 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/smsc-ircc2.c # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +20 -11 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/nsc-ircc.h # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/nsc-ircc.c # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +19 -11 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/ali-ircc.h # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +3 -0 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # drivers/net/irda/ali-ircc.c # 2004/06/18 14:11:22-07:00 wli@holomorphy.com +19 -11 # [IRDA]: Remove usage of isa_virt_to_bus() # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/18 14:09:17-07:00 dlstevens@us.ibm.com # [IPV6]: Handle user asking for any device in mcast calls. # # net/ipv6/mcast.c # 2004/06/18 14:09:03-07:00 dlstevens@us.ibm.com +1 -1 # [IPV6]: Handle user asking for any device in mcast calls. # # ChangeSet # 2004/06/18 13:54:52-07:00 shemminger@osdl.org # [PKT_SCHED]: Add loss option to network delay scheduler. # # This enhances the network simulation scheduler to do simple random loss. # # The loss parameter is a simple 32 bit value such that 0 means no loss, and # 0xffffffff is always drop. I have a new version of the tc command which takes # care of conversion from percent to this value. # # Same patch for 2.4 and 2.6 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/sched/sch_delay.c # 2004/06/18 13:54:39-07:00 shemminger@osdl.org +9 -0 # [PKT_SCHED]: Add loss option to network delay scheduler. # # This enhances the network simulation scheduler to do simple random loss. # # The loss parameter is a simple 32 bit value such that 0 means no loss, and # 0xffffffff is always drop. I have a new version of the tc command which takes # care of conversion from percent to this value. # # Same patch for 2.4 and 2.6 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # include/linux/pkt_sched.h # 2004/06/18 13:54:39-07:00 shemminger@osdl.org +2 -1 # [PKT_SCHED]: Add loss option to network delay scheduler. # # This enhances the network simulation scheduler to do simple random loss. # # The loss parameter is a simple 32 bit value such that 0 means no loss, and # 0xffffffff is always drop. I have a new version of the tc command which takes # care of conversion from percent to this value. # # Same patch for 2.4 and 2.6 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/18 13:51:42-07:00 davem@nuts.davemloft.net # [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver. # # Based upon a patch from Stephen Hemminger. # Signed-off-by: David S. Miller # # net/sched/sch_tbf.c # 2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +5 -7 # [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver. # # Based upon a patch from Stephen Hemminger. # # Signed-off-by: David S. Miller # # net/sched/sch_htb.c # 2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +0 -1 # [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver. # # Based upon a patch from Stephen Hemminger. # # Signed-off-by: David S. Miller # # net/sched/sch_hfsc.c # 2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +1 -2 # [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver. # # Based upon a patch from Stephen Hemminger. # # Signed-off-by: David S. Miller # # net/sched/sch_delay.c # 2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +5 -7 # [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver. # # Based upon a patch from Stephen Hemminger. # # Signed-off-by: David S. Miller # # net/sched/sch_cbq.c # 2004/06/18 13:51:18-07:00 davem@nuts.davemloft.net +1 -1 # [PKT_SCHED]: Do not check netif_queue_stopped() in dequeue ops, races with driver. # # Based upon a patch from Stephen Hemminger. # # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/18 13:50:35-07:00 torvalds@ppc970.osdl.org # sparse: fix up fusion/mptctl.c after merge # # drivers/message/fusion/mptctl.c # 2004/06/18 13:50:29-07:00 torvalds@ppc970.osdl.org +8 -7 # sparse: fix up fusion/mptctl.c after merge # # ChangeSet # 2004/06/18 13:46:11-07:00 torvalds@ppc970.osdl.org # Merge # # drivers/message/fusion/mptctl.c # 2004/06/18 13:46:06-07:00 torvalds@ppc970.osdl.org +0 -2 # Merge # # drivers/scsi/scsi_syms.c # 2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/scsi_ioctl.c # 2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/fdomain.c # 2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/fd_mcs.c # 2004/06/18 13:44:28-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/06/18 13:43:51-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: drivers/message/fusion annotations and fixes # # Sigh... First of all, LSI folks have very quaint idea of existing # platforms and word sizes on those. Their definitions of U32 and S32 # should really be reserved for posterity (preferably chiseled into the # rock they have between the ears), but kernel is the wrong place for # that. Fixed. # # mptctl_do_mpt_command() was always called on userland pointers; # kernel/userland argument removed along with dead code, function # annotated, callers updated. # # The rest is trivial annotations in mptctl.c and in its ioctl structures # - nothing fancy there. # # drivers/message/fusion/mptctl.h # 2004/06/18 08:09:14-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # sparse: drivers/message/fusion annotations and fixes # # drivers/message/fusion/mptctl.c # 2004/06/18 08:09:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +68 -77 # sparse: drivers/message/fusion annotations and fixes # # drivers/message/fusion/lsi/mpi_type.h # 2004/06/18 08:09:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +6 -11 # sparse: drivers/message/fusion annotations and fixes # # ChangeSet # 2004/06/18 13:43:40-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] crapectomy - last users of kernel_scsi_ioctl() gone # # Last 3 users of kernel_scsi_ioctl() eliminated; two of them used to read # partition table by issuing a READ6 via ioctl (instead of just calling # scsi_bios_ptable() as every other ->biosparam() instance does). # # The last one was doing a very quaint access to fields of scsi_device by # issuing SCSI_IOCLT_GET_LUN and then shuffling bits in the result. Down # with that insanity... # # ChangeSet # 2004/06/18 13:40:49-07:00 shemminger@osdl.org # [PKT_SCHED]: Delay scheduler should retry if requeue fails. # # If delay scheduler decides not to send the packet right away, it requeues # it. If the requeue fails, it should go and look again rather than waking # up prematurely. # # Same patch should apply to both 2.6 and 2.4 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/sched/sch_delay.c # 2004/06/18 13:40:35-07:00 shemminger@osdl.org +9 -5 # [PKT_SCHED]: Delay scheduler should retry if requeue fails. # # If delay scheduler decides not to send the packet right away, it requeues # it. If the requeue fails, it should go and look again rather than waking # up prematurely. # # Same patch should apply to both 2.6 and 2.4 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # include/scsi/scsi_ioctl.h # 2004/06/18 07:38:19-07:00 viro@parcelfarce.linux.theplanet.co.uk +0 -1 # crapectomy - last users of kernel_scsi_ioctl() gone # # drivers/scsi/scsi_syms.c # 2004/06/18 07:36:48-07:00 viro@parcelfarce.linux.theplanet.co.uk +0 -1 # crapectomy - last users of kernel_scsi_ioctl() gone # # drivers/scsi/scsi_ioctl.c # 2004/06/18 07:36:38-07:00 viro@parcelfarce.linux.theplanet.co.uk +0 -16 # crapectomy - last users of kernel_scsi_ioctl() gone # # drivers/scsi/pcmcia/nsp_cs.c # 2004/06/18 07:37:49-07:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # crapectomy - last users of kernel_scsi_ioctl() gone # # drivers/scsi/fdomain.c # 2004/06/18 07:37:05-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -16 # crapectomy - last users of kernel_scsi_ioctl() gone # # drivers/scsi/fd_mcs.c # 2004/06/18 07:37:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -14 # crapectomy - last users of kernel_scsi_ioctl() gone # # ChangeSet # 2004/06/18 13:36:39-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: ibmasmfs annotations # # Trivial annotations + couple of missing (void) in prototypes # # drivers/misc/ibmasm/ibmasmfs.c # 2004/06/18 08:05:56-07:00 viro@parcelfarce.linux.theplanet.co.uk +14 -14 # sparse: ibmasmfs annotations # # ChangeSet # 2004/06/18 13:36:27-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: ide-tape annotation # # drivers/ide/ide-tape.c # 2004/06/18 08:04:58-07:00 viro@parcelfarce.linux.theplanet.co.uk +11 -9 # sparse: ide-tape annotation # # ChangeSet # 2004/06/18 13:36:16-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: drivers/input annotations # # Trivial annotations in drivers/input # # drivers/input/tsdev.c # 2004/06/18 08:04:18-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # sparse: drivers/input annotations # # drivers/input/misc/uinput.c # 2004/06/18 08:04:24-07:00 viro@parcelfarce.linux.theplanet.co.uk +3 -3 # sparse: drivers/input annotations # # drivers/input/joydev.c # 2004/06/18 08:04:15-07:00 viro@parcelfarce.linux.theplanet.co.uk +21 -20 # sparse: drivers/input annotations # # ChangeSet # 2004/06/18 13:36:05-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: drivers/char/watchdog annotation # # Trivial annotations in drivers/char/watchdog/* # # drivers/char/watchdog/wdt_pci.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -7 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -7 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/wafer5823wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -7 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/w83877f_wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/w83627hf_wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/softdog.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -5 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/scx200_wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/sc520_wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/sc1200wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -7 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/sbc60xxwdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/pcwd_usb.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +11 -9 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/pcwd_pci.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +11 -9 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/mixcomwd.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -4 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/machzwd.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -4 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/ib700wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -5 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/i8xx_tco.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/eurotechwdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -8 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/cpu5wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -4 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/alim7101_wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/alim1535_wdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/advantechwdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -6 # sparse: drivers/char/watchdog annotation # # drivers/char/watchdog/acquirewdt.c # 2004/06/18 07:43:25-07:00 viro@parcelfarce.linux.theplanet.co.uk +7 -5 # sparse: drivers/char/watchdog annotation # # ChangeSet # 2004/06/18 13:35:54-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: ixj annotated # # drivers/telephony (aka ixj.c) annotated, IXJ_CADENCE split into kernel # and userland variants, ioctl structures got __user on pointers. # # include/linux/ixjuser.h # 2004/06/18 07:40:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # sparse: ixj annotated # # drivers/telephony/ixj.h # 2004/06/18 07:39:46-07:00 viro@parcelfarce.linux.theplanet.co.uk +8 -2 # sparse: ixj annotated # # drivers/telephony/ixj.c # 2004/06/18 07:39:48-07:00 viro@parcelfarce.linux.theplanet.co.uk +61 -45 # sparse: ixj annotated # # ChangeSet # 2004/06/18 13:35:42-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: vm86.c annotated # # vm86.c annotated; vm86old(2) and vm86(2) switched to explicit # # int (struct pt_regs regs) # # format. # # arch/i386/kernel/vm86.c # 2004/06/18 07:35:47-07:00 viro@parcelfarce.linux.theplanet.co.uk +19 -13 # sparse: vm86.c annotated # # ChangeSet # 2004/06/18 13:35:31-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: rt_sigsuspend/sigaltstack sanitized # # rt_sigsuspend() and sigaltstack() prototype changed; instead of # playing games with casts of argument address to struct pt_regs * and # digging through it, we declare them as # # int (struct pt_regs regs) # # instead. # # arch/i386/kernel/signal.c # 2004/06/18 07:35:29-07:00 viro@parcelfarce.linux.theplanet.co.uk +9 -9 # sparse: rt_sigsuspend/sigaltstack sanitized # # ChangeSet # 2004/06/18 13:35:20-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] sparse: i387 math-emu annotation # # arch/i386/math-emu/* annotated. # # arch/i386/math-emu/reg_ld_str.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +75 -75 # sparse: i387 math-emu annotation # # arch/i386/math-emu/reg_compare.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +6 -6 # sparse: i387 math-emu annotation # # arch/i386/math-emu/load_store.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +26 -26 # sparse: i387 math-emu annotation # # arch/i386/math-emu/get_address.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +15 -15 # sparse: i387 math-emu annotation # # arch/i386/math-emu/fpu_system.h # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # sparse: i387 math-emu annotation # # arch/i386/math-emu/fpu_proto.h # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +21 -21 # sparse: i387 math-emu annotation # # arch/i386/math-emu/fpu_etc.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # sparse: i387 math-emu annotation # # arch/i386/math-emu/fpu_entry.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +17 -16 # sparse: i387 math-emu annotation # # arch/i386/math-emu/fpu_aux.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +10 -10 # sparse: i387 math-emu annotation # # arch/i386/math-emu/fpu_arith.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +18 -18 # sparse: i387 math-emu annotation # # arch/i386/math-emu/errors.c # 2004/06/18 07:30:41-07:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # sparse: i387 math-emu annotation # # ChangeSet # 2004/06/18 13:18:34-07:00 shemminger@osdl.org # [PKT_SCHED]: Delay scheduler enqueue always succeeds. # # If underlying fifo enqueue fails, return the status not 0. # Same patch should apply to both 2.6 and 2.4 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/sched/sch_delay.c # 2004/06/18 13:18:20-07:00 shemminger@osdl.org +1 -1 # [PKT_SCHED]: Delay scheduler enqueue always succeeds. # # If underlying fifo enqueue fails, return the status not 0. # Same patch should apply to both 2.6 and 2.4 # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/18 13:15:58-07:00 shemminger@osdl.org # [BRIDGE]: Kill sysfs hotplug avoidance hacks. # # The whole effort to avoid hotplug was misguided. If it is really a problem # (which it doesn't appear to be) then it can more easily be addressed by smarter # hotplug scripts in user space. # # This patch gets rid of the whole subsystem hack for bridge kobjects. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br_sysfs_if.c # 2004/06/18 13:15:34-07:00 shemminger@osdl.org +1 -1 # [BRIDGE]: Kill sysfs hotplug avoidance hacks. # # The whole effort to avoid hotplug was misguided. If it is really a problem # (which it doesn't appear to be) then it can more easily be addressed by smarter # hotplug scripts in user space. # # This patch gets rid of the whole subsystem hack for bridge kobjects. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br_sysfs_br.c # 2004/06/18 13:15:34-07:00 shemminger@osdl.org +1 -18 # [BRIDGE]: Kill sysfs hotplug avoidance hacks. # # The whole effort to avoid hotplug was misguided. If it is really a problem # (which it doesn't appear to be) then it can more easily be addressed by smarter # hotplug scripts in user space. # # This patch gets rid of the whole subsystem hack for bridge kobjects. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br_private.h # 2004/06/18 13:15:34-07:00 shemminger@osdl.org +0 -5 # [BRIDGE]: Kill sysfs hotplug avoidance hacks. # # The whole effort to avoid hotplug was misguided. If it is really a problem # (which it doesn't appear to be) then it can more easily be addressed by smarter # hotplug scripts in user space. # # This patch gets rid of the whole subsystem hack for bridge kobjects. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br.c # 2004/06/18 13:15:34-07:00 shemminger@osdl.org +0 -3 # [BRIDGE]: Kill sysfs hotplug avoidance hacks. # # The whole effort to avoid hotplug was misguided. If it is really a problem # (which it doesn't appear to be) then it can more easily be addressed by smarter # hotplug scripts in user space. # # This patch gets rid of the whole subsystem hack for bridge kobjects. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/18 19:53:46+01:00 rmk@flint.arm.linux.org.uk # [ARM] Remove NexusPCI/FTVPCI platform. # # This platform is no longer maintained, and its maintainer says that # the hardware is obsolete and out of circulation. # # arch/arm/common/Makefile # 2004/06/18 19:51:33+01:00 rmk@flint.arm.linux.org.uk +0 -1 # Remove FTVPCI PCI host driver. # # arch/arm/Makefile # 2004/06/18 19:51:33+01:00 rmk@flint.arm.linux.org.uk +0 -2 # Remove FTVPCI. # # arch/arm/Kconfig # 2004/06/18 19:51:32+01:00 rmk@flint.arm.linux.org.uk +4 -9 # Remove FTVPCI. # # ChangeSet # 2004/06/18 19:45:27+01:00 rmk@flint.arm.linux.org.uk # [ARM] Remove TBOX. # # This platform is no longer maintained, and its maintainer says that # the hardware is obsolete and out of circulation. # # ChangeSet # 2004/06/18 11:43:35-07:00 torvalds@ppc970.osdl.org # Merge bk://kernel.bkbits.net/davem/net-2.6 # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # security/selinux/ss/services.c # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/ss/policydb.c # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/include/security.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/include/flask.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/include/class_to_string.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/include/av_permissions.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/include/av_perm_to_string.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/include/av_inherit.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/hooks.c # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/selinux/Makefile # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # security/dummy.c # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # net/netlink/af_netlink.c # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # include/linux/security.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # include/asm-ppc64/system.h # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # Documentation/filesystems/proc.txt # 2004/06/18 11:43:31-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # arch/arm/Makefile # 2004/06/18 19:42:57+01:00 rmk@flint.arm.linux.org.uk +0 -1 # Remove TBOX. # # BitKeeper/deleted/.del-plx90x0.c~6e00d8c4651bebd # 2004/06/18 19:22:53+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/common/plx90x0.c # # BitKeeper/deleted/.del-Makefile~743b0b21d18f48a3 # 2004/06/18 19:21:48+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/mach-tbox/Makefile # # BitKeeper/deleted/.del-Makefile~1bcec227c3749c2b # 2004/06/18 19:21:42+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/mach-ftvpci/Makefile # # BitKeeper/deleted/.del-vmalloc.h~6fe84d89a4fe0487 # 2004/06/18 19:20:44+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/vmalloc.h # # BitKeeper/deleted/.del-uncompress.h~d86deb706ce0af8c # 2004/06/18 19:20:41+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/uncompress.h # # BitKeeper/deleted/.del-timex.h~e40ee87eef3b5d82 # 2004/06/18 19:20:39+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/timex.h # # BitKeeper/deleted/.del-time.h~730e38fa47912a2c # 2004/06/18 19:20:37+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/time.h # # BitKeeper/deleted/.del-system.h~13cdaece381624c5 # 2004/06/18 19:20:34+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/system.h # # BitKeeper/deleted/.del-param.h~43f147e81e4d4aa # 2004/06/18 19:20:32+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/param.h # # BitKeeper/deleted/.del-memory.h~a8036cb472d809fd # 2004/06/18 19:20:31+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/memory.h # # BitKeeper/deleted/.del-irqs.h~4b397f62f210ba4a # 2004/06/18 19:20:29+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/irqs.h # # BitKeeper/deleted/.del-io.h~dad3ba234da9ed44 # 2004/06/18 19:20:28+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/io.h # # BitKeeper/deleted/.del-hardware.h~e2ae6d2a73466d92 # 2004/06/18 19:20:26+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/hardware.h # # BitKeeper/deleted/.del-dma.h~7c79d144ee7126 # 2004/06/18 19:20:25+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-nexuspci/dma.h # # BitKeeper/deleted/.del-vmalloc.h~9cc411fb2236e832 # 2004/06/18 19:20:24+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/vmalloc.h # # BitKeeper/deleted/.del-uncompress.h~ba1125271f695d9a # 2004/06/18 19:20:22+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/uncompress.h # # BitKeeper/deleted/.del-timex.h~21cf937463373e34 # 2004/06/18 19:20:20+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/timex.h # # BitKeeper/deleted/.del-time.h~e839fe4bcd9e4cf9 # 2004/06/18 19:20:18+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/time.h # # BitKeeper/deleted/.del-system.h~cd0858e052bb3f86 # 2004/06/18 19:20:16+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/system.h # # BitKeeper/deleted/.del-serial.h~4a4898b286343b2a # 2004/06/18 19:20:15+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/serial.h # # BitKeeper/deleted/.del-param.h~220f433111a13232 # 2004/06/18 19:20:13+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/param.h # # BitKeeper/deleted/.del-memory.h~32316a4b360340b5 # 2004/06/18 19:20:11+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/memory.h # # BitKeeper/deleted/.del-irqs.h~f8419d051722d58a # 2004/06/18 19:20:09+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/irqs.h # # BitKeeper/deleted/.del-io.h~62e0d6286c3e19bc # 2004/06/18 19:20:08+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/io.h # # BitKeeper/deleted/.del-hardware.h~7238d94368669e11 # 2004/06/18 19:20:05+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/hardware.h # # BitKeeper/deleted/.del-dma.h~4cb7553c767afee5 # 2004/06/18 19:20:03+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: include/asm-arm/arch-tbox/dma.h # # BitKeeper/deleted/.del-core.c~714a718aec4a2c30 # 2004/06/18 19:20:01+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/mach-tbox/core.c # # BitKeeper/deleted/.del-pci.c~550e56da56112be2 # 2004/06/18 19:19:59+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/mach-ftvpci/pci.c # # BitKeeper/deleted/.del-leds.c~78050371c0248352 # 2004/06/18 19:19:58+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/mach-ftvpci/leds.c # # BitKeeper/deleted/.del-core.c~9e662b6895b788f2 # 2004/06/18 19:19:57+01:00 rmk@flint.arm.linux.org.uk +0 -0 # Delete: arch/arm/mach-ftvpci/core.c # # ChangeSet # 2004/06/18 12:43:06-05:00 stevef@stevef95.austin.ibm.com # Merge bk://cifs.bkbits.net/linux-2.5cifs # into stevef95.austin.ibm.com:/home/stevef/linux-2.5cifs # # fs/Kconfig # 2004/06/18 12:42:54-05:00 stevef@stevef95.austin.ibm.com +0 -1 # Auto merged # # ChangeSet # 2004/06/18 10:32:19-07:00 greg@kroah.com # Merge kroah.com:/home/greg/linux/BK/bleed-2.6 # into kroah.com:/home/greg/linux/BK/usb-2.6 # # drivers/usb/storage/scsiglue.c # 2004/06/18 10:32:14-07:00 greg@kroah.com +0 -0 # Auto merged # # ChangeSet # 2004/06/18 10:06:37-07:00 torvalds@ppc970.osdl.org # Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.6 # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # include/linux/pci_ids.h # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/sr.c # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/ide-scsi.c # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/Makefile # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/scsi/Kconfig # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2 # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50 # 2004/06/18 10:06:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # MAINTAINERS # 2004/06/18 10:06:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2 # 2004/06/18 10:06:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Merge rename: drivers/scsi/scsi_pc98.c -> BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2 # # BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50 # 2004/06/18 10:06:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Merge rename: drivers/scsi/pc980155.c -> BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50 # # ChangeSet # 2004/06/18 10:04:39-07:00 greg@kroah.com # USB: mark pwc driver broken again, as it still is :( # # drivers/usb/media/Kconfig # 2004/06/18 03:03:21-07:00 greg@kroah.com +1 -1 # USB: mark pwc driver broken again, as it still is :( # # ChangeSet # 2004/06/18 17:58:33+01:00 tony@com.rmk.(none) # [ARM PATCH] 1931/1: Allow device address translation in dma-mapping, version 3 # # Patch from Tony Lindgren # # Allows translation of shared memory addresses for devices using # dma-mapping. In some cases the device DMA address is different # from the ARM DMA address, for example with some USB OHCI # controllers. # # For more background information, please see the ARM Linux mailing # list thread "OHCI controller". # # include/asm-arm/memory.h # 2004/06/18 00:11:37+01:00 tony@com.rmk.(none) +10 -1 # [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3 # # include/asm-arm/dma-mapping.h # 2004/06/18 00:11:37+01:00 tony@com.rmk.(none) +4 -4 # [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3 # # include/asm-arm/arch-omap/memory.h # 2004/06/18 00:11:37+01:00 tony@com.rmk.(none) +20 -4 # [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3 # # arch/arm/mm/consistent.c # 2004/06/18 00:11:02+01:00 tony@com.rmk.(none) +1 -1 # [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3 # # arch/arm/common/dmabounce.c # 2004/06/18 00:11:01+01:00 tony@com.rmk.(none) +5 -5 # [PATCH] 1931/1: Allow device address translation in dma-mapping, version 3 # # ChangeSet # 2004/06/18 17:53:15+01:00 nico@org.rmk.(none) # [ARM PATCH] 1932/1: fix comment about cache handling syscall # # Patch from Nicolas Pitre # # Let's make it coherent with what the actual code is doing and has # always done, even in 2.4. Nobody complained about this so let's # just fix the comment. The most natural usage pattern for this is # a base address and a size so it's more efficient to have an exclusive # end address anyway. # # ChangeSet # 2004/06/18 09:52:38-07:00 stern@rowland.harvard.edu # [PATCH] USB: dummy_hcd shouldn't reject SET-ADDRESS requests # # This patch for the dummy_hcd driver prevents it from rejecting SET-ADDRESS # requests when the address is already set. The USB 2.0 spec states that if # a device is in the ADDRESS state, it should accept and start using the new # address. Behavior in the CONFIGURED state is undefined, but since # dummy_hcd doesn't keep track of the difference between the two states we # might as well accept the new address in any case. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/dummy_hcd.c # 2004/06/18 03:18:28-07:00 stern@rowland.harvard.edu +0 -5 # USB: dummy_hcd shouldn't reject SET-ADDRESS requests # # arch/arm/kernel/traps.c # 2004/06/18 02:01:40+01:00 nico@org.rmk.(none) +1 -1 # [PATCH] 1932/1: fix comment about cache handling syscall # # ChangeSet # 2004/06/18 09:50:41-07:00 axboe@suse.de # [PATCH] cfq direct io alias problem # # This is a fix for when we encounter an alias during insert. When that # happens we move the request to dispatch, but it may happen that this # request is also the ->last_merge hint. So we may attempt to merge with # this later, when it's either in progress or already freed. Rearrange the # logic a bit so we clear the merge hint there as well. It looks more # complex than it is, the only real code change is the addition of a # cfq_remove_merge_hints() in cfq_dispatch_sort(). # # Signed-off-by: Linus Torvalds # # drivers/block/cfq-iosched.c # 2004/06/17 10:37:34-07:00 axboe@suse.de +14 -8 # cfq direct io alias problem # # ChangeSet # 2004/06/18 09:50:31-07:00 axboe@suse.de # [PATCH] cfq allocation race # # It's possible under unlucky circumstances for this race to trigger. I # described it with a comment in the code. # # Signed-Off-By: Jens Axboe # Signed-off-by: Linus Torvalds # # drivers/block/cfq-iosched.c # 2004/05/24 06:35:01-07:00 axboe@suse.de +19 -0 # cfq allocation race # # ChangeSet # 2004/06/18 09:50:20-07:00 axboe@suse.de # [PATCH] cfq sysfs support # # This makes the CFQ tunables available in sysfs, like AS and deadline. # # Signed-off-by: Jens Axboe # Signed-off-by: Linus Torvalds # # drivers/block/cfq-iosched.c # 2004/05/24 06:06:17-07:00 axboe@suse.de +113 -2 # cfq sysfs support # # ChangeSet # 2004/06/18 17:49:27+01:00 icampbell@com.rmk.(none) # [ARM PATCH] 1934/2: Consolidate code to set CKEN on PXA # # Patch from Ian Campbell # # I've seen comments several times that various PXA drivers # update CKEN in an unsafe manner. This patch consolidates # this code into a single function pxa_set_cken() and updates # all the in tree drivers to use it. # # ChangeSet # 2004/06/18 09:48:38-07:00 torvalds@ppc970.osdl.org # Remove old stale header files that aren't referenced anywhere. # # Noted by Alexey Dobriyan. # # BitKeeper/deleted/.del-netfilter_x25.h~5e2c13d4592d8c13 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/netfilter_x25.h # # BitKeeper/deleted/.del-netfilter_ipx.h~7e5cd8fa9a3985ac # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/netfilter_ipx.h # # BitKeeper/deleted/.del-netfilter_ddp.h~2153f0da7220ca38 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/netfilter_ddp.h # # BitKeeper/deleted/.del-netbeui.h~1cf2e2f4793bcad1 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/netbeui.h # # BitKeeper/deleted/.del-mpp.h~8ebce3fa907ece97 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/mpp.h # # BitKeeper/deleted/.del-isdn_lzscomp.h~99cfe6e36b994a1 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/isdn_lzscomp.h # # BitKeeper/deleted/.del-in_systm.h~268bf1b1642e1ee5 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/in_systm.h # # BitKeeper/deleted/.del-fsfilter.h~5fc8d5fdaaa381a # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/fsfilter.h # # BitKeeper/deleted/.del-atapi.h~8a1b1aeca6c26a7 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/atapi.h # # BitKeeper/deleted/.del-adb_mouse.h~d5f39849c4abbd6e # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/adb_mouse.h # # BitKeeper/deleted/.del-acpi_serial.h~d839323d8907296b # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/acpi_serial.h # # BitKeeper/deleted/.del-802_11.h~9b6bd4cff8af7a90 # 2004/06/18 09:47:58-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/linux/802_11.h # # include/asm-arm/arch-pxa/hardware.h # 2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +5 -0 # [PATCH] 1934/2: Consolidate code to set CKEN on PXA # # drivers/video/pxafb.c # 2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +1 -4 # [PATCH] 1934/2: Consolidate code to set CKEN on PXA # # drivers/usb/gadget/pxa2xx_udc.c # 2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +2 -2 # [PATCH] 1934/2: Consolidate code to set CKEN on PXA # # drivers/serial/pxa.c # 2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +2 -7 # [PATCH] 1934/2: Consolidate code to set CKEN on PXA # # arch/arm/mach-pxa/generic.c # 2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +18 -0 # [PATCH] 1934/2: Consolidate code to set CKEN on PXA # # ChangeSet # 2004/06/18 09:46:06-07:00 torvalds@ppc970.osdl.org # Merge # # drivers/net/at1700.c # 2004/06/18 09:46:04-07:00 torvalds@ppc970.osdl.org +0 -0 # SCCS merged # # ChangeSet # 2004/06/18 17:43:22+01:00 icampbell@com.rmk.(none) # [ARM PATCH] 1930/1: Allocate correct number of pseudo palette entries in pxafb # # Patch from Ian Campbell # # The pxafb driver incorrectly allocates 17 u32's for a 16 entry # pseudo palette. # # drivers/net/Makefile # 2004/06/18 09:43:07-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a # 2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # drivers/net/82596.c # 2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a # 2004/06/18 09:43:06-07:00 torvalds@ppc970.osdl.org +0 -0 # Merge rename: drivers/net/ne2k_cbus.c -> BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a # # drivers/video/pxafb.c # 2004/06/18 01:00:00+01:00 icampbell@com.rmk.(none) +1 -1 # [PATCH] 1930/1: Allocate correct number of pseudo palette entries in pxafb # # ChangeSet # 2004/06/18 09:36:50-07:00 davem@nuts.davemloft.net # Merge # # security/selinux/hooks.c # 2004/06/18 09:36:41-07:00 davem@nuts.davemloft.net +0 -101 # SCCS merged # # security/selinux/ss/services.c # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -12 # Auto merged # # security/selinux/ss/policydb.c # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -9 # Auto merged # # security/selinux/include/security.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -5 # Auto merged # # security/selinux/include/flask.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -21 # Auto merged # # security/selinux/include/class_to_string.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -21 # Auto merged # # security/selinux/include/av_permissions.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -573 # Auto merged # # security/selinux/include/av_perm_to_string.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -101 # Auto merged # # security/selinux/include/av_inherit.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -9 # Auto merged # # security/selinux/Makefile # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -1 # Auto merged # # security/dummy.c # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -1 # Auto merged # # net/netlink/af_netlink.c # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -4 # Auto merged # # include/linux/security.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -11 # Auto merged # # include/asm-ppc64/system.h # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -0 # Auto merged # # Documentation/filesystems/proc.txt # 2004/06/18 09:35:13-07:00 davem@nuts.davemloft.net +0 -0 # Auto merged # # ChangeSet # 2004/06/18 09:33:53-07:00 torvalds@ppc970.osdl.org # This removes the files orphaned by the earlier PC9800 removal # # BitKeeper/deleted/.del-smpboot_hooks.h~5940f4c36bed59b4 # 2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/smpboot_hooks.h # # BitKeeper/deleted/.del-setup_arch_pre.h~1aa05e47e2ae5d10 # 2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/setup_arch_pre.h # # BitKeeper/deleted/.del-setup_arch_post.h~c1ce95fa8d614f4d # 2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/setup_arch_post.h # # BitKeeper/deleted/.del-pci-functions.h~930f4ea96f69d14 # 2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/pci-functions.h # # BitKeeper/deleted/.del-mach_wakecpu.h~de206fda8667a7e7 # 2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/mach_wakecpu.h # # BitKeeper/deleted/.del-mach_traps.h~db7e527be9d0d95b # 2004/06/18 09:32:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/mach_traps.h # # BitKeeper/deleted/.del-mach_timer.h~6faf9e0362bc9cad # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/mach_timer.h # # BitKeeper/deleted/.del-mach_time.h~4ec98fea93568edd # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/mach_time.h # # BitKeeper/deleted/.del-mach_reboot.h~666bd1054bae0a25 # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/mach_reboot.h # # BitKeeper/deleted/.del-irq_vectors.h~5a325ee32bbed31 # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/irq_vectors.h # # BitKeeper/deleted/.del-io_ports.h~8f892217bfd99be4 # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/io_ports.h # # BitKeeper/deleted/.del-do_timer.h~e73335e43b11ea32 # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/do_timer.h # # BitKeeper/deleted/.del-bios_ebda.h~4a870d9833986305 # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/bios_ebda.h # # BitKeeper/deleted/.del-apm.h~324fabc1c2354803 # 2004/06/18 09:32:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/mach-pc9800/apm.h # # BitKeeper/deleted/.del-video.S~284da1c1c2e38aa8 # 2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/boot98/video.S # # BitKeeper/deleted/.del-setup.S~bd07a5b2361060c # 2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/boot98/setup.S # # BitKeeper/deleted/.del-mtools.conf.in~3346efde195fa35 # 2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/boot98/mtools.conf.in # # BitKeeper/deleted/.del-install.sh~6441f5459fde0cb0 # 2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/boot98/install.sh # # BitKeeper/deleted/.del-bootsect.S~aa4f19a632039843 # 2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/boot98/bootsect.S # # BitKeeper/deleted/.del-Makefile~2700a53f2e1fb469 # 2004/06/18 09:32:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/boot98/Makefile # # BitKeeper/deleted/.del-topology.c~607813b1b960974f # 2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/mach-pc9800/topology.c # # BitKeeper/deleted/.del-std_resources.c~54f4a08a759f2f5f # 2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/mach-pc9800/std_resources.c # # BitKeeper/deleted/.del-setup.c~161f6c99c14ddb5d # 2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/mach-pc9800/setup.c # # BitKeeper/deleted/.del-Makefile~c002abb789b0791f # 2004/06/18 09:32:43-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: arch/i386/mach-pc9800/Makefile # # BitKeeper/deleted/.del-sound_pc9800.h~d8dde13c75b5753b # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: sound/isa/cs423x/sound_pc9800.h # # BitKeeper/deleted/.del-pc9801_118_magic.h~479c5fdd78d01b7a # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: sound/isa/cs423x/pc9801_118_magic.h # # BitKeeper/deleted/.del-pc9800_sca.h~b52752436ddb82ea # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/pc9800_sca.h # # BitKeeper/deleted/.del-pc9800.h~e8f7c13f33846c88 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: include/asm-i386/pc9800.h # # BitKeeper/deleted/.del-pc9800.c~1af765dbb1c51b76 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/ide/legacy/pc9800.c # # BitKeeper/deleted/.del-pc98.c~e5a92ca5f2b01d36 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: sound/isa/cs423x/pc98.c # # BitKeeper/deleted/.del-nec98.h~a0b8de1e822fa884 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: fs/partitions/nec98.h # # BitKeeper/deleted/.del-nec98.c~2e65e92f56ce9a56 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: fs/partitions/nec98.c # # BitKeeper/deleted/.del-hd98.c~fc4a0b69729bf7c1 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/ide/legacy/hd98.c # # BitKeeper/deleted/.del-98spkr.c~a1a91856da60a088 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/input/misc/98spkr.c # # BitKeeper/deleted/.del-98busmouse.c~ca244def94322735 # 2004/06/18 09:32:33-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/input/mouse/98busmouse.c # # BitKeeper/deleted/.del-serial98.c~c69c28b9984f1cca # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/serial/serial98.c # # BitKeeper/deleted/.del-scsi_pc98.c~63183f0558d43fc2 # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/scsi/scsi_pc98.c # # BitKeeper/deleted/.del-pc980155.h~f12bd20496e02379 # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/scsi/pc980155.h # # BitKeeper/deleted/.del-pc980155.c~e29865f8a9a6ed50 # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/scsi/pc980155.c # # BitKeeper/deleted/.del-lp_old98.c~fc58ff5b2fa5c998 # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/char/lp_old98.c # # BitKeeper/deleted/.del-floppy98.c~12864e155d00fa0e # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/block/floppy98.c # # BitKeeper/deleted/.del-98kbd.c~fcb070eb5c330ed3 # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/input/keyboard/98kbd.c # # BitKeeper/deleted/.del-98kbd-io.c~37d03ba23bb15415 # 2004/06/18 09:32:32-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/input/serio/98kbd-io.c # # BitKeeper/deleted/.del-upd4990a.c~6da2f3423f9a74f # 2004/06/18 09:32:23-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/char/upd4990a.c # # BitKeeper/deleted/.del-ne2k_cbus.h~b1e2c6c8f1caf542 # 2004/06/18 09:32:23-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/net/ne2k_cbus.h # # BitKeeper/deleted/.del-ne2k_cbus.c~db2bde9191a8ce9a # 2004/06/18 09:32:23-07:00 torvalds@ppc970.osdl.org +0 -0 # Delete: drivers/net/ne2k_cbus.c # # ChangeSet # 2004/06/18 09:31:40-07:00 torvalds@ppc970.osdl.org # Merge # # arch/i386/kernel/acpi/boot.c # 2004/06/18 09:31:38-07:00 torvalds@ppc970.osdl.org +0 -0 # SCCS merged # # arch/i386/kernel/mpparse.c # 2004/06/18 09:29:48-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/06/18 09:24:59-07:00 torvalds@ppc970.osdl.org # Merge duplicate selinux network hooks # # security/selinux/hooks.c # 2004/06/18 09:24:54-07:00 torvalds@ppc970.osdl.org +0 -101 # Merge duplicate selinux hooks # # security/selinux/ss/services.c # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -12 # Auto merged # # security/selinux/ss/policydb.c # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -9 # Auto merged # # security/selinux/include/security.h # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -5 # Auto merged # # security/selinux/include/flask.h # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -21 # Auto merged # # security/selinux/include/class_to_string.h # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -21 # Auto merged # # security/selinux/include/av_permissions.h # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -573 # Auto merged # # security/selinux/include/av_perm_to_string.h # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -101 # Auto merged # # security/selinux/include/av_inherit.h # 2004/06/18 09:21:51-07:00 torvalds@ppc970.osdl.org +0 -9 # Auto merged # # security/selinux/Makefile # 2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -1 # Auto merged # # security/dummy.c # 2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -1 # Auto merged # # net/netlink/af_netlink.c # 2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -4 # Auto merged # # include/linux/security.h # 2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -11 # Auto merged # # include/asm-ppc64/system.h # 2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # Documentation/filesystems/proc.txt # 2004/06/18 09:21:50-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/06/18 08:25:41-07:00 chrisw@osdl.org # [PATCH] RLIM: remove unused queued_signals global accounting # # Remove unused queued_signals global accounting. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sysctl.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +0 -18 # RLIM: remove unused queued_signals global accounting # # kernel/signal.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +0 -3 # RLIM: remove unused queued_signals global accounting # # ChangeSet # 2004/06/18 08:25:30-07:00 chrisw@osdl.org # [PATCH] RLIM: enforce rlimits on queued signals # # Add a user_struct pointer to the sigqueue structure. Charge sigqueue # allocation and destruction to the user_struct rather than a global pool. This # per user rlimit accounting obsoletes the global queued_signals accouting. # # The patch as charges the sigqueue struct allocation to the queue that it's # pending on (the receiver of the signal). So the owner of the queue is charged # for whoever writes to it (much like quota for a 777 file). # # The patch started out charging the task which allocated the sigqueue struct. # In most cases, these are always the same user (permission for sending a # signal), so those cases are moot. In the cases where it isn't the same user, # it's a privileged user sending a signal to another user. # # It seems wrong to charge the allocation to the privleged user, when the other # user could block receipt as long as it feels. The flipside is, someone else # can fill your queue (expectation is that someone else is privileged). I think # it's right the way it is. The change to revert is very small. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/signal.c # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +11 -6 # RLIM: enforce rlimits on queued signals # # include/linux/signal.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: enforce rlimits on queued signals # # ChangeSet # 2004/06/18 08:25:20-07:00 chrisw@osdl.org # [PATCH] RLIM: pass task_struct in send_signal() # # Update send_signal() api to allow passing the task receiving the signal. This # is necessary to ensure signals generated out of process context can be charged # to the correct user. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/signal.c # 2004/06/18 00:32:25-07:00 chrisw@osdl.org +4 -3 # RLIM: pass task_struct in send_signal() # # ChangeSet # 2004/06/18 08:23:45-07:00 torvalds@ppc970.osdl.org # Fix kill_pg_info(): return success if _any_ signal succeeded. # # kernel/signal.c # 2004/06/18 08:23:40-07:00 torvalds@ppc970.osdl.org +7 -11 # Fix kill_pg_info(): return success if _any_ signal succeeded. # # ChangeSet # 2004/06/18 08:17:04-07:00 kszysiu@iceberg.elsat.net.pl # [PATCH] cmpci oops on rmmod + fix # # The cmpci driver included in Linux 2.6.7 causes an oops on rmmod, I believe # cm_remove should be marked __devexit rather than __devinit. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/oss/cmpci.c # 2004/06/18 00:06:08-07:00 kszysiu@iceberg.elsat.net.pl +2 -2 # cmpci oops on rmmod + fix # # ChangeSet # 2004/06/18 08:16:53-07:00 ysato@users.sourceforge.jp # [PATCH] H8/300: io.h cleanup # # - optimize byteswap # - add noswap io mode # - cleanup var type # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-h8300/io.h # 2004/06/18 00:06:08-07:00 ysato@users.sourceforge.jp +68 -24 # H8/300: io.h cleanup # # ChangeSet # 2004/06/18 08:16:42-07:00 ysato@users.sourceforge.jp # [PATCH] H8/300: ptrace fix # # - Kconfig typo fix # - PTRACE_PEEKUSER read process info support # - exr restore fix # - ptrace register offset fix # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/h8300/platform/h8s/ptrace_h8s.c # 2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +1 -1 # H8/300: ptrace fix # # arch/h8300/platform/h8s/entry.S # 2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +1 -1 # H8/300: ptrace fix # # arch/h8300/kernel/ptrace.c # 2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +23 -5 # H8/300: ptrace fix # # arch/h8300/Kconfig # 2004/06/18 00:06:07-07:00 ysato@users.sourceforge.jp +1 -1 # H8/300: ptrace fix # # ChangeSet # 2004/06/18 08:16:33-07:00 kaos@ocs.com.au # [PATCH] contify some scheduler functions # # Several scheduler macros only read from the task struct, mark them const. # It may help the compiler generate better code. # # Signed-off-by: Keith Owens # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/06/18 00:06:07-07:00 kaos@ocs.com.au +3 -3 # contify some scheduler functions # # kernel/exit.c # 2004/06/18 00:06:07-07:00 kaos@ocs.com.au +3 -3 # contify some scheduler functions # # include/linux/sched.h # 2004/06/18 00:06:07-07:00 kaos@ocs.com.au +6 -6 # contify some scheduler functions # # ChangeSet # 2004/06/18 08:16:21-07:00 greg@kroah.com # [PATCH] remove EXPORT_SYMBOL(kallsyms_lookup) # # Distros have started to ship kernels with this patch, as it seems that some # unnamed binary module authors are already abusing this function (as well as # some open source modules, like the openib code.) I could not find any valid # reason why this symbol should be exported, so here's a patch against 2.6.7 # that removes it. # # Signed-off-by: Greg Kroah-Hartman # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/kallsyms.c # 2004/06/18 00:06:07-07:00 greg@kroah.com +0 -1 # remove EXPORT_SYMBOL(kallsyms_lookup) # # ChangeSet # 2004/06/18 08:16:11-07:00 rddunlap@osdl.org # [PATCH] remove blank line in show_trace() # # Delete a blank line for more error reporting on-screen. # # Signed-off-by: Randy Dunlap # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/traps.c # 2004/06/18 00:06:07-07:00 rddunlap@osdl.org +0 -1 # remove blank line in show_trace() # # ChangeSet # 2004/06/18 08:16:00-07:00 kenneth.w.chen@intel.com # [PATCH] Hugetlb page bug fix for i386 in PAE mode # # Hit a bug check when unmap a hugetlb vma in PAE mode on i386 (and x86-64). # # Bad page state at free_hot_cold_page (in process 'a.out', page c165cc40) # flags:0x20000000 mapping:f75e1d00 mapped:0 count:0 # Backtrace: # Call Trace: # [] bad_page+0x79/0x9e # [] free_hot_cold_page+0x71/0xfa # [] unmap_hugepage_range+0xa3/0xbf # [] unmap_vmas+0xac/0x252 # [] default_wake_function+0x0/0xc # [] unmap_region+0xd8/0x145 # [] do_munmap+0xfc/0x14d # [] sys_shmdt+0xa5/0x126 # [] sys_ipc+0x23c/0x27f # [] sys_write+0x38/0x59 # [] syscall_call+0x7/0xb # # It turns out there is a bug in hugetlb_prefault(): with 3 level page table, # huge_pte_alloc() might return a pmd that points to a PTE page. It happens # if the virtual address for hugetlb mmap is recycled from previously used # normal page mmap. free_pgtables() might not scrub the pmd entry on munmap # and hugetlb_prefault skips on any pmd presence regardless what type it is. # Patch to fix the bug. # # Signed-off-by: Ken Chen # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/mm/hugetlbpage.c # 2004/06/18 00:06:07-07:00 kenneth.w.chen@intel.com +9 -2 # Hugetlb page bug fix for i386 in PAE mode # # ChangeSet # 2004/06/18 08:15:49-07:00 minyard@acm.org # [PATCH] IPMI base patch to fix channel handling and add polling # # This patch fixes some problems with handling of channel detection in the # driver. Some systems that are IPMI 1.5 do not implement the channel query # command. Also, the interface has to be fully up before the command is # ready. # # This patch also adds a polling interface; this is required for situations # where interrupts are not running, but the system must still issue IPMI # commands, like when taking a crash dump. # # It also updates the driver version to v32. # # Signed-off-by: Corey Minyard # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/ipmi_smi.h # 2004/06/18 00:06:07-07:00 minyard@acm.org +4 -0 # IPMI base patch to fix channel handling and add polling # # include/linux/ipmi_msgdefs.h # 2004/06/18 00:06:07-07:00 minyard@acm.org +1 -0 # IPMI base patch to fix channel handling and add polling # # include/linux/ipmi.h # 2004/06/18 00:06:07-07:00 minyard@acm.org +10 -0 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_watchdog.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +3 -5 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_smic_sm.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_si_intf.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +45 -16 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_msghandler.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +29 -2 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_kcs_sm.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_devintf.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1 # IPMI base patch to fix channel handling and add polling # # drivers/char/ipmi/ipmi_bt_sm.c # 2004/06/18 00:06:07-07:00 minyard@acm.org +1 -1 # IPMI base patch to fix channel handling and add polling # # ChangeSet # 2004/06/18 08:15:37-07:00 jmorris@redhat.com # [PATCH] SELinux: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Cc: David S. Miller # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/nlmsgtab.c # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +153 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/ss/services.c # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +12 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/ss/policydb.c # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +9 -1 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/nlmsgtab.c # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/security/selinux/nlmsgtab.c # # security/selinux/include/security.h # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +5 -4 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/include/flask.h # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +9 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/include/class_to_string.h # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +9 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/include/av_permissions.h # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +223 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/include/av_perm_to_string.h # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +12 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/include/av_inherit.h # 2004/06/18 00:06:06-07:00 jmorris@redhat.com +9 -0 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/hooks.c # 2004/06/18 00:06:06-07:00 jmorris@redhat.com +80 -22 # SELinux: Fine-grained Netlink support - SELinux changes # # security/selinux/Makefile # 2004/06/18 00:06:07-07:00 jmorris@redhat.com +1 -1 # SELinux: Fine-grained Netlink support - SELinux changes # # ChangeSet # 2004/06/18 08:15:25-07:00 jmorris@redhat.com # [PATCH] SELinux: Fine-grained Netlink support - add sk to netlink_send hook # # Modifies the LSM netlink_send() hook so that it takes a struct sock parameter. # SELinux will use this parameter to lookup the class of socket, which was # assigned during socket security initialization. # # Cc: David S. Miller # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/hooks.c # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +1 -1 # SELinux: Fine-grained Netlink support - add sk to netlink_send hook # # security/dummy.c # 2004/06/18 00:06:06-07:00 jmorris@redhat.com +1 -1 # SELinux: Fine-grained Netlink support - add sk to netlink_send hook # # net/netlink/af_netlink.c # 2004/06/18 00:06:06-07:00 jmorris@redhat.com +1 -1 # SELinux: Fine-grained Netlink support - add sk to netlink_send hook # # include/linux/security.h # 2004/06/18 00:06:06-07:00 jmorris@redhat.com +11 -8 # SELinux: Fine-grained Netlink support - add sk to netlink_send hook # # ChangeSet # 2004/06/18 08:15:14-07:00 jmorris@redhat.com # [PATCH] SELinux: Fine-grained Netlink support - move security_netlink_send() hook # # This patch moves the security_netlink_send() LSM hook after the user copy, so # that LSM modules can safely examine skb payload content. For SELinux, we need # to look at the Netlink message type. # # Cc: David S. Miller # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # net/netlink/af_netlink.c # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +4 -4 # SELinux: Fine-grained Netlink support - move security_netlink_send() hook # # ChangeSet # 2004/06/18 08:15:04-07:00 jmorris@redhat.com # [PATCH] SELinux: Fine-grained Netlink support - SELinux headers update # # This patch regenerates the SELinux module headers to reflect new class and # access vectors definitions. The size of the diff is misleading; much of it is # simply a change in the ordering of the automatically generated definitions. # The corresponding generation script has been changed to ensure a stable order # in the future. Please apply. # # Author: Stephen Smalley # Cc: David S. Miller # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/include/flask.h # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +12 -0 # SELinux: Fine-grained Netlink support - SELinux headers update # # security/selinux/include/class_to_string.h # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +12 -0 # SELinux: Fine-grained Netlink support - SELinux headers update # # security/selinux/include/av_permissions.h # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +350 -250 # SELinux: Fine-grained Netlink support - SELinux headers update # # security/selinux/include/av_perm_to_string.h # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +89 -3 # SELinux: Fine-grained Netlink support - SELinux headers update # # ChangeSet # 2004/06/18 08:14:53-07:00 chrisw@osdl.org # [PATCH] fix simple_strtoul base 16 handling # # I know it's simple_strtoul, but is it meant to be that simple? Fix up for # both simple_strtoul and simple_strtoull. # # simple_strtoul(0x401b, NULL, 0) = 0x401b # simple_strtoul(0X401b, NULL, 0) = 0x0 # simple_strtoul(0x401b, NULL, 16) = 0x0 # simple_strtoul(0X401b, NULL, 16) = 0x0 # # simple_strtoull(0x401b, NULL, 0) = 0x401b # simple_strtoull(0X401b, NULL, 0) = 0x0 # simple_strtoull(0x401b, NULL, 16) = 0x0 # simple_strtoull(0X401b, NULL, 16) = 0x0 # # Signed-off-by: Chris Wright # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # lib/vsprintf.c # 2004/06/18 00:06:06-07:00 chrisw@osdl.org +8 -2 # fix simple_strtoul base 16 handling # # ChangeSet # 2004/06/18 08:14:42-07:00 eger@havoc.gtf.org # [PATCH] rivafb: fb accel capabilities # # Here's the fb accel capabilities patch for rivafb. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/riva/fbdev.c # 2004/06/18 00:06:06-07:00 eger@havoc.gtf.org +6 -1 # rivafb: fb accel capabilities # # ChangeSet # 2004/06/18 08:14:31-07:00 geert@linux-m68k.org # [PATCH] fix warning in fbmem.c # # Fix a const/non-const warning. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/fb.h # 2004/06/18 00:06:06-07:00 geert@linux-m68k.org +1 -1 # fix warning in fbmem.c # # drivers/video/fbmem.c # 2004/06/18 00:06:06-07:00 geert@linux-m68k.org +13 -9 # fix warning in fbmem.c # # ChangeSet # 2004/06/18 08:14:20-07:00 eger@havoc.gtf.org # [PATCH] fix radeonfb panning and make it play nice with copyarea() # # radeonfb: fix panning corruption on a large virtual screen, Make panning # and copyarea() play nicely with each other. # # Signed-off-by: David Eger # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/aty/radeon_base.c # 2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +13 -0 # fix radeonfb panning and make it play nice with copyarea() # # drivers/video/aty/radeon_accel.c # 2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +4 -4 # fix radeonfb panning and make it play nice with copyarea() # # ChangeSet # 2004/06/18 08:14:09-07:00 lethal@Linux-SH.ORG # [PATCH] asiliantfb init fix # # asiliantfb seems to have only been partially merged (the fbmem.c bits in # particular seem to have been missed entirely). This adds them back in, # though they do seem to be present in the fbdev tree, at least they were the # last time I looked. # # These are the last bit of outstanding changes I have in the LinuxSH # tree for asiliantfb, so it would be nice to get this out of the way. # # Signed-off-by: Paul Mundt # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/fbmem.c # 2004/06/18 00:32:08-07:00 lethal@Linux-SH.ORG +4 -0 # asiliantfb init fix # # ChangeSet # 2004/06/18 08:13:58-07:00 adaplas@hotpop.com # [PATCH] More updates to rivafb driver # # 1. pass info->monspecs.modedb and info->monspecs.modedb_len to # fb_find_mode() instead of NULL, 0 since its contents are specific to the # attached display. Anyway, if info->monspecs.modedb == NULL, # fb_find_mode() will use the default database. # # 2. Added best fit algo to fb_find_mode(). # # 3. Use snprintf instead of sprintf. # # Signed-off-by: Antonino Daplas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/modedb.c # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +19 -2 # More updates to rivafb driver # # drivers/video/console/fbcon.c # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +4 -3 # More updates to rivafb driver # # ChangeSet # 2004/06/18 08:13:47-07:00 adaplas@hotpop.com # [PATCH] Updates to rivafb driver # # The patch updates rivafb to the following: # # 1. Fixed cursor corruption and simplified cursor code. # # 2. Maximized var->yres_virtual on initial mode setting. Scrolling, # therefore, defaults to y-panning which is significantly faster. # # 3. Restricted var->xres_virtual and var->yres_virtual to 0x7fff # (hardware limitation?). Otherwise, var->yres_virtual > 0x7fff + panning # will hang the GPU. # # 4. Added I2C/DDC support. This feature enables independent mode setup # to rivafb. 'stty rows n cols n' should now work correctly. This is a # configurable option. # # 5. Various/minor fixes to drawing code. # # Signed-off-by: Antonino Daplas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/riva/rivafb-i2c.c # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +209 -0 # Updates to rivafb driver # # drivers/video/riva/rivafb.h # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +24 -9 # Updates to rivafb driver # # drivers/video/riva/rivafb-i2c.c # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/video/riva/rivafb-i2c.c # # drivers/video/riva/fbdev.c # 2004/06/18 00:32:08-07:00 adaplas@hotpop.com +188 -148 # Updates to rivafb driver # # drivers/video/riva/Makefile # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +6 -2 # Updates to rivafb driver # # drivers/video/Kconfig # 2004/06/18 00:06:05-07:00 adaplas@hotpop.com +5 -0 # Updates to rivafb driver # # ChangeSet # 2004/06/18 08:13:36-07:00 eger@havoc.gtf.org # [PATCH] fbcon: prefer pan when available # # Improve heuristics to favor panning over copyarea() thanks to pseudocode # from Antonino Daplas # # Signed-off-by: David Eger # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/console/fbcon.c # 2004/06/18 00:32:09-07:00 eger@havoc.gtf.org +19 -15 # fbcon: prefer pan when available # # ChangeSet # 2004/06/18 08:13:25-07:00 eger@havoc.gtf.org # [PATCH] fb accel capabilities # # Baseline patch to make framebuffer/fbcon interaction more sane by basing the # fbcon heuristics on capabilities advertized by underlying framebuffer via the # fb_info.flags field. # # This patch updates fbcon, fb.h, and skeletonfb.c. It does *not* yet update # the drivers themselves. They should compile and work, but their hinting is # not correct yet, meaning most fb drivers will be slow until I set the flags to # the right hinting driver-by-driver # # Signed-off-by: David Eger # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/fb.h # 2004/06/18 00:32:08-07:00 eger@havoc.gtf.org +46 -6 # fb accel capabilities # # drivers/video/skeletonfb.c # 2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +7 -1 # fb accel capabilities # # drivers/video/console/fbcon.h # 2004/06/18 00:06:05-07:00 eger@havoc.gtf.org +19 -32 # fb accel capabilities # # drivers/video/console/fbcon.c # 2004/06/18 00:32:09-07:00 eger@havoc.gtf.org +50 -47 # fb accel capabilities # # ChangeSet # 2004/06/18 08:13:13-07:00 daniel@osdl.org # [PATCH] handle partial DIO write # # The fsx-linux hole fill failure problem was caused by # generic_file_aio_write_nolock() not handling the partial DIO write # correctly. Here's a patch lets DIO do the partial write, and the fallback # to buffered is done (correctly) for what is left. This fixes the hole # filling without retrying the entire i/o. This patch also applies to # 2.6.7-rc3 with some offset. # # I tested this (on ext3) with # fsx-linux -l 500000 -r 4096 -t 4096 -w 4096 -Z -N 10000 junk -R -W # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/filemap.c # 2004/06/18 00:06:05-07:00 daniel@osdl.org +1 -1 # handle partial DIO write # # fs/direct-io.c # 2004/06/18 00:06:05-07:00 daniel@osdl.org +7 -7 # handle partial DIO write # # ChangeSet # 2004/06/18 08:13:02-07:00 schwidefsky@de.ibm.com # [PATCH] s390: lost dirty bits # # The SetPageUptodate function is called for pages that are already up to # date. The arch_set_page_uptodate function of s390 may not clear the dirty # bit in that case otherwise a dirty bit which is set between the start of an # i/o for a writeback and a following call to SetPageUptodate is lost. # # Signed-off-by: Martin Schwidefsky # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/page-flags.h # 2004/06/18 00:06:04-07:00 schwidefsky@de.ibm.com +3 -9 # s390: lost dirty bits # # include/asm-s390/pgtable.h # 2004/06/18 00:06:04-07:00 schwidefsky@de.ibm.com +4 -2 # s390: lost dirty bits # # ChangeSet # 2004/06/18 08:12:51-07:00 hch@lst.de # [PATCH] fix standalone inclusion of asm-i386/dma-mapping.h # # Without this a usb-storage patch I sent fails on x86 because dma-mapping.h # uses struct device and various VM stuff without proper includes. It's fine # on ppc at least. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/dma-mapping.h # 2004/06/18 00:06:04-07:00 hch@lst.de +3 -0 # fix standalone inclusion of asm-i386/dma-mapping.h # # ChangeSet # 2004/06/18 08:12:41-07:00 jmorris@redhat.com # [PATCH] Fix sock_orphan race. # # The patch below fixes a race between sock_orphan() and # selinux_socket_sock_rcv_skb() which can lead to a null pointer deref oops # under heavy load. The sk_callback_lock is used in the patch to synchronize # access to the incoming socket's inode security state. # # This patch has been under test in the Fedora kernel for over a month # without incident. # # Author: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/hooks.c # 2004/06/18 00:32:07-07:00 jmorris@redhat.com +21 -16 # Fix sock_orphan race. # # ChangeSet # 2004/06/18 08:12:29-07:00 marcelo.tosatti@cyclades.com # [PATCH] update Marcelo CREDITS info # # Update my CREDITS information. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # CREDITS # 2004/06/18 00:06:04-07:00 marcelo.tosatti@cyclades.com +7 -6 # update Marcelo CREDITS info # # ChangeSet # 2004/06/18 08:12:18-07:00 jmorris@redhat.com # [PATCH] Add security_file_permission() to AIO paths. # # Currently, there are no LSM hooks in the AIO codepaths, which means that # LSM based access controls are not revalidated upon AIO read and write # operations. The patch below adds the security_file_permission() LSM hook # prior to the VFS aio_read()/aio_write() calls. # # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/aio.c # 2004/06/18 00:06:04-07:00 jmorris@redhat.com +7 -0 # Add security_file_permission() to AIO paths. # # ChangeSet # 2004/06/18 08:12:08-07:00 linux@dominikbrodowski.de # [PATCH] add 1 in __const_udelay() # # The "mull" instruction in __const_udelay() cuts off the lower 32 bits -- # so, it is "rounding down". This is both an issue for small ndelay()s for # _all_ values for loops_per_jiffy and for certain {n,u}delay()s for many # loops_per_jiffy values. # # Assuming # # LPJ = 1501115 # # udelay(87) # # results in # # 130597 loops to be spent. # # However, 1000 * 130597 / 1501115 is 86.999997 us, so we're actually # _rounding down_. 1000 * 130598 / 1501115 is 87.000662841, which would be # the technically correct thing to do. Of course, for the TSC case this # won't matter as the maths take some time, so the actual delay is # # 1000 * __udelay(x) / lpj + __OVERHEAD(x) # # Anybody worried about both the additional overhead and the fact that the # overhead takes some time to run should add a check # # if (unlikely(xloops < OVERHEAD)) # return; # xloops -= OVERHEAD; # # to the delay() routines in arch/i386/kernel/timers/*.c and determine # what the OVERHEAD is. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/lib/delay.c # 2004/06/18 00:06:04-07:00 linux@dominikbrodowski.de +1 -1 # add 1 in __const_udelay() # # ChangeSet # 2004/06/18 08:11:56-07:00 linux@dominikbrodowski.de # [PATCH] round up in __udelay() # # Round up in __udelay(): 2**32 / 100000 is 4294.97, so it's more intuitive # to round up, and it causes more predictable results: # # n usec delay on a 1500000 BogoMIPS system: # # n before -mull after # 1 1000 ticks 1499 ticks 1500 ticks # 10 14000 ticks 14999 ticks 15000 ticks # # n usec delay on a 100000 BogoMIPS system: # # n before -mull after # 1 0 ticks 99 ticks 100 ticks # 10 0 ticks 999 ticks 1000 ticks # 100 9000 ticks 9999 ticks 10000 ticks # # While it can be argued that some time is also spent in the delay functions, # it's better to spend _at least_ the specified time sleeping, in my humble # opinion. And the overhead of a specific ->delay() implementation should be # substracted in the specific ->delay() implementation. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/delay.h # 2004/06/18 00:06:04-07:00 linux@dominikbrodowski.de +1 -1 # round up in __udelay() # # arch/i386/lib/delay.c # 2004/06/18 00:32:10-07:00 linux@dominikbrodowski.de +1 -1 # round up in __udelay() # # ChangeSet # 2004/06/18 08:11:46-07:00 linux@dominikbrodowski.de # [PATCH] mull'ify multiplication with HZ in __const_udelay() # # John Stultz mentioned on lkml ( http://lkml.org/lkml/2004/6/5/15 ) that # calls to udelay() don't delay long enough, causing trouble e.g. in the USB # subsystem. The following patches address this issue. # # Move the multiplication of (loops_per_jiffy * xloops) with HZ into the # "mull" asm operation. This increases the accuracy of the delay functions # largely: # # n usec delay on a system with loops_per_jiffy = 1500000 : # # n before after # 1 1000 ticks 1499 ticks # 10 14000 ticks 14999 ticks # # n usec delay on a system with loops_per_jiffy = 100000 : # # n before after # 1 0 ticks 99 ticks # 10 0 ticks 999 ticks # 100 9000 ticks 9999 ticks # # As noted by Kurt Garloff, it's necessary to adjust for large # loops_per_jiffies, as the multiplication of it with HZ fails for 4GHz or # larger. So, John Stultz suggested multiplying xloops with 4 first, and # multiplying with (HZ/4). # # Signed-off-by: Dominik Brodowski # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/lib/delay.c # 2004/06/18 00:32:10-07:00 linux@dominikbrodowski.de +3 -2 # mull'ify multiplication with HZ in __const_udelay() # # ChangeSet # 2004/06/18 08:11:35-07:00 neilb@cse.unsw.edu.au # [PATCH] Fix raid1 read_balancing code. # # The meaning of mddev->in_sync changed subtly a while ago, and raid1 wasn't # changed to match. This results in raid1 read_balancing not working # properly. This patch corrects the relevant test. # # Signed-off-by: Neil Brown # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/raid1.c # 2004/06/18 00:06:03-07:00 neilb@cse.unsw.edu.au +2 -1 # Fix raid1 read_balancing code. # # ChangeSet # 2004/06/18 08:11:24-07:00 alex@clusterfs.com # [PATCH] ext3: htree readdir fix # # I've observed that ext3_htree_fill_tree() doesn't ignore empty records # (de->inode == 0). test case is very simple: turn htree on, create several # hundreds of files, remove them and look at strace ls: # # [root@victim tests]# ls -a /test/1 # . .. # # [root@victim tests]# strace ls /test/1/ # .... # getdents64(3, /* 18 entries */, 4096) = 432 # getdents64(3, /* 0 entries */, 4096) = 0 # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/ext3/namei.c # 2004/06/18 00:06:03-07:00 alex@clusterfs.com +2 -0 # ext3: htree readdir fix # # ChangeSet # 2004/06/18 08:11:13-07:00 wli@holomorphy.com # [PATCH] fix isofs ignoring noexec and mode mount options # # * Removed period check for executables in fs/isofs/inode.c # This fixes Debian BTS #162190 # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=162190 # # From: Jan Gregor # To: Debian Bug Tracking System # Subject: kernel-source-2.4.18: kernel ignores noexec and mode option in cdrom case # Message-ID: <20020924162129.A328@pisidlo> # # In /etc/fstab i have following line: # /dev/cdrom /cdrom iso9660 gid=100,noauto,ro,noexec,mode=0444,user 0 0 # # I found on one CD that some files have exec bit set. From brief view # those files has no extension (filename.ext). # # My drive is asus-1610a (ATAPI writer) connected throught scsi-emulation. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/isofs/inode.c # 2004/06/18 00:06:03-07:00 wli@holomorphy.com +0 -8 # fix isofs ignoring noexec and mode mount options # # ChangeSet # 2004/06/18 08:11:04-07:00 wli@holomorphy.com # [PATCH] fix handling of '/' embedded in filenames in isofs # # * Fix slashes in broken Acorn ISO9660 images in fs/isofs/dir.c (Darren Salt) # This fixes Debian BTS #141660. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=141660 # # From: Darren Salt # Message-ID: <4B238BA09A%linux@youmustbejoking.demon.co.uk> # To: submit@bugs.debian.org # Subject: Handle '/' in filenames in broken ISO9660 images # # [Also applicable to 2.2.x] # # There has been for some time a problem with certain CD-ROMs whose images # were generated using a particular tool on Acorn RISC OS. The problem is # that in certain catalogue entries, the extension separator character '/' # (RISC OS uses '.' and '/' the other way round) was not replaced with '.'; # thus Linux cannot properly parse this without this patch, thinking that it # is a directory separator. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/isofs/dir.c # 2004/06/18 00:06:03-07:00 wli@holomorphy.com +2 -1 # fix handling of '/' embedded in filenames in isofs # # ChangeSet # 2004/06/18 08:10:53-07:00 wli@holomorphy.com # [PATCH] fix duplicate environment variables passed to init # # * Fixed argument processing bug in init/main.c (Eric Delaunay) # This fixes Debian BTS #58566. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=58566 # # From: Eric Delaunay # Message-Id: <200002201918.UAA02327@jazz.pontchartrain.fr> # Subject: pb in handling parameters on kernel command line # To: submit@bugs.debian.org (debian bug tracking system) # # Hello, I found some bugs in kernel command line parser. AFAIK, they are not # Debian nor sparc specific but I'm not subscribed to linux-kernel mailing list # and since I'm involved with boot-floppies (mainly for sparc), I think I'm right # to report it here. Feel free to forward it upstream (I checked the latest # 2.3.46 sources and it seems these bugs are still there). # # These bugs are not release critical. The latter just not gives the user a # chance to overwrite TERM env var at boot time. It could be just # inconvenient for serial console boot, and in this case, our busybox' init is # already enforcing TERM=vt102. # Nevertheless if it could not be fixed before the release, I could even write a # workaround in busybox' init (it's just a matter of rewriting getenv()). # # At last, it does not affect sysvinit package because serial console tty is # controlled by a getty process which is reading terminal settings on its command # line (take a look in inittab for T0 entries, if any). # # Ok, here is my modest contribution to kernel hacking. I don't know much about # kernel internals but it seems that argument parsing is a bit broken. # # One trivial patch for command line like "init=/bin/sh console=prom" where # console=prom is replaced by lot of spaces in previous call to setup_arch() on # sparc, therefore the line parsed by parse_options() is really # "init=/bin/sh " and a lot of null args are pushed into argv_init. # # The other patch is for command line like "TERM=vt100" where both default & user # TERM entries are pushed into the env array. # Taking a look into /proc/1/environ, it shows up: # HOME=/ # TERM=linux # TERM=vt100 # # It appears that ash (maybe other shells too) is giving the latter entry but # glibc getenv() is giving the former. It is therefore impossible to get entry # from the user in a C program like busybox' init (used in Debian boot-floppies). # # I guess getenv() is not written to support duplicate entries, therefore the # kernel should avoid such construct. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # init/main.c # 2004/06/18 00:06:03-07:00 wli@holomorphy.com +2 -0 # fix duplicate environment variables passed to init # # ChangeSet # 2004/06/18 08:10:43-07:00 wli@holomorphy.com # [PATCH] unregister driver if probing fails in sb_card.c # # * Unregister driver if probing fails in sound/oss/sb_card.c # This fixes Debian BTS #218845. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=218845 # # From: Robin Gerard # To: submit@bugs.debian.org # Subject: no sound with kernel-image-2.6.0-test9-1-386 # Message-ID: <20031103004939.GA2071@mauritius> # # I downlaoded the kernel-image-2.6.0-test9-1-386_2.6.0-test9-1_i386.deb # and I installed it successfully. Everything works fine, except the sound. # (I run also the kernel-image-2.4.20 and the sound is ok with this kernel) # My sound card is a sb. # # First I launched modconf but no module was displayed. # # I did: modprobe sb # and I got: # # sb: Init: Done # sb: Init: Starting Probe... # kobject_register failed for OSS SndBlstr (-17) # Call Trace: # [] kobject_register+0x3a/0x40 # [] bus_add_driver+0x30/0x64 # [] driver_register+0x2d/0x34 # [] preempt_schedule+0x2a/0x48 # [] pnp_register_driver+0x28/0x58 # [] pnp_register_card_driver+0x5e/0x98 # [] sb_init+0x63/0xb5 [sb] # [] sys_init_module+0xe8/0x1f0 # [] syscall_call+0x7/0xb # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/oss/sb_card.c # 2004/06/18 00:06:03-07:00 wli@holomorphy.com +7 -1 # unregister driver if probing fails in sb_card.c # # ChangeSet # 2004/06/18 08:10:32-07:00 wli@holomorphy.com # [PATCH] lower priority of "too many keys" msg in atkbd.c # # From: "Jon Thackray" # # * Lowered priority of "too many keys" message in drivers/input/keyboard/atkbd.c # This fixes Debian BTS #239036. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=239036 # # # The keyboard under 2.6.4 seems to be behaving strangely, reporting unknown # key codes and too many keys pressed, even when no keys have been pressed. # The keyboard is connected via an 8 way KVM switch, but was working quite # acceptably under 2.4.25 with no such messages. Trying 2.6.3 is not an # option as it doesn't support the hardware properly, as previously reported. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/input/keyboard/atkbd.c # 2004/06/18 00:48:49-07:00 wli@holomorphy.com +1 -1 # lower priority of "too many keys" msg in atkbd.c # # ChangeSet # 2004/06/18 08:10:21-07:00 rddunlap@osdl.org # [PATCH] istallion printk fix # # istallion: Remove duplicate "%d" in printk(); # # Signed-off-by: Randy Dunlap # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/istallion.c # 2004/06/18 00:06:03-07:00 rddunlap@osdl.org +1 -1 # istallion printk fix # # ChangeSet # 2004/06/18 08:10:10-07:00 egmont@uhulinux.hu # [PATCH] Shift+PgUp if nr of scrolled lines is < 4 # # Using the vga console driver, if the number of the lines scrolled out is # less than four, then Shift+PageUp doesn't work. # # The bug is closely related to the 'margin' feature of scrolling, which # means that if less than four lines should remain unvisible in the direction # we are scrolling to, then we scroll a little bit more just to see those few # lines. Kind of two small magnets at the borders of the buffer. # # This bug was also reported with maybe a less clear description by Stepan # Koltsov (cc'ed just for fun) back in 2001 and he got no answer. I found it # at http://seclists.org/lists/linux-kernel/2001/Nov/0080.html # # His patch simply disables margin support and hence everythings becomes # okay, but you lose a nice feature. # # Here's a patch that retains margin support and fixes the bug. Works for # me, tested for a week. No guarantee. As I don't fully understand the code # (see also my previous mail) I'm not 100% sure that I'm doing the right # thing, so I'd prefer if someone would take a closer look at it. # # At least 2.4 and 2.6 are affected, maybe older ones too. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/video/console/vgacon.c # 2004/06/18 00:06:02-07:00 egmont@uhulinux.hu +2 -0 # Shift+PgUp if nr of scrolled lines is < 4 # # ChangeSet # 2004/06/18 08:09:59-07:00 davidel@xmailserver.org # [PATCH] epoll: replace the file lookup hash with rbtrees # # The epoll allocation for the fd lookup hash used to allocate up to 1MB # (depending on the "hint" size passed to epoll_create()) with # __get_free_pages(0), and this might lead to a "malicious" user to do # something like: # # for (i = 0; i < 1024; i++) # epoll_create(BIG-NUM); # # You can replace "malicious user" with IBM-ltp test suite, and the meaning # does not change. The above code might exhaust memory badly, even before # the file creation limit is topped. Also, the allocation was independent # from the number of fds pushed into the epoll fd hash. Using an rb-tree # ther will be not pre-allocation of the hash, and the size of the memory # used will be proportional to the number of fds pushed into the epoll fd. # The patch also removes 100 lines of code, that is never a bad thing ;) # # Signed-off-by: Davide Libenzi # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/eventpoll.c # 2004/06/18 00:06:02-07:00 davidel@xmailserver.org +93 -187 # epoll: replace the file lookup hash with rbtrees # # ChangeSet # 2004/06/18 08:09:48-07:00 rtjohnso@eecs.berkeley.edu # [PATCH] drivers/char/ipmi/ipmi_devintf.c: user/kernel pointer typo # # Judging from context, I think there's a misplaced "&" in this code that can # cause stack overflows and other nasty problems. Perhaps it's left over # from when msgdata was an array instead of a pointer? # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/ipmi/ipmi_devintf.c # 2004/06/18 00:32:07-07:00 rtjohnso@eecs.berkeley.edu +1 -1 # drivers/char/ipmi/ipmi_devintf.c: user/kernel pointer typo # # ChangeSet # 2004/06/18 08:09:37-07:00 akpm@osdl.org # [PATCH] Make update_one_process() static # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/timer.c # 2004/06/17 23:59:01-07:00 akpm@osdl.org +1 -1 # Make update_one_process() static # # include/linux/sched.h # 2004/06/18 00:32:06-07:00 akpm@osdl.org +0 -2 # Make update_one_process() static # # ChangeSet # 2004/06/18 08:09:26-07:00 vandrove@vc.cvut.cz # [PATCH] Decrease stack usage in ncpfs's ioctl # # It decreases stack consumption in one of ncpfs's paths from 3000 to 2200 # bytes (and stack portion in ncpfs ioctl code from 1336 to 452 bytes). # # - some code used large structure (with embeded 256 bytes for filename) # while it never passed filename around. Use something smaller in # ncp_conn_logged_in. Decrease 616 => 300. # # - gcc-3.3 is very bad when it comes to parallel blocks in ioctl. Split # some branches from large switch to separate functions. ncp_ioctl now # uses 152 bytes of stack (instead of 720) and biggest child 64. # # Signed-off-by: Petr Vandrovec # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/ncpfs/ncplib_kernel.h # 2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +5 -3 # Decrease stack usage in ncpfs's ioctl # # fs/ncpfs/ncplib_kernel.c # 2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +27 -15 # Decrease stack usage in ncpfs's ioctl # # fs/ncpfs/ioctl.c # 2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +160 -157 # Decrease stack usage in ncpfs's ioctl # # fs/ncpfs/dir.c # 2004/06/17 23:59:01-07:00 vandrove@vc.cvut.cz +5 -5 # Decrease stack usage in ncpfs's ioctl # # ChangeSet # 2004/06/18 08:09:16-07:00 herbert@gondor.apana.org.au # [PATCH] swsusp: remove copy_pagedir # # It can be replaced by a simple memcpy. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/power/swsusp.c # 2004/06/17 23:59:00-07:00 herbert@gondor.apana.org.au +3 -16 # swsusp: remove copy_pagedir # # kernel/power/pmdisk.c # 2004/06/17 23:59:00-07:00 herbert@gondor.apana.org.au +4 -16 # swsusp: remove copy_pagedir # # ChangeSet # 2004/06/18 08:09:05-07:00 herbert@gondor.apana.org.au # [PATCH] remove unnecessary memsets from swsusp and pmdisk # # Here's the patch that removes the memset calls from both pmdisk and swsusp. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/power/swsusp.c # 2004/06/18 00:32:12-07:00 herbert@gondor.apana.org.au +0 -1 # remove unnecessary memsets from swsusp and pmdisk # # kernel/power/pmdisk.c # 2004/06/18 00:32:12-07:00 herbert@gondor.apana.org.au +0 -1 # remove unnecessary memsets from swsusp and pmdisk # # ChangeSet # 2004/06/18 08:08:54-07:00 herbert@gondor.apana.org.au # [PATCH] omdisk memory leak fix # # Fix a couple of memory leaks in the pmdisk driver. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/power/pmdisk.c # 2004/06/18 00:32:13-07:00 herbert@gondor.apana.org.au +11 -11 # omdisk memory leak fix # # ChangeSet # 2004/06/18 08:08:43-07:00 pavel@ucw.cz # [PATCH] Fix memory leak in swsusp # # This fixes 2 memory leaks in swsusp: during relocating pagedir, eaten pages # were not properly freed in error path and even regular freeing path was # freeing one page too little. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/power/swsusp.c # 2004/06/18 00:32:13-07:00 pavel@ucw.cz +16 -11 # Fix memory leak in swsusp # # ChangeSet # 2004/06/18 08:08:32-07:00 axboe@suse.de # [PATCH] blk: move threshold unplugging # # The 'unplug on queued exceeding unplug threshold' logic only works for file # system requests currently, since it's in __make_request(). Move it where # it belongs, in elv_add_request(). This way it works for queued block sg # requests as well. # # Signed-Off-By: Jens Axboe # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/blkdev.h # 2004/06/18 08:08:26-07:00 axboe@suse.de +1 -0 # blk: move threshold unplugging # # drivers/block/ll_rw_blk.c # 2004/06/18 08:08:26-07:00 axboe@suse.de +4 -7 # blk: move threshold unplugging # # drivers/block/elevator.c # 2004/06/18 08:08:26-07:00 axboe@suse.de +8 -0 # blk: move threshold unplugging # # ChangeSet # 2004/06/18 08:08:21-07:00 axboe@suse.de # [PATCH] fix cdrom mt rainier probe # # Mt rainier probe must be deferred to media load time, since it requires a # valid media (the drive may present a different capability based on what # media is loaded). This fixes that for ide-cd and sr. # # Signed-Off-By: Jens Axboe # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/scsi/sr.c # 2004/06/18 08:08:15-07:00 axboe@suse.de +1 -15 # fix cdrom mt rainier probe # # drivers/ide/ide-cd.h # 2004/06/18 08:08:15-07:00 axboe@suse.de +0 -2 # fix cdrom mt rainier probe # # drivers/ide/ide-cd.c # 2004/06/18 08:08:15-07:00 axboe@suse.de +1 -22 # fix cdrom mt rainier probe # # drivers/cdrom/cdrom.c # 2004/06/18 08:08:15-07:00 axboe@suse.de +30 -2 # fix cdrom mt rainier probe # # ChangeSet # 2004/06/18 08:08:10-07:00 mikem@beardog.cca.cpqcorp.net # [PATCH] cciss ioctl32 update # # This patch provides a conversion routine for 32-bit user space apps that # call into a 64-bit kernel on x86_64 architectures. This is required for # the HP Array Configuration utility and the HP management agents. Without # this patch the apps will not function. # # The 2 ioctls affected are the cciss pass thru ioctls. Caveat: it spits out # 2 warnings during compilation. I've tried everything I can think of to # clean them up, but... If anyone has any helpful suggestions I'm all ears. # # Code by Stephen Cameron # Tested by Stephen Cameron & Mike Miller # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/cciss_ioctl.h # 2004/06/18 08:08:04-07:00 mikem@beardog.cca.cpqcorp.net +28 -0 # cciss ioctl32 update # # drivers/block/cciss.c # 2004/06/18 08:08:04-07:00 mikem@beardog.cca.cpqcorp.net +144 -0 # cciss ioctl32 update # # ChangeSet # 2004/06/18 08:07:59-07:00 andrea@suse.de # [PATCH] remap_file_pages() speedup # # Avoid taking down_write(mmap_sem) unless we really need it. # # Seems that the only reason we're taking it for writing is to protect # vma->vm_flags. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/fremap.c # 2004/06/17 23:58:59-07:00 andrea@suse.de +12 -5 # remap_file_pages() speedup # # ChangeSet # 2004/06/18 08:07:48-07:00 arun.sharma@intel.com # [PATCH] sys_getdents64 needs compat wrapper # # Due to different structure alignment rules in the ABI between ia32 and # ia64, certain members of the dirent structure are not guaranteed to be 8 # byte aligned on ia64. This requires a compat wrapper around these 32 bit # system calls. Other architectures may or may not have the problem, # depending on the alignment rules. # # This was observed by running /emul/ia32-linux/bin/ls on 2.6.6 which produces # kernel mode unaligned faults. # # Original patch by: Arnd Bergmann # Signed-off-by: Gordon Jin # Signed-off-by: Arun Sharma # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/compat.c # 2004/06/17 23:58:59-07:00 arun.sharma@intel.com +255 -0 # sys_getdents64 needs compat wrapper # # arch/ia64/ia32/ia32_entry.S # 2004/06/17 23:58:59-07:00 arun.sharma@intel.com +2 -2 # sys_getdents64 needs compat wrapper # # ChangeSet # 2004/06/18 08:07:37-07:00 tvignaud@mandrakesoft.com # [PATCH] checksatck.pl fixes # # - "\<" and "\>" can be safely replaced with "<" and ">" # # - "$var =~ /^string$/" is better written "$var eq 'string'" # # - $i is better written without the double quotes # # - it's not safe to use for without "my"ing the iteration variable # # - "print foreach @array" is better written "print @array" # # - declare variables # # - ".*" is useless at the end of a regexp # # - "$a[@a] = $foo" is a rather obfuscated syntax for "push @a, $foo"... # let's not opencoding language basic operators... # # - ignoring return value from a regexp is very bad: this can results in # working on previous value of $1, $2, ... # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # scripts/checkstack.pl # 2004/06/17 23:58:59-07:00 tvignaud@mandrakesoft.com +14 -15 # checksatck.pl fixes # # ChangeSet # 2004/06/18 08:07:26-07:00 ashok.raj@intel.com # [PATCH] don't create cpu/online sysfs file # # This file provides ability for caller of register_cpu() to either create a # control file, or not. This can be handy if a particular platform decides # that certain CPU's are not removable. Hence would like to not create a # control file. # # Signed-off-by: Dave Hansen # Signed-off-by: Ashok Raj # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/cpu.h # 2004/06/17 23:58:59-07:00 ashok.raj@intel.com +1 -0 # don't create cpu/online sysfs file # # drivers/base/cpu.c # 2004/06/17 23:58:59-07:00 ashok.raj@intel.com +3 -1 # don't create cpu/online sysfs file # # arch/ppc64/kernel/sysfs.c # 2004/06/17 23:58:59-07:00 ashok.raj@intel.com +10 -0 # don't create cpu/online sysfs file # # ChangeSet # 2004/06/18 08:07:15-07:00 umka@namesys.com # [PATCH] memory allocation checks in cs46xx_dsp_proc_register_scb_desc() # # Adds memory allocation checks in cs46xx_dsp_proc_register_scb_desc() # # Signed-off-by: Yury Umanets # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/pci/cs46xx/dsp_spos_scb_lib.c # 2004/06/17 23:57:06-07:00 umka@namesys.com +7 -1 # memory allocation checks in cs46xx_dsp_proc_register_scb_desc() # # ChangeSet # 2004/06/18 08:07:05-07:00 torque@ukrpost.net # [PATCH] memory allocation checks in mtdblock_open() # # Fixes memory allocation check in mtdblock_open() # # Signed-off-by: Yury Umanets # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/mtd/mtdblock.c # 2004/06/17 23:57:06-07:00 torque@ukrpost.net +1 -1 # memory allocation checks in mtdblock_open() # # ChangeSet # 2004/06/18 08:06:54-07:00 torque@ukrpost.net # [PATCH] memory allocation checks in eth1394_update() # # Adds memory allocation checks in eth1394_update(). # # Signed-off-by: Yury Umanets # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/ieee1394/eth1394.c # 2004/06/17 23:57:06-07:00 torque@ukrpost.net +4 -1 # memory allocation checks in eth1394_update() # # ChangeSet # 2004/06/18 08:06:43-07:00 ak@suse.de # [PATCH] Use numa policy API for boot time policy # # Suggested by Manfred Spraul. # # __get_free_pages had a hack to do node interleaving allocation at boot # time. This patch sets an interleave process policy using the NUMA API for # init and the idle threads instead. Before entering the user space init the # policy is reset to default again. Result is the same. # # Advantage is less code and removing of a check from a fast path. # # Removes more code than it adds. # # I verified that the memory distribution after boot is roughly the same. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/page_alloc.c # 2004/06/17 23:57:05-07:00 ak@suse.de +0 -41 # Use numa policy API for boot time policy # # mm/mempolicy.c # 2004/06/17 23:57:05-07:00 ak@suse.de +15 -3 # Use numa policy API for boot time policy # # init/main.c # 2004/06/18 00:32:11-07:00 ak@suse.de +4 -0 # Use numa policy API for boot time policy # # include/linux/mempolicy.h # 2004/06/17 23:57:05-07:00 ak@suse.de +11 -0 # Use numa policy API for boot time policy # # ChangeSet # 2004/06/18 08:06:32-07:00 wli@holomorphy.com # [PATCH] apic: make mach_default compile again # # While sweeping the APIC code two points were missed. The first is getting # the definition of BAD_APICID available to # include/asm-i386/mach-default/mach_apic.h by #including the right header, # and the second is UP local APIC without UP IO-APIC linking in # get_broadcast_physid(). # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/mach-default/mach_apic.h # 2004/06/17 23:56:25-07:00 wli@holomorphy.com +1 -0 # apic: make mach_default compile again # # arch/i386/kernel/io_apic.c # 2004/06/17 23:56:25-07:00 wli@holomorphy.com +0 -11 # apic: make mach_default compile again # # arch/i386/kernel/apic.c # 2004/06/17 23:56:25-07:00 wli@holomorphy.com +11 -0 # apic: make mach_default compile again # # ChangeSet # 2004/06/18 08:06:21-07:00 wli@holomorphy.com # [PATCH] apic: remove marking of non-present physids in phys_cpu_present_map # # Marking invalid APIC ID's in phys_cpu_present_map was intended to generate # "collisions" between APIC ID's in order to assist the ordinary bounds # checking against the broadcast physical APIC ID. However, this is bounds # checked everywhere it's necessary, and it's also not even possible to # properly bounds-check everywhere. So this patch removes that marking of # non-present physical APIC ID's. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/mach-visws/mpparse.c # 2004/06/17 23:56:23-07:00 wli@holomorphy.com +0 -8 # apic: remove marking of non-present physids in phys_cpu_present_map # # arch/i386/kernel/mpparse.c # 2004/06/17 23:56:23-07:00 wli@holomorphy.com +1 -13 # apic: remove marking of non-present physids in phys_cpu_present_map # # ChangeSet # 2004/06/18 08:06:09-07:00 wli@holomorphy.com # [PATCH] apic: fix kicking of non-present cpus # # The following patch repairs kicking of non-present cpus by making # cpu_present_to_apicid() bounds-check its argument. It also corrects the # same issue on NUMA-Q by correctly passing the generated artificial APIC ID # instead of the raw value discovered in the MP table. # # A miscellaneous compilefix for CONFIG_ACPI_BOOT is also included for # completeness. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/mach-visws/mach_apic.h # 2004/06/17 23:55:40-07:00 wli@holomorphy.com +4 -1 # apic: fix kicking of non-present cpus # # include/asm-i386/mach-default/mach_apic.h # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +4 -1 # apic: fix kicking of non-present cpus # # include/asm-i386/apic.h # 2004/06/17 23:55:40-07:00 wli@holomorphy.com +2 -0 # apic: fix kicking of non-present cpus # # arch/i386/kernel/mpparse.c # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +4 -4 # apic: fix kicking of non-present cpus # # arch/i386/kernel/io_apic.c # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +1 -1 # apic: fix kicking of non-present cpus # # ChangeSet # 2004/06/18 08:05:58-07:00 wli@holomorphy.com # [PATCH] APIC enumeration fixes # # The following patch appears sound according to an audit to ensure that all # of the codepaths where it was introduced were called after the APIC # fixmappings were set up. # # This patch introduces get_physical_broadcast(), which checks the version ID # of the local APIC to determine whether it's a serial APIC or xAPIC, and # returns the correct physical broadcast ID. It replaces all uses of # APIC_BROADCAST_ID and IO_APIC_MAX_ID with this in order to ensure. It also # changes the checks during MP table parsing so the APIC ID is checked in # tandem with the version number. # # I'm holding out for some kind of testing to get an idea of whether this # covers the cases or introduces regressions, or whatever. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/mpspec_def.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +1 -0 # APIC enumeration fixes # # include/asm-i386/mach-visws/mach_apic.h # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +0 -1 # APIC enumeration fixes # # include/asm-i386/mach-summit/mach_mpspec.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5 # APIC enumeration fixes # # include/asm-i386/mach-summit/mach_apic.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1 # APIC enumeration fixes # # include/asm-i386/mach-numaq/mach_mpspec.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5 # APIC enumeration fixes # # include/asm-i386/mach-numaq/mach_apic.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1 # APIC enumeration fixes # # include/asm-i386/mach-generic/mach_mpspec.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5 # APIC enumeration fixes # # include/asm-i386/mach-generic/mach_apic.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1 # APIC enumeration fixes # # include/asm-i386/mach-es7000/mach_mpspec.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5 # APIC enumeration fixes # # include/asm-i386/mach-es7000/mach_apic.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1 # APIC enumeration fixes # # include/asm-i386/mach-default/mach_mpspec.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5 # APIC enumeration fixes # # include/asm-i386/mach-default/mach_apic.h # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +0 -6 # APIC enumeration fixes # # include/asm-i386/mach-bigsmp/mach_mpspec.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -5 # APIC enumeration fixes # # include/asm-i386/mach-bigsmp/mach_apic.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -1 # APIC enumeration fixes # # include/asm-i386/genapic.h # 2004/06/17 23:55:23-07:00 wli@holomorphy.com +0 -2 # APIC enumeration fixes # # arch/i386/mach-visws/mpparse.c # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +10 -2 # APIC enumeration fixes # # arch/i386/kernel/mpparse.c # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +30 -2 # APIC enumeration fixes # # arch/i386/kernel/io_apic.c # 2004/06/18 00:32:15-07:00 wli@holomorphy.com +18 -9 # APIC enumeration fixes # # ChangeSet # 2004/06/18 08:05:47-07:00 akpm@osdl.org # [PATCH] i386 uninline some bitops # # Uninline the non-leaf bit search functions. Saves 9 kbytes from my vmlinux. # # And gratuitously s/__inline__/inline/ # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/lib/bitops.c # 2004/06/17 23:55:22-07:00 akpm@osdl.org +70 -0 # i386 uninline some bitops # # include/asm-i386/bitops.h # 2004/06/17 23:55:22-07:00 akpm@osdl.org +27 -77 # i386 uninline some bitops # # arch/i386/lib/bitops.c # 2004/06/17 23:55:22-07:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/i386/lib/bitops.c # # arch/i386/lib/Makefile # 2004/06/17 23:55:22-07:00 akpm@osdl.org +2 -3 # i386 uninline some bitops # # ChangeSet # 2004/06/18 08:05:36-07:00 wli@holomorphy.com # [PATCH] x86_64 numa cpumask build fix # # arch/x86_64/mm/numa.c: In function `numa_initmem_init': # arch/x86_64/mm/numa.c:185: error: incompatible types in assignment # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/x86_64/mm/numa.c # 2004/06/17 23:53:45-07:00 wli@holomorphy.com +1 -1 # x86_64 numa cpumask build fix # # ChangeSet # 2004/06/18 08:05:25-07:00 tom.l.nguyen@intel.com # [PATCH] msi TARGET_CPUS fix # # Somehow the change in TARGET_CPUS generated this error in UP environment. # Patch below will fix it. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/msi.h # 2004/06/17 23:53:44-07:00 tom.l.nguyen@intel.com +1 -1 # msi TARGET_CPUS fix # # ChangeSet # 2004/06/18 08:05:14-07:00 kevcorry@us.ibm.com # [PATCH] dm: dm-raid1.c: Use list_for_each_entry_safe # # dm-raid1.c: In rh_exit(), use list_for_each_entry_safe instead of # list_for_each_safe. # # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-raid1.c # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +2 -4 # dm: dm-raid1.c: Use list_for_each_entry_safe # # ChangeSet # 2004/06/18 08:05:03-07:00 kevcorry@us.ibm.com # [PATCH] dm: dm-raid1.c: Make delayed_bios a bio_list # # dm-raid1.c: Make struct region::delayed_bios a bio_list instead of a bio*. # This will ensure the queued bios are kept in the proper order. # # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-raid1.c # 2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +7 -10 # dm: dm-raid1.c: Make delayed_bios a bio_list # # ChangeSet # 2004/06/18 08:04:52-07:00 kevcorry@us.ibm.com # [PATCH] dm: dm-io: Error handling # # dm-io: Proper error handling when someone is trying to read from multiple # regions. # # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-io.c # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +12 -2 # dm: dm-io: Error handling # # ChangeSet # 2004/06/18 08:04:41-07:00 kevcorry@us.ibm.com # [PATCH] dm: Use structure assignments instead of memcpy # # Use structure assignments instead of memcpy's. # [Suggested by akpm during kcopyd review.] # # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/kcopyd.c # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +2 -2 # dm: Use structure assignments instead of memcpy # # drivers/md/dm.c # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +1 -1 # dm: Use structure assignments instead of memcpy # # drivers/md/dm-table.c # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +2 -2 # dm: Use structure assignments instead of memcpy # # drivers/md/dm-snap.c # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +1 -1 # dm: Use structure assignments instead of memcpy # # drivers/md/dm-raid1.c # 2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +2 -2 # dm: Use structure assignments instead of memcpy # # ChangeSet # 2004/06/18 08:04:32-07:00 kevcorry@us.ibm.com # [PATCH] dm: Create/destroy kcopyd on demand. # # Create/destroy kcopyd on demand. # # This changes kcopyd to initialize its mempool and workqueue only when a # client specifically needs to use it. # # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/kcopyd.h # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -3 # dm: Create/destroy kcopyd on demand. # # drivers/md/kcopyd.c # 2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +61 -27 # dm: Create/destroy kcopyd on demand. # # drivers/md/dm.h # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -3 # dm: Create/destroy kcopyd on demand. # # drivers/md/dm.c # 2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +0 -1 # dm: Create/destroy kcopyd on demand. # # ChangeSet # 2004/06/18 08:04:21-07:00 kevcorry@us.ibm.com # [PATCH] dm: Documentation # # Device-Mapper documentation. # # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/device-mapper/zero.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +37 -0 # dm: Documentation # # Documentation/device-mapper/striped.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +58 -0 # dm: Documentation # # Documentation/device-mapper/linear.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +61 -0 # dm: Documentation # # Documentation/device-mapper/kcopyd.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +47 -0 # dm: Documentation # # Documentation/device-mapper/dm-io.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +75 -0 # dm: Documentation # # Documentation/device-mapper/zero.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/zero.txt # # Documentation/device-mapper/striped.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/striped.txt # # Documentation/device-mapper/linear.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/linear.txt # # Documentation/device-mapper/kcopyd.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/kcopyd.txt # # Documentation/device-mapper/dm-io.txt # 2004/06/17 23:53:44-07:00 kevcorry@us.ibm.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/device-mapper/dm-io.txt # # ChangeSet # 2004/06/18 08:04:10-07:00 christophe@saout.de # [PATCH] Device-mapper: dm-zero flushing fix # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-zero.c # 2004/06/17 23:53:43-07:00 christophe@saout.de +2 -1 # Device-mapper: dm-zero flushing fix # # ChangeSet # 2004/06/18 08:03:59-07:00 kevcorry@us.ibm.com # [PATCH] dm: dm-zero version # # Add missing dm-zero version number. # # From: Alasdair Kergon # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-zero.c # 2004/06/18 00:32:17-07:00 kevcorry@us.ibm.com +1 -0 # dm: dm-zero version # # ChangeSet # 2004/06/18 08:03:48-07:00 agk@redhat.com # [PATCH] Device-mapper: dm-zero # # Add dm-zero target # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-zero.c # 2004/06/18 00:32:17-07:00 agk@redhat.com +96 -0 # Device-mapper: dm-zero # # drivers/md/dm-zero.c # 2004/06/18 00:32:17-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-zero.c # # drivers/md/Makefile # 2004/06/17 23:53:43-07:00 agk@redhat.com +1 -0 # Device-mapper: dm-zero # # drivers/md/Kconfig # 2004/06/17 23:53:43-07:00 agk@redhat.com +7 -0 # Device-mapper: dm-zero # # ChangeSet # 2004/06/18 08:03:37-07:00 agk@redhat.com # [PATCH] Device-mapper: mirroring # # Add mirror target. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-raid1.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +1283 -0 # Device-mapper: mirroring # # drivers/md/dm-log.h # 2004/06/17 23:53:43-07:00 agk@redhat.com +124 -0 # Device-mapper: mirroring # # drivers/md/dm-log.c # 2004/06/17 23:53:43-07:00 agk@redhat.com +629 -0 # Device-mapper: mirroring # # drivers/md/dm-raid1.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-raid1.c # # drivers/md/dm-log.h # 2004/06/17 23:53:43-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-log.h # # drivers/md/dm-log.c # 2004/06/17 23:53:43-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-log.c # # drivers/md/Makefile # 2004/06/18 00:32:17-07:00 agk@redhat.com +2 -0 # Device-mapper: mirroring # # drivers/md/Kconfig # 2004/06/18 00:32:17-07:00 agk@redhat.com +7 -0 # Device-mapper: mirroring # # ChangeSet # 2004/06/18 08:03:25-07:00 kevcorry@us.ibm.com # [PATCH] dm: Fix error cleanup in dm_create_persistent() # # dm-exception-store.c: Fix error cleanup in dm_create_persistent(). # This was originally found by chrisw during code review. # # From: Dave Olien # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-exception-store.c # 2004/06/17 23:53:43-07:00 kevcorry@us.ibm.com +2 -2 # dm: Fix error cleanup in dm_create_persistent() # # ChangeSet # 2004/06/18 08:03:15-07:00 agk@redhat.com # [PATCH] Device-mapper: snapshots # # Add snapshot target # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-snap.h # 2004/06/17 23:53:43-07:00 agk@redhat.com +161 -0 # Device-mapper: snapshots # # drivers/md/dm-snap.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +1213 -0 # Device-mapper: snapshots # # drivers/md/dm-snap.h # 2004/06/17 23:53:43-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-snap.h # # drivers/md/dm-snap.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-snap.c # # drivers/md/dm-exception-store.c # 2004/06/18 00:32:17-07:00 agk@redhat.com +648 -0 # Device-mapper: snapshots # # drivers/md/Makefile # 2004/06/18 00:32:17-07:00 agk@redhat.com +2 -0 # Device-mapper: snapshots # # drivers/md/Kconfig # 2004/06/18 00:32:17-07:00 agk@redhat.com +6 -0 # Device-mapper: snapshots # # drivers/md/dm-exception-store.c # 2004/06/18 00:32:17-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-exception-store.c # # ChangeSet # 2004/06/18 08:03:03-07:00 kevcorry@us.ibm.com # [PATCH] kcopyd commentary # # We're also working on some general documentation which will go in # Documentation/device-mapper and will include more detailed information # about the core driver and the other sub-modules. We'll try to submit those # patches in the near future. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/kcopyd.h # 2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +4 -0 # kcopyd commentary # # drivers/md/kcopyd.c # 2004/06/18 00:32:16-07:00 kevcorry@us.ibm.com +4 -0 # kcopyd commentary # # ChangeSet # 2004/06/18 08:02:55-07:00 kevcorry@us.ibm.com # [PATCH] dm: kcopyd: No need to lock pages # # No need to lock kcopyd pages. # # From: Alasdair Kergon # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/kcopyd.c # 2004/06/18 00:32:18-07:00 kevcorry@us.ibm.com +0 -2 # dm: kcopyd: No need to lock pages # # ChangeSet # 2004/06/18 08:02:44-07:00 kevcorry@us.ibm.com # [PATCH] dm: kcopyd: remove superfluous INIT_LIST_HEADs # # Remove superfluous kcopyd INIT_LIST_HEAD. # # From: Alasdair Kergon # Signed-off-by: Kevin Corry # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/kcopyd.c # 2004/06/18 00:32:18-07:00 kevcorry@us.ibm.com +0 -4 # dm: kcopyd: remove superfluous INIT_LIST_HEADs # # ChangeSet # 2004/06/18 08:02:33-07:00 agk@redhat.com # [PATCH] Device-mapper: kcopyd # # Add kcopyd - a daemon for copying regions of block devices around in an # efficient manner. Multiple destinations can be specified for a copy. # Designed to perform well both with many small chunks or few large chunks. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/kcopyd.h # 2004/06/18 00:32:18-07:00 agk@redhat.com +41 -0 # Device-mapper: kcopyd # # drivers/md/kcopyd.c # 2004/06/18 00:32:18-07:00 agk@redhat.com +667 -0 # Device-mapper: kcopyd # # drivers/md/kcopyd.h # 2004/06/18 00:32:18-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/kcopyd.h # # drivers/md/kcopyd.c # 2004/06/18 00:32:18-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/kcopyd.c # # drivers/md/dm.h # 2004/06/18 00:32:16-07:00 agk@redhat.com +3 -0 # Device-mapper: kcopyd # # drivers/md/dm.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +1 -0 # Device-mapper: kcopyd # # drivers/md/Makefile # 2004/06/18 00:32:17-07:00 agk@redhat.com +1 -1 # Device-mapper: kcopyd # # ChangeSet # 2004/06/18 08:02:21-07:00 agk@redhat.com # [PATCH] dm-io: device-mapper i/o library for kcopyd # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/dm-io.h # 2004/06/17 23:53:42-07:00 agk@redhat.com +77 -0 # dm-io: device-mapper i/o library for kcopyd # # mm/mempool.c # 2004/06/17 23:53:42-07:00 agk@redhat.com +0 -6 # dm-io: device-mapper i/o library for kcopyd # # drivers/md/dm-io.h # 2004/06/17 23:53:42-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-io.h # # drivers/md/dm-io.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +637 -0 # dm-io: device-mapper i/o library for kcopyd # # drivers/md/Makefile # 2004/06/18 00:32:18-07:00 agk@redhat.com +1 -1 # dm-io: device-mapper i/o library for kcopyd # # drivers/md/dm-io.c # 2004/06/18 00:32:16-07:00 agk@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-io.c # # ChangeSet # 2004/06/18 08:02:10-07:00 bogdan.costescu@iwr.uni-heidelberg.de # [PATCH] 3c59x: support for ATI Radeon 9100 IGP # # The following patch adds support for the 3Com networking core found in the # ATI Radeon 9100 IGP southbridge used on boards like Asus P4R800-VM. # # The main point of this patch is using HAS_MII instead of HAS_NWAY for the # definition of the board. All the previous trials since the end of last # year used HAS_NWAY which disables the Tx part of the transceiver; using # HAS_NWAY was the way all 3Com Cyclone and Tornado chips worked, as they had # the transceiver integrated. The ATI solution has an external transceiver # and I had to physically see the different chip on the board (the board was # provided by ATI) to finally understand that it needs the HAS_MII # definition... I'm still waiting for some docs from ATI to clarify if this # is the correct way of handling this chip and if there are any differences # w.r.t EEPROM handling, but as it appears to work and was also confirmed by # other testers, I don't want to keep owners of such boards away from their # networks :-) # # The textual identification was a bit hard to decide; it's called # "3c920B-EMB-WNM" in the Windows .INF file that Asus provides for their # boards. As this name was already used for PCI ID 9210, I added the # paranthesis which specifies where this chip is found. # # The Scyld driver defines FEATURE_TORNADO to include HAS_NWAY. This board # would then probably need to not be defined with FEATURE_TORNADO, but the # same as in this patch. # # I would like to publicly thank Tyson Vickers for both ideas and patience # during the last few weeks. He managed to get the driver working by # randomly setting driver parameters :-) But then he contacted me and worked # with me towards the solution. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/net/3c59x.c # 2004/06/17 23:53:42-07:00 bogdan.costescu@iwr.uni-heidelberg.de +8 -4 # 3c59x: support for ATI Radeon 9100 IGP # # ChangeSet # 2004/06/18 08:01:58-07:00 thomas@winischhofer.net # [PATCH] sisfb update 1.7.10 # # attached is an update for the sisfb driver to version 1.7.10. # # This update includes # # - fixes for pure 64bit and 32/64bit mixed systems (add ioctl conversion; # fix variable sizes, etc; REQUIRED for current X.org/XFree86 on 64bit # systems, even if pure 64bit), # # - fixes for 301C video bridge, (scales TV output correctly now) # # - fixes for 1600x1200 and 1400x1050 LCD panels, # # - many fixes for 661/741/760 (amongst others, proper LFB support for the # 760 and corrections for SiS' new BIOS data layout; would lead to display # corruption with old driver) # # - add support for many modes for LCD which were unsupported previously, # # - add support for HiVision and YPbPr HDTV # # - "vga=" statement now honoured properly (sisfb will set the same mode as # the kernel did by default) # # - use LCD native resolution mode if no mode is given # # - a major clean up of main driver code, # # - radical removal of duplicate (or nearly duplicate) code, # # - switched to 2.6 module_param macros, # # - enhanced communication with the X driver, # # - added eventual POSTing of SiS300/305 card for non-x86 archs, # # - added ability to relocate the image on the TV screen using a userland # tool, # # - added Documentation/fb/sisfb.txt (why the heck was this missing?!) # # - small fix for SiS DRM driver (match 32/64bit fixes mentioned above) # (cast the data passed to sis_free as u32) # # - make driver re-entrant by avoiding static structures and variables. # # As usual, heavily tested. The mode switching code is even lab-tested by # SiS (although 100% written by me). Please apply asap (especially since # 64bit systems were not properly supported previously; as mentioned, current # X.org/XFree86 needs this update for proper communication with the # framebuffer driver on 64bit systems. X crashes on such systems with the # old driver). # # Signed-off-by: Thomas Winischhofer # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/video/sisfb.h # 2004/06/17 23:53:42-07:00 thomas@winischhofer.net +80 -171 # sisfb update 1.7.10 # # drivers/video/sis/vstruct.h # 2004/06/17 23:53:42-07:00 thomas@winischhofer.net +58 -100 # sisfb update 1.7.10 # # drivers/video/sis/vgatypes.h # 2004/06/17 23:53:42-07:00 thomas@winischhofer.net +62 -103 # sisfb update 1.7.10 # # drivers/video/sis/sis_main.h # 2004/06/17 23:53:42-07:00 thomas@winischhofer.net +365 -704 # sisfb update 1.7.10 # # drivers/video/sis/sis_main.c # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +3762 -3016 # sisfb update 1.7.10 # # drivers/video/sis/sis_accel.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +140 -264 # sisfb update 1.7.10 # # drivers/video/sis/sis_accel.c # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +188 -187 # sisfb update 1.7.10 # # drivers/video/sis/sis.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +497 -2 # sisfb update 1.7.10 # # drivers/video/sis/osdef.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +45 -65 # sisfb update 1.7.10 # # drivers/video/sis/oem310.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +32 -196 # sisfb update 1.7.10 # # drivers/video/sis/oem300.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +3 -5 # sisfb update 1.7.10 # # drivers/video/sis/initdef.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +85 -37 # sisfb update 1.7.10 # # drivers/video/sis/init301.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +132 -60 # sisfb update 1.7.10 # # drivers/video/sis/init.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +198 -607 # sisfb update 1.7.10 # # drivers/video/sis/init.c # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +961 -1060 # sisfb update 1.7.10 # # Documentation/fb/sisfb.txt # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +158 -0 # sisfb update 1.7.10 # # drivers/video/sis/init301.c # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +3425 -4113 # sisfb update 1.7.10 # # drivers/video/sis/310vtbl.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +507 -1122 # sisfb update 1.7.10 # # drivers/video/sis/300vtbl.h # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +346 -458 # sisfb update 1.7.10 # # drivers/char/drm/sis_mm.c # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +2 -2 # sisfb update 1.7.10 # # Documentation/ioctl-number.txt # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +2 -0 # sisfb update 1.7.10 # # Documentation/fb/sisfb.txt # 2004/06/17 23:53:41-07:00 thomas@winischhofer.net +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/fb/sisfb.txt # # ChangeSet # 2004/06/18 08:01:45-07:00 paul@serice.net # [PATCH] iso9660: NFS fix # # Make all inode numbers unique for images less than 128GB in size. Required # for knfsd. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/iso_fs.h # 2004/06/17 23:53:41-07:00 paul@serice.net +6 -12 # iso9660: NFS fix # # fs/isofs/inode.c # 2004/06/18 00:32:11-07:00 paul@serice.net +4 -2 # iso9660: NFS fix # # fs/isofs/dir.c # 2004/06/18 00:32:11-07:00 paul@serice.net +12 -3 # iso9660: NFS fix # # ChangeSet # 2004/06/18 08:01:34-07:00 paul@serice.net # [PATCH] iso9660: fix handling of inodes beyond 4GB # # This is my fourth attempt to patch the isofs code. It is similar to the last # posting except this one implements the NFS get_parent() method which has # always been missing. # # The original problem I set out to addresses is that the current iso9660 file # system cannot reach inodes located beyond the 4GB barrier. This is caused by # using the inode number as the byte offset of the inode data. Being 32-bits # wide, the inode number is unable to reach inode data that does not reside on # the first 4GB of the file system. # # This causes real problems with "growisofs" # # http://fy.chalmers.se/~appro/linux/DVD+RW/#isofs4gb # # and my pet project "shunt" # # http://www.serice.net/shunt/ # # This patch switches the isofs code from iget() to iget5_locked() which allows # extra data to be passed into isofs_read_inode() so that inode data anywhere on # the disk can be reached. # # The inode number scheme was also changed. Continuing to use the byte offset # would have resulted in non-unique inodes in many common situations, but # because the inode number no longer plays any role in reading the meta-data off # the disk, I was free to set the inode number to some unique characteristic of # the file. I have chosen to use the block offset which is also 32-bits wide. # # Lastly, the pre-patch code uses the default export_operations to handle # accessing the file system through NFS. The problem with this is that the # default NFS operations assume that iget() works which is no longer the case # because of the necessity of switching to iget5_locked(). So, I had to # implement the NFS operations too. As a bonus, I went ahead and implemented # the NFS get_parent() method which has always been missing. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/isofs/export.c # 2004/06/17 23:53:41-07:00 paul@serice.net +228 -0 # iso9660: fix handling of inodes beyond 4GB # # include/linux/iso_fs_i.h # 2004/06/17 23:53:41-07:00 paul@serice.net +4 -1 # iso9660: fix handling of inodes beyond 4GB # # include/linux/iso_fs.h # 2004/06/18 00:32:20-07:00 paul@serice.net +66 -0 # iso9660: fix handling of inodes beyond 4GB # # fs/isofs/rock.c # 2004/06/17 23:53:41-07:00 paul@serice.net +7 -8 # iso9660: fix handling of inodes beyond 4GB # # fs/isofs/namei.c # 2004/06/17 23:53:41-07:00 paul@serice.net +21 -9 # iso9660: fix handling of inodes beyond 4GB # # fs/isofs/inode.c # 2004/06/18 00:32:20-07:00 paul@serice.net +104 -53 # iso9660: fix handling of inodes beyond 4GB # # fs/isofs/export.c # 2004/06/17 23:53:41-07:00 paul@serice.net +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/isofs/export.c # # fs/isofs/dir.c # 2004/06/18 00:32:20-07:00 paul@serice.net +3 -3 # iso9660: fix handling of inodes beyond 4GB # # fs/isofs/Makefile # 2004/06/17 23:53:41-07:00 paul@serice.net +1 -1 # iso9660: fix handling of inodes beyond 4GB # # ChangeSet # 2004/06/18 08:01:23-07:00 tim@physik3.uni-rostock.de # [PATCH] BSD accounting format rework # # BSD accounting format rework: # # Use all explicit and implicit padding in struct acct to # # - correctly report 32 bit uid/gid, # - correctly report jobs (e.g., daemons) running longer than 497 days, # - increase the precision of ac_etime from 2^-13 to 2^-20 # (i.e., from ~6 hours to ~1 min. after a year) # - store the current AHZ value. # - allow cross-platform processing of the accounting file # (limited for m68k which has a different size struct acct). # - introduce versioning for smooth transition to incompatible formats in # the future. Currently the following version numbers are defined: # 0: old format (until 2.6.7) with 16 bit uid/gid # 1: extended variant (binary compatible to v0 on M68K) # 2: extended variant (binary compatible to v0 on everything except M68K) # 3: a new binary incompatible format (64 bytes) # 4: new binary incompatible format (128 bytes). # layout of its first 64 bytes is the same as for v3. # 5: marks second half of new binary incompatible format (128 bytes) # (layout is not yet defined) # # All this is accomplished without breaking binary compatibility. 32 bit # uid/gid support is compatible with the patch previously floating around and # used e.g. by Red Hat. # # This patch also introduces a config option for a new, binary incompatible # "version 3" format that # # - is uniform across and properly aligned on all platforms # - stores pid and ppid # - uses AHZ==100 on all platforms (allows to report longer times) # # Much of the compatibility glue goes away when v1/v2 support is removed from # the kernel. Such a patch is at # # http://www.physik3.uni-rostock.de/tim/kernel/2.7/acct-cleanup-04.patch # # and might be applied in the 2.7 timeframe. # # The new v3 format is source compatible with current GNU acct tools (6.3.5). # However, current GNU acct tools can be compiled for only one format. As there # is no way to pass the kernel configuration to userspace, with my patch it will # still only support the old v2 format. Only if v1/v2 support is removed from # the kernel, recompiling GNU acct tools will yield v3 support. # # A preliminary take at the corresponding work on cross-platform userspace tools # (GNU acct package) is at # # http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/ # # This version of the package is able to read any of the v0/v2/v3 formats, # regardless of byte-order (untested), even within the same file. # Cross-platform compatibility with m68k (v1 format) is not yet implemented, but # native use on m68k should work (untested). pid and ppid are currently only # shown by the dump-acct utility. # # Thanks to Arthur Corliss, Albert Cahalan and Ragnar Kjørstad for their # comments, and to Albert Cahalan for the u64->IEEE float conversion code. # # Signed-off-by: Tim Schmielau # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/acct.c # 2004/06/17 23:53:41-07:00 tim@physik3.uni-rostock.de +97 -8 # BSD accounting format rework # # init/Kconfig # 2004/06/17 23:53:41-07:00 tim@physik3.uni-rostock.de +12 -0 # BSD accounting format rework # # include/linux/acct.h # 2004/06/17 23:53:41-07:00 tim@physik3.uni-rostock.de +120 -25 # BSD accounting format rework # # ChangeSet # 2004/06/18 08:01:12-07:00 alan@redhat.com # [PATCH] make the 3c59x/3c90x driver somewhat more reliable # # The existing driver violates basic PCI rules in several places making it # unusable for basic things like DHCP in Fedora Core. This patch removes all # the situations I can find where it writes to the device while in D3 state # and breaks stuff. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/net/3c59x.c # 2004/06/18 00:32:18-07:00 alan@redhat.com +34 -9 # make the 3c59x/3c90x driver somewhat more reliable # # ChangeSet # 2004/06/18 08:01:01-07:00 bwindle@fint.org # [PATCH] fix 3c59x.c to allow 3c905c 100bT-FD # # Fix the 3c905C 10/100 transceiver initialisation woes. # # (This was reverted from 2.6.7-rcX, but the bug reporter said the failure # turned out to be unrepeatable). # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/net/3c59x.c # 2004/06/18 00:32:20-07:00 bwindle@fint.org +1 -1 # fix 3c59x.c to allow 3c905c 100bT-FD # # ChangeSet # 2004/06/18 08:00:52-07:00 joris@eljakim.nl # [PATCH] Validate PM-Timer rate at boot time # # Add a check to the PM-Timer initialization code. It validates the PM-Timer # rate against PIT channel 2 and rejects the PM-Timer if its rate is not # withing 5% of the expected number. # # Rationale: # # The PMTMR timers of certain (older) mainboards are running at invalid # rates, often much faster than the rate expected by the PM-Timer code. This # causes the system clock to run much too fast. See also # http://bugme.osdl.org/show_bug.cgi?id=2375 # # Possible workarounds are disabling the PM-Timer in the kernel config or # disabling the PM-Timer at boot time through the "clock=tsc" parameter. # However, we believe it is more user friendly to automatically validate the # PM-Timer rate at boot time before using it as the system time source. # # Tested by me (with broken timer) and John Stultz (with good timer) and # believed to be ok. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/timers/timer_pm.c # 2004/06/17 23:53:40-07:00 joris@eljakim.nl +38 -0 # Validate PM-Timer rate at boot time # # ChangeSet # 2004/06/18 08:00:41-07:00 willy@debian.org # [PATCH] ahc1542 !CONFIG_MCA build fix # # The old 1542 scsi driver is both ISA and MCA. The MCA portions are disabled # when !CONFIG_MCA through the typical wrapper scheme (a la pci.h and # !CONFIG_PCI). However... the driver unconditionally includes linux/mca.h # which in turn unconditionally includes asm/mca.h. # # This breaks drivers on platforms with ISA but not MCA, like alpha. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/mca.h # 2004/06/17 23:53:40-07:00 willy@debian.org +2 -0 # ahc1542 !CONFIG_MCA build fix # # ChangeSet # 2004/06/18 08:00:30-07:00 mingo@elte.hu # [PATCH] x86: remove io_apic_sync # # The patch below gets rid of io_apic_sync(). # # io_apic_sync() was introduced in 2.1.104 and it was originally done for # masking and unmasking as well. Later the unmasking use got removed but the # masking use lingered around. I dont think it was ever justified to do it # and clearly since the lack of io_apic_sync() didnt break some of the other # writes we do to the IO-APIC registers, it must be unnecessary in the # masking case too. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/io_apic.h # 2004/06/17 23:49:30-07:00 mingo@elte.hu +0 -9 # x86: remove io_apic_sync # # arch/i386/kernel/io_apic.c # 2004/06/18 00:32:15-07:00 mingo@elte.hu +0 -3 # x86: remove io_apic_sync # # ChangeSet # 2004/06/18 08:00:20-07:00 mingo@elte.hu # [PATCH] x86: remove APIC_LOCKUP_DEBUG # # the patch below gets rid of APIC_LOCKUP_DEBUG. It has been in the kernel # for more than 3 years and the message was only reported once during that # period of time - and even in that case it was a side-effect of a really bad # crash. The lockup workaround works, the debugging code can be moved out. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/io_apic.c # 2004/06/18 00:32:21-07:00 mingo@elte.hu +0 -21 # x86: remove APIC_LOCKUP_DEBUG # # ChangeSet # 2004/06/18 08:00:09-07:00 pavel@ucw.cz # [PATCH] io_apic.c code consolidation # # This cleans up io_apic.c a bit -- I do not really like 4 copies of same # code. # # Ingo said: # # yeah, agreed - i checked & test it, it's ok. I made a small # modification (see the patch below) to uninline the __modify_IO_APIC_irq() # function - shaving 0.5K off the kernel's size. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/io_apic.c # 2004/06/18 00:32:21-07:00 pavel@ucw.cz +16 -51 # io_apic.c code consolidation # # ChangeSet # 2004/06/18 07:59:58-07:00 nickpiggin@yahoo.com.au # [PATCH] Fix read() vs truncate race # # do_generic_mapping_read() # { # isize1 = i_size_read(); # ... # readpage # copy_to_user up to isize1; # } # # readpage() # { # isize2 = i_size_read(); # ... # read blocks # ... # zero-fill all blocks past isize2 # } # # If a second thread runs truncate and shrinks i_size, so isize1 and isize2 are # different, the read can return up to a page of zero-fill that shouldn't really # exist. # # The trick is to read isize1 after doing the readpage. I realised this is the # right way to do it without having to change the readpage API. # # The patch should not cost any cycles when reading from pagecache. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/filemap.c # 2004/06/18 00:32:09-07:00 nickpiggin@yahoo.com.au +50 -26 # Fix read() vs truncate race # # ChangeSet # 2004/06/18 07:59:47-07:00 akpm@osdl.org # [PATCH] invalidate_inodes2(): mark pages not uptodate # # Andrea Arcangeli points out that invalidate_inode_pages2() is # supposed to mark mapped-into-pagetable pages as not uptodate so that next time # someone faults the page in we will go get a new version from backing store. # # The callers are the direct-io code and the NFS "something changed on the # server" code. In both these cases we do need to go and re-read the page. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/truncate.c # 2004/06/17 23:49:30-07:00 akpm@osdl.org +8 -2 # invalidate_inodes2(): mark pages not uptodate # # ChangeSet # 2004/06/18 07:59:36-07:00 herbert@gondor.apana.org.au # [PATCH] Check return status of register calls in i82365 # # i82365 calls driver_register and platform_device_register without checking # their return values. This patch fixes that. # # It also runs platform_device_register() prior to isa_probe() so we don't have # to undo ise_probe()'s effects if platform_device_register() ends up failing. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/pcmcia/i82365.c # 2004/06/17 23:49:30-07:00 herbert@gondor.apana.org.au +10 -4 # Check return status of register calls in i82365 # # ChangeSet # 2004/06/18 07:59:25-07:00 tol@stacken.kth.se # [PATCH] getgroups16() fix # # sys_getgroups16 (or rather groups16_to_user()) returns large gids # truncated. Needs to be fixed, one way or another. Don't know why the # other similar casts are still there. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/uid16.c # 2004/06/17 23:49:29-07:00 tol@stacken.kth.se +6 -6 # getgroups16() fix # # include/linux/sched.h # 2004/06/18 00:32:12-07:00 tol@stacken.kth.se +9 -1 # getgroups16() fix # # ChangeSet # 2004/06/18 07:59:14-07:00 rene.herman@keyaccess.nl # [PATCH] same small resource tweaks, x86_64 version # # The same small tweaks for x86_64. Just to keep the two in sync. One # additional wrinkle: vram_resource was exported to e820.c, which didn't # actually use it. Undo that. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/x86_64/kernel/setup.c # 2004/06/17 23:49:29-07:00 rene.herman@keyaccess.nl +11 -9 # same small resource tweaks, x86_64 version # # arch/x86_64/kernel/e820.c # 2004/06/17 23:49:29-07:00 rene.herman@keyaccess.nl +1 -1 # same small resource tweaks, x86_64 version # # ChangeSet # 2004/06/18 07:59:03-07:00 rene.herman@keyaccess.nl # [PATCH] small tweaks to standard resource stuff # # Various small tweaks. Compiled and booted. # # 1. add IORESOURCE_BUSY | IORESOURCE_MEM also for the kernel code and # data resources. I don't believe this actually matters one bit, but # they're hooked into a BUSY/MEM parent ("System RAM") and marking # them busy seems to make sense. # # 2. delete the .start = 1M default for the kernel code resource. This # isn't actually a change; it's set to virt_to_phys(_text) in # setup_arch() overriding any default anyways. # # 3. s/vram_resource/video_ram_resource/. Lines up much nicer with # video_rom_resource... # # 4. s/checksum/romchecksum/. setup.c is a fairly large file, and # "checksum" pollutes the namespace. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/setup.c # 2004/06/17 23:49:29-07:00 rene.herman@keyaccess.nl +11 -9 # small tweaks to standard resource stuff # # ChangeSet # 2004/06/18 07:58:52-07:00 hpa@zytor.com # [PATCH] Use first-fit for pty allocation # # (With Andrew Morton). # # The current dynamic pty allocation scheme has a few problems: # # - pty numbers grow to be very large, causing wtmp file bloat. # # - Seems to break libc5 and some old applications # # So change it to do first-fit. An IDR tree is used to provide a # logarithmic-time search. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/tty_io.c # 2004/06/17 23:49:29-07:00 hpa@zytor.com +64 -19 # Use first-fit for pty allocation # # ChangeSet # 2004/06/18 07:58:40-07:00 tytso@mit.edu # [PATCH] Ext3: Retry allocation after transaction commit (v2) # # Here is a reworked version of my patch to ext3 to retry certain filesystem # operations after an ENOSPC error. The ext3_should_retry_alloc() function will # not wait on the currently running transaction if there is a currently active # handle; hence this should avoid deadlocks in the Lustre use case. The patch # is versus BK-recent. # # I've also included a simple, reliable test case which demonstrates the problem # this patch is intended to fix. (Note that BK-recent is not sufficient to # address this test case, and waiting on the commiting transaction in # ext3_new_block is also not sufficient. Been there, tried that, didn't work. # We need to do the full-bore retry from the top level. The # ext3_should_retry_alloc() will only wait on the committing transaction if # there is an active handle; hence Lustre will probably also need to use # ext3_should_retry_alloc() if it wants to reliably avoid this particular # problem.) # # #!/bin/sh # # # # # TEST_DIR=/tmp # IMAGE=$TEST_DIR/retry.img # MNTPT=$TEST_DIR/retry.mnt # TEST_SRC=/usr/projects/e2fsprogs/e2fsprogs/build # MKE2FS_OPTS="" # IMAGE_SIZE=8192 # # umount $MNTPT # dd if=/dev/zero of=$IMAGE bs=4k count=$IMAGE_SIZE # mke2fs -j -F $MKE2FS_OPTS $IMAGE # # function test_log () # { # echo $* # logger -p local4.notice $* # } # # mkdir -p $MNTPT # mount -o loop -t ext3 $IMAGE $MNTPT # test_log Retry test: BEGIN # for i in `seq 1 3` # do # test_log "Retry test: Loop $i" # echo 2 > /proc/sys/fs/jbd-debug # while ! mkdir -p $MNTPT/foo/bar # do # test_log "Retry test: mkdir failed" # sleep 1 # done # echo 0 > /proc/sys/fs/jbd-debug # cp -r $TEST_SRC $MNTPT/foo/bar 2> /dev/null # rm -rf $MNTPT/* # done # umount $MNTPT # test_log "Retry test: END" # # # akpm@osdl.org # # Rework the code to make it a formal JBD API entry point. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/jbd.h # 2004/06/17 23:47:53-07:00 tytso@mit.edu +1 -0 # Ext3: Retry allocation after transaction commit (v2) # # include/linux/ext3_fs.h # 2004/06/17 23:47:53-07:00 tytso@mit.edu +1 -0 # Ext3: Retry allocation after transaction commit (v2) # # fs/jbd/journal.c # 2004/06/17 23:47:53-07:00 tytso@mit.edu +34 -0 # Ext3: Retry allocation after transaction commit (v2) # # fs/ext3/xattr.c # 2004/06/17 23:47:53-07:00 tytso@mit.edu +5 -1 # Ext3: Retry allocation after transaction commit (v2) # # fs/ext3/namei.c # 2004/06/18 00:32:11-07:00 tytso@mit.edu +20 -5 # Ext3: Retry allocation after transaction commit (v2) # # fs/ext3/inode.c # 2004/06/17 23:47:53-07:00 tytso@mit.edu +5 -14 # Ext3: Retry allocation after transaction commit (v2) # # fs/ext3/balloc.c # 2004/06/17 23:49:23-07:00 tytso@mit.edu +32 -6 # Ext3: Retry allocation after transaction commit (v2) # # fs/ext3/acl.c # 2004/06/17 23:47:53-07:00 tytso@mit.edu +9 -1 # Ext3: Retry allocation after transaction commit (v2) # # ChangeSet # 2004/06/18 07:58:28-07:00 rene.herman@keyaccess.nl # [PATCH] pc9800: merge std_resources.c back into setup.c # # std_resources.{c,h} was only split off due to pc9800 wanting to override it. # With it gone, it might as well be merged back in. Doesn't change any code. # It was compiled and booted. # # This time this also actually doesn't break compilation of any of the # subarches. That's to say, any further. I guess it might have been my .config # (my regular PC config, with just the subarch switched through menuconfig) or # O=, but only ELAN actually compiled. Voyager and VISWS bombed out at the # final link and NUMAQ much sooner (with "physnode_map undeclared" during # compilation of numaq.c). # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/setup.c # 2004/06/18 00:32:22-07:00 rene.herman@keyaccess.nl +200 -5 # pc9800: merge std_resources.c back into setup.c # # arch/i386/kernel/Makefile # 2004/06/17 23:44:27-07:00 rene.herman@keyaccess.nl +0 -1 # pc9800: merge std_resources.c back into setup.c # # arch/i386/Kconfig # 2004/06/17 23:44:27-07:00 rene.herman@keyaccess.nl +0 -6 # pc9800: merge std_resources.c back into setup.c # # BitKeeper/deleted/.del-std_resources.h~45da2e05d849a20f # 2004/06/18 07:58:23-07:00 rene.herman@keyaccess.nl +0 -0 # Delete: include/asm-i386/std_resources.h # # BitKeeper/deleted/.del-std_resources.c~3be5b97880eb064e # 2004/06/18 07:58:22-07:00 rene.herman@keyaccess.nl +0 -0 # Delete: arch/i386/kernel/std_resources.c # # ChangeSet # 2004/06/18 07:58:17-07:00 bunk@fs.tum.de # [PATCH] more PC9800 removal # # Removes more PC9800 code. # # Requires: # # bk rm drivers/char/upd4990a.c # bk rm drivers/net/ne2k_cbus.c # bk rm drivers/net/ne2k_cbus.h # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/drivers/opl3/opl3_lib.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -20 # more PC9800 removal # # sound/drivers/mpu401/mpu401.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -11 # more PC9800 removal # # sound/core/seq/instr/Makefile # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1 # more PC9800 removal # # sound/core/seq/Makefile # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1 # more PC9800 removal # # include/linux/serio.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1 # more PC9800 removal # # include/linux/serial_core.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -8 # more PC9800 removal # # include/linux/ide.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +1 -1 # more PC9800 removal # # include/asm-i386/timex.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -4 # more PC9800 removal # # include/asm-i386/serial.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -7 # more PC9800 removal # # include/asm-i386/processor.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -6 # more PC9800 removal # # include/asm-i386/ide.h # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -34 # more PC9800 removal # # drivers/serial/8250_pnp.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -3 # more PC9800 removal # # drivers/pnp/isapnp/core.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -5 # more PC9800 removal # # drivers/net/at1700.c # 2004/06/17 23:44:24-07:00 bunk@fs.tum.de +0 -88 # more PC9800 removal # # drivers/net/Space.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +2 -2 # more PC9800 removal # # drivers/net/3c509.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +9 -36 # more PC9800 removal # # drivers/ide/ide-proc.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -1 # more PC9800 removal # # drivers/char/keyboard.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +2 -3 # more PC9800 removal # # arch/i386/kernel/i8259.c # 2004/06/17 23:43:58-07:00 bunk@fs.tum.de +0 -5 # more PC9800 removal # # ChangeSet # 2004/06/18 07:58:05-07:00 rddunlap@osdl.org # [PATCH] Remove PC9800 support # # PC9800 sub-arch is incomplete, hackish (at least in IDE), maintainers don't # reply to emails and haven't touched it in awhile. Can't even config it to # try to build it without other patches to the kernel tree. # # bk-rm-script: # # #! /bin/sh # bk rm -r ./arch/i386/mach-pc9800 # bk rm -r ./arch/i386/boot98 # bk rm ./drivers/char/lp_old98.c # bk rm ./drivers/serial/serial98.c # bk rm ./drivers/scsi/scsi_pc98.c # bk rm ./drivers/scsi/pc980155.c # bk rm ./drivers/scsi/pc980155.h # bk rm ./drivers/block/floppy98.c # bk rm ./drivers/input/keyboard/98kbd.c # bk rm ./drivers/input/serio/98kbd-io.c # bk rm ./drivers/input/misc/98spkr.c # bk rm ./drivers/input/mouse/98busmouse.c # bk rm ./drivers/ide/legacy/pc9800.c # bk rm ./drivers/ide/legacy/hd98.c # bk rm -r ./include/asm-i386/mach-pc9800 # bk rm ./include/asm-i386/pc9800_sca.h # bk rm ./include/asm-i386/pc9800.h # bk rm ./fs/partitions/nec98.c # bk rm ./fs/partitions/nec98.h # bk rm ./sound/isa/cs423x/pc98.c # bk rm ./sound/isa/cs423x/pc9801_118_magic.h # bk rm ./sound/isa/cs423x/sound_pc9800.h # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/isa/cs423x/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -2 # Remove PC9800 support # # sound/isa/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -10 # Remove PC9800 support # # fs/partitions/check.c # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1 # Remove PC9800 support # # fs/partitions/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -7 # Remove PC9800 support # # drivers/serial/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1 # Remove PC9800 support # # drivers/serial/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -13 # Remove PC9800 support # # drivers/scsi/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -2 # Remove PC9800 support # # drivers/scsi/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -12 # Remove PC9800 support # # drivers/net/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1 # Remove PC9800 support # # drivers/net/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -51 # Remove PC9800 support # # drivers/input/serio/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -10 # Remove PC9800 support # # drivers/input/mouse/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1 # Remove PC9800 support # # drivers/input/mouse/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -11 # Remove PC9800 support # # drivers/input/misc/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -4 # Remove PC9800 support # # drivers/input/keyboard/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -12 # Remove PC9800 support # # drivers/ide/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1 # Remove PC9800 support # # drivers/ide/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -19 # Remove PC9800 support # # drivers/char/Makefile # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +0 -1 # Remove PC9800 support # # drivers/char/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -21 # Remove PC9800 support # # drivers/block/Kconfig # 2004/06/17 23:43:53-07:00 rddunlap@osdl.org +1 -8 # Remove PC9800 support # # ChangeSet # 2004/06/18 07:57:53-07:00 Robert.Picco@hp.com # [PATCH] HPET driver # # The driver supports the High Precision Event Timer. The driver has adopted # a similar API to the Real Time Clock driver. It can support any number of # HPET devices and the maximum number of timers per HPET device. For further # information look at the documentation in the patch. # # Thanks to Venki at Intel for testing the driver on X86 hardware with HPET. # # HPET documentation is available at http://www.intel.com/design/chipsets/datashts/252516.htm # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/hpet.h # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +133 -0 # HPET driver # # drivers/char/hpet.c # 2004/06/17 23:43:14-07:00 Robert.Picco@hp.com +1076 -0 # HPET driver # # include/linux/miscdevice.h # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +1 -0 # HPET driver # # include/linux/hpet.h # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/linux/hpet.h # # include/asm-i386/hpet.h # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +3 -0 # HPET driver # # drivers/char/rtc.c # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +5 -0 # HPET driver # # drivers/char/hpet.c # 2004/06/17 23:43:14-07:00 Robert.Picco@hp.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/char/hpet.c # # drivers/char/Makefile # 2004/06/18 00:32:23-07:00 Robert.Picco@hp.com +1 -0 # HPET driver # # drivers/char/Kconfig # 2004/06/18 00:32:23-07:00 Robert.Picco@hp.com +27 -0 # HPET driver # # arch/i386/kernel/time_hpet.c # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +46 -0 # HPET driver # # arch/i386/Kconfig # 2004/06/18 00:32:22-07:00 Robert.Picco@hp.com +2 -1 # HPET driver # # Documentation/hpet.txt # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +298 -0 # HPET driver # # Documentation/filesystems/proc.txt # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +1 -1 # HPET driver # # Documentation/hpet.txt # 2004/06/17 23:41:40-07:00 Robert.Picco@hp.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/hpet.txt # # ChangeSet # 2004/06/18 07:57:41-07:00 chrisw@osdl.org # [PATCH] RLIM: adjust default mqueue sizes # # Lower default sizes for POSIX mqueue allocation now that rlimits are in place. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ipc/mqueue.c # 2004/06/17 23:41:40-07:00 chrisw@osdl.org +3 -3 # RLIM: adjust default mqueue sizes # # ChangeSet # 2004/06/18 07:57:29-07:00 chrisw@osdl.org # [PATCH] RLIM: enforce rlimits for POSIX mqueue allocation # # Add a user_struct to the mq_inode_info structure. Charge the maximum number # of bytes that could be allocated to a mqueue to the user who creates the # mqueue. This is checked against the per user rlimit. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ipc/mqueue.c # 2004/06/18 00:32:23-07:00 chrisw@osdl.org +39 -5 # RLIM: enforce rlimits for POSIX mqueue allocation # # ChangeSet # 2004/06/18 07:57:18-07:00 chrisw@osdl.org # [PATCH] RLIM: add mq_attr_ok() helper # # Add helper function mq_attr_ok() to do mq_attr sanity checking, and do some # extra overlow checking. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ipc/mqueue.c # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +23 -10 # RLIM: add mq_attr_ok() helper # # ChangeSet # 2004/06/18 07:57:07-07:00 chrisw@osdl.org # [PATCH] RLIM: add mq_bytes to user_struct # # Add mq_bytes field to user_struct, and make sure it's properly initialized. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/user.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -0 # RLIM: add mq_bytes to user_struct # # include/linux/sched.h # 2004/06/18 00:32:22-07:00 chrisw@osdl.org +2 -0 # RLIM: add mq_bytes to user_struct # # ChangeSet # 2004/06/18 07:56:56-07:00 chrisw@osdl.org # [PATCH] RLIM: add rlimit entry for POSIX mqueue allocation # # Add an rlimit entry to control the maximum number of bytes a user can allocate # to a POSIX mqueue. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/mqueue.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +2 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-x86_64/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-v850/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-sparc64/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-sparc/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-sh/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-s390/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-ppc64/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-ppc/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-parisc/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-mips/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-m68k/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-ia64/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-i386/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-h8300/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-cris/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-arm26/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-arm/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # include/asm-alpha/resource.h # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/x86_64/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/v850/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/um/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/sparc64/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/sparc/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/sh/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/s390/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/ppc64/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/ppc/kernel/process.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/parisc/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/mips/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/m68knommu/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/m68k/kernel/process.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/ia64/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/i386/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/h8300/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/cris/kernel/process.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/arm26/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/arm/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # arch/alpha/kernel/init_task.c # 2004/06/17 23:41:39-07:00 chrisw@osdl.org +1 -0 # RLIM: add rlimit entry for POSIX mqueue allocation # # ChangeSet # 2004/06/18 07:56:43-07:00 chrisw@osdl.org # [PATCH] RLIM: add simple get_uid() helper # # Add simple helper function to grab a reference to a user_struct. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/sched.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -0 # RLIM: add simple get_uid() helper # # ChangeSet # 2004/06/18 07:56:32-07:00 chrisw@osdl.org # [PATCH] RLIM: add sigpending field to user_struct # # Add sigpending field to user_struct, and make sure it's properly initialized. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/user.c # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add sigpending field to user_struct # # include/linux/sched.h # 2004/06/18 00:32:25-07:00 chrisw@osdl.org +1 -0 # RLIM: add sigpending field to user_struct # # ChangeSet # 2004/06/18 07:56:20-07:00 chrisw@osdl.org # [PATCH] RLIM: add rlimit entry for controlling queued signals # # The following patches introduce per user rlimits for both queued signals and # POSIX message queues. The changes touch all the arches resource.h files as # well as init_task.c to get the rlimit defaults setup. # # Both require caching the user_struct to avoid problems with setuid(). # # The signal changes makes some small changes to send_signal() to pass along the # task being signalled to get proper accounting for signals initiated in # interrupt. Thanks to Marcelo for getting this one going. # # # This patch: # # Add an rlimit entry to control the maximum number of pending signals a user # may have. This is essentially just the resource.h changes. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/signal.h # 2004/06/18 00:32:25-07:00 chrisw@osdl.org +3 -0 # RLIM: add rlimit entry for controlling queued signals # # include/asm-x86_64/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2 # RLIM: add rlimit entry for controlling queued signals # # include/asm-v850/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2 # RLIM: add rlimit entry for controlling queued signals # # include/asm-sparc64/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +6 -4 # RLIM: add rlimit entry for controlling queued signals # # include/asm-sparc/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +6 -4 # RLIM: add rlimit entry for controlling queued signals # # include/asm-sh/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-s390/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2 # RLIM: add rlimit entry for controlling queued signals # # include/asm-ppc64/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-ppc/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-parisc/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-mips/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-m68k/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2 # RLIM: add rlimit entry for controlling queued signals # # include/asm-ia64/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-i386/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -2 # RLIM: add rlimit entry for controlling queued signals # # include/asm-h8300/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +4 -2 # RLIM: add rlimit entry for controlling queued signals # # include/asm-cris/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -3 # RLIM: add rlimit entry for controlling queued signals # # include/asm-arm26/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-arm/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +3 -1 # RLIM: add rlimit entry for controlling queued signals # # include/asm-alpha/resource.h # 2004/06/18 00:32:24-07:00 chrisw@osdl.org +5 -3 # RLIM: add rlimit entry for controlling queued signals # # ChangeSet # 2004/06/18 07:56:09-07:00 akpm@osdl.org # [PATCH] i2c fixups for idr API change # # Fix up the i2c code which uses the IDR library. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/i2c/i2c-core.c # 2004/06/17 23:41:38-07:00 akpm@osdl.org +8 -2 # i2c fixups for idr API change # # ChangeSet # 2004/06/18 07:55:58-07:00 minyard@acm.org # [PATCH] IDR fixups # # There were definately some problems in there. I've made some changes and # tested with a lot of bounds. I don't have a machine with enough memory to # fill it up (it would take ~16GB on a 64-bit machine), but I use the "above" # code to simulate a lot of situations. # # The problems were: # # * IDR_FULL was not the right value # * idr_get_new_above() was not defined in the headers or documented. # * idr_alloc() bug-ed if there was a race and not enough memory was # allocated. It should have returned NULL. # * id will overflow when you go past the end. # * There was a "(id >= (1 << (layers*IDR_BITS)))" comparison, but at # the top layer it would overflow the id and be zero. # * The allocation should return ENOSPC for an "above" value with # nothing above it, but it returned EAGAIN. # # I have not tested on 64-bits (as I don't have a 64-bit machine). # # I've included the files, a diff from the previous version, and my test # programs. # # For the test programs, idr_test will just attempt to allocate # elements, check them, free them, and check them again. # # idr_test2 will allocate element with between # them. # # idr_test3 just tests some bounds and tries all values with just a few in # the idr. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # lib/idr.c # 2004/06/17 23:41:38-07:00 minyard@acm.org +31 -14 # IDR fixups # # include/linux/idr.h # 2004/06/17 23:41:38-07:00 minyard@acm.org +9 -6 # IDR fixups # # ChangeSet # 2004/06/18 07:55:47-07:00 akpm@osdl.org # [PATCH] idr: remove counter bits from id's # # idr_get_new() currently returns an incrementing counter in the top 8 bits of # the counter. Which means that most users have to mask it off again, and we # only have a 24-bit range. # # So remove that counter. Also: # # - Remove the BITS_PER_INT define due to namespace collision risk. # # - Make MAX_ID_SHIFT 31, so counters have a 0 to 2G-1 range. # # - Why is MAX_ID_SHIFT using sizeof(int) and not sizeof(long)? If it's for # consistency across 32- and 64-bit machines, why not just make it "31"? # # - Does this still hold true with the counter removed? # # /* We can only use half the bits in the top level because there are # only four possible bits in the top level (5 bits * 4 levels = 25 # bits, but you only use 24 bits in the id). */ # # If not, what needs to change? # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # lib/idr.c # 2004/06/18 00:32:26-07:00 akpm@osdl.org +3 -16 # idr: remove counter bits from id's # # include/linux/idr.h # 2004/06/18 00:32:26-07:00 akpm@osdl.org +5 -13 # idr: remove counter bits from id's # # ChangeSet # 2004/06/18 07:55:36-07:00 minyard@acm.org # [PATCH] Fixes for idr code # # * On a 32-bit architecture, the idr code will cease to work if you add # more than 2^20 entries. You will not be able to find many of the # entries. The problem is that the IDR code uses 5-bit chunks of the # number and the lower portion used by IDR is 24 bits, so you have one bit # that leaks over into the comparisons that should not be there. The # solution is to mask off that bit before doing IDR processing. This # actually causes the POSIX timer code to crash if you create that many # timers. I have included an idr_test.tar.gz file that demonstrates this # with and without the fix, in case you need more evidence :). # # * When the IDR fills up, it returns -1. However, there was no way to # check for this condition. This patch adds the ability to check for the # idr being full and fixes all the users. It also fixes a problem in # fs/super.c where the idr code wasn't checking for -1. # # * There was a race condition creating POSIX timers. The timer was added # to a task struct for another process then the data for the timer was # filled out. The other task could use/destroy time timer as soon as it is # in the task's queue and the lock is released. This moves settup up the # timer data to before the timer is enqueued or (for some data) into the # lock. # # * Change things so that the caller doesn't need to run idr_full() to find # out the reason for an idr_get_new() failure. # # Just return -ENOSPC if the tree was full, or -EAGAIN if the caller needs # to re-run idr_pre_get() and try again. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # net/sctp/sm_make_chunk.c # 2004/06/17 23:41:37-07:00 minyard@acm.org +15 -10 # Fixes for idr code # # lib/idr.c # 2004/06/18 00:32:26-07:00 minyard@acm.org +37 -8 # Fixes for idr code # # kernel/posix-timers.c # 2004/06/17 23:41:37-07:00 minyard@acm.org +52 -34 # Fixes for idr code # # include/linux/idr.h # 2004/06/18 00:32:26-07:00 minyard@acm.org +7 -1 # Fixes for idr code # # fs/super.c # 2004/06/17 23:41:37-07:00 minyard@acm.org +10 -5 # Fixes for idr code # # fs/proc/generic.c # 2004/06/17 23:41:37-07:00 minyard@acm.org +6 -4 # Fixes for idr code # # ChangeSet # 2004/06/18 07:55:25-07:00 mason@suse.com # [PATCH] reiserfs data logging support # # Add data=journal support for reiserfs # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/reiserfs_fs_i.h # 2004/06/17 23:41:37-07:00 mason@suse.com +1 -0 # reiserfs data logging support # # include/linux/reiserfs_fs.h # 2004/06/17 23:41:37-07:00 mason@suse.com +8 -0 # reiserfs data logging support # # fs/reiserfs/tail_conversion.c # 2004/06/17 23:41:37-07:00 mason@suse.com +0 -41 # reiserfs data logging support # # fs/reiserfs/stree.c # 2004/06/17 23:41:37-07:00 mason@suse.com +40 -3 # reiserfs data logging support # # fs/reiserfs/journal.c # 2004/06/17 23:41:37-07:00 mason@suse.com +13 -4 # reiserfs data logging support # # fs/reiserfs/inode.c # 2004/06/17 23:41:37-07:00 mason@suse.com +49 -10 # reiserfs data logging support # # fs/reiserfs/file.c # 2004/06/17 23:41:37-07:00 mason@suse.com +18 -2 # reiserfs data logging support # # ChangeSet # 2004/06/18 07:55:13-07:00 mason@suse.com # [PATCH] reiserfs: btree readahead # # Walking the btree can trigger a number of single block synchronous reads. # This patch does btree readahead during operations that are likely to be long # and sequential. So far, that only includes directory reads and truncates, but # it can make both much faster. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/reiserfs_fs.h # 2004/06/18 00:32:26-07:00 mason@suse.com +5 -1 # reiserfs: btree readahead # # fs/reiserfs/stree.c # 2004/06/18 00:32:26-07:00 mason@suse.com +68 -25 # reiserfs: btree readahead # # fs/reiserfs/dir.c # 2004/06/17 23:41:37-07:00 mason@suse.com +1 -0 # reiserfs: btree readahead # # ChangeSet # 2004/06/18 07:55:03-07:00 mason@suse.com # [PATCH] reiserfs: remove debugging warning from block allocator # # Remove debugging warning from the reiserfs block allocator code # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/reiserfs/bitmap.c # 2004/06/17 23:41:37-07:00 mason@suse.com +0 -1 # reiserfs: remove debugging warning from block allocator # # ChangeSet # 2004/06/18 07:54:52-07:00 mason@suse.com # [PATCH] reiserfs: block allocator should not inherit "packing locality 1" # # reiserfsck --rebuild-tree expects the only key with a packing locality of 1 to # be for the root directory (key [1 2]). The new block allocator inherited that # packing locality down to subdirectories, which triggers failures in reiserfsck # --rebuild-tree # # reiserfsck in readonly check mode doesn't complain about this, thanks to Jeff # Mahoney for finding it. # # The fix is to never inherit packing locality #1 # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/reiserfs/bitmap.c # 2004/06/18 00:32:26-07:00 mason@suse.com +6 -1 # reiserfs: block allocator should not inherit "packing locality 1" # # ChangeSet # 2004/06/18 07:54:43-07:00 mason@suse.com # [PATCH] reiserfs: block allocator optimizations # # From: # From: # # The current reiserfs allocator pretty much allocates things sequentially # from the start of the disk, it works very nicely for desktop loads but # once you've got more then one proc doing io data files can fragment badly. # # One obvious solution is something like ext2's bitmap groups, which puts # file data into different areas of the disk based on which subdirectory # they are in. The problem with bitmap groups is that if you've got a # group of subdirectories their contents will be spread out all over the # disk, leading to lots of seeks during a sequential read. # # This allocator patch uses the packing locality to determine which bitmap # group to allocate from, but when you create a file it looks in the bitmaps # to see how 'full' that packing locality already is. If it hasn't been # heavily used yet, the packing locality is inherited from the parent # directory putting files in new subdirs close to the parent subdir, # otherwise it is the inode number of the parent directory putting new # files far away from the parent subdir. # # The end result is fewer bitmap groups for the same working set. For # example, one test data set created by 20 procs running in parallel has # 6822 subdirs. And with vanilla reiserfs that would mean 6822 # packing localities. This patch turns that into 26 packing localities. # # This makes sequential reads of big directory trees more efficient, but # it also makes the btree more efficient in general. Things end up sorted # better because groups of subdirs end up with similar keys in the btree, # instead of being spread out all over. # # The bitmap grouping code tries to use the start of each bitmap group # for metadata, and offsets the data slightly. The data and metadata # are still close together, but not completely intermixed like they are # in the default allocator. The end result is that leaf nodes tend to be # close to each other, making metadata readahead more effective. # # The old block allocator had the ability to enforce a minimum # allocation size, but did not use it. It now tries to do a pass looking # for larger allocation chunks before falling back to the old behaviour # of taking any blocks it can find. # # The patch changes the defaults to: # # mount -o alloc=skip_busy:dirid_groups:packing_groups # # You can get back the old behaviour with mount -o alloc=skip_busy # # mount -o alloc=dirid_groups will turn on the bitmap groups # mount -o alloc=packing_groups turns on the packing locality reduction code # mount -o alloc=skip_busy:dirid_groups turns on both dirid_groups and # skip_busy # # Finally the patch adds a mount -o alloc=oid_groups, which puts files into # bitmap groups based on a hash of their objectid. This would be used for # databases or other situations where you have a limited number of very # large files. # # This command will tell you how many packing localities are actually in # use: # # debugreiserfs -d /dev/xxx | grep '^|.*SD' | sed 's/^.....//' | awk '{print $1}' | sort -u | wc -l # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/reiserfs_fs.h # 2004/06/18 00:32:26-07:00 mason@suse.com +10 -1 # reiserfs: block allocator optimizations # # fs/reiserfs/super.c # 2004/06/17 23:41:36-07:00 mason@suse.com +7 -6 # reiserfs: block allocator optimizations # # fs/reiserfs/inode.c # 2004/06/18 00:32:26-07:00 mason@suse.com +1 -2 # reiserfs: block allocator optimizations # # fs/reiserfs/file.c # 2004/06/18 00:32:26-07:00 mason@suse.com +11 -3 # reiserfs: block allocator optimizations # # fs/reiserfs/bitmap.c # 2004/06/18 00:32:27-07:00 mason@suse.com +234 -55 # reiserfs: block allocator optimizations # # ChangeSet # 2004/06/18 07:54:32-07:00 akpm@osdl.org # [PATCH] ppc64: uninline __pte_free_tlb() # # The pgalloc.h changes broke ppc64: # # In file included from include/asm-generic/tlb.h:18, # from include/asm/tlb.h:24, # from arch/ppc64/mm/hash_utils.c:48: # include/asm/pgalloc.h: In function `__pte_free_tlb': # include/asm/pgalloc.h:110: dereferencing pointer to incomplete type # include/asm/pgalloc.h:111: dereferencing pointer to incomplete type # # Uninlining __pte_free_tlb() fixes that. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-ppc64/pgalloc.h # 2004/06/17 23:41:36-07:00 akpm@osdl.org +1 -27 # ppc64: uninline __pte_free_tlb() # # arch/ppc64/mm/tlb.c # 2004/06/17 23:41:36-07:00 akpm@osdl.org +27 -0 # ppc64: uninline __pte_free_tlb() # # ChangeSet # 2004/06/18 07:54:20-07:00 rmk@arm.linux.org.uk # [PATCH] Clean up asm/pgalloc.h include 3 # # This patch cleans up needless includes of asm/pgalloc.h from the arch/i386/ # subtree. Compile tested on x86_pc SMP. # # [I also tried VISWS + SMP without PM doesn't build in smpboot.c, # though I don't believe its caused by this patch. With PM, fails # to link complaining maxcpus is undefined. Therefore, I presume # VISWS + SMP is an invalid configuration.] # # This patch is part of a larger patch aiming towards getting the include of # asm/pgtable.h out of linux/mm.h, so that asm/pgtable.h can sanely get at # things like mm_struct and friends. # # I suggest testing in -mm for a while to ensure there aren't any hidden arch # issues. # # The outstanding list of files for other architectures can be found # at http://www.arm.linux.org.uk/misc/pgalloc.txt # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/mm/ioremap.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mm/init.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mm/hugetlbpage.c # 2004/06/18 00:32:07-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mm/fault.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mach-voyager/voyager_thread.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mach-voyager/voyager_smp.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mach-voyager/voyager_basic.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/mach-visws/traps.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/vm86.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/traps.c # 2004/06/18 00:32:07-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/smpboot.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/smp.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/mpparse.c # 2004/06/18 00:32:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/irq.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/i386_ksyms.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/efi.c # 2004/06/17 23:41:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/apic.c # 2004/06/18 00:32:15-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include 3 # # arch/i386/kernel/acpi/boot.c # 2004/06/17 23:41:33-07:00 rmk@arm.linux.org.uk +2 -1 # Clean up asm/pgalloc.h include 3 # # ChangeSet # 2004/06/18 07:54:08-07:00 rmk@arm.linux.org.uk # [PATCH] Clean up asm/pgalloc.h include # # This patch cleans up needless includes of asm/pgalloc.h from the drivers/ # subtree. drivers/char/mem.c has been compile tested; the others have not, # since they are for non-x86 and non-ARM architectures. # # This patch is part of a larger patch aiming towards getting the include of # asm/pgtable.h out of linux/mm.h, so that asm/pgtable.h can sanely get at # things like mm_struct and friends. # # I suggest testing in -mm for a while to ensure there aren't any hidden arch # issues. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/oss/dmasound/dmasound_atari.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/video/console/sticore.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/parisc/ccio-rm-dma.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/parisc/ccio-dma.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/net/sun3lance.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/net/macsonic.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/net/lasi_82596.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/net/82596.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # drivers/char/mem.c # 2004/06/17 23:41:10-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # ChangeSet # 2004/06/18 07:53:57-07:00 rmk@arm.linux.org.uk # [PATCH] Clean up asm/pgalloc.h include # # This patch cleans up needless includes of asm/pgalloc.h from the fs/ # kernel/ and mm/ subtrees. Compile tested on multiple ARM platforms, and # x86, this patch appears safe. # # This patch is part of a larger patch aiming towards getting the include of # asm/pgtable.h out of linux/mm.h, so that asm/pgtable.h can sanely get at # things like mm_struct and friends. # # I suggest testing in -mm for a while to ensure there aren't any hidden arch # issues. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/vmscan.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/vmalloc.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/nommu.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/msync.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/mremap.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/mprotect.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/mmap.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/mincore.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # mm/highmem.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # kernel/module.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # include/asm-generic/tlb.h # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +1 -0 # Clean up asm/pgalloc.h include # # include/asm-arm26/tlb.h # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +1 -0 # Clean up asm/pgalloc.h include # # fs/proc/proc_misc.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # fs/exec.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # fs/binfmt_flat.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # fs/binfmt_elf.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # fs/binfmt_aout.c # 2004/06/17 23:41:09-07:00 rmk@arm.linux.org.uk +0 -1 # Clean up asm/pgalloc.h include # # ChangeSet # 2004/06/18 07:53:45-07:00 yoav.zach@intel.com # [PATCH] binfmt_misc: improve calculation of interpreter's credentials # # This patch allows for misc binaries to run with credentials and security # token that are calculated according to the binaries, and not according to the # interpreter, which is the legacy behavior of binfmt_misc. # # The way it is done is by calling prepare_binprm, which is where these # attributes are calculated, before switching the 'file' field in the bprm from # the binary to the interpreter. # # This feature should be used with care, since the interpreter will have root # permissions when running a setuid binary owned by root. # # Please note - # # - Only root can register an interpreter with binfmt_misc. The feature is # documented and the administrator is advised to handle it with care # # - The new feature is enabled only with a special flag in the registration # string. When this flag is not specified the current behavior of # binfmt_misc is kept # # - This is the only 'right' way for an interpreter to know the correct # AT_SECURE value for the interpreted binary # # # From: Chris Wright # # This patchset looks OK, except for one problem. It installs the fd (which # could've been unreadable) without unsharing the ->files. So someone can use # this to read unreadable yet executable files. Here's a patch which fixes # that up. I added one bit that's commented out because I'm not positive if a # final steal_locks() is needed. # # I did a fair amount of rearranging to simplify the error conditions # relative to the fd_install(), and unshare_files(). # # From: Chris Wright # # I found that the intel patchset (and mine as well) leaked i_writecount on # the original executed file. In addition, I verified that the steal_locks() # bit is indeed needed. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/binfmt_misc.c # 2004/06/17 23:41:09-07:00 yoav.zach@intel.com +71 -51 # binfmt_misc: improve calculation of interpreter's credentials # # Documentation/binfmt_misc.txt # 2004/06/17 23:41:09-07:00 yoav.zach@intel.com +7 -0 # binfmt_misc: improve calculation of interpreter's credentials # # ChangeSet # 2004/06/18 07:53:34-07:00 yoav.zach@intel.com # [PATCH] Handle non-readable binfmt_misc executables # # # # I work in a group that works on enabling the IA-32 Execution Layer # (http://www.intel.com/pressroom/archive/releases/20040113comp.htm) on Linux. # In a few words - this is a dynamic translator for IA-32 binaries on IPF # platform. Following David Mosberger's advice - we use the binfmt_misc # mechanism for the invocation of the translator whenever the user tries to # exec an IA-32 binary. # # The EL is meant to help in the migration path from IA-32 to IPF. From our # beta customers we learnt that at first stage - they tend to keep their # environment mostly intact, using the legacy IA-32 binaries. # # Such an environment has, naturally, setuid and non-readable binaries. It # will be useless to ask the administrator to change the settings of such an # environment - some of them are very complex, and the administrators are # reluctant to make any changes in a system that already proved itself to be # robust and secure. So, our target with these patches is not to enhance the # support for scripts but rather to allow a translator to be integrated into a # working environment that is not (and should not be) aware to the fact it's # being emulated. # # As I said before - it is practically hopeless to expect an administrator of # such a system to change it so that it will suit the current behavior of # binfmt_misc. But, even if we could do that, # # I'm not sure it would be a good idea - these changes are likely to be less # secure than the suggested patches - # # - In order to execute non-readable binaries the binary will have to be made # readable, which is obviously less secure than allowing only a trusted # translator to read it # # - There will be no way for the translator to calculate the accurate # AT_SECURE value for the translated process. This might end up with the # translated process running in a non-secured mode when it actually needs to # be secured. # # # # # I prepared a patch that solves a couple of problems that interpreters have # when invoked via binfmt_misc. currently - # # 1) such interpreters cannot open non-readable binaries # # 2) the processes will have their credentials and security attributes # calculated according to interpreter permissions and not those of the # original binary # # the proposed patch solves these problems by - # # 1) opening the binary on behalf of the interpreter and passing its fd # instead of the path as argv[1] to the interpreter # # 2) calling prepare_binprm with the file struct of the binary and not the # one of the interpreter # # The new functionality is enabled by adding a special flag to the registration # string. If this flag is not added then old behavior is not changed. # # A preliminary version of this patch was sent to the list on 9/1/2003 with the # title "[PATCH]: non-readable binaries - binfmt_misc 2.6.0-test4". This new # version fixes the concerns that were raised by the patch, except of calling # unshare_files() before allocating a new fd. this is because this feature did # not enter 2.6 yet. # # # Arun Sharma says: # # We were going through an internal review of this patch: # # http://marc.theaimsgroup.com/?l=linux-kernel&m=107424598901720&w=2 # # which is in your tree already. I'm not sure if this line of code got # sufficient review. # # + /* call prepare_binprm before switching to interpreter's file # + * so that all security calculation will be done according to # + * binary and not interpreter */ # + retval = prepare_binprm(bprm); # # The case that concerns me is: unprivileged interpreter and a privileged # binary. One can use binfmt_misc to execute untrusted code (interpreter) with # elevated privileges. One could argue that all binfmt_misc interpreters are # trusted, because only root can register them. But that's a change from the # traditional behavior of binfmt_misc (and binfmt_script). # # # (Update): # # Arun pointed out that calculating the process credentials according to the # binary that needs to be translated is a bit risky, since it requires the # administrator to pay extra attention not to register an interpreter which is # not intended to run with root credentials. # # After discussing this issue with him, I would like to propose a modified # patch: The old patch did 2 things - 1) open the binary for reading and 2) # calculate the credentials according to the binary. # # I removed the riskier part of changing the credentials calculation, so the # revised patch only opens the binary for reading. It also includes few words # of warning in the description of the 'open-binary' feature in # binfmt_misc.txt, and makes the function entry_status print the flags in use. # # As for the 'credentials' part of the patch, I will prepare a separate patch # for it and send it again to the LKML, describe the problem and ask for people # comments. # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/binfmts.h # 2004/06/17 23:41:09-07:00 yoav.zach@intel.com +4 -0 # Handle non-readable binfmt_misc executables # # fs/exec.c # 2004/06/18 00:32:28-07:00 yoav.zach@intel.com +3 -1 # Handle non-readable binfmt_misc executables # # fs/binfmt_misc.c # 2004/06/18 00:32:28-07:00 yoav.zach@intel.com +120 -21 # Handle non-readable binfmt_misc executables # # Documentation/binfmt_misc.txt # 2004/06/18 00:32:28-07:00 yoav.zach@intel.com +19 -4 # Handle non-readable binfmt_misc executables # # ChangeSet # 2004/06/18 07:53:23-07:00 mporter@kernel.crashing.org # [PATCH] Add PPC4xx MAINTAINERS entry, merge CREDITS from 2.4 # # Add myself as the PPC4xx maintainer. Merge CREDITS entry from 2.4 # # Signed-off-by: Matt Porter # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # MAINTAINERS # 2004/06/17 23:41:09-07:00 mporter@kernel.crashing.org +7 -0 # Add PPC4xx MAINTAINERS entry, merge CREDITS from 2.4 # # CREDITS # 2004/06/18 00:32:10-07:00 mporter@kernel.crashing.org +8 -0 # Add PPC4xx MAINTAINERS entry, merge CREDITS from 2.4 # # ChangeSet # 2004/06/18 07:53:12-07:00 olh@suse.de # [PATCH] ppc64: avoid multiline /proc/cmdline content on iSeries # # /proc/cmdline is filled via an OS400 call iSeries_init(). It scans the # returned data from the end, instead of the beginning. This leads to # multiple lines in /proc/cmdline # # Just scan from the beginning and stop at the first newline. This patch # changes also the /proc/iSeries/mf/*/cmdline interface to do the same as the # initial setup. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ppc64/kernel/mf_proc.c # 2004/06/17 23:41:08-07:00 olh@suse.de +15 -22 # ppc64: avoid multiline /proc/cmdline content on iSeries # # arch/ppc64/kernel/iSeries_setup.c # 2004/06/17 23:41:08-07:00 olh@suse.de +6 -7 # ppc64: avoid multiline /proc/cmdline content on iSeries # # ChangeSet # 2004/06/18 07:53:00-07:00 mikpe@csd.uu.se # [PATCH] ppc32 irq.c cpumask fix # # 2.6.7-rc3-mm1 changed cpumask_t from ulong to a struct, causing # compile-time errors in arch/ppc/kernel/irq.c. # # Proposed fix below. Tested on a G3. # # Signed-off-by: Mikael Pettersson # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ppc/kernel/irq.c # 2004/06/17 23:41:08-07:00 mikpe@csd.uu.se +3 -1 # ppc32 irq.c cpumask fix # # ChangeSet # 2004/06/18 07:52:49-07:00 kumar.gala@freescale.com # [PATCH] ppc32: support for e500 and 85xx # # Here is both a GNU style and BK patch for adding support for the e500 core and # 85xx platform to 2.6. This is pretty much a direct port from 2.4 with a bit # of cleanup around the edges. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-ppc/mpc85xx.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +128 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/immap_85xx.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +126 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/fsl_ocp.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +54 -0 # ppc32: support for e500 and 85xx # # arch/ppc/syslib/ppc85xx_setup.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +67 -0 # ppc32: support for e500 and 85xx # # arch/ppc/syslib/ppc85xx_setup.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +341 -0 # ppc32: support for e500 and 85xx # # arch/ppc/syslib/ppc85xx_common.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +29 -0 # ppc32: support for e500 and 85xx # # arch/ppc/syslib/ppc85xx_common.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +46 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/mpc85xx_ads_common.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +50 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/mpc85xx_ads_common.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +237 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/mpc8540_ads.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +30 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/mpc8540_ads.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +238 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/mpc8540.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +97 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/Makefile # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/Kconfig # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +44 -0 # ppc32: support for e500 and 85xx # # arch/ppc/mm/fsl_booke_mmu.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +236 -0 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/head_e500.S # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1329 -0 # ppc32: support for e500 and 85xx # # include/linux/prctl.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +6 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/tlbflush.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +22 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/system.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/serial.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/reg_booke.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +119 -11 # ppc32: support for e500 and 85xx # # include/asm-ppc/reg.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +12 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/ptrace.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/processor.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +16 -9 # ppc32: support for e500 and 85xx # # include/asm-ppc/ppcboot.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -2 # ppc32: support for e500 and 85xx # # include/asm-ppc/ppc_asm.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +56 -10 # ppc32: support for e500 and 85xx # # include/asm-ppc/pgtable.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +37 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/ocp_ids.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -1 # ppc32: support for e500 and 85xx # # include/asm-ppc/ocp.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +4 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/mpc85xx.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/mpc85xx.h # # include/asm-ppc/mmu_context.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/mmu.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +68 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/io.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +2 -0 # ppc32: support for e500 and 85xx # # include/asm-ppc/immap_85xx.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/immap_85xx.h # # include/asm-ppc/fsl_ocp.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/fsl_ocp.h # # include/asm-ppc/elf.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1 -0 # ppc32: support for e500 and 85xx # # arch/ppc/syslib/ppc85xx_setup.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_setup.h # # arch/ppc/syslib/ppc85xx_setup.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_setup.c # # arch/ppc/syslib/ppc85xx_common.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_common.h # # arch/ppc/syslib/ppc85xx_common.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc85xx_common.c # # arch/ppc/syslib/open_pic.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1 -1 # ppc32: support for e500 and 85xx # # arch/ppc/syslib/Makefile # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -0 # ppc32: support for e500 and 85xx # # arch/ppc/platforms/85xx/mpc85xx_ads_common.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc85xx_ads_common.h # # arch/ppc/platforms/85xx/mpc85xx_ads_common.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc85xx_ads_common.c # # arch/ppc/platforms/85xx/mpc8540_ads.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc8540_ads.h # # arch/ppc/platforms/85xx/mpc8540_ads.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc8540_ads.c # # arch/ppc/platforms/85xx/mpc8540.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/mpc8540.c # # arch/ppc/platforms/85xx/Makefile # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/Makefile # # arch/ppc/platforms/85xx/Kconfig # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/85xx/Kconfig # # arch/ppc/mm/pgtable.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +32 -0 # ppc32: support for e500 and 85xx # # arch/ppc/mm/mmu_decl.h # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +9 -0 # ppc32: support for e500 and 85xx # # arch/ppc/mm/init.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +6 -0 # ppc32: support for e500 and 85xx # # arch/ppc/mm/fsl_booke_mmu.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/mm/fsl_booke_mmu.c # # arch/ppc/mm/fault.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -7 # ppc32: support for e500 and 85xx # # arch/ppc/mm/Makefile # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +1 -0 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/traps.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +89 -2 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/signal.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +42 -3 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/ptrace.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +84 -3 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/process.c # 2004/06/18 00:32:24-07:00 kumar.gala@freescale.com +95 -6 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/ppc_ksyms.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -1 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/misc.S # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +37 -3 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/head_e500.S # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/kernel/head_e500.S # # arch/ppc/kernel/entry.S # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +24 -12 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/cputable.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +12 -1 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/asm-offsets.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +7 -1 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/align.c # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +5 -5 # ppc32: support for e500 and 85xx # # arch/ppc/kernel/Makefile # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +4 -0 # ppc32: support for e500 and 85xx # # arch/ppc/Makefile # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +8 -2 # ppc32: support for e500 and 85xx # # arch/ppc/Kconfig # 2004/06/17 23:41:08-07:00 kumar.gala@freescale.com +33 -4 # ppc32: support for e500 and 85xx # # ChangeSet # 2004/06/18 07:52:38-07:00 hugh@veritas.com # [PATCH] mm: pretest pte_young and pte_dirty # # Test for pte_young before going to the costlier atomic test_and_clear, as # asm-generic does. Test for pte_dirty before going to the costlier atomic # test_and_clear, as asm-generic does (I said before that I would not do so for # pte_dirty, but was missing the point: there is nothing atomic about deciding # to do nothing). But I've not touched the rather different ppc and ppc64. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-x86_64/pgtable.h # 2004/06/17 23:41:07-07:00 hugh@veritas.com +15 -2 # mm: pretest pte_young and pte_dirty # # include/asm-parisc/pgtable.h # 2004/06/17 23:41:07-07:00 hugh@veritas.com +4 -0 # mm: pretest pte_young and pte_dirty # # include/asm-ia64/pgtable.h # 2004/06/17 23:41:07-07:00 hugh@veritas.com +4 -0 # mm: pretest pte_young and pte_dirty # # include/asm-i386/pgtable.h # 2004/06/17 23:41:07-07:00 hugh@veritas.com +14 -2 # mm: pretest pte_young and pte_dirty # # ChangeSet # 2004/06/18 07:52:27-07:00 hugh@veritas.com # [PATCH] mm: flush TLB when clearing young # # Traditionally we've not flushed TLB after clearing the young/referenced bit, # it has seemed just a waste of time. Russell King points out that on some # architectures, with the move from 2.4 mm sweeping to 2.6 rmap, this may be a # serious omission: very frequently referenced pages never re-marked young, and # the worst choices made for unmapping. # # So, replace ptep_test_and_clear_young by ptep_clear_flush_young throughout # rmap.c. Originally I'd imagined making some kind of TLB gather optimization, # but don't see what now: whether worth it rather depends on how common # cross-cpu flushes are, and whether global or not. # # ppc and ppc64 have already found this issue, and worked around it by arranging # TLB flush from their ptep_test_and_clear_young: with the aid of pgtable rmap # pointers. I'm hoping ptep_clear_flush_young will allow ppc and ppc64 to # remove that special code, but won't change them myself. # # It's worth noting that it is Andrea's anon_vma rmap which makes the vma # available for ptep_clear_flush_young in page_referenced_one: anonmm and # pte_chains would both need an additional find_vma for that. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/rmap.c # 2004/06/17 23:41:07-07:00 hugh@veritas.com +3 -3 # mm: flush TLB when clearing young # # ChangeSet # 2004/06/18 13:33:48+01:00 rmk@flint.arm.linux.org.uk # [ARM] Add support code for ARM hardware vector floating point # # This cset adds the code to handle the hardware vector floating point # unit found on some ARM926 and later CPUs. The hardware provides # an implementation for the common cases, and bounces exceptions for # other cases, which have to be handled in software, and signalling # SIGFPE as appropriate. # # include/asm-arm/vfpmacros.h # 2004/06/18 13:31:34+01:00 rmk@flint.arm.linux.org.uk +25 -0 # # include/asm-arm/vfpmacros.h # 2004/06/18 13:31:33+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/vfpmacros.h # # include/asm-arm/vfp.h # 2004/06/18 13:31:26+01:00 rmk@flint.arm.linux.org.uk +78 -0 # # include/asm-arm/vfp.h # 2004/06/18 13:31:26+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/vfp.h # # arch/arm/vfp/vfpsingle.c # 2004/06/18 13:31:18+01:00 rmk@flint.arm.linux.org.uk +1224 -0 # # arch/arm/vfp/vfpsingle.c # 2004/06/18 13:31:18+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpsingle.c # # arch/arm/vfp/vfpmodule.c # 2004/06/18 13:31:11+01:00 rmk@flint.arm.linux.org.uk +288 -0 # # arch/arm/vfp/vfpmodule.c # 2004/06/18 13:31:11+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpmodule.c # # arch/arm/vfp/vfpinstr.h # 2004/06/18 13:31:03+01:00 rmk@flint.arm.linux.org.uk +88 -0 # # arch/arm/vfp/vfpinstr.h # 2004/06/18 13:31:03+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpinstr.h # # arch/arm/vfp/vfphw.S # 2004/06/18 13:30:55+01:00 rmk@flint.arm.linux.org.uk +210 -0 # # arch/arm/vfp/vfphw.S # 2004/06/18 13:30:55+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfphw.S # # arch/arm/vfp/vfpdouble.c # 2004/06/18 13:30:41+01:00 rmk@flint.arm.linux.org.uk +1186 -0 # # arch/arm/vfp/vfpdouble.c # 2004/06/18 13:30:41+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfpdouble.c # # arch/arm/vfp/vfp.h # 2004/06/18 13:30:32+01:00 rmk@flint.arm.linux.org.uk +333 -0 # # arch/arm/vfp/vfp.h # 2004/06/18 13:30:32+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/vfp.h # # arch/arm/vfp/entry.S # 2004/06/18 13:30:14+01:00 rmk@flint.arm.linux.org.uk +45 -0 # # arch/arm/vfp/entry.S # 2004/06/18 13:30:14+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/entry.S # # arch/arm/vfp/Makefile # 2004/06/18 13:29:58+01:00 rmk@flint.arm.linux.org.uk +12 -0 # # arch/arm/vfp/Makefile # 2004/06/18 13:29:58+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/vfp/Makefile # # Documentation/arm/VFP/release-notes.txt # 2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +55 -0 # # include/asm-arm/thread_info.h # 2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +5 -2 # Add VFP state to thread information structure. # # include/asm-arm/fpstate.h # 2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +32 -0 # Add VFP hardware structures. # # Documentation/arm/VFP/release-notes.txt # 2004/06/18 13:29:51+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/VFP/release-notes.txt # # arch/arm/kernel/process.c # 2004/06/18 13:29:50+01:00 rmk@flint.arm.linux.org.uk +6 -0 # Add VFP calls for releasing VFP state held by a thread and # initialising VFP State. # # arch/arm/kernel/entry-armv.S # 2004/06/18 13:29:50+01:00 rmk@flint.arm.linux.org.uk +13 -0 # Add VFP calls and additional context switch support. # # arch/arm/Makefile # 2004/06/18 13:29:50+01:00 rmk@flint.arm.linux.org.uk +1 -0 # Add VFP directory to build # # arch/arm/Kconfig # 2004/06/18 13:29:49+01:00 rmk@flint.arm.linux.org.uk +11 -0 # Add VFP configuration option. # # ChangeSet # 2004/06/18 15:21:08+09:00 yoshfuji@linux-ipv6.org # [XFRM] fix dependency issues for CONFIG_IPV6=m. # # net/xfrm/xfrm_state.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +10 -0 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/xfrm/xfrm_export.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/xfrm/Makefile # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/ipv6/ipcomp6.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +5 -1 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/ipv6/esp6.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +8 -5 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/ipv6/ah6.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +5 -1 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/ipv4/ipcomp.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +7 -3 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/ipv4/esp4.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +9 -4 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # net/ipv4/ah4.c # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +4 -1 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # include/net/xfrm.h # 2004/06/18 15:20:58+09:00 yoshfuji@linux-ipv6.org +1 -1 # [XFRM] split up xfrm_check_output() into two functions to solve dependency issues. # # BitKeeper/deleted/.del-xfrm_output.c~af23cc5516e28602 # 2004/06/18 15:10:51+09:00 yoshfuji@linux-ipv6.org +0 -0 # Delete: net/xfrm/xfrm_output.c # # ChangeSet # 2004/06/18 01:56:40-04:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7 # into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7 # # drivers/acpi/pci_link.c # 2004/06/18 01:54:24-04:00 len.brown@intel.com +0 -0 # Auto merged # # arch/x86_64/kernel/mpparse.c # 2004/06/18 01:54:24-04:00 len.brown@intel.com +0 -0 # Auto merged # # arch/i386/kernel/mpparse.c # 2004/06/18 01:54:23-04:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/06/18 01:40:30-04:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.6 # into intel.com:/home/lenb/src/linux-acpi-test-2.6.7 # # arch/x86_64/kernel/mpparse.c # 2004/06/18 01:40:27-04:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/06/18 14:25:15+09:00 yoshfuji@linux-ipv6.org # [IPV6] XFRM: support (uncompressed) tunnel mode ipcomp6 using xfrm6_tunnel infrastructure. # # net/ipv6/xfrm6_tunnel.c # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +623 -0 # # net/ipv6/xfrm6_tunnel.c # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +0 -0 # BitKeeper file /home2/yoshfuji/BitKeeper/linux-2.6-export-2.6.8/linux-2.6-xfrm6tunnel/net/ipv6/xfrm6_tunnel.c # # net/ipv6/xfrm6_policy.c # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +2 -0 # [IPV6] XFRM: add missing xfrm6_tunnel.c. # # net/ipv6/ipcomp6.c # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +69 -0 # [IPV6] XFRM: support (uncompressed) tunnel mode ipcomp6 using xfrm6_tunnel infrastructure. # # net/ipv6/ip6_tunnel.c # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +9 -9 # [IPV6] XFRM: use xfrm6_tunnel infrastructure to register/unregister protocol handers. # # net/ipv6/Makefile # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +2 -1 # [IPV6] XFRM: add missing xfrm6_tunnel.c. # # include/net/xfrm.h # 2004/06/18 14:25:06+09:00 yoshfuji@linux-ipv6.org +14 -4 # [IPV6] XFRM: add missing xfrm6_tunnel.c. # # ChangeSet # 2004/06/18 13:56:36+09:00 yoshfuji@linux-ipv6.org # [IPV6] XFRM: add missing xfrm6_policy_check(). # # net/ipv6/ip6_tunnel.c # 2004/06/18 13:56:27+09:00 yoshfuji@linux-ipv6.org +5 -0 # [IPV6] XFRM: add missing xfrm6_policy_check(). # # ChangeSet # 2004/06/18 13:54:05+09:00 yoshfuji@linux-ipv6.org # [IPV6] make several functions static in ip6_tunnel that should be. # # net/ipv6/ip6_tunnel.c # 2004/06/18 13:53:56+09:00 yoshfuji@linux-ipv6.org +10 -6 # [IPV6] make several functions static in ip6_tunnel that should be. # # ChangeSet # 2004/06/18 00:18:19-04:00 len.brown@intel.com # [ACPI] handle SCI override to nth IOAPIC # http://bugzilla.kernel.org/show_bug.cgi?id=2835 # # arch/x86_64/kernel/mpparse.c # 2004/06/17 20:18:02-04:00 len.brown@intel.com +1 -0 # handle SCI override to nth IOAPIC # # arch/i386/kernel/mpparse.c # 2004/06/17 20:18:02-04:00 len.brown@intel.com +1 -0 # handle SCI override to nth IOAPIC # # ChangeSet # 2004/06/17 21:16:48-07:00 rth@twiddle.net # [PATCH] alpha: fix discontigmem+initrd build # # From: Ivan Kokshaysky # # Compilation fails due to incorrect usage of NODE_DATA(). # # Reported by hpa. # # arch/alpha/mm/numa.c # 2004/06/14 08:25:24-07:00 rth@twiddle.net +2 -2 # alpha: fix discontigmem+initrd build # # ChangeSet # 2004/06/17 21:04:44-07:00 paulus@samba.org # [PATCH] ppc64: Optimize exception/syscall entry/exit # # This rewrites the PPC64 exception entry/exit routines to make them # smaller and faster. # # In particular we no longer save all of the registers for the common # exceptions - system calls, hardware interrupts and decrementer (timer) # interrupts - only the volatile registers. The other registers are saved # and restored (if used) by the C functions we call. This involved # changing the registers we use in early exception processing from r20-r23 # to r9-r12, which ended up changing quite a lot of code in head.S. # Overall this gives us about a 20% reduction in null syscall time. # # Some system calls need all the registers (e.g. fork/clone/vfork and # [rt_]sigsuspend). For these the syscall dispatch code calls a stub that # saves the nonvolatile registers before calling the real handler. # # This also implements the force_successful_syscall_return() thing for # ppc64. # # Signed-off-by: Paul Mackerras # Signed-off-by: Linus Torvalds # # include/asm-ppc64/thread_info.h # 2004/06/16 22:46:06-07:00 paulus@samba.org +2 -2 # ppc64: Optimize exception/syscall entry/exit # # include/asm-ppc64/ptrace.h # 2004/06/16 22:46:06-07:00 paulus@samba.org +12 -0 # ppc64: Optimize exception/syscall entry/exit # # include/asm-ppc64/processor.h # 2004/06/16 22:46:06-07:00 paulus@samba.org +1 -2 # ppc64: Optimize exception/syscall entry/exit # # include/asm-ppc64/ppc_asm.h # 2004/06/16 22:46:06-07:00 paulus@samba.org +3 -5 # ppc64: Optimize exception/syscall entry/exit # # include/asm-ppc64/paca.h # 2004/06/16 22:46:06-07:00 paulus@samba.org +9 -11 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/xmon/xmon.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +0 -3 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/mm/fault.c # 2004/06/16 23:23:50-07:00 paulus@samba.org +33 -24 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/traps.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +15 -1 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/syscalls.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +14 -0 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/signal32.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +1 -1 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/signal.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +2 -2 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/process.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +5 -1 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/pacaData.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +0 -2 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/misc.S # 2004/06/16 22:46:06-07:00 paulus@samba.org +13 -12 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/head.S # 2004/06/16 22:46:06-07:00 paulus@samba.org +707 -760 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/entry.S # 2004/06/16 22:48:02-07:00 paulus@samba.org +277 -193 # ppc64: Optimize exception/syscall entry/exit # # arch/ppc64/kernel/asm-offsets.c # 2004/06/16 22:46:06-07:00 paulus@samba.org +10 -2 # ppc64: Optimize exception/syscall entry/exit # # ChangeSet # 2004/06/17 21:04:32-07:00 paulus@samba.org # [PATCH] ppc64: Implement CONFIG_PREEMPT # # This implements CONFIG_PREEMPT for ppc64. Aside from the entry.S # changes to check the _TIF_NEED_RESCHED bit when returning from an # exception, there are various changes to make the ppc64-specific code # preempt-safe, mostly adding preempt_enable/disable or get_cpu/put_cpu # calls where needed. I have been using this on my desktop G5 for the # last week without problems. # # Signed-off-by: Paul Mackerras # Signed-off-by: Linus Torvalds # # include/asm-ppc64/thread_info.h # 2004/06/09 23:21:41-07:00 paulus@samba.org +5 -2 # ppc64: Implement CONFIG_PREEMPT # # include/asm-ppc64/system.h # 2004/06/09 23:21:41-07:00 paulus@samba.org +2 -0 # ppc64: Implement CONFIG_PREEMPT # # include/asm-ppc64/hardirq.h # 2004/06/09 23:21:41-07:00 paulus@samba.org +2 -0 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/mm/tlb.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +5 -1 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/mm/init.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +4 -1 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/mm/hugetlbpage.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +4 -1 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/mm/hash_utils.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +7 -3 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/traps.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +2 -4 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/sys_ppc32.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +2 -6 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/signal32.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +5 -7 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/signal.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +3 -5 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/rtas.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +4 -2 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/ptrace32.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +6 -12 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/ptrace.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +4 -8 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/process.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +64 -23 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/entry.S # 2004/06/09 23:21:41-07:00 paulus@samba.org +50 -9 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/asm-offsets.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +1 -0 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/kernel/align.c # 2004/06/09 23:21:41-07:00 paulus@samba.org +9 -4 # ppc64: Implement CONFIG_PREEMPT # # arch/ppc64/Kconfig # 2004/06/09 23:21:41-07:00 paulus@samba.org +0 -1 # ppc64: Implement CONFIG_PREEMPT # # ChangeSet # 2004/06/17 22:54:26-05:00 stevef@smfhome1.smfdom # Fix typo in name of CIFS Kconfig option and add rename stats # # fs/cifs/cifssmb.c # 2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +12 -1 # add rename stats # # fs/cifs/cifsglob.h # 2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +2 -0 # add rename stats # # fs/cifs/cifs_debug.c # 2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +7 -1 # Add rename stats # # fs/Kconfig # 2004/06/17 22:54:19-05:00 stevef@smfhome1.smfdom +1 -1 # Fix typo in name of CIFS Kconfig option # # ChangeSet # 2004/06/17 23:21:03-04:00 len.brown@intel.com # [ACPI] avoid spurious interrupts on VIA # http://bugzilla.kernel.org/show_bug.cgi?id=2243 # # drivers/acpi/pci_link.c # 2004/06/11 10:38:46-04:00 len.brown@intel.com +3 -19 # disable all PCI Interrupt Links to be enabled by _SRS # # ChangeSet # 2004/06/17 23:00:08-04:00 len.brown@intel.com # [ACPI] fix passive cooling mode indicator (Luming Yu) # http://bugzilla.kernel.org/show_bug.cgi?id=1770 # # drivers/acpi/thermal.c # 2004/01/02 00:06:13-05:00 len.brown@intel.com +7 -0 # fix passive cooling mode indicator (Luming Yu) # # ChangeSet # 2004/06/17 16:25:47-07:00 tony.luck@intel.com # [PATCH] ia64: switching between CPEI & CPEP # # A couple of months ago Hidetoshi Seto from Fujitsu proposed # a patch to provide similar switching between interrupt mode # and polling mode for corrected platform events (CPE) as we # have for processor events (CMC) [with the obvious difference # that not all platforms support an interrupt for CPE]. # # I dusted it off and made a couple of very minor cleanups (which # Seto-san checked out last night on his test setup and confirmed # still passes). # # Signed-off-by: Tony Luck # Signed-off-by: David Mosberger # # arch/ia64/kernel/mca.c # 2004/06/16 13:24:00-07:00 tony.luck@intel.com +71 -16 # ia64: switching between CPEI & CPEP # # ChangeSet # 2004/06/17 16:22:26-07:00 pfg@sgi.com # [PATCH] ia64: fix SN2 interrupt rerouting # # Signed-off-by: Patrick Gefre # Signed-off-by: David Mosberger # # arch/ia64/sn/kernel/irq.c # 2004/06/17 08:42:20-07:00 pfg@sgi.com +17 -0 # ia64: fix SN2 interrupt rerouting # # arch/ia64/sn/io/sn2/ml_iograph.c # 2004/06/17 08:42:20-07:00 pfg@sgi.com +8 -8 # ia64: fix SN2 interrupt rerouting # # ChangeSet # 2004/06/17 15:47:19-07:00 davidm@tiger.hpl.hp.com # ia64: Fix build-problem when CONFIG_IA32 is not enabled. # # Without this fix, you'll get unresolved references to # sys_rt_sigaction(). # # include/asm-ia64/unistd.h # 2004/06/17 15:47:11-07:00 davidm@tiger.hpl.hp.com +2 -1 # (__ARCH_WANT_SYS_RT_SIGACTION): Move outside of # #ifdef CONFIG_IA32_SUPPORT bracket---we need # sys_rt_sigaction() whether we have ia32 emulation or not. # # ChangeSet # 2004/06/17 15:45:25-07:00 davidm@tiger.hpl.hp.com # ia64: Squish some more hazards & warnings for UP compile. # # include/asm-ia64/system.h # 2004/06/17 15:45:17-07:00 davidm@tiger.hpl.hp.com +1 -1 # (local_irq_enable): Precede ia64_ssm() with ia64_stop() to avoid # WAW hazard when local_irq_disable() is followed in the # same instruction-group by local_irq_enable(). # # include/asm-ia64/gcc_intrin.h # 2004/06/17 15:45:17-07:00 davidm@tiger.hpl.hp.com +11 -5 # (ia64_ptcga): Follow with ia64_dv_serialize_data() to shut up some # compiler/assembler-warnings which showed when compiling for UP. # (ia64_ptcl): Likewise. # (ia64_intrin_local_irq_restore): Put a stop-bit before the cmp.ne to # work around an apparent GCC v3.4 bug/limitation (it doesn't # seem to heed the clobber of p6/p7 and merrily generates code # that writes to p6/p7 right before the cmp.ne. # # ChangeSet # 2004/06/17 15:41:25-07:00 davidm@tiger.hpl.hp.com # ia64: Squish compiler-warning in perfmon.c when compiling for UP. # # arch/ia64/kernel/perfmon.c # 2004/06/17 15:41:17-07:00 davidm@tiger.hpl.hp.com +26 -25 # (pfm_force_cleanup): Move nside "#ifdef CONFIG_SMP" bracket to # avoid compiler-warning. # # ChangeSet # 2004/06/17 15:23:14-07:00 stern@rowland.harvard.edu # [PATCH] USB: Fix endian bug in g_file_storage # # This patch fixes a couple of places in g_file_storage where I forgot to # use proper byte-swapping. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/file_storage.c # 2004/06/17 09:15:53-07:00 stern@rowland.harvard.edu +2 -2 # USB: Fix endian bug in g_file_storage # # ChangeSet # 2004/06/17 15:22:55-07:00 stern@rowland.harvard.edu # [PATCH] USB Storage: unusual_devs.h update # # On Thu, 17 Jun 2004, Daniel Nouri wrote: # > I get this message when inserting my USB MMC card reader: # > # > usb 3-1: new full speed USB device using address 4 # > usb.agent[5388]: usb-storage: already loaded # > usb-storage: This device (04e6,0006,0205 S 01 P 01) has an unneeded Protocol entry in unusual_devs.h # > Please send a copy of this message to # # Thanks for letting us know. This patch will eliminate that log message. # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2004/06/17 09:06:45-07:00 stern@rowland.harvard.edu +1 -1 # USB Storage: unusual_devs.h update # # ChangeSet # 2004/06/17 15:22:34-07:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: Lexar Jumpshot CF reader # # This patch is required to fix up the jumpshot driver, and to supress # the 'unneeded entry' message for another device which uses the same # VID/PID/rev for multiple different versions of the device. # # Alan Stern cooked this patch up, originally. # # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2004/06/17 08:57:07-07:00 mdharm-usb@one-eyed-alien.net +2 -2 # USB Storage: Lexar Jumpshot CF reader # # drivers/usb/storage/jumpshot.c # 2004/06/17 08:51:10-07:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Lexar Jumpshot CF reader # # ChangeSet # 2004/06/17 15:22:14-07:00 david-b@pacbell.net # [PATCH] USB: add support for Buffalo LUA-U2-KTX # # Add support for Buffalo's LUA-U2-KTX, which is a AX8817X based usb # ethernet adapter. I just added the USB id and it worked like a dream. # # From: Neil Bortnak # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/usbnet.c # 2004/06/14 05:52:53-07:00 david-b@pacbell.net +6 -0 # USB: add support for Buffalo LUA-U2-KTX # # ChangeSet # 2004/06/17 15:21:44-07:00 david-b@pacbell.net # [PATCH] proper bios handoff in ehci-hcd # # Stuart Hayes here at Dell has identified this or/and mix-up in the # ehci-hcd driver. Because of this, ehci-hcd is not properly released by # BIOSes supporting full 2.0 and port behavior can then become erratic. # # (Code predates general availability of such BIOS firmware. This version # of the patch also fixes minor linewrap issues.) # # From: Gary Lerhaupt # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ehci-hcd.c # 2004/06/16 01:29:01-07:00 david-b@pacbell.net +4 -3 # proper bios handoff in ehci-hcd # # ChangeSet # 2004/06/17 15:21:14-07:00 sean@mess.org # [PATCH] USB: PhidgetServo driver fixes # # Here is a patch for the phidgetservo driver -- it was using memory after # kfree(), and using driver_info is much nicer. :) # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/phidgetservo.c # 2004/06/16 08:28:42-07:00 sean@mess.org +63 -54 # USB: PhidgetServo driver fixes # # ChangeSet # 2004/06/17 15:20:50-07:00 stern@rowland.harvard.edu # [PATCH] USB: Only process ports with change events pending # # This patch adds a bit-array to the hub driver's private data structure, # used for storing the contents of the hub's interrupt status message. That # message indicates which ports have events pending (and whether the hub # itself has events pending). By only polling the status of the ports # listed in the bit-array we can save a fair amount of overhead in hub # communication. # # (The #error test added to hub.h is a little awkward, but it's purely # precautionary -- it won't matter until someone decides to support hubs # with more than 31 ports!) # # Also included in the patch, since this seemed the perfect opportunity for # it, is Byron's suggestion for handling hub events in the order in which # they were received. # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.h # 2004/06/15 09:10:57-07:00 stern@rowland.harvard.edu +4 -0 # USB: Only process ports with change events pending # # drivers/usb/core/hub.c # 2004/06/15 09:11:37-07:00 stern@rowland.harvard.edu +14 -2 # USB: Only process ports with change events pending # # ChangeSet # 2004/06/17 13:40:02-07:00 jmorris@redhat.com # [IPV6]: Fix OOPS in fragmentation. # # Incorrect SKB pointer is passed to output() callback # in ip6_fragment(). # # Work done by James Morris and Yoshifuji Hideaki. # # Signed-off-by: James Morris # Signed-off-by: Yoshifuji Hideaki # Signed-off-by: David S. Miller # # net/ipv6/ip6_output.c # 2004/06/17 13:39:47-07:00 jmorris@redhat.com +4 -6 # [IPV6]: Fix OOPS in fragmentation. # # Incorrect SKB pointer is passed to output() callback # in ip6_fragment(). # # Work done by James Morris and Yoshifuji Hideaki. # # Signed-off-by: James Morris # Signed-off-by: Yoshifuji Hideaki # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/17 16:31:52-04:00 len.brown@intel.com # [ACPI] PCI bus numbering workaround for ServerWorks # from David Shaohua Li # http://bugzilla.kernel.org/show_bug.cgi?id=1662 # # drivers/acpi/pci_root.c # 2004/06/17 12:31:13-04:00 len.brown@intel.com +48 -1 # if _BBN is bogus, evaluate _CRS on PCI bus # to get the bus number (David Shaohua Li) # # ChangeSet # 2004/06/17 12:11:42-07:00 davem@nuts.davemloft.net # [NET]: In unregister_netdevice(), do synchronize_net() before final dev_put(). # # This way we make sure that all destination cache updates # to remove references to this device are seen by entire # system before final destruction of the device. # # ChangeSet # 2004/06/17 12:09:59-07:00 davem@nuts.davemloft.net # Cset exclude: kuznet@ms2.inr.ac.ru|ChangeSet|20040616204246|05149 # # net/core/dst.c # 2004/06/17 12:09:54-07:00 davem@nuts.davemloft.net +0 -0 # Exclude # # ChangeSet # 2004/06/17 11:52:18-07:00 shemminger@osdl.org # [SPARSE]: Fix another net warning. # # Get rid of warning from assignment in conditional. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/core/net-sysfs.c # 2004/06/17 11:52:04-07:00 shemminger@osdl.org +1 -1 # [SPARSE]: Fix another net warning. # # Get rid of warning from assignment in conditional. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/17 11:40:00-07:00 shemminger@osdl.org # [SPARSE]: Get rid of warning in bridge ethtool ioctl. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br_if.c # 2004/06/17 11:39:35-07:00 shemminger@osdl.org +1 -1 # [SPARSE]: Get rid of warning in bridge ethtool ioctl. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/17 11:16:48-07:00 shemminger@osdl.org # [SPARSE]: Annotate csum_and_copy_to_user(). # # include/asm-sparc64/checksum.h # 2004/06/17 11:16:34-07:00 shemminger@osdl.org +2 -1 # [SPARSE]: Annotate csum_and_copy_to_user(). # # include/asm-sparc/checksum.h # 2004/06/17 11:16:34-07:00 shemminger@osdl.org +1 -1 # [SPARSE]: Annotate csum_and_copy_to_user(). # # include/asm-sh/checksum.h # 2004/06/17 11:16:34-07:00 shemminger@osdl.org +4 -2 # [SPARSE]: Annotate csum_and_copy_to_user(). # # include/asm-parisc/checksum.h # 2004/06/17 11:16:34-07:00 shemminger@osdl.org +4 -2 # [SPARSE]: Annotate csum_and_copy_to_user(). # # include/asm-mips/checksum.h # 2004/06/17 11:16:34-07:00 shemminger@osdl.org +2 -1 # [SPARSE]: Annotate csum_and_copy_to_user(). # # include/asm-i386/checksum.h # 2004/06/17 11:16:34-07:00 shemminger@osdl.org +4 -2 # [SPARSE]: Annotate csum_and_copy_to_user(). # # ChangeSet # 2004/06/17 11:15:13-07:00 akpm@osdl.org # [BRIDGE]: Fix bridge sysfs improprely initialized kobject. # # The bridge sysfs interface introduced around 2.6.7-rc1 created a bad # entry in /sys because it didn't initialise the name member of the kobject. # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # net/bridge/br_sysfs_br.c # 2004/06/17 11:14:46-07:00 akpm@osdl.org +1 -3 # [BRIDGE]: Fix bridge sysfs improprely initialized kobject. # # The bridge sysfs interface introduced around 2.6.7-rc1 created a bad # entry in /sys because it didn't initialise the name member of the kobject. # # Signed-off-by: Andrew Morton # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/17 10:56:25-07:00 shemminger@osdl.org # [SPARSE]: Add annotations to sock_filter.h # # Since sock_fprog is argument in ioctl, the filter pointer needs # to be annotated. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # include/linux/filter.h # 2004/06/17 10:56:10-07:00 shemminger@osdl.org +3 -1 # [SPARSE]: Add annotations to sock_filter.h # # Since sock_fprog is argument in ioctl, the filter pointer needs # to be annotated. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/17 10:51:14-07:00 shemminger@osdl.org # [SPARSE]: Get rid of warning in irtty_ioctl(). # # Don't really need verify_area because result of copy_to_user is checked. # Add annotation to get rid of sparse warnings. # # Signed-off-by: Stephen Hemminger # Signed-off-by: Jean Tourrilhes # Signed-off-by: David S. Miller # # drivers/net/irda/irtty-sir.c # 2004/06/17 10:50:59-07:00 shemminger@osdl.org +1 -9 # [SPARSE]: Get rid of warning in irtty_ioctl(). # # Don't really need verify_area because result of copy_to_user is checked. # Add annotation to get rid of sparse warnings. # # Signed-off-by: Stephen Hemminger # Signed-off-by: Jean Tourrilhes # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/17 11:09:05-05:00 stevef@stevef95.austin.ibm.com # fix typo in cifs kernel config option title # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/Kconfig # 2004/06/17 11:08:47-05:00 stevef@stevef95.austin.ibm.com +1 -1 # fix typo in cifs kernel config option title # # ChangeSet # 2004/06/17 02:15:36-04:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7-mpparse # into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7 # # arch/x86_64/kernel/mpparse.c # 2004/06/17 02:15:31-04:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/06/17 01:42:44-04:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7 # into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7 # # arch/x86_64/kernel/mpparse.c # 2004/06/17 01:42:37-04:00 len.brown@intel.com +0 -0 # Auto merged # # arch/ia64/pci/pci.c # 2004/06/17 01:42:37-04:00 len.brown@intel.com +0 -0 # Auto merged # # arch/ia64/kernel/iosapic.c # 2004/06/17 01:42:36-04:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/06/17 01:30:00-04:00 len.brown@intel.com # Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.6 # into intel.com:/home/lenb/src/linux-acpi-test-2.6.7 # # arch/i386/kernel/dmi_scan.c # 2004/06/17 01:29:57-04:00 len.brown@intel.com +0 -0 # Auto merged # # ChangeSet # 2004/06/17 01:26:33-04:00 len.brown@intel.com # [ACPI] Fix a lockup which Sid Boyce # discovered with IOAPIC disabled. # # The problem was that drivers/serial/8250_acpi.c found COM1 in the ACPI # namespace and called acpi_register_gsi() to set up its IRQ. ACPI tells us # that the COM1 IRQ is edge triggered, active high, but acpi_register_gsi() # was ignoring the edge_level argument, so it blindly set the COM1 IRQ to be # level-triggered. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Andrew Morton # With the 2.6.7-rc3-mm1 acpi changes to arch/x86_64/kernel/mpparse.c, # mp_find_ioapic is called from a non-__init function. The fatal code # path is reached when loading device drivers for PCI devices. # # ChangeSet # 2004/06/17 01:19:49-04:00 len.brown@intel.com # [ACPI] mp_find_ioapic() oops from mp_register_gsi() on device resume # Signed-off-by: Andrew Morton # # arch/i386/kernel/mpparse.c # 2004/05/31 06:03:27-04:00 len.brown@intel.com +1 -1 # It is called from mp_register_gsi(), which is called on the device resume # path. Kernel oopses. # # Program received signal SIGEMT, Emulation trap. # mp_find_ioapic (gsi=1) at arch/i386/kernel/mpparse.c:862 # 862 { # (gdb) bt # #0 mp_find_ioapic (gsi=1) at arch/i386/kernel/mpparse.c:862 # #1 0xc0111de1 in mp_register_gsi (gsi=17, edge_level=1, active_high_low=1) # at arch/i386/kernel/mpparse.c:1042 # #2 0xc010e164 in acpi_register_gsi (gsi=17, edge_level=9, active_high_low=9) # at arch/i386/kernel/acpi/boot.c:460 # #3 0xc01ef27e in acpi_pci_irq_enable (dev=0xc16da800) at drivers/acpi/pci_irq.c:382 # # ChangeSet # 2004/06/17 01:15:58-04:00 len.brown@intel.com # [ACPI] *** Warning: "acpi_register_gsi" [drivers/serial/8250_acpi.ko] undefined! # # Signed-off-by: Andrew Morton # # arch/i386/kernel/acpi/boot.c # 2004/06/17 01:15:53-04:00 len.brown@intel.com +2 -0 # *** Warning: "acpi_register_gsi" [drivers/serial/8250_acpi.ko] undefined! # # Signed-off-by: Andrew Morton # # ChangeSet # 2004/06/16 23:10:50-05:00 stevef@smfhome1.smfdom # Fix /proc/fs/cifs/Stats to handle larger return data, and correct Kconfig reference to /proc/fs/cifs/Stats # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifsfs.h # 2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +1 -1 # update cifs version to 1.19 # # fs/cifs/cifs_debug.c # 2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +42 -17 # fix /proc/fs/cifs/Stats to handle larger return data # # fs/cifs/CHANGES # 2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +9 -1 # Update cifs change log for 1.19 # # fs/Kconfig # 2004/06/16 23:10:44-05:00 stevef@smfhome1.smfdom +11 -2 # Correct name of /proc/fs/cifs/Stats file. Add cifs posix extensions configure option. # # ChangeSet # 2004/06/16 21:05:55-07:00 davidm@tiger.hpl.hp.com # Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5 # into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5 # # arch/ia64/kernel/gate.S # 2004/06/16 21:05:50-07:00 davidm@tiger.hpl.hp.com +0 -4 # Auto merged # # arch/ia64/kernel/fsys.S # 2004/06/16 21:05:50-07:00 davidm@tiger.hpl.hp.com +0 -2 # Auto merged # # ChangeSet # 2004/06/16 20:53:53-07:00 davidm@tiger.hpl.hp.com # ia64: Nuke two warnings in mca.c that showed in the simulator configuration. # # arch/ia64/kernel/mca.c # 2004/06/16 20:53:46-07:00 davidm@tiger.hpl.hp.com +8 -0 # (ia64_mca_cpe_int_handler): Define only if CONFIG_ACPI is defined. # (ia64_mca_cpe_int_caller): Likewise. # # ChangeSet # 2004/06/16 20:51:30-07:00 davidm@tiger.hpl.hp.com # ia64: Fix ia32 partial-page-list code to compile cleanly in more configs. # # # include/asm-ia64/ia32.h # 2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +9 -3 # (IA32_PAGE_SHIFT): Move to here from ia32priv.h. # (ia32_copy_partial_page_list): Declare unconditionally. If # PAGE_SHIFT == IA32_PAGE_SHIFT< define it as a no-op. # (ia32_drop_partial_page_list): Likewise. # # arch/ia64/kernel/process.c # 2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +2 -6 # (flush_thread): Remove #ifdef CONFIG_IA32_SUPPORT bracket (no longer needed). # Pass task-pointer to ia32_drop_partial_page_list() instead of # partial-page list (the thread.ppl member may not exist in all # configurations). # (exit_thread): Likewise. # # arch/ia64/ia32/sys_ia32.c # 2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +8 -5 # (ia32_drop_partial_page_list): Take task-pointer instead of partial_page_list- # pointer. # (sys32_munmap): Declare pstart and pend only when really needed. # (sys32_mremap): Likewise. # # arch/ia64/ia32/ia32priv.h # 2004/06/16 20:51:21-07:00 davidm@tiger.hpl.hp.com +7 -4 # (_ASM_IA64_IA32_PRIV_H): Rename from _ASM_IA64_IA32_H to avoid name-clash. # (IA32_PAGE_SHIFT): Move to include/asm-ia64/ia32.h. # (ia32_init_pp_list): Define as 0 for case swhere PAGE_SHIFT==IA32_PAGE_SHIFT. # # arch/ia64/kernel/head.S # 2004/06/16 18:09:33-07:00 davidm@tiger.hpl.hp.com +5 -1 # (_start): Initialize "current" pointer for init-task to be in # region 5, not 7. # # arch/ia64/kernel/entry.S # 2004/06/16 18:09:33-07:00 davidm@tiger.hpl.hp.com +4 -2 # (ia64_switch_to): Don't try to map "current"-pointers which are # inside region 5. # # arch/ia64/ia32/ia32_support.c # 2004/06/16 18:09:33-07:00 davidm@tiger.hpl.hp.com +10 -6 # ia64: Move "current" pointer for init-task from region 7 to region 5. # # This patch initializes "current" for the init-task such that it will # be an address in region 5 rather than region 7. Also, it updates the # context-switch code such that it won't attempt to install a pinned TLB # entry when the current task points inside region 5 (as will happen now # with the init-task). # # This fixes a problem which was triggered by SELinux. The problem was # due to the fact that the init_task is initialized statically (in # init_tasks.c) and hence resides in region 5, but the "current" pointer # was using the region 7-alias of that data-structure, which causes # inconsistencies and failers with the list-maniplulation code. # # Signed-off-by: Kazuto MIYOSHI # Signed-off-by: Takayoshi Kochi # Signed-off-by: Kaigai Kohei # Signed-off-by: David Mosberger # # ChangeSet # 2004/06/16 19:57:30-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/netdev-2.6/via-rhine # into pobox.com:/spare/repo/net-drivers-2.6 # # drivers/net/via-rhine.c # 2004/06/16 19:57:26-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # ChangeSet # 2004/06/16 19:56:25-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/netdev-2.6/via-gbit # into pobox.com:/spare/repo/net-drivers-2.6 # # drivers/net/Kconfig # 2004/06/16 19:56:21-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # ChangeSet # 2004/06/16 19:54:04-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/netdev-2.6/misc-herbert # into pobox.com:/spare/repo/net-drivers-2.6 # # drivers/net/yellowfin.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/sungem.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/starfire.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/ns83820.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/ibmlana.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/forcedeth.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/ewrk3.c # 2004/06/16 19:54:01-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/at1700.c # 2004/06/16 19:54:00-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/acenic.c # 2004/06/16 19:54:00-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/3c527.c # 2004/06/16 19:54:00-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # ChangeSet # 2004/06/16 19:51:21-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/netdev-2.6/ip-copysum # into pobox.com:/spare/repo/net-drivers-2.6 # # drivers/net/yellowfin.c # 2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/tulip/winbond-840.c # 2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/epic100.c # 2004/06/16 19:51:17-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # ChangeSet # 2004/06/16 16:51:07-07:00 jbarnes@engr.sgi.com # [PATCH] ia64: update sn2_defconfig # # Small patch to update the sn2_defconfig file. I just did a 'make oldconfig' # with the current sn2_defconfig and removed 8250 support. # Signed-off-by: David Mosberger # # arch/ia64/configs/sn2_defconfig # 2004/06/16 09:03:12-07:00 jbarnes@engr.sgi.com +51 -55 # ia64: update sn2_defconfig # # ChangeSet # 2004/06/16 16:04:19-07:00 kaos@sgi.com # [PATCH] ia64: Support SN platform specific error features # # The SN prom supports fine grained error handling features, the OS needs # to tell the prom if the OS expects to use these platform specific # features. # # Signed-off-by: Keith Owens # Signed-off-by: David Mosberger # # include/asm-ia64/sn/sn_sal.h # 2004/06/16 06:14:42-07:00 kaos@sgi.com +34 -0 # ia64: Support SN platform specific error features # # arch/ia64/sn/kernel/setup.c # 2004/06/16 06:14:42-07:00 kaos@sgi.com +22 -1 # ia64: Support SN platform specific error features # # ChangeSet # 2004/06/16 18:25:29-04:00 alan@redhat.com # [PATCH] add new via-velocity gigabit ethernet driver # # Contributed by VIA, cleaned up by Alan. # # drivers/net/via-velocity.h # 2004/06/02 15:49:48-04:00 alan@redhat.com +1885 -0 # PATCH: via-velocity with new ethtool used # # drivers/net/via-velocity.h # 2004/06/02 15:49:48-04:00 alan@redhat.com +0 -0 # BitKeeper file /spare/repo/netdev-2.6/via-gbit/drivers/net/via-velocity.h # # drivers/net/via-velocity.c # 2004/06/16 17:29:42-04:00 alan@redhat.com +3277 -0 # PATCH: via-velocity with new ethtool used # # drivers/net/Makefile # 2004/06/16 16:22:14-04:00 alan@redhat.com +1 -0 # PATCH: via-velocity with new ethtool used # # drivers/net/Kconfig # 2004/06/16 16:22:14-04:00 alan@redhat.com +11 -0 # PATCH: via-velocity with new ethtool used # # drivers/net/via-velocity.c # 2004/06/16 17:29:42-04:00 alan@redhat.com +0 -0 # BitKeeper file /spare/repo/netdev-2.6/via-gbit/drivers/net/via-velocity.c # # ChangeSet # 2004/06/16 15:52:13-05:00 stevef@stevef95.austin.ibm.com # fix throttle to limit number of requests to 50 on wire to server at one time. # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/transport.c # 2004/06/16 15:52:04-05:00 stevef@stevef95.austin.ibm.com +20 -13 # fix throttle to limit number of requests to 50 on wire to server at one time. # # ChangeSet # 2004/06/16 13:48:12-07:00 davem@nuts.davemloft.net # [TCP]: No vegas by default just yet. # # net/ipv4/tcp_input.c # 2004/06/16 13:47:53-07:00 davem@nuts.davemloft.net +1 -1 # [TCP]: No vegas by default just yet. # # ChangeSet # 2004/06/16 11:18:42-07:00 dada1@cosmosbay.com # [NET]: Tidy somaxconn sysctl doc. # # Documentation/networking/ip-sysctl.txt # 2004/06/16 11:18:23-07:00 dada1@cosmosbay.com +3 -2 # [NET]: Tidy somaxconn sysctl doc. # # ChangeSet # 2004/06/16 10:57:05-07:00 dlstevens@us.ibm.com # [IPV4]: Fix interface selection in multicast sockops. # # net/ipv4/ip_sockglue.c # 2004/06/16 10:56:46-07:00 dlstevens@us.ibm.com +1 -0 # [IPV4]: Fix interface selection in multicast sockops. # # ChangeSet # 2004/06/16 10:27:13-07:00 herbert@gondor.apana.org.au # [NET]: Clear dev refs in dst->child. # # This is a resend of an earlier patch to dst_dev_event. I've changed # it slightly by moving the input/output assignment into dst_ifdown. # # To recap, this patch drops lingering IPsec references to a device that # is being unregistered. The child processing in the GC is too late # since it never runs until the reference on the dst hits zero which # could take a long time for things like TCP connections. # # The reason I've left the input/output assignment outside the loop is # because they aren't really necessary for the IPsec dst's, and if # it were in the loop then we'll have to do the same child processing # in ___dst_free as well. # # I've tested this with an ESP/IPCOMP tunnel and I can confirm that it # does fix the problem. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # net/core/dst.c # 2004/06/16 10:26:56-07:00 herbert@gondor.apana.org.au +37 -25 # [NET]: Clear dev refs in dst->child. # # This is a resend of an earlier patch to dst_dev_event. I've changed # it slightly by moving the input/output assignment into dst_ifdown. # # To recap, this patch drops lingering IPsec references to a device that # is being unregistered. The child processing in the GC is too late # since it never runs until the reference on the dst hits zero which # could take a long time for things like TCP connections. # # The reason I've left the input/output assignment outside the loop is # because they aren't really necessary for the IPsec dst's, and if # it were in the loop then we'll have to do the same child processing # in ___dst_free as well. # # I've tested this with an ESP/IPCOMP tunnel and I can confirm that it # does fix the problem. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/16 10:23:42-07:00 davem@nuts.davemloft.net # Merge nuts.davemloft.net:/disk1/BK/net-2.6.8 # into nuts.davemloft.net:/disk1/BK/net-2.6 # # net/ipv4/tcp.c # 2004/06/16 10:23:34-07:00 davem@nuts.davemloft.net +0 -0 # Auto merged # # ChangeSet # 2004/06/16 11:36:45-05:00 jejb@mulgrave.(none) # scsi_debug: num_parts, ptype and (re-)scans # # From: Douglas Gilbert # # Changes in version 1.73: # - 'num_parts' parameter to specify 0 to 4 partitions # - 'ptype' to specify (or change via sysfs) SCSI # peripheral device type # - support ability to increase the number of targets # and/or luns then re-scan a scsi_debug host # - remove redundant trailing spaces # # The new facilties are described at: # http://www.torque.net/sg/sdebug26.html # A tarball of driver (version 1.73) is also there. # # Signed-off-by: James Bottomley # (conflict resolution) # # drivers/scsi/scsi_debug.h # 2004/06/16 11:36:19-05:00 jejb@mulgrave.(none) +1 -4 # scsi_debug: num_parts, ptype and (re-)scans # # drivers/scsi/scsi_debug.c # 2004/06/16 11:36:19-05:00 jejb@mulgrave.(none) +253 -124 # scsi_debug: num_parts, ptype and (re-)scans # # ChangeSet # 2004/06/16 09:32:58-05:00 jejb@mulgrave.(none) # SCSI: fix uninitialised variable warning # # Spotted By: Andrew Morton # # drivers/scsi/scsi_transport_spi.c: In function `spi_dv_retrain': # drivers/scsi/scsi_transport_spi.c:393: warning: `period' might be used uninitialized in this function # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_transport_spi.c # 2004/06/16 09:32:42-05:00 jejb@mulgrave.(none) +1 -1 # SCSI: fix uninitialised variable warning # # ChangeSet # 2004/06/15 21:46:23-07:00 jmorris@redhat.com # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/ss/services.c # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +12 -0 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/ss/policydb.c # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -1 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/security.h # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +5 -4 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/flask.h # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -0 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/class_to_string.h # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -0 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/av_permissions.h # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +223 -0 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/av_perm_to_string.h # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +12 -0 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/av_inherit.h # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +9 -0 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/hooks.c # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +80 -22 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/Makefile # 2004/06/15 21:46:08-07:00 jmorris@redhat.com +1 -1 # [SELINUX]: Fine-grained Netlink support - SELinux changes # # This patch contains SELinux changes which add support for extended Netlink # socket classes and the associated permissions nlmsg_read and nlmsg_write. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 21:45:30-07:00 jmorris@redhat.com # [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook # # Modifies the LSM netlink_send() hook so that it takes a struct sock # parameter. SELinux will use this parameter to lookup the class of socket, # which was assigned during socket security initialization. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/hooks.c # 2004/06/15 21:45:15-07:00 jmorris@redhat.com +1 -1 # [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook # # Modifies the LSM netlink_send() hook so that it takes a struct sock # parameter. SELinux will use this parameter to lookup the class of socket, # which was assigned during socket security initialization. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/dummy.c # 2004/06/15 21:45:15-07:00 jmorris@redhat.com +1 -1 # [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook # # Modifies the LSM netlink_send() hook so that it takes a struct sock # parameter. SELinux will use this parameter to lookup the class of socket, # which was assigned during socket security initialization. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # net/netlink/af_netlink.c # 2004/06/15 21:45:15-07:00 jmorris@redhat.com +1 -1 # [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook # # Modifies the LSM netlink_send() hook so that it takes a struct sock # parameter. SELinux will use this parameter to lookup the class of socket, # which was assigned during socket security initialization. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # include/linux/security.h # 2004/06/15 21:45:15-07:00 jmorris@redhat.com +11 -8 # [SELINUX]: Fine-grained Netlink support - add sk to netlink_send hook # # Modifies the LSM netlink_send() hook so that it takes a struct sock # parameter. SELinux will use this parameter to lookup the class of socket, # which was assigned during socket security initialization. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 21:44:40-07:00 jmorris@redhat.com # [SELINUX]: Fine-grained Netlink support - move security_netlink_send() hook. # # This patch moves the security_netlink_send() LSM hook after the user copy, # so that LSM modules can safely examine skb payload content. For SELinux, # we need to look at the Netlink message type. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # net/netlink/af_netlink.c # 2004/06/15 21:44:26-07:00 jmorris@redhat.com +4 -4 # [SELINUX]: Fine-grained Netlink support - move security_netlink_send() hook. # # This patch moves the security_netlink_send() LSM hook after the user copy, # so that LSM modules can safely examine skb payload content. For SELinux, # we need to look at the Netlink message type. # # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 21:42:03-07:00 jmorris@redhat.com # [SELINUX]: Fine-grained Netlink support - SELinux headers # # This patch regenerates the SELinux module headers to reflect new class # and access vectors definitions. The size of the diff is misleading; # much of it is simply a change in the ordering of the automatically # generated definitions. The corresponding generation script has been # changed to ensure a stable order in the future. # # Author: Stephen Smalley # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/flask.h # 2004/06/15 21:41:48-07:00 jmorris@redhat.com +12 -0 # [SELINUX]: Fine-grained Netlink support - SELinux headers # # This patch regenerates the SELinux module headers to reflect new class # and access vectors definitions. The size of the diff is misleading; # much of it is simply a change in the ordering of the automatically # generated definitions. The corresponding generation script has been # changed to ensure a stable order in the future. # # Author: Stephen Smalley # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/class_to_string.h # 2004/06/15 21:41:48-07:00 jmorris@redhat.com +12 -0 # [SELINUX]: Fine-grained Netlink support - SELinux headers # # This patch regenerates the SELinux module headers to reflect new class # and access vectors definitions. The size of the diff is misleading; # much of it is simply a change in the ordering of the automatically # generated definitions. The corresponding generation script has been # changed to ensure a stable order in the future. # # Author: Stephen Smalley # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/av_permissions.h # 2004/06/15 21:41:48-07:00 jmorris@redhat.com +350 -250 # [SELINUX]: Fine-grained Netlink support - SELinux headers # # This patch regenerates the SELinux module headers to reflect new class # and access vectors definitions. The size of the diff is misleading; # much of it is simply a change in the ordering of the automatically # generated definitions. The corresponding generation script has been # changed to ensure a stable order in the future. # # Author: Stephen Smalley # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/include/av_perm_to_string.h # 2004/06/15 21:41:48-07:00 jmorris@redhat.com +89 -3 # [SELINUX]: Fine-grained Netlink support - SELinux headers # # This patch regenerates the SELinux module headers to reflect new class # and access vectors definitions. The size of the diff is misleading; # much of it is simply a change in the ordering of the automatically # generated definitions. The corresponding generation script has been # changed to ensure a stable order in the future. # # Author: Stephen Smalley # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 21:39:10-07:00 anton@samba.org # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # include/linux/skbuff.h # 2004/06/15 21:38:55-07:00 anton@samba.org +24 -0 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # include/asm-ppc64/system.h # 2004/06/15 21:38:55-07:00 anton@samba.org +9 -0 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # drivers/net/s2io.h # 2004/06/15 21:38:55-07:00 anton@samba.org +0 -1 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # drivers/net/s2io.c # 2004/06/15 21:38:55-07:00 anton@samba.org +2 -2 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # drivers/net/ixgb/ixgb_main.c # 2004/06/15 21:38:55-07:00 anton@samba.org +2 -3 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # drivers/net/e1000/e1000_main.c # 2004/06/15 21:38:55-07:00 anton@samba.org +2 -3 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # drivers/net/e1000/e1000_ethtool.c # 2004/06/15 21:38:55-07:00 anton@samba.org +3 -2 # [NET]: Allow IP header alignment to be overriden. # # Author: Anton Blanchard # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 21:37:06-07:00 shemminger@osdl.org # [ATM]: Include compiler.h in atm.h # # include/linux/atm.h # 2004/06/15 21:36:52-07:00 shemminger@osdl.org +1 -0 # [ATM]: Include compiler.h in atm.h # # ChangeSet # 2004/06/15 21:35:21-07:00 davem@nuts.davemloft.net # [TCP]: Tweak some default sysctl values. # # tcp_default_win_scale: 7 # tcp_vegas_cong_avoid: 1 # tcp_moderate_rcvbuf: 1 # tcp_bic: 1 # # net/ipv4/tcp_input.c # 2004/06/15 21:18:53-07:00 davem@nuts.davemloft.net +3 -3 # [TCP]: Tweak some default sysctl values. # # tcp_default_win_scale: 7 # tcp_vegas_cong_avoid: 1 # tcp_moderate_rcvbuf: 1 # tcp_bic: 1 # # net/ipv4/tcp.c # 2004/06/15 21:18:53-07:00 davem@nuts.davemloft.net +1 -1 # [TCP]: Tweak some default sysctl values. # # tcp_default_win_scale: 7 # tcp_vegas_cong_avoid: 1 # tcp_moderate_rcvbuf: 1 # tcp_bic: 1 # # ChangeSet # 2004/06/15 21:09:47-07:00 yoshfuji@linux-ipv6.org # [IPV6]: UDPv6 checksum. # # We always need to check UDPv6 checksum because it is mandatory. # # Author: Yoshifuji Hideaki # Signed-off-by: David S. Miller # # net/ipv6/udp.c # 2004/06/15 21:09:31-07:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: UDPv6 checksum. # # We always need to check UDPv6 checksum because it is mandatory. # # Author: Yoshifuji Hideaki # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 21:07:24-07:00 jmorris@redhat.com # [SELINUX]: Fix sock_orphan race. # # The patch below fixes a race between sock_orphan() and # selinux_socket_sock_rcv_skb() which can lead to a null pointer deref oops # under heavy load. The sk_callback_lock is used in the patch to # synchronize access to the incoming socket's inode security state. # # This patch has been under test in the Fedora kernel for over a month # without incident. # # Author: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # security/selinux/hooks.c # 2004/06/15 21:07:09-07:00 jmorris@redhat.com +21 -16 # [SELINUX]: Fix sock_orphan race. # # The patch below fixes a race between sock_orphan() and # selinux_socket_sock_rcv_skb() which can lead to a null pointer deref oops # under heavy load. The sk_callback_lock is used in the patch to # synchronize access to the incoming socket's inode security state. # # This patch has been under test in the Fedora kernel for over a month # without incident. # # Author: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/16 00:33:13-03:00 acme@toy.kerneljanitors.org # [ECONET] kill some trivial warnings # # Signed-off-by: Arnaldo Carvalho de Melo # # net/econet/af_econet.c # 2004/06/16 00:33:01-03:00 acme@toy.kerneljanitors.org +6 -8 # [ECONET] kill some trivial warnings # # Signed-off-by: Arnaldo Carvalho de Melo # # ChangeSet # 2004/06/15 20:24:51-07:00 davem@nuts.davemloft.net # Merge bk://kernel.bkbits.net/acme/net-2.6 # into nuts.davemloft.net:/disk1/BK/net-2.6 # # net/ipv6/tcp_ipv6.c # 2004/06/15 20:24:38-07:00 davem@nuts.davemloft.net +0 -0 # Auto merged # # ChangeSet # 2004/06/15 20:20:25-07:00 ahu@ds9a.nl # [NET]: Update some sysctl documentation. # # I ran the following (crappy) script: # ... # In /proc/sys/ and found a host of undocumented sysctls. This patch documents # a number of them, and at least mentions the rest as 'TODO'. Please verify my # code-inspired documentation before applying! # # Signed-off-by: Bert Hubert # Signed-off-by: David S. Miller # # Documentation/networking/ip-sysctl.txt # 2004/06/15 20:19:32-07:00 ahu@ds9a.nl +57 -0 # [NET]: Update some sysctl documentation. # # I ran the following (crappy) script: # ... # In /proc/sys/ and found a host of undocumented sysctls. This patch documents # a number of them, and at least mentions the rest as 'TODO'. Please verify my # code-inspired documentation before applying! # # Signed-off-by: Bert Hubert # Signed-off-by: David S. Miller # # Documentation/filesystems/proc.txt # 2004/06/15 20:19:32-07:00 ahu@ds9a.nl +2 -1 # [NET]: Update some sysctl documentation. # # I ran the following (crappy) script: # ... # In /proc/sys/ and found a host of undocumented sysctls. This patch documents # a number of them, and at least mentions the rest as 'TODO'. Please verify my # code-inspired documentation before applying! # # Signed-off-by: Bert Hubert # Signed-off-by: David S. Miller # # ChangeSet # 2004/06/15 16:29:30-07:00 eranian@hpl.hp.com # [PATCH] ia64: fix info in /proc/pal/*/bus_info # # This patch fixes to minor bugs: # - corrected descriptions for bit 52 and 53 of the /proc/pal/CPU*/bus_info # entry; they were swapped # - corrected a typo for bit 55 of the /proc/pal/CPU*/bus_info entry # # Signed-off-by: Stephane Eranian # Signed-off-by: David Mosberger # # arch/ia64/kernel/palinfo.c # 2004/06/15 10:28:07-07:00 eranian@hpl.hp.com +2 -2 # ia64: fix info in /proc/pal/*/bus_info # # ChangeSet # 2004/06/15 12:48:08-05:00 jejb@mulgrave.(none) # Fix endless loop in SCSI SPI transport class # # If the driver doesn't update the peroid, we go # around forever. The fix is to keep our old period # unless the driver returns a greater one. # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_transport_spi.c # 2004/06/15 12:47:53-05:00 jejb@mulgrave.(none) +3 -1 # Fix endless loop in SCSI SPI transport class # # ChangeSet # 2004/06/15 12:32:52-05:00 jejb@mulgrave.(none) # Merge # # drivers/scsi/qlogicpti.c # 2004/06/15 12:32:34-05:00 jejb@mulgrave.(none) +0 -1 # SCCS merged # # drivers/scsi/esp.c # 2004/06/15 12:32:09-05:00 jejb@mulgrave.(none) +0 -1 # SCCS merged # # include/linux/pci_ids.h # 2004/06/15 12:28:06-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # drivers/scsi/st.c # 2004/06/15 12:28:06-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # drivers/scsi/scsi_debug.c # 2004/06/15 12:28:06-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # drivers/scsi/osst.c # 2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # drivers/scsi/cpqfcTScontrol.c # 2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # drivers/scsi/Kconfig # 2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/06/15 12:28:05-05:00 jejb@mulgrave.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/15 12:09:19-05:00 rddunlap@osdl.org # [PATCH] Comment out an unused function in drivers/scsi/wd7000.c # # Eliminate unused function wd7000_abort() in wd7000 driver. # # CC [M] drivers/scsi/wd7000.o # drivers/scsi/wd7000.c:1612: warning: `wd7000_abort' defined but not used # # As the author states in his comment, this is "unfinished business" ;-) # # # From: Mika Kukkonen # Signed-off-by: Randy Dunlap # Signed-off-by: James Bottomley # # drivers/scsi/wd7000.c # 2004/06/15 10:49:13-05:00 rddunlap@osdl.org +2 -1 # Comment out an unused function in drivers/scsi/wd7000.c # # ChangeSet # 2004/06/15 12:07:20-05:00 bunk@fs.tum.de # [PATCH] modular scsi/mca_53c9x doesn't work # # On Mon, Jun 14, 2004 at 08:22:15PM +0100, Christoph Hellwig wrote: # > On Mon, Jun 14, 2004 at 08:52:56PM +0200, Adrian Bunk wrote: # > > The issue described in the mail forwarded below is still present in # > > 2.6.7-rc3-mm2 (but not specific to -mm). # > > # > > I'd suggest the following workaround: # > # > Please add the exports instead. It'll affect all the other 53C9X-based # > drivers aswell. # # This sounds like a better solution. # # Signed-off-by: James Bottomley # # drivers/scsi/NCR53C9x.c # 2004/06/14 17:47:23-05:00 bunk@fs.tum.de +11 -0 # modular scsi/mca_53c9x doesn't work # # ChangeSet # 2004/06/15 12:06:00-05:00 akpm@osdl.org # [PATCH] drivers/scsi/megaraid.c: user/kernel pointer bugs # # From: "Robert T. Johnson" # # Since arg is a user pointer, so are uioc_mimd and uiocp, and hence umc is a # user pointer. Thus reading umc->xferaddr requires dereferencing a user # pointer, which isn't safe. # # Signed-off-by: Andrew Morton # Signed-off-by: James Bottomley # # drivers/scsi/megaraid.c # 2004/06/10 08:19:19-05:00 akpm@osdl.org +4 -2 # drivers/scsi/megaraid.c: user/kernel pointer bugs # # ChangeSet # 2004/06/15 12:04:04-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: 64-bit cleanup # # > Although, I think, there's still a glitch there (modified if's order). # > I'll send a new version, if the approach is approved in principle. # # Ok, attached is version 3:-) It also fixes a definite (although, perhaps, # harmless) bug in scsiiom.c. And removes a redundant assignment in # tmscsim.c. # # Signed-off-by: Guennadi Liakhovetski # Signed-off-by: James Bottomley # # drivers/scsi/tmscsim.c # 2004/06/14 17:28:50-05:00 g.liakhovetski@gmx.de +40 -34 # tmscsim: 64-bit cleanup # # ChangeSet # 2004/06/15 12:01:55-05:00 hch@lst.de # [PATCH] avoid obsolete scsi APIs in eata_pio # # Signed-off-by: James Bottomley # # drivers/scsi/eata_pio.c # 2004/06/07 05:22:42-05:00 hch@lst.de +66 -65 # avoid obsolete scsi APIs in eata_pio # # drivers/scsi/eata_generic.h # 2004/06/07 05:19:05-05:00 hch@lst.de +1 -1 # avoid obsolete scsi APIs in eata_pio # # ChangeSet # 2004/06/15 11:59:06-05:00 hch@lst.de # [PATCH] clean up SCSI_TIMEOUT usage # # - qlogicfc.c abuses SCSI_TIEMOUT although it's not part of the scsi # core, give it it's own ISP_TIMEOUT define # - avoid redefining timeouts #ifdef DEBUG, that's a cause for heisenbugs # just waiting to happen # - now SCSI_TIMEOUT is private to scsi_scan.c, move it there # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_scan.c # 2004/06/06 06:20:50-05:00 hch@lst.de +5 -0 # clean up SCSI_TIMEOUT usage # # drivers/scsi/scsi_error.c # 2004/06/06 06:19:15-05:00 hch@lst.de +4 -9 # clean up SCSI_TIMEOUT usage # # drivers/scsi/scsi.h # 2004/06/06 06:17:31-05:00 hch@lst.de +0 -6 # clean up SCSI_TIMEOUT usage # # drivers/scsi/qlogicfc.c # 2004/06/06 06:17:21-05:00 hch@lst.de +2 -1 # clean up SCSI_TIMEOUT usage # # ChangeSet # 2004/06/15 16:33:27+01:00 rmk@flint.arm.linux.org.uk # [ARM] pxafb doesn't need to include asm/mach-types.h # # drivers/video/pxafb.c # 2004/06/15 16:31:17+01:00 rmk@flint.arm.linux.org.uk +0 -1 # pxafb doesn't need to include asm/mach-types.h # # ChangeSet # 2004/06/15 15:50:19+01:00 elf@com.rmk.(none) # [ARM PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM # # Patch from Marc Singer # # [if's replaced by ifdef's.] # # While the BLOB boot loader doesn't support it, there are two others, # UBOOT and Logic's LOLO, that will initialize the SDRAM controller such # that the memory appears as a contiguous region. This layout to be # required for WinCE and, thus, is the default for these loaders. The # memory organization had been optimized for discontiguous blocks. Now, # it supports a default mode that is compatible with all of the # bootloaders as well as options to optimize for either contiguous or # discontiguous models. # # Withing, there is also a slight change to the way that the DEBUG_LL # macros select the UART address. Now it uses immediate constants # exclusively. # # # include/asm-arm/arch-lh7a40x/memory.h # 2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +21 -48 # [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM # # arch/arm/mach-lh7a40x/Kconfig # 2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +31 -0 # [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM # # arch/arm/kernel/debug.S # 2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +2 -1 # [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM # # arch/arm/Kconfig # 2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +2 -2 # [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM # # Documentation/arm/Sharp-LH/SDRAM # 2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +51 -0 # [PATCH] 1928/1: lh7a40x #7 Changes to memory model to support contiguous SDRAM # # Documentation/arm/Sharp-LH/SDRAM # 2004/06/12 22:57:20+01:00 elf@com.rmk.(none) +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/Sharp-LH/SDRAM # # ChangeSet # 2004/06/15 15:46:21+01:00 icampbell@com.rmk.(none) # [ARM PATCH] 1926/3: PXAFB cleanups and fixes # # Patch from Ian Campbell # # Sorry, 1926/2 was missing a brace. Fixed here. # # Previous commentry: # I have corrected the grayscale conversion to correctly use the upper # byte rather than the lower one. As requested I have also left the # actual grayscale conversion where it was this time and just dealt with # the palette differences in pxafb_setpalettereg. # # fb_alloc_cmap is only called when bits_per_pixel is < 16, otherwise # any existing cmap is freed. # # I also fixed up all the spaces and brackets issues (not just the one # you raised previously) this introduces some noise in the patch, if # you'd like the two patches separately please ask. # # drivers/video/pxafb.c # 2004/06/15 13:42:45+01:00 icampbell@com.rmk.(none) +50 -43 # [PATCH] 1926/3: PXAFB cleanups and fixes # # ChangeSet # 2004/06/15 14:52:36+01:00 rmk@flint.arm.linux.org.uk # [ARM] Add clock API # # Since peripheral clocks are be derived in SoC or even platform # specific ways, we need a way to keep this information out of the # drivers. AMBA Primecells are defined in terms of functional units # where clocks are derived from external sources, and it is up to the # SoC designer to determine where to derive those clocks from. # # Therefore, we provide a very basic API which allows platforms to # provide this information in a generic manner to their peripherals. # This framework also allows peripherals to shut down unused clock # sources when they're not in use. # # include/asm-arm/hardware/clock.h # 2004/06/15 14:49:41+01:00 rmk@flint.arm.linux.org.uk +121 -0 # # include/asm-arm/hardware/clock.h # 2004/06/15 14:49:41+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/hardware/clock.h # # arch/arm/mach-versatile/clock.h # 2004/06/15 14:49:33+01:00 rmk@flint.arm.linux.org.uk +25 -0 # # arch/arm/mach-versatile/clock.h # 2004/06/15 14:49:33+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-versatile/clock.h # # arch/arm/mach-versatile/clock.c # 2004/06/15 14:49:25+01:00 rmk@flint.arm.linux.org.uk +146 -0 # # arch/arm/mach-versatile/clock.c # 2004/06/15 14:49:25+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-versatile/clock.c # # arch/arm/mach-integrator/clock.h # 2004/06/15 14:49:18+01:00 rmk@flint.arm.linux.org.uk +25 -0 # # arch/arm/mach-integrator/clock.h # 2004/06/15 14:49:18+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-integrator/clock.h # # arch/arm/mach-integrator/clock.c # 2004/06/15 14:49:09+01:00 rmk@flint.arm.linux.org.uk +138 -0 # # include/asm-arm/arch-integrator/impd1.h # 2004/06/15 14:49:09+01:00 rmk@flint.arm.linux.org.uk +0 -1 # IM-PD/1 VCO is now controlled via the clock subsystem. # # arch/arm/mach-integrator/clock.c # 2004/06/15 14:49:09+01:00 rmk@flint.arm.linux.org.uk +0 -0 # BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-integrator/clock.c # # drivers/serial/amba-pl011.c # 2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +58 -23 # Make PL011 UART use clock layer to obtain clock source information. # # drivers/input/serio/ambakmi.c # 2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +33 -5 # Make keyboard/mouse interface use clock layer to obtain KMI clock # source information. # # arch/arm/mach-versatile/Makefile # 2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Add clock.o object. # # arch/arm/mach-integrator/integrator_cp.c # 2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +62 -0 # Add Integrator/CP specific clocks. # # arch/arm/mach-integrator/impd1.c # 2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +28 -13 # Add clock structures for IM-PD/1 on-board clocks. # # arch/arm/mach-integrator/Makefile # 2004/06/15 14:49:08+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Add clock.o to build objects. # # drivers/net/acenic.c # 2004/06/14 18:49:59-04:00 johnpol@2ka.mipt.ru +2 -2 # Typo in ethtool code in acenic driver # # ChangeSet # 2004/06/14 18:34:29-04:00 akpm@osdl.org # [PATCH] prism94 build fix # # init_wds is being instantiated in both isl_ioctl.c and islpci_eth.c, causing # linkage errors. # # drivers/net/wireless/prism54/islpci_mgt.o(.rodata+0x198): In function `islpci_mgmt_rx_fill': # /usr/src/25/drivers/net/wireless/prism54/islpci_mgt.c:154: multiple definition of `init_wds' # drivers/net/wireless/prism54/islpci_eth.o(.rodata+0x1c8):/usr/src/25/include/linux/skbuff.h:815: first defined here # # Signed-off-by: Andrew Morton # # drivers/net/wireless/prism54/islpci_mgt.h # 2004/06/13 22:29:45-04:00 akpm@osdl.org +1 -1 # prism94 build fix # # ChangeSet # 2004/06/14 18:33:35-04:00 a.othieno@bluewin.ch # [PATCH] Kill stale references to Documentation/networking/8139too.txt # # Documentation/networking/8139too.txt was removed with this ChangeSet: # # ChangeSet@1.1371.153.2 2004-01-10 15:34:47-05:00 jgarzik@redhat.com # [netdrvr] remove Documentation/networking/8139too.txt # # All sections of the document are woefully outdated. # # # However, `grep' still reveals these references to it: # # drivers/net/8139too.c:90: See 8139too.txt for more details. # drivers/net/Kconfig:1539: as well as the # Documentation/networking/00-INDEX:7:8139too.txt # # Signed-off-by: Arthur Othieno # # drivers/net/Kconfig # 2004/06/14 14:50:09-04:00 a.othieno@bluewin.ch +1 -3 # Kill stale references to Documentation/networking/8139too.txt # # drivers/net/8139too.c # 2004/06/14 14:50:09-04:00 a.othieno@bluewin.ch +0 -2 # Kill stale references to Documentation/networking/8139too.txt # # Documentation/networking/00-INDEX # 2004/06/14 14:50:09-04:00 a.othieno@bluewin.ch +0 -2 # Kill stale references to Documentation/networking/8139too.txt # # ChangeSet # 2004/06/14 18:32:42-04:00 johnpol@2ka.mipt.ru # [PATCH] Typo in ethtool code in acenic driver # # In 10mbps detection code. # # ChangeSet # 2004/06/14 14:38:31-07:00 stern@rowland.harvard.edu # [PATCH] USB: Remove private khubd semaphore # # This patch removes the private semaphore used by the hub driver, and uses # the regular "serialize" semaphore instead. This will satisfy the general # locking requirements for adding and removing devices attached to the hub. # The only tricky aspect is that now the hub event handler must take a # reference to the hub device while waiting to acquire the semaphore, in # case the hub is disconnected during the wait. # # The patch also replaces a few occurrences of spin_lock_irqsave() in # regions where interrupts are known to be enabled with spin_lock_irq(). # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.h # 2004/06/14 03:33:06-07:00 stern@rowland.harvard.edu +0 -1 # USB: Remove private khubd semaphore # # drivers/usb/core/hub.c # 2004/06/14 03:59:02-07:00 stern@rowland.harvard.edu +24 -21 # USB: Remove private khubd semaphore # # ChangeSet # 2004/06/14 10:35:58-07:00 stern@rowland.harvard.edu # [PATCH] USB: Fix bug in TT initialization introduced by earlier # # This patch repairs a bug introduced by an earlier patch: The TT # initialization code was moved to _after_ the TT's first use. The patch # simply puts the code back the way it used to be. # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/13 07:11:31-07:00 stern@rowland.harvard.edu +13 -10 # USB: Fix bug in TT initialization introduced by earlier # # ChangeSet # 2004/06/14 10:35:15-07:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: Fix race when removing the SCSI host # # This patch fixes a race is disconnecting a usb-storage device that occurs # with the SCSI layer. It's primarily reproducable via adding delays into # various disconnect and reset processing paths, but has also been # encountered in the field. # # This patch started life as as281b, and was modified by me only to patch # properly against current kernels. # # The main features of the patch are: # # Store the host pointer at the start of the control thread # rather than trying to get it from srb->device; after the host # is removed the SCSI device structure may no longer exist. # # Keep dev_semaphore locked during the entire time the control # thread or reset handlers are using the us_data structure. # # Reorder the items in dissociate_dev() and release_resources() # so that things are released in the opposite order from the way # they were acquired originally. Don't bother to increment and # decrement the usb_device's reference count; it's unnecessary. # # In disconnect(), first set the DISCONNECTING flag so that no # more I/O will take place and no more requests will be accepted. # Next, cut short the current command and wait for it to finish. # Then call scsi_remove_host(). The SCSI core guarantees that # when scsi_remove_host() returns, the host will not be in error # recovery and all outstanding commands will have been cancelled. # # Remove some old useless left-over code that was #if'ed out. # # Use a wait_queue for the 6-second delay during device resets # so that we can be woken up in the middle if a disconnect occurs. # # The key point here is that after scsi_remove_host(), everything is idle as # far as the SCSI midlayer is concerned. But if there was a command in # progress at the time, the midlayer will abort it without telling us or # waiting for it to complete. Hence we have to wait for the control thread # to be idle before we can try to kill it. This should happen quickly, # since all I/O attempted by the thread will fail immediately. # # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2004/06/13 13:09:07-07:00 mdharm-usb@one-eyed-alien.net +3 -2 # USB Storage: Fix race when removing the SCSI host # # drivers/usb/storage/usb.c # 2004/06/13 13:09:07-07:00 mdharm-usb@one-eyed-alien.net +85 -126 # USB Storage: Fix race when removing the SCSI host # # drivers/usb/storage/transport.c # 2004/06/13 13:09:07-07:00 mdharm-usb@one-eyed-alien.net +5 -4 # USB Storage: Fix race when removing the SCSI host # # ChangeSet # 2004/06/14 10:33:05-07:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: INQUIRY fixup, mode-sense options, Genesys devices # # This patch does a few things (all in the same section of code). It started # life as patches as226b, as280, and as275. Later it was merged into as226e # and I added significantly to it. # # # First, this patch introduces a new config option to allow people to enable # write-protect detection for their USB devices. With some luck, we've # finally got it right and can eventually remove this option in favor of # enabling this behavior all the time. # # Next, we change how we force some flags on -- it turns out that there are # some 'generic' entries in the SCSI devinfo which was overriding us when we # didn't want it. # # Finally, we add a safety check to the workaround for GeneSys Logic devices # -- if the max_sectors parameter has already been turned down, we won't turn # it up. # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/scsiglue.c # 2004/06/13 08:24:10-07:00 mdharm-usb@one-eyed-alien.net +46 -6 # USB Storage: INQUIRY fixup, mode-sense options, Genesys devices # # drivers/usb/storage/Kconfig # 2004/06/13 08:24:10-07:00 mdharm-usb@one-eyed-alien.net +22 -0 # USB Storage: INQUIRY fixup, mode-sense options, Genesys devices # # ChangeSet # 2004/06/12 22:23:05-03:00 acme@toy.kerneljanitors.org # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/core/stream.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +41 -0 # # net/sunrpc/xprt.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +2 -2 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/sunrpc/svcsock.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/ipv6/tcp_ipv6.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/ipv4/tcp_output.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +4 -4 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/ipv4/tcp_minisocks.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/ipv4/tcp_ipv4.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/ipv4/tcp.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +3 -22 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # net/core/stream.c # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +0 -0 # BitKeeper file /home/acme/bk/net-2.6/net/core/stream.c # # net/core/Makefile # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +1 -1 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # include/net/tcp.h # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +0 -22 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # include/net/sock.h # 2004/06/12 22:22:55-03:00 acme@toy.kerneljanitors.org +20 -0 # [NET] first bits of net/core/stream.c # # Move tcp sk_wmem_queued related functions to net/core/stream.c, will be # used by other SOCK_STREAM protocols, starting with LLC. # # Also move the tcp_charge_skb to sock.h, for the same reasons. # # Signed-off-by: Arnaldo Carvalho de Melo # # arch/ia64/kernel/unwind.c # 2004/06/11 17:13:56-07:00 kaos@sgi.com +20 -15 # ia64: Remove warnings when unwind debug is turned on # # ChangeSet # 2004/06/11 17:06:39-07:00 david-b@pacbell.net # [PATCH] USB: usb on big endian, ehci needs a byteswap # # Adds a missing byteswap that would affect interrupt transfers # with EHCI on big-endian platforms, like Rick's MIPS-4km uClinux. # Needed for external hubs, and then likely for mice, keyboards, # and so on. # # From: Rick Sewill # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ehci-sched.c # 2004/06/11 06:09:39-07:00 david-b@pacbell.net +1 -1 # USB: usb on big endian, ehci needs a byteswap # # ChangeSet # 2004/06/11 17:06:09-07:00 david-b@pacbell.net # [PATCH] USB: retry string fetches on ZLPs not just STALLs # # This matches the behavior for other descriptor fetches. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/message.c # 2004/06/11 04:49:33-07:00 david-b@pacbell.net +2 -2 # USB: retry string fetches on ZLPs not just STALLs # # ChangeSet # 2004/06/11 17:05:38-07:00 david-b@pacbell.net # [PATCH] USB: usbnet shouldn't oops on cdc error path # # If the string descriptor fetch works, no problem. Else # make the disconnect() logic -- newly called because of # "recent" changes to interface claiming logic -- use its # fast cleanup path, since we're still not fully set up yet. # # Should resolve OSDL bugid 2714; please merge. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/usbnet.c # 2004/06/10 23:55:54-07:00 david-b@pacbell.net +1 -0 # USB: usbnet shouldn't oops on cdc error path # # ChangeSet # 2004/06/11 17:05:08-07:00 david-b@pacbell.net # [PATCH] USB: usbtest just uses module_param() # # This prevents some warnings during modprobe. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/usbtest.c # 2004/06/11 00:06:34-07:00 david-b@pacbell.net +8 -8 # USB: usbtest just uses module_param() # # ChangeSet # 2004/06/11 16:52:33-07:00 thoffman@arnor.net # [PATCH] USB: ATI Remote driver update # # Here are some contributed improvements for the ATI remote driver. # # I submitted the driver and it was accepted several months ago. # Since then a few people have sent me patches and suggestions. # # This patch adds two things: # # (1) support for the "Lola" X10 remote, sent to me by # Seth Cohn # # (2) key autorepeat support, sent to me by # Vincent Vanackere # # The key autorepeat support has been tested by me, but the Lola support # has not, as I don't have the hardware. # # Thanks to Seth and Vincent, with my apologies for taking so long to # forward their improvements along. # # # Signed-off-by: Torrey Hoffman # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/input/ati_remote.c # 2004/06/08 17:12:09-07:00 thoffman@arnor.net +42 -12 # USB: ATI Remote driver update # # drivers/usb/input/Kconfig # 2004/06/09 15:24:29-07:00 thoffman@arnor.net +8 -6 # USB: ATI Remote driver update # # ChangeSet # 2004/06/11 16:51:56-07:00 stern@rowland.harvard.edu # [PATCH] USB: Mark devices as NOTATTACHED as soon as possible # # This patch implements something we've been lacking for a long time: a way # to mark devices as USB_STATE_NOTATTACHED as soon as we know that they're # gone. The usb_device->state member is no longer protected by the # ->serialize semaphore; instead there's a new private spinlock. Usbcore # routines should no longer set ->state directly; instead they should use # the new utility routine usb_set_device_state(). There are protections # against changing states while devices are being added or removed. # # Change assignments to udev->state into calls of # usb_set_device_state(). # # Add new private device_state_lock to the hub driver, along # with usb_set_device_state() and recursively_mark_NOTATTACHED(). # # Acquire the new spinlock while adding or removing children[] # pointers. # # When disabling a port that has a child device, mark the child # as NOTATTACHED. # # You mentioned once having tried to do something like this and running into # trouble. Take a good look and let me know if you see any difficulties # here. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.h # 2004/06/09 06:52:00-07:00 stern@rowland.harvard.edu +3 -0 # USB: Mark devices as NOTATTACHED as soon as possible # # drivers/usb/core/message.c # 2004/06/09 06:50:10-07:00 stern@rowland.harvard.edu +4 -4 # USB: Mark devices as NOTATTACHED as soon as possible # # drivers/usb/core/hub.c # 2004/06/09 07:16:54-07:00 stern@rowland.harvard.edu +85 -12 # USB: Mark devices as NOTATTACHED as soon as possible # # drivers/usb/core/hcd.c # 2004/06/09 06:46:56-07:00 stern@rowland.harvard.edu +2 -2 # USB: Mark devices as NOTATTACHED as soon as possible # # ChangeSet # 2004/06/11 16:24:02-07:00 davidm@tiger.hpl.hp.com # ia64: Update defconfig # # arch/ia64/defconfig # 2004/06/11 16:23:55-07:00 davidm@tiger.hpl.hp.com +17 -6 # Update # # ChangeSet # 2004/06/11 11:32:29-07:00 kaos@sgi.com # [PATCH] ia64: Remove warnings when unwind debug is turned on # # Turning on UNW_DEBUG generates warnings for incorrect number of # parameters for formats and several cases of "suggest explicit braces to # avoid ambiguous `else'", because UNW_DPRINT contains an if statement. # # Signed-off-by: Keith Owens # Signed-off-by: David Mosberger # # ChangeSet # 2004/06/10 20:00:01-04:00 margitsw@t-online.de # [PATCH] prism54: White space and indentation # # 2004-05-29 Margit Schubert-While # # * White space and indentation patch # # ChangeSet # 2004/06/10 19:59:53-04:00 margitsw@t-online.de # [PATCH] prism54: Fix typo # # 2004-05-29 Margit Schubert-While # # * isl_ioctl.c : Fix typo # # ChangeSet # 2004/06/10 19:59:45-04:00 margitsw@t-online.de # [PATCH] prism54: Fix channel stats, bump version to 1.2 # # 2004-05-20 Aurelien Alleaume # # * islpci_eth.c : use dev_kfree_skb_irq instead of dev_kfree_skb where needed. # # * isl_ioctl.c : report channel instead of frequency in scan. # # * islpci_hotplug.c : bump version to 1.2 # # ChangeSet # 2004/06/10 19:59:36-04:00 margitsw@t-online.de # [PATCH] prism54: Reduce module verbosity # # 2004-05-01 Margit Schubert-While # # * Reduce module verbosity # # ChangeSet # 2004/06/10 19:59:28-04:00 margitsw@t-online.de # [PATCH] prism54: Align skb patch # # * islpci_eth.c, islpci_dev.c : Align skb->data unconditonally after # allocation. This would appear to improve RX rate # # ChangeSet # 2004/06/10 19:59:20-04:00 margitsw@t-online.de # [PATCH] prism54: Add likely/unlikely, KO wds completely # # * islpci_mgt.h : Change init_wds definition # # * islpci_eth.c : Do some likely/unlikely # # ChangeSet # 2004/06/10 19:59:11-04:00 margitsw@t-online.de # [PATCH] prism54: Don't allow mib reads while unconfigured # # 004-04-17 Aurelien Alleaume # # * oid_mgt.c, isl_ioctl.c : Cleanup. Prevented real oid reading # before the card is configured with mib values (might be # related to # bug #53). # # ChangeSet # 2004/06/10 19:59:03-04:00 margitsw@t-online.de # [PATCH] prism54: Fix bug 77, strengthened oid txn # # 2004-04-09 Aurelien Alleaume # # * oid_mgt.c, isl_ioctl.c : Cleanups. Bug #77. Minor stuffs. # # * islpci_mgt.c (islpci_mgt_transaction) : enforce serialization # in oid transaction. lindent.sh. # # * islpci_mgt.c (islpci_mgt_transaction) : Strengthened oid transaction. # # ChangeSet # 2004/06/10 19:58:55-04:00 margitsw@t-online.de # [PATCH] prism54: Fix bugs 39/73 # # 2004-04-07 Margit Schubert-While # # * Bugs 39 and 73 # # ChangeSet # 2004/06/10 19:58:46-04:00 margitsw@t-online.de # [PATCH] prism54: Fix bugs 74/75 # # 2004-03-22 Aurelien Alleaume # # * oid_mgt.c, isl_ioctl.c : Minor bugfixes : #74 and #75. # # ChangeSet # 2004/06/10 19:38:59-04:00 bunk@fs.tum.de # [PATCH] add NAPI help texts # # NAPI seems to be so self-explaining that no help texts are needed. ;-) # # I combined the two help texts that were at NAPI options, and added them # to all NAPI options. # # ChangeSet # 2004/06/10 19:37:53-04:00 rmk@arm.linux.org.uk # [PATCH] add ARM smc91x driver # # ChangeSet # 2004/06/10 19:58:38-04:00 margitsw@t-online.de # [PATCH] prism54: Fix endian patch # # * Split out patch islpci_eth.c : # * Fix endian problem (bug 74/75 related) # # ChangeSet # 2004/06/10 20:52:50-04:00 jgarzik@pobox.com # [netdrvr acenic] remove unneeded ifdefs # # ChangeSet # 2004/06/10 20:19:03-04:00 shemminger@osdl.org # [PATCH] fix oops from acenic ethtool # # Fix the following OOPS that happens when doing ifup on FC-2 # with 2.6.7 in acenic and a security hole due to missing capable(NET_ADMIN), # by replacing private ethtool handling with ethtool_ops. # # (Yes, Jes because of DEV_ETHTOOL_OPS define it will still work # on ancient kernels.) # # ChangeSet # 2004/06/10 19:58:30-04:00 margitsw@t-online.de # [PATCH] prism54: Kernel compatibility # # 2004-03-20 Margit Schubert-While # # * isl_38xx.[ch], isl_ioctl.c, islpci_dev.[ch], islpci_eth.c # islpci_hotplug.c, islpci_mgt.[ch], oid_mgt.c, prismcompat.h: # Adopt new prism54 kernel compatibility. # Remove remaining kernel version ifdefs. # # ChangeSet # 2004/06/10 19:37:01-04:00 akpm@osdl.org # [PATCH] fealnx-mac-address-and-other-issues.patch # # (resend - I need to get this out of my tree my one means or another..) # # # From: "SuD (Alex)" # # I recently was given a surecom 10/100 ethernet card and found that i could # not change Mac address for it as other driver/devices allow. I tried to # implement the missing feature and noticed that the device is quite peculiar # (or either my system is broken), when trying to fill mac address registers # (no matter whether io_ops is set): - If I write a byte (writeb) to an even # i/o address it seems like actually a word was written (the next byte is set # to 0). - If I write a byte to an odd i/o address my pc gets bad freezed. # # That made think of writing 16bit words (writew) for the memory address, as # opposed to what most driver examples do. It works for me (I hope i set the # lines at the right place in device_open function after the device is # reset). I hope the code is clean enough and does not mess with byte # ordering. This is the patch (this time against 2.6.5): # # (akpm: Is this right on big-endian?) # # drivers/net/acenic.c # 2004/06/10 20:52:44-04:00 jgarzik@pobox.com +0 -6 # [netdrvr acenic] remove unneeded ifdefs # # drivers/net/acenic.h # 2004/06/04 17:31:46-04:00 shemminger@osdl.org +0 -1 # fix oops from acenic ethtool # # drivers/net/acenic.c # 2004/06/04 17:31:46-04:00 shemminger@osdl.org +127 -121 # fix oops from acenic ethtool # # drivers/net/wireless/prism54/oid_mgt.h # 2004/05/28 08:06:38-04:00 margitsw@t-online.de +1 -1 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/05/28 09:12:49-04:00 margitsw@t-online.de +7 -7 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/05/28 09:12:49-04:00 margitsw@t-online.de +42 -42 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +8 -8 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/islpci_dev.h # 2004/05/28 08:25:30-04:00 margitsw@t-online.de +1 -1 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +28 -34 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:33:42-04:00 margitsw@t-online.de +1 -1 # prism54: Fix typo # # drivers/net/wireless/prism54/islpci_hotplug.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +1 -1 # prism54: Fix channel stats, bump version to 1.2 (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +3 -3 # prism54: Fix channel stats, bump version to 1.2 (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +2 -2 # prism54: Fix channel stats, bump version to 1.2 (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 08:11:34-04:00 margitsw@t-online.de +3 -1 # prism54: Reduce module verbosity (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/06/05 08:09:41-04:00 margitsw@t-online.de +1 -0 # prism54: Align skb patch (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 08:09:41-04:00 margitsw@t-online.de +1 -0 # prism54: Align skb patch (resend) # # drivers/net/wireless/prism54/islpci_mgt.h # 2004/05/28 09:33:42-04:00 margitsw@t-online.de +1 -1 # prism54: Add likely/unlikely, KO wds completely (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 09:33:42-04:00 margitsw@t-online.de +9 -8 # prism54: Add likely/unlikely, KO wds completely (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +40 -21 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +5 -3 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +3 -1 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/isl_ioctl.h # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +0 -1 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +5 -31 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/05/28 09:08:01-04:00 margitsw@t-online.de +2 -6 # prism54: Fix bug 77, strengthened oid txn (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/05/28 09:08:01-04:00 margitsw@t-online.de +35 -26 # prism54: Fix bug 77, strengthened oid txn (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:08:01-04:00 margitsw@t-online.de +13 -76 # prism54: Fix bug 77, strengthened oid txn (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 07:57:11-04:00 margitsw@t-online.de +2 -2 # prism54: Fix bugs 39/73 (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/05/28 08:43:01-04:00 margitsw@t-online.de +2 -2 # prism54: Fix bugs 74/75 (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 08:43:01-04:00 margitsw@t-online.de +1 -0 # prism54: Fix bugs 74/75 (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 08:25:30-04:00 margitsw@t-online.de +16 -16 # prism54: Fix endian patch (resend) # # drivers/net/wireless/prism54/prismcompat.h # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +46 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/prismcompat.h # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +0 -0 # BitKeeper file /spare/repo/netdev-2.6/prism54/drivers/net/wireless/prism54/prismcompat.h # # drivers/net/wireless/prism54/oid_mgt.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_mgt.h # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +0 -9 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -15 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_hotplug.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_dev.h # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +0 -20 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +121 -27 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -1 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/isl_38xx.h # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +0 -10 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/isl_38xx.c # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +2 -132 # prism54: Kernel compatibility (resend) # # drivers/net/tulip/Kconfig # 2004/06/04 11:16:07-04:00 bunk@fs.tum.de +11 -4 # add NAPI help texts # # drivers/net/Kconfig # 2004/06/04 11:18:14-04:00 bunk@fs.tum.de +70 -0 # add NAPI help texts # # drivers/net/arm/smc91x.h # 2004/05/29 08:04:43-04:00 rmk@arm.linux.org.uk +829 -0 # Re: smc91x driver # # drivers/net/arm/smc91x.c # 2004/05/29 07:57:20-04:00 rmk@arm.linux.org.uk +2171 -0 # Re: smc91x driver # # drivers/net/arm/smc91x.h # 2004/05/29 08:04:43-04:00 rmk@arm.linux.org.uk +0 -0 # BitKeeper file /spare/repo/netdev-2.6/misc/drivers/net/arm/smc91x.h # # drivers/net/arm/smc91x.c # 2004/05/29 07:57:20-04:00 rmk@arm.linux.org.uk +0 -0 # BitKeeper file /spare/repo/netdev-2.6/misc/drivers/net/arm/smc91x.c # # drivers/net/arm/Makefile # 2003/07/06 11:12:19-04:00 rmk@arm.linux.org.uk +1 -0 # Re: smc91x driver # # drivers/net/arm/Kconfig # 2003/09/28 11:03:12-04:00 rmk@arm.linux.org.uk +17 -0 # Re: smc91x driver # # drivers/net/fealnx.c # 2004/04/23 01:29:23-04:00 akpm@osdl.org +5 -0 # fealnx-mac-address-and-other-issues.patch # # ChangeSet # 2004/06/10 16:34:14-07:00 kenneth.w.chen@intel.com # [PATCH] ia64: fix race in fsys_bubble_down to avoid fp-register corruption # # The fast system-call fall-back-path has a race: it reads PSR, modifies # some bits, then writes back the new PSR. Unfortunately, the contents # of PSR may change between reading and writing it. For example, an # interrupt could occur which could trigger a context-switch. The # context-switch might in turn flush the floating-point-high (FPH) # partition to memory, clear PSR.MFH, and set PSR.DFH. To prevent this # race, the patch below turns off PSR.I before reading PSR. # # This fixes a floating-point corruption problem that was observed on a # system with a libc which has the fast system-call support enabled. # # The performance impact is minimal (on the order of a handful of cycles). # # Signed-off-by: Kevin Tian # Signed-off-by: Ken Chen # Signed-off-by: Asit Mallick # Signed-off-by: David Mosberger # # arch/ia64/kernel/gate.S # 2004/06/09 05:36:21-07:00 kenneth.w.chen@intel.com +4 -2 # ia64: fix race in fsys_bubble_down # # arch/ia64/kernel/fsys.S # 2004/06/09 05:11:54-07:00 kenneth.w.chen@intel.com +2 -1 # ia64: fix race in fsys_bubble_down # # ChangeSet # 2004/06/10 13:25:26-07:00 Robert.Picco@hp.com # [PATCH] ia64: mark non-existent NUMA-nodes as offline # # I found a problem with HP NUMA configuration in 2.6.7-rc3-mm1. The # node_online_map is incorrect because of actions taken by # reassign_cpu_only_nodes in arch/ia64/mm/discontig.c. The mm1 patch # which changes the mempolicy for the init_task uses this invalid # node_online_map and eventually uses a non-existent node's zonelist # when calling __alloc_pages. # # The patch below takes care of this issue. It puts the non-existent # nodes offline. # # Signed-off-by: David Mosberger # # arch/ia64/mm/discontig.c # 2004/06/09 15:44:02-07:00 Robert.Picco@hp.com +3 -0 # ia64: mark non-existent NUMA-nodes as offline # # ChangeSet # 2004/06/10 12:09:46-07:00 greg@kroah.com # USB: fix up dumb int_user_arg variable name as pointed out by Al Viro. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/auerswald.c # 2004/06/10 05:08:46-07:00 greg@kroah.com +7 -7 # USB: fix up dumb int_user_arg variable name as pointed out by Al Viro. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/input/hiddev.c # 2004/06/10 05:08:46-07:00 greg@kroah.com +4 -5 # USB: fix up dumb int_user_arg variable name as pointed out by Al Viro. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/audio.c # 2004/06/10 05:08:46-07:00 greg@kroah.com +32 -32 # USB: fix up dumb int_user_arg variable name as pointed out by Al Viro. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/06/10 11:40:08-07:00 greg@kroah.com # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/whiteheat.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +3 -2 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/kobil_sct.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +5 -4 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/kl5kusb105.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +7 -8 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/io_ti.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +3 -3 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/io_edgeport.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +7 -8 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/ftdi_sio.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +6 -6 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/rtl8150.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +15 -15 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/legousbtower.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +4 -4 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/auerswald.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +8 -6 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/w9968cf.h # 2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/w9968cf.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +24 -23 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/vicam.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +14 -18 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/usbvideo.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +2 -2 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/stv680.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/se401.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/pwc-if.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +2 -2 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/ov511.h # 2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/ov511.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +1 -1 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/dabusb.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +5 -5 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/input/hiddev.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +26 -24 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/input/hid-core.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +3 -1 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/image/mdc800.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +3 -3 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/audio.c # 2004/06/10 04:39:09-07:00 greg@kroah.com +36 -30 # USB: sparse cleanups for the whole driver/usb/* tree. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/06/10 09:48:09-07:00 rtjohnso@eecs.berkeley.edu # [PATCH] PATCH: 2.6.7-rc3 drivers/usb/core/devio.c: user/kernel pointer bugs # # Since ctrl is copied in from userspace, ctrl.data cannot safely be # dereferenced. Let me know if you have any questions or if I've made # a mistake. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/devio.c # 2004/06/09 05:49:50-07:00 rtjohnso@eecs.berkeley.edu +2 -2 # PATCH: 2.6.7-rc3 drivers/usb/core/devio.c: user/kernel pointer bugs # # ChangeSet # 2004/06/09 11:14:30-07:00 greg@kroah.com # USB: crap, I misapplied a patch with the wrong level # # This gets rid of usb/host and puts the file in the proper drivers/usb/host # directory. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ohci-lh7a404.c # 2004/06/09 04:12:00-07:00 greg@kroah.com +0 -0 # USB: crap, I misapplied a patch with the wrong level # # This gets rid of usb/host and puts the file in the proper drivers/usb/host # directory. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/06/09 11:10:52-07:00 stern@rowland.harvard.edu # [PATCH] USB: Update root-hub code for the ohci-lh7a404 driver # # On Wed, 9 Jun 2004, David Brownell wrote: # # > Needs an update for ohci-lh7a404.c too ... # # I didn't even know this driver existed! Where did usb/host/* come from? # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # usb/host/ohci-lh7a404.c # 2004/06/09 06:09:47-07:00 stern@rowland.harvard.edu +1 -3 # USB: Update root-hub code for the ohci-lh7a404 driver # # ChangeSet # 2004/06/09 11:10:09-07:00 stern@rowland.harvard.edu # [PATCH] USB: Minor tidying up of hub driver # # After my last few changesets there were a few small items that needed to # be tidied up. # # Update kerneldoc to reflect the actual operation of # usb_disconnect() and usb_new_device(). The new locking # requirements are listed too, though they aren't all # implemented yet. # # Fulfill the new locking requirement in hcd_panic(). # # Remove unneeded local variables to conserve stack space in # usb_disconnect(), which calls itself recursively. # # In hub_port_connect_change(), store the parent's children[] # pointer as late as possible and don't lock the new device until # then (that's when it becomes globally accessible). This will # minimize the time that the not-fully-configured device structure # is visible to other parts of the kernel. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/09 05:20:00-07:00 stern@rowland.harvard.edu +25 -23 # USB: Minor tidying up of hub driver # # drivers/usb/core/hcd.c # 2004/06/09 05:03:06-07:00 stern@rowland.harvard.edu +2 -0 # USB: Minor tidying up of hub driver # # ChangeSet # 2004/06/09 11:09:31-07:00 stern@rowland.harvard.edu # [PATCH] USB: Fix bus-list root-hub race # # There are a few places where the code enumerates through all the USB # devices on all the buses, starting with each bus's root hub and working # down. However a bus does not always have a root hub, and the code does # not check that the root_hub pointer is non-NULL. This patch fixes the # problem, using the usb_bus_list_lock semaphore to synchronize access when # root hubs are added or removed. # # In addition it seemed like a good idea to minimize the time that a # non-fully-configured root hub is accessible through the bus's pointer. So # this patch delays setting the pointer and holds usb_bus_list_lock while # configuring a root hub. # # It turned out that a bunch of things needed to be changed for all this to # work: # # Check for NULL root_hub pointer in usb_device_read() and # usb_find_device(). # # Pass the root-hub device as a separate argument to # hcd_register_root(). # # Make usb_register_root_hub() acquire the usb_bus_list_lock and # set the bus->root_hub pointer. # # For consistency's sake, move the place where the children[] # pointer to a non-root-hub device gets stored as close as possible # to where usb_new_device() is called. # # Make usb_disconnect() acquire the usb_bus_list_lock when removing # a root hub. # # Change usb_hcd_pci_remove() and the non-PCI host drivers so that # they call usb_disconnect() with a pointer to the bus's root_hub # pointer, not a pointer to a temporary variable. # # Change all the host controller drivers not to store the root_hub # pointer in the bus structure but instead to pass it as a new # argument to hcd_register_root(). # # I made some attempt to update the hc_sl811 driver along with the rest, but # it's pretty clear that driver won't work in the current framework. Among # other things, it never reads the root hub's device descriptor. To what # extent is the driver really supported? # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hcd.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3 # USB: Fix bus-list root-hub race # # drivers/usb/host/ohci-sa1111.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +1 -3 # USB: Fix bus-list root-hub race # # drivers/usb/host/ohci-omap.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +1 -3 # USB: Fix bus-list root-hub race # # drivers/usb/host/ohci-hcd.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3 # USB: Fix bus-list root-hub race # # drivers/usb/host/hc_sl811_rh.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +8 -2 # USB: Fix bus-list root-hub race # # drivers/usb/host/ehci-hcd.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3 # USB: Fix bus-list root-hub race # # drivers/usb/gadget/dummy_hcd.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -3 # USB: Fix bus-list root-hub race # # drivers/usb/core/usb.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -0 # USB: Fix bus-list root-hub race # # drivers/usb/core/hub.c # 2004/06/09 04:45:43-07:00 stern@rowland.harvard.edu +16 -7 # USB: Fix bus-list root-hub race # # drivers/usb/core/hcd.h # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +3 -3 # USB: Fix bus-list root-hub race # # drivers/usb/core/hcd.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +10 -3 # USB: Fix bus-list root-hub race # # drivers/usb/core/hcd-pci.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +1 -3 # USB: Fix bus-list root-hub race # # drivers/usb/core/devices.c # 2004/06/09 04:40:49-07:00 stern@rowland.harvard.edu +2 -0 # USB: Fix bus-list root-hub race # # ChangeSet # 2004/06/09 11:08:58-07:00 oliver@neukum.org # [PATCH] USB: add printer reset ioctl # # - add soft reset ioctl # # Signed-off-by: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/usblp.c # 2004/06/09 10:05:10-07:00 oliver@neukum.org +10 -0 # USB: add printer reset ioctl # # ChangeSet # 2004/06/08 16:10:24-07:00 stern@rowland.harvard.edu # [PATCH] USB: Initialize endpoint autoconfig in g_file_storage # # This one-line patch corrects a simple problem in the g_file_storage # driver. It neglected to initialize the endpoint-autoconfiguration library # before using it. Please apply. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/file_storage.c # 2004/06/08 04:03:07-07:00 stern@rowland.harvard.edu +1 -0 # USB: Initialize endpoint autoconfig in g_file_storage # # ChangeSet # 2004/06/08 16:09:55-07:00 david-b@pacbell.net # [PATCH] lh7a404 USB host against 2.6.7-rc2 # # Support for the Sharp LH7A404 OHCI, another non-PCI implementation. # This uses a platform_device and a workaround for a register read # problem. # # Signed-off-by: Marc Singer # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # usb/host/ohci-lh7a404.c # 2004/06/07 16:24:04-07:00 david-b@pacbell.net +387 -0 # lh7a404 USB host against 2.6.7-rc2 # # drivers/usb/Kconfig # 2004/06/07 09:24:04-07:00 david-b@pacbell.net +1 -1 # lh7a404 USB host against 2.6.7-rc2 # # usb/host/ohci-lh7a404.c # 2004/06/07 16:24:04-07:00 david-b@pacbell.net +0 -0 # BitKeeper file /home/greg/linux/BK/usb-2.6/usb/host/ohci-lh7a404.c # # drivers/usb/host/ohci.h # 2004/06/07 09:24:04-07:00 david-b@pacbell.net +19 -0 # lh7a404 USB host against 2.6.7-rc2 # # drivers/usb/host/ohci-q.c # 2004/06/07 09:24:04-07:00 david-b@pacbell.net +3 -3 # lh7a404 USB host against 2.6.7-rc2 # # drivers/usb/host/ohci-hub.c # 2004/06/07 09:33:47-07:00 david-b@pacbell.net +21 -21 # lh7a404 USB host against 2.6.7-rc2 # # drivers/usb/host/ohci-hcd.c # 2004/06/07 09:24:04-07:00 david-b@pacbell.net +26 -16 # lh7a404 USB host against 2.6.7-rc2 # # drivers/usb/host/ohci-dbg.c # 2004/06/07 09:24:04-07:00 david-b@pacbell.net +15 -15 # lh7a404 USB host against 2.6.7-rc2 # # ChangeSet # 2004/06/08 16:09:24-07:00 david-b@pacbell.net # [PATCH] USB: rndis (3/4) Big Endian support for gadget RNDIS # # Add byteswapping. Original version partially worked on PPC with Net2280, # this version applies to the latest RNDIS code but hasn't been retested on # big-endian. Ping should be working in at least one one direction. # # Also added a handful of other things from my BK: track suspend/resume # (to eventually implement wake-on-lan), give a better rndis error # message, and add missing declarations for PM-related OIDs (usage is # #ifdeffed out by previous patch). # # From: Jon Neal # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/rndis.c # 2004/06/07 11:30:16-07:00 david-b@pacbell.net +199 -163 # USB: rndis (3/4) Big Endian support for gadget RNDIS # # drivers/usb/gadget/ndis.h # 2004/06/07 11:30:16-07:00 david-b@pacbell.net +30 -0 # USB: rndis (3/4) Big Endian support for gadget RNDIS # # drivers/usb/gadget/ether.c # 2004/06/07 11:32:18-07:00 david-b@pacbell.net +28 -2 # USB: rndis (3/4) Big Endian support for gadget RNDIS # # ChangeSet # 2004/06/08 16:08:52-07:00 david-b@pacbell.net # [PATCH] USB: usb suspend/resume work better on net2280 # # This makes net2280 behave more correctly with respect to # usb suspend and resume processing. # # So for example gadget zero autoresume testing works. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/net2280.c # 2004/06/07 07:31:53-07:00 david-b@pacbell.net +17 -8 # USB: usb suspend/resume work better on net2280 # # ChangeSet # 2004/06/08 16:08:19-07:00 david-b@pacbell.net # [PATCH] USB: usb root hubs can set power budgets # # This adds hub_set_power_budget(), mostly so that HCDs for low # powered ports (cell phone, PDA, etc) can more easily report their # true power budgets. It's not always 500mA per root hub port; this # makes dummy_hcd report the minimum, 8mA. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/dummy_hcd.c # 2004/06/07 07:31:53-07:00 david-b@pacbell.net +3 -0 # USB: usb root hubs can set power budgets # # drivers/usb/core/hub.h # 2004/06/07 07:31:53-07:00 david-b@pacbell.net +11 -0 # USB: usb root hubs can set power budgets # # ChangeSet # 2004/06/08 14:12:40-07:00 greg@kroah.com # Merge kroah.com:/home/greg/linux/BK/bleed-2.6 # into kroah.com:/home/greg/linux/BK/usb-2.6 # # include/linux/usb.h # 2004/06/08 14:12:36-07:00 greg@kroah.com +0 -1 # Auto merged # # drivers/usb/serial/cyberjack.c # 2004/06/08 14:12:36-07:00 greg@kroah.com +0 -6 # Auto merged # # drivers/usb/media/pwc-if.c # 2004/06/08 14:12:36-07:00 greg@kroah.com +0 -1 # Auto merged # # drivers/usb/media/Kconfig # 2004/06/08 14:12:35-07:00 greg@kroah.com +0 -1 # Auto merged # # drivers/usb/core/devio.c # 2004/06/08 14:12:35-07:00 greg@kroah.com +0 -1 # Auto merged # # ChangeSet # 2004/06/07 21:38:30-07:00 kaos@sgi.com # [PATCH] ia64: Rename SN "modules" variable to "sn_modules". # # SN code has a "modules" variable that conflicts with a variable of the # same name in kernel/module.c. This conflict breaks lcrash for ia64. # Rename "modules" to "sn_modules". # # Signed-off-by: Keith Owens # Signed-off-by: David Mosberger # # include/asm-ia64/sn/module.h # 2004/06/07 08:45:42-07:00 kaos@sgi.com +1 -1 # ia64: Rename modules to sn_modules # # arch/ia64/sn/io/sn2/module.c # 2004/06/07 08:45:32-07:00 kaos@sgi.com +7 -7 # ia64: Rename modules to sn_modules # # arch/ia64/sn/io/sn2/klgraph.c # 2004/06/07 08:49:25-07:00 kaos@sgi.com +2 -2 # ia64: Rename modules to sn_modules # # arch/ia64/sn/io/machvec/pci_bus_cvlink.c # 2004/06/07 08:45:20-07:00 kaos@sgi.com +2 -2 # ia64: Rename modules to sn_modules # # ChangeSet # 2004/06/07 17:01:22-07:00 david-b@pacbell.net # [PATCH] USB: rndis (4/4) start documenting spec variances # # This partially reverts one of the changes in an earlier patch, # starting to document where Microsoft's spec is lying. Needed # to interop with Windows ME. # # # The Windows ME implementation of RNDIS relies on a message that # Microsoft's specification says isn't used. Restore this (removed # in earlier cleanup), and start collecting comments specifically # on where MSFT violates its own specifications. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/rndis.c # 2004/06/07 07:04:50-07:00 david-b@pacbell.net +17 -0 # USB: rndis (4/4) start documenting spec variances # # ChangeSet # 2004/06/07 16:58:23-07:00 david-b@pacbell.net # [PATCH] USB: rndis (2/4) fix memory leaks # # Tao Huang wrote: # > I'm writing udc driver for S3C2410. I found RNDIS almost not call my # > driver's free_request and free_buffer. So after run my driver about 3 # > hours the system will out of memory. # > # > This patch will fix the memory leak. # > # > There will still have memory leak when driver unload, but I don't known # > where is the proper place to fix it. # > 1) rndis.c should free resp_queue when it unload # > 2) ether.c should free tx_reqs and rx_reqs when it unload (as # > eth_reset_config) # # Thanks ... this is a nice patch to have. # # # From: Tao Huang # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/ether.c # 2004/06/06 06:34:51-07:00 david-b@pacbell.net +13 -5 # USB: rndis (2/4) fix memory leaks # # ChangeSet # 2004/06/07 16:57:06-07:00 david-b@pacbell.net # [PATCH] USB: rndis (1/4) update OID support # # NDIS devices have a generic attribute get/set API where the attributes # are identified by 32 bit "OIDs". This fixes some problems with the OIDs # supported by the original RNDIS patch: # # - It included OIDs not found in the RNDIS spec. These have been # removed. As a rule, these weren't exported in the "OIDs I support" # list, and only a couple wouldn't fail those accesses, so this mostly # changes what debug printk appears. # # - OIDs used for optional 802.3 statistics were partially supported. # They're all in the OID list now, but the support is #ifdeffed out. # (Those statistics were mostly just made up, anyway!) # # - "Required" OIDs for suspend, resume, and wakeup support weren't # listed. Their messages are now defined, but support is #ifdeffed # out. Seems the docs aren't entirely accurate, and Windows can # behave reasonably without them. (This area needs help from someone # who knows MS-Windows power management.) # # There are also a few minor cleanups, more reasonable default volume level # for debug messages (never at KERN_INFO, keepalives only if VERBOSE), and # dumping of all bytes of some undocumented messages Windows XP has been # seen emitting shortly before the host suspended itself. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/rndis.h # 2004/06/06 06:06:42-07:00 david-b@pacbell.net +37 -4 # USB: rndis (1/4) update OID support # # drivers/usb/gadget/rndis.c # 2004/06/06 06:06:42-07:00 david-b@pacbell.net +162 -166 # USB: rndis (1/4) update OID support # # ChangeSet # 2004/06/07 16:55:44-07:00 stern@rowland.harvard.edu # [PATCH] USB: unusual_devs.h update # # Given the problems that Dan Scholnik has reported, we should combine the # unusual_devs.h entries for the Casio QV cameras into one. The new # NEED_OVERRIDE flag will prevent complaints about unnecessary overrides, # and Dan says the same subclass and protocol values should work for all the # cameras. If they don't we'll hear about it soon enough! # # # On Tue, 1 Jun 2004, Dan Scholnik wrote: # > On Tue, 2004-06-01 at 14:14, Alan Stern wrote: # > > On Tue, 1 Jun 2004, Dan Scholnik wrote: # > > # > > > Up until the 2.6 kernels, there was one entry for all the QV cameras # > > > with both US_SC_8070 and US_PR_CB that I think seemed to work fine for # > > > everyone. As far as I know the only problem was all the folks emailing # > > > the log entry stating that the Casio entry wasn't needed. So, you could # > > > revert back to that, or revert back to the 2.6.3ish version (pre-as190) # > > > that had the overrides just for product IDs 1001-9009. I'm not really # > > > an expert on Casio's cameras, I'm afraid, just the one model I own which # > > > is 4-5 years old now. # > > > # > > > I'll be happy to prepare a patch any way you choose to go. # > > # > > How does this work for you? # > > # > > Alan Stern # > # > Works fine for me; that's I think exactly how it was from the beginning # > until 2.6 and the later 2.4 kernels when all the changes were made. # > Just cross your fingers that it doesn't somehow break newer Casios, as # > it would seem every camera they ever made falls under that entry. # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2004/06/01 05:46:58-07:00 stern@rowland.harvard.edu +3 -9 # USB: unusual_devs.h update # # ChangeSet # 2004/06/07 16:55:17-07:00 stern@rowland.harvard.edu # [PATCH] USB: Fix resource leakage in the hub driver # # The hub driver is very careless about returning resources when an error # occurs while installing a new device. This patch attempts to put some # order back into the situation. Details: # # Since usb_new_device() allocates neither the device structure # nor the device address, it shouldn't release either one. # # Because usb_new_device() no longer releases the device structure, # usb_register_root_hub() doesn't need to take an extra reference # to it. # # Since the device address selection and TT setup code is used # only for new devices, not ones being reset, move that code from # hub_port_init() to hub_port_connect_change(). By the same token, # hub_port_init() doesn't have to release the device address or # the device structure. # # Just to make things look better, move the failure code in # hub_port_init() to the end of the routine. And when disabling # endpoint 0, disable both the IN and OUT parts of the endpoint. # # In hub_port_connect_change(), make all the failure paths # execute the same code so that resources are always released. # These resources comprise: the pointer from the parent to the # new child device, the HCD state for ep0, the device's address, # and the device structure itself -- in short, everything that's # set up before calling usb_new_device(). # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/07 10:08:06-07:00 stern@rowland.harvard.edu +45 -50 # USB: Fix resource leakage in the hub driver # # drivers/usb/core/hcd.c # 2004/06/07 09:55:49-07:00 stern@rowland.harvard.edu +1 -3 # USB: Fix resource leakage in the hub driver # # ChangeSet # 2004/06/07 16:54:49-07:00 stern@rowland.harvard.edu # [PATCH] USB: Check port reset return code # # This patch adds checking for the SET-FEATURE request that actually does a # port reset. Without the check, the hub driver just assumes that the port # reset command actually was transferred okay. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/07 08:20:11-07:00 stern@rowland.harvard.edu +6 -2 # USB: Check port reset return code # # ChangeSet # 2004/06/07 16:34:04-07:00 baldrick@free.fr # [PATCH] USB devio.c: deadlock fix # # proc_resetdevice is called with dev->serialize held. # usb_reset_device takes dev->serialize and then calls # __usb_reset_device. To avoid deadlock, proc_resetdevice # should call __usb_reset_device directly. # # Signed-off-by: Duncan Sands # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2004/06/07 01:39:20-07:00 baldrick@free.fr +1 -0 # USB devio.c: deadlock fix # # drivers/usb/core/devio.c # 2004/06/07 01:39:20-07:00 baldrick@free.fr +1 -1 # USB devio.c: deadlock fix # # ChangeSet # 2004/06/07 14:39:16-07:00 arun.sharma@intel.com # [PATCH] ia64: fix ia32 virtual memory leaks due to partial-page mappings # # Certain IA-32 applications which do mmap/munmaps which are not # PAGE_SIZE aligned could see temporary (recovered at process exit time) # memory leaks, because the kernel didn't have enough data to decide if # the complete page could be unmapped. This patch adds a new data # structure called the "partial page list" which helps the kernel keep # track of precisely which 4k pages are in use by the IA-32 application. # # Armed with this data, the kernel can make better decisions at munmap # and mprotect time. No significant performance degradation was observed # in the workloads we tested and in some cases, the performance actually # improved! This is possibly due to the reduced length of the vma list. # # Signed-off-by: Arun Sharma # Signed-off-by: Gordon Jin # Signed-off-by: David Mosberger # # include/asm-ia64/processor.h # 2004/06/04 18:14:13-07:00 arun.sharma@intel.com +4 -1 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # include/asm-ia64/ia32.h # 2004/06/04 18:15:32-07:00 arun.sharma@intel.com +2 -0 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # arch/ia64/kernel/process.c # 2004/06/04 04:59:05-07:00 arun.sharma@intel.com +12 -0 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # arch/ia64/ia32/sys_ia32.c # 2004/06/04 06:31:39-07:00 arun.sharma@intel.com +524 -5 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # arch/ia64/ia32/ia32priv.h # 2004/06/04 03:42:27-07:00 arun.sharma@intel.com +25 -0 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # arch/ia64/ia32/ia32_support.c # 2004/06/04 02:57:01-07:00 arun.sharma@intel.com +8 -0 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # arch/ia64/ia32/ia32_entry.S # 2004/06/04 02:57:01-07:00 arun.sharma@intel.com +1 -1 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # arch/ia64/ia32/binfmt_elf32.c # 2004/06/04 02:57:01-07:00 arun.sharma@intel.com +4 -0 # ia64: fix virtual memory leaks in ia32 emulator due to partial-page mappings # # ChangeSet # 2004/06/07 13:00:07-07:00 stern@rowland.harvard.edu # [PATCH] USB: Fix logic in usb_get_descriptor() # # This patch fixes a simple logic error in usb_get_descriptor(). It also # takes the opportunity to make the subroutine a little easier to read. # Please apply. # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/message.c # 2004/06/06 09:43:22-07:00 stern@rowland.harvard.edu +7 -7 # USB: Fix logic in usb_get_descriptor() # # ChangeSet # 2004/06/07 12:59:41-07:00 kaie@kuix.de # [PATCH] USB: enable pwc usb camera driver # # The attached patch enables the pwc driver included with kernel 2.6.7-rc2 # # It also removes the warnings during compilation. # However, note that I blindly duplicated the release approach used by # other usb camera drivers, replacing the current no-op. # # The driver works for me with a Logitech QuickCam Notebook Pro and # GnomeMeeting. # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/pwc-if.c # 2004/06/07 02:42:50-07:00 kaie@kuix.de +1 -8 # USB: enable pwc usb camera driver # # drivers/usb/media/Kconfig # 2004/06/07 02:27:03-07:00 kaie@kuix.de +1 -1 # USB: enable pwc usb camera driver # # ChangeSet # 2004/06/07 12:59:12-07:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: GetMaxLUN tightening # # This patch started life from Alan Stern as as274, and has been heavily # modified. It narrows the case where a clear_halt() is issued after a # failed GetMaxLUN command to only a STALL case. # # Since the only legimate responses to a GetMaxLUN are STALL or data, # anything else is now considered a fatal error and we give up on the device. # # # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.c # 2004/06/06 15:22:29-07:00 mdharm-usb@one-eyed-alien.net +8 -2 # USB Storage: GetMaxLUN tightening # # drivers/usb/storage/transport.c # 2004/06/06 15:22:29-07:00 mdharm-usb@one-eyed-alien.net +13 -10 # USB Storage: GetMaxLUN tightening # # ChangeSet # 2004/06/07 12:58:42-07:00 Siegfried.Hildebrand@FernUni-Hagen.de # [PATCH] Re: Problems with cyberjack usb-serial-module since kernel 2.6.2 # # > Send me a patch to back those changes out to fix your device and I'll # > apply it. If the author is around to realize this, that should wake # > them up :) # # Ok, here you are! :) # Attached is a patch for linux-2.6.7-rc2. (though the patch hasn't changed # since -rc1) # # Again a short description: # (the patch removes most of the changes done in linux-2.6.2) # 1. Removed the local buffer of cyberjack_write, because something goes wrong # upon a write-request bigger than the buffer. Without this, a write-request # stalls with error -3. # 2. Removed some usb_clear_halt() lines. Without this, the device doesn't even # open and returns -7. # # It works for my cyberjack pinpad USB card reader on # - nforce2 chipset # - VIA KM266 chipset # - AMD Irongate chipset # # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/cyberjack.c # 2004/06/06 09:25:11-07:00 Siegfried.Hildebrand@FernUni-Hagen.de +6 -15 # Re: Problems with cyberjack usb-serial-module since kernel 2.6.2 # # ChangeSet # 2004/06/07 11:44:48-07:00 alex.williamson@hp.com # [PATCH] ia64: delete McKinley A-stepping code # # The patch below removes the config option and one bit of code for # McKinley A0/A1 CPU workarounds. These CPUs were never used in # production, and IIRC this workaround really only affected X11. # # Signed-off-by: David Mosberger # # include/asm-ia64/pgtable.h # 2004/06/07 03:07:59-07:00 alex.williamson@hp.com +1 -5 # ia64: delete McKinley A-stepping code # # arch/ia64/Kconfig # 2004/06/07 03:03:19-07:00 alex.williamson@hp.com +0 -14 # ia64: delete McKinley A-stepping code # # ChangeSet # 2004/06/07 11:27:28-07:00 greg@kroah.com # USB: make usb devices remove their sysfs files when disconnected. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.h # 2004/06/07 04:26:43-07:00 greg@kroah.com +2 -0 # USB: make usb devices remove their sysfs files when disconnected. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/sysfs.c # 2004/06/07 04:26:43-07:00 greg@kroah.com +59 -30 # USB: make usb devices remove their sysfs files when disconnected. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/message.c # 2004/06/07 04:26:43-07:00 greg@kroah.com +1 -0 # USB: make usb devices remove their sysfs files when disconnected. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/07 04:26:43-07:00 greg@kroah.com +1 -0 # USB: make usb devices remove their sysfs files when disconnected. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/06/07 10:30:35-07:00 greg@kroah.com # Merge kroah.com:/home/greg/linux/BK/bleed-2.6 # into kroah.com:/home/greg/linux/BK/usb-2.6 # # drivers/usb/gadget/ether.c # 2004/06/07 10:30:30-07:00 greg@kroah.com +0 -0 # Auto merged # # ChangeSet # 2004/06/04 17:17:42-05:00 stern@rowland.harvard.edu # [PATCH] Make the scsi error handler bus settle delay a per template option # # On 1 Jun 2004, James Bottomley wrote: # > On Tue, 2004-06-01 at 15:29, Alan Stern wrote: # > > In addition, the settle-time delays would have to be removed from the # > > error handler -- which means adding it to all the low-level drivers. Is # > > that doable? # > # > Well, for 2.6, I think that a simple flag indicating that the driver # > will implement it's own timeout should suffice rather than altering # > every LLD... # # Signed-off-by: Alan Stern # Signed-off-by: James Bottomley # # include/scsi/scsi_host.h # 2004/06/04 11:51:31-05:00 stern@rowland.harvard.edu +5 -0 # Make the scsi error handler bus settle delay a per template option # # drivers/usb/storage/scsiglue.c # 2004/06/04 11:52:56-05:00 stern@rowland.harvard.edu +3 -0 # Make the scsi error handler bus settle delay a per template option # # drivers/scsi/scsi_error.c # 2004/06/04 11:54:06-05:00 stern@rowland.harvard.edu +4 -2 # Make the scsi error handler bus settle delay a per template option # # ChangeSet # 2004/06/04 15:15:08-07:00 stern@rowland.harvard.edu # [PATCH] USB: Genuine changes to hub_port_debounce() # # This patch includes the algorithmic changes I would like to see in # hub_port_debounce(). They are: # # Increase the total timeout period from 400 ms to 1500 ms. # # Check the port's connect-changed status during the polling # loop. # # Return as soon as the connection has been stable for the # required time, even if it has been stably _dis_-connected. # (The current code waits for the full timeout period if there # isn't a connection.) # # In previous emails I have responded to all the concerns raised by others # about these changes, and I can't imagine how they could cause any trouble. # # Increasing the total timeout won't affect people with properly # functioning hardware. Their connections will quickly stabilize # and the routine will return just as before. People with flaky # hardware that takes a long time to settle down will now be able # to use their devices. # # Checking the connect-changed status during the polling loop will # make the test more conservative. The code will be able to # detect transient disconnections that it would have missed # before, and it won't return until the connection really _is_ # stable. Furthermore, this makes the test compliant with the # USB specification, which requires the stability timer to be # restarted whenever a connection change occurs. # # Returning early for disconnections is a simple optimization. # It's more important now that the total timeout length is 1.5 # seconds rather than 0.4 seconds. # # I urge you to apply this patch and for people to try it out. If there do # turn out to be problems... the patch is very small, well-contained, and # easy to revert. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/04 07:28:00-07:00 stern@rowland.harvard.edu +4 -4 # USB: Genuine changes to hub_port_debounce() # # ChangeSet # 2004/06/04 15:14:42-07:00 stern@rowland.harvard.edu # [PATCH] USB: Superficial improvements to hub_port_debounce() # # Since my previous suggestions for changes to hub_port_debounce() # encountered so much resistance, this patch makes some fairly superficial # improvements to the code while leaving the logic of the algorithm almost # completely intact. The only behavioral change is that it actually # requests the port status at the start, rather than assuming the status is # not CONNECTED. Changes include: # # Vastly improved comments that are now unambiguous and accurately # descriptive of the code. # # Local variables changed to more sensible names. The stability # period is now reported in milliseconds rather than a meaningless # poll count. # # The sleep interval is moved from the start of the loop to the # end, so that the first time through we read the port status # immediately. # # If the connection has not stabilized after the total timeout # expires, -ETIMEDOUT is returned rather than whatever the # current connect status happens to be. # # If the connection does stabilize then the port status is returned # so that hub_port_connect_change() will have an up-to-date value # for the status rather than relying on the pre-debounce value. # # The changes I wanted to make but other people were worried about are # included as comments. A later (small) patch will uncomment them for # testing. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/04 07:15:37-07:00 stern@rowland.harvard.edu +34 -30 # USB: Superficial improvements to hub_port_debounce() # # ChangeSet # 2004/06/04 15:14:11-07:00 stern@rowland.harvard.edu # [PATCH] USB: Debounce all connect change events # # This patch makes the hub driver debounce all connection changes. Right # now the driver only does so if the status happens to be CONNECTED at one # particular instant. However, the whole point of debouncing is that the # connection is subject to transient interruptions until it has stabilized; # hence deciding whether to debounce based on a single initial test defeats # the entire purpose. # # There are some additional smaller changes that go along with the major # one: # # Comments added to hub_port_connect_change() detailing the # conditions under which it will be called. # # Don't clear the port's connect-changed feature if it wasn't # set. # # Skip debouncing if there wasn't a physical connection change # but only a logical port-enable change (or a firmware-download- # induced device morph -- not yet implemented). # # Clear all the hub status change indicators in hub_events() # before handling a connect change. This will reduce syslog # clutter from status change bits that remain set while khubd # is busy taking care of a new device. # # The patch includes no changes to the debounce routine itself. Please # apply. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/06/04 07:10:33-07:00 stern@rowland.harvard.edu +41 -22 # USB: Debounce all connect change events # # ChangeSet # 2004/06/04 15:13:47-07:00 stern@rowland.harvard.edu # [PATCH] USB: Code cleanup for the UHCI driver # # This patch makes some simple cleanups in the UHCI driver: # # It introduces msecs_to_jiffies() conversions and uses msleep(). # # It wakes up threads waiting for an endpoint to be disabled # in the oddball case where interrupts aren't working. (This # should have been in a previous patch but I missed it.) # # It disables PCI interrupt generation whenever the controller # is reset and enables it when the controller is started. This # may possibly solve some people's problems with suspend/resume. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hcd.c # 2004/06/04 08:14:49-07:00 stern@rowland.harvard.edu +28 -17 # USB: Code cleanup for the UHCI driver # # ChangeSet # 2004/06/04 15:13:16-07:00 jnardelli@infosciences.com # [PATCH] USB: fix Memory leak in visor.c and ftdi_sio.c # # Signed-off-by: Joe Nardelli # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/visor.c # 2004/06/04 07:13:10-07:00 jnardelli@infosciences.com +1 -0 # USB: fix Memory leak in visor.c and ftdi_sio.c # # drivers/usb/serial/ftdi_sio.c # 2004/06/04 06:53:27-07:00 jnardelli@infosciences.com +1 -0 # USB: fix Memory leak in visor.c and ftdi_sio.c # # ChangeSet # 2004/06/04 15:12:44-07:00 spitalnik@penguin.cz # [PATCH] USB: pegasus driver and ATEN device support # # I have created a patch to add support for ATEN device in pegasus usb driver. # I've sent the patch to the maintainer stated in pegasus.h but after several # weeks I didn't recieve a response, so I'm sending it to you now. The patch # should apply cleanly on 2.6.6, but it doesn't apply cleanly on todays -bk as # there was some patch adding some other device. One thing I'm not 100% sure # are the flags specified to PEGASUS_DEV, what means HAS_HOME_PNA? # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/pegasus.h # 2004/04/15 14:37:12-07:00 spitalnik@penguin.cz +3 -0 # USB: pegasus driver and ATEN device support # # ChangeSet # 2004/06/04 11:55:11-05:00 jejb@mulgrave.(none) # sg update to 20040516 # # From: Douglas Gilbert # # Here are some further refinements to this patch with help # from Pat Mansfield: # - replace vmalloc() with kmalloc(,GFP_KERNEL) # - bump max sg devices from 8192 to 32768 # # Tested to 16k devices (and 8k devices on a box with 512MB # ram), Patch is against lk 2.6.6 (or 2.6.6-bk1). # # Signed-off-by: James Bottomley # # drivers/scsi/sg.c # 2004/06/04 11:54:42-05:00 jejb@mulgrave.(none) +22 -15 # sg update to 20040516 # # ChangeSet # 2004/06/04 09:13:16-05:00 hch@lst.de # [PATCH] kill dead compat code in advansys # # I actually wanted to fix up the check_region usage there but got lost # in the mess. Let's start by kicking out the 2.2 compat and using scsi # layer constants instead of their own redefinitions first. # # Signed-off-by: James Bottomley # # drivers/scsi/advansys.c # 2004/06/04 06:19:50-05:00 hch@lst.de +119 -508 # kill dead compat code in advansys # # ChangeSet # 2004/06/04 09:09:27-05:00 hch@lst.de # [PATCH] update 53c700 to avoid obsolete headers # # Signed-off-by: James Bottomley # # drivers/scsi/sim710.c # 2004/06/04 05:53:02-05:00 hch@lst.de +2 -3 # update 53c700 to avoid obsolete headers # # drivers/scsi/lasi700.c # 2004/06/04 05:53:02-05:00 hch@lst.de +1 -2 # update 53c700 to avoid obsolete headers # # drivers/scsi/NCR_D700.c # 2004/06/04 06:45:28-05:00 hch@lst.de +1 -3 # update 53c700 to avoid obsolete headers # # drivers/scsi/53c700.h # 2004/06/04 06:43:36-05:00 hch@lst.de +13 -10 # update 53c700 to avoid obsolete headers # # drivers/scsi/53c700.c # 2004/06/04 06:43:46-05:00 hch@lst.de +65 -64 # update 53c700 to avoid obsolete headers # # ChangeSet # 2004/06/04 08:59:37-05:00 hch@lst.de # [PATCH] missing forward declarations in scsi_eh.h # # Signed-off-by: James Bottomley # # include/scsi/scsi_eh.h # 2004/06/04 06:45:01-05:00 hch@lst.de +4 -0 # missing forward declarations in scsi_eh.h # # ChangeSet # 2004/06/03 21:54:17-05:00 akpm@osdl.org # [PATCH] 3ware 9000 schedule_timeout fix # # From: "Adam Radford" # # This small patch fixes the broken schedule_timeout() usage in the 3w-9xxx # driver, and replaces the calls with msleep(). # # Signed-off-by: Andrew Morton # Signed-off-by: James Bottomley # # drivers/scsi/3w-9xxx.c # 2004/06/03 19:43:06-05:00 akpm@osdl.org +4 -3 # 3ware 9000 schedule_timeout fix # # ChangeSet # 2004/06/03 21:51:02-05:00 akpm@osdl.org # [PATCH] 3ware 9000 driver update # # From: "Adam Radford" # # This patch updates the 3w-9xxx driver in 2.6.7-rc2-mm1 to v2.26.02.000 to # cleanup several things pointed out by Chris Hellwig / Jeff Garzik. # # Changes in this release: # - Use descriptive defines for phase numbers. # - Remove un-needed casts for TW_Command_Full # - Rework eh_reset(), eh_abort() spinlocks. # - Remove all mdelays, replace w/ schedule_timeout(). # - Remove MODULE_PARAM cmds_per_lun, add sysfs device attribute 'queue_depth'. # - Remove twa_slave_configure(). # - Remove twa_info(). # - Remove all bitfields from structures, add bitmask macros. # - Remove twa_setup_irq() wrapper, call directly. # - Remove un-needed prototypes. # - Propogate return value of pci_enable_device(), pci_set_dma_mask(), ioremap(). # - Use pci_request/free_regions(). # - Add missing call to pci_disable_device() on probe failure. # - Unregister character ioctl interface in twa_remove(). # - Make some excessively lengthy lines < 80 columns. # - Use pci_module_init() instead of pci_register_driver(). # - Remove bogus TW_IN_INTR check, fix twa_interrupt() spinlock. # - Rev driver branch to .02 to denote kernel version. # # Signed-off-by: Andrew Morton # Signed-off-by: James Bottomley # # drivers/scsi/3w-9xxx.h # 2004/06/03 21:44:23-05:00 akpm@osdl.org +31 -53 # 3ware 9000 driver update # # drivers/scsi/3w-9xxx.c # 2004/06/03 21:44:23-05:00 akpm@osdl.org +167 -159 # 3ware 9000 driver update # # ChangeSet # 2004/06/03 20:12:20-05:00 arjanv@redhat.com # [PATCH] SCSI: replace deprecated hosts.h file # # Signed-off-by: James Bottomley # # drivers/scsi/zalon.c # 2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/wd7000.c # 2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/wd33c93.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ultrastor.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/u14-34f.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/tmscsim.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/t128.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sym53c416.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sun3x_esp.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sun3_scsi_vme.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sun3_scsi.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/st.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sr_vendor.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sr_ioctl.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sr.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sim710.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sgiwd93.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sg.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/seagate.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/sd.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsicam.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsi_pc98.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsi_module.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsi_ioctl.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsi_error.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsi_devinfo.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/scsi_debug.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qlogicpti.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qlogicisp.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qlogicfc.c # 2004/05/12 10:46:23-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qlogicfas408.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qlogicfas.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qla2xxx/qla_os.h # 2004/05/12 10:46:27-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/qla1280.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/psi240i.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ppa.h # 2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pluto.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pcmcia/qlogic_stub.c # 2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pcmcia/fdomain_stub.c # 2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pcmcia/aha152x_stub.c # 2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pci2220i.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pci2000.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pc980155.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/pas16.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/osst.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/oktagon_esp.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/nsp32.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ncr53c8xx.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/mvme16x.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/mvme147.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/megaraid.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/mca_53c9x.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/mac_scsi.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/mac_esp.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/lasi700.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/jazz_esp.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ips.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ini9100u.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/in2000.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/imm.h # 2004/05/12 10:46:24-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ide-scsi.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/ibmmca.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/i60uscsi.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/gvp11.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/g_NCR5380.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/fdomain.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/fd_mcs.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/fcal.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/fastlane.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/esp.c # 2004/05/12 10:46:21-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/eata_pio.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/eata.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/dtc.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/dmx3191d.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/dec_esp.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/dc395x.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/cyberstormII.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/cyberstorm.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/cpqfcTSworker.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/cpqfcTSinit.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +2 -2 # SCSI: replace deprecated hosts.h file # # drivers/scsi/cpqfcTScontrol.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/constants.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/bvme6000.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/blz2060.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/blz1230.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/atp870u.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/atari_scsi.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/amiga7xx.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/aic7xxx_old.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/aic7xxx/aiclib.c # 2004/05/12 10:46:25-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/aic7xxx/aic7xxx_osm.h # 2004/05/12 10:46:27-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/aic7xxx/aic79xx_osm.h # 2004/05/12 10:46:27-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/aha1740.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/aha1542.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/advansys.c # 2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/a3000.c # 2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/a2091.c # 2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/NCR_Q720.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/NCR_D700.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/NCR53c406a.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/NCR53C9x.c # 2004/05/12 10:46:22-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/BusLogic.c # 2004/05/12 10:46:20-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/53c7xx.c # 2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/53c700.c # 2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # drivers/scsi/3w-xxxx.c # 2004/05/12 10:46:19-05:00 arjanv@redhat.com +1 -1 # SCSI: replace deprecated hosts.h file # # ChangeSet # 2004/06/03 20:07:56-05:00 akpm@osdl.org # [PATCH] scsi_transport_spi.c build fix # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_transport_spi.c # 2004/06/03 11:23:05-05:00 akpm@osdl.org +1 -1 # scsi_transport_spi.c build fix # # ChangeSet # 2004/06/03 20:06:32-05:00 akpm@osdl.org # [PATCH] Lost 2.4 change for BusLogic info # # From: Alan Cox # # I think it might be a good thing if this was fixed to match 2.4 # # Signed-off-by: Andrew Morton # Signed-off-by: James Bottomley # # drivers/scsi/Kconfig # 2004/06/03 01:56:10-05:00 akpm@osdl.org +1 -3 # Lost 2.4 change for BusLogic info # # ChangeSet # 2004/06/03 20:05:10-05:00 hch@lst.de # [PATCH] scsi_dev_flags must be __initdata, not __init # # __init is only for functions # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_devinfo.c # 2004/05/31 16:05:51-05:00 hch@lst.de +1 -1 # scsi_dev_flags must be __initdata, not __init # # ChangeSet # 2004/06/03 20:03:33-05:00 rddunlap@osdl.org # [PATCH] fix check_region usage in eata_pio # # Based on "eata_generic.h", this SCSI controller has 9 bytes of IO # space, not 8, so update request_region(), release_region(), and # n_io_port to use 9 instead of 8. # # diffstat:= # drivers/scsi/eata_pio.c | 16 ++++++++-------- # 1 files changed, 8 insertions(+), 8 deletions(-) # # Signed-off-by: James Bottomley # # drivers/scsi/eata_pio.c # 2004/06/01 17:29:30-05:00 rddunlap@osdl.org +8 -8 # fix check_region usage in eata_pio # # ChangeSet # 2004/06/03 20:01:03-05:00 James.Bottomley@steeleye.com # [PATCH] Advansys: Add basic highmem/DMA support # # On Wed, 2004-05-19 at 05:38, Herbert Xu wrote: # > This is a resend of my patch that adds basic support for highmem # > on i386 to the advansys driver. It has been tested in # > http://bugs.debian.org/245238. # > # > The maintainer email address listed in the MAINTAINERS file bounced # > so someone else will need to look at this. # # I converted your patch to use the DMA-API. This will be necessary to # use the EISA advansys boards---Of course, EISA won't work properly until # the entire driver is converted to the driverfs probing API, sigh, but # I'll get around to that eventually. # # OK, and I couldn't resist getting rid of the stupid in_isr locking on # the done function. # # Converted from original patch by Herbert Xu # Signed-off-by: James Bottomley # # drivers/scsi/advansys.c # 2004/05/31 12:14:32-05:00 James.Bottomley@steeleye.com +95 -50 # Add basic highmem/DMA support # # ChangeSet # 2004/06/03 19:59:37-05:00 hch@lst.de # [PATCH] remove obsolete API usage from dpt_i2o # # Signed-off-by: James Bottomley # # drivers/scsi/dpti.h # 2004/05/31 08:34:32-05:00 hch@lst.de +12 -12 # remove obsolete API usage from dpt_i2o # # drivers/scsi/dpt_i2o.c # 2004/05/31 08:35:50-05:00 hch@lst.de +28 -25 # remove obsolete API usage from dpt_i2o # # ChangeSet # 2004/06/03 19:58:15-05:00 hch@lst.de # [PATCH] fix sym53c416 check_region usage # # again, the init code could use some bigger rework, but let's stick to # the minimal fix until we have some testers. # # Signed-off-by: James Bottomley # # drivers/scsi/sym53c416.c # 2004/05/31 07:18:12-05:00 hch@lst.de +41 -42 # fix sym53c416 check_region usage # # ChangeSet # 2004/06/03 19:56:47-05:00 hch@lst.de # [PATCH] fix check_region usage in eata_pio # # I'd love to rework the init sequence a bit more, but without beeing able # to actually test the driver I'd rather stick to the bulletproof fix. # # Signed-off-by: James Bottomley # # drivers/scsi/eata_pio.c # 2004/05/31 06:30:48-05:00 hch@lst.de +58 -44 # fix check_region usage in eata_pio # # ChangeSet # 2004/06/03 19:55:15-05:00 hch@lst.de # [PATCH] handle NO_SENSE in sd # # Original patch from # http://marc.theaimsgroup.com/?l=linux-scsi&m=107428662718579&w=2 # reworked to according to James' suggestion to handle NO_SENSE the same # as RECOVERED_ERROR. # # Signed-off-by: James Bottomley # # drivers/scsi/sd.c # 2004/05/31 05:53:01-05:00 hch@lst.de +4 -4 # handle NO_SENSE in sd # # ChangeSet # 2004/06/03 19:53:41-05:00 hch@lst.de # [PATCH] remove sleep_on_timeout usage in megaraid # # megaraid does sleep_on_timeout on a stack waitq - use msleep instead. # # Signed-off-by: James Bottomley # # drivers/scsi/megaraid.c # 2004/05/30 08:04:14-05:00 hch@lst.de +3 -6 # remove sleep_on_timeout usage in megaraid # # ChangeSet # 2004/06/03 19:52:05-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: Store pDCB in device->hostdata # # On Sun, 23 May 2004, Christoph Hellwig wrote: # > The other thing is that most calls to dc390_findDCB could probably be # > replaced with stroing the pDCB in scsi_device->hostdata on slave_alloc, # > but that could aswell be done in an incremental patch. # # Done in the attached patch. Tested as usual and a bit harder. # # Signed-off-by: James Bottomley # # drivers/scsi/tmscsim.c # 2004/05/28 18:17:17-05:00 g.liakhovetski@gmx.de +8 -10 # tmscsim: Store pDCB in device->hostdata # # ChangeSet # 2004/06/03 19:50:16-05:00 hch@lst.de # [PATCH] fix dpt_i2o compilation for alpha and sparc # # This patch has been floating around for ages, got reminded of it again # when looking at the debian kernel package. # # Signed-off-by: James Bottomley # # drivers/scsi/dpt_i2o.c # 2004/05/10 07:21:38-05:00 hch@lst.de +2 -2 # fix dpt_i2o compilation for alpha and sparc # # ChangeSet # 2004/06/03 20:43:58-04:00 len.brown@intel.com # [ACPI] acpi=force overrides blacklist pci=noacpi or acpi=noirq (Andi Kleen) # # arch/i386/kernel/dmi_scan.c # 2004/06/03 20:43:48-04:00 len.brown@intel.com +12 -6 # acpi=force overrides blacklist pci=noacpi or acpi=noirq (Andi Kleen) # # ChangeSet # 2004/06/03 19:41:12-05:00 aradford@amcc.com # [PATCH] 2/2 3ware 9000 SATA-RAID driver v2.26.00.009 # # Signed-off-by: James Bottomley # # include/linux/pci_ids.h # 2004/05/21 17:33:51-05:00 aradford@amcc.com +2 -0 # 3ware 9000 SATA-RAID driver v2.26.00.009 # # drivers/scsi/Makefile # 2004/05/21 17:24:55-05:00 aradford@amcc.com +1 -0 # 3ware 9000 SATA-RAID driver v2.26.00.009 # # drivers/scsi/Kconfig # 2004/05/21 18:29:59-05:00 aradford@amcc.com +12 -1 # 3ware 9000 SATA-RAID driver v2.26.00.009 # # drivers/scsi/3w-9xxx.h # 2004/05/26 15:17:26-05:00 aradford@amcc.com +726 -0 # 3ware 9000 SATA-RAID driver v2.26.00.009 # # MAINTAINERS # 2004/05/21 17:56:25-05:00 aradford@amcc.com +14 -0 # 3ware 9000 SATA-RAID driver v2.26.00.009 # # drivers/scsi/3w-9xxx.h # 2004/05/26 15:17:26-05:00 aradford@amcc.com +0 -0 # BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/3w-9xxx.h # # ChangeSet # 2004/06/03 19:39:01-05:00 aradford@amcc.com # [PATCH] 1/2 3ware 9000 SATA-RAID driver v2.26.00.009 # # Here is an updated version v2.26.00.009 of the 3ware 9000 SATA-RAID driver. # # Changes in this release: # - Convert driver to pci_driver format. # - Remove proc interface, add sysfs attributes. # - Return SCSI_MLQUEUE_HOST_BUSY when card status is busy. # # Future versions may include: # - PAE fix # - 80 column wrap fixes # - Remove more prototypes by re-ordering functions. # - sysfs queue depth adjustment instead of module_param # # Signed-off-by: James Bottomley # # drivers/scsi/3w-9xxx.c # 2004/05/26 15:17:24-05:00 aradford@amcc.com +2144 -0 # 3ware 9000 SATA-RAID driver v2.26.00.009 # # drivers/scsi/3w-9xxx.c # 2004/05/26 15:17:24-05:00 aradford@amcc.com +0 -0 # BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/3w-9xxx.c # # ChangeSet # 2004/06/03 17:14:32-07:00 greg@kroah.com # USB: remove "devfs" message from kernel log for usb-serial driver # # No one uses devfs on 2.6 :) # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/bus.c # 2004/06/03 17:14:00-07:00 greg@kroah.com +2 -2 # USB: remove "devfs" message from kernel log for usb-serial driver # # No one uses devfs on 2.6 :) # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/06/03 16:50:29-07:00 scott@concord.org # [PATCH] USB: kyocera 7135 patch # # Here is a patch based on 2.6.7-rc2 that makes the Kyocera 7135 work. # The Kyocera appears to have the same setup as the Trio. Its endpoints # are laid out like this: # # > >>>type address # > >>>usb bulk out: 0x01 # > >>>usb interrupt in: 0x82 # > >>>usb bulk out: 0x03 # > >>>usb bulk in: 0x84 # The last two are the ones used for the syncing communication. # # So the patch adds the ids for the kyocera and makes the treo_attach # function handle the kyocera too. I also changed the comment; it appears # there was an error in the original comment about the treo: # # Joe Nardelli wrote: # > Actually, the comment isn't quite right for Treos either (oops). It # > should read: # > # > ... # > 1st bulk in endpoint to communicate with the 2nd bulk out endpoint # > ... # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/visor.h # 2004/06/02 07:09:27-07:00 scott@concord.org +3 -0 # USB: kyocera 7135 patch # # drivers/usb/serial/visor.c # 2004/06/02 10:03:04-07:00 scott@concord.org +11 -7 # USB: kyocera 7135 patch # # ChangeSet # 2004/06/03 16:49:51-07:00 stern@rowland.harvard.edu # [PATCH] USB: 2.6-BK usb (printing) broken # # On Sat, 29 May 2004, Jens Axboe wrote: # # > > > Both 2.6.7-rc1 and BK current spit out a bunch of: # > > > # > > > drivers/usb/class/usblp.c: usblp1: nonzero read/write bulk status received: -2 # > > > drivers/usb/class/usblp.c: usblp1: error -2 reading from printer # > > > drivers/usb/class/usblp.c: usblp1: error -115 reading from printer # > > > drivers/usb/class/usblp.c: usblp1: error -115 reading from printer # > > > ... # > > > # > > > (about ~80 of that last line) but work for me. # # > Sorry wasn't quite clear - the above messages are with 2.6.7-rc1 and # > current bk with your patch backed out. Current bk with the patch reports # > only the timeouts I originally listed. # # Okay, I feel better. # # It looks like those errors you see are caused by a bug in the usblp # driver. The patch below ought to help. # # drivers/usb/class/usblp.c # 2004/05/29 07:25:51-07:00 stern@rowland.harvard.edu +1 -0 # USB: 2.6-BK usb (printing) broken # # ChangeSet # 2004/06/03 12:06:36-07:00 greg@kroah.com # Cset exclude: vojtech@suse.cz|ChangeSet|20040602201956|45549 # # Oops, this broke device removal pretty badly :( # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/transport.c # 2004/06/03 12:06:28-07:00 greg@kroah.com +0 -0 # Exclude # # drivers/usb/storage/isd200.c # 2004/06/03 12:06:28-07:00 greg@kroah.com +0 -0 # Exclude # # ChangeSet # 2004/06/03 00:45:08-04:00 len.brown@intel.com # [ACPI] fix !CONFIG_PCI build (Bjorn Helgaas) # # include/linux/acpi.h # 2004/06/02 11:02:20-04:00 len.brown@intel.com +2 -2 # fix !CONFIG_PCI build (Bjorn Helgaas) # # arch/i386/kernel/acpi/boot.c # 2004/06/02 11:02:20-04:00 len.brown@intel.com +5 -4 # fix !CONFIG_PCI build (Bjorn Helgaas) # # ChangeSet # 2004/06/02 14:07:26-07:00 stern@rowland.harvard.edu # [PATCH] USB: Move usb_new_device() et al. into hub.c # # This patch moves usb_new_device(), usb_disconnect(), usb_choose_address(), # and usb_release_address() from usb.c to hub.c. As a side benefit, # choose_address() and release_address() can now become static. The other # two can't, because they have to be exported for use by HCD's when # registering/unregistering root hubs. # # Some other features of the patch: # # The usb_snddefctrl() and usb_rcvdefctrl() macros have been # removed, since only one of them was used and only in one spot. # # The comment about configuration choice needing to interact with # hub power budgeting has been moved in accordance with David's # wish. usb_new_device() checks to make sure a configuration # could be chosen and logs a warning if no choice was made. # # Following Linus's preference, the #ifdef preprocessor stuff has # been removed from around the calls the show_string routine. It # is now defined as a non-inline routine when debugging is enabled # and as an inline no-op otherwise (the compiler will optimize # away the useless tests). # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.c # 2004/06/01 09:54:17-07:00 stern@rowland.harvard.edu +0 -229 # USB: Move usb_new_device() et al. into hub.c # # drivers/usb/core/hub.c # 2004/06/01 09:54:17-07:00 stern@rowland.harvard.edu +231 -3 # USB: Move usb_new_device() et al. into hub.c # # drivers/usb/core/hcd.h # 2004/06/01 09:54:17-07:00 stern@rowland.harvard.edu +0 -7 # USB: Move usb_new_device() et al. into hub.c # # ChangeSet # 2004/06/02 14:06:55-07:00 stern@rowland.harvard.edu # [PATCH] USB: Minor cleanups for hub driver # # Greg: # # This patch takes care of some small miscellaneous items in hub.c: # # Move the definition of CONFIG to the right place; # # Print the proper value for submission status in the error log; # # Remove an unused list of all hubs; # # Remove some unneeded braces; # # Kill an accidentally-resurrected comment. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.h # 2004/06/01 09:31:11-07:00 stern@rowland.harvard.edu +0 -1 # USB: Minor cleanups for hub driver # # drivers/usb/core/hub.c # 2004/06/01 09:39:04-07:00 stern@rowland.harvard.edu +9 -25 # USB: Minor cleanups for hub driver # # ChangeSet # 2004/06/02 13:55:44-07:00 oliver@neukum.org # [PATCH] USB: fix race between disconnect and write of acm driver # # acm uses a workqueue to defer part of a write operation. # In case of disconnect this work must be waited for. # - fix race between write and disconnect # # Signed-off-by: Oliver Neukum # Signed-off-by: Vojtech Pavlik # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/cdc-acm.c # 2004/05/31 08:13:14-07:00 oliver@neukum.org +2 -0 # USB: fix race between disconnect and write of acm driver # # ChangeSet # 2004/06/02 13:49:28-07:00 oliver@neukum.org # [PATCH] USB: fix racy access to urb->status in cdc acm driver # # Hi, # # fix access to urb->status by introduction of an explicit flag # for finished data transfer. # - fix racy access to urb->status # # Signed-off-by: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/cdc-acm.h # 2004/05/31 08:02:12-07:00 oliver@neukum.org +1 -0 # USB: fix racy access to urb->status in cdc acm driver # # drivers/usb/class/cdc-acm.c # 2004/05/31 08:02:12-07:00 oliver@neukum.org +10 -6 # USB: fix racy access to urb->status in cdc acm driver # # ChangeSet # 2004/06/02 13:36:24-07:00 oliver@neukum.org # [PATCH] USB: error handling of open of acm driver # # this adds error handling to the open method of the cdc acm driver. # The change set is relative to my last patch rewriting probe. # - add error handling to open method # # # Signed-off-by: Oliver Neukum # Signed-off-by: Vojtech Pavlik # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/cdc-acm.c # 2004/05/31 06:54:36-07:00 oliver@neukum.org +23 -8 # USB: error handling of open of acm driver # # ChangeSet # 2004/06/02 13:31:54-07:00 oliver@neukum.org # [PATCH] USB: proper evaluation of the union descriptor for CDC ACM # # this changes acm_probe() to using the proper union descriptor. # It contains the workaround David suggested. Please apply. # # - fix probing to use cdc union descriptor # # Signed-off-by: Oliver Neukum # Signed-off-by: Vojtech Pavlik # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/cdc-acm.c # 2004/05/30 03:56:45-07:00 oliver@neukum.org +100 -174 # USB: proper evaluation of the union descriptor for CDC ACM # # drivers/usb/class/cdc-acm.h # 2004/05/30 03:56:45-07:00 oliver@neukum.org +114 -0 # USB: proper evaluation of the union descriptor for CDC ACM # # drivers/usb/class/cdc-acm.h # 2004/05/30 03:56:45-07:00 oliver@neukum.org +0 -0 # BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/class/cdc-acm.h # # ChangeSet # 2004/06/02 13:25:59-07:00 david-b@pacbell.net # [PATCH] USB: usb retry cleanups # # This patch stops changing the reported fault mode in cases where retries of # GET_DESCRIPTOR fail because the device just doesn't have such a descriptor. # Plus, it stops printing messages when retrying. # # It also reduces the number of retries; the first retry seems to resolve most # of these firmware problems. # # Signed-Off-By: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/message.c # 2004/06/01 08:10:37-07:00 david-b@pacbell.net +1 -4 # USB: usb retry cleanups # # ChangeSet # 2004/06/02 13:25:08-07:00 david-b@pacbell.net # [PATCH] USB: pxa/rndis device descriptor # # This fixes a problem that all pxa2xx_udc g_ether devices # would run into. They'd give the wrong descriptors, like: # # > --------msg1- usbview ---------- # > Device Descriptor: bcdUSB: 0x0200 # > bDeviceClass: 0xFF # > bDeviceSubClass: 0x00 # > bDeviceProtocol: 0x00 # > bMaxPacketSize0: 0x10 (16) # # Windows doesn't like RNDIS-supporting devices to point # out that they're really vendor-specific. So this patch # makes sure they don't. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/ether.c # 2004/05/29 04:01:44-07:00 david-b@pacbell.net +10 -11 # USB: pxa/rndis device descriptor # # ChangeSet # 2004/06/02 13:19:23-07:00 numlock@freesurf.ch # [PATCH] Add support for ISD-300 controller # # This patch adds support in unusual_devs.h for the ISD-300 USB controller # used in CD-ROM enclosures. # # With it, since 2.6.0 it allowed me to move gigabytes of data and worked # without a hitch. # # # Signed-off-by: Andrew Morton # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2004/05/25 20:32:24-07:00 numlock@freesurf.ch +6 -0 # Add support for ISD-300 controller # # ChangeSet # 2004/06/02 13:18:53-07:00 stern@rowland.harvard.edu # [PATCH] USB: Fix disconnect bug in dummy_hcd # # Greg: # # This patch fixes a bug in disconnect handling for the dummy_hcd driver. # After a disconnect the driver would still accept URBs for endpoint 0, # leading to an oops. It also improves the ad-hoc technique used by the # driver to track its gadget's struct usb_device and fixes the way # port-power changes are handled. Please apply. # # Alan Stern # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/dummy_hcd.c # 2004/05/17 10:12:20-07:00 stern@rowland.harvard.edu +11 -4 # USB: Fix disconnect bug in dummy_hcd # # ChangeSet # 2004/06/02 13:18:15-07:00 stern@rowland.harvard.edu # [PATCH] USB: unusual_devs.h update # # On Mon, 3 May 2004, zcat wrote: # # > I am trying to get my camera going as a webcam (concord EyeQ Duo in PC # > mode, not HDD mode) with the 2.6.4 kernel using the se401 driver # > (compiled in).. It logged the following message, which doesn't mean much # > to me so I have no idea if it's useful information or not; # > # > May 3 21:08:11 mrsnorris kernel: usb 1-1: new full speed USB device # > using address 2 # > May 3 21:08:16 mrsnorris kernel: usb 1-1: control timeout on ep0out # > May 3 21:08:16 mrsnorris kernel: usb-storage: This device # > (0595,4343,0100 S 00 P 00) has an unneeded Protocol entry in unusual_devs.h # > May 3 21:08:16 mrsnorris kernel: Please send a copy of this message # > to # # This fixes the "unneeded Protocol entry" message. We never solved the # control timeout problem. # # Alan Stern # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2004/05/03 04:15:35-07:00 stern@rowland.harvard.edu +1 -1 # USB: unusual_devs.h update # # ChangeSet # 2004/06/02 15:37:59-04:00 rl@hellgate.ch # [PATCH] Add rhine_power_init(): get power regs into sane state # # Add rhine_power_init(): get power regs into sane state. # Move the respective code out of rhine_init_one. Add code for # two additional patterns (Rhine III). # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +35 -20 # Add rhine_power_init(): get power regs into sane state # # ChangeSet # 2004/06/02 15:37:51-04:00 rl@hellgate.ch # [PATCH] Rewrite special-casing # # Use PCI revision to determine special cases. One bit field replaces a # bunch of data structures holding special case information. # # Replace chip_id, drv_flags in rhine_private with quirks # # Remove enum rhine_chips, struct rhine_chip_info (and array), # enum chip_capability_flags # # Add enum rhine_revs, enum rhine_quirks (some values in preparation for # subsequent changes) # # wait_for_reset() and enable_mmio() now use quirks instead of chip_id # # Remove model names from ident strings for now. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +76 -58 # Rewrite special-casing # # ChangeSet # 2004/06/02 15:37:42-04:00 rl@hellgate.ch # [PATCH] Return codes for rhine_init_one # # Use return codes in rhine_init_one instead of -ENODEV for all errors. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +15 -7 # Return codes for rhine_init_one # # ChangeSet # 2004/06/02 15:37:34-04:00 rl@hellgate.ch # [PATCH] Nuke all pci_flags # # All this code together can be replaced with a single #ifdef USE_MMIO. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +11 -20 # Nuke all pci_flags # # ChangeSet # 2004/06/02 15:37:26-04:00 rl@hellgate.ch # [PATCH] Nuke default_port, references to if_port, medialock # # As is, code doesn't do anything useful. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +0 -10 # Nuke default_port, references to if_port, medialock # # ChangeSet # 2004/06/02 15:37:18-04:00 rl@hellgate.ch # [PATCH] Nuke HasESIPhy and related code # # This has been dead code forever. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +2 -3 # Nuke HasESIPhy and related code # # ChangeSet # 2004/06/02 15:37:09-04:00 rl@hellgate.ch # [PATCH] Nuke CanHaveMII and related code # # All Rhines can have a MII. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +26 -40 # Nuke CanHaveMII and related code # # ChangeSet # 2004/06/02 15:37:01-04:00 rl@hellgate.ch # [PATCH] Nuke HAS_IP_COPYSUM # # HAS_IP_COPYSUM has been utterly meaningless for a long time. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM # # ChangeSet # 2004/06/01 12:39:07-05:00 jejb@raven.il.steeleye.com # Merge # # drivers/scsi/sr_ioctl.c # 2004/06/01 12:38:49-05:00 jejb@raven.il.steeleye.com +0 -0 # SCCS merged # # drivers/scsi/sg.c # 2004/06/01 12:36:37-05:00 jejb@raven.il.steeleye.com +0 -0 # Auto merged # # drivers/scsi/scsi_devinfo.c # 2004/06/01 12:36:37-05:00 jejb@raven.il.steeleye.com +0 -0 # Auto merged # # drivers/scsi/constants.c # 2004/06/01 12:36:36-05:00 jejb@raven.il.steeleye.com +0 -0 # Auto merged # # ChangeSet # 2004/05/29 10:47:12-05:00 akpm@osdl.org # [PATCH] remove calls of obsolete scsi APIs in i2o_scsi # # From: Markus Lidel # # Here is a patch from Christoph Hellwig, which removes calls of the obsolete # scsi API in i2o_scsi. # # Signed-off-by: Andrew Morton # Signed-off-by: James Bottomley # # drivers/message/i2o/i2o_scsi.c # 2004/05/28 11:21:05-05:00 akpm@osdl.org +34 -57 # remove calls of obsolete scsi APIs in i2o_scsi # # ChangeSet # 2004/05/29 10:44:40-05:00 Markus.Lidel@shadowconnect.com # [PATCH] get I2O working with Adaptec's zero channel # # this patch now gets the mentioned controllers working with the I2O # subsystem. It tested on two different system with ASR-2005S and # ASR-2010S and reported as working. # # It's also tested on i686 and x86_64 with already working I2O controllers # without a problem. # # Signed-off-by: James Bottomley # # include/linux/i2o.h # 2004/05/24 18:53:22-05:00 Markus.Lidel@shadowconnect.com +9 -5 # get I2O working with Adaptec's zero channel # # drivers/message/i2o/i2o_scsi.c # 2004/05/24 18:56:46-05:00 Markus.Lidel@shadowconnect.com +3 -3 # get I2O working with Adaptec's zero channel # # drivers/message/i2o/i2o_core.c # 2004/05/24 19:07:35-05:00 Markus.Lidel@shadowconnect.com +104 -55 # get I2O working with Adaptec's zero channel # # drivers/message/i2o/i2o_config.c # 2004/05/24 16:57:44-05:00 Markus.Lidel@shadowconnect.com +1 -1 # get I2O working with Adaptec's zero channel # # drivers/message/i2o/i2o_block.c # 2004/05/24 18:56:06-05:00 Markus.Lidel@shadowconnect.com +4 -4 # get I2O working with Adaptec's zero channel # # ChangeSet # 2004/05/29 10:40:12-05:00 brking@us.ibm.com # [PATCH] ipr operational timeout oops # # This patch fixes an oops that can occur if an adapter times # out coming operational. # # Signed-off-by: James Bottomley # # drivers/scsi/ipr.h # 2004/05/26 22:30:13-05:00 brking@us.ibm.com +2 -2 # ipr operational timeout oops # # drivers/scsi/ipr.c # 2004/05/26 17:22:36-05:00 brking@us.ibm.com +1 -0 # ipr operational timeout oops # # ChangeSet # 2004/05/29 10:37:41-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: convert to slave_... # # On Wed, 26 May 2004, Christoph Hellwig wrote: # > Looks like a way to go. I'm not sure what scan_device is supposed to # > do as I already wrote, but from looking at when it's set/cleared I'm # > pretty sure it tries to indicate whethere we're currently scanning for # > devices. And useing slave_alloc/slave_configure is a much safer way to # > find that out then guessing from the commands sent. # # Attached is a patch, that moves scan_device to # slave_alloc/_configure/_destroy, as you suggested (to be precise, as I # understood your suggestion:-)) # # Signed-off-by: James Bottomley # # drivers/scsi/tmscsim.h # 2004/05/27 17:52:39-05:00 g.liakhovetski@gmx.de +0 -2 # tmscsim: convert to slave_... # # drivers/scsi/tmscsim.c # 2004/05/27 17:57:12-05:00 g.liakhovetski@gmx.de +19 -14 # tmscsim: convert to slave_... # # drivers/scsi/scsiiom.c # 2004/05/27 17:32:23-05:00 g.liakhovetski@gmx.de +21 -41 # tmscsim: convert to slave_... # # drivers/scsi/dc390.h # 2004/05/27 17:57:23-05:00 g.liakhovetski@gmx.de +1 -13 # tmscsim: convert to slave_... # # ChangeSet # 2004/05/29 10:33:13-05:00 akpm@osdl.org # [PATCH] unchecked kmalloc in sr_audio_ioctl() # # From: "Luiz Fernando N. Capitulino" # # # Signed-off-by: Andrew Morton # Signed-off-by: James Bottomley # # drivers/scsi/sr_ioctl.c # 2004/05/26 11:03:15-05:00 akpm@osdl.org +3 -0 # unchecked kmalloc in sr_audio_ioctl() # # ChangeSet # 2004/05/29 10:31:04-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: remove DeviceCnt # # On Wed, 26 May 2004, Christoph Hellwig wrote: # > On Sun, May 23, 2004 at 11:19:58PM +0200, Guennadi Liakhovetski wrote: # > > # > > Whereas, DCBCnt is incremented on slave_alloc, decremented on # > > slave_destroy and used in a couple more places. So, is it safe to assume # > > that DeviceCnt is redundant and remove it in a next patch?... Then it # > > might be already safe to move scan_devices as you suggest? # > # > Looks like a way to go. I'm not sure what scan_device is supposed to # > do as I already wrote, but from looking at when it's set/cleared I'm # > pretty sure it tries to indicate whethere we're currently scanning for # > devices. And useing slave_alloc/slave_configure is a much safer way to # > find that out then guessing from the commands sent. # # So, here's the first one - remove DeviceCnt. # # Signed-off-by: James Bottomley # # drivers/scsi/tmscsim.h # 2004/05/26 15:23:14-05:00 g.liakhovetski@gmx.de +2 -9 # tmscsim: remove DeviceCnt # # drivers/scsi/tmscsim.c # 2004/05/26 15:24:01-05:00 g.liakhovetski@gmx.de +1 -2 # tmscsim: remove DeviceCnt # # drivers/scsi/scsiiom.c # 2004/05/26 15:23:32-05:00 g.liakhovetski@gmx.de +0 -2 # tmscsim: remove DeviceCnt # # ChangeSet # 2004/05/29 10:28:07-05:00 g.liakhovetski@gmx.de # [PATCH] tmscsim: Update version after "new API" # # The "API-update" patch, just approved by Christoph deserves a new version. # # Signed-off-by: James Bottomley # # drivers/scsi/tmscsim.c # 2004/05/26 15:16:10-05:00 g.liakhovetski@gmx.de +2 -0 # tmscsim: Update version after "new API" # # drivers/scsi/dc390.h # 2004/05/26 15:16:08-05:00 g.liakhovetski@gmx.de +1 -1 # tmscsim: Update version after "new API" # # ChangeSet # 2004/05/29 10:24:44-05:00 davej@redhat.com # [PATCH] SCSI: Correct BELKIN card reader whitelist entry. # # Should be FORCELUN not SPARSELUN ? # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_devinfo.c # 2004/05/26 08:13:42-05:00 davej@redhat.com +1 -1 # SCSI: Correct BELKIN card reader whitelist entry. # # ChangeSet # 2004/05/29 10:22:47-05:00 davej@redhat.com # [PATCH] SCSI: more whitelist updates for usb card readers # # ATech 9-in-1 card reader. # Cbox 3 5 1/2 bay with 6in1 card reader # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_devinfo.c # 2004/05/26 07:44:43-05:00 davej@redhat.com +3 -0 # SCSI: more whitelist updates for usb card readers # # ChangeSet # 2004/05/29 10:20:15-05:00 akpm@osdl.org # [PATCH] Stop megaraid trashing other i960 based devices # # From: Alan Cox # # In 2.4 the megaraid driver was careful to avoid stepping on wrong devices. # Specifically the megaraid3 series devices used an intel pci ID (8086:1960) # which is the generic i960 identifier not their own. # # The code to do this in 2.4 worked for almost all cases, but even that code has # mysteriously vanished in 2.6 meaning the megaraid driver trashes stuff like # promise i2o cards and compaq management cards. # # The following patch puts back the 2.4 stuff + one additional check so that the # driver isn't quite as rude as it was before. # # Signed-off-by: James Bottomley # # drivers/scsi/megaraid.c # 2004/05/22 20:59:10-05:00 akpm@osdl.org +20 -0 # Stop megaraid trashing other i960 based devices # # ChangeSet # 2004/05/29 10:17:42-05:00 lcapitulino@prefeitura.sp.gov.br # [PATCH] qla1280.c warning fix. # # drivers/scsi/qla1280.c:3124: warning: `qla1280_64bit_start_scsi' defined but not used # # Signed-off-by: James Bottomley # # drivers/scsi/qla1280.c # 2004/04/13 12:56:24-05:00 lcapitulino@prefeitura.sp.gov.br +2 -2 # qla1280.c warning fix. # # ChangeSet # 2004/05/29 10:13:11-05:00 michaelc@cs.wisc.edu # [PATCH] SCSI: remove extra queue unplug calls # # blk_insert_request will do the right thing and either unplug the queue or # call the request_fn, so users of scsi_do_req do not need to call # generic_unplug_device themselves. The attached patch just removes that # call from scsi_lib.c and the sg driver after they do a scsi_do_req. # # Signed-off-by: James Bottomley # # drivers/scsi/sg.c # 2004/05/24 20:59:40-05:00 michaelc@cs.wisc.edu +0 -1 # SCSI: remove extra queue unplug calls # # drivers/scsi/scsi_lib.c # 2004/05/24 20:59:39-05:00 michaelc@cs.wisc.edu +0 -1 # SCSI: remove extra queue unplug calls # # ChangeSet # 2004/05/29 10:11:11-05:00 jejb@mulgrave.(none) # MPT Fusion driver 3.01.07 update # # From: "Moore, Eric Dean" # # Clean up backword compatibility with 2.4 kernel and older. Patch # provided by Christoph Hellwig # # Signed-off-by: James Bottomley # # drivers/message/fusion/mptscsih.h # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +0 -71 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/mptscsih.c # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +36 -37 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/mptlan.c # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +3 -16 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/mptctl.c # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +2 -66 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/mptbase.h # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +7 -3 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/mptbase.c # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +10 -8 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/linux_compat.h # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +0 -189 # MPT Fusion driver 3.01.07 update # # drivers/message/fusion/isense.c # 2004/05/29 10:10:51-05:00 jejb@mulgrave.(none) +0 -8 # MPT Fusion driver 3.01.07 update # # ChangeSet # 2004/05/29 10:06:35-05:00 davej@redhat.com # [PATCH] USB / SCSI multi-card reader whitelist updates. # # For more info see Red Hat bugzilla entries #85851 and #124048 # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_devinfo.c # 2004/05/04 11:44:37-05:00 davej@redhat.com +2 -0 # USB / SCSI multi-card reader whitelist updates. # # ChangeSet # 2004/05/29 10:04:10-05:00 brking@us.ibm.com # [PATCH] ipr driver version 2.0.8 # # Bump driver version # # Signed-off-by: James Bottomley # # drivers/scsi/ipr.h # 2004/05/23 21:48:22-05:00 brking@us.ibm.com +2 -2 # ipr driver version 2.0.8 # # ChangeSet # 2004/05/29 10:01:45-05:00 brking@us.ibm.com # [PATCH] ipr duplicate ioa reset fix # # This patch closes a window where if a device had a cancel all # outstanding as a result of a check condition and the adapter # was reset for some reason, a request sense would still be issued, # which would end up timing out and issuing an additional adapter # reset. It could also result in a leak of command blocks, depending # on when it timed out. # # Signed-off-by: James Bottomley # # drivers/scsi/ipr.c # 2004/05/23 21:43:47-05:00 brking@us.ibm.com +6 -0 # ipr duplicate ioa reset fix # # ChangeSet # 2004/05/29 09:59:59-05:00 brking@us.ibm.com # [PATCH] ipr scsi busy io hang # # Signed-off-by: James Bottomley # # drivers/scsi/ipr.c # 2004/05/23 21:40:15-05:00 brking@us.ibm.com +5 -1 # ipr scsi busy io hang # # ChangeSet # 2004/05/29 09:59:10-05:00 jejb@mulgrave.(none) # Convert tmcscsim to new probing interfaces # # From: Guennadi Liakhovetski # # Update the driver to use the new pci, scsi and # module interfaces. # # Modified with feedback from hch # # Signed-off-by: James Bottomley # # drivers/scsi/tmscsim.c # 2004/05/29 09:58:54-05:00 jejb@mulgrave.(none) +151 -98 # Convert tmcscsim to new probing interfaces # # drivers/scsi/scsiiom.c # 2004/05/29 09:58:54-05:00 jejb@mulgrave.(none) +12 -26 # Convert tmcscsim to new probing interfaces # # drivers/scsi/dc390.h # 2004/05/29 09:58:54-05:00 jejb@mulgrave.(none) +0 -1 # Convert tmcscsim to new probing interfaces # # ChangeSet # 2004/05/29 09:55:10-05:00 jejb@mulgrave.(none) # SCSI: slave_detach -> slave_destory comment fix # # From: Guennadi Liakhovetski # # Signed-off-by: James Bottomley # # include/scsi/scsi_host.h # 2004/05/29 09:54:55-05:00 jejb@mulgrave.(none) +2 -2 # SCSI: slave_detach -> slave_destory comment fix # # ChangeSet # 2004/05/29 09:48:47-05:00 hch@lst.de # [PATCH] move scsi debugging helpers and give them sane names # # - give the constants.c prettyprinting helpers proper scsi_ prefixed # names (and keep compat versions for 2.6.x) # - move them to include/scsi/scsi_dbg.h so now really only legacy stuff # is left in drivers/scsi/scsi.h # # Signed-off-by: James Bottomley # # drivers/scsi/scsi_syms.c # 2004/05/19 12:46:14-05:00 hch@lst.de +6 -6 # move scsi debugging helpers and give them sane names # # drivers/scsi/scsi.h # 2004/05/19 12:46:14-05:00 hch@lst.de +42 -15 # move scsi debugging helpers and give them sane names # # drivers/scsi/constants.c # 2004/05/19 12:46:14-05:00 hch@lst.de +11 -11 # move scsi debugging helpers and give them sane names # # include/scsi/scsi_dbg.h # 2004/05/13 03:45:25-05:00 hch@lst.de +18 -0 # move scsi debugging helpers and give them sane names # # include/scsi/scsi_dbg.h # 2004/05/13 03:45:25-05:00 hch@lst.de +0 -0 # BitKeeper file /home/jejb/BK/scsi-misc-2.6/include/scsi/scsi_dbg.h # # ChangeSet # 2004/05/27 15:21:03-04:00 herbert@gondor.apana.org.au # [NETDRV #2] Use driver-specific name for resources # # Here is the next part which uses a driver-specific name instead of # dev->name for resource allocations prior to netdev registration. # It also changes printks that are in direct response to errors in # resource allocations. # # drivers/net/zorro8390.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/yellowfin.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/wd.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/sunhme.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/sungem.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/sun3_82586.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/stnic.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/starfire.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc9194.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc-ultra32.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc-ultra.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc-mca.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/r8169.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/oaknet.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ns83820.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ni52.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne3210.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +6 -4 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne2k_cbus.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne2.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne-h8300.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/natsemi.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/lp486e.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/lne390.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/jazzsonic.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ibmlana.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/hp.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/hp-plus.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/forcedeth.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/fmv18x.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ewrk3.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/eth16i.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -4 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/eepro.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/e2100.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/defxx.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/cs89x0.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/at1700.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/apne.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/acenic.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ac3200.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/82596.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c527.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c523.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c507.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c503.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c501.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # ChangeSet # 2004/05/27 15:20:53-04:00 herbert@gondor.apana.org.au # [NETDRV #1] Ifdef builtin-only probe in ISA/MCA drivers # # Here is the bit which conditionalises the # builtin-only probe functions. # # drivers/net/wd.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/smc-ultra.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne2k_cbus.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne2.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne-h8300.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/lne390.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/lance.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/isa-skeleton.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/hp100.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/hp.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/hp-plus.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ewrk3.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/eth16i.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/es3210.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/eexpress.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/eepro.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/e2100.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/cs89x0.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +1 -1 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ac3200.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/3c523.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/3c505.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -1 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/3c503.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # ChangeSet # 2004/05/27 13:38:57-04:00 rl@hellgate.ch # [PATCH] Nuke HAS_IP_COPYSUM for net drivers # # Entirely untested, but Obviously Correct(TM). HAS_IP_COPYSUM has been # utterly meaningless for a long time. # # drivers/net/yellowfin.c # 2004/05/25 14:46:47-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM for net drivers # # drivers/net/tulip/winbond-840.c # 2004/05/25 14:46:26-04:00 rl@hellgate.ch +0 -6 # Nuke HAS_IP_COPYSUM for net drivers # # drivers/net/natsemi.c # 2004/05/25 14:51:58-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM for net drivers # # drivers/net/epic100.c # 2004/05/25 14:45:55-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM for net drivers # # ChangeSet # 2004/05/25 01:32:47-04:00 len.brown@intel.com # [ACPI] PCI IRQ update (Bjorn Helgaas) # http://bugme.osdl.org/show_bug.cgi?id=2574 # # mp_parse_prt() and iosapic_parse_prt() used to allocate all # IRQs, whether devices needed them or not. Some devices # failed because the this method enabled unused PCI Interrupt # Link Devices, which disrupted active link devices. # # Now the PRT knowledge is pulled out of the arch # code and the IRQ allocation and IO-APIC programming # is done by pci_enable_device(). # This is also a step toward allowing the addition # of new root bridges and PRTs at run-time. # # The architecture supplies # # unsigned int # acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) # # which is called by acpi_pci_irq_enable(). ACPI supplies # all the information from the PRT, and the arch sets up # the routing and returns the IRQ it allocated. # # include/linux/acpi.h # 2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1 # PCI IRQ update (Bjorn Helgaas) # # include/asm-x86_64/mpspec.h # 2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1 # PCI IRQ update (Bjorn Helgaas) # # include/asm-ia64/iosapic.h # 2004/05/25 01:32:34-04:00 len.brown@intel.com +0 -1 # PCI IRQ update (Bjorn Helgaas) # # include/asm-i386/mpspec.h # 2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1 # PCI IRQ update (Bjorn Helgaas) # # include/acpi/acpi_drivers.h # 2004/05/25 01:32:34-04:00 len.brown@intel.com +1 -1 # PCI IRQ update (Bjorn Helgaas) # # drivers/serial/8250_hcdp.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +4 -8 # PCI IRQ update (Bjorn Helgaas) # # drivers/serial/8250_acpi.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +6 -16 # PCI IRQ update (Bjorn Helgaas) # # drivers/acpi/tables.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +3 -3 # PCI IRQ update (Bjorn Helgaas) # # drivers/acpi/pci_link.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +2 -2 # PCI IRQ update (Bjorn Helgaas) # # drivers/acpi/pci_irq.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +36 -83 # PCI IRQ update (Bjorn Helgaas) # # arch/x86_64/kernel/mpparse.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +39 -76 # PCI IRQ update (Bjorn Helgaas) # # arch/ia64/pci/pci.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +12 -4 # PCI IRQ update (Bjorn Helgaas) # # arch/ia64/kernel/iosapic.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +80 -129 # PCI IRQ update (Bjorn Helgaas) # # arch/ia64/kernel/acpi.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +8 -15 # PCI IRQ update (Bjorn Helgaas) # # arch/i386/pci/acpi.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +23 -8 # PCI IRQ update (Bjorn Helgaas) # # arch/i386/kernel/mpparse.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +38 -78 # PCI IRQ update (Bjorn Helgaas) # # arch/i386/kernel/acpi/boot.c # 2004/05/25 01:32:34-04:00 len.brown@intel.com +28 -0 # PCI IRQ update (Bjorn Helgaas) # # ChangeSet # 2004/05/22 23:32:21-04:00 len.brown@intel.com # Kconfig typo fix from Jochen Voss # # drivers/acpi/Kconfig # 2004/04/05 06:54:30-04:00 len.brown@intel.com +1 -1 # Kconfig typo fix from Jochen Voss # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS 2004-06-20 13:00:25 -07:00 +++ b/CREDITS 2004-06-20 13:00:25 -07:00 @@ -2571,6 +2571,14 @@ D: sonypi, meye drivers, mct_u232 usb serial hacks S: Paris, France +N: Matt Porter +E: mporter@kernel.crashing.org +D: Motorola PowerPC PReP support +D: cPCI PowerPC support +D: Embedded PowerPC 4xx/6xx/7xx/74xx support +S: Chandler, Arizona 85249 +S: USA + N: Frederic Potter E: fpotter@cirpack.com D: Some PCI kernel support @@ -3109,12 +3117,13 @@ S: USA N: Marcelo W. Tosatti -E: marcelo@conectiva.com.br -W: http://bazar.conectiva.com.br/~marcelo/ -D: Miscellaneous kernel hacker (mostly VM/MM work) -S: Conectiva S.A. -S: R. Tocantins, 89 - Cristo Rei -S: 80050-430 - Curitiba - Paraná +E: marcelo.tosatti@cyclades.com +D: Miscellaneous kernel hacker +D: v2.4 kernel maintainer +D: Current pc300/cyclades maintainer +S: Cyclades Corporation +S: Av Cristovao Colombo, 462. Floresta. +S: Porto Alegre S: Brazil N: Stefan Traby diff -Nru a/Documentation/arm/Sharp-LH/SDRAM b/Documentation/arm/Sharp-LH/SDRAM --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/arm/Sharp-LH/SDRAM 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,51 @@ +README on the SDRAM Controller for the LH7a40X +============================================== + +The standard configuration for the SDRAM controller generates a sparse +memory array. The precise layout is determined by the SDRAM chips. A +default kernel configuration assembles the discontiguous memory +regions into separate memory nodes via the NUMA (Non-Uniform Memory +Architecture) facilities. In this default configuration, the kernel +is forgiving about the precise layout. As long as it is given an +accurate picture of available memory by the bootloader the kernel will +execute correctly. + +The SDRC supports a mode where some of the chip select lines are +swapped in order to make SDRAM look like a synchronous ROM. Setting +this bit means that the RAM will present as a contiguous array. Some +programmers prefer this to the discontiguous layout. Be aware that +may be a penalty for this feature where some some configurations of +memory are significantly reduced; i.e. 64MiB of RAM appears as only 32 +MiB. + +There are a couple of configuration options to override the default +behavior. When the SROMLL bit is set and memory appears as a +contiguous array, there is no reason to support NUMA. +CONFIG_LH7A40X_CONTIGMEM disables NUMA support. When physical memory +is discontiguous, the memory tables are organized such that there are +two banks per nodes with a small gap between them. This layout wastes +some kernel memory for page tables representing non-existent memory. +CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that +there are no gaps. These options control the low level organization +of the memory management tables in ways that may prevent the kernel +from booting or may cause the kernel to allocated excessively large +page tables. Be warned. Only change these options if you know what +you are doing. The default behavior is a reasonable compromise that +will suit all users. + +-- + +A typical 32MiB system with the default configuration options will +find physical memory managed as follows. + + node 0: 0xc0000000 4MiB + 0xc1000000 4MiB + node 1: 0xc4000000 4MiB + 0xc5000000 4MiB + node 2: 0xc8000000 4MiB + 0xc9000000 4MiB + node 3: 0xcc000000 4MiB + 0xcd000000 4MiB + +Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a +separate node. diff -Nru a/Documentation/arm/VFP/release-notes.txt b/Documentation/arm/VFP/release-notes.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/arm/VFP/release-notes.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,55 @@ +Release notes for Linux Kernel VFP support code +----------------------------------------------- + +Date: 20 May 2004 +Author: Russell King + +This is the first release of the Linux Kernel VFP support code. It +provides support for the exceptions bounced from VFP hardware found +on ARM926EJ-S. + +This release has been validated against the SoftFloat-2b library by +John R. Hauser using the TestFloat-2a test suite. Details of this +library and test suite can be found at: + + http://www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html + +The operations which have been tested with this package are: + + - fdiv + - fsub + - fadd + - fmul + - fcmp + - fcmpe + - fcvtd + - fcvts + - fsito + - ftosi + - fsqrt + +All the above pass softfloat tests with the following exceptions: + +- fadd/fsub shows some differences in the handling of +0 / -0 results + when input operands differ in signs. +- the handling of underflow exceptions is slightly different. If a + result underflows before rounding, but becomes a normalised number + after rounding, we do not signal an underflow exception. + +Other operations which have been tested by basic assembly-only tests +are: + + - fcpy + - fabs + - fneg + - ftoui + - ftosiz + - ftouiz + +The combination operations have not been tested: + + - fmac + - fnmac + - fmsc + - fnmsc + - fnmul diff -Nru a/Documentation/binfmt_misc.txt b/Documentation/binfmt_misc.txt --- a/Documentation/binfmt_misc.txt 2004-06-20 13:00:26 -07:00 +++ b/Documentation/binfmt_misc.txt 2004-06-20 13:00:26 -07:00 @@ -15,7 +15,7 @@ mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc To actually register a new binary type, you have to set up a string looking like -:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon +:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register. Here is what the fields mean: - 'name' is an identifier string. A new /proc file will be created with this @@ -34,6 +34,28 @@ The mask is anded with the byte sequence of the file. - 'interpreter' is the program that should be invoked with the binary as first argument (specify the full path) + - 'flags' is an optional field that controls several aspects of the invocation + of the interpreter. It is a string of capital letters, each controls a certain + aspect. The following flags are supported - + 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the + original argv[0] with the full path to the binary. When this flag is + included, binfmt_misc will add an argument to the argument vector for + this purpose, thus preserving the original argv[0]. + 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path + of the binary to the interpreter as an argument. When this flag is + included, binfmt_misc will open the file for reading and pass its + descriptor as an argument, instead of the full path, thus allowing + the interpreter to execute non-readable binaries. This feature should + be used with care - the interpreter has to be trusted not to emit + the contents of the non-readable binary. + 'C' - credentials. Currently, the behavior of binfmt_misc is to calculate + the credentials and security token of the new process according to + the interpreter. When this flag is included, these attributes are + calculated according to the binary. It also implies the 'O' flag. + This feature should be used with care as the interpreter + will run with root permissions when a setuid binary owned by root + is run with binfmt_misc. + There are some restrictions: - the whole register string may not exceed 255 characters @@ -83,9 +105,9 @@ write a wrapper script for it. See Documentation/java.txt for an example. -Your interpreter should NOT look in the PATH for the filename; the -kernel passes it the full filename to use. Using the PATH can cause -unexpected behaviour and be a security hazard. +Your interpreter should NOT look in the PATH for the filename; the kernel +passes it the full filename (or the file descriptor) to use. Using $PATH can +cause unexpected behaviour and can be a security hazard. There is a web page about binfmt_misc at diff -Nru a/Documentation/device-mapper/dm-io.txt b/Documentation/device-mapper/dm-io.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/device-mapper/dm-io.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,75 @@ +dm-io +===== + +Dm-io provides synchronous and asynchronous I/O services. There are three +types of I/O services available, and each type has a sync and an async +version. + +The user must set up an io_region structure to describe the desired location +of the I/O. Each io_region indicates a block-device along with the starting +sector and size of the region. + + struct io_region { + struct block_device *bdev; + sector_t sector; + sector_t count; + }; + +Dm-io can read from one io_region or write to one or more io_regions. Writes +to multiple regions are specified by an array of io_region structures. + +The first I/O service type takes a list of memory pages as the data buffer for +the I/O, along with an offset into the first page. + + struct page_list { + struct page_list *next; + struct page *page; + }; + + int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits); + int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context); + +The second I/O service type takes an array of bio vectors as the data buffer +for the I/O. This service can be handy if the caller has a pre-assembled bio, +but wants to direct different portions of the bio to different devices. + + int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, + int rw, struct bio_vec *bvec, + unsigned long *error_bits); + int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, + int rw, struct bio_vec *bvec, + io_notify_fn fn, void *context); + +The third I/O service type takes a pointer to a vmalloc'd memory buffer as the +data buffer for the I/O. This service can be handy if the caller needs to do +I/O to a large region but doesn't want to allocate a large number of individual +memory pages. + + int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits); + int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context); + +Callers of the asynchronous I/O services must include the name of a completion +callback routine and a pointer to some context data for the I/O. + + typedef void (*io_notify_fn)(unsigned long error, void *context); + +The "error" parameter in this callback, as well as the "*error" parameter in +all of the synchronous versions, is a bitset (instead of a simple error value). +In the case of an write-I/O to multiple regions, this bitset allows dm-io to +indicate success or failure on each individual region. + +Before using any of the dm-io services, the user should call dm_io_get() +and specify the number of pages they expect to perform I/O on concurrently. +Dm-io will attempt to resize its mempool to make sure enough pages are +always available in order to avoid unnecessary waiting while performing I/O. + +When the user is finished using the dm-io services, they should call +dm_io_put() and specify the same number of pages that were given on the +dm_io_get() call. + diff -Nru a/Documentation/device-mapper/kcopyd.txt b/Documentation/device-mapper/kcopyd.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/device-mapper/kcopyd.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,47 @@ +kcopyd +====== + +Kcopyd provides the ability to copy a range of sectors from one block-device +to one or more other block-devices, with an asynchronous completion +notification. It is used by dm-snapshot and dm-mirror. + +Users of kcopyd must first create a client and indicate how many memory pages +to set aside for their copy jobs. This is done with a call to +kcopyd_client_create(). + + int kcopyd_client_create(unsigned int num_pages, + struct kcopyd_client **result); + +To start a copy job, the user must set up io_region structures to describe +the source and destinations of the copy. Each io_region indicates a +block-device along with the starting sector and size of the region. The source +of the copy is given as one io_region structure, and the destinations of the +copy are given as an array of io_region structures. + + struct io_region { + struct block_device *bdev; + sector_t sector; + sector_t count; + }; + +To start the copy, the user calls kcopyd_copy(), passing in the client +pointer, pointers to the source and destination io_regions, the name of a +completion callback routine, and a pointer to some context data for the copy. + + int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, + unsigned int num_dests, struct io_region *dests, + unsigned int flags, kcopyd_notify_fn fn, void *context); + + typedef void (*kcopyd_notify_fn)(int read_err, unsigned int write_err, + void *context); + +When the copy completes, kcopyd will call the user's completion routine, +passing back the user's context pointer. It will also indicate if a read or +write error occurred during the copy. + +When a user is done with all their copy jobs, they should call +kcopyd_client_destroy() to delete the kcopyd client, which will release the +associated memory pages. + + void kcopyd_client_destroy(struct kcopyd_client *kc); + diff -Nru a/Documentation/device-mapper/linear.txt b/Documentation/device-mapper/linear.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/device-mapper/linear.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,61 @@ +dm-linear +========= + +Device-Mapper's "linear" target maps a linear range of the Device-Mapper +device onto a linear range of another device. This is the basic building +block of logical volume managers. + +Parameters: + : Full pathname to the underlying block-device, or a + "major:minor" device-number. + : Starting sector within the device. + + +Example scripts +=============== +[[ +#!/bin/sh +# Create an identity mapping for a device +echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity +]] + + +[[ +#!/bin/sh +# Join 2 devices together +size1=`blockdev --getsize $1` +size2=`blockdev --getsize $2` +echo "0 $size1 linear $1 0 +$size1 $size2 linear $2 0" | dmsetup create joined +]] + + +[[ +#!/usr/bin/perl -w +# Split a device into 4M chunks and then join them together in reverse order. + +my $name = "reverse"; +my $extent_size = 4 * 1024 * 2; +my $dev = $ARGV[0]; +my $table = ""; +my $count = 0; + +if (!defined($dev)) { + die("Please specify a device.\n"); +} + +my $dev_size = `blockdev --getsize $dev`; +my $extents = int($dev_size / $extent_size) - + (($dev_size % $extent_size) ? 1 : 0); + +while ($extents > 0) { + my $this_start = $count * $extent_size; + $extents--; + $count++; + my $this_offset = $extents * $extent_size; + + $table .= "$this_start $extent_size linear $dev $this_offset\n"; +} + +`echo \"$table\" | dmsetup create $name`; +]] diff -Nru a/Documentation/device-mapper/striped.txt b/Documentation/device-mapper/striped.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/device-mapper/striped.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,58 @@ +dm-stripe +========= + +Device-Mapper's "striped" target is used to create a striped (i.e. RAID-0) +device across one or more underlying devices. Data is written in "chunks", +with consecutive chunks rotating among the underlying devices. This can +potentially provide improved I/O throughput by utilizing several physical +devices in parallel. + +Parameters: [ ]+ + : Number of underlying devices. + : Size of each chunk of data. Must be a power-of-2 and at + least as large as the system's PAGE_SIZE. + : Full pathname to the underlying block-device, or a + "major:minor" device-number. + : Starting sector within the device. + +One or more underlying devices can be specified. The striped device size must +be a multiple of the chunk size and a multiple of the number of underlying +devices. + + +Example scripts +=============== + +[[ +#!/usr/bin/perl -w +# Create a striped device across any number of underlying devices. The device +# will be called "stripe_dev" and have a chunk-size of 128k. + +my $chunk_size = 128 * 2; +my $dev_name = "stripe_dev"; +my $num_devs = @ARGV; +my @devs = @ARGV; +my ($min_dev_size, $stripe_dev_size, $i); + +if (!$num_devs) { + die("Specify at least one device\n"); +} + +$min_dev_size = `blockdev --getsize $devs[0]`; +for ($i = 1; $i < $num_devs; $i++) { + my $this_size = `blockdev --getsize $devs[$i]`; + $min_dev_size = ($min_dev_size < $this_size) ? + $min_dev_size : $this_size; +} + +$stripe_dev_size = $min_dev_size * $num_devs; +$stripe_dev_size -= $stripe_dev_size % ($chunk_size * $num_devs); + +$table = "0 $stripe_dev_size striped $num_devs $chunk_size"; +for ($i = 0; $i < $num_devs; $i++) { + $table .= " $devs[$i] 0"; +} + +`echo $table | dmsetup create $dev_name`; +]] + diff -Nru a/Documentation/device-mapper/zero.txt b/Documentation/device-mapper/zero.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/device-mapper/zero.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,37 @@ +dm-zero +======= + +Device-Mapper's "zero" target provides a block-device that always returns +zero'd data on reads and silently drops writes. This is similar behavior to +/dev/zero, but as a block-device instead of a character-device. + +Dm-zero has no target-specific parameters. + +One very interesting use of dm-zero is for creating "sparse" devices in +conjunction with dm-snapshot. A sparse device reports a device-size larger +than the amount of actual storage space available for that device. A user can +write data anywhere within the sparse device and read it back like a normal +device. Reads to previously unwritten areas will return a zero'd buffer. When +enough data has been written to fill up the actual storage space, the sparse +device is deactivated. This can be very useful for testing device and +filesystem limitations. + +To create a sparse device, start by creating a dm-zero device that's the +desired size of the sparse device. For this example, we'll assume a 10TB +sparse device. + +TEN_TERABYTES=`expr 10 \* 1024 \* 1024 \* 1024 \* 2` # 10 TB in sectors +echo "0 $TEN_TERABYTES zero" | dmsetup create zero1 + +Then create a snapshot of the zero device, using any available block-device as +the COW device. The size of the COW device will determine the amount of real +space available to the sparse device. For this example, we'll assume /dev/sdb1 +is an available 10GB partition. + +echo "0 $TEN_TERABYTES snapshot /dev/mapper/zero1 /dev/sdb1 p 128" | \ + dmsetup create sparse1 + +This will create a 10TB sparse device called /dev/mapper/sparse1 that has +10GB of actual storage space available. If more than 10GB of data is written +to this device, it will start returning I/O errors. + diff -Nru a/Documentation/fb/sisfb.txt b/Documentation/fb/sisfb.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/fb/sisfb.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,158 @@ + +What is sisfb? +============== + +sisfb is a framebuffer device driver for SiS (Silicon Integrated Systems) +graphics chips. Supported are: + +- SiS 300 series: SiS 300/305, 540, 630(S), 730(S) +- SiS 315 series: SiS 315/H/PRO, 55x, (M)65x, 740, (M)661(F/M)X, (M)741(GX) +- SiS 330 series: SiS 330 ("Xabre"), (M)760 + + +Why do I need a framebuffer driver? +=================================== + +sisfb is eg. useful if you want a high-resolution text console. Besides that, +sisfb is required to run DirectFB (which comes with an additional, dedicated +driver for the 315 series). + +On the 300 series, sisfb on kernels older than 2.6.3 furthermore plays an +important role in connection with DRM/DRI: Sisfb manages the memory heap +used by DRM/DRI for 3D texture and other data. This memory management is +required for using DRI/DRM. + +Kernels >= around 2.6.3 do not need sisfb any longer for DRI/DRM memory +management. The SiS DRM driver has been updated and features a memory manager +of its own (which will be used if sisfb is not compiled). So unless you want +a graphical console, you don't need sisfb on kernels >=2.6.3. + +Sidenote: Since this seems to be a commonly made mistake: sisfb and vesafb +cannot be active at the same time! Do only select one of them in your kernel +configuration. + + +How are parameters passed to sisfb? +=================================== + +Well, it depends: If compiled statically into the kernel, use lilo's append +statement to add the parameters to the kernel command line. Please see lilo's +(or GRUB's) documentation for more information. If sisfb is a kernel module, +parameters are given with the modprobe (or insmod) command. + +Example for sisfb as part of the static kernel: Add the following line to your +lilo.conf: + + append="video=sisfb:mode:1024x768x16,mem:12288,rate:75" + +Example for sisfb as a module: Start sisfb by typing + + modprobe sisfb mode=1024x768x16 rate=75 mem=12288 + +A common mistake is that folks use a wrong parameter format when using the +driver compiled into the kernel. Please note: If compiled into the kernel, +the parameter format is video=sisfb:mode:none or video=sisfb:mode:1024x768x16 +(or whatever mode you want to use, alternatively using any other format +described above or the vesa keyword instead of mode). If compiled as a module, +the parameter format reads mode=none or mode=1024x768x16 (or whatever mode you +want to use). Using a "=" for a ":" (and vice versa) is a huge difference! +Additionally: If you give more than one argument to the in-kernel sisfb, the +arguments are separated with ",". For example: + + video=sisfb:mode:1024x768x16,rate:75,mem:12288 + + +How do I use it? +================ + +Preface statement: This file only covers very little of the driver's +capabilities and features. Please refer to the author's and maintainer's +website at http://www.winischhofer.net/linuxsisvga.shtml for more +information. Additionally, "modinfo sisfb" gives an overview over all +supported options including some explanation. + +The desired display mode can be specified using the keyword "mode" with +a parameter in one of the follwing formats: + - XxYxDepth or + - XxY-Depth or + - XxY-Depth@Rate or + - XxY + - or simply use the VESA mode number in hexadecimal or decimal. + +For example: 1024x768x16, 1024x768-16@75, 1280x1024-16. If no depth is +specified, it defaults to 8. If no rate is given, it defaults to 60Hz. Depth 32 +means 24bit color depth (but 32 bit framebuffer depth, which is not relevant +to the user). + +Additionally, sisfb understands the keyword "vesa" followed by a VESA mode +number in decimal or hexadecimal. For example: vesa=791 or vesa=0x117. Please +use either "mode" or "vesa" but not both. + +Linux 2.4 only: If no mode is given, sisfb defaults to "no mode" (mode=none) if +compiled as a module; if sisfb is statically compiled into the kernel, it +defaults to 800x600x8 unless CRT2 type is LCD, in which case the LCD's native +resolution is used. If you want to switch to a different mode, use the fbset +shell command. + +Linux 2.6 only: If no mode is given, sisfb defaults to 800x600x8 unless CRT2 +type is LCD, in which case it defaults to the LCD's native resolution. If +you want to switch to another mode, use the stty shell command. + +You should compile in both vgacon (to boot if you remove you SiS card from +your system) and sisfb (for graphics mode). Under Linux 2.6, also "Framebuffer +console support" (fbcon) is needed for a graphical console. + +You should *not* compile-in vesafb. And please do not use the "vga=" keyword +in lilo's or grub's configuration file; mode selection is done using the +"mode" or "vesa" keywords as a parameter. See above and below. + + +X11 +=== + +If using XFree86 or X.org, it is recommended that you don't use the "fbdev" +driver but the dedicated "sis" X driver. The "sis" X driver and sisfb are +developed by the same person (Thomas Winischhofer) and cooperate well with +each other. + + +SVGALib +======= + +SVGALib, if directly accessing the hardware, never restores the screen +correctly, especially on laptops or if the output devices are LCD or TV. +Therefore, use the chipset "FBDEV" in SVGALib configuration. This will make +SVGALib use the framebuffer device for mode switches and restoration. + + +Configuration +============= + +(Some) accepted options: + +off - Disable sisfb. This option is only understood if sisfb is + in-kernel, not a module. +mem:X - size of memory for the console, rest will be used for DRI/DRM. X + is in kilobytes. On 300 series, the default is 4096, 8192 or + 16384 (each in kilobyte) depending on how much video ram the card + has. On 315/330 series, the default is the maximum available ram + (since DRI/DRM is not supported for these chipsets). +noaccel - do not use 2D acceleration engine. (Default: use acceleration) +noypan - disable y-panning and scroll by redrawing the entire screen. + This is much slower than y-panning. (Default: use y-panning) +vesa:X - selects startup videomode. X is number from 0 to 0x1FF and + represents the VESA mode number (can be given in decimal or + hexadecimal form, the latter prefixed with "0x"). +mode:X - selects startup videomode. Please see above for the format of + "X". + +Boolean options such as "noaccel" or "noypan" are to be given without a +parameter if sisfb is in-kernel (for example "video=sisfb:noypan). If +sisfb is a module, these are to be set to 1 (for example "modprobe sisfb +noypan=1"). + +-- +Thomas Winischhofer +May 27, 2004 + + diff -Nru a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt --- a/Documentation/filesystems/hpfs.txt 2004-06-20 13:00:24 -07:00 +++ b/Documentation/filesystems/hpfs.txt 2004-06-20 13:00:24 -07:00 @@ -1,5 +1,5 @@ -Read/Write HPFS 2.05 -1998-2001, Mikulas Patocka +Read/Write HPFS 2.09 +1998-2004, Mikulas Patocka email: mikulas@artax.karlin.mff.cuni.cz homepage: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi @@ -283,6 +283,14 @@ 2.05 Fixed crash when got mount parameters without = Fixed crash when allocation of anode failed due to full disk Fixed some crashes when block io or inode allocation failed +2.06 Fixed some crash on corrupted disk structures + Better allocation strategy + Reschedule points added so that it doesn't lock CPU long time + It should work in read-only mode on Warp Server +2.07 More fixes for Warp Server. Now it really works +2.08 Creating new files is not so slow on large disks + An attempt to sync deleted file does not generate filesystem error +2.09 Fixed error on extremly fragmented files vim: set textwidth=80: diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt --- a/Documentation/filesystems/proc.txt 2004-06-20 13:00:23 -07:00 +++ b/Documentation/filesystems/proc.txt 2004-06-20 13:00:23 -07:00 @@ -201,7 +201,7 @@ devices Available devices (block and character) dma Used DMS channels filesystems Supported filesystems - driver Various drivers grouped here, currently rtc (2.4) + driver Various drivers grouped here, currently rtc (2.4) and hpet (2.6) execdomains Execdomains, related to security (2.4) fb Frame Buffer devices (2.4) fs File system parameters, currently nfs/exports (2.4) @@ -1640,7 +1640,8 @@ Writing to this file results in a flush of the routing cache. -gc_elastic, gc_interval, gc_min_interval, gc_tresh, gc_timeout +gc_elasticity, gc_interval, gc_min_interval, gc_tresh, gc_timeout, +gc_thresh, gc_thresh1, gc_thresh2, gc_thresh3 -------------------------------------------------------------- Values to control the frequency and behavior of the garbage collection diff -Nru a/Documentation/hpet.txt b/Documentation/hpet.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/hpet.txt 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,298 @@ + High Precision Event Timer Driver for Linux + +The High Precision Event Timer (HPET) hardware is the future replacement for the 8254 and Real +Time Clock (RTC) periodic timer functionality. Each HPET can have up two 32 timers. It is possible +to configure the first two timers as legacy replacements for 8254 and RTC periodic. A specification +done by INTEL and Microsoft can be found at http://www.intel.com/labs/platcomp/hpet/hpetspec.htm. + +The driver supports detection of HPET driver allocation and initialization of the HPET before the +driver module_init routine is called. This enables platform code which uses timer 0 or 1 as the +main timer to intercept HPET initialization. An example of this initialization can be found in +arch/i386/kernel/time_hpet.c. + +The driver provides two APIs which are very similar to the API found in the rtc.c driver. +There is a user space API and a kernel space API. An example user space program is provided +below. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern void hpet_open_close(int, const char **); +extern void hpet_info(int, const char **); +extern void hpet_poll(int, const char **); +extern void hpet_fasync(int, const char **); +extern void hpet_read(int, const char **); + +#include +#include +#include + +struct hpet_command { + char *command; + void (*func)(int argc, const char ** argv); +} hpet_command[] = { + { + "open-close", + hpet_open_close + }, + { + "info", + hpet_info + }, + { + "poll", + hpet_poll + }, + { + "fasync", + hpet_fasync + }, +}; + +int +main(int argc, const char ** argv) +{ + int i; + + argc--; + argv++; + + if (!argc) { + fprintf(stderr, "-hpet: requires command\n"); + return -1; + } + + + for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++) + if (!strcmp(argv[0], hpet_command[i].command)) { + argc--; + argv++; + fprintf(stderr, "-hpet: executing %s\n", + hpet_command[i].command); + hpet_command[i].func(argc, argv); + return 0; + } + + fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]); + + return -1; +} + +void +hpet_open_close(int argc, const char **argv) +{ + int fd; + + if (argc != 1) { + fprintf(stderr, "hpet_open_close: device-name\n"); + return; + } + + fd = open(argv[0], O_RDWR); + if (fd < 0) + fprintf(stderr, "hpet_open_close: open failed\n"); + else + close(fd); + + return; +} + +void +hpet_info(int argc, const char **argv) +{ +} + +void +hpet_poll(int argc, const char **argv) +{ + unsigned long freq; + int iterations, i, fd; + struct pollfd pfd; + struct hpet_info info; + struct timeval stv, etv; + struct timezone tz; + long usec; + + if (argc != 3) { + fprintf(stderr, "hpet_poll: device-name freq iterations\n"); + return; + } + + freq = atoi(argv[1]); + iterations = atoi(argv[2]); + + fd = open(argv[0], O_RDWR); + + if (fd < 0) { + fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]); + return; + } + + if (ioctl(fd, HPET_IRQFREQ, freq) < 0) { + fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n"); + goto out; + } + + if (ioctl(fd, HPET_INFO, &info) < 0) { + fprintf(stderr, "hpet_poll: failed to get info\n"); + goto out; + } + + fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags); + + if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) { + fprintf(stderr, "hpet_poll: HPET_EPI failed\n"); + goto out; + } + + if (ioctl(fd, HPET_IE_ON, 0) < 0) { + fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n"); + goto out; + } + + pfd.fd = fd; + pfd.events = POLLIN; + + for (i = 0; i < iterations; i++) { + pfd.revents = 0; + gettimeofday(&stv, &tz); + if (poll(&pfd, 1, -1) < 0) + fprintf(stderr, "hpet_poll: poll failed\n"); + else { + long data; + + gettimeofday(&etv, &tz); + usec = stv.tv_sec * 1000000 + stv.tv_usec; + usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec; + + fprintf(stderr, + "hpet_poll: expired time = 0x%lx\n", usec); + + fprintf(stderr, "hpet_poll: revents = 0x%x\n", + pfd.revents); + + if (read(fd, &data, sizeof(data)) != sizeof(data)) { + fprintf(stderr, "hpet_poll: read failed\n"); + } + else + fprintf(stderr, "hpet_poll: data 0x%lx\n", + data); + } + } + +out: + close(fd); + return; +} + +static int hpet_sigio_count; + +static void +hpet_sigio(int val) +{ + fprintf(stderr, "hpet_sigio: called\n"); + hpet_sigio_count++; +} + +void +hpet_fasync(int argc, const char **argv) +{ + unsigned long freq; + int iterations, i, fd, value; + sig_t oldsig; + struct hpet_info info; + + hpet_sigio_count = 0; + fd = -1; + + if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) { + fprintf(stderr, "hpet_fasync: failed to set signal handler\n"); + return; + } + + if (argc != 3) { + fprintf(stderr, "hpet_fasync: device-name freq iterations\n"); + goto out; + } + + fd = open(argv[0], O_RDWR); + + if (fd < 0) { + fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]); + return; + } + + + if ((fcntl(fd, F_SETOWN, getpid()) == 1) || + ((value = fcntl(fd, F_GETFL)) == 1) || + (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) { + fprintf(stderr, "hpet_fasync: fcntl failed\n"); + goto out; + } + + freq = atoi(argv[1]); + iterations = atoi(argv[2]); + + if (ioctl(fd, HPET_IRQFREQ, freq) < 0) { + fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n"); + goto out; + } + + if (ioctl(fd, HPET_INFO, &info) < 0) { + fprintf(stderr, "hpet_fasync: failed to get info\n"); + goto out; + } + + fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags); + + if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) { + fprintf(stderr, "hpet_fasync: HPET_EPI failed\n"); + goto out; + } + + if (ioctl(fd, HPET_IE_ON, 0) < 0) { + fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n"); + goto out; + } + + for (i = 0; i < iterations; i++) { + (void) pause(); + fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count); + } + +out: + signal(SIGIO, oldsig); + + if (fd >= 0) + close(fd); + + return; +} + +The kernel API has three interfaces exported from the driver: + + hpet_register(struct hpet_task *tp, int periodic) + hpet_unregister(struct hpet_task *tp) + hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) + +The kernel module using this interface fills in the ht_func and ht_data members of the +hpet_task structure before calling hpet_register. hpet_control simply vectors to the hpet_ioctl +routine and has the same commands and respective arguments as the user API. hpet_unregister +is used to terminate usage of the HPET timer reserved by hpet_register. + + diff -Nru a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt --- a/Documentation/ioctl-number.txt 2004-06-20 13:00:26 -07:00 +++ b/Documentation/ioctl-number.txt 2004-06-20 13:00:26 -07:00 @@ -189,3 +189,5 @@ 0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ +0xF3 00-3F video/sisfb.h sisfb (in development) + diff -Nru a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX --- a/Documentation/networking/00-INDEX 2004-06-20 13:00:25 -07:00 +++ b/Documentation/networking/00-INDEX 2004-06-20 13:00:25 -07:00 @@ -4,8 +4,6 @@ - information on the 3Com EtherLink Plus (3c505) driver. 6pack.txt - info on the 6pack protocol, an alternative to KISS for AX.25 -8139too.txt - - info on the 8139too driver for RTL-8139 based network cards. Configurable - info on some of the configurable network parameters DLINK.txt diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt --- a/Documentation/networking/ip-sysctl.txt 2004-06-20 13:00:24 -07:00 +++ b/Documentation/networking/ip-sysctl.txt 2004-06-20 13:00:24 -07:00 @@ -17,6 +17,16 @@ Disable Path MTU Discovery. default FALSE +min_pmtu - INTEGER + default 562 - minimum discovered Path MTU + +mtu_expires - INTEGER + Time, in seconds, that cached PMTU information is kept. + +min_adv_mss - INTEGER + The advertised MSS depends on the first hop route MTU, but will + never be lower than this setting. + IP Fragmentation: ipfrag_high_thresh - INTEGER @@ -345,6 +355,20 @@ conections. Default: 7 + +tcp_frto - BOOLEAN + Enables F-RTO, an enhanced recovery algorithm for TCP retransmission + timeouts. It is particularly beneficial in wireless environments + where packet loss is typically due to random radio interference + rather than intermediate router congestion. + +somaxconn - INTEGER + Limit of socket listen() backlog, known in userspace as SOMAXCONN. + Defaults to 128. See also tcp_max_syn_backlog for additional tuning + for TCP sockets. + +IP Variables: + ip_local_port_range - 2 INTEGERS Defines the local port range that is used by TCP and UDP to choose the local port. The first number is the first, the @@ -586,6 +610,19 @@ The max value from conf/{all,interface}/arp_ignore is used when ARP request is received on the {interface} +app_solicit - INTEGER + The maximum number of probes to send to the user space ARP daemon + via netlink before dropping back to multicast probes (see + mcast_solicit). Defaults to 0. + +disable_policy - BOOLEAN + Disable IPSEC policy (SPD) for this interface + +disable_xfrm - BOOLEAN + Disable IPSEC encryption on this interface, whatever the policy + + + tag - INTEGER Allows you to write a number, which can be used as required. Default value is 0. @@ -678,9 +715,11 @@ disabled if local forwarding is enabled. autoconf - BOOLEAN - Configure link-local addresses using L2 hardware addresses. + Autoconfigure addresses using Prefix Information in Router + Advertisements. - Default: TRUE + Functional default: enabled if accept_ra is enabled. + disabled if accept_ra is disabled. dad_transmits - INTEGER The amount of Duplicate Address Detection probes to send. @@ -803,5 +842,26 @@ 0 : disable this. Default: 1 + +UNDOCUMENTED: + +dev_weight FIXME +discovery_slots FIXME +discovery_timeout FIXME +fast_poll_increase FIXME +ip6_queue_maxlen FIXME +lap_keepalive_time FIXME +lo_cong FIXME +max_baud_rate FIXME +max_dgram_qlen FIXME +max_noreply_time FIXME +max_tx_data_size FIXME +max_tx_window FIXME +min_tx_turn_time FIXME +mod_cong FIXME +no_cong FIXME +no_cong_thresh FIXME +slot_timeout FIXME +warn_noreply_time FIXME $Id: ip-sysctl.txt,v 1.20 2001/12/13 09:00:18 davem Exp $ diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS 2004-06-20 13:00:25 -07:00 +++ b/MAINTAINERS 2004-06-20 13:00:25 -07:00 @@ -90,6 +90,20 @@ L: linux-net@vger.kernel.org S: Maintained +3W-XXXX ATA-RAID CONTROLLER DRIVER +P: Adam Radford +M: linuxraid@amcc.com +L: linux-scsi@vger.kernel.org +W: http://www.amcc.com +S: Supported + +3W-9XXX SATA-RAID CONTROLLER DRIVER +P: Adam Radford +M: linuxraid@amcc.com +L: linux-scsi@vger.kernel.org +W: http://www.amcc.com +S: Supported + 53C700 AND 53C700-66 SCSI DRIVER P: James E.J. Bottomley M: James.Bottomley@HansenPartnership.com @@ -1249,6 +1263,13 @@ M: benh@kernel.crashing.org W: http://www.linuxppc.org/ L: linuxppc-dev@lists.linuxppc.org +S: Maintained + +LINUX FOR POWERPC EMBEDDED PPC4XX +P: Matt Porter +M: mporter@kernel.crashing.org +W: http://www.penguinppc.org/ +L: linuxppc-embedded@lists.linuxppc.org S: Maintained LLC (802.2) diff -Nru a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c --- a/arch/alpha/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/alpha/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -4,6 +4,7 @@ #include #include #include +#include #include diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c --- a/arch/alpha/mm/numa.c 2004-06-20 13:00:23 -07:00 +++ b/arch/alpha/mm/numa.c 2004-06-20 13:00:23 -07:00 @@ -279,8 +279,8 @@ initrd_end, phys_to_virt(PFN_PHYS(max_low_pfn))); } else { - nid = NODE_DATA(kvaddr_to_nid(initrd_start)); - reserve_bootmem_node(nid, + nid = kvaddr_to_nid(initrd_start); + reserve_bootmem_node(NODE_DATA(nid), virt_to_phys((void *)initrd_start), INITRD_SIZE); } diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/Kconfig 2004-06-20 13:00:24 -07:00 @@ -246,10 +246,10 @@ # Select various configuration options depending on the machine type config DISCONTIGMEM bool - depends on ARCH_EDB7211 || ARCH_SA1100 || ARCH_LH7A40X + depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_SROMLL) default y help - Say Y to upport efficient handling of discontiguous physical memory, + Say Y to support efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access) or have huge holes in the physical address space for other reasons. See for more. @@ -257,7 +257,7 @@ # Now handle the bus types config PCI bool "PCI support" if ARCH_INTEGRATOR_AP - default y if ARCH_FTVPCI || ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX + default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside @@ -270,11 +270,6 @@ doesn't. # Select the host bridge type -config PCI_HOST_PLX90X0 - bool - depends on PCI && ARCH_FTVPCI - default y - config PCI_HOST_VIA82C505 bool depends on PCI && ARCH_SHARK @@ -421,6 +416,17 @@ If you do not feel you need a faster FP emulation you should better choose NWFPE. +config VFP + bool "VFP-format floating point maths" + help + Say Y to include VFP support code in the kernel. This is needed + if your hardware includes a VFP unit. + + Please see for + release notes and additional status information. + + Say N if your target does not have VFP hardware. + source "fs/Kconfig.binfmt" source "drivers/base/Kconfig" @@ -539,7 +545,7 @@ config LEDS bool "Timer and CPU usage LEDs" - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB + depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. @@ -553,7 +559,7 @@ config LEDS_TIMER bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB) - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_FTVPCI || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB + depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB default y if ARCH_EBSA110 help If you say Y here, one of the system LEDs (the green one on the @@ -609,7 +615,7 @@ source "net/Kconfig" -if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_FTVPCI || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE +if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE source "drivers/ide/Kconfig" endif diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile --- a/arch/arm/Makefile 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/Makefile 2004-06-20 13:00:24 -07:00 @@ -74,9 +74,6 @@ textaddr-$(CONFIG_ARCH_CO285) := 0x60008000 machine-$(CONFIG_ARCH_CO285) := footbridge incdir-$(CONFIG_ARCH_CO285) := ebsa285 - machine-$(CONFIG_ARCH_FTVPCI) := ftvpci - incdir-$(CONFIG_ARCH_FTVPCI) := nexuspci - machine-$(CONFIG_ARCH_TBOX) := tbox machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SA1100) := sa1100 ifeq ($(CONFIG_ARCH_SA1100),y) @@ -119,6 +116,7 @@ endif core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) +core-$(CONFIG_VFP) += arch/arm/vfp/ drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ diff -Nru a/arch/arm/common/Makefile b/arch/arm/common/Makefile --- a/arch/arm/common/Makefile 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/common/Makefile 2004-06-20 13:00:24 -07:00 @@ -6,6 +6,5 @@ obj-$(CONFIG_ARM_AMBA) += amba.o obj-$(CONFIG_ICST525) += icst525.o obj-$(CONFIG_SA1111) += sa1111.o -obj-$(CONFIG_PCI_HOST_PLX90X0) += plx90x0.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff -Nru a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c --- a/arch/arm/common/dmabounce.c 2004-06-20 13:00:23 -07:00 +++ b/arch/arm/common/dmabounce.c 2004-06-20 13:00:23 -07:00 @@ -234,7 +234,7 @@ } } - dma_addr = virt_to_bus(ptr); + dma_addr = virt_to_dma(dev, ptr); if (device_info && dma_needs_bounce(dev, dma_addr, size)) { struct safe_buffer *buf; @@ -248,7 +248,7 @@ dev_dbg(dev, "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - __func__, buf->ptr, (void *) virt_to_bus(buf->ptr), + __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); if ((dir == DMA_TO_DEVICE) || @@ -290,7 +290,7 @@ dev_dbg(dev, "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - __func__, buf->ptr, (void *) virt_to_bus(buf->ptr), + __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); @@ -342,7 +342,7 @@ dev_dbg(dev, "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", - __func__, buf->ptr, (void *) virt_to_bus(buf->ptr), + __func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr), buf->safe, (void *) buf->safe_dma_addr); DO_STATS ( device_info->bounce_count++ ); @@ -367,7 +367,7 @@ } consistent_sync(buf->safe, size, dir); } else { - consistent_sync(bus_to_virt(dma_addr), size, dir); + consistent_sync(dma_to_virt(dev, dma_addr), size, dir); } } diff -Nru a/arch/arm/common/plx90x0.c b/arch/arm/common/plx90x0.c --- a/arch/arm/common/plx90x0.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,178 +0,0 @@ -/* - * Driver for PLX Technology PCI9000-series host bridge. - * - * Copyright (C) 1997, 1998, 1999, 2000 FutureTV Labs Ltd - */ - -/* - * 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. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Since the following functions are all very similar, the common parts - * are pulled out into these macros. - */ - -#define PLX_CLEAR_CONFIG \ - __raw_writel(0, PLX_BASE + 0xac); \ - local_irq_restore(flags); } - -#define PLX_SET_CONFIG \ - { unsigned long flags; \ - local_irq_save(flags); \ - __raw_writel((1<<31 | (bus->number << 16) \ - | (devfn << 8) | (where & ~3) \ - | ((bus->number == 0)?0:1)), PLX_BASE + 0xac); \ - -#define PLX_CONFIG_WRITE(size) \ - PLX_SET_CONFIG \ - __raw_write##size(value, PCIO_BASE + (where & 3)); \ - if (__raw_readw(PLX_BASE + 0x6) & 0x2000) \ - __raw_writew(0x2000, PLX_BASE + 0x6); \ - PLX_CLEAR_CONFIG \ - return PCIBIOS_SUCCESSFUL; - -#define PLX_CONFIG_READ(size) \ - PLX_SET_CONFIG \ - *value = __raw_read##size(PCIO_BASE + (where & 3)); \ - if (__raw_readw(PLX_BASE + 0x6) & 0x2000) { \ - __raw_writew(0x2000, PLX_BASE + 0x6); \ - *value = 0xffffffffUL; \ - } \ - PLX_CLEAR_CONFIG \ - return PCIBIOS_SUCCESSFUL; - -/* Configuration space access routines */ - -static int -plx90x0_read_config (struct pci_bus *bus, unsigned int devfn, int where, - int where, int size, u32 *value) -{ - switch (size) { - case 1: - PLX_CONFIG_READ(b) - break; - case 2: - PLX_CONFIG_READ(w) - break; - case 4: - PLX_CONFIG_READ(l) - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int -plx90x0_write_config (struct pci_bus *bus, unsigned int devfn, int where, - int where, int size, u32 value) -{ - switch (size) { - case 1: - PLX_CONFIG_WRITE(b) - break; - case 2: - PLX_CONFIG_WRITE(w) - break; - case 4: - PLX_CONFIG_WRITE(l) - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops plx90x0_ops = -{ - .read = plx90x0_read_config, - .write = plx90x0_write_config, -}; - -static void -plx_syserr_handler(int irq, void *handle, struct pt_regs *regs) -{ - printk("PLX90x0: machine check %04x (pc=%08lx)\n", - readw(PLX_BASE + 6), regs->ARM_pc); - __raw_writew(0xf000, PLX_BASE + 6); -} - -/* - * Initialise the PCI system. - */ - -void __init -plx90x0_init(struct arm_sysdata *sysdata) -{ - static const unsigned long int base = PLX_BASE; - char *what; - unsigned long bar = (unsigned long)virt_to_bus((void *)PAGE_OFFSET); - - /* Have a sniff around and see which PLX device is present. */ - unsigned long id = __raw_readl(base + 0xf0); - -#if 0 - /* This check was a good idea, but can fail. The PLX9060 puts no - default value in these registers unless NB# is asserted (which it - isn't on these cards). */ - if ((id & 0xffff) != PCI_VENDOR_ID_PLX) - return; /* Nothing found */ -#endif - - /* Found one - now work out what it is. */ - switch (id >> 16) { - case 0: /* PCI_DEVICE_ID_PLX_9060 */ - what = "PCI9060"; - break; - case PCI_DEVICE_ID_PLX_9060ES: - what = "PCI9060ES"; - break; - case PCI_DEVICE_ID_PLX_9060SD: - what = "PCI9060SD"; /* uhuhh.. */ - break; - case PCI_DEVICE_ID_PLX_9080: - what = "PCI9080"; - break; - default: - printk("PCI: Unknown PLX device %04lx found -- ignored.\n", - id >> 16); - return; - } - - printk("PCI: PLX Technology %s host bridge found.\n", what); - - /* Now set it up for both master and slave accesses. */ - __raw_writel(0xffff0147, base + 0x4); - __raw_writeb(32, base + 0xd); - __raw_writel(0x8 | bar, base + 0x18); - __raw_writel(0xf8000008, base + 0x80); - __raw_writel(0x40000001, base + 0x84); - __raw_writel(0, base + 0x88); - __raw_writel(0, base + 0x8c); - __raw_writel(0x11, base + 0x94); - __raw_writel(0xC3 + (4 << 28) - + (8 << 11) + (1 << 10) - + (1 << 24), base + 0x98); - __raw_writel(0xC0000000, base + 0x9c); - __raw_writel(PLX_MEM_START, base + 0xa0); - __raw_writel(PLX_IO_START, base + 0xa4); - __raw_writel(0x3, base + 0xa8); - __raw_writel(0, base + 0xac); - __raw_writel(0x10001, base + 0xe8); - __raw_writel(0x8000767e, base + 0xec); - - request_irq(IRQ_SYSERR, plx_syserr_handler, 0, - "system error", NULL); - - pci_scan_bus(0, &plx90x0_ops, sysdata); -} diff -Nru a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S --- a/arch/arm/kernel/debug.S 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/kernel/debug.S 2004-06-20 13:00:24 -07:00 @@ -591,7 +591,8 @@ .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? - ldr \rx, =0x80000700 @ physical base address + mov \rx, #0x00000700 @ offset from base + orreq \rx, \rx, #0x80000000 @ physical base orrne \rx, \rx, #0xf8000000 @ virtual base .endm diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/kernel/entry-armv.S 2004-06-20 13:00:24 -07:00 @@ -19,6 +19,7 @@ #include #include #include +#include #include "entry-header.S" @@ -1198,8 +1199,13 @@ mov pc, lr @ CP#7 mov pc, lr @ CP#8 mov pc, lr @ CP#9 +#ifdef CONFIG_VFP + b do_vfp @ CP#10 (VFP) + b do_vfp @ CP#11 (VFP) +#else mov pc, lr @ CP#10 (VFP) mov pc, lr @ CP#11 (VFP) +#endif mov pc, lr @ CP#12 mov pc, lr @ CP#13 mov pc, lr @ CP#14 (Debug) @@ -1260,6 +1266,13 @@ ldr r3, [r2, #TI_CPU_DOMAIN]! stmia ip, {r4 - sl, fp, sp, lr} @ Store most regs on stack mcr p15, 0, r3, c3, c0, 0 @ Set domain register +#ifdef CONFIG_VFP + @ Always disable VFP so we can lazily save/restore the old + @ state. This occurs in the context of the previous thread. + VFPFMRX r4, FPEXC + bic r4, r4, #FPEXC_ENABLE + VFPFMXR FPEXC, r4 +#endif ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously __INIT diff -Nru a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c --- a/arch/arm/kernel/init_task.c 2004-06-20 13:00:25 -07:00 +++ b/arch/arm/kernel/init_task.c 2004-06-20 13:00:25 -07:00 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c --- a/arch/arm/kernel/process.c 2004-06-20 13:00:25 -07:00 +++ b/arch/arm/kernel/process.c 2004-06-20 13:00:25 -07:00 @@ -314,10 +314,16 @@ memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); fp_init(&thread->fpstate); +#if defined(CONFIG_VFP) + vfp_flush_thread(&thread->vfpstate); +#endif } void release_thread(struct task_struct *dead_task) { +#if defined(CONFIG_VFP) + vfp_release_thread(&dead_task->thread_info->vfpstate); +#endif } asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c --- a/arch/arm/kernel/traps.c 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/kernel/traps.c 2004-06-20 13:00:24 -07:00 @@ -426,7 +426,7 @@ /* * Flush a region from virtual address 'r0' to virtual address 'r1' - * _inclusive_. There is no alignment requirement on either address; + * _exclusive_. There is no alignment requirement on either address; * user space does not need to know the hardware cache layout. * * r2 contains flags. It should ALWAYS be passed as ZERO until it diff -Nru a/arch/arm/mach-ftvpci/Makefile b/arch/arm/mach-ftvpci/Makefile --- a/arch/arm/mach-ftvpci/Makefile 2004-06-20 13:00:26 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,13 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := core.o -obj-m := -obj-n := -obj- := - -obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_LEDS) += leds.o diff -Nru a/arch/arm/mach-ftvpci/core.c b/arch/arm/mach-ftvpci/core.c --- a/arch/arm/mach-ftvpci/core.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,96 +0,0 @@ -/* - * linux/arch/arm/mach-ftvpci/core.c - * - * Architecture specific fixups. - * - * 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. - */ -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -extern unsigned long soft_irq_mask; - -static const unsigned char irq_cmd[] = -{ - INTCONT_IRQ_DUART, - INTCONT_IRQ_PLX, - INTCONT_IRQ_D, - INTCONT_IRQ_C, - INTCONT_IRQ_B, - INTCONT_IRQ_A, - INTCONT_IRQ_SYSERR -}; - -static void ftvpci_mask_irq(unsigned int irq) -{ - __raw_writel(irq_cmd[irq], INTCONT_BASE); - soft_irq_mask &= ~(1<= FIRST_IRQ && i <= LAST_IRQ) { - irq_desc[i].valid = 1; - irq_desc[i].probe_ok = 1; - irq_desc[i].mask_ack = ftvpci_mask_irq; - irq_desc[i].mask = ftvpci_mask_irq; - irq_desc[i].unmask = ftvpci_unmask_irq; - ftvpci_mask_irq(i); - } else { - irq_desc[i].valid = 0; - irq_desc[i].probe_ok = 0; - } - } -} - -static struct map_desc ftvpci_io_desc[] __initdata = { - { INTCONT_BASE, INTCONT_START, 0x00001000, MT_DEVICE }, - { PLX_BASE, PLX_START, 0x00001000, MT_DEVICE }, - { PCIO_BASE, PLX_IO_START, 0x00100000, MT_DEVICE }, - { DUART_BASE, DUART_START, 0x00001000, MT_DEVICE }, - { STATUS_BASE, STATUS_START, 0x00001000, MT_DEVICE } -}; - -static void __init ftvpci_map_io(void) -{ - iotable_init(ftvpci_io_desc, ARRAY_SIZE(ftvpci_io_desc)); -} - -MACHINE_START(NEXUSPCI, "FTV/PCI") - MAINTAINER("Philip Blundell") - BOOT_MEM(0x40000000, 0x10000000, 0xe0000000) - MAPIO(ftvpci_map_io) - INITIRQ(ftvpci_init_irq) -MACHINE_END diff -Nru a/arch/arm/mach-ftvpci/leds.c b/arch/arm/mach-ftvpci/leds.c --- a/arch/arm/mach-ftvpci/leds.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/kernel/leds-ftvpci.c - * - * Copyright (C) 1999 FutureTV Labs Ltd - */ - -#include -#include - -#include -#include -#include -#include - -static void ftvpci_leds_event(led_event_t ledevt) -{ - static int led_state = 0; - - switch(ledevt) { - case led_timer: - led_state ^= 1; - raw_writeb(0x1a | led_state, INTCONT_BASE); - break; - - default: - break; - } -} - -static int __init ftvpci_leds_init(void) -{ - leds_event = ftvpci_leds_event; - return 0; -} - -arch_initcall(ftvpci_leds_init); diff -Nru a/arch/arm/mach-ftvpci/pci.c b/arch/arm/mach-ftvpci/pci.c --- a/arch/arm/mach-ftvpci/pci.c 2004-06-20 13:00:26 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,60 +0,0 @@ -/* - * linux/arch/arm/kernel/ftv-pci.c - * - * PCI bios-type initialisation for PCI machines - * - * Bits taken from various places. - */ -#include -#include -#include - -#include -#include -#include - -/* - * Owing to a PCB cockup, issue A backplanes are wired thus: - * - * Slot 1 2 3 4 5 Bridge S1 S2 S3 S4 - * IRQ D C B A A C B A D - * A D C B B D C B A - * B A D C C A D C B - * C B A D D B A D C - * - * ID A31 A30 A29 A28 A27 A26 DEV4 DEV5 DEV6 DEV7 - * - * Actually, this isn't too bad, because with the processor card - * in slot 5 on the primary bus, the IRQs rotate on both sides - * as you'd expect. - */ - -static int irqmap_ftv[] __initdata = { IRQ_PCI_D, IRQ_PCI_C, IRQ_PCI_B, IRQ_PCI_A }; - -static int __init ftv_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - if (slot > 0x10) - slot--; - return irqmap_ftv[(slot - pin) & 3]; -} - -static u8 __init ftv_swizzle(struct pci_dev *dev, u8 *pin) -{ - return PCI_SLOT(dev->devfn); -} - -/* ftv host-specific stuff */ -static struct hw_pci ftv_pci __initdata = { - .init = plx90x0_init, - .swizzle = ftv_swizzle, - .map_irq = ftv_map_irq, -}; - -static int __init ftv_pci_init(void) -{ - if (machine_is_ftvpci()) - pci_common_init(&ftv_pci); - return 0; -} - -subsys_initcall(ftv_pci_init); diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile --- a/arch/arm/mach-integrator/Makefile 2004-06-20 13:00:25 -07:00 +++ b/arch/arm/mach-integrator/Makefile 2004-06-20 13:00:25 -07:00 @@ -4,7 +4,7 @@ # Object file lists. -obj-y := core.o lm.o time.o +obj-y := clock.o core.o lm.o time.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o diff -Nru a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/mach-integrator/clock.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,138 @@ +/* + * linux/arch/arm/mach-integrator/clock.c + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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 "clock.h" + +static LIST_HEAD(clocks); +static DECLARE_MUTEX(clocks_sem); + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *p, *clk = ERR_PTR(-ENOENT); + + down(&clocks_sem); + list_for_each_entry(p, &clocks, node) { + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + break; + } + } + up(&clocks_sem); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + module_put(clk->owner); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +int clk_use(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_use); + +void clk_unuse(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_unuse); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EIO; + if (clk->setvco) { + struct icst525_vco vco; + + vco = icst525_khz_to_vco(clk->params, rate); + clk->rate = icst525_khz(clk->params, vco); + + printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", + clk->name, vco.s, vco.r, vco.v); + + clk->setvco(clk, vco); + ret = 0; + } + return 0; +} +EXPORT_SYMBOL(clk_set_rate); + +/* + * These are fixed clocks. + */ +static struct clk kmi_clk = { + .name = "KMIREFCLK", + .rate = 24000000, +}; + +static struct clk uart_clk = { + .name = "UARTCLK", + .rate = 14745600, +}; + +int clk_register(struct clk *clk) +{ + down(&clocks_sem); + list_add(&clk->node, &clocks); + up(&clocks_sem); + return 0; +} +EXPORT_SYMBOL(clk_register); + +void clk_unregister(struct clk *clk) +{ + down(&clocks_sem); + list_del(&clk->node); + up(&clocks_sem); +} +EXPORT_SYMBOL(clk_unregister); + +static int __init clk_init(void) +{ + clk_register(&kmi_clk); + clk_register(&uart_clk); + return 0; +} +arch_initcall(clk_init); diff -Nru a/arch/arm/mach-integrator/clock.h b/arch/arm/mach-integrator/clock.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/mach-integrator/clock.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/mach-integrator/clock.h + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + */ +struct module; +struct icst525_params; + +struct clk { + struct list_head node; + unsigned long rate; + struct module *owner; + const char *name; + const struct icst525_params *params; + void *data; + void (*setvco)(struct clk *, struct icst525_vco vco); +}; + +int clk_register(struct clk *clk); +void clk_unregister(struct clk *clk); diff -Nru a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c --- a/arch/arm/mach-integrator/impd1.c 2004-06-20 13:00:24 -07:00 +++ b/arch/arm/mach-integrator/impd1.c 2004-06-20 13:00:24 -07:00 @@ -25,13 +25,16 @@ #include #include +#include "clock.h" + static int module_id; module_param_named(lmid, module_id, int, 0444); MODULE_PARM_DESC(lmid, "logic module stack position"); struct impd1_module { - void *base; + void *base; + struct clk vcos[2]; }; static const struct icst525_params impd1_vco_params = { @@ -43,25 +46,20 @@ .rd_max = 120, }; -void impd1_set_vco(struct device *dev, int vconr, unsigned long period) +static void impd1_setvco(struct clk *clk, struct icst525_vco vco) { - struct impd1_module *impd1 = dev_get_drvdata(dev); - struct icst525_vco vco; + struct impd1_module *impd1 = clk->data; + int vconr = clk - impd1->vcos; u32 val; - vco = icst525_ps_to_vco(&impd1_vco_params, period); - - pr_debug("Guessed VCO reg params: S=%d R=%d V=%d\n", - vco.s, vco.r, vco.v); - val = vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, impd1->base + IMPD1_LOCK); switch (vconr) { - case 1: + case 0: writel(val, impd1->base + IMPD1_OSC1); break; - case 2: + case 1: writel(val, impd1->base + IMPD1_OSC2); break; } @@ -77,8 +75,6 @@ #endif } -EXPORT_SYMBOL(impd1_set_vco); - void impd1_tweak_control(struct device *dev, u32 mask, u32 val) { struct impd1_module *impd1 = dev_get_drvdata(dev); @@ -140,6 +136,11 @@ } }; +static const char *impd1_vconames[2] = { + "CLCDCLK", + "AUXVCO2", +}; + static int impd1_probe(struct lm_device *dev) { struct impd1_module *impd1; @@ -168,6 +169,16 @@ printk("IM-PD1 found at 0x%08lx\n", dev->resource.start); + for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { + impd1->vcos[i].owner = THIS_MODULE, + impd1->vcos[i].name = impd1_vconames[i], + impd1->vcos[i].params = &impd1_vco_params, + impd1->vcos[i].data = impd1, + impd1->vcos[i].setvco = impd1_setvco; + + clk_register(&impd1->vcos[i]); + } + for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) { struct impd1_device *idev = impd1_devs + i; struct amba_device *d; @@ -216,12 +227,16 @@ { struct impd1_module *impd1 = lm_get_drvdata(dev); struct list_head *l, *n; + int i; list_for_each_safe(l, n, &dev->dev.children) { struct device *d = list_to_dev(l); device_unregister(d); } + + for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) + clk_unregister(&impd1->vcos[i]); lm_set_drvdata(dev, NULL); diff -Nru a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c --- a/arch/arm/mach-integrator/integrator_cp.c 2004-06-20 13:00:25 -07:00 +++ b/arch/arm/mach-integrator/integrator_cp.c 2004-06-20 13:00:25 -07:00 @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -32,12 +33,16 @@ #include #include +#include "clock.h" + #define INTCP_PA_MMC_BASE 0x1c000000 #define INTCP_PA_AACI_BASE 0x1d000000 #define INTCP_PA_FLASH_BASE 0x24000000 #define INTCP_FLASH_SIZE SZ_32M +#define INTCP_PA_CLCD_BASE 0xc0000000 + #define INTCP_VA_CIC_BASE 0xf1000040 #define INTCP_VA_PIC_BASE 0xf1400000 #define INTCP_VA_SIC_BASE 0xfca00000 @@ -210,6 +215,44 @@ } /* + * Clock handling + */ +#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET) +#define CM_AUXOSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+0x1c) + +static const struct icst525_params cp_auxvco_params = { + .ref = 24000, + .vco_max = 320000, + .vd_min = 8, + .vd_max = 263, + .rd_min = 3, + .rd_max = 65, +}; + +static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco) +{ + u32 val; + + val = readl(CM_AUXOSC) & ~0x7ffff; + val |= vco.v | (vco.r << 9) | (vco.s << 16); + + writel(0xa05f, CM_LOCK); + writel(val, CM_AUXOSC); + writel(0, CM_LOCK); +} + +static struct clk cp_clcd_clk = { + .name = "CLCDCLK", + .params = &cp_auxvco_params, + .setvco = cp_auxvco_set, +}; + +static struct clk cp_mmci_clk = { + .name = "MCLK", + .rate = 33000000, +}; + +/* * Flash handling. */ static int intcp_flash_init(void) @@ -340,14 +383,33 @@ .periphid = 0, }; +static struct amba_device clcd_device = { + .dev = { + .bus_id = "mb:c0", + .coherent_dma_mask = ~0, + }, + .res = { + .start = INTCP_PA_CLCD_BASE, + .end = INTCP_PA_CLCD_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .dma_mask = ~0, + .irq = { IRQ_CP_CLCDCINT, NO_IRQ }, + .periphid = 0, +}; + static struct amba_device *amba_devs[] __initdata = { &mmc_device, &aaci_device, + &clcd_device, }; static void __init intcp_init(void) { int i; + + clk_register(&cp_clcd_clk); + clk_register(&cp_mmci_clk); platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); diff -Nru a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig --- a/arch/arm/mach-lh7a40x/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/arch/arm/mach-lh7a40x/Kconfig 2004-06-20 13:00:25 -07:00 @@ -34,6 +34,37 @@ config ARCH_LH7A404 bool +config LH7A40X_CONTIGMEM + bool "Disable NUMA Support" + depends on ARCH_LH7A40X + help + Say Y here if your bootloader sets the SROMLL bit(s) in + the SDRAM controller, organizing memory as a contiguous + array. This option will disable CONFIG_DISCONTIGMEM and + force the kernel to manage all memory in one node. + + Setting this option incorrectly may prevent the kernel from + booting. It is OK to leave it N. + + For more information, consult + . + +config LH7A40X_ONE_BANK_PER_NODE + bool "Optimize NUMA Node Tables for Size" + depends on ARCH_LH7A40X && !LH7A40X_CONTIGMEM + help + Say Y here to produce compact memory node tables. By + default pairs of adjacent physical RAM banks are managed + together in a single node, incurring some wasted overhead + in the node tables, however also maintaining compatibility + with systems where physical memory is truly contiguous. + + Setting this option incorrectly may prevent the kernel from + booting. It is OK to leave it N. + + For more information, consult + . + endmenu endif diff -Nru a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c --- a/arch/arm/mach-pxa/generic.c 2004-06-20 13:00:23 -07:00 +++ b/arch/arm/mach-pxa/generic.c 2004-06-20 13:00:23 -07:00 @@ -59,6 +59,24 @@ EXPORT_SYMBOL(pxa_gpio_mode); /* + * Routine to safely enable or disable a clock in the CKEN + */ +void pxa_set_cken(int clock, int enable) +{ + unsigned long flags; + local_irq_save(flags); + + if (enable) + CKEN |= clock; + else + CKEN &= ~clock; + + local_irq_restore(flags); +} + +EXPORT_SYMBOL(pxa_set_cken); + +/* * Intel PXA2xx internal register mapping. * * Note 1: not all PXA2xx variants implement all those addresses. diff -Nru a/arch/arm/mach-tbox/Makefile b/arch/arm/mach-tbox/Makefile --- a/arch/arm/mach-tbox/Makefile 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,11 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. - -obj-y := core.o -obj-m := -obj-n := -obj- := - diff -Nru a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c --- a/arch/arm/mach-tbox/core.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,73 +0,0 @@ -/* - * linux/arch/arm/mm/mm-tbox.c - * - * Copyright (C) 1998, 1999, 2000 Phil Blundell - * Copyright (C) 1998-1999 Russell King - * - * Extra MM routines for the Tbox architecture - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -extern unsigned long soft_irq_mask; - -static void tbox_mask_irq(unsigned int irq) -{ - __raw_writel(0, INTCONT + (irq << 2)); - soft_irq_mask &= ~(1<= 12 && i <= 13)) { - irq_desc[i].valid = 1; - irq_desc[i].probe_ok = 0; - irq_desc[i].mask_ack = tbox_mask_irq; - irq_desc[i].mask = tbox_mask_irq; - irq_desc[i].unmask = tbox_unmask_irq; - tbox_mask_irq(i); - } else { - irq_desc[i].valid = 0; - irq_desc[i].probe_ok = 0; - } - } -} - -static struct map_desc tbox_io_desc[] __initdata = { - /* See hardware.h for details */ - { IO_BASE, IO_START, 0x00100000, MT_DEVICE } -}; - -static void __init tbox_map_io(void) -{ - iotable_init(tbox_io_desc, ARRAY_SIZE(tbox_io_desc)); -} - -MACHINE_START(TBOX, "unknown-TBOX") - MAINTAINER("Philip Blundell") - BOOT_MEM(0x80000000, 0x00400000, 0xe0000000) - MAPIO(tbox_map_io) - INITIRQ(tbox_init_irq) -MACHINE_END - diff -Nru a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile --- a/arch/arm/mach-versatile/Makefile 2004-06-20 13:00:23 -07:00 +++ b/arch/arm/mach-versatile/Makefile 2004-06-20 13:00:23 -07:00 @@ -2,4 +2,4 @@ # Makefile for the linux kernel. # -obj-y := core.o +obj-y := core.o clock.o diff -Nru a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/mach-versatile/clock.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,146 @@ +/* + * linux/arch/arm/mach-versatile/clock.c + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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 "clock.h" + +static LIST_HEAD(clocks); +static DECLARE_MUTEX(clocks_sem); + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *p, *clk = ERR_PTR(-ENOENT); + + down(&clocks_sem); + list_for_each_entry(p, &clocks, node) { + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + break; + } + } + up(&clocks_sem); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + module_put(clk->owner); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +int clk_use(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_use); + +void clk_unuse(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_unuse); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EIO; +#if 0 // Not yet + if (clk->setvco) { + struct icst525_vco vco; + + vco = icst525_khz_to_vco(clk->params, rate); + clk->rate = icst525_khz(clk->params, vco); + + printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", + clk->name, vco.s, vco.r, vco.v); + + clk->setvco(clk, vco); + ret = 0; + } +#endif + return 0; +} +EXPORT_SYMBOL(clk_set_rate); + +/* + * These are fixed clocks. + */ +static struct clk kmi_clk = { + .name = "KMIREFCLK", + .rate = 24000000, +}; + +static struct clk uart_clk = { + .name = "UARTCLK", + .rate = 24000000, +}; + +static struct clk mmci_clk = { + .name = "MCLK", + .rate = 33000000, +}; + +int clk_register(struct clk *clk) +{ + down(&clocks_sem); + list_add(&clk->node, &clocks); + up(&clocks_sem); + return 0; +} +EXPORT_SYMBOL(clk_register); + +void clk_unregister(struct clk *clk) +{ + down(&clocks_sem); + list_del(&clk->node); + up(&clocks_sem); +} +EXPORT_SYMBOL(clk_unregister); + +static int __init clk_init(void) +{ + clk_register(&kmi_clk); + clk_register(&uart_clk); + clk_register(&mmci_clk); + return 0; +} +arch_initcall(clk_init); diff -Nru a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/mach-versatile/clock.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/mach-versatile/clock.h + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + */ +struct module; +struct icst525_params; + +struct clk { + struct list_head node; + unsigned long rate; + struct module *owner; + const char *name; + const struct icst525_params *params; + void *data; + void (*setvco)(struct clk *, struct icst525_vco vco); +}; + +int clk_register(struct clk *clk); +void clk_unregister(struct clk *clk); diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c --- a/arch/arm/mm/consistent.c 2004-06-20 13:00:25 -07:00 +++ b/arch/arm/mm/consistent.c 2004-06-20 13:00:25 -07:00 @@ -194,7 +194,7 @@ /* * Set the "dma handle" */ - *handle = page_to_bus(page); + *handle = page_to_dma(dev, page); do { BUG_ON(!pte_none(*pte)); diff -Nru a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/Makefile 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,12 @@ +# +# linux/arch/arm/vfp/Makefile +# +# Copyright (C) 2001 ARM Limited +# + +# EXTRA_CFLAGS := -DDEBUG +# EXTRA_AFLAGS := -DDEBUG + +obj-y += vfp.o + +vfp-$(CONFIG_VFP) += entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o diff -Nru a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/entry.S 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,45 @@ +/* + * linux/arch/arm/vfp/entry.S + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + * + * Basic entry code, called from the kernel's undefined instruction trap. + * r0 = faulted instruction + * r5 = faulted PC+4 + * r9 = successful return + * r10 = thread_info structure + * lr = failure return + */ +#include +#include +#include +#include + + .globl do_vfp +do_vfp: + ldr r4, .LCvfp + add r10, r10, #TI_VFPSTATE @ r10 = workspace + ldr pc, [r4] @ call VFP entry point + +.LCvfp: + .word vfp_vector + +@ This code is called if the VFP does not exist. It needs to flag the +@ failure to the VFP initialisation code. + + __INIT + .globl vfp_testing_entry +vfp_testing_entry: + ldr r0, VFP_arch_address + str r5, [r0] @ known non-zero value + mov pc, r9 @ we have handled the fault + +VFP_arch_address: + .word VFP_arch + + __FINIT diff -Nru a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/vfp.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,333 @@ +/* + * linux/arch/arm/vfp/vfp.h + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + */ + +static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) +{ + if (shift) { + if (shift < 32) + val = val >> shift | ((val << (32 - shift)) != 0); + else + val = val != 0; + } + return val; +} + +static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) +{ + if (shift) { + if (shift < 64) + val = val >> shift | ((val << (64 - shift)) != 0); + else + val = val != 0; + } + return val; +} + +static inline u32 vfp_hi64to32jamming(u64 val) +{ + u32 v; + + asm( + "cmp %Q1, #1 @ vfp_hi64to32jamming\n\t" + "movcc %0, %R1\n\t" + "orrcs %0, %R1, #1" + : "=r" (v) : "r" (val) : "cc"); + + return v; +} + +static inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) +{ + asm( "adds %Q0, %Q2, %Q4\n\t" + "adcs %R0, %R2, %R4\n\t" + "adcs %Q1, %Q3, %Q5\n\t" + "adc %R1, %R3, %R5" + : "=r" (nl), "=r" (nh) + : "0" (nl), "1" (nh), "r" (ml), "r" (mh) + : "cc"); + *resh = nh; + *resl = nl; +} + +static inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml) +{ + asm( "subs %Q0, %Q2, %Q4\n\t" + "sbcs %R0, %R2, %R4\n\t" + "sbcs %Q1, %Q3, %Q5\n\t" + "sbc %R1, %R3, %R5\n\t" + : "=r" (nl), "=r" (nh) + : "0" (nl), "1" (nh), "r" (ml), "r" (mh) + : "cc"); + *resh = nh; + *resl = nl; +} + +static inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m) +{ + u32 nh, nl, mh, ml; + u64 rh, rma, rmb, rl; + + nl = n; + ml = m; + rl = (u64)nl * ml; + + nh = n >> 32; + rma = (u64)nh * ml; + + mh = m >> 32; + rmb = (u64)nl * mh; + rma += rmb; + + rh = (u64)nh * mh; + rh += ((u64)(rma < rmb) << 32) + (rma >> 32); + + rma <<= 32; + rl += rma; + rh += (rl < rma); + + *resl = rl; + *resh = rh; +} + +static inline void shift64left(u64 *resh, u64 *resl, u64 n) +{ + *resh = n >> 63; + *resl = n << 1; +} + +static inline u64 vfp_hi64multiply64(u64 n, u64 m) +{ + u64 rh, rl; + mul64to128(&rh, &rl, n, m); + return rh | (rl != 0); +} + +static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) +{ + u64 mh, ml, remh, reml, termh, terml, z; + + if (nh >= m) + return ~0ULL; + mh = m >> 32; + z = (mh << 32 <= nh) ? 0xffffffff00000000ULL : (nh / mh) << 32; + mul64to128(&termh, &terml, m, z); + sub128(&remh, &reml, nh, nl, termh, terml); + ml = m << 32; + while ((s64)remh < 0) { + z -= 0x100000000ULL; + add128(&remh, &reml, remh, reml, mh, ml); + } + remh = (remh << 32) | (reml >> 32); + z |= (mh << 32 <= remh) ? 0xffffffff : remh / mh; + return z; +} + +/* + * Operations on unpacked elements + */ +#define vfp_sign_negate(sign) (sign ^ 0x8000) + +/* + * Single-precision + */ +struct vfp_single { + s16 exponent; + u16 sign; + u32 significand; +}; + +extern s32 vfp_get_float(unsigned int reg); +extern void vfp_put_float(unsigned int reg, s32 val); + +/* + * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa + * VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent + * VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand + * which are not propagated to the float upon packing. + */ +#define VFP_SINGLE_MANTISSA_BITS (23) +#define VFP_SINGLE_EXPONENT_BITS (8) +#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) +#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) + +/* + * The bit in an unpacked float which indicates that it is a quiet NaN + */ +#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) + +/* + * Operations on packed single-precision numbers + */ +#define vfp_single_packed_sign(v) ((v) & 0x80000000) +#define vfp_single_packed_negate(v) ((v) ^ 0x80000000) +#define vfp_single_packed_abs(v) ((v) & ~0x80000000) +#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) +#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) + +/* + * Unpack a single-precision float. Note that this returns the magnitude + * of the single-precision float mantissa with the 1. if necessary, + * aligned to bit 30. + */ +static inline void vfp_single_unpack(struct vfp_single *s, s32 val) +{ + u32 significand; + + s->sign = vfp_single_packed_sign(val) >> 16, + s->exponent = vfp_single_packed_exponent(val); + + significand = (u32) val; + significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; + if (s->exponent && s->exponent != 255) + significand |= 0x40000000; + s->significand = significand; +} + +/* + * Re-pack a single-precision float. This assumes that the float is + * already normalised such that the MSB is bit 30, _not_ bit 31. + */ +static inline s32 vfp_single_pack(struct vfp_single *s) +{ + u32 val; + val = (s->sign << 16) + + (s->exponent << VFP_SINGLE_MANTISSA_BITS) + + (s->significand >> VFP_SINGLE_LOW_BITS); + return (s32)val; +} + +#define VFP_NUMBER (1<<0) +#define VFP_ZERO (1<<1) +#define VFP_DENORMAL (1<<2) +#define VFP_INFINITY (1<<3) +#define VFP_NAN (1<<4) +#define VFP_NAN_SIGNAL (1<<5) + +#define VFP_QNAN (VFP_NAN) +#define VFP_SNAN (VFP_NAN|VFP_NAN_SIGNAL) + +static inline int vfp_single_type(struct vfp_single *s) +{ + int type = VFP_NUMBER; + if (s->exponent == 255) { + if (s->significand == 0) + type = VFP_INFINITY; + else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN) + type = VFP_QNAN; + else + type = VFP_SNAN; + } else if (s->exponent == 0) { + if (s->significand == 0) + type |= VFP_ZERO; + else + type |= VFP_DENORMAL; + } + return type; +} + +#ifndef DEBUG +#define vfp_single_normaliseround(sd,vsd,fpscr,except,func) __vfp_single_normaliseround(sd,vsd,fpscr,except) +u32 __vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions); +#else +u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func); +#endif + +/* + * Double-precision + */ +struct vfp_double { + s16 exponent; + u16 sign; + u64 significand; +}; + +extern u64 vfp_get_double(unsigned int reg); +extern void vfp_put_double(unsigned int reg, u64 val); + +#define VFP_DOUBLE_MANTISSA_BITS (52) +#define VFP_DOUBLE_EXPONENT_BITS (11) +#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) +#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) + +/* + * The bit in an unpacked double which indicates that it is a quiet NaN + */ +#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) + +/* + * Operations on packed single-precision numbers + */ +#define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) +#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) +#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) +#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) +#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) + +/* + * Unpack a double-precision float. Note that this returns the magnitude + * of the double-precision float mantissa with the 1. if necessary, + * aligned to bit 62. + */ +static inline void vfp_double_unpack(struct vfp_double *s, s64 val) +{ + u64 significand; + + s->sign = vfp_double_packed_sign(val) >> 48; + s->exponent = vfp_double_packed_exponent(val); + + significand = (u64) val; + significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2; + if (s->exponent && s->exponent != 2047) + significand |= (1ULL << 62); + s->significand = significand; +} + +/* + * Re-pack a double-precision float. This assumes that the float is + * already normalised such that the MSB is bit 30, _not_ bit 31. + */ +static inline s64 vfp_double_pack(struct vfp_double *s) +{ + u64 val; + val = ((u64)s->sign << 48) + + ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + + (s->significand >> VFP_DOUBLE_LOW_BITS); + return (s64)val; +} + +static inline int vfp_double_type(struct vfp_double *s) +{ + int type = VFP_NUMBER; + if (s->exponent == 2047) { + if (s->significand == 0) + type = VFP_INFINITY; + else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN) + type = VFP_QNAN; + else + type = VFP_SNAN; + } else if (s->exponent == 0) { + if (s->significand == 0) + type |= VFP_ZERO; + else + type |= VFP_DENORMAL; + } + return type; +} + +u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func); + +/* + * System registers + */ +extern u32 vfp_get_sys(unsigned int reg); +extern void vfp_put_sys(unsigned int reg, u32 val); + +u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); diff -Nru a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/vfpdouble.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1186 @@ +/* + * linux/arch/arm/vfp/vfpdouble.c + * + * This code is derived in part from John R. Housers softfloat library, which + * carries the following notice: + * + * =========================================================================== + * This C source file is part of the SoftFloat IEC/IEEE Floating-point + * Arithmetic Package, Release 2. + * + * Written by John R. Hauser. This work was made possible in part by the + * International Computer Science Institute, located at Suite 600, 1947 Center + * Street, Berkeley, California 94704. Funding was partially provided by the + * National Science Foundation under grant MIP-9311980. The original version + * of this code was written as part of a project to build a fixed-point vector + * processor in collaboration with the University of California at Berkeley, + * overseen by Profs. Nelson Morgan and John Wawrzynek. More information + * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ + * arithmetic/softfloat.html'. + * + * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort + * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT + * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO + * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY + * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + * + * Derivative works are acceptable, even for commercial purposes, so long as + * (1) they include prominent notice that the work is derivative, and (2) they + * include prominent notice akin to these three paragraphs for those parts of + * this code that are retained. + * =========================================================================== + */ +#include +#include +#include +#include + +#include "vfpinstr.h" +#include "vfp.h" + +static struct vfp_double vfp_double_default_qnan = { + .exponent = 2047, + .sign = 0, + .significand = VFP_DOUBLE_SIGNIFICAND_QNAN, +}; + +static void vfp_double_dump(const char *str, struct vfp_double *d) +{ + pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n", + str, d->sign != 0, d->exponent, d->significand); +} + +static void vfp_double_normalise_denormal(struct vfp_double *vd) +{ + int bits = 31 - fls(vd->significand >> 32); + if (bits == 31) + bits = 62 - fls(vd->significand); + + vfp_double_dump("normalise_denormal: in", vd); + + if (bits) { + vd->exponent -= bits - 1; + vd->significand <<= bits; + } + + vfp_double_dump("normalise_denormal: out", vd); +} + +u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func) +{ + u64 significand, incr; + int exponent, shift, underflow; + u32 rmode; + + vfp_double_dump("pack: in", vd); + + /* + * Infinities and NaNs are a special case. + */ + if (vd->exponent == 2047 && (vd->significand == 0 || exceptions)) + goto pack; + + /* + * Special-case zero. + */ + if (vd->significand == 0) { + vd->exponent = 0; + goto pack; + } + + exponent = vd->exponent; + significand = vd->significand; + + shift = 32 - fls(significand >> 32); + if (shift == 32) + shift = 64 - fls(significand); + if (shift) { + exponent -= shift; + significand <<= shift; + } + +#ifdef DEBUG + vd->exponent = exponent; + vd->significand = significand; + vfp_double_dump("pack: normalised", vd); +#endif + + /* + * Tiny number? + */ + underflow = exponent < 0; + if (underflow) { + significand = vfp_shiftright64jamming(significand, -exponent); + exponent = 0; +#ifdef DEBUG + vd->exponent = exponent; + vd->significand = significand; + vfp_double_dump("pack: tiny number", vd); +#endif + if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1))) + underflow = 0; + } + + /* + * Select rounding increment. + */ + incr = 0; + rmode = fpscr & FPSCR_RMODE_MASK; + + if (rmode == FPSCR_ROUND_NEAREST) { + incr = 1ULL << VFP_DOUBLE_LOW_BITS; + if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0) + incr -= 1; + } else if (rmode == FPSCR_ROUND_TOZERO) { + incr = 0; + } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0)) + incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1; + + pr_debug("VFP: rounding increment = 0x%08llx\n", incr); + + /* + * Is our rounding going to overflow? + */ + if ((significand + incr) < significand) { + exponent += 1; + significand = (significand >> 1) | (significand & 1); + incr >>= 1; +#ifdef DEBUG + vd->exponent = exponent; + vd->significand = significand; + vfp_double_dump("pack: overflow", vd); +#endif + } + + /* + * If any of the low bits (which will be shifted out of the + * number) are non-zero, the result is inexact. + */ + if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1)) + exceptions |= FPSCR_IXC; + + /* + * Do our rounding. + */ + significand += incr; + + /* + * Infinity? + */ + if (exponent >= 2046) { + exceptions |= FPSCR_OFC | FPSCR_IXC; + if (incr == 0) { + vd->exponent = 2045; + vd->significand = 0x7fffffffffffffffULL; + } else { + vd->exponent = 2047; /* infinity */ + vd->significand = 0; + } + } else { + if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0) + exponent = 0; + if (exponent || significand > 0x8000000000000000ULL) + underflow = 0; + if (underflow) + exceptions |= FPSCR_UFC; + vd->exponent = exponent; + vd->significand = significand >> 1; + } + + pack: + vfp_double_dump("pack: final", vd); + { + s64 d = vfp_double_pack(vd); + pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func, + dd, d, exceptions); + vfp_put_double(dd, d); + } + return exceptions; +} + +/* + * Propagate the NaN, setting exceptions if it is signalling. + * 'n' is always a NaN. 'm' may be a number, NaN or infinity. + */ +static u32 +vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, + struct vfp_double *vdm, u32 fpscr) +{ + struct vfp_double *nan; + int tn, tm = 0; + + tn = vfp_double_type(vdn); + + if (vdm) + tm = vfp_double_type(vdm); + + if (fpscr & FPSCR_DEFAULT_NAN) + /* + * Default NaN mode - always returns a quiet NaN + */ + nan = &vfp_double_default_qnan; + else { + /* + * Contemporary mode - select the first signalling + * NAN, or if neither are signalling, the first + * quiet NAN. + */ + if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN)) + nan = vdn; + else + nan = vdm; + /* + * Make the NaN quiet. + */ + nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; + } + + *vdd = *nan; + + /* + * If one was a signalling NAN, raise invalid operation. + */ + return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : 0x100; +} + +/* + * Extended operations + */ +static u32 vfp_double_fabs(int dd, int unused, int dm, u32 fpscr) +{ + vfp_put_double(dd, vfp_double_packed_abs(vfp_get_double(dm))); + return 0; +} + +static u32 vfp_double_fcpy(int dd, int unused, int dm, u32 fpscr) +{ + vfp_put_double(dd, vfp_get_double(dm)); + return 0; +} + +static u32 vfp_double_fneg(int dd, int unused, int dm, u32 fpscr) +{ + vfp_put_double(dd, vfp_double_packed_negate(vfp_get_double(dm))); + return 0; +} + +static u32 vfp_double_fsqrt(int dd, int unused, int dm, u32 fpscr) +{ + struct vfp_double vdm, vdd; + int ret, tm; + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + tm = vfp_double_type(&vdm); + if (tm & (VFP_NAN|VFP_INFINITY)) { + struct vfp_double *vdp = &vdd; + + if (tm & VFP_NAN) + ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr); + else if (vdm.sign == 0) { + sqrt_copy: + vdp = &vdm; + ret = 0; + } else { + sqrt_invalid: + vdp = &vfp_double_default_qnan; + ret = FPSCR_IOC; + } + vfp_put_double(dd, vfp_double_pack(vdp)); + return ret; + } + + /* + * sqrt(+/- 0) == +/- 0 + */ + if (tm & VFP_ZERO) + goto sqrt_copy; + + /* + * Normalise a denormalised number + */ + if (tm & VFP_DENORMAL) + vfp_double_normalise_denormal(&vdm); + + /* + * sqrt(<0) = invalid + */ + if (vdm.sign) + goto sqrt_invalid; + + vfp_double_dump("sqrt", &vdm); + + /* + * Estimate the square root. + */ + vdd.sign = 0; + vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023; + vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31; + + vfp_double_dump("sqrt estimate1", &vdd); + + vdm.significand >>= 1 + (vdm.exponent & 1); + vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand); + + vfp_double_dump("sqrt estimate2", &vdd); + + /* + * And now adjust. + */ + if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) { + if (vdd.significand < 2) { + vdd.significand = ~0ULL; + } else { + u64 termh, terml, remh, reml; + vdm.significand <<= 2; + mul64to128(&termh, &terml, vdd.significand, vdd.significand); + sub128(&remh, &reml, vdm.significand, 0, termh, terml); + while ((s64)remh < 0) { + vdd.significand -= 1; + shift64left(&termh, &terml, vdd.significand); + terml |= 1; + add128(&remh, &reml, remh, reml, termh, terml); + } + vdd.significand |= (remh | reml) != 0; + } + } + vdd.significand = vfp_shiftright64jamming(vdd.significand, 1); + + return vfp_double_normaliseround(dd, &vdd, fpscr, 0, "fsqrt"); +} + +/* + * Equal := ZC + * Less than := N + * Greater than := C + * Unordered := CV + */ +static u32 vfp_compare(int dd, int signal_on_qnan, int dm, u32 fpscr) +{ + s64 d, m; + u32 ret = 0; + + m = vfp_get_double(dm); + if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { + ret |= FPSCR_C | FPSCR_V; + if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) + /* + * Signalling NaN, or signalling on quiet NaN + */ + ret |= FPSCR_IOC; + } + + d = vfp_get_double(dd); + if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { + ret |= FPSCR_C | FPSCR_V; + if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) + /* + * Signalling NaN, or signalling on quiet NaN + */ + ret |= FPSCR_IOC; + } + + if (ret == 0) { + if (d == m || vfp_double_packed_abs(d | m) == 0) { + /* + * equal + */ + ret |= FPSCR_Z | FPSCR_C; + } else if (vfp_double_packed_sign(d ^ m)) { + /* + * different signs + */ + if (vfp_double_packed_sign(d)) + /* + * d is negative, so d < m + */ + ret |= FPSCR_N; + else + /* + * d is positive, so d > m + */ + ret |= FPSCR_C; + } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) { + /* + * d < m + */ + ret |= FPSCR_N; + } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) { + /* + * d > m + */ + ret |= FPSCR_C; + } + } + + return ret; +} + +static u32 vfp_double_fcmp(int dd, int unused, int dm, u32 fpscr) +{ + return vfp_compare(dd, 0, dm, fpscr); +} + +static u32 vfp_double_fcmpe(int dd, int unused, int dm, u32 fpscr) +{ + return vfp_compare(dd, 1, dm, fpscr); +} + +static u32 vfp_double_fcmpz(int dd, int unused, int dm, u32 fpscr) +{ + return vfp_compare(dd, 0, -1, fpscr); +} + +static u32 vfp_double_fcmpez(int dd, int unused, int dm, u32 fpscr) +{ + return vfp_compare(dd, 1, -1, fpscr); +} + +static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr) +{ + struct vfp_double vdm; + struct vfp_single vsd; + int tm; + u32 exceptions = 0; + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + + tm = vfp_double_type(&vdm); + + /* + * If we have a signalling NaN, signal invalid operation. + */ + if (tm == VFP_SNAN) + exceptions = FPSCR_IOC; + + if (tm & VFP_DENORMAL) + vfp_double_normalise_denormal(&vdm); + + vsd.sign = vdm.sign; + vsd.significand = vfp_hi64to32jamming(vdm.significand); + + /* + * If we have an infinity or a NaN, the exponent must be 255 + */ + if (tm & (VFP_INFINITY|VFP_NAN)) { + vsd.exponent = 255; + if (tm & VFP_NAN) + vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; + goto pack_nan; + } else if (tm & VFP_ZERO) + vsd.exponent = 0; + else + vsd.exponent = vdm.exponent - (1023 - 127); + + return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fcvts"); + + pack_nan: + vfp_put_float(sd, vfp_single_pack(&vsd)); + return exceptions; +} + +static u32 vfp_double_fuito(int dd, int unused, int dm, u32 fpscr) +{ + struct vfp_double vdm; + u32 m = vfp_get_float(dm); + + vdm.sign = 0; + vdm.exponent = 1023 + 63 - 1; + vdm.significand = (u64)m; + + return vfp_double_normaliseround(dd, &vdm, fpscr, 0, "fuito"); +} + +static u32 vfp_double_fsito(int dd, int unused, int dm, u32 fpscr) +{ + struct vfp_double vdm; + u32 m = vfp_get_float(dm); + + vdm.sign = (m & 0x80000000) >> 16; + vdm.exponent = 1023 + 63 - 1; + vdm.significand = vdm.sign ? -m : m; + + return vfp_double_normaliseround(dd, &vdm, fpscr, 0, "fsito"); +} + +static u32 vfp_double_ftoui(int sd, int unused, int dm, u32 fpscr) +{ + struct vfp_double vdm; + u32 d, exceptions = 0; + int rmode = fpscr & FPSCR_RMODE_MASK; + int tm; + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + + /* + * Do we have a denormalised number? + */ + tm = vfp_double_type(&vdm); + if (tm & VFP_DENORMAL) + exceptions |= FPSCR_IDC; + + if (tm & VFP_NAN) + vdm.sign = 0; + + if (vdm.exponent >= 1023 + 32) { + d = vdm.sign ? 0 : 0xffffffff; + exceptions = FPSCR_IOC; + } else if (vdm.exponent >= 1023 - 1) { + int shift = 1023 + 63 - vdm.exponent; + u64 rem, incr = 0; + + /* + * 2^0 <= m < 2^32-2^8 + */ + d = (vdm.significand << 1) >> shift; + rem = vdm.significand << (65 - shift); + + if (rmode == FPSCR_ROUND_NEAREST) { + incr = 0x8000000000000000ULL; + if ((d & 1) == 0) + incr -= 1; + } else if (rmode == FPSCR_ROUND_TOZERO) { + incr = 0; + } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) { + incr = ~0ULL; + } + + if ((rem + incr) < rem) { + if (d < 0xffffffff) + d += 1; + else + exceptions |= FPSCR_IOC; + } + + if (d && vdm.sign) { + d = 0; + exceptions |= FPSCR_IOC; + } else if (rem) + exceptions |= FPSCR_IXC; + } else { + d = 0; + if (vdm.exponent | vdm.significand) { + exceptions |= FPSCR_IXC; + if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) + d = 1; + else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { + d = 0; + exceptions |= FPSCR_IOC; + } + } + } + + pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); + + vfp_put_float(sd, d); + + return exceptions; +} + +static u32 vfp_double_ftouiz(int sd, int unused, int dm, u32 fpscr) +{ + return vfp_double_ftoui(sd, unused, dm, FPSCR_ROUND_TOZERO); +} + +static u32 vfp_double_ftosi(int sd, int unused, int dm, u32 fpscr) +{ + struct vfp_double vdm; + u32 d, exceptions = 0; + int rmode = fpscr & FPSCR_RMODE_MASK; + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + vfp_double_dump("VDM", &vdm); + + /* + * Do we have denormalised number? + */ + if (vfp_double_type(&vdm) & VFP_DENORMAL) + exceptions |= FPSCR_IDC; + + if (vdm.exponent >= 1023 + 32) { + d = 0x7fffffff; + if (vdm.sign) + d = ~d; + exceptions |= FPSCR_IOC; + } else if (vdm.exponent >= 1023 - 1) { + int shift = 1023 + 63 - vdm.exponent; /* 58 */ + u64 rem, incr = 0; + + d = (vdm.significand << 1) >> shift; + rem = vdm.significand << (65 - shift); + + if (rmode == FPSCR_ROUND_NEAREST) { + incr = 0x8000000000000000ULL; + if ((d & 1) == 0) + incr -= 1; + } else if (rmode == FPSCR_ROUND_TOZERO) { + incr = 0; + } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) { + incr = ~0ULL; + } + + if ((rem + incr) < rem && d < 0xffffffff) + d += 1; + if (d > 0x7fffffff + (vdm.sign != 0)) { + d = 0x7fffffff + (vdm.sign != 0); + exceptions |= FPSCR_IOC; + } else if (rem) + exceptions |= FPSCR_IXC; + + if (vdm.sign) + d = -d; + } else { + d = 0; + if (vdm.exponent | vdm.significand) { + exceptions |= FPSCR_IXC; + if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) + d = 1; + else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) + d = -1; + } + } + + pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); + + vfp_put_float(sd, (s32)d); + + return exceptions; +} + +static u32 vfp_double_ftosiz(int dd, int unused, int dm, u32 fpscr) +{ + return vfp_double_ftosi(dd, unused, dm, FPSCR_ROUND_TOZERO); +} + + +static u32 (* const fop_extfns[32])(int dd, int unused, int dm, u32 fpscr) = { + [FEXT_TO_IDX(FEXT_FCPY)] = vfp_double_fcpy, + [FEXT_TO_IDX(FEXT_FABS)] = vfp_double_fabs, + [FEXT_TO_IDX(FEXT_FNEG)] = vfp_double_fneg, + [FEXT_TO_IDX(FEXT_FSQRT)] = vfp_double_fsqrt, + [FEXT_TO_IDX(FEXT_FCMP)] = vfp_double_fcmp, + [FEXT_TO_IDX(FEXT_FCMPE)] = vfp_double_fcmpe, + [FEXT_TO_IDX(FEXT_FCMPZ)] = vfp_double_fcmpz, + [FEXT_TO_IDX(FEXT_FCMPEZ)] = vfp_double_fcmpez, + [FEXT_TO_IDX(FEXT_FCVT)] = vfp_double_fcvts, + [FEXT_TO_IDX(FEXT_FUITO)] = vfp_double_fuito, + [FEXT_TO_IDX(FEXT_FSITO)] = vfp_double_fsito, + [FEXT_TO_IDX(FEXT_FTOUI)] = vfp_double_ftoui, + [FEXT_TO_IDX(FEXT_FTOUIZ)] = vfp_double_ftouiz, + [FEXT_TO_IDX(FEXT_FTOSI)] = vfp_double_ftosi, + [FEXT_TO_IDX(FEXT_FTOSIZ)] = vfp_double_ftosiz, +}; + + + + +static u32 +vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn, + struct vfp_double *vdm, u32 fpscr) +{ + struct vfp_double *vdp; + u32 exceptions = 0; + int tn, tm; + + tn = vfp_double_type(vdn); + tm = vfp_double_type(vdm); + + if (tn & tm & VFP_INFINITY) { + /* + * Two infinities. Are they different signs? + */ + if (vdn->sign ^ vdm->sign) { + /* + * different signs -> invalid + */ + exceptions = FPSCR_IOC; + vdp = &vfp_double_default_qnan; + } else { + /* + * same signs -> valid + */ + vdp = vdn; + } + } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) { + /* + * One infinity and one number -> infinity + */ + vdp = vdn; + } else { + /* + * 'n' is a NaN of some type + */ + return vfp_propagate_nan(vdd, vdn, vdm, fpscr); + } + *vdd = *vdp; + return exceptions; +} + +static u32 +vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, + struct vfp_double *vdm, u32 fpscr) +{ + u32 exp_diff; + u64 m_sig; + + if (vdn->significand & (1ULL << 63) || + vdm->significand & (1ULL << 63)) { + pr_info("VFP: bad FP values in %s\n", __func__); + vfp_double_dump("VDN", vdn); + vfp_double_dump("VDM", vdm); + } + + /* + * Ensure that 'n' is the largest magnitude number. Note that + * if 'n' and 'm' have equal exponents, we do not swap them. + * This ensures that NaN propagation works correctly. + */ + if (vdn->exponent < vdm->exponent) { + struct vfp_double *t = vdn; + vdn = vdm; + vdm = t; + } + + /* + * Is 'n' an infinity or a NaN? Note that 'm' may be a number, + * infinity or a NaN here. + */ + if (vdn->exponent == 2047) + return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr); + + /* + * We have two proper numbers, where 'vdn' is the larger magnitude. + * + * Copy 'n' to 'd' before doing the arithmetic. + */ + *vdd = *vdn; + + /* + * Align 'm' with the result. + */ + exp_diff = vdn->exponent - vdm->exponent; + m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff); + + /* + * If the signs are different, we are really subtracting. + */ + if (vdn->sign ^ vdm->sign) { + m_sig = vdn->significand - m_sig; + if ((s64)m_sig < 0) { + vdd->sign = vfp_sign_negate(vdd->sign); + m_sig = -m_sig; + } + } else { + m_sig += vdn->significand; + } + vdd->significand = m_sig; + + return 0; +} + +static u32 +vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, + struct vfp_double *vdm, u32 fpscr) +{ + vfp_double_dump("VDN", vdn); + vfp_double_dump("VDM", vdm); + + /* + * Ensure that 'n' is the largest magnitude number. Note that + * if 'n' and 'm' have equal exponents, we do not swap them. + * This ensures that NaN propagation works correctly. + */ + if (vdn->exponent < vdm->exponent) { + struct vfp_double *t = vdn; + vdn = vdm; + vdm = t; + pr_debug("VFP: swapping M <-> N\n"); + } + + vdd->sign = vdn->sign ^ vdm->sign; + + /* + * If 'n' is an infinity or NaN, handle it. 'm' may be anything. + */ + if (vdn->exponent == 2047) { + if (vdn->significand || (vdm->exponent == 2047 && vdm->significand)) + return vfp_propagate_nan(vdd, vdn, vdm, fpscr); + if ((vdm->exponent | vdm->significand) == 0) { + *vdd = vfp_double_default_qnan; + return FPSCR_IOC; + } + vdd->exponent = vdn->exponent; + vdd->significand = 0; + return 0; + } + + /* + * If 'm' is zero, the result is always zero. In this case, + * 'n' may be zero or a number, but it doesn't matter which. + */ + if ((vdm->exponent | vdm->significand) == 0) { + vdd->exponent = 0; + vdd->significand = 0; + return 0; + } + + /* + * We add 2 to the destination exponent for the same reason + * as the addition case - though this time we have +1 from + * each input operand. + */ + vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2; + vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand); + + vfp_double_dump("VDD", vdd); + return 0; +} + +#define NEG_MULTIPLY (1 << 0) +#define NEG_SUBTRACT (1 << 1) + +static u32 +vfp_double_multiply_accumulate(int dd, int dn, int dm, u32 fpscr, u32 negate, char *func) +{ + struct vfp_double vdd, vdp, vdn, vdm; + u32 exceptions; + + vfp_double_unpack(&vdn, vfp_get_double(dn)); + if (vdn.exponent == 0 && vdn.significand) + vfp_double_normalise_denormal(&vdn); + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + if (vdm.exponent == 0 && vdm.significand) + vfp_double_normalise_denormal(&vdm); + + exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr); + if (negate & NEG_MULTIPLY) + vdp.sign = vfp_sign_negate(vdp.sign); + + vfp_double_unpack(&vdn, vfp_get_double(dd)); + if (negate & NEG_SUBTRACT) + vdn.sign = vfp_sign_negate(vdn.sign); + + exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr); + + return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, func); +} + +/* + * Standard operations + */ + +/* + * sd = sd + (sn * sm) + */ +static u32 vfp_double_fmac(int dd, int dn, int dm, u32 fpscr) +{ + return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, 0, "fmac"); +} + +/* + * sd = sd - (sn * sm) + */ +static u32 vfp_double_fnmac(int dd, int dn, int dm, u32 fpscr) +{ + return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac"); +} + +/* + * sd = -sd + (sn * sm) + */ +static u32 vfp_double_fmsc(int dd, int dn, int dm, u32 fpscr) +{ + return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc"); +} + +/* + * sd = -sd - (sn * sm) + */ +static u32 vfp_double_fnmsc(int dd, int dn, int dm, u32 fpscr) +{ + return vfp_double_multiply_accumulate(dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); +} + +/* + * sd = sn * sm + */ +static u32 vfp_double_fmul(int dd, int dn, int dm, u32 fpscr) +{ + struct vfp_double vdd, vdn, vdm; + u32 exceptions; + + vfp_double_unpack(&vdn, vfp_get_double(dn)); + if (vdn.exponent == 0 && vdn.significand) + vfp_double_normalise_denormal(&vdn); + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + if (vdm.exponent == 0 && vdm.significand) + vfp_double_normalise_denormal(&vdm); + + exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); + return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fmul"); +} + +/* + * sd = -(sn * sm) + */ +static u32 vfp_double_fnmul(int dd, int dn, int dm, u32 fpscr) +{ + struct vfp_double vdd, vdn, vdm; + u32 exceptions; + + vfp_double_unpack(&vdn, vfp_get_double(dn)); + if (vdn.exponent == 0 && vdn.significand) + vfp_double_normalise_denormal(&vdn); + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + if (vdm.exponent == 0 && vdm.significand) + vfp_double_normalise_denormal(&vdm); + + exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); + vdd.sign = vfp_sign_negate(vdd.sign); + + return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fnmul"); +} + +/* + * sd = sn + sm + */ +static u32 vfp_double_fadd(int dd, int dn, int dm, u32 fpscr) +{ + struct vfp_double vdd, vdn, vdm; + u32 exceptions; + + vfp_double_unpack(&vdn, vfp_get_double(dn)); + if (vdn.exponent == 0 && vdn.significand) + vfp_double_normalise_denormal(&vdn); + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + if (vdm.exponent == 0 && vdm.significand) + vfp_double_normalise_denormal(&vdm); + + exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr); + + return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fadd"); +} + +/* + * sd = sn - sm + */ +static u32 vfp_double_fsub(int dd, int dn, int dm, u32 fpscr) +{ + struct vfp_double vdd, vdn, vdm; + u32 exceptions; + + vfp_double_unpack(&vdn, vfp_get_double(dn)); + if (vdn.exponent == 0 && vdn.significand) + vfp_double_normalise_denormal(&vdn); + + vfp_double_unpack(&vdm, vfp_get_double(dm)); + if (vdm.exponent == 0 && vdm.significand) + vfp_double_normalise_denormal(&vdm); + + /* + * Subtraction is like addition, but with a negated operand. + */ + vdm.sign = vfp_sign_negate(vdm.sign); + + exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr); + + return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fsub"); +} + +/* + * sd = sn / sm + */ +static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr) +{ + struct vfp_double vdd, vdn, vdm; + u32 exceptions = 0; + int tm, tn; + + vfp_double_unpack(&vdn, vfp_get_double(dn)); + vfp_double_unpack(&vdm, vfp_get_double(dm)); + + vdd.sign = vdn.sign ^ vdm.sign; + + tn = vfp_double_type(&vdn); + tm = vfp_double_type(&vdm); + + /* + * Is n a NAN? + */ + if (tn & VFP_NAN) + goto vdn_nan; + + /* + * Is m a NAN? + */ + if (tm & VFP_NAN) + goto vdm_nan; + + /* + * If n and m are infinity, the result is invalid + * If n and m are zero, the result is invalid + */ + if (tm & tn & (VFP_INFINITY|VFP_ZERO)) + goto invalid; + + /* + * If n is infinity, the result is infinity + */ + if (tn & VFP_INFINITY) + goto infinity; + + /* + * If m is zero, raise div0 exceptions + */ + if (tm & VFP_ZERO) + goto divzero; + + /* + * If m is infinity, or n is zero, the result is zero + */ + if (tm & VFP_INFINITY || tn & VFP_ZERO) + goto zero; + + if (tn & VFP_DENORMAL) + vfp_double_normalise_denormal(&vdn); + if (tm & VFP_DENORMAL) + vfp_double_normalise_denormal(&vdm); + + /* + * Ok, we have two numbers, we can perform division. + */ + vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1; + vdm.significand <<= 1; + if (vdm.significand <= (2 * vdn.significand)) { + vdn.significand >>= 1; + vdd.exponent++; + } + vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand); + if ((vdd.significand & 0x1ff) <= 2) { + u64 termh, terml, remh, reml; + mul64to128(&termh, &terml, vdm.significand, vdd.significand); + sub128(&remh, &reml, vdn.significand, 0, termh, terml); + while ((s64)remh < 0) { + vdd.significand -= 1; + add128(&remh, &reml, remh, reml, 0, vdm.significand); + } + vdd.significand |= (reml != 0); + } + return vfp_double_normaliseround(dd, &vdd, fpscr, 0, "fdiv"); + + vdn_nan: + exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); + pack: + vfp_put_double(dd, vfp_double_pack(&vdd)); + return exceptions; + + vdm_nan: + exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr); + goto pack; + + zero: + vdd.exponent = 0; + vdd.significand = 0; + goto pack; + + divzero: + exceptions = FPSCR_DZC; + infinity: + vdd.exponent = 2047; + vdd.significand = 0; + goto pack; + + invalid: + vfp_put_double(dd, vfp_double_pack(&vfp_double_default_qnan)); + return FPSCR_IOC; +} + +static u32 (* const fop_fns[16])(int dd, int dn, int dm, u32 fpscr) = { + [FOP_TO_IDX(FOP_FMAC)] = vfp_double_fmac, + [FOP_TO_IDX(FOP_FNMAC)] = vfp_double_fnmac, + [FOP_TO_IDX(FOP_FMSC)] = vfp_double_fmsc, + [FOP_TO_IDX(FOP_FNMSC)] = vfp_double_fnmsc, + [FOP_TO_IDX(FOP_FMUL)] = vfp_double_fmul, + [FOP_TO_IDX(FOP_FNMUL)] = vfp_double_fnmul, + [FOP_TO_IDX(FOP_FADD)] = vfp_double_fadd, + [FOP_TO_IDX(FOP_FSUB)] = vfp_double_fsub, + [FOP_TO_IDX(FOP_FDIV)] = vfp_double_fdiv, +}; + +#define FREG_BANK(x) ((x) & 0x0c) +#define FREG_IDX(x) ((x) & 3) + +u32 vfp_double_cpdo(u32 inst, u32 fpscr) +{ + u32 op = inst & FOP_MASK; + u32 exceptions = 0; + unsigned int dd = vfp_get_sd(inst); + unsigned int dn = vfp_get_sn(inst); + unsigned int dm = vfp_get_sm(inst); + unsigned int vecitr, veclen, vecstride; + u32 (*fop)(int, int, s32, u32); + + veclen = fpscr & FPSCR_LENGTH_MASK; + vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2; + + /* + * If destination bank is zero, vector length is always '1'. + * ARM DDI0100F C5.1.3, C5.3.2. + */ + if (FREG_BANK(dd) == 0) + veclen = 0; + + pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, + (veclen >> FPSCR_LENGTH_BIT) + 1); + + fop = (op == FOP_EXT) ? fop_extfns[dn] : fop_fns[FOP_TO_IDX(op)]; + if (!fop) + goto invalid; + + for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { + u32 except; + + if (op == FOP_EXT) + pr_debug("VFP: itr%d (d%u.%u) = op[%u] (d%u.%u)\n", + vecitr >> FPSCR_LENGTH_BIT, + dd >> 1, dd & 1, dn, + dm >> 1, dm & 1); + else + pr_debug("VFP: itr%d (d%u.%u) = (d%u.%u) op[%u] (d%u.%u)\n", + vecitr >> FPSCR_LENGTH_BIT, + dd >> 1, dd & 1, + dn >> 1, dn & 1, + FOP_TO_IDX(op), + dm >> 1, dm & 1); + + except = fop(dd, dn, dm, fpscr); + pr_debug("VFP: itr%d: exceptions=%08x\n", + vecitr >> FPSCR_LENGTH_BIT, except); + + exceptions |= except; + + /* + * This ensures that comparisons only operate on scalars; + * comparisons always return with one FPSCR status bit set. + */ + if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) + break; + + /* + * CHECK: It appears to be undefined whether we stop when + * we encounter an exception. We continue. + */ + + dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6); + dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6); + if (FREG_BANK(dm) != 0) + dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6); + } + return exceptions; + + invalid: + return ~0; +} diff -Nru a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/vfphw.S 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,210 @@ +/* + * linux/arch/arm/vfp/vfphw.S + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + * + * This code is called from the kernel's undefined instruction trap. + * r9 holds the return address for successful handling. + * lr holds the return address for unrecognised instructions. + * r10 points at the start of the private FP workspace in the thread structure + * sp points to a struct pt_regs (as defined in include/asm/proc/ptrace.h) + */ +#include +#include +#include "../kernel/entry-header.S" + + .macro DBGSTR, str +#ifdef DEBUG + stmfd sp!, {r0-r3, ip, lr} + add r0, pc, #4 + bl printk + b 1f + .asciz "<7>VFP: \str\n" + .balign 4 +1: ldmfd sp!, {r0-r3, ip, lr} +#endif + .endm + + .macro DBGSTR1, str, arg +#ifdef DEBUG + stmfd sp!, {r0-r3, ip, lr} + mov r1, \arg + add r0, pc, #4 + bl printk + b 1f + .asciz "<7>VFP: \str\n" + .balign 4 +1: ldmfd sp!, {r0-r3, ip, lr} +#endif + .endm + + .macro DBGSTR3, str, arg1, arg2, arg3 +#ifdef DEBUG + stmfd sp!, {r0-r3, ip, lr} + mov r3, \arg3 + mov r2, \arg2 + mov r1, \arg1 + add r0, pc, #4 + bl printk + b 1f + .asciz "<7>VFP: \str\n" + .balign 4 +1: ldmfd sp!, {r0-r3, ip, lr} +#endif + .endm + + +@ VFP hardware support entry point. +@ +@ r0 = faulted instruction +@ r5 = faulted PC+4 +@ r9 = successful return +@ r10 = vfp_state union +@ lr = failure return + + .globl vfp_support_entry +vfp_support_entry: + DBGSTR3 "instr %08x pc %08x state %p", r0, r5, r10 + + VFPFMRX r1, FPEXC @ Is the VFP enabled? + DBGSTR1 "fpexc %08x", r1 + tst r1, #FPEXC_ENABLE + bne look_for_VFP_exceptions @ VFP is already enabled + + DBGSTR1 "enable %x", r10 + ldr r3, last_VFP_context_address + orr r1, r1, #FPEXC_ENABLE @ user FPEXC has the enable bit set + ldr r4, [r3] @ last_VFP_context pointer + bic r2, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled + cmp r4, r10 + beq check_for_exception @ we are returning to the same + @ process, so the registers are + @ still there. In this case, we do + @ not want to drop a pending exception. + + VFPFMXR FPEXC, r2 @ enable VFP, disable any pending + @ exceptions, so we can get at the + @ rest of it + + @ Save out the current registers to the old thread state + + DBGSTR1 "save old state %p", r4 + cmp r4, #0 + beq no_old_VFP_process + VFPFMRX r2, FPSCR @ current status + VFPFMRX r6, FPINST @ FPINST (always there, rev0 onwards) + tst r1, #FPEXC_FPV2 @ is there an FPINST2 to read? + VFPFMRX r8, FPINST2, NE @ FPINST2 if needed - avoids reading + @ nonexistant reg on rev0 + VFPFSTMIA r4 @ save the working registers + add r4, r4, #8*16+4 + stmia r4, {r1, r2, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 + @ and point r4 at the word at the + @ start of the register dump + +no_old_VFP_process: + DBGSTR1 "load state %p", r10 + str r10, [r3] @ update the last_VFP_context pointer + @ Load the saved state back into the VFP + add r4, r10, #8*16+4 + ldmia r4, {r1, r2, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 + VFPFLDMIA r10 @ reload the working registers while + @ FPEXC is in a safe state + tst r1, #FPEXC_FPV2 @ is there an FPINST2 to write? + VFPFMXR FPINST2, r8, NE @ FPINST2 if needed - avoids writing + @ nonexistant reg on rev0 + VFPFMXR FPINST, r6 + VFPFMXR FPSCR, r2 @ restore status + +check_for_exception: + tst r1, #FPEXC_EXCEPTION + bne process_exception @ might as well handle the pending + @ exception before retrying branch + @ out before setting an FPEXC that + @ stops us reading stuff + VFPFMXR FPEXC, r1 @ restore FPEXC last + sub r5, r5, #4 + str r5, [sp, #S_PC] @ retry the instruction + mov pc, r9 @ we think we have handled things + + +look_for_VFP_exceptions: + tst r1, #FPEXC_EXCEPTION + bne process_exception + VFPFMRX r2, FPSCR + tst r2, #FPSCR_IXE @ IXE doesn't set FPEXC_EXCEPTION ! + bne process_exception + + @ Fall into hand on to next handler - appropriate coproc instr + @ not recognised by VFP + + DBGSTR "not VFP" + mov pc, lr + +process_exception: + DBGSTR "bounce" + sub r5, r5, #4 + str r5, [sp, #S_PC] @ retry the instruction on exit from + @ the imprecise exception handling in + @ the support code + mov r2, sp @ nothing stacked - regdump is at TOS + mov lr, r9 @ setup for a return to the user code. + + @ Now call the C code to package up the bounce to the support code + @ r0 holds the trigger instruction + @ r1 holds the FPEXC value + @ r2 pointer to register dump + b VFP9_bounce @ we have handled this - the support + @ code will raise an exception if + @ required. If not, the user code will + @ retry the faulted instruction + +last_VFP_context_address: + .word last_VFP_context + + .globl vfp_get_float +vfp_get_float: + add pc, pc, r0, lsl #3 + mov r0, r0 + .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mrc p10, 0, r0, c\dr, c0, 0 @ fmrs r0, s0 + mov pc, lr + mrc p10, 0, r0, c\dr, c0, 4 @ fmrs r0, s1 + mov pc, lr + .endr + + .globl vfp_put_float +vfp_put_float: + add pc, pc, r0, lsl #3 + mov r0, r0 + .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mcr p10, 0, r1, c\dr, c0, 0 @ fmsr r0, s0 + mov pc, lr + mcr p10, 0, r1, c\dr, c0, 4 @ fmsr r0, s1 + mov pc, lr + .endr + + .globl vfp_get_double +vfp_get_double: + mov r0, r0, lsr #1 + add pc, pc, r0, lsl #3 + mov r0, r0 + .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mrrc p10, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr + mov pc, lr + .endr + + .globl vfp_put_double +vfp_put_double: + mov r0, r0, lsr #1 + add pc, pc, r0, lsl #3 + mov r0, r0 + .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + mcrr p10, 1, r1, r2, c\dr @ fmrrd r1, r2, d\dr + mov pc, lr + .endr diff -Nru a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/vfpinstr.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,88 @@ +/* + * linux/arch/arm/vfp/vfpinstr.h + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + * + * VFP instruction masks. + */ +#define INST_CPRTDO(inst) (((inst) & 0x0f000000) == 0x0e000000) +#define INST_CPRT(inst) ((inst) & (1 << 4)) +#define INST_CPRT_L(inst) ((inst) & (1 << 20)) +#define INST_CPRT_Rd(inst) (((inst) & (15 << 12)) >> 12) +#define INST_CPRT_OP(inst) (((inst) >> 21) & 7) +#define INST_CPNUM(inst) ((inst) & 0xf00) +#define CPNUM(cp) ((cp) << 8) + +#define FOP_MASK (0x00b00040) +#define FOP_FMAC (0x00000000) +#define FOP_FNMAC (0x00000040) +#define FOP_FMSC (0x00100000) +#define FOP_FNMSC (0x00100040) +#define FOP_FMUL (0x00200000) +#define FOP_FNMUL (0x00200040) +#define FOP_FADD (0x00300000) +#define FOP_FSUB (0x00300040) +#define FOP_FDIV (0x00800000) +#define FOP_EXT (0x00b00040) + +#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) + +#define FEXT_MASK (0x000f0080) +#define FEXT_FCPY (0x00000000) +#define FEXT_FABS (0x00000080) +#define FEXT_FNEG (0x00010000) +#define FEXT_FSQRT (0x00010080) +#define FEXT_FCMP (0x00040000) +#define FEXT_FCMPE (0x00040080) +#define FEXT_FCMPZ (0x00050000) +#define FEXT_FCMPEZ (0x00050080) +#define FEXT_FCVT (0x00070080) +#define FEXT_FUITO (0x00080000) +#define FEXT_FSITO (0x00080080) +#define FEXT_FTOUI (0x000c0000) +#define FEXT_FTOUIZ (0x000c0080) +#define FEXT_FTOSI (0x000d0000) +#define FEXT_FTOSIZ (0x000d0080) + +#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) + +#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) +#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12) +#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) +#define vfp_get_dm(inst) ((inst & 0x0000000f)) +#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) +#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16) + +#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) + +#define FPSCR_N (1 << 31) +#define FPSCR_Z (1 << 30) +#define FPSCR_C (1 << 29) +#define FPSCR_V (1 << 28) + +/* + * Since we aren't building with -mfpu=vfp, we need to code + * these instructions using their MRC/MCR equivalents. + */ +#define vfpreg(_vfp_) #_vfp_ + +#define fmrx(_vfp_) ({ \ + u32 __v; \ + asm("mrc%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx %0, " #_vfp_ \ + : "=r" (__v)); \ + __v; \ + }) + +#define fmxr(_vfp_,_var_) \ + asm("mcr%? p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \ + : : "r" (_var_)) + +u32 vfp_single_cpdo(u32 inst, u32 fpscr); +u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs); + +u32 vfp_double_cpdo(u32 inst, u32 fpscr); diff -Nru a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/vfpmodule.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,288 @@ +/* + * linux/arch/arm/vfp/vfpmodule.c + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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 "vfpinstr.h" +#include "vfp.h" + +/* + * Our undef handlers (in entry.S) + */ +void vfp_testing_entry(void); +void vfp_support_entry(void); + +void (*vfp_vector)(void) = vfp_testing_entry; +union vfp_state *last_VFP_context; + +/* + * Dual-use variable. + * Used in startup: set to non-zero if VFP checks fail + * After startup, holds VFP architecture + */ +unsigned int VFP_arch; + +/* + * Per-thread VFP initialisation. + */ +void vfp_flush_thread(union vfp_state *vfp) +{ + memset(vfp, 0, sizeof(union vfp_state)); + + vfp->hard.fpexc = FPEXC_ENABLE; + vfp->hard.fpscr = FPSCR_ROUND_NEAREST; + + /* + * Disable VFP to ensure we initialise it first. + */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); + + /* + * Ensure we don't try to overwrite our newly initialised + * state information on the first fault. + */ + if (last_VFP_context == vfp) + last_VFP_context = NULL; +} + +/* + * Per-thread VFP cleanup. + */ +void vfp_release_thread(union vfp_state *vfp) +{ + if (last_VFP_context == vfp) + last_VFP_context = NULL; +} + +/* + * Raise a SIGFPE for the current process. + * sicode describes the signal being raised. + */ +void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) +{ + siginfo_t info; + + memset(&info, 0, sizeof(info)); + + info.si_signo = SIGFPE; + info.si_code = sicode; + info.si_addr = (void *)(instruction_pointer(regs) - 4); + + /* + * This is the same as NWFPE, because it's not clear what + * this is used for + */ + current->thread.error_code = 0; + current->thread.trap_no = 6; + + force_sig_info(SIGFPE, &info, current); +} + +static void vfp_panic(char *reason) +{ + int i; + + printk(KERN_ERR "VFP: Error: %s\n", reason); + printk(KERN_ERR "VFP: EXC 0x%08x SCR 0x%08x INST 0x%08x\n", + fmrx(FPEXC), fmrx(FPSCR), fmrx(FPINST)); + for (i = 0; i < 32; i += 2) + printk(KERN_ERR "VFP: s%2u: 0x%08x s%2u: 0x%08x\n", + i, vfp_get_float(i), i+1, vfp_get_float(i+1)); +} + +/* + * Process bitmask of exception conditions. + */ +static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs) +{ + int si_code = 0; + + pr_debug("VFP: raising exceptions %08x\n", exceptions); + + if (exceptions == (u32)-1) { + vfp_panic("unhandled bounce"); + vfp_raise_sigfpe(0, regs); + return; + } + + /* + * If any of the status flags are set, update the FPSCR. + * Comparison instructions always return at least one of + * these flags set. + */ + if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) + fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); + + fpscr |= exceptions; + + fmxr(FPSCR, fpscr); + +#define RAISE(stat,en,sig) \ + if (exceptions & stat && fpscr & en) \ + si_code = sig; + + /* + * These are arranged in priority order, least to highest. + */ + RAISE(FPSCR_IXC, FPSCR_IXE, FPE_FLTRES); + RAISE(FPSCR_UFC, FPSCR_UFE, FPE_FLTUND); + RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); + RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV); + + if (si_code) + vfp_raise_sigfpe(si_code, regs); +} + +/* + * Emulate a VFP instruction. + */ +static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs) +{ + u32 exceptions = (u32)-1; + + pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr); + + if (INST_CPRTDO(inst)) { + if (!INST_CPRT(inst)) { + /* + * CPDO + */ + if (vfp_single(inst)) { + exceptions = vfp_single_cpdo(inst, fpscr); + } else { + exceptions = vfp_double_cpdo(inst, fpscr); + } + } else { + /* + * A CPRT instruction can not appear in FPINST2, nor + * can it cause an exception. Therefore, we do not + * have to emulate it. + */ + } + } else { + /* + * A CPDT instruction can not appear in FPINST2, nor can + * it cause an exception. Therefore, we do not have to + * emulate it. + */ + } + return exceptions; +} + +/* + * Package up a bounce condition. + */ +void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) +{ + u32 fpscr, orig_fpscr, exceptions, inst; + + pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc); + + /* + * Enable access to the VFP so we can handle the bounce. + */ + fmxr(FPEXC, fpexc & ~(FPEXC_EXCEPTION|FPEXC_INV|FPEXC_UFC|FPEXC_IOC)); + + orig_fpscr = fpscr = fmrx(FPSCR); + + /* + * If we are running with inexact exceptions enabled, we need to + * emulate the trigger instruction. Note that as we're emulating + * the trigger instruction, we need to increment PC. + */ + if (fpscr & FPSCR_IXE) { + regs->ARM_pc += 4; + goto emulate; + } + + barrier(); + + /* + * Modify fpscr to indicate the number of iterations remaining + */ + if (fpexc & FPEXC_EXCEPTION) { + u32 len; + + len = fpexc + (1 << FPEXC_LENGTH_BIT); + + fpscr &= ~FPSCR_LENGTH_MASK; + fpscr |= (len & FPEXC_LENGTH_MASK) << (FPSCR_LENGTH_BIT - FPEXC_LENGTH_BIT); + } + + /* + * Handle the first FP instruction. We used to take note of the + * FPEXC bounce reason, but this appears to be unreliable. + * Emulate the bounced instruction instead. + */ + inst = fmrx(FPINST); + exceptions = vfp_emulate_instruction(inst, fpscr, regs); + if (exceptions) + vfp_raise_exceptions(exceptions, inst, orig_fpscr, regs); + + /* + * If there isn't a second FP instruction, exit now. + */ + if (!(fpexc & FPEXC_FPV2)) + return; + + /* + * The barrier() here prevents fpinst2 being read + * before the condition above. + */ + barrier(); + trigger = fmrx(FPINST2); + fpscr = fmrx(FPSCR); + + emulate: + exceptions = vfp_emulate_instruction(trigger, fpscr, regs); + if (exceptions) + vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); +} + +/* + * VFP support code initialisation. + */ +static int __init vfp_init(void) +{ + unsigned int vfpsid; + + /* + * First check that there is a VFP that we can use. + * The handler is already setup to just log calls, so + * we just need to read the VFPSID register. + */ + vfpsid = fmrx(FPSID); + + printk(KERN_INFO "VFP support v0.3: "); + if (VFP_arch) { + printk("not present\n"); + } else if (vfpsid & FPSID_NODOUBLE) { + printk("no double precision support\n"); + } else { + VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ + printk("implementor %02x architecture %d part %02x variant %x rev %x\n", + (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, + (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT, + (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, + (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, + (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); + vfp_vector = vfp_support_entry; + } + return 0; +} + +late_initcall(vfp_init); diff -Nru a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/arm/vfp/vfpsingle.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1224 @@ +/* + * linux/arch/arm/vfp/vfpsingle.c + * + * This code is derived in part from John R. Housers softfloat library, which + * carries the following notice: + * + * =========================================================================== + * This C source file is part of the SoftFloat IEC/IEEE Floating-point + * Arithmetic Package, Release 2. + * + * Written by John R. Hauser. This work was made possible in part by the + * International Computer Science Institute, located at Suite 600, 1947 Center + * Street, Berkeley, California 94704. Funding was partially provided by the + * National Science Foundation under grant MIP-9311980. The original version + * of this code was written as part of a project to build a fixed-point vector + * processor in collaboration with the University of California at Berkeley, + * overseen by Profs. Nelson Morgan and John Wawrzynek. More information + * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ + * arithmetic/softfloat.html'. + * + * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort + * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT + * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO + * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY + * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + * + * Derivative works are acceptable, even for commercial purposes, so long as + * (1) they include prominent notice that the work is derivative, and (2) they + * include prominent notice akin to these three paragraphs for those parts of + * this code that are retained. + * =========================================================================== + */ +#include +#include +#include +#include + +#include "vfpinstr.h" +#include "vfp.h" + +static struct vfp_single vfp_single_default_qnan = { + .exponent = 255, + .sign = 0, + .significand = VFP_SINGLE_SIGNIFICAND_QNAN, +}; + +static void vfp_single_dump(const char *str, struct vfp_single *s) +{ + pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n", + str, s->sign != 0, s->exponent, s->significand); +} + +static void vfp_single_normalise_denormal(struct vfp_single *vs) +{ + int bits = 31 - fls(vs->significand); + + vfp_single_dump("normalise_denormal: in", vs); + + if (bits) { + vs->exponent -= bits - 1; + vs->significand <<= bits; + } + + vfp_single_dump("normalise_denormal: out", vs); +} + +#ifndef DEBUG +#define vfp_single_normaliseround(sd,vsd,fpscr,except,func) __vfp_single_normaliseround(sd,vsd,fpscr,except) +u32 __vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions) +#else +u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func) +#endif +{ + u32 significand, incr, rmode; + int exponent, shift, underflow; + + vfp_single_dump("pack: in", vs); + + /* + * Infinities and NaNs are a special case. + */ + if (vs->exponent == 255 && (vs->significand == 0 || exceptions)) + goto pack; + + /* + * Special-case zero. + */ + if (vs->significand == 0) { + vs->exponent = 0; + goto pack; + } + + exponent = vs->exponent; + significand = vs->significand; + + /* + * Normalise first. Note that we shift the significand up to + * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least + * significant bit. + */ + shift = 32 - fls(significand); + if (shift < 32 && shift) { + exponent -= shift; + significand <<= shift; + } + +#ifdef DEBUG + vs->exponent = exponent; + vs->significand = significand; + vfp_single_dump("pack: normalised", vs); +#endif + + /* + * Tiny number? + */ + underflow = exponent < 0; + if (underflow) { + significand = vfp_shiftright32jamming(significand, -exponent); + exponent = 0; +#ifdef DEBUG + vs->exponent = exponent; + vs->significand = significand; + vfp_single_dump("pack: tiny number", vs); +#endif + if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))) + underflow = 0; + } + + /* + * Select rounding increment. + */ + incr = 0; + rmode = fpscr & FPSCR_RMODE_MASK; + + if (rmode == FPSCR_ROUND_NEAREST) { + incr = 1 << VFP_SINGLE_LOW_BITS; + if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0) + incr -= 1; + } else if (rmode == FPSCR_ROUND_TOZERO) { + incr = 0; + } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0)) + incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1; + + pr_debug("VFP: rounding increment = 0x%08x\n", incr); + + /* + * Is our rounding going to overflow? + */ + if ((significand + incr) < significand) { + exponent += 1; + significand = (significand >> 1) | (significand & 1); + incr >>= 1; +#ifdef DEBUG + vs->exponent = exponent; + vs->significand = significand; + vfp_single_dump("pack: overflow", vs); +#endif + } + + /* + * If any of the low bits (which will be shifted out of the + * number) are non-zero, the result is inexact. + */ + if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)) + exceptions |= FPSCR_IXC; + + /* + * Do our rounding. + */ + significand += incr; + + /* + * Infinity? + */ + if (exponent >= 254) { + exceptions |= FPSCR_OFC | FPSCR_IXC; + if (incr == 0) { + vs->exponent = 253; + vs->significand = 0x7fffffff; + } else { + vs->exponent = 255; /* infinity */ + vs->significand = 0; + } + } else { + if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0) + exponent = 0; + if (exponent || significand > 0x80000000) + underflow = 0; + if (underflow) + exceptions |= FPSCR_UFC; + vs->exponent = exponent; + vs->significand = significand >> 1; + } + + pack: + vfp_single_dump("pack: final", vs); + { + s32 d = vfp_single_pack(vs); + pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func, + sd, d, exceptions); + vfp_put_float(sd, d); + } + + return exceptions; +} + +/* + * Propagate the NaN, setting exceptions if it is signalling. + * 'n' is always a NaN. 'm' may be a number, NaN or infinity. + */ +static u32 +vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, + struct vfp_single *vsm, u32 fpscr) +{ + struct vfp_single *nan; + int tn, tm = 0; + + tn = vfp_single_type(vsn); + + if (vsm) + tm = vfp_single_type(vsm); + + if (fpscr & FPSCR_DEFAULT_NAN) + /* + * Default NaN mode - always returns a quiet NaN + */ + nan = &vfp_single_default_qnan; + else { + /* + * Contemporary mode - select the first signalling + * NAN, or if neither are signalling, the first + * quiet NAN. + */ + if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN)) + nan = vsn; + else + nan = vsm; + /* + * Make the NaN quiet. + */ + nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN; + } + + *vsd = *nan; + + /* + * If one was a signalling NAN, raise invalid operation. + */ + return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : 0x100; +} + + +/* + * Extended operations + */ +static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr) +{ + vfp_put_float(sd, vfp_single_packed_abs(m)); + return 0; +} + +static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr) +{ + vfp_put_float(sd, m); + return 0; +} + +static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr) +{ + vfp_put_float(sd, vfp_single_packed_negate(m)); + return 0; +} + +static const u16 sqrt_oddadjust[] = { + 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0, + 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67 +}; + +static const u16 sqrt_evenadjust[] = { + 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e, + 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002 +}; + +u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) +{ + int index; + u32 z, a; + + if ((significand & 0xc0000000) != 0x40000000) { + printk(KERN_WARNING "VFP: estimate_sqrt: invalid significand\n"); + } + + a = significand << 1; + index = (a >> 27) & 15; + if (exponent & 1) { + z = 0x4000 + (a >> 17) - sqrt_oddadjust[index]; + z = ((a / z) << 14) + (z << 15); + a >>= 1; + } else { + z = 0x8000 + (a >> 17) - sqrt_evenadjust[index]; + z = a / z + z; + z = (z >= 0x20000) ? 0xffff8000 : (z << 15); + if (z <= a) + return (s32)a >> 1; + } + return (u32)(((u64)a << 31) / z) + (z >> 1); +} + +static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr) +{ + struct vfp_single vsm, vsd; + int ret, tm; + + vfp_single_unpack(&vsm, m); + tm = vfp_single_type(&vsm); + if (tm & (VFP_NAN|VFP_INFINITY)) { + struct vfp_single *vsp = &vsd; + + if (tm & VFP_NAN) + ret = vfp_propagate_nan(vsp, &vsm, NULL, fpscr); + else if (vsm.sign == 0) { + sqrt_copy: + vsp = &vsm; + ret = 0; + } else { + sqrt_invalid: + vsp = &vfp_single_default_qnan; + ret = FPSCR_IOC; + } + vfp_put_float(sd, vfp_single_pack(vsp)); + return ret; + } + + /* + * sqrt(+/- 0) == +/- 0 + */ + if (tm & VFP_ZERO) + goto sqrt_copy; + + /* + * Normalise a denormalised number + */ + if (tm & VFP_DENORMAL) + vfp_single_normalise_denormal(&vsm); + + /* + * sqrt(<0) = invalid + */ + if (vsm.sign) + goto sqrt_invalid; + + vfp_single_dump("sqrt", &vsm); + + /* + * Estimate the square root. + */ + vsd.sign = 0; + vsd.exponent = ((vsm.exponent - 127) >> 1) + 127; + vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2; + + vfp_single_dump("sqrt estimate", &vsd); + + /* + * And now adjust. + */ + if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) { + if (vsd.significand < 2) { + vsd.significand = 0xffffffff; + } else { + u64 term; + s64 rem; + vsm.significand <<= !(vsm.exponent & 1); + term = (u64)vsd.significand * vsd.significand; + rem = ((u64)vsm.significand << 32) - term; + + pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem); + + while (rem < 0) { + vsd.significand -= 1; + rem += ((u64)vsd.significand << 1) | 1; + } + vsd.significand |= rem != 0; + } + } + vsd.significand = vfp_shiftright32jamming(vsd.significand, 1); + + return vfp_single_normaliseround(sd, &vsd, fpscr, 0, "fsqrt"); +} + +/* + * Equal := ZC + * Less than := N + * Greater than := C + * Unordered := CV + */ +static u32 vfp_compare(int sd, int signal_on_qnan, s32 m, u32 fpscr) +{ + s32 d; + u32 ret = 0; + + d = vfp_get_float(sd); + if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) { + ret |= FPSCR_C | FPSCR_V; + if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) + /* + * Signalling NaN, or signalling on quiet NaN + */ + ret |= FPSCR_IOC; + } + + if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) { + ret |= FPSCR_C | FPSCR_V; + if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) + /* + * Signalling NaN, or signalling on quiet NaN + */ + ret |= FPSCR_IOC; + } + + if (ret == 0) { + if (d == m || vfp_single_packed_abs(d | m) == 0) { + /* + * equal + */ + ret |= FPSCR_Z | FPSCR_C; + } else if (vfp_single_packed_sign(d ^ m)) { + /* + * different signs + */ + if (vfp_single_packed_sign(d)) + /* + * d is negative, so d < m + */ + ret |= FPSCR_N; + else + /* + * d is positive, so d > m + */ + ret |= FPSCR_C; + } else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) { + /* + * d < m + */ + ret |= FPSCR_N; + } else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) { + /* + * d > m + */ + ret |= FPSCR_C; + } + } + return ret; +} + +static u32 vfp_single_fcmp(int sd, int unused, s32 m, u32 fpscr) +{ + return vfp_compare(sd, 0, m, fpscr); +} + +static u32 vfp_single_fcmpe(int sd, int unused, s32 m, u32 fpscr) +{ + return vfp_compare(sd, 1, m, fpscr); +} + +static u32 vfp_single_fcmpz(int sd, int unused, s32 m, u32 fpscr) +{ + return vfp_compare(sd, 0, 0, fpscr); +} + +static u32 vfp_single_fcmpez(int sd, int unused, s32 m, u32 fpscr) +{ + return vfp_compare(sd, 1, 0, fpscr); +} + +static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr) +{ + struct vfp_single vsm; + struct vfp_double vdd; + int tm; + u32 exceptions = 0; + + vfp_single_unpack(&vsm, m); + + tm = vfp_single_type(&vsm); + + /* + * If we have a signalling NaN, signal invalid operation. + */ + if (tm == VFP_SNAN) + exceptions = FPSCR_IOC; + + if (tm & VFP_DENORMAL) + vfp_single_normalise_denormal(&vsm); + + vdd.sign = vsm.sign; + vdd.significand = (u64)vsm.significand << 32; + + /* + * If we have an infinity or NaN, the exponent must be 2047. + */ + if (tm & (VFP_INFINITY|VFP_NAN)) { + vdd.exponent = 2047; + if (tm & VFP_NAN) + vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; + goto pack_nan; + } else if (tm & VFP_ZERO) + vdd.exponent = 0; + else + vdd.exponent = vsm.exponent + (1023 - 127); + + /* + * Technically, if bit 0 of dd is set, this is an invalid + * instruction. However, we ignore this for efficiency. + */ + return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd"); + + pack_nan: + vfp_put_double(dd, vfp_double_pack(&vdd)); + return exceptions; +} + +static u32 vfp_single_fuito(int sd, int unused, s32 m, u32 fpscr) +{ + struct vfp_single vs; + + vs.sign = 0; + vs.exponent = 127 + 31 - 1; + vs.significand = (u32)m; + + return vfp_single_normaliseround(sd, &vs, fpscr, 0, "fuito"); +} + +static u32 vfp_single_fsito(int sd, int unused, s32 m, u32 fpscr) +{ + struct vfp_single vs; + + vs.sign = (m & 0x80000000) >> 16; + vs.exponent = 127 + 31 - 1; + vs.significand = vs.sign ? -m : m; + + return vfp_single_normaliseround(sd, &vs, fpscr, 0, "fsito"); +} + +static u32 vfp_single_ftoui(int sd, int unused, s32 m, u32 fpscr) +{ + struct vfp_single vsm; + u32 d, exceptions = 0; + int rmode = fpscr & FPSCR_RMODE_MASK; + int tm; + + vfp_single_unpack(&vsm, m); + vfp_single_dump("VSM", &vsm); + + /* + * Do we have a denormalised number? + */ + tm = vfp_single_type(&vsm); + if (tm & VFP_DENORMAL) + exceptions |= FPSCR_IDC; + + if (tm & VFP_NAN) + vsm.sign = 0; + + if (vsm.exponent >= 127 + 32) { + d = vsm.sign ? 0 : 0xffffffff; + exceptions = FPSCR_IOC; + } else if (vsm.exponent >= 127 - 1) { + int shift = 127 + 31 - vsm.exponent; + u32 rem, incr = 0; + + /* + * 2^0 <= m < 2^32-2^8 + */ + d = (vsm.significand << 1) >> shift; + rem = vsm.significand << (33 - shift); + + if (rmode == FPSCR_ROUND_NEAREST) { + incr = 0x80000000; + if ((d & 1) == 0) + incr -= 1; + } else if (rmode == FPSCR_ROUND_TOZERO) { + incr = 0; + } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) { + incr = ~0; + } + + if ((rem + incr) < rem) { + if (d < 0xffffffff) + d += 1; + else + exceptions |= FPSCR_IOC; + } + + if (d && vsm.sign) { + d = 0; + exceptions |= FPSCR_IOC; + } else if (rem) + exceptions |= FPSCR_IXC; + } else { + d = 0; + if (vsm.exponent | vsm.significand) { + exceptions |= FPSCR_IXC; + if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) + d = 1; + else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { + d = 0; + exceptions |= FPSCR_IOC; + } + } + } + + pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); + + vfp_put_float(sd, d); + + return exceptions; +} + +static u32 vfp_single_ftouiz(int sd, int unused, s32 m, u32 fpscr) +{ + return vfp_single_ftoui(sd, unused, m, FPSCR_ROUND_TOZERO); +} + +static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr) +{ + struct vfp_single vsm; + u32 d, exceptions = 0; + int rmode = fpscr & FPSCR_RMODE_MASK; + + vfp_single_unpack(&vsm, m); + vfp_single_dump("VSM", &vsm); + + /* + * Do we have a denormalised number? + */ + if (vfp_single_type(&vsm) & VFP_DENORMAL) + exceptions |= FPSCR_IDC; + + if (vsm.exponent >= 127 + 32) { + /* + * m >= 2^31-2^7: invalid + */ + d = 0x7fffffff; + if (vsm.sign) + d = ~d; + exceptions |= FPSCR_IOC; + } else if (vsm.exponent >= 127 - 1) { + int shift = 127 + 31 - vsm.exponent; + u32 rem, incr = 0; + + /* 2^0 <= m <= 2^31-2^7 */ + d = (vsm.significand << 1) >> shift; + rem = vsm.significand << (33 - shift); + + if (rmode == FPSCR_ROUND_NEAREST) { + incr = 0x80000000; + if ((d & 1) == 0) + incr -= 1; + } else if (rmode == FPSCR_ROUND_TOZERO) { + incr = 0; + } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) { + incr = ~0; + } + + if ((rem + incr) < rem && d < 0xffffffff) + d += 1; + if (d > 0x7fffffff + (vsm.sign != 0)) { + d = 0x7fffffff + (vsm.sign != 0); + exceptions |= FPSCR_IOC; + } else if (rem) + exceptions |= FPSCR_IXC; + + if (vsm.sign) + d = -d; + } else { + d = 0; + if (vsm.exponent | vsm.significand) { + exceptions |= FPSCR_IXC; + if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) + d = 1; + else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) + d = -1; + } + } + + pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); + + vfp_put_float(sd, (s32)d); + + return exceptions; +} + +static u32 vfp_single_ftosiz(int sd, int unused, s32 m, u32 fpscr) +{ + return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO); +} + +static u32 (* const fop_extfns[32])(int sd, int unused, s32 m, u32 fpscr) = { + [FEXT_TO_IDX(FEXT_FCPY)] = vfp_single_fcpy, + [FEXT_TO_IDX(FEXT_FABS)] = vfp_single_fabs, + [FEXT_TO_IDX(FEXT_FNEG)] = vfp_single_fneg, + [FEXT_TO_IDX(FEXT_FSQRT)] = vfp_single_fsqrt, + [FEXT_TO_IDX(FEXT_FCMP)] = vfp_single_fcmp, + [FEXT_TO_IDX(FEXT_FCMPE)] = vfp_single_fcmpe, + [FEXT_TO_IDX(FEXT_FCMPZ)] = vfp_single_fcmpz, + [FEXT_TO_IDX(FEXT_FCMPEZ)] = vfp_single_fcmpez, + [FEXT_TO_IDX(FEXT_FCVT)] = vfp_single_fcvtd, + [FEXT_TO_IDX(FEXT_FUITO)] = vfp_single_fuito, + [FEXT_TO_IDX(FEXT_FSITO)] = vfp_single_fsito, + [FEXT_TO_IDX(FEXT_FTOUI)] = vfp_single_ftoui, + [FEXT_TO_IDX(FEXT_FTOUIZ)] = vfp_single_ftouiz, + [FEXT_TO_IDX(FEXT_FTOSI)] = vfp_single_ftosi, + [FEXT_TO_IDX(FEXT_FTOSIZ)] = vfp_single_ftosiz, +}; + + + + + +static u32 +vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn, + struct vfp_single *vsm, u32 fpscr) +{ + struct vfp_single *vsp; + u32 exceptions = 0; + int tn, tm; + + tn = vfp_single_type(vsn); + tm = vfp_single_type(vsm); + + if (tn & tm & VFP_INFINITY) { + /* + * Two infinities. Are they different signs? + */ + if (vsn->sign ^ vsm->sign) { + /* + * different signs -> invalid + */ + exceptions = FPSCR_IOC; + vsp = &vfp_single_default_qnan; + } else { + /* + * same signs -> valid + */ + vsp = vsn; + } + } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) { + /* + * One infinity and one number -> infinity + */ + vsp = vsn; + } else { + /* + * 'n' is a NaN of some type + */ + return vfp_propagate_nan(vsd, vsn, vsm, fpscr); + } + *vsd = *vsp; + return exceptions; +} + +static u32 +vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, + struct vfp_single *vsm, u32 fpscr) +{ + u32 exp_diff, m_sig; + + if (vsn->significand & 0x80000000 || + vsm->significand & 0x80000000) { + pr_info("VFP: bad FP values in %s\n", __func__); + vfp_single_dump("VSN", vsn); + vfp_single_dump("VSM", vsm); + } + + /* + * Ensure that 'n' is the largest magnitude number. Note that + * if 'n' and 'm' have equal exponents, we do not swap them. + * This ensures that NaN propagation works correctly. + */ + if (vsn->exponent < vsm->exponent) { + struct vfp_single *t = vsn; + vsn = vsm; + vsm = t; + } + + /* + * Is 'n' an infinity or a NaN? Note that 'm' may be a number, + * infinity or a NaN here. + */ + if (vsn->exponent == 255) + return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr); + + /* + * We have two proper numbers, where 'vsn' is the larger magnitude. + * + * Copy 'n' to 'd' before doing the arithmetic. + */ + *vsd = *vsn; + + /* + * Align both numbers. + */ + exp_diff = vsn->exponent - vsm->exponent; + m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff); + + /* + * If the signs are different, we are really subtracting. + */ + if (vsn->sign ^ vsm->sign) { + m_sig = vsn->significand - m_sig; + if ((s32)m_sig < 0) { + vsd->sign = vfp_sign_negate(vsd->sign); + m_sig = -m_sig; + } else if (m_sig == 0) { + vsd->sign = (fpscr & FPSCR_RMODE_MASK) == + FPSCR_ROUND_MINUSINF ? 0x8000 : 0; + } + } else { + m_sig = vsn->significand + m_sig; + } + vsd->significand = m_sig; + + return 0; +} + +static u32 +vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr) +{ + vfp_single_dump("VSN", vsn); + vfp_single_dump("VSM", vsm); + + /* + * Ensure that 'n' is the largest magnitude number. Note that + * if 'n' and 'm' have equal exponents, we do not swap them. + * This ensures that NaN propagation works correctly. + */ + if (vsn->exponent < vsm->exponent) { + struct vfp_single *t = vsn; + vsn = vsm; + vsm = t; + pr_debug("VFP: swapping M <-> N\n"); + } + + vsd->sign = vsn->sign ^ vsm->sign; + + /* + * If 'n' is an infinity or NaN, handle it. 'm' may be anything. + */ + if (vsn->exponent == 255) { + if (vsn->significand || (vsm->exponent == 255 && vsm->significand)) + return vfp_propagate_nan(vsd, vsn, vsm, fpscr); + if ((vsm->exponent | vsm->significand) == 0) { + *vsd = vfp_single_default_qnan; + return FPSCR_IOC; + } + vsd->exponent = vsn->exponent; + vsd->significand = 0; + return 0; + } + + /* + * If 'm' is zero, the result is always zero. In this case, + * 'n' may be zero or a number, but it doesn't matter which. + */ + if ((vsm->exponent | vsm->significand) == 0) { + vsd->exponent = 0; + vsd->significand = 0; + return 0; + } + + /* + * We add 2 to the destination exponent for the same reason as + * the addition case - though this time we have +1 from each + * input operand. + */ + vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2; + vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand); + + vfp_single_dump("VSD", vsd); + return 0; +} + +#define NEG_MULTIPLY (1 << 0) +#define NEG_SUBTRACT (1 << 1) + +static u32 +vfp_single_multiply_accumulate(int sd, int sn, s32 m, u32 fpscr, u32 negate, char *func) +{ + struct vfp_single vsd, vsp, vsn, vsm; + u32 exceptions; + s32 v; + + v = vfp_get_float(sn); + pr_debug("VFP: s%u = %08x\n", sn, v); + vfp_single_unpack(&vsn, v); + if (vsn.exponent == 0 && vsn.significand) + vfp_single_normalise_denormal(&vsn); + + vfp_single_unpack(&vsm, m); + if (vsm.exponent == 0 && vsm.significand) + vfp_single_normalise_denormal(&vsm); + + exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr); + if (negate & NEG_MULTIPLY) + vsp.sign = vfp_sign_negate(vsp.sign); + + v = vfp_get_float(sd); + pr_debug("VFP: s%u = %08x\n", sd, v); + vfp_single_unpack(&vsn, v); + if (negate & NEG_SUBTRACT) + vsn.sign = vfp_sign_negate(vsn.sign); + + exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr); + + return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, func); +} + +/* + * Standard operations + */ + +/* + * sd = sd + (sn * sm) + */ +static u32 vfp_single_fmac(int sd, int sn, s32 m, u32 fpscr) +{ + return vfp_single_multiply_accumulate(sd, sn, m, fpscr, 0, "fmac"); +} + +/* + * sd = sd - (sn * sm) + */ +static u32 vfp_single_fnmac(int sd, int sn, s32 m, u32 fpscr) +{ + return vfp_single_multiply_accumulate(sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); +} + +/* + * sd = -sd + (sn * sm) + */ +static u32 vfp_single_fmsc(int sd, int sn, s32 m, u32 fpscr) +{ + return vfp_single_multiply_accumulate(sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); +} + +/* + * sd = -sd - (sn * sm) + */ +static u32 vfp_single_fnmsc(int sd, int sn, s32 m, u32 fpscr) +{ + return vfp_single_multiply_accumulate(sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); +} + +/* + * sd = sn * sm + */ +static u32 vfp_single_fmul(int sd, int sn, s32 m, u32 fpscr) +{ + struct vfp_single vsd, vsn, vsm; + u32 exceptions; + s32 n = vfp_get_float(sn); + + pr_debug("VFP: s%u = %08x\n", sn, n); + + vfp_single_unpack(&vsn, n); + if (vsn.exponent == 0 && vsn.significand) + vfp_single_normalise_denormal(&vsn); + + vfp_single_unpack(&vsm, m); + if (vsm.exponent == 0 && vsm.significand) + vfp_single_normalise_denormal(&vsm); + + exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); + return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fmul"); +} + +/* + * sd = -(sn * sm) + */ +static u32 vfp_single_fnmul(int sd, int sn, s32 m, u32 fpscr) +{ + struct vfp_single vsd, vsn, vsm; + u32 exceptions; + s32 n = vfp_get_float(sn); + + pr_debug("VFP: s%u = %08x\n", sn, n); + + vfp_single_unpack(&vsn, n); + if (vsn.exponent == 0 && vsn.significand) + vfp_single_normalise_denormal(&vsn); + + vfp_single_unpack(&vsm, m); + if (vsm.exponent == 0 && vsm.significand) + vfp_single_normalise_denormal(&vsm); + + exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); + vsd.sign = vfp_sign_negate(vsd.sign); + return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fnmul"); +} + +/* + * sd = sn + sm + */ +static u32 vfp_single_fadd(int sd, int sn, s32 m, u32 fpscr) +{ + struct vfp_single vsd, vsn, vsm; + u32 exceptions; + s32 n = vfp_get_float(sn); + + pr_debug("VFP: s%u = %08x\n", sn, n); + + /* + * Unpack and normalise denormals. + */ + vfp_single_unpack(&vsn, n); + if (vsn.exponent == 0 && vsn.significand) + vfp_single_normalise_denormal(&vsn); + + vfp_single_unpack(&vsm, m); + if (vsm.exponent == 0 && vsm.significand) + vfp_single_normalise_denormal(&vsm); + + exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr); + + return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fadd"); +} + +/* + * sd = sn - sm + */ +static u32 vfp_single_fsub(int sd, int sn, s32 m, u32 fpscr) +{ + /* + * Subtraction is addition with one sign inverted. + */ + return vfp_single_fadd(sd, sn, vfp_single_packed_negate(m), fpscr); +} + +/* + * sd = sn / sm + */ +static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr) +{ + struct vfp_single vsd, vsn, vsm; + u32 exceptions = 0; + s32 n = vfp_get_float(sn); + int tm, tn; + + pr_debug("VFP: s%u = %08x\n", sn, n); + + vfp_single_unpack(&vsn, n); + vfp_single_unpack(&vsm, m); + + vsd.sign = vsn.sign ^ vsm.sign; + + tn = vfp_single_type(&vsn); + tm = vfp_single_type(&vsm); + + /* + * Is n a NAN? + */ + if (tn & VFP_NAN) + goto vsn_nan; + + /* + * Is m a NAN? + */ + if (tm & VFP_NAN) + goto vsm_nan; + + /* + * If n and m are infinity, the result is invalid + * If n and m are zero, the result is invalid + */ + if (tm & tn & (VFP_INFINITY|VFP_ZERO)) + goto invalid; + + /* + * If n is infinity, the result is infinity + */ + if (tn & VFP_INFINITY) + goto infinity; + + /* + * If m is zero, raise div0 exception + */ + if (tm & VFP_ZERO) + goto divzero; + + /* + * If m is infinity, or n is zero, the result is zero + */ + if (tm & VFP_INFINITY || tn & VFP_ZERO) + goto zero; + + if (tn & VFP_DENORMAL) + vfp_single_normalise_denormal(&vsn); + if (tm & VFP_DENORMAL) + vfp_single_normalise_denormal(&vsm); + + /* + * Ok, we have two numbers, we can perform division. + */ + vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1; + vsm.significand <<= 1; + if (vsm.significand <= (2 * vsn.significand)) { + vsn.significand >>= 1; + vsd.exponent++; + } + vsd.significand = ((u64)vsn.significand << 32) / vsm.significand; + if ((vsd.significand & 0x3f) == 0) + vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32); + + return vfp_single_normaliseround(sd, &vsd, fpscr, 0, "fdiv"); + + vsn_nan: + exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); + pack: + vfp_put_float(sd, vfp_single_pack(&vsd)); + return exceptions; + + vsm_nan: + exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr); + goto pack; + + zero: + vsd.exponent = 0; + vsd.significand = 0; + goto pack; + + divzero: + exceptions = FPSCR_DZC; + infinity: + vsd.exponent = 255; + vsd.significand = 0; + goto pack; + + invalid: + vfp_put_float(sd, vfp_single_pack(&vfp_single_default_qnan)); + return FPSCR_IOC; +} + +static u32 (* const fop_fns[16])(int sd, int sn, s32 m, u32 fpscr) = { + [FOP_TO_IDX(FOP_FMAC)] = vfp_single_fmac, + [FOP_TO_IDX(FOP_FNMAC)] = vfp_single_fnmac, + [FOP_TO_IDX(FOP_FMSC)] = vfp_single_fmsc, + [FOP_TO_IDX(FOP_FNMSC)] = vfp_single_fnmsc, + [FOP_TO_IDX(FOP_FMUL)] = vfp_single_fmul, + [FOP_TO_IDX(FOP_FNMUL)] = vfp_single_fnmul, + [FOP_TO_IDX(FOP_FADD)] = vfp_single_fadd, + [FOP_TO_IDX(FOP_FSUB)] = vfp_single_fsub, + [FOP_TO_IDX(FOP_FDIV)] = vfp_single_fdiv, +}; + +#define FREG_BANK(x) ((x) & 0x18) +#define FREG_IDX(x) ((x) & 7) + +u32 vfp_single_cpdo(u32 inst, u32 fpscr) +{ + u32 op = inst & FOP_MASK; + u32 exceptions = 0; + unsigned int sd = vfp_get_sd(inst); + unsigned int sn = vfp_get_sn(inst); + unsigned int sm = vfp_get_sm(inst); + unsigned int vecitr, veclen, vecstride; + u32 (*fop)(int, int, s32, u32); + + veclen = fpscr & FPSCR_LENGTH_MASK; + vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); + + /* + * If destination bank is zero, vector length is always '1'. + * ARM DDI0100F C5.1.3, C5.3.2. + */ + if (FREG_BANK(sd) == 0) + veclen = 0; + + pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, + (veclen >> FPSCR_LENGTH_BIT) + 1); + + fop = (op == FOP_EXT) ? fop_extfns[sn] : fop_fns[FOP_TO_IDX(op)]; + if (!fop) + goto invalid; + + for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { + s32 m = vfp_get_float(sm); + u32 except; + + if (op == FOP_EXT) + pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n", + vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m); + else + pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n", + vecitr >> FPSCR_LENGTH_BIT, sd, sn, + FOP_TO_IDX(op), sm, m); + + except = fop(sd, sn, m, fpscr); + pr_debug("VFP: itr%d: exceptions=%08x\n", + vecitr >> FPSCR_LENGTH_BIT, except); + + exceptions |= except; + + /* + * This ensures that comparisons only operate on scalars; + * comparisons always return with one FPSCR status bit set. + */ + if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) + break; + + /* + * CHECK: It appears to be undefined whether we stop when + * we encounter an exception. We continue. + */ + + sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7); + sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7); + if (FREG_BANK(sm) != 0) + sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7); + } + return exceptions; + + invalid: + return (u32)-1; +} diff -Nru a/arch/arm26/kernel/init_task.c b/arch/arm26/kernel/init_task.c --- a/arch/arm26/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/arm26/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c --- a/arch/cris/kernel/process.c 2004-06-20 13:00:25 -07:00 +++ b/arch/cris/kernel/process.c 2004-06-20 13:00:25 -07:00 @@ -112,6 +112,7 @@ #include #include #include +#include //#define DEBUG diff -Nru a/arch/h8300/Kconfig b/arch/h8300/Kconfig --- a/arch/h8300/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/arch/h8300/Kconfig 2004-06-20 13:00:25 -07:00 @@ -223,7 +223,7 @@ config CONFIG_SH_STANDARD_BIOS bool "Use gdb protocol serial console" - depends on (!H8300H_SIM && H8S_SIM) + depends on (!H8300H_SIM && !H8S_SIM) help serial console output using GDB protocol. Require eCos/RedBoot diff -Nru a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c --- a/arch/h8300/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/h8300/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c --- a/arch/h8300/kernel/ptrace.c 2004-06-20 13:00:24 -07:00 +++ b/arch/h8300/kernel/ptrace.c 2004-06-20 13:00:24 -07:00 @@ -116,18 +116,36 @@ case PTRACE_PEEKUSR: { unsigned long tmp; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { ret = -EIO; + break ; + } - tmp = 0; /* Default return condition */ + ret = 0; /* Default return condition */ addr = addr >> 2; /* temporary hack. */ + if (addr < H8300_REGS_NO) tmp = h8300_get_reg(child, addr); else { - ret = -EIO; - break ; + switch(addr) { + case 49: + tmp = child->mm->start_code; + break ; + case 50: + tmp = child->mm->start_data; + break ; + case 51: + tmp = child->mm->end_code; + break ; + case 52: + tmp = child->mm->end_data; + break ; + default: + ret = -EIO; + } } - ret = put_user(tmp,(unsigned long *) data); + if (!ret) + ret = put_user(tmp,(unsigned long *) data); break ; } diff -Nru a/arch/h8300/platform/h8s/entry.S b/arch/h8300/platform/h8s/entry.S --- a/arch/h8300/platform/h8s/entry.S 2004-06-20 13:00:25 -07:00 +++ b/arch/h8300/platform/h8s/entry.S 2004-06-20 13:00:25 -07:00 @@ -83,6 +83,7 @@ mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */ mov.l er1,@er0 mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */ + mov.b r1l,r1h mov.w r1,@(8:16,er0) mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */ mov.b r1l,r1h @@ -213,7 +214,6 @@ mov.l er0,@(LER0:16,sp) /* save the return value */ jsr @SYMBOL_NAME(syscall_trace) bra SYMBOL_NAME(ret_from_exception):8 - SYMBOL_NAME_LABEL(ret_from_fork) mov.l er2,er0 diff -Nru a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c --- a/arch/h8300/platform/h8s/ptrace_h8s.c 2004-06-20 13:00:23 -07:00 +++ b/arch/h8300/platform/h8s/ptrace_h8s.c 2004-06-20 13:00:23 -07:00 @@ -23,7 +23,7 @@ static const int h8300_register_offset[] = { PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4), PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0), - PT_REG(ccr), PT_REG(pc), PT_REG(exr) + PT_REG(ccr), PT_REG(pc), 0, PT_REG(exr) }; /* read register */ diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/Kconfig 2004-06-20 13:00:23 -07:00 @@ -436,7 +436,8 @@ Choose N to continue using the legacy 8254 timer. config HPET_EMULATE_RTC - def_bool HPET_TIMER && RTC=y + bool "Provide RTC interrupt" + depends on HPET_TIMER && RTC=y config SMP bool "Symmetric multi-processing support" @@ -1333,12 +1334,6 @@ config X86_TRAMPOLINE bool depends on X86_SMP || (X86_VOYAGER && SMP) - default y - -# std_resources is overridden for pc9800, but that's not -# a currently selectable arch choice -config X86_STD_RESOURCES - bool default y config PC diff -Nru a/arch/i386/boot98/Makefile b/arch/i386/boot98/Makefile --- a/arch/i386/boot98/Makefile 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,102 +0,0 @@ -# -# arch/i386/boot/Makefile -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 1994 by Linus Torvalds -# - -# ROOT_DEV specifies the default root-device when making the image. -# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case -# the default of FLOPPY is used by 'build'. - -ROOT_DEV := CURRENT - -# If you want to preset the SVGA mode, uncomment the next line and -# set SVGA_MODE to whatever number you want. -# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. -# The number is the same as you would ordinarily press at bootup. - -SVGA_MODE := -DSVGA_MODE=NORMAL_VGA - -# If you want the RAM disk device, define this to be the size in blocks. - -#RAMDISK := -DRAMDISK=512 - -targets := vmlinux.bin bootsect bootsect.o setup setup.o \ - zImage bzImage -subdir- := compressed - -host-progs := tools/build - -# --------------------------------------------------------------------------- - -$(obj)/zImage: IMAGE_OFFSET := 0x1000 -$(obj)/zImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -$(obj)/bzImage: IMAGE_OFFSET := 0x100000 -$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ -$(obj)/bzImage: BUILDFLAGS := -b - -quiet_cmd_image = BUILD $@ -cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ - $(obj)/vmlinux.bin $(ROOT_DEV) > $@ - -$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ - $(obj)/vmlinux.bin $(obj)/tools/build FORCE - $(call if_changed,image) - @echo 'Kernel: $@ is ready' - -$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE - $(call if_changed,objcopy) - -LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary -LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext - -$(obj)/setup $(obj)/bootsect: %: %.o FORCE - $(call if_changed,ld) - -$(obj)/compressed/vmlinux: FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ - -# Set this if you want to pass append arguments to the zdisk/fdimage kernel -FDARGS = - -$(obj)/mtools.conf: $(src)/mtools.conf.in - sed -e 's|@OBJ@|$(obj)|g' < $< > $@ - -# This requires write access to /dev/fd0 -zdisk: $(BOOTIMAGE) $(obj)/mtools.conf - MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync - syslinux /dev/fd0 ; sync - echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg - MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync - -# These require being root or having syslinux 2.02 or higher installed -fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf - dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 - MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync - syslinux $(obj)/fdimage ; sync - echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg - MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync - -fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf - dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 - MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync - syslinux $(obj)/fdimage ; sync - echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg - MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync - -zlilo: $(BOOTIMAGE) - if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi - if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi - cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz - cp System.map $(INSTALL_PATH)/ - if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi - -install: $(BOOTIMAGE) - sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff -Nru a/arch/i386/boot98/bootsect.S b/arch/i386/boot98/bootsect.S --- a/arch/i386/boot98/bootsect.S 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,397 +0,0 @@ -/* - * bootsect.S - boot sector for NEC PC-9800 series - * - * Linux/98 project at Kyoto University Microcomputer Club (KMC) - * FUJITA Norimasa, TAKAI Kousuke 1997-1998 - * rewritten by TAKAI Kousuke (as86 -> gas), Nov 1999 - * - * Based on: - * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds - * modified by Drew Eckhardt - * modified by Bruce Evans (bde) - * - * bootsect.S is loaded at 0x1FC00 or 0x1FE00 by the bios-startup routines, - * and moves itself out of the way to address 0x90000, and jumps there. - * - * It then loads 'setup' directly after itself (0x90200), and the system - * at 0x10000, using BIOS interrupts. - * - * NOTE! currently system is at most (8*65536-4096) bytes long. This should - * be no problem, even in the future. I want to keep it simple. This 508 kB - * kernel size should be enough, especially as this doesn't contain the - * buffer cache as in minix (and especially now that the kernel is - * compressed :-) - * - * The loader has been made as simple as possible, and continuous - * read errors will result in a unbreakable loop. Reboot by hand. It - * loads pretty fast by getting whole tracks at a time whenever possible. - */ - -#include /* for CONFIG_ROOT_RDONLY */ -#include - -SETUPSECTS = 4 /* default nr of setup-sectors */ -BOOTSEG = 0x1FC0 /* original address of boot-sector */ -INITSEG = DEF_INITSEG /* we move boot here - out of the way */ -SETUPSEG = DEF_SETUPSEG /* setup starts here */ -SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ -SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ - /* to be loaded */ -ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ -SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ - -#ifndef SVGA_MODE -#define SVGA_MODE ASK_VGA -#endif - -#ifndef RAMDISK -#define RAMDISK 0 -#endif - -#ifndef ROOT_RDONLY -#define ROOT_RDONLY 1 -#endif - -/* normal/hireso text VRAM segments */ -#define NORMAL_TEXT 0xa000 -#define HIRESO_TEXT 0xe000 - -/* bios work area addresses */ -#define EXPMMSZ 0x0401 -#define BIOS_FLAG 0x0501 -#define DISK_BOOT 0x0584 - -.code16 -.text - -.global _start -_start: - -#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */ - int $0x3 -#endif - jmp real_start - .ascii "Linux 98" - .word 0 -real_start: - xorw %di, %di /* %di = 0 */ - movw %di, %ss /* %ss = 0 */ - movw $0x03F0, %sp - pushw %cx /* for hint */ - - movw $0x0A00, %ax /* normal mode defaults (80x25) */ - - testb $0x08, %ss:BIOS_FLAG /* check hi-reso bit */ - jnz set_crt_mode -/* - * Hi-Reso (high-resolution) machine. - * - * Some hi-reso machines have no RAMs on bank 8/A (0x080000 - 0x0BFFFF). - * On such machines we get two RAM banks from top of protect menory and - * map them on bank 8/A. - * These work-around must be done before moving myself on INITSEG (0x090000-). - */ - movw $(HIRESO_TEXT >> 8), %cs:(vram + 1) /* text VRAM segment */ - - /* set memory window */ - movb $0x08, %al - outb %al, $0x91 /* map native RAM (if any) */ - movb $0x0A, %al - outb %al, $0x93 - - /* check bank ram A */ - pushw $0xA500 - popw %ds - movw (%di), %cx /* %si == 0 from entry */ - notw %cx - movw %cx, (%di) - - movw $0x43F, %dx /* cache flush for 486 and up. */ - movb $0xA0, %al - outb %al, %dx - - cmpw %cx, (%di) - je hireso_done - - /* - * Write test failed; we have no native RAM on 080000h - 0BFFFFh. - * Take 256KB of RAM from top of protected memory. - */ - movb %ss:EXPMMSZ, %al - subb $2, %al /* reduce 2 x 128KB */ - movb %al, %ss:EXPMMSZ - addb %al, %al - addb $0x10, %al - outb %al, $0x91 - addb $2, %al - outb %al, $0x93 - -hireso_done: - movb $0x10, %al /* CRT mode 80x31, %ah still 0Ah */ - -set_crt_mode: - int $0x18 /* set CRT mode */ - - movb $0x0C, %ah /* turn on text displaying */ - int $0x18 - - xorw %dx, %dx /* position cursor to home */ - movb $0x13, %ah - int $0x18 - - movb $0x11, %ah /* turn cursor displaying on */ - int $0x18 - - /* move 1 kilobytes from [BOOTSEG:0000h] to [INITSEG:0000h] */ - cld - xorw %si, %si - pushw $INITSEG - popw %es - movw $512, %cx /* %di == 0 from entry */ - rep - cs - movsw - - ljmp $INITSEG, $go - -go: - pushw %cs - popw %ds /* %ds = %cs */ - - popw %dx /* %dh = saved %ch passed from BIOS */ - movb %ss:DISK_BOOT, %al - andb $0xf0, %al /* %al = Device Address */ - movb $18, %ch /* 18 secs/track, 512 b/sec (1440 KB) */ - cmpb $0x30, %al - je try512 - cmpb $0x90, %al /* 1 MB I/F, 1 MB floppy */ - je try1.2M - cmpb $0xf0, %al /* 640 KB I/F, 1 MB floppy */ - je try1.2M - movb $9, %ch /* 9 secs/track, 512 b/sec ( 720 KB) */ - cmpb $0x10, %al /* 1 MB I/F, 640 KB floppy */ - je try512 - cmpb $0x70, %al /* 640 KB I/F, 640 KB floppy */ - jne error /* unknown device? */ - - /* XXX: Does it make sense to support 8 secs/track, 512 b/sec - (640 KB) floppy? */ - -try512: movb $2, %cl /* 512 b/sec */ -lasttry:call tryload -/* - * Display error message and halt - */ -error: movw $error_msg, %si - call print -wait_reboot: - movb $0x0, %ah - int $0x18 /* wait keyboard input */ -1: movb $0, %al - outb %al, $0xF0 /* reset CPU */ - jmp 1b /* just in case... */ - -try1.2M:cmpb $2, %dh - je try2HC - movw $0x0803, %cx /* 8 secs/track, 1024 b/sec (1232 KB) */ - call tryload - movb $15, %ch /* 15 secs/track, 512 b/sec (1200 KB) */ - jmp try512 -try2HC: movw $0x0F02, %cx /* 15 secs/track, 512 b/sec (1200 KB) */ - call tryload - movw $0x0803, %cx /* 8 secs/track, 1024 b/sec (1232 KB) */ - jmp lasttry - -/* - * Try to load SETUP and SYSTEM provided geometry information in %cx. - * This routine *will not* return on successful load... - */ -tryload: - movw %cx, sectlen - movb %ss:DISK_BOOT, %al - movb $0x7, %ah /* recalibrate the drive */ - int $0x1b - jc error /* recalibration should succeed */ - - /* - * Load SETUP into memory. It is assumed that SETUP fits into - * first cylinder (2 tracks, 9KB on 2DD, 15-18KB on 2HD). - */ - movb $0, %bl - movb setup_sects, %bh - incb %bh - shlw %bx /* %bx = (setup_sects + 1) * 512 */ - movw $128, %bp - shlw %cl, %bp /* %bp = */ - subw %bp, %bx /* length to load */ - movw $0x0002, %dx /* head 0, sector 2 */ - movb %cl, %ch /* `N' for sector address */ - movb $0, %cl /* cylinder 0 */ - pushw %cs - popw %es /* %es = %cs (= INITSEG) */ - movb $0xd6, %ah /* read, multi-track, MFM */ - int $0x1b /* load it! */ - jc read_error - - movw $loading_msg, %si - call print - - movw $SYSSEG, %ax - movw %ax, %es /* %es = SYSSEG */ - -/* - * This routine loads the system at address 0x10000, making sure - * no 64kB boundaries are crossed. We try to load it as fast as - * possible, loading whole tracks whenever we can. - * - * in: es - starting address segment (normally 0x1000) - */ - movb %ch, %cl - addb $7, %cl /* %cl = log2 */ - shrw %cl, %bx /* %bx = # of phys. sectors in SETUP */ - addb %bl, %dl /* %dl = start sector # of SYSTEM */ - decb %dl /* %dl is 0-based in below loop */ - -rp_read_newseg: - xorw %bp, %bp /* = starting address within segment */ -#ifdef __BIG_KERNEL__ - bootsect_kludge = 0x220 /* 0x200 (size of bootsector) + 0x20 (offset */ - lcall *bootsect_kludge /* of bootsect_kludge in setup.S */ -#else - movw %es, %ax - subw $SYSSEG, %ax -#endif - cmpw syssize, %ax - ja boot /* done! */ - -rp_read: - movb sectors, %al - addb %al, %al - movb %al, %ch /* # of sectors on both surface */ - subb %dl, %al /* # of sectors left on this track */ - movb $0, %ah - shlw %cl, %ax /* # of bytes left on this track */ - movw %ax, %bx /* transfer length */ - addw %bp, %ax /* cross 64K boundary? */ - jnc 1f /* ok. */ - jz 1f /* also ok. */ - /* - * Oops, we are crossing 64K boundary... - * Adjust transfer length to make transfer fit in the boundary. - * - * Note: sector size is assumed to be a measure of 65536. - */ - xorw %bx, %bx - subw %bp, %bx -1: pushw %dx - movw $dot_msg, %si /* give progress message */ - call print - xchgw %ax, %dx - movb $0, %ah - divb sectors - xchgb %al, %ah - xchgw %ax, %dx /* %dh = head # / %dl = sector # */ - incb %dl /* fix %dl to 1-based */ - pushw %cx - movw cylinder, %cx - movb $0xd6, %ah /* read, multi-track, seek, MFM */ - movb %ss:DISK_BOOT, %al - int $0x1b - popw %cx - popw %dx - jc read_error - movw %bx, %ax /* # of bytes just read */ - shrw %cl, %ax /* %ax = # of sectors just read */ - addb %al, %dl /* advance sector # */ - cmpb %ch, %dl /* %ch = # of sectors/cylinder */ - jb 2f - incb cylinder /* next cylinder */ - xorb %dl, %dl /* sector 0 */ -2: addw %bx, %bp /* advance offset pointer */ - jnc rp_read - /* offset pointer wrapped; advance segment pointer. */ - movw %es, %ax - addw $0x1000, %ax - movw %ax, %es - jmp rp_read_newseg - -read_error: - ret - -boot: movw %cs, %ax /* = INITSEG */ - /* movw %ax, %ds */ - movw %ax, %ss - movw $0x4000, %sp /* 0x4000 is arbitrary value >= - * length of bootsect + length of - * setup + room for stack; - * PC-9800 never have BIOS workareas - * on high memory. - */ -/* - * After that we check which root-device to use. If the device is - * not defined, /dev/fd0 (2, 0) will be used. - */ - cmpw $0, root_dev - jne 3f - movb $2, root_dev+1 -3: - -/* - * After that (everything loaded), we jump to the setup-routine - * loaded directly after the bootblock: - */ - ljmp $SETUPSEG, $0 - -/* - * Subroutine for print string on console. - * %cs:%si - pointer to message - */ -print: - pushaw - pushw %ds - pushw %es - pushw %cs - popw %ds - lesw curpos, %di /* %es:%di = current text VRAM addr. */ -1: xorw %ax, %ax - lodsb - testb %al, %al - jz 2f /* end of string */ - stosw /* character code */ - movb $0xE1, %es:0x2000-2(%di) /* character attribute */ - jmp 1b -2: movw %di, %dx - movb $0x13, %ah - int $0x18 /* move cursor to current point */ - popw %es - popw %ds - popaw - ret - -loading_msg: - .string "Loading" -dot_msg: - .string "." -error_msg: - .string "Read Error!" - - .org 490 - -curpos: .word 160 /* current cursor position */ -vram: .word NORMAL_TEXT /* text VRAM segment */ - -cylinder: .byte 0 /* current cylinder (lower byte) */ -sectlen: .byte 0 /* (log2 of ) - 7 */ -sectors: .byte 0x0F /* default is 2HD (15 sector/track) */ - -# XXX: This is a fairly snug fit. - -.org 497 -setup_sects: .byte SETUPSECTS -root_flags: .word ROOT_RDONLY -syssize: .word SYSSIZE -swap_dev: .word SWAP_DEV -ram_size: .word RAMDISK -vid_mode: .word SVGA_MODE -root_dev: .word ROOT_DEV -boot_flag: .word 0xAA55 diff -Nru a/arch/i386/boot98/install.sh b/arch/i386/boot98/install.sh --- a/arch/i386/boot98/install.sh 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,40 +0,0 @@ -#!/bin/sh -# -# arch/i386/boot/install.sh -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 1995 by Linus Torvalds -# -# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin -# -# "make install" script for i386 architecture -# -# Arguments: -# $1 - kernel version -# $2 - kernel image file -# $3 - kernel map file -# $4 - default install path (blank if root directory) -# - -# User may have a custom install script - -if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi -if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi - -# Default install - same as make zlilo - -if [ -f $4/vmlinuz ]; then - mv $4/vmlinuz $4/vmlinuz.old -fi - -if [ -f $4/System.map ]; then - mv $4/System.map $4/System.old -fi - -cat $2 > $4/vmlinuz -cp $3 $4/System.map - -if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi diff -Nru a/arch/i386/boot98/mtools.conf.in b/arch/i386/boot98/mtools.conf.in --- a/arch/i386/boot98/mtools.conf.in 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,17 +0,0 @@ -# -# mtools configuration file for "make (b)zdisk" -# - -# Actual floppy drive -drive a: - file="/dev/fd0" - -# 1.44 MB floppy disk image -drive v: - file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter - -# 2.88 MB floppy disk image (mostly for virtual uses) -drive w: - file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter - - diff -Nru a/arch/i386/boot98/setup.S b/arch/i386/boot98/setup.S --- a/arch/i386/boot98/setup.S 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,876 +0,0 @@ -/* - * setup.S Copyright (C) 1991, 1992 Linus Torvalds - * - * setup.s is responsible for getting the system data from the BIOS, - * and putting them into the appropriate places in system memory. - * both setup.s and system has been loaded by the bootblock. - * - * This code asks the bios for memory/disk/other parameters, and - * puts them in a "safe" place: 0x90000-0x901FF, ie where the - * boot-block used to be. It is then up to the protected mode - * system to read them from there before the area is overwritten - * for buffer-blocks. - * - * Move PS/2 aux init code to psaux.c - * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 - * - * some changes and additional features by Christoph Niemann, - * March 1993/June 1994 (Christoph.Niemann@linux.org) - * - * add APM BIOS checking by Stephen Rothwell, May 1994 - * (sfr@canb.auug.org.au) - * - * High load stuff, initrd support and position independency - * by Hans Lermen & Werner Almesberger, February 1996 - * , - * - * Video handling moved to video.S by Martin Mares, March 1996 - * - * - * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david - * parsons) to avoid loadlin confusion, July 1997 - * - * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. - * - * - * Fix to work around buggy BIOSes which dont use carry bit correctly - * and/or report extended memory in CX/DX for e801h memory size detection - * call. As a result the kernel got wrong figures. The int15/e801h docs - * from Ralf Brown interrupt list seem to indicate AX/BX should be used - * anyway. So to avoid breaking many machines (presumably there was a reason - * to orginally use CX/DX instead of AX/BX), we do a kludge to see - * if CX/DX have been changed in the e801 call and if so use AX/BX . - * Michael Miller, April 2001 - * - * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes - * by Robert Schwebel, December 2001 - * - * Heavily modified for NEC PC-9800 series by Kyoto University Microcomputer - * Club (KMC) Linux/98 project , 1997-1999 - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Signature words to ensure LILO loaded us right */ -#define SIG1 0xAA55 -#define SIG2 0x5A5A - -#define HIRESO_TEXT 0xe000 -#define NORMAL_TEXT 0xa000 - -#define BIOS_FLAG2 0x0400 -#define BIOS_FLAG5 0x0458 -#define RDISK_EQUIP 0x0488 -#define BIOS_FLAG 0x0501 -#define KB_SHFT_STS 0x053a -#define DISK_EQUIP 0x055c - -INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way -SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). -SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment - # ... and the former contents of CS - -DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 - -.code16 -.globl begtext, begdata, begbss, endtext, enddata, endbss - -.text -begtext: -.data -begdata: -.bss -begbss: -.text - -start: - jmp trampoline - -# This is the setup header, and it must start at %cs:2 (old 0x9020:2) - - .ascii "HdrS" # header signature - .word 0x0203 # header version number (>= 0x0105) - # or else old loadlin-1.5 will fail) -realmode_swtch: .word 0, 0 # default_switch, SETUPSEG -start_sys_seg: .word SYSSEG - .word kernel_version # pointing to kernel version string - # above section of header is compatible - # with loadlin-1.5 (header v1.5). Don't - # change it. - -type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, - # Bootlin, SYSLX, bootsect...) - # See Documentation/i386/boot.txt for - # assigned ids - -# flags, unused bits must be zero (RFU) bit within loadflags -loadflags: -LOADED_HIGH = 1 # If set, the kernel is loaded high -CAN_USE_HEAP = 0x80 # If set, the loader also has set - # heap_end_ptr to tell how much - # space behind setup.S can be used for - # heap purposes. - # Only the loader knows what is free -#ifndef __BIG_KERNEL__ - .byte 0 -#else - .byte LOADED_HIGH -#endif - -setup_move_size: .word 0x8000 # size to move, when setup is not - # loaded at 0x90000. We will move setup - # to 0x90000 then just before jumping - # into the kernel. However, only the - # loader knows how much data behind - # us also needs to be loaded. - -code32_start: # here loaders can put a different - # start address for 32-bit code. -#ifndef __BIG_KERNEL__ - .long 0x1000 # 0x1000 = default for zImage -#else - .long 0x100000 # 0x100000 = default for big kernel -#endif - -ramdisk_image: .long 0 # address of loaded ramdisk image - # Here the loader puts the 32-bit - # address where it loaded the image. - # This only will be read by the kernel. - -ramdisk_size: .long 0 # its size in bytes - -bootsect_kludge: - .long 0 # obsolete - -heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) - # space from here (exclusive) down to - # end of setup code can be used by setup - # for local heap purposes. - -pad1: .word 0 -cmd_line_ptr: .long 0 # (Header version 0x0202 or later) - # If nonzero, a 32-bit pointer - # to the kernel command line. - # The command line should be - # located between the start of - # setup and the end of low - # memory (0xa0000), or it may - # get overwritten before it - # gets read. If this field is - # used, there is no longer - # anything magical about the - # 0x90000 segment; the setup - # can be located anywhere in - # low memory 0x10000 or higher. - -ramdisk_max: .long MAXMEM-1 # (Header version 0x0203 or later) - # The highest safe address for - # the contents of an initrd - -trampoline: call start_of_setup - .space 1024 -# End of setup header ##################################################### - -start_of_setup: -# Set %ds = %cs, we know that SETUPSEG = %cs at this point - movw %cs, %ax # aka SETUPSEG - movw %ax, %ds -# Check signature at end of setup - cmpw $SIG1, setup_sig1 - jne bad_sig - - cmpw $SIG2, setup_sig2 - jne bad_sig - - jmp good_sig1 - -# Routine to print asciiz string at ds:si -prtstr: - lodsb - andb %al, %al - jz fin - - call prtchr - jmp prtstr - -fin: ret - -no_sig_mess: .string "No setup signature found ..." - -good_sig1: - jmp good_sig - -# We now have to find the rest of the setup code/data -bad_sig: - movw %cs, %ax # SETUPSEG - subw $DELTA_INITSEG, %ax # INITSEG - movw %ax, %ds - xorb %bh, %bh - movb (497), %bl # get setup sect from bootsect - subw $4, %bx # LILO loads 4 sectors of setup - shlw $8, %bx # convert to words (1sect=2^8 words) - movw %bx, %cx - shrw $3, %bx # convert to segment - addw $SYSSEG, %bx - movw %bx, %cs:start_sys_seg -# Move rest of setup code/data to here - movw $2048, %di # four sectors loaded by LILO - subw %si, %si - pushw %cs - popw %es - movw $SYSSEG, %ax - movw %ax, %ds - rep - movsw - movw %cs, %ax # aka SETUPSEG - movw %ax, %ds - cmpw $SIG1, setup_sig1 - jne no_sig - - cmpw $SIG2, setup_sig2 - jne no_sig - - jmp good_sig - -no_sig: - lea no_sig_mess, %si - call prtstr - -no_sig_loop: - hlt - jmp no_sig_loop - -good_sig: - movw %cs, %ax # aka SETUPSEG - subw $DELTA_INITSEG, %ax # aka INITSEG - movw %ax, %ds -# Check if an old loader tries to load a big-kernel - testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? - jz loader_ok # No, no danger for old loaders. - - cmpb $0, %cs:type_of_loader # Do we have a loader that - # can deal with us? - jnz loader_ok # Yes, continue. - - pushw %cs # No, we have an old loader, - popw %ds # die. - lea loader_panic_mess, %si - call prtstr - - jmp no_sig_loop - -loader_panic_mess: .string "Wrong loader, giving up..." - -loader_ok: -# Get memory size (extended mem, kB) - -# On PC-9800, memory size detection is done completely in 32-bit -# kernel initialize code (kernel/setup.c). - pushw %es - xorl %eax, %eax - movw %ax, %es - movb %al, (E820NR) # PC-9800 has no E820 - movb %es:(0x401), %al - shll $7, %eax - addw $1024, %ax - movw %ax, (2) - movl %eax, (0x1e0) - movw %es:(0x594), %ax - shll $10, %eax - addl %eax, (0x1e0) - popw %es - -# Check for video adapter and its parameters and allow the -# user to browse video modes. - call video # NOTE: we need %ds pointing - # to bootsector - -# Get text video mode - movb $0x0B, %ah - int $0x18 # CRT mode sense - movw $(20 << 8) + 40, %cx - testb $0x10, %al - jnz 3f - movb $20, %ch - testb $0x01, %al - jnz 1f - movb $25, %ch - jmp 1f -3: # If bit 4 was 1, it means either 1) 31 lines for hi-reso mode, - # or 2) 30 lines for PC-9821. - movb $31, %ch # hireso mode value - pushw $0 - popw %es - testb $0x08, %es:BIOS_FLAG - jnz 1f - movb $30, %ch -1: # Now we got # of rows in %ch - movb %ch, (14) - - testb $0x02, %al - jnz 2f - movb $80, %cl -2: # Now we got # of columns in %cl - movb %cl, (7) - - # Next, get horizontal frequency if supported - movw $0x3100, %ax - int $0x18 # Call CRT bios - movb %al, (6) # If 31h is unsupported, %al remains 0 - -# Get hd0-3 data... - pushw %ds # aka INITSEG - popw %es - xorw %ax, %ax - movw %ax, %ds - cld - movw $0x0080, %di - movb DISK_EQUIP+1, %ah - movb $0x80, %al - -get_hd_info: - shrb %ah - pushw %ax - jnc 1f - movb $0x84, %ah - int $0x1b - jnc 2f # Success -1: xorw %cx, %cx # `0 cylinders' means no drive -2: # Attention! Work area (drive_info) is arranged for PC-9800. - movw %cx, %ax # # of cylinders - stosw - movw %dx, %ax # # of sectors / # of heads - stosw - movw %bx, %ax # sector size in bytes - stosw - popw %ax - incb %al - cmpb $0x84, %al - jb get_hd_info - -# Get fd data... - movw DISK_EQUIP, %ax - andw $0xf00f, %ax - orb %al, %ah - movb RDISK_EQUIP, %al - notb %al - andb %al, %ah # ignore all `RAM drive' - - movb $0x30, %al - -get_fd_info: - shrb %ah - pushw %ax - jnc 1f - movb $0xc4, %ah - int $0x1b - movb %ah, %al - andb $4, %al # 1.44MB support flag - shrb %al - addb $2, %al # %al = 2 (1.2MB) or 4 (1.44MB) - jmp 2f -1: movb $0, %al # no drive -2: stosb - popw %ax - incb %al - testb $0x04, %al - jz get_fd_info - - addb $(0xb0 - 0x34), %al - jnc get_fd_info # check FDs on 640KB I/F - - pushw %es - popw %ds # %ds got bootsector again -#if 0 - mov $0, (0x1ff) # default is no pointing device -#endif - -#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) -# Then check for an APM BIOS... - # %ds points to the bootsector - movw $0, 0x40 # version = 0 means no APM BIOS - movw $0x09a00, %ax # APM BIOS installation check - xorw %bx, %bx - int $0x1f - jc done_apm_bios # Nope, no APM BIOS - - cmpw $0x0504d, %bx # Check for "PM" signature - jne done_apm_bios # No signature, no APM BIOS - - testb $0x02, %cl # Is 32 bit supported? - je done_apm_bios # No 32-bit, no (good) APM BIOS - - movw $0x09a04, %ax # Disconnect first just in case - xorw %bx, %bx - int $0x1f # ignore return code - movw $0x09a03, %ax # 32 bit connect - xorl %ebx, %ebx - int $0x1f - jc no_32_apm_bios # Ack, error. - - movw %ax, (66) # BIOS code segment - movl %ebx, (68) # BIOS entry point offset - movw %cx, (72) # BIOS 16 bit code segment - movw %dx, (74) # BIOS data segment - movl %esi, (78) # BIOS code segment length - movw %di, (82) # BIOS data segment length -# Redo the installation check as the 32 bit connect -# modifies the flags returned on some BIOSs - movw $0x09a00, %ax # APM BIOS installation check - xorw %bx, %bx - int $0x1f - jc apm_disconnect # error -> shouldn't happen - - cmpw $0x0504d, %bx # check for "PM" signature - jne apm_disconnect # no sig -> shouldn't happen - - movw %ax, (64) # record the APM BIOS version - movw %cx, (76) # and flags - jmp done_apm_bios - -apm_disconnect: # Tidy up - movw $0x09a04, %ax # Disconnect - xorw %bx, %bx - int $0x1f # ignore return code - - jmp done_apm_bios - -no_32_apm_bios: - andw $0xfffd, (76) # remove 32 bit support bit -done_apm_bios: -#endif - -# Pass cursor position to kernel... - movw %cs:cursor_address, %ax - shrw %ax # cursor_address is 2 bytes unit - movb $80, %cl - divb %cl - xchgb %al, %ah # (0) = %al = X, (1) = %ah = Y - movw %ax, (0) - -#if 0 - movw $msg_cpos, %si - call prtstr_cs - call prthex - call prtstr_cs - movw %ds, %ax - call prthex - call prtstr_cs - movb $0x11, %ah - int $0x18 - movb $0, %ah - int $0x18 - .section .rodata, "a" -msg_cpos: .string "Cursor position: 0x" - .string ", %ds:0x" - .string "\r\n" - .previous -#endif - -# Now we want to move to protected mode ... - cmpw $0, %cs:realmode_swtch - jz rmodeswtch_normal - - lcall *%cs:realmode_swtch - - jmp rmodeswtch_end - -rmodeswtch_normal: - pushw %cs - call default_switch - -rmodeswtch_end: -# we get the code32 start address and modify the below 'jmpi' -# (loader may have changed it) - movl %cs:code32_start, %eax - movl %eax, %cs:code32 - -# Now we move the system to its rightful place ... but we check if we have a -# big-kernel. In that case we *must* not move it ... - testb $LOADED_HIGH, %cs:loadflags - jz do_move0 # .. then we have a normal low - # loaded zImage - # .. or else we have a high - # loaded bzImage - jmp end_move # ... and we skip moving - -do_move0: - movw $0x100, %ax # start of destination segment - movw %cs, %bp # aka SETUPSEG - subw $DELTA_INITSEG, %bp # aka INITSEG - movw %cs:start_sys_seg, %bx # start of source segment - cld -do_move: - movw %ax, %es # destination segment - incb %ah # instead of add ax,#0x100 - movw %bx, %ds # source segment - addw $0x100, %bx - subw %di, %di - subw %si, %si - movw $0x800, %cx - rep - movsw - cmpw %bp, %bx # assume start_sys_seg > 0x200, - # so we will perhaps read one - # page more than needed, but - # never overwrite INITSEG - # because destination is a - # minimum one page below source - jb do_move - -end_move: -# then we load the segment descriptors - movw %cs, %ax # aka SETUPSEG - movw %ax, %ds - -# Check whether we need to be downward compatible with version <=201 - cmpl $0, cmd_line_ptr - jne end_move_self # loader uses version >=202 features - cmpb $0x20, type_of_loader - je end_move_self # bootsect loader, we know of it - -# Boot loader does not support boot protocol version 2.02. -# If we have our code not at 0x90000, we need to move it there now. -# We also then need to move the params behind it (commandline) -# Because we would overwrite the code on the current IP, we move -# it in two steps, jumping high after the first one. - movw %cs, %ax - cmpw $SETUPSEG, %ax - je end_move_self - - cli # make sure we really have - # interrupts disabled ! - # because after this the stack - # should not be used - subw $DELTA_INITSEG, %ax # aka INITSEG - movw %ss, %dx - cmpw %ax, %dx - jb move_self_1 - - addw $INITSEG, %dx - subw %ax, %dx # this will go into %ss after - # the move -move_self_1: - movw %ax, %ds - movw $INITSEG, %ax # real INITSEG - movw %ax, %es - movw %cs:setup_move_size, %cx - std # we have to move up, so we use - # direction down because the - # areas may overlap - movw %cx, %di - decw %di - movw %di, %si - subw $move_self_here+0x200, %cx - rep - movsb - ljmp $SETUPSEG, $move_self_here - -move_self_here: - movw $move_self_here+0x200, %cx - rep - movsb - movw $SETUPSEG, %ax - movw %ax, %ds - movw %dx, %ss - -end_move_self: # now we are at the right place - lidt idt_48 # load idt with 0,0 - xorl %eax, %eax # Compute gdt_base - movw %ds, %ax # (Convert %ds:gdt to a linear ptr) - shll $4, %eax - addl $gdt, %eax - movl %eax, (gdt_48+2) - lgdt gdt_48 # load gdt with whatever is - # appropriate - -# that was painless, now we enable A20 - - outb %al, $0xf2 # A20 on - movb $0x02, %al - outb %al, $0xf6 # also A20 on; making ITF's - # way our model - - # PC-9800 seems to enable A20 at the moment of `outb'; - # so we don't wait unlike IBM PCs (see ../setup.S). - -# enable DMA to access memory over 0x100000 (1MB). - - movw $0x439, %dx - inb %dx, %al - andb $(~4), %al - outb %al, %dx - -# Set DMA to increment its bank address automatically at 16MB boundary. -# Initial setting is 64KB boundary mode so that we can't run DMA crossing -# physical address 0xXXXXFFFF. - - movb $0x0c, %al - outb %al, $0x29 # ch. 0 - movb $0x0d, %al - outb %al, $0x29 # ch. 1 - movb $0x0e, %al - outb %al, $0x29 # ch. 2 - movb $0x0f, %al - outb %al, $0x29 # ch. 3 - movb $0x50, %al - outb %al, $0x11 # reinitialize DMAC - -# make sure any possible coprocessor is properly reset.. - movb $0, %al - outb %al, $0xf8 - outb %al, $0x5f # delay - -# well, that went ok, I hope. Now we mask all interrupts - the rest -# is done in init_IRQ(). - movb $0xFF, %al # mask all interrupts for now - outb %al, $0x0A - outb %al, $0x5f # delay - - movb $0x7F, %al # mask all irq's but irq7 which - outb %al, $0x02 # is cascaded - -# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't -# need no steenking BIOS anyway (except for the initial loading :-). -# The BIOS-routine wants lots of unnecessary data, and it's less -# "interesting" anyway. This is how REAL programmers do it. -# -# Well, now's the time to actually move into protected mode. To make -# things as simple as possible, we do no register set-up or anything, -# we let the gnu-compiled 32-bit programs do that. We just jump to -# absolute address 0x1000 (or the loader supplied one), -# in 32-bit protected mode. -# -# Note that the short jump isn't strictly needed, although there are -# reasons why it might be a good idea. It won't hurt in any case. - movw $1, %ax # protected mode (PE) bit - lmsw %ax # This is it! - jmp flush_instr - -flush_instr: - xorw %bx, %bx # Flag to indicate a boot - xorl %esi, %esi # Pointer to real-mode code - movw %cs, %si - subw $DELTA_INITSEG, %si - shll $4, %esi # Convert to 32-bit pointer -# NOTE: For high loaded big kernels we need a -# jmpi 0x100000,__BOOT_CS -# -# but we yet haven't reloaded the CS register, so the default size -# of the target offset still is 16 bit. -# However, using an operand prefix (0x66), the CPU will properly -# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference -# Manual, Mixing 16-bit and 32-bit code, page 16-6) - - .byte 0x66, 0xea # prefix + jmpi-opcode -code32: .long 0x1000 # will be set to 0x100000 - # for big kernels - .word __BOOT_CS - -# Here's a bunch of information about your current kernel.. -kernel_version: .ascii UTS_RELEASE - .ascii " (" - .ascii LINUX_COMPILE_BY - .ascii "@" - .ascii LINUX_COMPILE_HOST - .ascii ") " - .ascii UTS_VERSION - .byte 0 - -# This is the default real mode switch routine. -# to be called just before protected mode transition -default_switch: - cli # no interrupts allowed ! - outb %al, $0x50 # disable NMI for bootup - # sequence - lret - - -# This routine prints one character (in %al) on console. -# PC-9800 doesn't have BIOS-function to do it like IBM PC's INT 10h - 0Eh, -# so we hardcode `prtchr' subroutine here. -prtchr: - pushaw - pushw %es - cmpb $0, %cs:prtchr_initialized - jnz prtchr_ok - xorw %cx, %cx - movw %cx, %es - testb $0x8, %es:BIOS_FLAG - jz 1f - movb $(HIRESO_TEXT >> 8), %cs:cursor_address+3 - movw $(80 * 31 * 2), %cs:max_cursor_offset -1: pushw %ax - call get_cursor_position - movw %ax, %cs:cursor_address - popw %ax - movb $1, %cs:prtchr_initialized -prtchr_ok: - lesw %cs:cursor_address, %di - movw $160, %bx - movb $0, %ah - cmpb $13, %al - je do_cr - cmpb $10, %al - je do_lf - - # normal (printable) character - stosw - movb $0xe1, %es:0x2000-2(%di) - jmp 1f - -do_cr: movw %di, %ax - divb %bl # %al = Y, %ah = X * 2 - mulb %bl - movw %ax, %dx - jmp 2f - -do_lf: addw %bx, %di -1: movw %cs:max_cursor_offset, %cx - cmpw %cx, %di - movw %di, %dx - jb 2f - # cursor reaches bottom of screen; scroll it - subw %bx, %dx - xorw %di, %di - movw %bx, %si - cld - subw %bx, %cx - shrw %cx - pushw %cx - rep; es; movsw - movb $32, %al # clear bottom line characters - movb $80, %cl - rep; stosw - movw $0x2000, %di - popw %cx - leaw (%bx,%di), %si - rep; es; movsw - movb $0xe1, %al # clear bottom line attributes - movb $80, %cl - rep; stosw -2: movw %dx, %cs:cursor_address - movb $0x13, %ah # move cursor to right position - int $0x18 - popw %es - popaw - ret - -cursor_address: - .word 0 - .word NORMAL_TEXT -max_cursor_offset: - .word 80 * 25 * 2 # for normal 80x25 mode - -# putstr may called without running through start_of_setup (via bootsect_panic) -# so we should initialize ourselves on demand. -prtchr_initialized: - .byte 0 - -# This routine queries GDC (graphic display controller) for current cursor -# position. Cursor position is returned in %ax (CPU offset address). -get_cursor_position: -1: inb $0x60, %al - outb %al, $0x5f # delay - outb %al, $0x5f # delay - testb $0x04, %al # Is FIFO empty? - jz 1b # no -> wait until empty - - movb $0xe0, %al # CSRR command - outb %al, $0x62 # command write - outb %al, $0x5f # delay - outb %al, $0x5f # delay - -2: inb $0x60, %al - outb %al, $0x5f # delay - outb %al, $0x5f # delay - testb $0x01, %al # Is DATA READY? - jz 2b # no -> wait until ready - - inb $0x62, %al # read xAD (L) - outb %al, $0x5f # delay - outb %al, $0x5f # delay - movb %al, %ah - inb $0x62, %al # read xAD (H) - outb %al, $0x5f # delay - outb %al, $0x5f # delay - xchgb %al, %ah # correct byte order - pushw %ax - inb $0x62, %al # read yAD (L) - outb %al, $0x5f # delay - outb %al, $0x5f # delay - inb $0x62, %al # read yAD (M) - outb %al, $0x5f # delay - outb %al, $0x5f # delay - inb $0x62, %al # read yAD (H) - # yAD is not our interest, - # so discard it. - popw %ax - addw %ax, %ax # convert to CPU address - ret - -# Descriptor tables -# -# NOTE: The intel manual says gdt should be sixteen bytes aligned for -# efficiency reasons. However, there are machines which are known not -# to boot with misaligned GDTs, so alter this at your peril! If you alter -# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two -# empty GDT entries (one for NULL and one reserved). -# -# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is -# true for the Voyager Quad CPU card which will not boot without -# This directive. 16 byte aligment is recommended by intel. -# - .align 16 -gdt: - .fill GDT_ENTRY_BOOT_CS,8,0 - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9A00 # code read/exec - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) - - .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) - .word 0 # base address = 0 - .word 0x9200 # data read/write - .word 0x00CF # granularity = 4096, 386 - # (+5th nibble of limit) -gdt_end: - .align 4 - - .word 0 # alignment byte -idt_48: - .word 0 # idt limit = 0 - .word 0, 0 # idt base = 0L - - .word 0 # alignment byte -gdt_48: - .word gdt_end - gdt - 1 # gdt limit - .word 0, 0 # gdt base (filled in later) - -# Include video setup & detection code - -#include "video.S" - -# Setup signature -- must be last -setup_sig1: .word SIG1 -setup_sig2: .word SIG2 - -# After this point, there is some free space which is used by the video mode -# handling code to store the temporary mode table (not used by the kernel). - -modelist: - -.text -endtext: -.data -enddata: -.bss -endbss: diff -Nru a/arch/i386/boot98/video.S b/arch/i386/boot98/video.S --- a/arch/i386/boot98/video.S 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,262 +0,0 @@ -/* video.S - * - * Video mode setup, etc. for NEC PC-9800 series. - * - * Copyright (C) 1997,98,99 Linux/98 project - * - * Based on the video.S for IBM PC: - * copyright (C) Martin Mares - */ - -/* Positions of various video parameters passed to the kernel */ -/* (see also include/linux/tty.h) */ -#define PARAM_CURSOR_POS 0x00 -#define PARAM_VIDEO_PAGE 0x04 -#define PARAM_VIDEO_MODE 0x06 -#define PARAM_VIDEO_COLS 0x07 -#define PARAM_VIDEO_EGA_BX 0x0a -#define PARAM_VIDEO_LINES 0x0e -#define PARAM_HAVE_VGA 0x0f -#define PARAM_FONT_POINTS 0x10 - -#define PARAM_VIDEO98_COMPAT 0x0a -#define PARAM_VIDEO98_HIRESO 0x0b -#define PARAM_VIDEO98_MACHTYPE 0x0c -#define PARAM_VIDEO98_LINES 0x0e -#define PARAM_VIDEO98_COLS 0x0f - -# PARAM_LFB_* and PARAM_VESAPM_* are unused on PC-9800. - -# This is the main entry point called by setup.S -# %ds *must* be pointing to the bootsector -video: xorw %ax, %ax - movw %ax, %es # %es = 0 - - movb %es:BIOS_FLAG, %al - movb %al, PARAM_VIDEO_MODE - - movb $0, PARAM_VIDEO98_HIRESO # 0 = normal - movw $NORMAL_TEXT, PARAM_VIDEO_PAGE - testb $0x8, %al - movw $(80 * 256 + 25), %ax - jz 1f - # hireso machine. - movb $1, PARAM_VIDEO98_HIRESO # !0 = hi-reso - movb $(HIRESO_TEXT >> 8), PARAM_VIDEO_PAGE + 1 - movw $(80 * 256 + 31), %ax -1: movw %ax, PARAM_VIDEO98_LINES # also sets VIDEO98_COLS - - movb $0xc0, %ch # 400-line graphic mode - movb $0x42, %ah - int $0x18 - - movw $80, PARAM_VIDEO_COLS - - movw $msg_probing, %si - call prtstr_cs - -# Check vendor from font pattern of `A'... - -1: inb $0x60, %al # wait V-sync - testb $0x20, %al - jnz 1b -2: inb $0x60, %al - testb $0x20, %al - jz 2b - - movb $0x00, %al # select font of `A' - outb %al, $0xa1 - movb $0x41, %al - outb %al, $0xa3 - - movw $8, %cx - movw PARAM_VIDEO_PAGE, %ax - cmpw $NORMAL_TEXT, %ax - je 3f - movb $24, %cl # for hi-reso machine -3: addw $0x400, %ax # %ax = CG window segment - pushw %ds - movw %ax, %ds - xorw %dx, %dx # get sum of `A' pattern... - xorw %si, %si -4: lodsw - addw %ax, %dx - loop 4b - popw %ds - - movw %dx, %ax - movw $msg_nec, %si - xorw %bx, %bx # vendor info will go into %bx - testb $8, %es:BIOS_FLAG - jnz check_hireso_vendor - cmpw $0xc7f8, %ax - je 5f - jmp 6f -check_hireso_vendor: - cmpw $0x9639, %ax # XXX: NOT VERIFIED!!! - je 5f -6: incw %bx # compatible machine - movw $msg_compat, %si -5: movb %bl, PARAM_VIDEO98_COMPAT - call prtstr_cs - - movw $msg_fontdata, %si - call prtstr_cs # " (CG sum of A = 0x" - movw %dx, %ax - call prthex - call prtstr_cs # ") PC-98" - - movb $'0', %al - pushw %ds - pushw $0xf8e8 - popw %ds - cmpw $0x2198, (0) - popw %ds - jne 7f - movb $'2', %al -7: call prtchr - call prtstr_cs # "1 " - - movb $0, PARAM_VIDEO98_MACHTYPE -#if 0 /* XXX - This check is bogus? [0000:BIOS_FLAG2]-bit7 does NOT - indicate whether it is a note machine, but merely indicates - whether it has ``RAM drive''. */ -# check note machine - testb $0x80, %es:BIOS_FLAG2 - jnz is_note - pushw %ds - pushw $0xfd80 - popw %ds - movb (4), %al - popw %ds - cmpb $0x20, %al # EPSON note A - je epson_note - cmpb $0x22, %al # EPSON note W - je epson_note - cmpb $0x27, %al # EPSON note AE - je epson_note - cmpb $0x2a, %al # EPSON note WR - jne note_done -epson_note: - movb $1, PARAM_VIDEO98_MACHTYPE - movw $msg_note, %si - call prtstr_cs -note_done: -#endif - -# print h98 ? (only NEC) - cmpb $0, PARAM_VIDEO98_COMPAT - jnz 8f # not NEC -> not H98 - - testb $0x80, %es:BIOS_FLAG5 - jz 8f # have NESA bus -> H98 - movw $msg_h98, %si - call prtstr_cs - orb $2, PARAM_VIDEO98_MACHTYPE -8: testb $0x40, %es:BIOS_FLAG5 - jz 9f - movw $msg_gs, %si - call prtstr_cs # only prints it :-) -9: - movw $msg_normal, %si # "normal" - testb $0x8, %es:BIOS_FLAG - jz 1f - movw $msg_hireso, %si -1: call prtstr_cs - - movw $msg_sysclk, %si - call prtstr_cs - movb $'5', %al - testb $0x80, %es:BIOS_FLAG - jz 2f - movb $'8', %al -2: call prtchr - call prtstr_cs - -#if 0 - testb $0x40, %es:(0x45c) - jz no_30line # no 30-line support - - movb %es:KB_SHFT_STS, %al - testb $0x01, %al # is SHIFT key pressed? - jz no_30line - - testb $0x10, %al # is CTRL key pressed? - jnz line40 - - # switch to 30-line mode - movb $30, PARAM_VIDEO98_LINES - movw $msg_30line, %si - jmp 3f - -line40: - movb $37, PARAM_VIDEO98_LINES - movw $40, PARAM_VIDEO_LINES - movw $msg_40line, %si -3: call prtstr_cs - - movb $0x32, %bh - movw $0x300c, %ax - int $0x18 # switch video mode - movb $0x0c, %ah - int $0x18 # turn on text plane - movw %cs:cursor_address, %dx - movb $0x13, %ah - int $0x18 # move cursor to correct place - mov $0x11, %ah - int $0x18 # turn on text plane - - call prtstr_cs # "Ok.\r\n" -no_30line: -#endif - ret - -prtstr_cs: - pushw %ds - pushw %cs - popw %ds - call prtstr - popw %ds - ret - -# prthex is for debugging purposes, and prints %ax in hexadecimal. -prthex: pushw %cx - movw $4, %cx -1: rolw $4, %ax - pushw %ax - andb $0xf, %al - cmpb $10, %al - sbbb $0x69, %al - das - call prtchr - popw %ax - loop 1b - popw %cx - ret - -msg_probing: .string "Probing machine: " - -msg_nec: .string "NEC" -msg_compat: .string "compatible" - -msg_fontdata: .string " (CG sum of A = 0x" - .string ") PC-98" - .string "1 " - -msg_gs: .string "(GS) " -msg_h98: .string "(H98) " - -msg_normal: .string "normal" -msg_hireso: .string "Hi-reso" - -msg_sysclk: .string " mode, system clock " - .string "MHz\r\n" - -#if 0 -msg_40line: # cpp will concat following lines, so the assembler can deal. - .ascii "\ -Video mode will be adjusted to 37-line (so-called ``40-line'') mode later.\r\n\ -THIS MODE MAY DAMAGE YOUR MONITOR PHYSICALLY. USE AT YOUR OWN RISK.\r\n" -msg_30line: .string "Switching video mode to 30-line (640x480) mode... " - .string "Ok.\r\n" -#endif diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/Makefile 2004-06-20 13:00:23 -07:00 @@ -31,7 +31,6 @@ obj-$(CONFIG_HPET_TIMER) += time_hpet.o obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_X86_STD_RESOURCES) += std_resources.o EXTRA_AFLAGS := -traditional diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c --- a/arch/i386/kernel/acpi/boot.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/kernel/acpi/boot.c 2004-06-20 13:00:25 -07:00 @@ -28,7 +28,9 @@ #include #include #include -#include +#include + +#include #include #include #include @@ -436,6 +438,38 @@ *irq = gsi; return 0; } + +unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) +{ + unsigned int irq; + +#ifdef CONFIG_PCI + /* + * Make sure all (legacy) PCI IRQs are set as level-triggered. + */ + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { + static u16 irq_mask; + extern void eisa_set_level_irq(unsigned int irq); + + if (edge_level == ACPI_LEVEL_SENSITIVE) { + if ((gsi < 16) && !((1 << gsi) & irq_mask)) { + Dprintk(KERN_DEBUG PREFIX "Setting GSI %u as level-triggered\n", gsi); + irq_mask |= (1 << gsi); + eisa_set_level_irq(gsi); + } + } + } +#endif + +#ifdef CONFIG_X86_IO_APIC + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { + mp_register_gsi(gsi, edge_level, active_high_low); + } +#endif + acpi_gsi_to_irq(gsi, &irq); + return irq; +} +EXPORT_SYMBOL(acpi_register_gsi); static unsigned long __init acpi_scan_rsdp ( diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c 2004-06-20 13:00:26 -07:00 +++ b/arch/i386/kernel/apic.c 2004-06-20 13:00:26 -07:00 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -79,6 +78,17 @@ if (!APIC_INTEGRATED(ver)) /* 82489DX */ v |= APIC_LVT_LEVEL_TRIGGER; apic_write_around(APIC_LVT0, v); +} + +int get_physical_broadcast(void) +{ + unsigned int lvr, version; + lvr = apic_read(APIC_LVR); + version = GET_APIC_VERSION(lvr); + if (version >= 0x14) + return 0xff; + else + return 0xf; } int get_maxlvt(void) diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c --- a/arch/i386/kernel/dmi_scan.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/kernel/dmi_scan.c 2004-06-20 13:00:24 -07:00 @@ -546,15 +546,21 @@ #ifdef CONFIG_ACPI_PCI static __init int disable_acpi_irq(struct dmi_blacklist *d) -{ - printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", d->ident); - acpi_noirq_set(); +{ + if (!acpi_force) { + printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", + d->ident); + acpi_noirq_set(); + } return 0; } static __init int disable_acpi_pci(struct dmi_blacklist *d) -{ - printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident); - acpi_disable_pci(); +{ + if (!acpi_force) { + printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", + d->ident); + acpi_disable_pci(); + } return 0; } #endif diff -Nru a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c --- a/arch/i386/kernel/efi.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/kernel/efi.c 2004-06-20 13:00:25 -07:00 @@ -37,7 +37,6 @@ #include #include #include -#include #include #define EFI_DEBUG 0 diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c 2004-06-20 13:00:26 -07:00 +++ b/arch/i386/kernel/i386_ksyms.c 2004-06-20 13:00:26 -07:00 @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c --- a/arch/i386/kernel/i8259.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/kernel/i8259.c 2004-06-20 13:00:25 -07:00 @@ -317,16 +317,11 @@ * be shot. */ -/* - * =PC9800NOTE= In NEC PC-9800, we use irq8 instead of irq13! - */ static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) { extern void math_error(void *); -#ifndef CONFIG_X86_PC9800 outb(0,0xF0); -#endif if (ignore_fpu_irq || !boot_cpu_data.hard_math) return IRQ_NONE; math_error((void *)regs->eip); diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c --- a/arch/i386/kernel/init_task.c 2004-06-20 13:00:26 -07:00 +++ b/arch/i386/kernel/init_task.c 2004-06-20 13:00:26 -07:00 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/kernel/io_apic.c 2004-06-20 13:00:24 -07:00 @@ -41,10 +41,6 @@ #include "io_ports.h" -#undef APIC_LOCKUP_DEBUG - -#define APIC_LOCKUP_DEBUG - static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; /* @@ -127,83 +123,47 @@ } } -/* mask = 1 */ -static void __mask_IO_APIC_irq (unsigned int irq) +static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable) { - int pin; struct irq_pin_list *entry = irq_2_pin + irq; + unsigned int pin, reg; for (;;) { - unsigned int reg; pin = entry->pin; if (pin == -1) break; reg = io_apic_read(entry->apic, 0x10 + pin*2); - io_apic_modify(entry->apic, 0x10 + pin*2, reg |= 0x00010000); + reg &= ~disable; + reg |= enable; + io_apic_modify(entry->apic, 0x10 + pin*2, reg); if (!entry->next) break; entry = irq_2_pin + entry->next; } - io_apic_sync(entry->apic); +} + +/* mask = 1 */ +static void __mask_IO_APIC_irq (unsigned int irq) +{ + __modify_IO_APIC_irq(irq, 0x00010000, 0); } /* mask = 0 */ static void __unmask_IO_APIC_irq (unsigned int irq) { - int pin; - struct irq_pin_list *entry = irq_2_pin + irq; - - for (;;) { - unsigned int reg; - pin = entry->pin; - if (pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + pin*2); - io_apic_modify(entry->apic, 0x10 + pin*2, reg &= 0xfffeffff); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } + __modify_IO_APIC_irq(irq, 0, 0x00010000); } /* mask = 1, trigger = 0 */ static void __mask_and_edge_IO_APIC_irq (unsigned int irq) { - int pin; - struct irq_pin_list *entry = irq_2_pin + irq; - - for (;;) { - unsigned int reg; - pin = entry->pin; - if (pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + pin*2); - reg = (reg & 0xffff7fff) | 0x00010000; - io_apic_modify(entry->apic, 0x10 + pin*2, reg); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } + __modify_IO_APIC_irq(irq, 0x00010000, 0x00008000); } /* mask = 0, trigger = 1 */ static void __unmask_and_level_IO_APIC_irq (unsigned int irq) { - int pin; - struct irq_pin_list *entry = irq_2_pin + irq; - - for (;;) { - unsigned int reg; - pin = entry->pin; - if (pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + pin*2); - reg = (reg & 0xfffeffff) | 0x00008000; - io_apic_modify(entry->apic, 0x10 + pin*2, reg); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } + __modify_IO_APIC_irq(irq, 0x00008000, 0x00010000); } static void mask_IO_APIC_irq (unsigned int irq) @@ -1366,7 +1326,7 @@ printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS); - if (reg_00.bits.ID >= APIC_BROADCAST_ID) + if (reg_00.bits.ID >= get_physical_broadcast()) UNEXPECTED_IO_APIC(); if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2) UNEXPECTED_IO_APIC(); @@ -1682,7 +1642,7 @@ old_id = mp_ioapics[apic].mpc_apicid; - if (mp_ioapics[apic].mpc_apicid >= APIC_BROADCAST_ID) { + if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", @@ -1703,10 +1663,10 @@ mp_ioapics[apic].mpc_apicid)) { printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", apic, mp_ioapics[apic].mpc_apicid); - for (i = 0; i < APIC_BROADCAST_ID; i++) + for (i = 0; i < get_physical_broadcast(); i++) if (!physid_isset(i, phys_id_present_map)) break; - if (i >= APIC_BROADCAST_ID) + if (i >= get_physical_broadcast()) panic("Max APIC ID exceeded!\n"); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", i); @@ -1893,30 +1853,11 @@ ack_APIC_irq(); if (!(v & (1 << (i & 0x1f)))) { -#ifdef APIC_LOCKUP_DEBUG - struct irq_pin_list *entry; -#endif - #ifdef APIC_MISMATCH_DEBUG atomic_inc(&irq_mis_count); #endif spin_lock(&ioapic_lock); __mask_and_edge_IO_APIC_irq(irq); -#ifdef APIC_LOCKUP_DEBUG - for (entry = irq_2_pin + irq;;) { - unsigned int reg; - - if (entry->pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2); - if (reg & 0x00004000) - printk(KERN_CRIT "Aieee!!! Remote IRR" - " still set after unlock!\n"); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } -#endif __unmask_and_level_IO_APIC_irq(irq); spin_unlock(&ioapic_lock); } @@ -2322,8 +2263,6 @@ #ifdef CONFIG_ACPI_BOOT -#define IO_APIC_MAX_ID APIC_BROADCAST_ID - int __init io_apic_get_unique_id (int ioapic, int apic_id) { union IO_APIC_reg_00 reg_00; @@ -2348,7 +2287,7 @@ reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (apic_id >= IO_APIC_MAX_ID) { + if (apic_id >= get_physical_broadcast()) { printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " "%d\n", ioapic, apic_id, reg_00.bits.ID); apic_id = reg_00.bits.ID; @@ -2360,12 +2299,12 @@ */ if (check_apicid_used(apic_id_map, apic_id)) { - for (i = 0; i < IO_APIC_MAX_ID; i++) { + for (i = 0; i < get_physical_broadcast(); i++) { if (!check_apicid_used(apic_id_map, i)) break; } - if (i == IO_APIC_MAX_ID) + if (i == get_physical_broadcast()) panic("Max apic_id exceeded!\n"); printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/irq.c 2004-06-20 13:00:23 -07:00 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/kernel/mpparse.c 2004-06-20 13:00:24 -07:00 @@ -23,12 +23,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -104,6 +104,21 @@ static int mpc_record; static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; +#ifdef CONFIG_X86_NUMAQ +static int MP_valid_apicid(int apicid, int version) +{ + return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf; +} +#else +static int MP_valid_apicid(int apicid, int version) +{ + if (version >= 0x14) + return apicid < 0xff; + else + return apicid < 0xf; +} +#endif + void __init MP_processor_info (struct mpc_config_processor *m) { int ver, apicid; @@ -180,14 +195,14 @@ return; } num_processors++; + ver = m->mpc_apicver; - if (MAX_APICS - m->mpc_apicid <= 0) { + if (!MP_valid_apicid(apicid, ver)) { printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); --num_processors; return; } - ver = m->mpc_apicver; tmp = apicid_to_cpu_present(apicid); physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp); @@ -844,7 +859,7 @@ MP_processor_info(&processor); } -#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) +#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT)) #define MP_ISA_BUS 0 #define MP_MAX_IOAPIC_PIN 127 @@ -857,7 +872,7 @@ } mp_ioapic_routing[MAX_IO_APICS]; -static int __init mp_find_ioapic ( +static int mp_find_ioapic ( int gsi) { int i = 0; @@ -1002,6 +1017,7 @@ for (idx = 0; idx < mp_irq_entries; idx++) if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS && + (mp_irqs[idx].mpc_dstapic == ioapic) && (mp_irqs[idx].mpc_srcbusirq == i || mp_irqs[idx].mpc_dstirq == i)) break; @@ -1025,96 +1041,56 @@ } } -extern FADT_DESCRIPTOR acpi_fadt; - -#ifdef CONFIG_ACPI_PCI - int (*platform_rename_gsi)(int ioapic, int gsi); -void __init mp_parse_prt (void) +void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) { - struct list_head *node = NULL; - struct acpi_prt_entry *entry = NULL; int ioapic = -1; int ioapic_pin = 0; - int gsi = 0; int idx, bit = 0; - int edge_level = 0; - int active_high_low = 0; - /* - * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all entries. - */ - list_for_each(node, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); +#ifdef CONFIG_ACPI_BUS + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == gsi) + return; +#endif - /* Need to get gsi for dynamic entry */ - if (entry->link.handle) { - gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); - if (!gsi) - continue; - } - else { - /* Hardwired GSI. Assume PCI standard settings */ - gsi = entry->link.index; - edge_level = 1; - active_high_low = 1; - } + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) { + printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); + return; + } - /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_fadt.sci_int == gsi) { - /* we still need to set entry's irq */ - acpi_gsi_to_irq(gsi, &entry->irq); - continue; - } - - ioapic = mp_find_ioapic(gsi); - if (ioapic < 0) - continue; - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; - - if (platform_rename_gsi) - gsi = platform_rename_gsi(ioapic, gsi); - - /* - * Avoid pin reprogramming. PRTs typically include entries - * with redundant pin->gsi mappings (but unique PCI devices); - * we only only program the IOAPIC on the first. - */ - bit = ioapic_pin % 32; - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); - if (idx > 3) { - printk(KERN_ERR "Invalid reference to IOAPIC pin " - "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, - ioapic_pin); - continue; - } - if ((1<irq); - continue; - } + ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq); - } - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d %s %s\n", - entry->id.segment, entry->id.bus, - entry->id.device, ('A' + entry->pin), - mp_ioapic_routing[ioapic].apic_id, ioapic_pin, - entry->irq, edge_level ? "level" : "edge", - active_high_low ? "low" : "high"); + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->gsi mappings (but unique PCI devices); + * we only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + return; + } + if ((1< #include #include -#include +#include #include "setup_arch_pre.h" /* This value is set up by the early boot code to point to the value @@ -133,8 +133,203 @@ unsigned char __initdata boot_params[PARAM_SIZE]; -static struct resource code_resource = { "Kernel code", 0x100000, 0 }; -static struct resource data_resource = { "Kernel data", 0, 0 }; +static struct resource data_resource = { + .name = "Kernel data", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource code_resource = { + .name = "Kernel code", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource system_rom_resource = { + .name = "System ROM", + .start = 0xf0000, + .end = 0xfffff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource extension_rom_resource = { + .name = "Extension ROM", + .start = 0xe0000, + .end = 0xeffff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource adapter_rom_resources[] = { { + .name = "Adapter ROM", + .start = 0xc8000, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +} }; + +#define ADAPTER_ROM_RESOURCES \ + (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0]) + +static struct resource video_rom_resource = { + .name = "Video ROM", + .start = 0xc0000, + .end = 0xc7fff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource video_ram_resource = { + .name = "Video RAM area", + .start = 0xa0000, + .end = 0xbffff, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource standard_io_resources[] = { { + .name = "dma1", + .start = 0x0000, + .end = 0x001f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "pic1", + .start = 0x0020, + .end = 0x0021, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "timer", + .start = 0x0040, + .end = 0x005f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "keyboard", + .start = 0x0060, + .end = 0x006f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "dma page reg", + .start = 0x0080, + .end = 0x008f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "pic2", + .start = 0x00a0, + .end = 0x00a1, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "dma2", + .start = 0x00c0, + .end = 0x00df, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "fpu", + .start = 0x00f0, + .end = 0x00ff, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +} }; + +#define STANDARD_IO_RESOURCES \ + (sizeof standard_io_resources / sizeof standard_io_resources[0]) + +#define romsignature(x) (*(unsigned short *)(x) == 0xaa55) + +static int __init romchecksum(unsigned char *rom, unsigned long length) +{ + unsigned char *p, sum = 0; + + for (p = rom; p < rom + length; p++) + sum += *p; + return sum == 0; +} + +static void __init probe_roms(void) +{ + unsigned long start, length, upper; + unsigned char *rom; + int i; + + /* video rom */ + upper = adapter_rom_resources[0].start; + for (start = video_rom_resource.start; start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + video_rom_resource.start = start; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* if checksum okay, trust length byte */ + if (length && romchecksum(rom, length)) + video_rom_resource.end = start + length - 1; + + request_resource(&iomem_resource, &video_rom_resource); + break; + } + + start = (video_rom_resource.end + 1 + 2047) & ~2047UL; + if (start < upper) + start = upper; + + /* system rom */ + request_resource(&iomem_resource, &system_rom_resource); + upper = system_rom_resource.start; + + /* check for extension rom (ignore length byte!) */ + rom = isa_bus_to_virt(extension_rom_resource.start); + if (romsignature(rom)) { + length = extension_rom_resource.end - extension_rom_resource.start + 1; + if (romchecksum(rom, length)) { + request_resource(&iomem_resource, &extension_rom_resource); + upper = extension_rom_resource.start; + } + } + + /* check for adapter roms on 2k boundaries */ + for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* but accept any length that fits if checksum okay */ + if (!length || start + length > upper || !romchecksum(rom, length)) + continue; + + adapter_rom_resources[i].start = start; + adapter_rom_resources[i].end = start + length - 1; + request_resource(&iomem_resource, &adapter_rom_resources[i]); + + start = adapter_rom_resources[i++].end & ~2047UL; + } +} static void __init limit_regions(unsigned long long size) { @@ -948,6 +1143,7 @@ static void __init register_memory(unsigned long max_low_pfn) { unsigned long low_mem_size; + int i; if (efi_enabled) efi_initialize_iomem_resources(&code_resource, &data_resource); @@ -955,10 +1151,11 @@ legacy_init_iomem_resources(&code_resource, &data_resource); /* EFI systems may still have VGA */ - request_graphics_resource(); + request_resource(&iomem_resource, &video_ram_resource); /* request I/O space for devices used on all i[345]86 PCs */ - request_standard_io_resources(); + for (i = 0; i < STANDARD_IO_RESOURCES; i++) + request_resource(&ioport_resource, &standard_io_resources[i]); /* Tell the PCI layer not to allocate too close to the RAM area.. */ low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff; diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c --- a/arch/i386/kernel/signal.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/kernel/signal.c 2004-06-20 13:00:24 -07:00 @@ -56,16 +56,15 @@ } asmlinkage int -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) +sys_rt_sigsuspend(struct pt_regs regs) { - struct pt_regs * regs = (struct pt_regs *) &unewset; sigset_t saveset, newset; /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) + if (regs.ecx != sizeof(sigset_t)) return -EINVAL; - if (copy_from_user(&newset, unewset, sizeof(newset))) + if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset))) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); @@ -75,11 +74,11 @@ recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->eax = -EINTR; + regs.eax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(regs, &saveset)) + if (do_signal(®s, &saveset)) return -EINTR; } } @@ -117,10 +116,11 @@ } asmlinkage int -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) +sys_sigaltstack(struct pt_regs regs) { - struct pt_regs *regs = (struct pt_regs *) &uss; - return do_sigaltstack(uss, uoss, regs->esp); + const stack_t __user *uss = (const stack_t __user *)regs.ebx; + stack_t __user *uoss = (stack_t __user *)regs.ecx; + return do_sigaltstack(uss, uoss, regs.esp); } diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c --- a/arch/i386/kernel/smp.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/smp.c 2004-06-20 13:00:23 -07:00 @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/kernel/smpboot.c 2004-06-20 13:00:24 -07:00 @@ -47,7 +47,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/i386/kernel/std_resources.c b/arch/i386/kernel/std_resources.c --- a/arch/i386/kernel/std_resources.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,204 +0,0 @@ -/* - * Machine specific resource allocation for generic. - */ - -#include -#include -#include - -#define romsignature(x) (*(unsigned short *)(x) == 0xaa55) - -static struct resource system_rom_resource = { - .name = "System ROM", - .start = 0xf0000, - .end = 0xfffff, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}; - -static struct resource extension_rom_resource = { - .name = "Extension ROM", - .start = 0xe0000, - .end = 0xeffff, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}; - -static struct resource adapter_rom_resources[] = { { - .name = "Adapter ROM", - .start = 0xc8000, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -} }; - -#define ADAPTER_ROM_RESOURCES \ - (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0]) - -static struct resource video_rom_resource = { - .name = "Video ROM", - .start = 0xc0000, - .end = 0xc7fff, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}; - -static struct resource vram_resource = { - .name = "Video RAM area", - .start = 0xa0000, - .end = 0xbffff, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM -}; - -static struct resource standard_io_resources[] = { { - .name = "dma1", - .start = 0x0000, - .end = 0x001f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "pic1", - .start = 0x0020, - .end = 0x0021, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "timer", - .start = 0x0040, - .end = 0x005f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "keyboard", - .start = 0x0060, - .end = 0x006f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "dma page reg", - .start = 0x0080, - .end = 0x008f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "pic2", - .start = 0x00a0, - .end = 0x00a1, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "dma2", - .start = 0x00c0, - .end = 0x00df, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "fpu", - .start = 0x00f0, - .end = 0x00ff, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -} }; - -#define STANDARD_IO_RESOURCES \ - (sizeof standard_io_resources / sizeof standard_io_resources[0]) - -static int __init checksum(unsigned char *rom, unsigned long length) -{ - unsigned char *p, sum = 0; - - for (p = rom; p < rom + length; p++) - sum += *p; - return sum == 0; -} - -void __init probe_roms(void) -{ - unsigned long start, length, upper; - unsigned char *rom; - int i; - - /* video rom */ - upper = adapter_rom_resources[0].start; - for (start = video_rom_resource.start; start < upper; start += 2048) { - rom = isa_bus_to_virt(start); - if (!romsignature(rom)) - continue; - - video_rom_resource.start = start; - - /* 0 < length <= 0x7f * 512, historically */ - length = rom[2] * 512; - - /* if checksum okay, trust length byte */ - if (length && checksum(rom, length)) - video_rom_resource.end = start + length - 1; - - request_resource(&iomem_resource, &video_rom_resource); - break; - } - - start = (video_rom_resource.end + 1 + 2047) & ~2047UL; - if (start < upper) - start = upper; - - /* system rom */ - request_resource(&iomem_resource, &system_rom_resource); - upper = system_rom_resource.start; - - /* check for extension rom (ignore length byte!) */ - rom = isa_bus_to_virt(extension_rom_resource.start); - if (romsignature(rom)) { - length = extension_rom_resource.end - extension_rom_resource.start + 1; - if (checksum(rom, length)) { - request_resource(&iomem_resource, &extension_rom_resource); - upper = extension_rom_resource.start; - } - } - - /* check for adapter roms on 2k boundaries */ - for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) { - rom = isa_bus_to_virt(start); - if (!romsignature(rom)) - continue; - - /* 0 < length <= 0x7f * 512, historically */ - length = rom[2] * 512; - - /* but accept any length that fits if checksum okay */ - if (!length || start + length > upper || !checksum(rom, length)) - continue; - - adapter_rom_resources[i].start = start; - adapter_rom_resources[i].end = start + length - 1; - request_resource(&iomem_resource, &adapter_rom_resources[i]); - - start = adapter_rom_resources[i++].end & ~2047UL; - } -} - -void __init request_graphics_resource(void) -{ - request_resource(&iomem_resource, &vram_resource); -} - -void __init request_standard_io_resources(void) -{ - int i; - - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, &standard_io_resources[i]); -} diff -Nru a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c --- a/arch/i386/kernel/time_hpet.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/time_hpet.c 2004-06-20 13:00:23 -07:00 @@ -21,6 +21,7 @@ #include #include +#include unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* hpet clks count per tick */ @@ -135,6 +136,51 @@ hpet_writel(cfg, HPET_CFG); use_hpet = 1; + +#ifdef CONFIG_HPET + { + struct hpet_data hd; + unsigned int ntimer; + + memset(&hd, 0, sizeof (hd)); + + ntimer = hpet_readl(HPET_ID); + ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; + ntimer++; + + /* + * Register with driver. + * Timer0 and Timer1 is used by platform. + */ + hd.hd_address = hpet_virt_address; + hd.hd_nirqs = ntimer; + hd.hd_flags = HPET_DATA_PLATFORM; +#ifndef CONFIG_HPET_EMULATE_RTC + hd.hd_state = 0x1; +#else + hd.hd_state = 0x3; +#endif + hd.hd_irq[0] = HPET_LEGACY_8254; + hd.hd_irq[1] = HPET_LEGACY_RTC; + if (ntimer > 2) { + struct hpet *hpet; + struct hpet_timer *timer; + int i; + + hpet = (struct hpet *) hpet_virt_address; + + for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer; + timer++, i++) + hd.hd_irq[i] = (timer->hpet_config & + Tn_INT_ROUTE_CNF_MASK) >> + Tn_INT_ROUTE_CNF_SHIFT; + + } + + hpet_alloc(&hd); + } +#endif + #ifdef CONFIG_X86_LOCAL_APIC wait_timer_tick = wait_hpet_tick; #endif diff -Nru a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c --- a/arch/i386/kernel/timers/timer_pm.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/timers/timer_pm.c 2004-06-20 13:00:23 -07:00 @@ -21,6 +21,14 @@ #include #include +#include +#include "mach_timer.h" + +/* Number of PMTMR ticks expected during calibration run */ +#define PMTMR_TICKS_PER_SEC 3579545 +#define PMTMR_EXPECTED_RATE \ + ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10)) + /* The I/O port the PMTMR resides at. * The location is detected during setup_arch(), @@ -57,6 +65,33 @@ return v2 & ACPI_PM_MASK; } + +/* + * Some boards have the PMTMR running way too fast. We check + * the PMTMR rate against PIT channel 2 to catch these cases. + */ +static int verify_pmtmr_rate(void) +{ + u32 value1, value2; + unsigned long count, delta; + + mach_prepare_counter(); + value1 = read_pmtmr(); + mach_countup(&count); + value2 = read_pmtmr(); + delta = (value2 - value1) & ACPI_PM_MASK; + + /* Check that the PMTMR delta is within 5% of what we expect */ + if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || + delta > (PMTMR_EXPECTED_RATE * 21) / 20) { + printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", 100UL * delta / PMTMR_EXPECTED_RATE); + return -1; + } + + return 0; +} + + static int init_pmtmr(char* override) { u32 value1, value2; @@ -89,6 +124,9 @@ return -ENODEV; pm_good: + if (verify_pmtmr_rate() != 0) + return -ENODEV; + init_cpu_khz(); return 0; } diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/traps.c 2004-06-20 13:00:23 -07:00 @@ -47,7 +47,6 @@ #include #include -#include #include #include @@ -163,7 +162,6 @@ break; printk(" =======================\n"); } - printk("\n"); } void show_stack(struct task_struct *task, unsigned long *esp) diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/kernel/vm86.c 2004-06-20 13:00:23 -07:00 @@ -44,7 +44,6 @@ #include #include -#include #include #include #include @@ -178,8 +177,9 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber); static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); -asmlinkage int sys_vm86old(struct vm86_struct __user * v86) +asmlinkage int sys_vm86old(struct pt_regs regs) { + struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs.ebx; struct kernel_vm86_struct info; /* declare this _on top_, * this avoids wasting of stack space. * This remains on the stack until we @@ -198,7 +198,7 @@ if (tmp) goto out; memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus); - info.regs32 = (struct pt_regs *) &v86; + info.regs32 = ®s; tsk->thread.vm86_info = v86; do_sys_vm86(&info, tsk); ret = 0; /* we never return here */ @@ -207,7 +207,7 @@ } -asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct __user * v86) +asmlinkage int sys_vm86(struct pt_regs regs) { struct kernel_vm86_struct info; /* declare this _on top_, * this avoids wasting of stack space. @@ -216,14 +216,15 @@ */ struct task_struct *tsk; int tmp, ret; + struct vm86plus_struct __user *v86; tsk = current; - switch (subfunction) { + switch (regs.ebx) { case VM86_REQUEST_IRQ: case VM86_FREE_IRQ: case VM86_GET_IRQ_BITS: case VM86_GET_AND_RESET_IRQ: - ret = do_vm86_irq_handling(subfunction,(int)v86); + ret = do_vm86_irq_handling(regs.ebx, (int)regs.ecx); goto out; case VM86_PLUS_INSTALL_CHECK: /* NOTE: on old vm86 stuff this will return the error @@ -239,13 +240,14 @@ ret = -EPERM; if (tsk->thread.saved_esp0) goto out; + v86 = (struct vm86plus_struct __user *)regs.ecx; tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, (long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2); ret = -EFAULT; if (tmp) goto out; - info.regs32 = (struct pt_regs *) &subfunction; + info.regs32 = ®s; info.vm86plus.is_vm86pus = 1; tsk->thread.vm86_info = (struct vm86_struct __user *)v86; do_sys_vm86(&info, tsk); @@ -486,9 +488,10 @@ * in userspace is always better than an Oops anyway.) [KD] */ static void do_int(struct kernel_vm86_regs *regs, int i, - unsigned char * ssp, unsigned short sp) + unsigned char __user * ssp, unsigned short sp) { - unsigned long *intr_ptr, segoffs; + unsigned long __user *intr_ptr; + unsigned long segoffs; if (regs->cs == BIOSSEG) goto cannot_handle; @@ -496,7 +499,7 @@ goto cannot_handle; if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored)) goto cannot_handle; - intr_ptr = (unsigned long *) (i << 2); + intr_ptr = (unsigned long __user *) (i << 2); if (get_user(segoffs, intr_ptr)) goto cannot_handle; if ((segoffs >> 16) == BIOSSEG) @@ -521,7 +524,7 @@ if (VMPI.is_vm86pus) { if ( (trapno==3) || (trapno==1) ) return_to_32bit(regs, VM86_TRAP + (trapno << 8)); - do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs)); + do_int(regs, trapno, (unsigned char __user *) (regs->ss << 4), SP(regs)); return 0; } if (trapno !=1) @@ -541,7 +544,9 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) { - unsigned char *csp, *ssp, opcode; + unsigned char opcode; + unsigned char __user *csp; + unsigned char __user *ssp; unsigned short ip, sp; int data32, pref_done; @@ -553,8 +558,8 @@ return_to_32bit(regs, VM86_PICRETURN); \ return; } while (0) - csp = (unsigned char *) (regs->cs << 4); - ssp = (unsigned char *) (regs->ss << 4); + csp = (unsigned char __user *) (regs->cs << 4); + ssp = (unsigned char __user *) (regs->ss << 4); sp = SP(regs); ip = IP(regs); diff -Nru a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile --- a/arch/i386/lib/Makefile 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/lib/Makefile 2004-06-20 13:00:23 -07:00 @@ -3,9 +3,8 @@ # -lib-y = checksum.o delay.o \ - usercopy.o getuser.o \ - memcpy.o strstr.o +lib-y = checksum.o delay.o usercopy.o getuser.o memcpy.o strstr.o \ + bitops.o lib-$(CONFIG_X86_USE_3DNOW) += mmx.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff -Nru a/arch/i386/lib/bitops.c b/arch/i386/lib/bitops.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/i386/lib/bitops.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,70 @@ +#include +#include + +/** + * find_next_bit - find the first set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +int find_next_bit(const unsigned long *addr, int size, int offset) +{ + const unsigned long *p = addr + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* + * Look for nonzero in the first 32 bits: + */ + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" + : "=r" (set) + : "r" (*p >> bit)); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No set bit yet, search remaining full words for a bit + */ + res = find_first_bit (p, size - 32 * (p - addr)); + return (offset + set + res); +} +EXPORT_SYMBOL(find_next_bit); + +/** + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +int find_next_zero_bit(const unsigned long *addr, int size, int offset) +{ + unsigned long * p = ((unsigned long *) addr) + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* + * Look for zero in the first 32 bits. + */ + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" + : "=r" (set) + : "r" (~(*p >> bit))); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No zero yet, search remaining full bytes for a zero + */ + res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); + return (offset + set + res); +} +EXPORT_SYMBOL(find_next_zero_bit); diff -Nru a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c --- a/arch/i386/lib/delay.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/lib/delay.c 2004-06-20 13:00:25 -07:00 @@ -31,15 +31,16 @@ inline void __const_udelay(unsigned long xloops) { int d0; + xloops *= 4; __asm__("mull %0" :"=d" (xloops), "=&a" (d0) - :"1" (xloops),"0" (current_cpu_data.loops_per_jiffy)); - __delay(xloops * HZ); + :"1" (xloops),"0" (current_cpu_data.loops_per_jiffy * (HZ/4))); + __delay(++xloops); } void __udelay(unsigned long usecs) { - __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ + __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ } void __ndelay(unsigned long nsecs) diff -Nru a/arch/i386/mach-pc9800/Makefile b/arch/i386/mach-pc9800/Makefile --- a/arch/i386/mach-pc9800/Makefile 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,5 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-y := setup.o topology.o std_resources.o diff -Nru a/arch/i386/mach-pc9800/setup.c b/arch/i386/mach-pc9800/setup.c --- a/arch/i386/mach-pc9800/setup.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,117 +0,0 @@ -/* - * Machine specific setup for pc9800 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct sys_desc_table_struct { - unsigned short length; - unsigned char table[0]; -}; - -/** - * pre_intr_init_hook - initialisation prior to setting up interrupt vectors - * - * Description: - * Perform any necessary interrupt initialisation prior to setting up - * the "ordinary" interrupt call gates. For legacy reasons, the ISA - * interrupts should be initialised here if the machine emulates a PC - * in any way. - **/ -void __init pre_intr_init_hook(void) -{ - init_ISA_irqs(); -} - -/* - * IRQ7 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq7 = { no_action, 0, 0, "cascade", NULL, NULL}; - -/** - * intr_init_hook - post gate setup interrupt initialisation - * - * Description: - * Fill in any interrupts that may have been left out by the general - * init_IRQ() routine. interrupts having to do with the machine rather - * than the devices on the I/O bus (like APIC interrupts in intel MP - * systems) are started here. - **/ -void __init intr_init_hook(void) -{ -#ifdef CONFIG_X86_LOCAL_APIC - apic_intr_init(); -#endif - - setup_irq(7, &irq7); -} - -/** - * pre_setup_arch_hook - hook called prior to any setup_arch() execution - * - * Description: - * generally used to activate any machine specific identification - * routines that may be needed before setup_arch() runs. On VISWS - * this is used to get the board revision and type. - **/ -void __init pre_setup_arch_hook(void) -{ - SYS_DESC_TABLE.length = 0; - MCA_bus = 0; - /* In PC-9800, APM BIOS version is written in BCD...?? */ - APM_BIOS_INFO.version = (APM_BIOS_INFO.version & 0xff00) - | ((APM_BIOS_INFO.version & 0x00f0) >> 4); -} - -/** - * trap_init_hook - initialise system specific traps - * - * Description: - * Called as the final act of trap_init(). Used in VISWS to initialise - * the various board specific APIC traps. - **/ -void __init trap_init_hook(void) -{ -} - -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; - -/** - * time_init_hook - do any specific initialisations for the system timer. - * - * Description: - * Must plug the system timer interrupt source at HZ into the IRQ listed - * in irq_vectors.h:TIMER_IRQ - **/ -void __init time_init_hook(void) -{ - setup_irq(0, &irq0); -} - -#ifdef CONFIG_MCA -/** - * mca_nmi_hook - hook into MCA specific NMI chain - * - * Description: - * The MCA (Microchannel Architecture) has an NMI chain for NMI sources - * along the MCA bus. Use this to hook into that chain if you will need - * it. - **/ -void __init mca_nmi_hook(void) -{ - /* If I recall correctly, there's a whole bunch of other things that - * we can do to check for NMI problems, but that's all I know about - * at the moment. - */ - - printk("NMI generated from unknown source!\n"); -} -#endif diff -Nru a/arch/i386/mach-pc9800/std_resources.c b/arch/i386/mach-pc9800/std_resources.c --- a/arch/i386/mach-pc9800/std_resources.c 2004-06-20 13:00:26 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,195 +0,0 @@ -/* - * Machine specific resource allocation for PC-9800. - * Written by Osamu Tomita - */ - -#include -#include -#include - -static char str_pic1[] = "pic1"; -static char str_dma[] = "dma"; -static char str_pic2[] = "pic2"; -static char str_calender_clock[] = "calender clock"; -static char str_system[] = "system"; -static char str_nmi_control[] = "nmi control"; -static char str_kanji_rom[] = "kanji rom"; -static char str_keyboard[] = "keyboard"; -static char str_text_gdc[] = "text gdc"; -static char str_crtc[] = "crtc"; -static char str_timer[] = "timer"; -static char str_graphic_gdc[] = "graphic gdc"; -static char str_dma_ex_bank[] = "dma ex. bank"; -static char str_beep_freq[] = "beep freq."; -static char str_mouse_pio[] = "mouse pio"; -struct resource standard_io_resources[] = { - { str_pic1, 0x00, 0x00, IORESOURCE_BUSY }, - { str_dma, 0x01, 0x01, IORESOURCE_BUSY }, - { str_pic1, 0x02, 0x02, IORESOURCE_BUSY }, - { str_dma, 0x03, 0x03, IORESOURCE_BUSY }, - { str_dma, 0x05, 0x05, IORESOURCE_BUSY }, - { str_dma, 0x07, 0x07, IORESOURCE_BUSY }, - { str_pic2, 0x08, 0x08, IORESOURCE_BUSY }, - { str_dma, 0x09, 0x09, IORESOURCE_BUSY }, - { str_pic2, 0x0a, 0x0a, IORESOURCE_BUSY }, - { str_dma, 0x0b, 0x0b, IORESOURCE_BUSY }, - { str_dma, 0x0d, 0x0d, IORESOURCE_BUSY }, - { str_dma, 0x0f, 0x0f, IORESOURCE_BUSY }, - { str_dma, 0x11, 0x11, IORESOURCE_BUSY }, - { str_dma, 0x13, 0x13, IORESOURCE_BUSY }, - { str_dma, 0x15, 0x15, IORESOURCE_BUSY }, - { str_dma, 0x17, 0x17, IORESOURCE_BUSY }, - { str_dma, 0x19, 0x19, IORESOURCE_BUSY }, - { str_dma, 0x1b, 0x1b, IORESOURCE_BUSY }, - { str_dma, 0x1d, 0x1d, IORESOURCE_BUSY }, - { str_dma, 0x1f, 0x1f, IORESOURCE_BUSY }, - { str_calender_clock, 0x20, 0x20, 0 }, - { str_dma, 0x21, 0x21, IORESOURCE_BUSY }, - { str_calender_clock, 0x22, 0x22, 0 }, - { str_dma, 0x23, 0x23, IORESOURCE_BUSY }, - { str_dma, 0x25, 0x25, IORESOURCE_BUSY }, - { str_dma, 0x27, 0x27, IORESOURCE_BUSY }, - { str_dma, 0x29, 0x29, IORESOURCE_BUSY }, - { str_dma, 0x2b, 0x2b, IORESOURCE_BUSY }, - { str_dma, 0x2d, 0x2d, IORESOURCE_BUSY }, - { str_system, 0x31, 0x31, IORESOURCE_BUSY }, - { str_system, 0x33, 0x33, IORESOURCE_BUSY }, - { str_system, 0x35, 0x35, IORESOURCE_BUSY }, - { str_system, 0x37, 0x37, IORESOURCE_BUSY }, - { str_nmi_control, 0x50, 0x50, IORESOURCE_BUSY }, - { str_nmi_control, 0x52, 0x52, IORESOURCE_BUSY }, - { "time stamp", 0x5c, 0x5f, IORESOURCE_BUSY }, - { str_kanji_rom, 0xa1, 0xa1, IORESOURCE_BUSY }, - { str_kanji_rom, 0xa3, 0xa3, IORESOURCE_BUSY }, - { str_kanji_rom, 0xa5, 0xa5, IORESOURCE_BUSY }, - { str_kanji_rom, 0xa7, 0xa7, IORESOURCE_BUSY }, - { str_kanji_rom, 0xa9, 0xa9, IORESOURCE_BUSY }, - { str_keyboard, 0x41, 0x41, IORESOURCE_BUSY }, - { str_keyboard, 0x43, 0x43, IORESOURCE_BUSY }, - { str_text_gdc, 0x60, 0x60, IORESOURCE_BUSY }, - { str_text_gdc, 0x62, 0x62, IORESOURCE_BUSY }, - { str_text_gdc, 0x64, 0x64, IORESOURCE_BUSY }, - { str_text_gdc, 0x66, 0x66, IORESOURCE_BUSY }, - { str_text_gdc, 0x68, 0x68, IORESOURCE_BUSY }, - { str_text_gdc, 0x6a, 0x6a, IORESOURCE_BUSY }, - { str_text_gdc, 0x6c, 0x6c, IORESOURCE_BUSY }, - { str_text_gdc, 0x6e, 0x6e, IORESOURCE_BUSY }, - { str_crtc, 0x70, 0x70, IORESOURCE_BUSY }, - { str_crtc, 0x72, 0x72, IORESOURCE_BUSY }, - { str_crtc, 0x74, 0x74, IORESOURCE_BUSY }, - { str_crtc, 0x74, 0x74, IORESOURCE_BUSY }, - { str_crtc, 0x76, 0x76, IORESOURCE_BUSY }, - { str_crtc, 0x78, 0x78, IORESOURCE_BUSY }, - { str_crtc, 0x7a, 0x7a, IORESOURCE_BUSY }, - { str_timer, 0x71, 0x71, IORESOURCE_BUSY }, - { str_timer, 0x73, 0x73, IORESOURCE_BUSY }, - { str_timer, 0x75, 0x75, IORESOURCE_BUSY }, - { str_timer, 0x77, 0x77, IORESOURCE_BUSY }, - { str_graphic_gdc, 0xa0, 0xa0, IORESOURCE_BUSY }, - { str_graphic_gdc, 0xa2, 0xa2, IORESOURCE_BUSY }, - { str_graphic_gdc, 0xa4, 0xa4, IORESOURCE_BUSY }, - { str_graphic_gdc, 0xa6, 0xa6, IORESOURCE_BUSY }, - { "cpu", 0xf0, 0xf7, IORESOURCE_BUSY }, - { "fpu", 0xf8, 0xff, IORESOURCE_BUSY }, - { str_dma_ex_bank, 0x0e05, 0x0e05, 0 }, - { str_dma_ex_bank, 0x0e07, 0x0e07, 0 }, - { str_dma_ex_bank, 0x0e09, 0x0e09, 0 }, - { str_dma_ex_bank, 0x0e0b, 0x0e0b, 0 }, - { str_beep_freq, 0x3fd9, 0x3fd9, IORESOURCE_BUSY }, - { str_beep_freq, 0x3fdb, 0x3fdb, IORESOURCE_BUSY }, - { str_beep_freq, 0x3fdd, 0x3fdd, IORESOURCE_BUSY }, - { str_beep_freq, 0x3fdf, 0x3fdf, IORESOURCE_BUSY }, - /* All PC-9800 have (exactly) one mouse interface. */ - { str_mouse_pio, 0x7fd9, 0x7fd9, 0 }, - { str_mouse_pio, 0x7fdb, 0x7fdb, 0 }, - { str_mouse_pio, 0x7fdd, 0x7fdd, 0 }, - { str_mouse_pio, 0x7fdf, 0x7fdf, 0 }, - { "mouse timer", 0xbfdb, 0xbfdb, 0 }, - { "mouse irq", 0x98d7, 0x98d7, 0 }, -}; - -#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) - -static struct resource tvram_resource = { "Text VRAM/CG window", 0xa0000, 0xa4fff, IORESOURCE_BUSY }; -static struct resource gvram_brg_resource = { "Graphic VRAM (B/R/G)", 0xa8000, 0xbffff, IORESOURCE_BUSY }; -static struct resource gvram_e_resource = { "Graphic VRAM (E)", 0xe0000, 0xe7fff, IORESOURCE_BUSY }; - -/* System ROM resources */ -#define MAXROMS 6 -static struct resource rom_resources[MAXROMS] = { - { "System ROM", 0xe8000, 0xfffff, IORESOURCE_BUSY } -}; - -void __init probe_roms(void) -{ - int i; - __u8 *xrom_id; - int roms = 1; - - request_resource(&iomem_resource, rom_resources+0); - - xrom_id = (__u8 *) isa_bus_to_virt(PC9800SCA_XROM_ID + 0x10); - - for (i = 0; i < 16; i++) { - if (xrom_id[i] & 0x80) { - int j; - - for (j = i + 1; j < 16 && (xrom_id[j] & 0x80); j++) - ; - rom_resources[roms].start = 0x0d0000 + i * 0x001000; - rom_resources[roms].end = 0x0d0000 + j * 0x001000 - 1; - rom_resources[roms].name = "Extension ROM"; - rom_resources[roms].flags = IORESOURCE_BUSY; - - request_resource(&iomem_resource, - rom_resources + roms); - if (++roms >= MAXROMS) - return; - } - } -} - -void __init request_graphics_resource(void) -{ - int i; - - if (PC9800_HIGHRESO_P()) { - tvram_resource.start = 0xe0000; - tvram_resource.end = 0xe4fff; - gvram_brg_resource.name = "Graphic VRAM"; - gvram_brg_resource.start = 0xc0000; - gvram_brg_resource.end = 0xdffff; - } - - request_resource(&iomem_resource, &tvram_resource); - request_resource(&iomem_resource, &gvram_brg_resource); - if (!PC9800_HIGHRESO_P()) - request_resource(&iomem_resource, &gvram_e_resource); - - if (PC9800_HIGHRESO_P() || PC9800_9821_P()) { - static char graphics[] = "graphics"; - static struct resource graphics_resources[] = { - { graphics, 0x9a0, 0x9a0, 0 }, - { graphics, 0x9a2, 0x9a2, 0 }, - { graphics, 0x9a4, 0x9a4, 0 }, - { graphics, 0x9a6, 0x9a6, 0 }, - { graphics, 0x9a8, 0x9a8, 0 }, - { graphics, 0x9aa, 0x9aa, 0 }, - { graphics, 0x9ac, 0x9ac, 0 }, - { graphics, 0x9ae, 0x9ae, 0 }, - }; - -#define GRAPHICS_RESOURCES (sizeof(graphics_resources)/sizeof(struct resource)) - - for (i = 0; i < GRAPHICS_RESOURCES; i++) - request_resource(&ioport_resource, graphics_resources + i); - } -} - -void __init request_standard_io_resources(void) -{ - int i; - - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, standard_io_resources+i); -} diff -Nru a/arch/i386/mach-pc9800/topology.c b/arch/i386/mach-pc9800/topology.c --- a/arch/i386/mach-pc9800/topology.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,44 +0,0 @@ -/* - * arch/i386/mach-pc9800/topology.c - Populate driverfs with topology information - * - * Written by: Matthew Dobson, IBM Corporation - * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL - * - * Copyright (C) 2002, IBM Corp. - * - * 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 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Modify for PC-9800 by Osamu Tomita - * - */ -#include -#include -#include - -struct i386_cpu cpu_devices[NR_CPUS]; - -static int __init topology_init(void) -{ - int i; - - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) arch_register_cpu(i); - return 0; -} - -subsys_initcall(topology_init); diff -Nru a/arch/i386/mach-visws/mpparse.c b/arch/i386/mach-visws/mpparse.c --- a/arch/i386/mach-visws/mpparse.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/mach-visws/mpparse.c 2004-06-20 13:00:23 -07:00 @@ -57,12 +57,12 @@ boot_cpu_logical_apicid = logical_apicid; } - if (m->mpc_apicid > MAX_APICS) { + ver = m->mpc_apicver; + if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) { printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", m->mpc_apicid, MAX_APICS); return; } - ver = m->mpc_apicver; apic_cpus = apicid_to_cpu_present(m->mpc_apicid); physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus); diff -Nru a/arch/i386/mach-visws/traps.c b/arch/i386/mach-visws/traps.c --- a/arch/i386/mach-visws/traps.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/mach-visws/traps.c 2004-06-20 13:00:25 -07:00 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include "cobalt.h" diff -Nru a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c --- a/arch/i386/mach-voyager/voyager_basic.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/mach-voyager/voyager_basic.c 2004-06-20 13:00:23 -07:00 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c --- a/arch/i386/mach-voyager/voyager_smp.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/mach-voyager/voyager_smp.c 2004-06-20 13:00:24 -07:00 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c --- a/arch/i386/mach-voyager/voyager_thread.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/mach-voyager/voyager_thread.c 2004-06-20 13:00:25 -07:00 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/i386/math-emu/errors.c b/arch/i386/math-emu/errors.c --- a/arch/i386/math-emu/errors.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/math-emu/errors.c 2004-06-20 13:00:24 -07:00 @@ -41,18 +41,18 @@ RE_ENTRANT_CHECK_OFF; /* No need to verify_area(), we have previously fetched these bytes. */ - printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address); + printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *) address); if ( FPU_CS == __USER_CS ) { while ( 1 ) { - FPU_get_user(byte1, (u_char *) address); + FPU_get_user(byte1, (u_char __user *) address); if ( (byte1 & 0xf8) == 0xd8 ) break; printk("[%02x]", byte1); address++; } printk("%02x ", byte1); - FPU_get_user(FPU_modrm, 1 + (u_char *) address); + FPU_get_user(FPU_modrm, 1 + (u_char __user *) address); if (FPU_modrm >= 0300) printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); @@ -98,7 +98,7 @@ #define MAX_PRINTED_BYTES 20 for ( i = 0; i < MAX_PRINTED_BYTES; i++ ) { - FPU_get_user(byte1, (u_char *) address); + FPU_get_user(byte1, (u_char __user *) address); if ( (byte1 & 0xf8) == 0xd8 ) { printk(" %02x", byte1); @@ -111,7 +111,7 @@ printk(" [more..]\n"); else { - FPU_get_user(FPU_modrm, 1 + (u_char *) address); + FPU_get_user(FPU_modrm, 1 + (u_char __user *) address); if (FPU_modrm >= 0300) printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); diff -Nru a/arch/i386/math-emu/fpu_arith.c b/arch/i386/math-emu/fpu_arith.c --- a/arch/i386/math-emu/fpu_arith.c 2004-06-20 13:00:26 -07:00 +++ b/arch/i386/math-emu/fpu_arith.c 2004-06-20 13:00:26 -07:00 @@ -16,7 +16,7 @@ #include "status_w.h" -void fadd__() +void fadd__(void) { /* fadd st,st(i) */ int i = FPU_rm; @@ -25,7 +25,7 @@ } -void fmul__() +void fmul__(void) { /* fmul st,st(i) */ int i = FPU_rm; @@ -35,7 +35,7 @@ -void fsub__() +void fsub__(void) { /* fsub st,st(i) */ clear_C1(); @@ -43,7 +43,7 @@ } -void fsubr_() +void fsubr_(void) { /* fsubr st,st(i) */ clear_C1(); @@ -51,7 +51,7 @@ } -void fdiv__() +void fdiv__(void) { /* fdiv st,st(i) */ clear_C1(); @@ -59,7 +59,7 @@ } -void fdivr_() +void fdivr_(void) { /* fdivr st,st(i) */ clear_C1(); @@ -68,7 +68,7 @@ -void fadd_i() +void fadd_i(void) { /* fadd st(i),st */ int i = FPU_rm; @@ -77,7 +77,7 @@ } -void fmul_i() +void fmul_i(void) { /* fmul st(i),st */ clear_C1(); @@ -85,7 +85,7 @@ } -void fsubri() +void fsubri(void) { /* fsubr st(i),st */ clear_C1(); @@ -93,7 +93,7 @@ } -void fsub_i() +void fsub_i(void) { /* fsub st(i),st */ clear_C1(); @@ -101,7 +101,7 @@ } -void fdivri() +void fdivri(void) { /* fdivr st(i),st */ clear_C1(); @@ -109,7 +109,7 @@ } -void fdiv_i() +void fdiv_i(void) { /* fdiv st(i),st */ clear_C1(); @@ -118,7 +118,7 @@ -void faddp_() +void faddp_(void) { /* faddp st(i),st */ int i = FPU_rm; @@ -128,7 +128,7 @@ } -void fmulp_() +void fmulp_(void) { /* fmulp st(i),st */ clear_C1(); @@ -138,7 +138,7 @@ -void fsubrp() +void fsubrp(void) { /* fsubrp st(i),st */ clear_C1(); @@ -147,7 +147,7 @@ } -void fsubp_() +void fsubp_(void) { /* fsubp st(i),st */ clear_C1(); @@ -156,7 +156,7 @@ } -void fdivrp() +void fdivrp(void) { /* fdivrp st(i),st */ clear_C1(); @@ -165,7 +165,7 @@ } -void fdivp_() +void fdivp_(void) { /* fdivp st(i),st */ clear_C1(); diff -Nru a/arch/i386/math-emu/fpu_aux.c b/arch/i386/math-emu/fpu_aux.c --- a/arch/i386/math-emu/fpu_aux.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/math-emu/fpu_aux.c 2004-06-20 13:00:23 -07:00 @@ -30,7 +30,7 @@ } /* Needs to be externally visible */ -void finit() +void finit(void) { control_word = 0x037f; partial_status = 0; @@ -58,7 +58,7 @@ fsetpm, FPU_illegal, FPU_illegal, FPU_illegal }; -void finit_() +void finit_(void) { (finit_table[FPU_rm])(); } @@ -75,7 +75,7 @@ FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal }; -void fstsw_() +void fstsw_(void) { (fstsw_table[FPU_rm])(); } @@ -86,13 +86,13 @@ FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal }; -void fp_nop() +void fp_nop(void) { (fp_nop_table[FPU_rm])(); } -void fld_i_() +void fld_i_(void) { FPU_REG *st_new_ptr; int i; @@ -124,7 +124,7 @@ } -void fxch_i() +void fxch_i(void) { /* fxch st(i) */ FPU_REG t; @@ -173,14 +173,14 @@ } -void ffree_() +void ffree_(void) { /* ffree st(i) */ FPU_settagi(FPU_rm, TAG_Empty); } -void ffreep() +void ffreep(void) { /* ffree st(i) + pop - unofficial code */ FPU_settagi(FPU_rm, TAG_Empty); @@ -188,14 +188,14 @@ } -void fst_i_() +void fst_i_(void) { /* fst st(i) */ FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm); } -void fstp_i() +void fstp_i(void) { /* fstp st(i) */ FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm); diff -Nru a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c --- a/arch/i386/math-emu/fpu_entry.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/math-emu/fpu_entry.c 2004-06-20 13:00:25 -07:00 @@ -128,7 +128,7 @@ u_char emulating=0; #endif /* RE_ENTRANT_CHECKING */ -static int valid_prefix(u_char *Byte, u_char **fpu_eip, +static int valid_prefix(u_char *Byte, u_char __user **fpu_eip, overrides *override); asmlinkage void math_emulate(long arg) @@ -140,7 +140,7 @@ FPU_REG loaded_data; FPU_REG *st0_ptr; u_char loaded_tag, st0_tag; - void *data_address; + void __user *data_address; struct address data_sel_off; struct address entry_sel_off; unsigned long code_base = 0; @@ -192,7 +192,8 @@ math_abort(FPU_info, SIGILL); } - if ( SEG_D_SIZE(code_descriptor = LDT_DESCRIPTOR(FPU_CS)) ) + code_descriptor = LDT_DESCRIPTOR(FPU_CS); + if ( SEG_D_SIZE(code_descriptor) ) { /* The above test may be wrong, the book is not clear */ /* Segmented 32 bit protected mode */ @@ -214,7 +215,7 @@ if (current->ptrace & PT_PTRACED) FPU_lookahead = 0; - if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP, + if ( !valid_prefix(&byte1, (u_char __user **)&FPU_EIP, &addr_modes.override) ) { RE_ENTRANT_CHECK_OFF; @@ -257,7 +258,7 @@ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(1); - FPU_get_user(FPU_modrm, (u_char *) FPU_EIP); + FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP); RE_ENTRANT_CHECK_ON; FPU_EIP++; @@ -336,23 +337,23 @@ switch ( (byte1 >> 1) & 3 ) { case 0: - unmasked = FPU_load_single((float *)data_address, + unmasked = FPU_load_single((float __user *)data_address, &loaded_data); loaded_tag = unmasked & 0xff; unmasked &= ~0xff; break; case 1: - loaded_tag = FPU_load_int32((long *)data_address, &loaded_data); + loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data); break; case 2: - unmasked = FPU_load_double((double *)data_address, + unmasked = FPU_load_double((double __user *)data_address, &loaded_data); loaded_tag = unmasked & 0xff; unmasked &= ~0xff; break; case 3: default: /* Used here to suppress gcc warnings. */ - loaded_tag = FPU_load_int16((short *)data_address, &loaded_data); + loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data); break; } @@ -563,7 +564,7 @@ if (FPU_lookahead && !need_resched()) { FPU_ORIG_EIP = FPU_EIP - code_base; - if ( valid_prefix(&byte1, (u_char **)&FPU_EIP, + if ( valid_prefix(&byte1, (u_char __user **)&FPU_EIP, &addr_modes.override) ) goto do_another_FPU_instruction; } @@ -579,11 +580,11 @@ all prefix bytes, further changes are needed in the emulator code which accesses user address space. Access to separate segments is important for msdos emulation. */ -static int valid_prefix(u_char *Byte, u_char **fpu_eip, +static int valid_prefix(u_char *Byte, u_char __user **fpu_eip, overrides *override) { u_char byte; - u_char *ip = *fpu_eip; + u_char __user *ip = *fpu_eip; *override = (overrides) { 0, 0, PREFIX_DEFAULT }; /* defaults */ @@ -679,9 +680,9 @@ #define sstatus_word() \ ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top)) -int restore_i387_soft(void *s387, struct _fpstate *buf) +int restore_i387_soft(void *s387, struct _fpstate __user *buf) { - u_char *d = (u_char *)buf; + u_char __user *d = (u_char __user *)buf; int offset, other, i, tags, regnr, tag, newtop; RE_ENTRANT_CHECK_OFF; @@ -725,9 +726,9 @@ } -int save_i387_soft(void *s387, struct _fpstate * buf) +int save_i387_soft(void *s387, struct _fpstate __user * buf) { - u_char *d = (u_char *)buf; + u_char __user *d = (u_char __user *)buf; int offset = (S387->ftop & 7) * 10, other = 80 - offset; RE_ENTRANT_CHECK_OFF; diff -Nru a/arch/i386/math-emu/fpu_etc.c b/arch/i386/math-emu/fpu_etc.c --- a/arch/i386/math-emu/fpu_etc.c 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/math-emu/fpu_etc.c 2004-06-20 13:00:24 -07:00 @@ -137,7 +137,7 @@ ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal }; -void FPU_etc() +void FPU_etc(void) { (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0()); } diff -Nru a/arch/i386/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h --- a/arch/i386/math-emu/fpu_proto.h 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/math-emu/fpu_proto.h 2004-06-20 13:00:25 -07:00 @@ -77,13 +77,13 @@ extern void FPU_triga(void); extern void FPU_trigb(void); /* get_address.c */ -extern void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, +extern void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, struct address *addr, fpu_addr_modes addr_modes); -extern void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, +extern void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, struct address *addr, fpu_addr_modes addr_modes); /* load_store.c */ extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes, - void *data_address); + void __user *data_address); /* poly_2xm1.c */ extern int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result); /* poly_atan.c */ @@ -112,26 +112,26 @@ /* reg_constant.c */ extern void fconst(void); /* reg_ld_str.c */ -extern int FPU_load_extended(long double *s, int stnr); -extern int FPU_load_double(double *dfloat, FPU_REG *loaded_data); -extern int FPU_load_single(float *single, FPU_REG *loaded_data); -extern int FPU_load_int64(long long *_s); -extern int FPU_load_int32(long *_s, FPU_REG *loaded_data); -extern int FPU_load_int16(short *_s, FPU_REG *loaded_data); -extern int FPU_load_bcd(u_char *s); +extern int FPU_load_extended(long double __user *s, int stnr); +extern int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data); +extern int FPU_load_single(float __user *single, FPU_REG *loaded_data); +extern int FPU_load_int64(long long __user *_s); +extern int FPU_load_int32(long __user *_s, FPU_REG *loaded_data); +extern int FPU_load_int16(short __user *_s, FPU_REG *loaded_data); +extern int FPU_load_bcd(u_char __user *s); extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, - long double *d); -extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat); -extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single); -extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long *d); -extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long *d); -extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short *d); -extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d); + long double __user *d); +extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat); +extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single); +extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d); +extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d); +extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d); +extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d); extern int FPU_round_to_int(FPU_REG *r, u_char tag); -extern u_char *fldenv(fpu_addr_modes addr_modes, u_char *s); -extern void frstor(fpu_addr_modes addr_modes, u_char *data_address); -extern u_char *fstenv(fpu_addr_modes addr_modes, u_char *d); -extern void fsave(fpu_addr_modes addr_modes, u_char *data_address); +extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s); +extern void frstor(fpu_addr_modes addr_modes, u_char __user *data_address); +extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d); +extern void fsave(fpu_addr_modes addr_modes, u_char __user *data_address); extern int FPU_tagof(FPU_REG *ptr); /* reg_mul.c */ extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w); diff -Nru a/arch/i386/math-emu/fpu_system.h b/arch/i386/math-emu/fpu_system.h --- a/arch/i386/math-emu/fpu_system.h 2004-06-20 13:00:24 -07:00 +++ b/arch/i386/math-emu/fpu_system.h 2004-06-20 13:00:24 -07:00 @@ -80,7 +80,7 @@ /* A simpler test than verify_area() can probably be done for FPU_code_verify_area() because the only possible error is to step past the upper boundary of a legal code area. */ -#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z) +#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void __user *)FPU_EIP,z) #endif #define FPU_get_user(x,y) get_user((x),(y)) diff -Nru a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c --- a/arch/i386/math-emu/get_address.c 2004-06-20 13:00:26 -07:00 +++ b/arch/i386/math-emu/get_address.c 2004-06-20 13:00:26 -07:00 @@ -82,7 +82,7 @@ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(1); - FPU_get_user(base, (u_char *) (*fpu_eip)); /* The SIB byte */ + FPU_get_user(base, (u_char __user *) (*fpu_eip)); /* The SIB byte */ RE_ENTRANT_CHECK_ON; (*fpu_eip)++; ss = base >> 6; @@ -112,7 +112,7 @@ long displacement; RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(1); - FPU_get_user(displacement, (signed char *) (*fpu_eip)); + FPU_get_user(displacement, (signed char __user *) (*fpu_eip)); offset += displacement; RE_ENTRANT_CHECK_ON; (*fpu_eip)++; @@ -123,7 +123,7 @@ long displacement; RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(4); - FPU_get_user(displacement, (long *) (*fpu_eip)); + FPU_get_user(displacement, (long __user *) (*fpu_eip)); offset += displacement; RE_ENTRANT_CHECK_ON; (*fpu_eip) += 4; @@ -241,7 +241,7 @@ */ -void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, +void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, struct address *addr, fpu_addr_modes addr_modes) { @@ -277,24 +277,24 @@ /* Special case: disp32 */ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(4); - FPU_get_user(address, (unsigned long *) (*fpu_eip)); + FPU_get_user(address, (unsigned long __user *) (*fpu_eip)); (*fpu_eip) += 4; RE_ENTRANT_CHECK_ON; addr->offset = address; - return (void *) address; + return (void __user *) address; } else { address = *cpu_reg_ptr; /* Just return the contents of the cpu register */ addr->offset = address; - return (void *) address; + return (void __user *) address; } case 1: /* 8 bit signed displacement */ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(1); - FPU_get_user(address, (signed char *) (*fpu_eip)); + FPU_get_user(address, (signed char __user *) (*fpu_eip)); RE_ENTRANT_CHECK_ON; (*fpu_eip)++; break; @@ -302,7 +302,7 @@ /* 32 bit displacement */ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(4); - FPU_get_user(address, (long *) (*fpu_eip)); + FPU_get_user(address, (long __user *) (*fpu_eip)); (*fpu_eip) += 4; RE_ENTRANT_CHECK_ON; break; @@ -331,11 +331,11 @@ EXCEPTION(EX_INTERNAL|0x133); } - return (void *)address; + return (void __user *)address; } -void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, +void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, struct address *addr, fpu_addr_modes addr_modes) { @@ -363,7 +363,7 @@ /* Special case: disp16 */ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(2); - FPU_get_user(address, (unsigned short *) (*fpu_eip)); + FPU_get_user(address, (unsigned short __user *) (*fpu_eip)); (*fpu_eip) += 2; RE_ENTRANT_CHECK_ON; goto add_segment; @@ -373,7 +373,7 @@ /* 8 bit signed displacement */ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(1); - FPU_get_user(address, (signed char *) (*fpu_eip)); + FPU_get_user(address, (signed char __user *) (*fpu_eip)); RE_ENTRANT_CHECK_ON; (*fpu_eip)++; break; @@ -381,7 +381,7 @@ /* 16 bit displacement */ RE_ENTRANT_CHECK_OFF; FPU_code_verify_area(2); - FPU_get_user(address, (unsigned short *) (*fpu_eip)); + FPU_get_user(address, (unsigned short __user *) (*fpu_eip)); (*fpu_eip) += 2; RE_ENTRANT_CHECK_ON; break; @@ -445,5 +445,5 @@ EXCEPTION(EX_INTERNAL|0x131); } - return (void *)address ; + return (void __user *)address ; } diff -Nru a/arch/i386/math-emu/load_store.c b/arch/i386/math-emu/load_store.c --- a/arch/i386/math-emu/load_store.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/math-emu/load_store.c 2004-06-20 13:00:23 -07:00 @@ -61,7 +61,7 @@ }; int FPU_load_store(u_char type, fpu_addr_modes addr_modes, - void *data_address) + void __user *data_address) { FPU_REG loaded_data; FPU_REG *st0_ptr; @@ -119,7 +119,7 @@ { case 000: /* fld m32real */ clear_C1(); - loaded_tag = FPU_load_single((float *)data_address, &loaded_data); + loaded_tag = FPU_load_single((float __user *)data_address, &loaded_data); if ( (loaded_tag == TAG_Special) && isNaN(&loaded_data) && (real_1op_NaN(&loaded_data) < 0) ) @@ -131,12 +131,12 @@ break; case 001: /* fild m32int */ clear_C1(); - loaded_tag = FPU_load_int32((long *)data_address, &loaded_data); + loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data); FPU_copy_to_reg0(&loaded_data, loaded_tag); break; case 002: /* fld m64real */ clear_C1(); - loaded_tag = FPU_load_double((double *)data_address, &loaded_data); + loaded_tag = FPU_load_double((double __user *)data_address, &loaded_data); if ( (loaded_tag == TAG_Special) && isNaN(&loaded_data) && (real_1op_NaN(&loaded_data) < 0) ) @@ -148,68 +148,68 @@ break; case 003: /* fild m16int */ clear_C1(); - loaded_tag = FPU_load_int16((short *)data_address, &loaded_data); + loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data); FPU_copy_to_reg0(&loaded_data, loaded_tag); break; case 010: /* fst m32real */ clear_C1(); - FPU_store_single(st0_ptr, st0_tag, (float *)data_address); + FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address); break; case 011: /* fist m32int */ clear_C1(); - FPU_store_int32(st0_ptr, st0_tag, (long *)data_address); + FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address); break; case 012: /* fst m64real */ clear_C1(); - FPU_store_double(st0_ptr, st0_tag, (double *)data_address); + FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address); break; case 013: /* fist m16int */ clear_C1(); - FPU_store_int16(st0_ptr, st0_tag, (short *)data_address); + FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address); break; case 014: /* fstp m32real */ clear_C1(); - if ( FPU_store_single(st0_ptr, st0_tag, (float *)data_address) ) + if ( FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; case 015: /* fistp m32int */ clear_C1(); - if ( FPU_store_int32(st0_ptr, st0_tag, (long *)data_address) ) + if ( FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; case 016: /* fstp m64real */ clear_C1(); - if ( FPU_store_double(st0_ptr, st0_tag, (double *)data_address) ) + if ( FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; case 017: /* fistp m16int */ clear_C1(); - if ( FPU_store_int16(st0_ptr, st0_tag, (short *)data_address) ) + if ( FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; case 020: /* fldenv m14/28byte */ - fldenv(addr_modes, (u_char *)data_address); + fldenv(addr_modes, (u_char __user *)data_address); /* Ensure that the values just loaded are not changed by fix-up operations. */ return 1; case 022: /* frstor m94/108byte */ - frstor(addr_modes, (u_char *)data_address); + frstor(addr_modes, (u_char __user *)data_address); /* Ensure that the values just loaded are not changed by fix-up operations. */ return 1; case 023: /* fbld m80dec */ clear_C1(); - loaded_tag = FPU_load_bcd((u_char *)data_address); + loaded_tag = FPU_load_bcd((u_char __user *)data_address); FPU_settag0(loaded_tag); break; case 024: /* fldcw */ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_READ, data_address, 2); - FPU_get_user(control_word, (unsigned short *) data_address); + FPU_get_user(control_word, (unsigned short __user *) data_address); RE_ENTRANT_CHECK_ON; if ( partial_status & ~control_word & CW_Exceptions ) partial_status |= (SW_Summary | SW_Backward); @@ -221,47 +221,47 @@ return 1; case 025: /* fld m80real */ clear_C1(); - loaded_tag = FPU_load_extended((long double *)data_address, 0); + loaded_tag = FPU_load_extended((long double __user *)data_address, 0); FPU_settag0(loaded_tag); break; case 027: /* fild m64int */ clear_C1(); - loaded_tag = FPU_load_int64((long long *)data_address); + loaded_tag = FPU_load_int64((long long __user *)data_address); FPU_settag0(loaded_tag); break; case 030: /* fstenv m14/28byte */ - fstenv(addr_modes, (u_char *)data_address); + fstenv(addr_modes, (u_char __user *)data_address); return 1; case 032: /* fsave */ - fsave(addr_modes, (u_char *)data_address); + fsave(addr_modes, (u_char __user *)data_address); return 1; case 033: /* fbstp m80dec */ clear_C1(); - if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char *)data_address) ) + if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; case 034: /* fstcw m16int */ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,data_address,2); - FPU_put_user(control_word, (unsigned short *) data_address); + FPU_put_user(control_word, (unsigned short __user *) data_address); RE_ENTRANT_CHECK_ON; return 1; case 035: /* fstp m80real */ clear_C1(); - if ( FPU_store_extended(st0_ptr, st0_tag, (long double *)data_address) ) + if ( FPU_store_extended(st0_ptr, st0_tag, (long double __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; case 036: /* fstsw m2byte */ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,data_address,2); - FPU_put_user(status_word(),(unsigned short *) data_address); + FPU_put_user(status_word(),(unsigned short __user *) data_address); RE_ENTRANT_CHECK_ON; return 1; case 037: /* fistp m64int */ clear_C1(); - if ( FPU_store_int64(st0_ptr, st0_tag, (long long *)data_address) ) + if ( FPU_store_int64(st0_ptr, st0_tag, (long long __user *)data_address) ) pop_0(); /* pop only if the number was actually stored (see the 80486 manual p16-28) */ break; diff -Nru a/arch/i386/math-emu/reg_compare.c b/arch/i386/math-emu/reg_compare.c --- a/arch/i386/math-emu/reg_compare.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/math-emu/reg_compare.c 2004-06-20 13:00:25 -07:00 @@ -324,14 +324,14 @@ /*---------------------------------------------------------------------------*/ -void fcom_st() +void fcom_st(void) { /* fcom st(i) */ compare_st_st(FPU_rm); } -void fcompst() +void fcompst(void) { /* fcomp st(i) */ if ( !compare_st_st(FPU_rm) ) @@ -339,7 +339,7 @@ } -void fcompp() +void fcompp(void) { /* fcompp */ if (FPU_rm != 1) @@ -352,7 +352,7 @@ } -void fucom_() +void fucom_(void) { /* fucom st(i) */ compare_u_st_st(FPU_rm); @@ -360,7 +360,7 @@ } -void fucomp() +void fucomp(void) { /* fucomp st(i) */ if ( !compare_u_st_st(FPU_rm) ) @@ -368,7 +368,7 @@ } -void fucompp() +void fucompp(void) { /* fucompp */ if (FPU_rm == 1) diff -Nru a/arch/i386/math-emu/reg_ld_str.c b/arch/i386/math-emu/reg_ld_str.c --- a/arch/i386/math-emu/reg_ld_str.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/math-emu/reg_ld_str.c 2004-06-20 13:00:25 -07:00 @@ -86,7 +86,7 @@ /* Get a long double from user memory */ -int FPU_load_extended(long double *s, int stnr) +int FPU_load_extended(long double __user *s, int stnr) { FPU_REG *sti_ptr = &st(stnr); @@ -100,15 +100,15 @@ /* Get a double from user memory */ -int FPU_load_double(double *dfloat, FPU_REG *loaded_data) +int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data) { int exp, tag, negative; unsigned m64, l64; RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_READ, dfloat, 8); - FPU_get_user(m64, 1 + (unsigned long *) dfloat); - FPU_get_user(l64, (unsigned long *) dfloat); + FPU_get_user(m64, 1 + (unsigned long __user *) dfloat); + FPU_get_user(l64, (unsigned long __user *) dfloat); RE_ENTRANT_CHECK_ON; negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive; @@ -172,14 +172,14 @@ /* Get a float from user memory */ -int FPU_load_single(float *single, FPU_REG *loaded_data) +int FPU_load_single(float __user *single, FPU_REG *loaded_data) { unsigned m32; int exp, tag, negative; RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_READ, single, 4); - FPU_get_user(m32, (unsigned long *) single); + FPU_get_user(m32, (unsigned long __user *) single); RE_ENTRANT_CHECK_ON; negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive; @@ -236,7 +236,7 @@ /* Get a long long from user memory */ -int FPU_load_int64(long long *_s) +int FPU_load_int64(long long __user *_s) { long long s; int sign; @@ -268,7 +268,7 @@ /* Get a long from user memory */ -int FPU_load_int32(long *_s, FPU_REG *loaded_data) +int FPU_load_int32(long __user *_s, FPU_REG *loaded_data) { long s; int negative; @@ -297,7 +297,7 @@ /* Get a short from user memory */ -int FPU_load_int16(short *_s, FPU_REG *loaded_data) +int FPU_load_int16(short __user *_s, FPU_REG *loaded_data) { int s, negative; @@ -326,7 +326,7 @@ /* Get a packed bcd array from user memory */ -int FPU_load_bcd(u_char *s) +int FPU_load_bcd(u_char __user *s) { FPU_REG *st0_ptr = &st(0); int pos; @@ -341,7 +341,7 @@ { l *= 10; RE_ENTRANT_CHECK_OFF; - FPU_get_user(bcd, (u_char *) s+pos); + FPU_get_user(bcd, s+pos); RE_ENTRANT_CHECK_ON; l += bcd >> 4; l *= 10; @@ -349,7 +349,7 @@ } RE_ENTRANT_CHECK_OFF; - FPU_get_user(sign, (u_char *) s+9); + FPU_get_user(sign, s+9); sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive; RE_ENTRANT_CHECK_ON; @@ -369,7 +369,7 @@ /*===========================================================================*/ /* Put a long double into user memory */ -int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double *d) +int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d) { /* The only exception raised by an attempt to store to an @@ -382,9 +382,9 @@ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE, d, 10); - FPU_put_user(st0_ptr->sigl, (unsigned long *) d); - FPU_put_user(st0_ptr->sigh, (unsigned long *) ((u_char *)d + 4)); - FPU_put_user(exponent16(st0_ptr), (unsigned short *) ((u_char *)d + 8)); + FPU_put_user(st0_ptr->sigl, (unsigned long __user *) d); + FPU_put_user(st0_ptr->sigh, (unsigned long __user *) ((u_char __user *)d + 4)); + FPU_put_user(exponent16(st0_ptr), (unsigned short __user *) ((u_char __user *)d + 8)); RE_ENTRANT_CHECK_ON; return 1; @@ -398,9 +398,9 @@ /* Put out the QNaN indefinite */ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,d,10); - FPU_put_user(0, (unsigned long *) d); - FPU_put_user(0xc0000000, 1 + (unsigned long *) d); - FPU_put_user(0xffff, 4 + (short *) d); + FPU_put_user(0, (unsigned long __user *) d); + FPU_put_user(0xc0000000, 1 + (unsigned long __user *) d); + FPU_put_user(0xffff, 4 + (short __user *) d); RE_ENTRANT_CHECK_ON; return 1; } @@ -411,7 +411,7 @@ /* Put a double into user memory */ -int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat) +int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat) { unsigned long l[2]; unsigned long increment = 0; /* avoid gcc warnings */ @@ -607,9 +607,9 @@ /* The masked response */ /* Put out the QNaN indefinite */ RE_ENTRANT_CHECK_OFF; - FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8); - FPU_put_user(0, (unsigned long *) dfloat); - FPU_put_user(0xfff80000, 1 + (unsigned long *) dfloat); + FPU_verify_area(VERIFY_WRITE,dfloat,8); + FPU_put_user(0, (unsigned long __user *) dfloat); + FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat); RE_ENTRANT_CHECK_ON; return 1; } @@ -620,9 +620,9 @@ l[1] |= 0x80000000; RE_ENTRANT_CHECK_OFF; - FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8); - FPU_put_user(l[0], (unsigned long *)dfloat); - FPU_put_user(l[1], 1 + (unsigned long *)dfloat); + FPU_verify_area(VERIFY_WRITE,dfloat,8); + FPU_put_user(l[0], (unsigned long __user *)dfloat); + FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat); RE_ENTRANT_CHECK_ON; return 1; @@ -630,7 +630,7 @@ /* Put a float into user memory */ -int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single) +int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single) { long templ = 0; unsigned long increment = 0; /* avoid gcc warnings */ @@ -826,8 +826,8 @@ /* The masked response */ /* Put out the QNaN indefinite */ RE_ENTRANT_CHECK_OFF; - FPU_verify_area(VERIFY_WRITE,(void *)single,4); - FPU_put_user(0xffc00000, (unsigned long *) single); + FPU_verify_area(VERIFY_WRITE,single,4); + FPU_put_user(0xffc00000, (unsigned long __user *) single); RE_ENTRANT_CHECK_ON; return 1; } @@ -845,8 +845,8 @@ templ |= 0x80000000; RE_ENTRANT_CHECK_OFF; - FPU_verify_area(VERIFY_WRITE,(void *)single,4); - FPU_put_user(templ,(unsigned long *) single); + FPU_verify_area(VERIFY_WRITE,single,4); + FPU_put_user(templ,(unsigned long __user *) single); RE_ENTRANT_CHECK_ON; return 1; @@ -854,7 +854,7 @@ /* Put a long long into user memory */ -int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long *d) +int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d) { FPU_REG t; long long tll; @@ -906,7 +906,7 @@ } RE_ENTRANT_CHECK_OFF; - FPU_verify_area(VERIFY_WRITE,(void *)d,8); + FPU_verify_area(VERIFY_WRITE,d,8); copy_to_user(d, &tll, 8); RE_ENTRANT_CHECK_ON; @@ -915,7 +915,7 @@ /* Put a long into user memory */ -int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long *d) +int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d) { FPU_REG t; int precision_loss; @@ -964,7 +964,7 @@ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,d,4); - FPU_put_user(t.sigl, (unsigned long *) d); + FPU_put_user(t.sigl, (unsigned long __user *) d); RE_ENTRANT_CHECK_ON; return 1; @@ -972,7 +972,7 @@ /* Put a short into user memory */ -int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short *d) +int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d) { FPU_REG t; int precision_loss; @@ -1021,7 +1021,7 @@ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,d,2); - FPU_put_user((short)t.sigl,(short *) d); + FPU_put_user((short)t.sigl, d); RE_ENTRANT_CHECK_ON; return 1; @@ -1029,7 +1029,7 @@ /* Put a packed bcd array into user memory */ -int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d) +int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d) { FPU_REG t; unsigned long long ll; @@ -1071,10 +1071,10 @@ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,d,10); for ( i = 0; i < 7; i++) - FPU_put_user(0, (u_char *) d+i); /* These bytes "undefined" */ - FPU_put_user(0xc0, (u_char *) d+7); /* This byte "undefined" */ - FPU_put_user(0xff, (u_char *) d+8); - FPU_put_user(0xff, (u_char *) d+9); + FPU_put_user(0, d+i); /* These bytes "undefined" */ + FPU_put_user(0xc0, d+7); /* This byte "undefined" */ + FPU_put_user(0xff, d+8); + FPU_put_user(0xff, d+9); RE_ENTRANT_CHECK_ON; return 1; } @@ -1095,11 +1095,11 @@ b = FPU_div_small(&ll, 10); b |= (FPU_div_small(&ll, 10)) << 4; RE_ENTRANT_CHECK_OFF; - FPU_put_user(b,(u_char *) d+i); + FPU_put_user(b, d+i); RE_ENTRANT_CHECK_ON; } RE_ENTRANT_CHECK_OFF; - FPU_put_user(sign,(u_char *) d+9); + FPU_put_user(sign, d+9); RE_ENTRANT_CHECK_ON; return 1; @@ -1175,7 +1175,7 @@ /*===========================================================================*/ -u_char *fldenv(fpu_addr_modes addr_modes, u_char *s) +u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s) { unsigned short tag_word = 0; u_char tag; @@ -1187,13 +1187,13 @@ { RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_READ, s, 0x0e); - FPU_get_user(control_word, (unsigned short *) s); - FPU_get_user(partial_status, (unsigned short *) (s+2)); - FPU_get_user(tag_word, (unsigned short *) (s+4)); - FPU_get_user(instruction_address.offset, (unsigned short *) (s+6)); - FPU_get_user(instruction_address.selector, (unsigned short *) (s+8)); - FPU_get_user(operand_address.offset, (unsigned short *) (s+0x0a)); - FPU_get_user(operand_address.selector, (unsigned short *) (s+0x0c)); + FPU_get_user(control_word, (unsigned short __user *) s); + FPU_get_user(partial_status, (unsigned short __user *) (s+2)); + FPU_get_user(tag_word, (unsigned short __user *) (s+4)); + FPU_get_user(instruction_address.offset, (unsigned short __user *) (s+6)); + FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+8)); + FPU_get_user(operand_address.offset, (unsigned short __user *) (s+0x0a)); + FPU_get_user(operand_address.selector, (unsigned short __user *) (s+0x0c)); RE_ENTRANT_CHECK_ON; s += 0x0e; if ( addr_modes.default_mode == VM86 ) @@ -1207,14 +1207,14 @@ { RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_READ, s, 0x1c); - FPU_get_user(control_word, (unsigned short *) s); - FPU_get_user(partial_status, (unsigned short *) (s+4)); - FPU_get_user(tag_word, (unsigned short *) (s+8)); - FPU_get_user(instruction_address.offset, (unsigned long *) (s+0x0c)); - FPU_get_user(instruction_address.selector, (unsigned short *) (s+0x10)); - FPU_get_user(instruction_address.opcode, (unsigned short *) (s+0x12)); - FPU_get_user(operand_address.offset, (unsigned long *) (s+0x14)); - FPU_get_user(operand_address.selector, (unsigned long *) (s+0x18)); + FPU_get_user(control_word, (unsigned short __user *) s); + FPU_get_user(partial_status, (unsigned short __user *) (s+4)); + FPU_get_user(tag_word, (unsigned short __user *) (s+8)); + FPU_get_user(instruction_address.offset, (unsigned long __user *) (s+0x0c)); + FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+0x10)); + FPU_get_user(instruction_address.opcode, (unsigned short __user *) (s+0x12)); + FPU_get_user(operand_address.offset, (unsigned long __user *) (s+0x14)); + FPU_get_user(operand_address.selector, (unsigned long __user *) (s+0x18)); RE_ENTRANT_CHECK_ON; s += 0x1c; } @@ -1266,10 +1266,10 @@ } -void frstor(fpu_addr_modes addr_modes, u_char *data_address) +void frstor(fpu_addr_modes addr_modes, u_char __user *data_address) { int i, regnr; - u_char *s = fldenv(addr_modes, data_address); + u_char __user *s = fldenv(addr_modes, data_address); int offset = (top & 7) * 10, other = 80 - offset; /* Copy all registers in stack order. */ @@ -1291,7 +1291,7 @@ } -u_char *fstenv(fpu_addr_modes addr_modes, u_char *d) +u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d) { if ( (addr_modes.default_mode == VM86) || ((addr_modes.default_mode == PM16) @@ -1300,25 +1300,25 @@ RE_ENTRANT_CHECK_OFF; FPU_verify_area(VERIFY_WRITE,d,14); #ifdef PECULIAR_486 - FPU_put_user(control_word & ~0xe080, (unsigned long *) d); + FPU_put_user(control_word & ~0xe080, (unsigned long __user *) d); #else - FPU_put_user(control_word, (unsigned short *) d); + FPU_put_user(control_word, (unsigned short __user *) d); #endif /* PECULIAR_486 */ - FPU_put_user(status_word(), (unsigned short *) (d+2)); - FPU_put_user(fpu_tag_word, (unsigned short *) (d+4)); - FPU_put_user(instruction_address.offset, (unsigned short *) (d+6)); - FPU_put_user(operand_address.offset, (unsigned short *) (d+0x0a)); + FPU_put_user(status_word(), (unsigned short __user *) (d+2)); + FPU_put_user(fpu_tag_word, (unsigned short __user *) (d+4)); + FPU_put_user(instruction_address.offset, (unsigned short __user *) (d+6)); + FPU_put_user(operand_address.offset, (unsigned short __user *) (d+0x0a)); if ( addr_modes.default_mode == VM86 ) { FPU_put_user((instruction_address.offset & 0xf0000) >> 4, - (unsigned short *) (d+8)); + (unsigned short __user *) (d+8)); FPU_put_user((operand_address.offset & 0xf0000) >> 4, - (unsigned short *) (d+0x0c)); + (unsigned short __user *) (d+0x0c)); } else { - FPU_put_user(instruction_address.selector, (unsigned short *) (d+8)); - FPU_put_user(operand_address.selector, (unsigned short *) (d+0x0c)); + FPU_put_user(instruction_address.selector, (unsigned short __user *) (d+8)); + FPU_put_user(operand_address.selector, (unsigned short __user *) (d+0x0c)); } RE_ENTRANT_CHECK_ON; d += 0x0e; @@ -1348,9 +1348,9 @@ } -void fsave(fpu_addr_modes addr_modes, u_char *data_address) +void fsave(fpu_addr_modes addr_modes, u_char __user *data_address) { - u_char *d; + u_char __user *d; int offset = (top & 7) * 10, other = 80 - offset; d = fstenv(addr_modes, data_address); diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/mm/fault.c 2004-06-20 13:00:23 -07:00 @@ -24,7 +24,6 @@ #include #include -#include #include #include diff -Nru a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c --- a/arch/i386/mm/hugetlbpage.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/mm/hugetlbpage.c 2004-06-20 13:00:25 -07:00 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -245,8 +244,15 @@ ret = -ENOMEM; goto out; } - if (!pte_none(*pte)) - continue; + + if (!pte_none(*pte)) { + pmd_t *pmd = (pmd_t *) pte; + + page = pmd_page(*pmd); + pmd_clear(pmd); + dec_page_state(nr_page_table_pages); + page_cache_release(page); + } idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/mm/init.c 2004-06-20 13:00:25 -07:00 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c --- a/arch/i386/mm/ioremap.c 2004-06-20 13:00:23 -07:00 +++ b/arch/i386/mm/ioremap.c 2004-06-20 13:00:23 -07:00 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c --- a/arch/i386/pci/acpi.c 2004-06-20 13:00:25 -07:00 +++ b/arch/i386/pci/acpi.c 2004-06-20 13:00:25 -07:00 @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "pci.h" struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) @@ -15,18 +17,31 @@ static int __init pci_acpi_init(void) { + struct pci_dev *dev = NULL; + if (pcibios_scanned) return 0; - if (!acpi_noirq) { - if (!acpi_pci_irq_init()) { - printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - pcibios_scanned++; - pcibios_enable_irq = acpi_pci_irq_enable; - } else - printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); + if (acpi_noirq) + return 0; - } + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + acpi_irq_penalty_init(); + pcibios_scanned++; + pcibios_enable_irq = acpi_pci_irq_enable; + + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + acpi_pci_irq_enable(dev); + +#ifdef CONFIG_X86_IO_APIC + if (acpi_ioapic) + print_IO_APIC(); +#endif return 0; } diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig 2004-06-20 13:00:26 -07:00 +++ b/arch/ia64/Kconfig 2004-06-20 13:00:26 -07:00 @@ -149,20 +149,6 @@ default "6" if ITANIUM # align cache-sensitive data to 64 bytes -config MCKINLEY_ASTEP_SPECIFIC - bool "McKinley A-step specific code" - depends on MCKINLEY - help - Select this option to build a kernel for an IA-64 McKinley prototype - system with any A-stepping CPU. - -config MCKINLEY_A0_SPECIFIC - bool "McKinley A0/A1-step specific code" - depends on MCKINLEY_ASTEP_SPECIFIC - help - Select this option to build a kernel for an IA-64 McKinley prototype - system with an A0 or A1 stepping CPU. - config NUMA bool "NUMA support" depends on !IA64_HP_SIM diff -Nru a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig --- a/arch/ia64/configs/sn2_defconfig 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/configs/sn2_defconfig 2004-06-20 13:00:23 -07:00 @@ -14,18 +14,22 @@ # CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=20 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -60,7 +64,6 @@ CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_IA64_L1_CACHE_SHIFT=7 -# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set CONFIG_NUMA=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_DISCONTIGMEM=y @@ -70,12 +73,17 @@ CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=512 +# CONFIG_HOTPLUG_CPU is not set # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y + +# +# Firmware Drivers +# CONFIG_EFI_VARS=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -105,6 +113,7 @@ # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_USE_VECTOR is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y @@ -174,7 +183,6 @@ # CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=m CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_IDEFLOPPY=y @@ -218,6 +226,7 @@ # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y @@ -243,7 +252,6 @@ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -281,7 +289,9 @@ CONFIG_SCSI_SATA_SVW=m CONFIG_SCSI_ATA_PIIX=m CONFIG_SCSI_SATA_PROMISE=m +# CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set CONFIG_SCSI_SATA_VIA=m CONFIG_SCSI_SATA_VITESSE=y # CONFIG_SCSI_BUSLOGIC is not set @@ -298,6 +308,7 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y @@ -343,6 +354,7 @@ # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -389,8 +401,6 @@ CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_IPV6_TUNNEL=m -# CONFIG_DECNET is not set -CONFIG_BRIDGE=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -452,6 +462,7 @@ CONFIG_IP_NF_ARP_MANGLE=m # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_IP_NF_RAW is not set # # IPv6: Netfilter Configuration @@ -471,7 +482,9 @@ # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +CONFIG_BRIDGE=m CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -516,12 +529,14 @@ # Network testing # # CONFIG_NET_PKTGEN is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_EQUALIZER=m @@ -529,6 +544,11 @@ # CONFIG_ETHERTAP is not set # +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -582,7 +602,6 @@ CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m -CONFIG_SIS190=m CONFIG_SK98LIN=m CONFIG_TIGON3=y @@ -591,6 +610,22 @@ # CONFIG_IXGB=m # CONFIG_IXGB_NAPI is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PPP=m @@ -602,45 +637,11 @@ # CONFIG_PPP_BSDCOMP is not set # CONFIG_PPPOE is not set # CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set CONFIG_NET_FC=y # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y - -# # ISDN subsystem # # CONFIG_ISDN is not set @@ -703,6 +704,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set # CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set @@ -713,18 +715,11 @@ # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_HCDP=y -CONFIG_SERIAL_8250_ACPI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -740,7 +735,6 @@ # # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC is not set CONFIG_EFI_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -852,6 +846,7 @@ # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y @@ -897,7 +892,6 @@ # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -968,6 +962,7 @@ # Library routines # CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m @@ -1019,4 +1014,5 @@ # CONFIG_CRYPTO_ARC4 is not set CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_TEST is not set diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig --- a/arch/ia64/defconfig 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/defconfig 2004-06-20 13:00:23 -07:00 @@ -26,6 +26,7 @@ CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -66,7 +67,6 @@ CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_IA64_L1_CACHE_SHIFT=7 -# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set # CONFIG_NUMA is not set CONFIG_VIRTUAL_MEM_MAP=y # CONFIG_IA64_CYCLONE is not set @@ -74,6 +74,7 @@ CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=16 +# CONFIG_HOTPLUG_CPU is not set # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y @@ -178,7 +179,6 @@ # CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=m @@ -220,6 +220,7 @@ # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y @@ -245,7 +246,6 @@ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -282,6 +282,7 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set @@ -328,6 +329,7 @@ # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -573,7 +575,12 @@ # # IPMI # -# CONFIG_IPMI_HANDLER is not set +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_PANIC_EVENT=y +CONFIG_IPMI_PANIC_STRING=y +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m # # Watchdog Cards @@ -651,6 +658,7 @@ # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -662,6 +670,7 @@ # 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_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -688,6 +697,7 @@ # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set CONFIG_FB_RIVA=m # CONFIG_FB_MATROX is not set @@ -852,6 +862,7 @@ # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # CONFIG_USB_MTOUCH is not set +# CONFIG_USB_EGALAX is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -901,6 +912,7 @@ # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set # @@ -998,7 +1010,6 @@ # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -1083,7 +1094,7 @@ # CONFIG_IA64_GRANULE_64MB is not set CONFIG_DEBUG_KERNEL=y CONFIG_IA64_PRINT_HAZARDS=y -CONFIG_DISABLE_VHPT=y +# CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_IA64_EARLY_PRINTK_VGA is not set # CONFIG_DEBUG_SLAB is not set diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c --- a/arch/ia64/ia32/binfmt_elf32.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/ia32/binfmt_elf32.c 2004-06-20 13:00:25 -07:00 @@ -197,6 +197,10 @@ } up_write(¤t->mm->mmap_sem); + /* Can't do it in ia64_elf32_init(). Needs to be done before calls to + elf32_map() */ + current->thread.ppl = ia32_init_pp_list(); + return 0; } diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S --- a/arch/ia64/ia32/ia32_entry.S 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/ia32/ia32_entry.S 2004-06-20 13:00:24 -07:00 @@ -349,7 +349,7 @@ data8 sys_setfsuid /* 16-bit version */ data8 sys_setfsgid /* 16-bit version */ data8 sys_llseek /* 140 */ - data8 sys32_getdents + data8 compat_sys_getdents data8 compat_sys_select data8 sys_flock data8 sys32_msync @@ -371,7 +371,7 @@ data8 sys_sched_get_priority_min /* 160 */ data8 sys32_sched_rr_get_interval data8 compat_sys_nanosleep - data8 sys_mremap + data8 sys32_mremap data8 sys_setresuid /* 16-bit version */ data8 sys32_getresuid16 /* 16-bit version */ /* 165 */ data8 sys_ni_syscall /* vm86 */ @@ -428,7 +428,7 @@ data8 sys_pivot_root data8 sys_mincore data8 sys_madvise - data8 sys_getdents64 /* 220 */ + data8 compat_sys_getdents64 /* 220 */ data8 compat_sys_fcntl64 data8 sys_ni_syscall /* reserved for TUX */ data8 sys_ni_syscall /* reserved for Security */ diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c --- a/arch/ia64/ia32/ia32_support.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/ia32/ia32_support.c 2004-06-20 13:00:23 -07:00 @@ -218,6 +218,18 @@ ia32_exec_domain.signal_map = default_exec_domain.signal_map; ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; register_exec_domain(&ia32_exec_domain); + +#if PAGE_SHIFT > IA32_PAGE_SHIFT + { + extern kmem_cache_t *partial_page_cachep; + + partial_page_cachep = kmem_cache_create("partial_page_cache", + sizeof(struct partial_page), 0, 0, + NULL, NULL); + if (!partial_page_cachep) + panic("Cannot create partial page SLAB cache"); + } +#endif return 0; } diff -Nru a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h --- a/arch/ia64/ia32/ia32priv.h 2004-06-20 13:00:26 -07:00 +++ b/arch/ia64/ia32/ia32priv.h 2004-06-20 13:00:26 -07:00 @@ -1,5 +1,5 @@ -#ifndef _ASM_IA64_IA32_H -#define _ASM_IA64_IA32_H +#ifndef _ASM_IA64_IA32_PRIV_H +#define _ASM_IA64_IA32_PRIV_H #include @@ -9,6 +9,7 @@ #include #include +#include #include @@ -16,12 +17,39 @@ * 32 bit structures for IA32 support. */ -#define IA32_PAGE_SHIFT 12 /* 4KB pages */ #define IA32_PAGE_SIZE (1UL << IA32_PAGE_SHIFT) #define IA32_PAGE_MASK (~(IA32_PAGE_SIZE - 1)) #define IA32_PAGE_ALIGN(addr) (((addr) + IA32_PAGE_SIZE - 1) & IA32_PAGE_MASK) #define IA32_CLOCKS_PER_SEC 100 /* Cast in stone for IA32 Linux */ +/* + * partially mapped pages provide precise accounting of which 4k sub pages + * are mapped and which ones are not, thereby improving IA-32 compatibility. + */ +struct partial_page { + struct partial_page *next; /* linked list, sorted by address */ + struct rb_node pp_rb; + /* 64K is the largest "normal" page supported by ia64 ABI. So 4K*32 + * should suffice.*/ + unsigned int bitmap; + unsigned int base; +}; + +struct partial_page_list { + struct partial_page *pp_head; /* list head, points to the lowest + * addressed partial page */ + struct rb_root ppl_rb; + struct partial_page *pp_hint; /* pp_hint->next is the last + * accessed partial page */ + atomic_t pp_count; /* reference count */ +}; + +#if PAGE_SHIFT > IA32_PAGE_SHIFT +struct partial_page_list* ia32_init_pp_list (void); +#else +# define ia32_init_pp_list() 0 +#endif + /* sigcontext.h */ /* * As documented in the iBCS2 standard.. @@ -528,4 +556,4 @@ #endif /* !CONFIG_IA32_SUPPORT */ -#endif /* _ASM_IA64_IA32_H */ +#endif /* _ASM_IA64_IA32_PRIV_H */ diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/ia32/sys_ia32.c 2004-06-20 13:00:25 -07:00 @@ -8,6 +8,7 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2000-2003 Hewlett-Packard Co * David Mosberger-Tang + * Copyright (C) 2004 Gordon Jin * * These routines maintain argument size conversion between 32bit and 64bit * environment. @@ -48,6 +49,7 @@ #include #include #include +#include #include #include @@ -250,6 +252,508 @@ return ret; } +/* SLAB cache for partial_page structures */ +kmem_cache_t *partial_page_cachep; + +/* + * init partial_page_list. + * return 0 means kmalloc fail. + */ +struct partial_page_list* +ia32_init_pp_list(void) +{ + struct partial_page_list *p; + + if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL) + return p; + p->pp_head = 0; + p->ppl_rb = RB_ROOT; + p->pp_hint = 0; + atomic_set(&p->pp_count, 1); + return p; +} + +/* + * Search for the partial page with @start in partial page list @ppl. + * If finds the partial page, return the found partial page. + * Else, return 0 and provide @pprev, @rb_link, @rb_parent to + * be used by later __ia32_insert_pp(). + */ +static struct partial_page * +__ia32_find_pp(struct partial_page_list *ppl, unsigned int start, + struct partial_page **pprev, struct rb_node ***rb_link, + struct rb_node **rb_parent) +{ + struct partial_page *pp; + struct rb_node **__rb_link, *__rb_parent, *rb_prev; + + pp = ppl->pp_hint; + if (pp && pp->base == start) + return pp; + + __rb_link = &ppl->ppl_rb.rb_node; + rb_prev = __rb_parent = NULL; + + while (*__rb_link) { + __rb_parent = *__rb_link; + pp = rb_entry(__rb_parent, struct partial_page, pp_rb); + + if (pp->base == start) { + ppl->pp_hint = pp; + return pp; + } else if (pp->base < start) { + rb_prev = __rb_parent; + __rb_link = &__rb_parent->rb_right; + } else { + __rb_link = &__rb_parent->rb_left; + } + } + + *rb_link = __rb_link; + *rb_parent = __rb_parent; + *pprev = NULL; + if (rb_prev) + *pprev = rb_entry(rb_prev, struct partial_page, pp_rb); + return NULL; +} + +/* + * insert @pp into @ppl. + */ +static void +__ia32_insert_pp(struct partial_page_list *ppl, struct partial_page *pp, + struct partial_page *prev, struct rb_node **rb_link, + struct rb_node *rb_parent) +{ + /* link list */ + if (prev) { + pp->next = prev->next; + prev->next = pp; + } else { + ppl->pp_head = pp; + if (rb_parent) + pp->next = rb_entry(rb_parent, + struct partial_page, pp_rb); + else + pp->next = NULL; + } + + /* link rb */ + rb_link_node(&pp->pp_rb, rb_parent, rb_link); + rb_insert_color(&pp->pp_rb, &ppl->ppl_rb); + + ppl->pp_hint = pp; +} + +/* + * delete @pp from partial page list @ppl. + */ +static void +__ia32_delete_pp(struct partial_page_list *ppl, struct partial_page *pp, + struct partial_page *prev) +{ + if (prev) { + prev->next = pp->next; + if (ppl->pp_hint == pp) + ppl->pp_hint = prev; + } else { + ppl->pp_head = pp->next; + if (ppl->pp_hint == pp) + ppl->pp_hint = pp->next; + } + rb_erase(&pp->pp_rb, &ppl->ppl_rb); + kmem_cache_free(partial_page_cachep, pp); +} + +static struct partial_page * +__pp_prev(struct partial_page *pp) +{ + struct rb_node *prev = rb_prev(&pp->pp_rb); + if (prev) + return rb_entry(prev, struct partial_page, pp_rb); + else + return NULL; +} + +/* + * Delete partial pages with address between @start and @end. + * @start and @end are page aligned. + */ +static void +__ia32_delete_pp_range(unsigned int start, unsigned int end) +{ + struct partial_page *pp, *prev; + struct rb_node **rb_link, *rb_parent; + + if (start >= end) + return; + + pp = __ia32_find_pp(current->thread.ppl, start, &prev, + &rb_link, &rb_parent); + if (pp) + prev = __pp_prev(pp); + else { + if (prev) + pp = prev->next; + else + pp = current->thread.ppl->pp_head; + } + + while (pp && pp->base < end) { + struct partial_page *tmp = pp->next; + __ia32_delete_pp(current->thread.ppl, pp, prev); + pp = tmp; + } +} + +/* + * Set the range between @start and @end in bitmap. + * @start and @end should be IA32 page aligned and in the same IA64 page. + */ +static int +__ia32_set_pp(unsigned int start, unsigned int end, int flags) +{ + struct partial_page *pp, *prev; + struct rb_node ** rb_link, *rb_parent; + unsigned int pstart, start_bit, end_bit, i; + + pstart = PAGE_START(start); + start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; + end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; + if (end_bit == 0) + end_bit = PAGE_SIZE / IA32_PAGE_SIZE; + pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, + &rb_link, &rb_parent); + if (pp) { + for (i = start_bit; i < end_bit; i++) + set_bit(i, &pp->bitmap); + /* + * Check: if this partial page has been set to a full page, + * then delete it. + */ + if (find_first_zero_bit(&pp->bitmap, sizeof(pp->bitmap)*8) >= + PAGE_SIZE/IA32_PAGE_SIZE) { + __ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp)); + } + return 0; + } + + /* + * MAP_FIXED may lead to overlapping mmap. + * In this case, the requested mmap area may already mmaped as a full + * page. So check vma before adding a new partial page. + */ + if (flags & MAP_FIXED) { + struct vm_area_struct *vma = find_vma(current->mm, pstart); + if (vma && vma->vm_start <= pstart) + return 0; + } + + /* new a partial_page */ + pp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL); + if (!pp) + return -ENOMEM; + pp->base = pstart; + pp->bitmap = 0; + for (i=start_bit; ibitmap)); + pp->next = NULL; + __ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent); + return 0; +} + +/* + * @start and @end should be IA32 page aligned, but don't need to be in the + * same IA64 page. Split @start and @end to make sure they're in the same IA64 + * page, then call __ia32_set_pp(). + */ +static void +ia32_set_pp(unsigned int start, unsigned int end, int flags) +{ + down_write(¤t->mm->mmap_sem); + if (flags & MAP_FIXED) { + /* + * MAP_FIXED may lead to overlapping mmap. When this happens, + * a series of complete IA64 pages results in deletion of + * old partial pages in that range. + */ + __ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end)); + } + + if (end < PAGE_ALIGN(start)) { + __ia32_set_pp(start, end, flags); + } else { + if (offset_in_page(start)) + __ia32_set_pp(start, PAGE_ALIGN(start), flags); + if (offset_in_page(end)) + __ia32_set_pp(PAGE_START(end), end, flags); + } + up_write(¤t->mm->mmap_sem); +} + +/* + * Unset the range between @start and @end in bitmap. + * @start and @end should be IA32 page aligned and in the same IA64 page. + * After doing that, if the bitmap is 0, then free the page and return 1, + * else return 0; + * If not find the partial page in the list, then + * If the vma exists, then the full page is set to a partial page; + * Else return -ENOMEM. + */ +static int +__ia32_unset_pp(unsigned int start, unsigned int end) +{ + struct partial_page *pp, *prev; + struct rb_node ** rb_link, *rb_parent; + unsigned int pstart, start_bit, end_bit, i; + struct vm_area_struct *vma; + + pstart = PAGE_START(start); + start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; + end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; + if (end_bit == 0) + end_bit = PAGE_SIZE / IA32_PAGE_SIZE; + + pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, + &rb_link, &rb_parent); + if (pp) { + for (i = start_bit; i < end_bit; i++) + clear_bit(i, &pp->bitmap); + if (pp->bitmap == 0) { + __ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp)); + return 1; + } + return 0; + } + + vma = find_vma(current->mm, pstart); + if (!vma || vma->vm_start > pstart) { + return -ENOMEM; + } + + /* new a partial_page */ + pp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL); + if (!pp) + return -ENOMEM; + pp->base = pstart; + pp->bitmap = 0; + for (i = 0; i < start_bit; i++) + set_bit(i, &(pp->bitmap)); + for (i = end_bit; i < PAGE_SIZE / IA32_PAGE_SIZE; i++) + set_bit(i, &(pp->bitmap)); + pp->next = NULL; + __ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent); + return 0; +} + +/* + * Delete pp between PAGE_ALIGN(start) and PAGE_START(end) by calling + * __ia32_delete_pp_range(). Unset possible partial pages by calling + * __ia32_unset_pp(). + * The returned value see __ia32_unset_pp(). + */ +static int +ia32_unset_pp(unsigned int *startp, unsigned int *endp) +{ + unsigned int start = *startp, end = *endp; + int ret = 0; + + down_write(¤t->mm->mmap_sem); + + __ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end)); + + if (end < PAGE_ALIGN(start)) { + ret = __ia32_unset_pp(start, end); + if (ret == 1) { + *startp = PAGE_START(start); + *endp = PAGE_ALIGN(end); + } + if (ret == 0) { + /* to shortcut sys_munmap() in sys32_munmap() */ + *startp = PAGE_START(start); + *endp = PAGE_START(end); + } + } else { + if (offset_in_page(start)) { + ret = __ia32_unset_pp(start, PAGE_ALIGN(start)); + if (ret == 1) + *startp = PAGE_START(start); + if (ret == 0) + *startp = PAGE_ALIGN(start); + if (ret < 0) + goto out; + } + if (offset_in_page(end)) { + ret = __ia32_unset_pp(PAGE_START(end), end); + if (ret == 1) + *endp = PAGE_ALIGN(end); + if (ret == 0) + *endp = PAGE_START(end); + } + } + + out: + up_write(¤t->mm->mmap_sem); + return ret; +} + +/* + * Compare the range between @start and @end with bitmap in partial page. + * @start and @end should be IA32 page aligned and in the same IA64 page. + */ +static int +__ia32_compare_pp(unsigned int start, unsigned int end) +{ + struct partial_page *pp, *prev; + struct rb_node ** rb_link, *rb_parent; + unsigned int pstart, start_bit, end_bit, size; + unsigned int first_bit, next_zero_bit; /* the first range in bitmap */ + + pstart = PAGE_START(start); + + pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, + &rb_link, &rb_parent); + if (!pp) + return 1; + + start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; + end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; + size = sizeof(pp->bitmap) * 8; + first_bit = find_first_bit(&pp->bitmap, size); + next_zero_bit = find_next_zero_bit(&pp->bitmap, size, first_bit); + if ((start_bit < first_bit) || (end_bit > next_zero_bit)) { + /* exceeds the first range in bitmap */ + return -ENOMEM; + } else if ((start_bit == first_bit) && (end_bit == next_zero_bit)) { + first_bit = find_next_bit(&pp->bitmap, size, next_zero_bit); + if ((next_zero_bit < first_bit) && (first_bit < size)) + return 1; /* has next range */ + else + return 0; /* no next range */ + } else + return 1; +} + +/* + * @start and @end should be IA32 page aligned, but don't need to be in the + * same IA64 page. Split @start and @end to make sure they're in the same IA64 + * page, then call __ia32_compare_pp(). + * + * Take this as example: the range is the 1st and 2nd 4K page. + * Return 0 if they fit bitmap exactly, i.e. bitmap = 00000011; + * Return 1 if the range doesn't cover whole bitmap, e.g. bitmap = 00001111; + * Return -ENOMEM if the range exceeds the bitmap, e.g. bitmap = 00000001 or + * bitmap = 00000101. + */ +static int +ia32_compare_pp(unsigned int *startp, unsigned int *endp) +{ + unsigned int start = *startp, end = *endp; + int retval = 0; + + down_write(¤t->mm->mmap_sem); + + if (end < PAGE_ALIGN(start)) { + retval = __ia32_compare_pp(start, end); + if (retval == 0) { + *startp = PAGE_START(start); + *endp = PAGE_ALIGN(end); + } + } else { + if (offset_in_page(start)) { + retval = __ia32_compare_pp(start, + PAGE_ALIGN(start)); + if (retval == 0) + *startp = PAGE_START(start); + if (retval < 0) + goto out; + } + if (offset_in_page(end)) { + retval = __ia32_compare_pp(PAGE_START(end), end); + if (retval == 0) + *endp = PAGE_ALIGN(end); + } + } + + out: + up_write(¤t->mm->mmap_sem); + return retval; +} + +static void +__ia32_drop_pp_list(struct partial_page_list *ppl) +{ + struct partial_page *pp = ppl->pp_head; + + while (pp) { + struct partial_page *next = pp->next; + kmem_cache_free(partial_page_cachep, pp); + pp = next; + } + + kfree(ppl); +} + +void +ia32_drop_partial_page_list(struct task_struct *task) +{ + struct partial_page_list* ppl = task->thread.ppl; + + if (ppl && atomic_dec_and_test(&ppl->pp_count)) + __ia32_drop_pp_list(ppl); +} + +/* + * Copy current->thread.ppl to ppl (already initialized). + */ +static int +__ia32_copy_pp_list(struct partial_page_list *ppl) +{ + struct partial_page *pp, *tmp, *prev; + struct rb_node **rb_link, *rb_parent; + + ppl->pp_head = NULL; + ppl->pp_hint = NULL; + ppl->ppl_rb = RB_ROOT; + rb_link = &ppl->ppl_rb.rb_node; + rb_parent = NULL; + prev = NULL; + + for (pp = current->thread.ppl->pp_head; pp; pp = pp->next) { + tmp = kmem_cache_alloc(partial_page_cachep, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + *tmp = *pp; + __ia32_insert_pp(ppl, tmp, prev, rb_link, rb_parent); + prev = tmp; + rb_link = &tmp->pp_rb.rb_right; + rb_parent = &tmp->pp_rb; + } + return 0; +} + +int +ia32_copy_partial_page_list(struct task_struct *p, unsigned long clone_flags) +{ + int retval = 0; + + if (clone_flags & CLONE_VM) { + atomic_inc(¤t->thread.ppl->pp_count); + p->thread.ppl = current->thread.ppl; + } else { + p->thread.ppl = ia32_init_pp_list(); + if (!p->thread.ppl) + return -ENOMEM; + down_write(¤t->mm->mmap_sem); + { + retval = __ia32_copy_pp_list(p->thread.ppl); + } + up_write(¤t->mm->mmap_sem); + } + + return retval; +} + static unsigned long emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags, loff_t off) @@ -263,6 +767,7 @@ pend = PAGE_ALIGN(end); if (flags & MAP_FIXED) { + ia32_set_pp((unsigned int)start, (unsigned int)end, flags); if (start > pstart) { if (flags & MAP_SHARED) printk(KERN_INFO @@ -274,7 +779,7 @@ return ret; pstart += PAGE_SIZE; if (pstart >= pend) - return start; /* done */ + goto out; /* done */ } if (end < pend) { if (flags & MAP_SHARED) @@ -287,7 +792,7 @@ return ret; pend -= PAGE_SIZE; if (pstart >= pend) - return start; /* done */ + goto out; /* done */ } } else { /* @@ -341,6 +846,10 @@ if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0) return -EINVAL; } + + if (!(flags & MAP_FIXED)) + ia32_set_pp((unsigned int)start, (unsigned int)end, flags); +out: return start; } @@ -478,11 +987,16 @@ #if PAGE_SHIFT <= IA32_PAGE_SHIFT ret = sys_munmap(start, end - start); #else + if (OFFSET4K(start)) + return -EINVAL; + + end = IA32_PAGE_ALIGN(end); if (start >= end) return -EINVAL; - start = PAGE_ALIGN(start); - end = PAGE_START(end); + ret = ia32_unset_pp(&start, &end); + if (ret < 0) + return ret; if (start >= end) return 0; @@ -521,7 +1035,7 @@ asmlinkage long sys32_mprotect (unsigned int start, unsigned int len, int prot) { - unsigned long end = start + len; + unsigned int end = start + len; #if PAGE_SHIFT > IA32_PAGE_SHIFT long retval = 0; #endif @@ -538,6 +1052,11 @@ if (end < start) return -EINVAL; + retval = ia32_compare_pp(&start, &end); + + if (retval < 0) + return retval; + down(&ia32_mmap_sem); { if (offset_in_page(start)) { @@ -565,6 +1084,59 @@ up(&ia32_mmap_sem); return retval; #endif +} + +asmlinkage long +sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, + unsigned int flags, unsigned int new_addr) +{ + long ret; + +#if PAGE_SHIFT <= IA32_PAGE_SHIFT + ret = sys_mremap(addr, old_len, new_len, flags, new_addr); +#else + unsigned int old_end, new_end; + + if (OFFSET4K(addr)) + return -EINVAL; + + old_len = IA32_PAGE_ALIGN(old_len); + new_len = IA32_PAGE_ALIGN(new_len); + old_end = addr + old_len; + new_end = addr + new_len; + + if (!new_len) + return -EINVAL; + + if ((flags & MREMAP_FIXED) && (OFFSET4K(new_addr))) + return -EINVAL; + + if (old_len >= new_len) { + ret = sys32_munmap(addr + new_len, old_len - new_len); + if (ret && old_len != new_len) + return ret; + ret = addr; + if (!(flags & MREMAP_FIXED) || (new_addr == addr)) + return ret; + old_len = new_len; + } + + addr = PAGE_START(addr); + old_len = PAGE_ALIGN(old_end) - addr; + new_len = PAGE_ALIGN(new_end) - addr; + + down(&ia32_mmap_sem); + { + ret = sys_mremap(addr, old_len, new_len, flags, new_addr); + } + up(&ia32_mmap_sem); + + if ((ret >= 0) && (old_len < new_len)) { + /* mremap expanded successfully */ + ia32_set_pp(old_end, new_end, flags); + } +#endif + return ret; } asmlinkage long diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/kernel/acpi.c 2004-06-20 13:00:24 -07:00 @@ -521,9 +521,14 @@ #endif /* CONFIG_ACPI_NUMA */ unsigned int -acpi_register_gsi (u32 gsi, int polarity, int trigger) +acpi_register_gsi (u32 gsi, int edge_level, int active_high_low) { - return acpi_register_irq(gsi, polarity, trigger); + if (has_8259 && gsi < 16) + return isa_irq_to_vector(gsi); + + return iosapic_register_intr(gsi, + (active_high_low == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (edge_level == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); } EXPORT_SYMBOL(acpi_register_gsi); @@ -548,7 +553,7 @@ if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES) acpi_legacy_devices = 1; - acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); + acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); return 0; } @@ -661,17 +666,5 @@ } return 0; } - -int -acpi_register_irq (u32 gsi, u32 polarity, u32 trigger) -{ - if (has_8259 && gsi < 16) - return isa_irq_to_vector(gsi); - - return iosapic_register_intr(gsi, - (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - (trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); -} -EXPORT_SYMBOL(acpi_register_irq); #endif /* CONFIG_ACPI_BOOT */ diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/kernel/entry.S 2004-06-20 13:00:23 -07:00 @@ -179,17 +179,19 @@ .body adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13 + movl r25=init_task mov r27=IA64_KR(CURRENT_STACK) + adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 dep r20=0,in0,61,3 // physical address of "current" ;; st8 [r22]=sp // save kernel stack pointer of old task shr.u r26=r20,IA64_GRANULE_SHIFT - adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 + cmp.eq p7,p6=r25,in0 ;; /* * If we've already mapped this task's page, we can skip doing it again. */ - cmp.eq p7,p6=r26,r27 +(p6) cmp.eq p7,p6=r26,r27 (p6) br.cond.dpnt .map ;; .done: diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/kernel/head.S 2004-06-20 13:00:25 -07:00 @@ -154,6 +154,10 @@ #endif ;; tpa r3=r2 // r3 == phys addr of task struct + ;; + shr.u r16=r3,IA64_GRANULE_SHIFT +(isBP) br.cond.dpnt .load_current // BP stack is on region 5 --- no need to map it + // load mapping for stack (virtaddr in r2, physaddr in r3) rsm psr.ic movl r17=PAGE_KERNEL @@ -165,7 +169,6 @@ dep r2=-1,r3,61,3 // IMVA of task ;; mov r17=rr[r2] - shr.u r16=r3,IA64_GRANULE_SHIFT ;; dep r17=0,r17,8,24 ;; @@ -180,6 +183,7 @@ srlz.d ;; +.load_current: // load the "current" pointer (r13) and ar.k6 with the current task mov IA64_KR(CURRENT)=r2 // virtual address mov IA64_KR(CURRENT_STACK)=r16 diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c 2004-06-20 13:00:26 -07:00 +++ b/arch/ia64/kernel/init_task.c 2004-06-20 13:00:26 -07:00 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/kernel/iosapic.c 2004-06-20 13:00:24 -07:00 @@ -100,7 +100,6 @@ #endif static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; -extern cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ @@ -335,21 +334,6 @@ #endif } -static inline void move_irq(int irq) -{ - /* note - we hold desc->lock */ - cpumask_t tmp; - irq_desc_t *desc = irq_descp(irq); - - if (!cpus_empty(pending_irq_cpumask[irq])) { - cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); - if (unlikely(!cpus_empty(tmp))) { - desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); - } - cpus_clear(pending_irq_cpumask[irq]); - } -} - /* * Handlers for level-triggered interrupts. */ @@ -483,7 +467,7 @@ index = find_iosapic(gsi); if (index < 0) { - printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi); + printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi); return; } @@ -512,6 +496,42 @@ } } +static unsigned int +get_target_cpu (void) +{ +#ifdef CONFIG_SMP + static int cpu = -1; + + /* + * If the platform supports redirection via XTP, let it + * distribute interrupts. + */ + if (smp_int_redirect & SMP_IRQ_REDIRECTION) + return hard_smp_processor_id(); + + /* + * Some interrupts (ACPI SCI, for instance) are registered + * before the BSP is marked as online. + */ + if (!cpu_online(smp_processor_id())) + return hard_smp_processor_id(); + + /* + * Otherwise, round-robin interrupt vectors across all the + * processors. (It'd be nice if we could be smarter in the + * case of NUMA.) + */ + do { + if (++cpu >= NR_CPUS) + cpu = 0; + } while (!cpu_online(cpu)); + + return cpu_physical_id(cpu); +#else + return hard_smp_processor_id(); +#endif +} + /* * ACPI can describe IOSAPIC interrupts via static tables and namespace * methods. This provides an interface to register those interrupts and @@ -522,21 +542,35 @@ unsigned long polarity, unsigned long trigger) { int vector; - unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; + unsigned int dest; + unsigned long flags; - vector = gsi_to_vector(gsi); - if (vector < 0) - vector = assign_irq_vector(AUTO_ASSIGN); + /* + * If this GSI has already been registered (i.e., it's a + * shared interrupt, or we lost a race to register it), + * don't touch the RTE. + */ + spin_lock_irqsave(&iosapic_lock, flags); + { + vector = gsi_to_vector(gsi); + if (vector > 0) { + spin_unlock_irqrestore(&iosapic_lock, flags); + return vector; + } - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, trigger); + vector = assign_irq_vector(AUTO_ASSIGN); + dest = get_target_cpu(); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, + polarity, trigger); + } + spin_unlock_irqrestore(&iosapic_lock, flags); - printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), - (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); + printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", + gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), + (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + cpu_logical_id(dest), dest, vector); - /* program the IOSAPIC routing table */ - set_rte(vector, dest, 0); + set_rte(vector, dest, 1); return vector; } @@ -549,8 +583,9 @@ int iosapic_vector, u16 eid, u16 id, unsigned long polarity, unsigned long trigger) { + static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"}; unsigned char delivery; - int vector; + int vector, mask = 0; unsigned int dest = ((id << 8) | eid) & 0xffff; switch (int_type) { @@ -570,21 +605,22 @@ case ACPI_INTERRUPT_CPEI: vector = IA64_CPE_VECTOR; delivery = IOSAPIC_LOWEST_PRIORITY; + mask = 1; break; default: - printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type\n"); + printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type); return -1; } - register_intr(gsi, vector, delivery, polarity, - trigger); + register_intr(gsi, vector, delivery, polarity, trigger); - printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), - (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); + printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", + int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown", + int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), + (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + cpu_logical_id(dest), dest, vector); - /* program the IOSAPIC routing table */ - set_rte(vector, dest, 0); + set_rte(vector, dest, mask); return vector; } @@ -599,18 +635,18 @@ unsigned long trigger) { int vector; - unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; + unsigned int dest = hard_smp_processor_id(); vector = isa_irq_to_vector(isa_irq); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); - DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", - isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low", - trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); + DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", + isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level", + polarity == IOSAPIC_POL_HIGH ? "high" : "low", + cpu_logical_id(dest), dest, vector); - /* program the IOSAPIC routing table */ - set_rte(vector, dest, 0); + set_rte(vector, dest, 1); } void __init @@ -665,104 +701,3 @@ iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } - -void -iosapic_enable_intr (unsigned int vector) -{ - unsigned int dest; - irq_desc_t *desc; - - /* - * In the case of a shared interrupt, do not re-route the vector, and - * especially do not mask a running interrupt (startup will not get - * called for a shared interrupt). - */ - desc = irq_descp(vector); - if (desc->action) - return; - -#ifdef CONFIG_SMP - /* - * For platforms that do not support interrupt redirect via the XTP interface, we - * can round-robin the PCI device interrupts to the processors - */ - if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) { - static int cpu_index = -1; - - do - if (++cpu_index >= NR_CPUS) - cpu_index = 0; - while (!cpu_online(cpu_index)); - - dest = cpu_physical_id(cpu_index) & 0xffff; - } else { - /* - * Direct the interrupt vector to the current cpu, platform redirection - * will distribute them. - */ - dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; - } -#else - /* direct the interrupt vector to the running cpu id */ - dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; -#endif - set_rte(vector, dest, 1); - - printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n", - vector, dest); -} - -#ifdef CONFIG_ACPI_PCI - -void __init -iosapic_parse_prt (void) -{ - struct acpi_prt_entry *entry; - struct list_head *node; - unsigned int gsi; - int vector; - char pci_id[16]; - struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; - irq_desc_t *idesc; - - list_for_each(node, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); - - /* We're only interested in static (non-link) entries. */ - if (entry->link.handle) - continue; - - gsi = entry->link.index; - - vector = gsi_to_vector(gsi); - if (vector < 0) { - if (find_iosapic(gsi) < 0) - continue; - - /* allocate a vector for this interrupt line */ - if (pcat_compat && (gsi < 16)) - vector = isa_irq_to_vector(gsi); - else - /* new GSI; allocate a vector for it */ - vector = assign_irq_vector(AUTO_ASSIGN); - - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, - IOSAPIC_LEVEL); - } - entry->irq = vector; - snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", - entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); - - /* - * If vector was previously initialized to a different - * handler, re-initialize. - */ - idesc = irq_descp(vector); - if (idesc->handler != irq_type) - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, - IOSAPIC_LEVEL); - - } -} - -#endif /* CONFIG_ACPI */ diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/kernel/irq.c 2004-06-20 13:00:25 -07:00 @@ -1018,6 +1018,22 @@ return full_count; } +void move_irq(int irq) +{ + /* note - we hold desc->lock */ + cpumask_t tmp; + irq_desc_t *desc = irq_descp(irq); + + if (!cpus_empty(pending_irq_cpumask[irq])) { + cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); + if (unlikely(!cpus_empty(tmp))) { + desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); + } + cpus_clear(pending_irq_cpumask[irq]); + } +} + + #endif /* CONFIG_SMP */ #ifdef CONFIG_HOTPLUG_CPU diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/kernel/mca.c 2004-06-20 13:00:24 -07:00 @@ -108,6 +108,7 @@ #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */ #define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */ #define CMC_POLL_INTERVAL (1*60*HZ) /* 1 minute */ +#define CPE_HISTORY_LENGTH 5 #define CMC_HISTORY_LENGTH 5 static struct timer_list cpe_poll_timer; @@ -127,6 +128,8 @@ */ static int cpe_poll_enabled = 1; +static int cpe_vector = -1; + extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); /* @@ -267,20 +270,65 @@ */ #ifndef PLATFORM_MCA_HANDLERS +#ifdef CONFIG_ACPI + static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { - IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n", - __FUNCTION__, smp_processor_id(), cpe_irq); + static unsigned long cpe_history[CPE_HISTORY_LENGTH]; + static int index; + static spinlock_t cpe_history_lock = SPIN_LOCK_UNLOCKED; + + IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n", + __FUNCTION__, cpe_irq, smp_processor_id()); /* SAL spec states this should run w/ interrupts enabled */ local_irq_enable(); - /* Get the CMC error record and log it */ + /* Get the CPE error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE); + + spin_lock(&cpe_history_lock); + if (!cpe_poll_enabled && cpe_vector >= 0) { + + int i, count = 1; /* we know 1 happened now */ + unsigned long now = jiffies; + + for (i = 0; i < CPE_HISTORY_LENGTH; i++) { + if (now - cpe_history[i] <= HZ) + count++; + } + + IA64_MCA_DEBUG(KERN_INFO "CPE threshold %d/%d\n", count, CPE_HISTORY_LENGTH); + if (count >= CPE_HISTORY_LENGTH) { + + cpe_poll_enabled = 1; + spin_unlock(&cpe_history_lock); + disable_irq_nosync(local_vector_to_irq(IA64_CPE_VECTOR)); + + /* + * Corrected errors will still be corrected, but + * make sure there's a log somewhere that indicates + * something is generating more than we can handle. + */ + printk(KERN_WARNING "WARNING: Switching to polling CPE handler; error records may be lost\n"); + + mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL); + + /* lock already released, get out now */ + return IRQ_HANDLED; + } else { + cpe_history[index++] = now; + if (index == CPE_HISTORY_LENGTH) + index = 0; + } + } + spin_unlock(&cpe_history_lock); return IRQ_HANDLED; } +#endif /* CONFIG_ACPI */ + static void show_min_state (pal_min_state_area_t *minstate) { @@ -901,7 +949,7 @@ * handled */ static irqreturn_t -ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) +ia64_mca_cmc_int_caller(int cmc_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; unsigned int cpuid; @@ -912,7 +960,7 @@ if (start_count == -1) start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC); - ia64_mca_cmc_int_handler(cpe_irq, arg, ptregs); + ia64_mca_cmc_int_handler(cmc_irq, arg, ptregs); for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++); @@ -967,11 +1015,13 @@ * Outputs * handled */ +#ifdef CONFIG_ACPI + static irqreturn_t ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; - static int poll_time = MAX_CPE_POLL_INTERVAL; + static int poll_time = MIN_CPE_POLL_INTERVAL; unsigned int cpuid; cpuid = smp_processor_id(); @@ -989,20 +1039,30 @@ } else { /* * If a log was recorded, increase our polling frequency, - * otherwise, backoff. + * otherwise, backoff or return to interrupt mode. */ if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) { poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time / 2); - } else { + } else if (cpe_vector < 0) { poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2); + } else { + poll_time = MIN_CPE_POLL_INTERVAL; + + printk(KERN_WARNING "Returning to interrupt driven CPE handler\n"); + enable_irq(local_vector_to_irq(IA64_CPE_VECTOR)); + cpe_poll_enabled = 0; } + + if (cpe_poll_enabled) + mod_timer(&cpe_poll_timer, jiffies + poll_time); start_count = -1; - mod_timer(&cpe_poll_timer, jiffies + poll_time); } return IRQ_HANDLED; } +#endif /* CONFIG_ACPI */ + /* * ia64_mca_cpe_poll * @@ -1240,21 +1300,23 @@ register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); #ifdef CONFIG_ACPI - /* Setup the CPE interrupt vector */ + /* Setup the CPEI/P vector and handler */ { irq_desc_t *desc; unsigned int irq; - int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI); - if (cpev >= 0) { + cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI); + + if (cpe_vector >= 0) { for (irq = 0; irq < NR_IRQS; ++irq) - if (irq_to_vector(irq) == cpev) { + if (irq_to_vector(irq) == cpe_vector) { desc = irq_descp(irq); desc->status |= IRQ_PER_CPU; setup_irq(irq, &mca_cpe_irqaction); } - ia64_mca_register_cpev(cpev); + ia64_mca_register_cpev(cpe_vector); } + register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); } #endif @@ -1294,9 +1356,10 @@ #ifdef CONFIG_ACPI /* If platform doesn't support CPEI, get the timer going. */ - if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { - register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); + if (cpe_vector < 0 && cpe_poll_enabled) { ia64_mca_cpe_poll(0UL); + } else { + cpe_poll_enabled = 0; } #endif diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c --- a/arch/ia64/kernel/palinfo.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/kernel/palinfo.c 2004-06-20 13:00:23 -07:00 @@ -515,10 +515,10 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - "Enable Cache Line Repl. Exclusive", "Enable Cache Line Repl. Shared", + "Enable Cache Line Repl. Exclusive", "Disable Transaction Queuing", - "Disable Reponse Error Checking", + "Disable Response Error Checking", "Disable Bus Error Checking", "Disable Bus Requester Internal Error Signalling", "Disable Bus Requester Error Signalling", diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/kernel/perfmon.c 2004-06-20 13:00:25 -07:00 @@ -311,6 +311,7 @@ unsigned int ctx_cpu; /* cpu to which perfmon is applied (system wide) */ int ctx_fd; /* file descriptor used my this context */ + pfm_ovfl_arg_t ctx_ovfl_arg; /* argument to custom buffer format handler */ pfm_buffer_fmt_t *ctx_buf_fmt; /* buffer format callbacks */ void *ctx_smpl_hdr; /* points to sampling buffer header kernel vaddr */ @@ -4584,31 +4585,6 @@ return 0; } -static void -pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs) -{ - struct task_struct *task = ctx->ctx_task; - - ia64_psr(regs)->up = 0; - ia64_psr(regs)->sp = 1; - - if (GET_PMU_OWNER() == task) { - DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid)); - SET_PMU_OWNER(NULL, NULL); - } - - /* - * disconnect the task from the context and vice-versa - */ - PFM_SET_WORK_PENDING(task, 0); - - task->thread.pfm_context = NULL; - task->thread.flags &= ~IA64_THREAD_PM_VALID; - - DPRINT(("force cleanupf for [%d]\n", task->pid)); -} - - /* * called only from exit_thread(): task == current @@ -5185,7 +5161,7 @@ static void pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) { - pfm_ovfl_arg_t ovfl_arg; + pfm_ovfl_arg_t *ovfl_arg; unsigned long mask; unsigned long old_val, ovfl_val, new_val; unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL, reset_pmds; @@ -5272,7 +5248,8 @@ int j, k, ret = 0; int this_cpu = smp_processor_id(); - pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; + pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; + ovfl_arg = &ctx->ctx_ovfl_arg; prefetch(ctx->ctx_smpl_hdr); @@ -5282,15 +5259,15 @@ if ((pmd_mask & 0x1) == 0) continue; - ovfl_arg.ovfl_pmd = (unsigned char )i; - ovfl_arg.ovfl_notify = ovfl_notify & mask ? 1 : 0; - ovfl_arg.active_set = 0; - ovfl_arg.ovfl_ctrl.val = 0; /* module must fill in all fields */ - ovfl_arg.smpl_pmds[0] = smpl_pmds = ctx->ctx_pmds[i].smpl_pmds[0]; - - ovfl_arg.pmd_value = ctx->ctx_pmds[i].val; - ovfl_arg.pmd_last_reset = ctx->ctx_pmds[i].lval; - ovfl_arg.pmd_eventid = ctx->ctx_pmds[i].eventid; + ovfl_arg->ovfl_pmd = (unsigned char )i; + ovfl_arg->ovfl_notify = ovfl_notify & mask ? 1 : 0; + ovfl_arg->active_set = 0; + ovfl_arg->ovfl_ctrl.val = 0; /* module must fill in all fields */ + ovfl_arg->smpl_pmds[0] = smpl_pmds = ctx->ctx_pmds[i].smpl_pmds[0]; + + ovfl_arg->pmd_value = ctx->ctx_pmds[i].val; + ovfl_arg->pmd_last_reset = ctx->ctx_pmds[i].lval; + ovfl_arg->pmd_eventid = ctx->ctx_pmds[i].eventid; /* * copy values of pmds of interest. Sampling format may copy them @@ -5299,8 +5276,8 @@ if (smpl_pmds) { for(j=0, k=0; smpl_pmds; j++, smpl_pmds >>=1) { if ((smpl_pmds & 0x1) == 0) continue; - ovfl_arg.smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ? pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j); - DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg.smpl_pmds_values[k-1])); + ovfl_arg->smpl_pmds_values[k++] = PMD_IS_COUNTING(j) ? pfm_read_soft_counter(ctx, j) : ia64_get_pmd(j); + DPRINT_ovfl(("smpl_pmd[%d]=pmd%u=0x%lx\n", k-1, j, ovfl_arg->smpl_pmds_values[k-1])); } } @@ -5311,7 +5288,7 @@ /* * call custom buffer format record (handler) routine */ - ret = (*ctx->ctx_buf_fmt->fmt_handler)(task, ctx->ctx_smpl_hdr, &ovfl_arg, regs, tstamp); + ret = (*ctx->ctx_buf_fmt->fmt_handler)(task, ctx->ctx_smpl_hdr, ovfl_arg, regs, tstamp); end_cycles = ia64_get_itc(); @@ -5319,13 +5296,13 @@ * For those controls, we take the union because they have * an all or nothing behavior. */ - ovfl_ctrl.bits.notify_user |= ovfl_arg.ovfl_ctrl.bits.notify_user; - ovfl_ctrl.bits.block_task |= ovfl_arg.ovfl_ctrl.bits.block_task; - ovfl_ctrl.bits.mask_monitoring |= ovfl_arg.ovfl_ctrl.bits.mask_monitoring; + ovfl_ctrl.bits.notify_user |= ovfl_arg->ovfl_ctrl.bits.notify_user; + ovfl_ctrl.bits.block_task |= ovfl_arg->ovfl_ctrl.bits.block_task; + ovfl_ctrl.bits.mask_monitoring |= ovfl_arg->ovfl_ctrl.bits.mask_monitoring; /* * build the bitmask of pmds to reset now */ - if (ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask; + if (ovfl_arg->ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask; pfm_stats[this_cpu].pfm_smpl_handler_cycles += end_cycles - start_cycles; } @@ -5793,6 +5770,32 @@ } #ifdef CONFIG_SMP + +static void +pfm_force_cleanup(pfm_context_t *ctx, struct pt_regs *regs) +{ + struct task_struct *task = ctx->ctx_task; + + ia64_psr(regs)->up = 0; + ia64_psr(regs)->sp = 1; + + if (GET_PMU_OWNER() == task) { + DPRINT(("cleared ownership for [%d]\n", ctx->ctx_task->pid)); + SET_PMU_OWNER(NULL, NULL); + } + + /* + * disconnect the task from the context and vice-versa + */ + PFM_SET_WORK_PENDING(task, 0); + + task->thread.pfm_context = NULL; + task->thread.flags &= ~IA64_THREAD_PM_VALID; + + DPRINT(("force cleanup for [%d]\n", task->pid)); +} + + /* * in 2.6, interrupts are masked when we come here and the runqueue lock is held */ diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/kernel/process.c 2004-06-20 13:00:24 -07:00 @@ -439,6 +439,10 @@ ia32_save_state(p); if (clone_flags & CLONE_SETTLS) retval = ia32_clone_tls(p, child_ptregs); + + /* Copy partially mapped page list */ + if (!retval) + retval = ia32_copy_partial_page_list(p, clone_flags); } #endif @@ -672,6 +676,8 @@ /* drop floating-point and debug-register state if it exists: */ current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); ia64_drop_fpu(current); + if (IS_IA32_PROCESS(ia64_task_regs(current))) + ia32_drop_partial_page_list(current); } /* @@ -691,6 +697,8 @@ if (current->thread.flags & IA64_THREAD_DBG_VALID) pfm_release_debug_registers(current); #endif + if (IS_IA32_PROCESS(ia64_task_regs(current))) + ia32_drop_partial_page_list(current); } unsigned long diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c --- a/arch/ia64/kernel/unwind.c 2004-06-20 13:00:26 -07:00 +++ b/arch/ia64/kernel/unwind.c 2004-06-20 13:00:26 -07:00 @@ -385,9 +385,10 @@ } if (write) { - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else { + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else { *addr = *val; if (*nat) *nat_addr |= nat_mask; @@ -432,9 +433,10 @@ return -1; } if (write) - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; else *val = *addr; @@ -480,9 +482,10 @@ } if (write) - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; else *val = *addr; @@ -576,9 +579,10 @@ } if (write) { - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; } else *val = *addr; @@ -596,9 +600,10 @@ addr = &info->sw->pr; if (write) { - if (read_only(addr)) - UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n"); - else + if (read_only(addr)) { + UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n", + __FUNCTION__); + } else *addr = *val; } else *val = *addr; diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c --- a/arch/ia64/mm/discontig.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/mm/discontig.c 2004-06-20 13:00:25 -07:00 @@ -154,6 +154,9 @@ memcpy(numa_slit, numa_slit_fix, sizeof (numa_slit)); + for (i = nnode; i < numnodes; i++) + node_set_offline(i); + numnodes = nnode; return; diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- a/arch/ia64/mm/hugetlbpage.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/mm/hugetlbpage.c 2004-06-20 13:00:24 -07:00 @@ -297,7 +297,7 @@ unlock_page(page); } else { hugetlb_put_quota(mapping); - free_huge_page(page); + page_cache_release(page); goto out; } } diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ia64/pci/pci.c 2004-06-20 13:00:24 -07:00 @@ -134,10 +134,18 @@ static int __init pci_acpi_init (void) { - if (!acpi_pci_irq_init()) - printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - else - printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); + struct pci_dev *dev = NULL; + + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + acpi_pci_irq_enable(dev); + return 0; } diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c 2004-06-20 13:00:25 -07:00 @@ -741,7 +741,7 @@ /* Is this PCI bus associated with this moduleid? */ moduleid = NODE_MODULEID( nasid_to_cnodeid(pcibr_soft->bs_nasid)); - if (modules[i]->id == moduleid) { + if (sn_modules[i]->id == moduleid) { struct pcibr_list_s *new_element; new_element = kmalloc(sizeof (struct pcibr_soft_s), GFP_KERNEL); @@ -781,7 +781,7 @@ /* * We now have a list of all the pci bridges associated with - * the module_id, modules[i]. Call pci_bus_map_create() for + * the module_id, sn_modules[i]. Call pci_bus_map_create() for * each pci bridge */ softlistp = first_in_list; diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c --- a/arch/ia64/sn/io/sn2/klgraph.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ia64/sn/io/sn2/klgraph.c 2004-06-20 13:00:25 -07:00 @@ -527,7 +527,7 @@ /* Use module as module vertex fastinfo */ memset(buffer, 0, 16); - format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF); + format_module_id(buffer, sn_modules[cm]->id, MODULE_FORMAT_BRIEF); sprintf(name, EDGE_LBL_MODULE "/%s", buffer); rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl); @@ -535,7 +535,7 @@ rc = rc; HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n"); - hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]); + hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) sn_modules[cm]); /* Add system controller */ sprintf(name, diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c --- a/arch/ia64/sn/io/sn2/ml_iograph.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/sn/io/sn2/ml_iograph.c 2004-06-20 13:00:23 -07:00 @@ -518,6 +518,14 @@ ASSERT(hubv != GRAPH_VERTEX_NONE); /* + * attach our hub_provider information to hubv, + * so we can use it as a crosstalk provider "master" + * vertex. + */ + xtalk_provider_register(hubv, &hub_provider); + xtalk_provider_startup(hubv); + + /* * If nothing connected to this hub's xtalk port, we're done. */ early_probe_for_widget(hubv, &hwid); @@ -526,14 +534,6 @@ return; /* NOTREACHED */ } - - /* - * attach our hub_provider information to hubv, - * so we can use it as a crosstalk provider "master" - * vertex. - */ - xtalk_provider_register(hubv, &hub_provider); - xtalk_provider_startup(hubv); /* * Create a vertex to represent the crosstalk bus diff -Nru a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c --- a/arch/ia64/sn/io/sn2/module.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/sn/io/sn2/module.c 2004-06-20 13:00:23 -07:00 @@ -33,7 +33,7 @@ #define DPRINTF(x...) #endif -module_t *modules[MODULE_MAX]; +module_t *sn_modules[MODULE_MAX]; int nummodules; #define SN00_SERIAL_FUDGE 0x3b1af409d513c2 @@ -59,9 +59,9 @@ int i; for (i = 0; i < nummodules; i++) - if (modules[i]->id == id) { - DPRINTF("module_lookup: found m=0x%p\n", modules[i]); - return modules[i]; + if (sn_modules[i]->id == id) { + DPRINTF("module_lookup: found m=0x%p\n", sn_modules[i]); + return sn_modules[i]; } return NULL; @@ -104,10 +104,10 @@ /* Insert in sorted order by module number */ - for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--) - modules[i] = modules[i - 1]; + for (i = nummodules; i > 0 && sn_modules[i - 1]->id > moduleid; i--) + sn_modules[i] = sn_modules[i - 1]; - modules[i] = m; + sn_modules[i] = m; nummodules++; } diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c --- a/arch/ia64/sn/kernel/irq.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/sn/kernel/irq.c 2004-06-20 13:00:23 -07:00 @@ -41,6 +41,7 @@ extern void pcibr_force_interrupt(pcibr_intr_t intr); extern int sn_force_interrupt_flag; struct irq_desc * sn_irq_desc(unsigned int irq); +extern cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; struct sn_intr_list_t { struct sn_intr_list_t *next; @@ -71,6 +72,21 @@ { } +static inline void move_irq(int irq) +{ + /* note - we hold desc->lock */ + cpumask_t tmp; + irq_desc_t *desc = irq_descp(irq); + + if (!cpus_empty(pending_irq_cpumask[irq])) { + cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); + if (unlikely(!cpus_empty(tmp))) { + desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); + } + cpus_clear(pending_irq_cpumask[irq]); + } +} + static void sn_ack_irq(unsigned int irq) { @@ -94,6 +110,7 @@ } HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask ); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); + move_irq(irq); } static void diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ia64/sn/kernel/setup.c 2004-06-20 13:00:23 -07:00 @@ -226,7 +226,25 @@ shub_1_1_found = 1; } - +/** + * sn_set_error_handling_features - Tell the SN prom how to handle certain + * error types. + */ +static void __init +sn_set_error_handling_features(void) +{ + u64 ret; + u64 sn_ehf_bits[7]; /* see ia64_sn_set_error_handling_features */ + memset(sn_ehf_bits, 0, sizeof(sn_ehf_bits)); +#define EHF(x) __set_bit(SN_SAL_EHF_ ## x, sn_ehf_bits) + EHF(MCA_SLV_TO_OS_INIT_SLV); + EHF(NO_RZ_TLBC); + // Uncomment once Jesse's code goes in - EHF(NO_RZ_IO_READ); +#undef EHF + ret = ia64_sn_set_error_handling_features(sn_ehf_bits); + if (ret) + printk(KERN_ERR "%s: failed, return code %ld\n", __FUNCTION__, ret); +} /** * sn_setup - SN platform setup routine @@ -317,6 +335,9 @@ printk(KERN_DEBUG "sn_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address); } + + /* Tell the prom how to handle certain error types */ + sn_set_error_handling_features(); /* * we set the default root device to /dev/hda diff -Nru a/arch/m68k/Makefile b/arch/m68k/Makefile --- a/arch/m68k/Makefile 2004-06-20 13:00:25 -07:00 +++ b/arch/m68k/Makefile 2004-06-20 13:00:25 -07:00 @@ -28,6 +28,8 @@ LDFLAGS_vmlinux = -N endif +CHECK := $(CHECK) -D__mc68000__=1 -I$(shell $(CC) -print-file-name=include) + # without -fno-strength-reduce the 53c7xx.c driver fails ;-( CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 diff -Nru a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S --- a/arch/m68k/ifpsp060/iskeleton.S 2004-06-20 13:00:23 -07:00 +++ b/arch/m68k/ifpsp060/iskeleton.S 2004-06-20 13:00:23 -07:00 @@ -196,14 +196,57 @@ | Expected outputs: | d0 = 0 -> success; non-zero -> failure | -| Linux/68k: As long as ints are disabled, no swapping out should -| occur (hopefully...) +| Linux/m68k: Make sure the page is properly paged in, so we use +| plpaw and handle any exception here. The kernel must not be +| preempted until _060_unlock_page(), so that the page stays mapped. | .global _060_real_lock_page _060_real_lock_page: - clr.l %d0 + move.l %d2,-(%sp) + | load sfc/dfc + moveq #5,%d0 + tst.b %d0 + jne 1f + moveq #1,%d0 +1: movec.l %dfc,%d2 + movec.l %d0,%dfc + movec.l %d0,%sfc + + clr.l %d0 + | prefetch address + .chip 68060 + move.l %a0,%a1 +1: plpaw (%a1) + addq.w #1,%a0 + tst.b %d1 + jeq 2f + addq.w #2,%a0 +2: plpaw (%a0) +3: .chip 68k + + | restore sfc/dfc + movec.l %d2,%dfc + movec.l %d2,%sfc + move.l (%sp)+,%d2 rts +.section __ex_table,"a" + .align 4 + .long 1b,11f + .long 2b,21f +.previous +.section .fixup,"ax" + .even +11: move.l #0x020003c0,%d0 + or.l %d2,%d0 + swap %d0 + jra 3b +21: move.l #0x02000bc0,%d0 + or.l %d2,%d0 + swap %d0 + jra 3b +.previous + | | _060_unlock_page(): | @@ -216,8 +259,7 @@ | d0 = `xxxxxxff -> supervisor; `xxxxxx00 -> user | d1 = `xxxxxxff -> longword; `xxxxxx00 -> word | -| Linux/68k: As we do no special locking operation, also no unlocking -| is needed... +| Linux/m68k: perhaps reenable preemption here... .global _060_real_unlock_page _060_real_unlock_page: diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c --- a/arch/m68k/kernel/process.c 2004-06-20 13:00:26 -07:00 +++ b/arch/m68k/kernel/process.c 2004-06-20 13:00:26 -07:00 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c --- a/arch/m68k/kernel/signal.c 2004-06-20 13:00:25 -07:00 +++ b/arch/m68k/kernel/signal.c 2004-06-20 13:00:25 -07:00 @@ -228,8 +228,8 @@ goto out; __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%/fp0-%/fp1\n\t" - "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" + "fmovemx %0,%%fp0-%%fp1\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" ".chip 68k" : /* no outputs */ : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); @@ -258,7 +258,7 @@ if (FPU_IS_EMU) { /* restore fpu control register */ if (__copy_from_user(current->thread.fpcntl, - &uc->uc_mcontext.fpregs.f_pcr, 12)) + uc->uc_mcontext.fpregs.f_fpcntl, 12)) goto out; /* restore all other fpu register */ if (__copy_from_user(current->thread.fp, @@ -298,12 +298,12 @@ sizeof(fpregs))) goto out; __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%/fp0-%/fp7\n\t" - "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" + "fmovemx %0,%%fp0-%%fp7\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" ".chip 68k" : /* no outputs */ : "m" (*fpregs.f_fpregs), - "m" (fpregs.f_pcr)); + "m" (*fpregs.f_fpcntl)); } if (context_size && __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, @@ -586,12 +586,12 @@ sc->sc_fpstate[0x38] |= 1 << 3; } __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %/fp0-%/fp1,%0\n\t" - "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" + "fmovemx %%fp0-%%fp1,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" ".chip 68k" - : /* no outputs */ - : "m" (*sc->sc_fpregs), - "m" (*sc->sc_fpcntl) + : "=m" (*sc->sc_fpregs), + "=m" (*sc->sc_fpcntl) + : /* no inputs */ : "memory"); } } @@ -604,7 +604,7 @@ if (FPU_IS_EMU) { /* save fpu control register */ - err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr, + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl, current->thread.fpcntl, 12); /* save all other fpu register */ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, @@ -631,12 +631,12 @@ fpstate[0x38] |= 1 << 3; } __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %/fp0-%/fp7,%0\n\t" - "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" + "fmovemx %%fp0-%%fp7,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" ".chip 68k" - : /* no outputs */ - : "m" (*fpregs.f_fpregs), - "m" (fpregs.f_pcr) + : "=m" (*fpregs.f_fpregs), + "=m" (*fpregs.f_fpcntl) + : /* no inputs */ : "memory"); err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, sizeof(fpregs)); diff -Nru a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c --- a/arch/m68k/kernel/traps.c 2004-06-20 13:00:26 -07:00 +++ b/arch/m68k/kernel/traps.c 2004-06-20 13:00:26 -07:00 @@ -329,7 +329,8 @@ * fault during mem_read/mem_write in ifpsp060/os.S */ send_fault_sig(&fp->ptregs); - } else { + } else if (!(fslw & (MMU060_RE|MMU060_WE)) || + send_fault_sig(&fp->ptregs) > 0) { printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); printk( "68060 access error, fslw=%lx\n", fslw ); trap_c( fp ); @@ -517,7 +518,7 @@ if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) fp->un.fmt7.wb2s &= ~WBV_040; } - } else { + } else if (send_fault_sig(&fp->ptregs) > 0) { printk("68040 access error, ssw=%x\n", ssw); trap_c(fp); } @@ -732,7 +733,7 @@ return; } else if (!(mmusr & MMU_I)) { /* probably a 020 cas fault */ - if (!(ssw & RM)) + if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { printk("invalid %s access at %#lx from pc %#lx\n", diff -Nru a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c --- a/arch/m68k/mac/iop.c 2004-06-20 13:00:25 -07:00 +++ b/arch/m68k/mac/iop.c 2004-06-20 13:00:25 -07:00 @@ -261,7 +261,7 @@ } else { iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA; } - iop_base[IOP_NUM_SCC]->status_ctrl = 0; + iop_base[IOP_NUM_ISM]->status_ctrl = 0; iop_ism_present = 1; } else { iop_base[IOP_NUM_ISM] = NULL; diff -Nru a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c --- a/arch/m68k/mm/memory.c 2004-06-20 13:00:25 -07:00 +++ b/arch/m68k/mm/memory.c 2004-06-20 13:00:25 -07:00 @@ -54,7 +54,7 @@ /* unreserve the page so it's possible to free that page */ PD_PAGE(dp)->flags &= ~(1 << PG_reserved); - atomic_set(&PD_PAGE(dp)->count, 1); + set_page_count(PD_PAGE(dp), 1); return; } diff -Nru a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c --- a/arch/m68knommu/kernel/init_task.c 2004-06-20 13:00:24 -07:00 +++ b/arch/m68knommu/kernel/init_task.c 2004-06-20 13:00:24 -07:00 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c --- a/arch/mips/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/mips/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c --- a/arch/parisc/kernel/init_task.c 2004-06-20 13:00:24 -07:00 +++ b/arch/parisc/kernel/init_task.c 2004-06-20 13:00:24 -07:00 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig 2004-06-20 13:00:26 -07:00 +++ b/arch/ppc/Kconfig 2004-06-20 13:00:26 -07:00 @@ -72,8 +72,21 @@ config 8xx bool "8xx" +config E500 + bool "e500" + endchoice +config BOOKE + bool + depends on E500 + default y + +config FSL_BOOKE + bool + depends on E500 + default y + config PTE_64BIT bool depends on 44x @@ -96,6 +109,21 @@ If in doubt, say Y here. +config SPE + bool "SPE Support" + depends on E500 + ---help--- + This option enables kernel support for the Signal Processing + Extensions (SPE) to the PowerPC processor. The kernel currently + supports saving and restoring SPE registers, and turning on the + 'spe enable' bit so user processes can execute SPE instructions. + + This option is only usefully if you have a processor that supports + SPE (e500, otherwise known as 85xx series), but does not have any + affect on a non-spe cpu (it does, however add code to the kernel). + + If in doubt, say Y here. + config TAU bool "Thermal Management Support" depends on 6xx && !8260 @@ -142,7 +170,7 @@ config MATH_EMULATION bool "Math emulation" - depends on 4xx || 8xx + depends on 4xx || 8xx || E500 ---help--- Some PowerPC chips designed for embedded applications do not have a floating-point unit and therefore do not implement the @@ -198,6 +226,7 @@ If in doubt, say Y here. source arch/ppc/platforms/4xx/Kconfig +source arch/ppc/platforms/85xx/Kconfig config PPC64BRIDGE bool @@ -974,8 +1003,8 @@ bool config PCI - bool "PCI support" if 40x || 8260 - default y if !40x && !8260 && !8xx && !APUS + bool "PCI support" if 40x || 8260 || 85xx + default y if !40x && !8260 && !8xx && !APUS && !85xx default PCI_PERMEDIA if !4xx && !8260 && !8xx && APUS default PCI_QSPAN if !4xx && !8260 && 8xx help @@ -1273,7 +1302,7 @@ config PPC_OCP bool - depends on IBM_OCP + depends on IBM_OCP || FSL_OCP default y endmenu diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/Makefile 2004-06-20 13:00:23 -07:00 @@ -17,19 +17,24 @@ CPPFLAGS += -Iarch/$(ARCH) AFLAGS += -Iarch/$(ARCH) cflags-y += -Iarch/$(ARCH) -msoft-float -pipe \ - -ffixed-r2 -Wno-uninitialized -mmultiple -mstring + -ffixed-r2 -Wno-uninitialized -mmultiple CPP = $(CC) -E $(CFLAGS) +ifndef CONFIG_E500 +cflags-y += -mstring +endif + cflags-$(CONFIG_4xx) += -Wa,-m405 +cflags-$(CONFIG_E500) += -Wa,-me500 cflags-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge CFLAGS += $(cflags-y) - head-y := arch/ppc/kernel/head.o head-$(CONFIG_8xx) := arch/ppc/kernel/head_8xx.o head-$(CONFIG_4xx) := arch/ppc/kernel/head_4xx.o head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o +head-$(CONFIG_E500) := arch/ppc/kernel/head_e500.o head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o @@ -37,6 +42,7 @@ core-y += arch/ppc/kernel/ arch/ppc/platforms/ \ arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/ core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/ +core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/ core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/ core-$(CONFIG_XMON) += arch/ppc/xmon/ core-$(CONFIG_APUS) += arch/ppc/amiga/ diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc/kernel/Makefile 2004-06-20 13:00:25 -07:00 @@ -8,10 +8,14 @@ ifdef CONFIG_4xx EXTRA_AFLAGS := -Wa,-m405 endif +ifdef CONFIG_E500 +EXTRA_AFLAGS := -Wa,-me500 +endif extra-$(CONFIG_PPC_STD_MMU) := head.o extra-$(CONFIG_40x) := head_4xx.o extra-$(CONFIG_44x) := head_44x.o +extra-$(CONFIG_E500) := head_e500.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o extra-$(CONFIG_POWER4) += idle_power4.o diff -Nru a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c --- a/arch/ppc/kernel/align.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/kernel/align.c 2004-06-20 13:00:23 -07:00 @@ -21,7 +21,7 @@ unsigned char flags; }; -#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE) #define OPCD(inst) (((inst) & 0xFC000000) >> 26) #define RS(inst) (((inst) & 0x03E00000) >> 21) #define RA(inst) (((inst) & 0x001F0000) >> 16) @@ -184,7 +184,7 @@ fix_alignment(struct pt_regs *regs) { int instr, nb, flags; -#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE) int opcode, f1, f2, f3; #endif int i, t; @@ -199,8 +199,8 @@ CHECK_FULL_REGS(regs); -#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) - /* The 4xx-family processors have no DSISR register, +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) || defined(CONFIG_BOOKE) + /* The 4xx-family & Book-E processors have no DSISR register, * so we emulate it. * The POWER4 has a DSISR register but doesn't set it on * an alignment fault. -- paulus @@ -250,7 +250,7 @@ flags = aligninfo[instr].flags; - /* For the 4xx-family processors, the 'dar' field of the + /* For the 4xx-family & Book-E processors, the 'dar' field of the * pt_regs structure is overloaded and is really from the DEAR. */ diff -Nru a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c --- a/arch/ppc/kernel/asm-offsets.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc/kernel/asm-offsets.c 2004-06-20 13:00:24 -07:00 @@ -44,7 +44,7 @@ DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); -#ifdef CONFIG_4xx +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); DEFINE(PT_PTRACED, PT_PTRACED); #endif @@ -54,6 +54,12 @@ DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0])); + DEFINE(THREAD_ACC, offsetof(struct thread_struct, acc)); + DEFINE(THREAD_SPEFSCR, offsetof(struct thread_struct, spefscr)); + DEFINE(THREAD_USED_SPE, offsetof(struct thread_struct, used_spe)); +#endif /* CONFIG_SPE */ /* Interrupt register frame */ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c --- a/arch/ppc/kernel/cputable.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc/kernel/cputable.c 2004-06-20 13:00:24 -07:00 @@ -34,7 +34,8 @@ extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spec* spec); #define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ - !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4)) + !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ + !defined(CONFIG_BOOKE)) /* This table only contains "desktop" CPUs, it need to be filled with embedded * ones as well... @@ -561,6 +562,16 @@ 0, /*__setup_cpu_440 */ }, #endif /* CONFIG_44x */ +#ifdef CONFIG_E500 + { /* e500 */ + 0xffff0000, 0x80200000, "e500", + /* xxx - galak: add CPU_FTR_CAN_DOZE */ + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 32, 32, + 0, /*__setup_cpu_e500 */ + }, +#endif #if !CLASSIC_PPC { /* default match */ 0x00000000, 0x00000000, "(generic PPC)", diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S --- a/arch/ppc/kernel/entry.S 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc/kernel/entry.S 2004-06-20 13:00:25 -07:00 @@ -36,7 +36,7 @@ #undef SHOW_SYSCALLS_TASK /* - * MSR_KERNEL is > 0x10000 on 4xx since it include MSR_CE. + * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE. */ #if MSR_KERNEL >= 0x10000 #define LOAD_MSR_KERNEL(r, x) lis r,(x)@h; ori r,r,(x)@l @@ -45,7 +45,7 @@ #endif #ifdef CONFIG_BOOKE -#define COR r8 +#define COR r8 /* Critical Offset Register (COR) */ #define BOOKE_LOAD_COR lis COR,crit_save@ha #define BOOKE_REST_COR mfspr COR,SPRG2 #define BOOKE_SAVE_COR mtspr SPRG2,COR @@ -241,11 +241,11 @@ andi. r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED) bne- syscall_exit_work syscall_exit_cont: -#ifdef CONFIG_4xx +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) /* If the process has its own DBCR0 value, load it up */ lwz r0,PTRACE(r2) andi. r0,r0,PT_PTRACED - bnel- load_4xx_dbcr0 + bnel- load_dbcr0 #endif stwcx. r0,0,r1 /* to clear the reservation */ lwz r4,_LINK(r1) @@ -510,7 +510,12 @@ stw r12,THREAD+THREAD_VRSAVE(r2) END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ - and. r0,r0,r11 /* FP or altivec enabled? */ +#ifdef CONFIG_SPE + oris r0,r0,MSR_SPE@h /* Disable SPE */ + mfspr r12,SPRN_SPEFSCR /* save spefscr register value */ + stw r12,THREAD+THREAD_SPEFSCR(r2) +#endif /* CONFIG_SPE */ + and. r0,r0,r11 /* FP or altivec or SPE enabled? */ beq+ 1f andc r11,r11,r0 MTMSRD(r11) @@ -543,6 +548,10 @@ mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + lwz r0,THREAD+THREAD_SPEFSCR(r2) + mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */ +#endif /* CONFIG_SPE */ lwz r0,_CCR(r1) mtcrf 0xFF,r0 @@ -589,11 +598,11 @@ bne do_work restore_user: -#ifdef CONFIG_4xx +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) /* Check whether this process has its own DBCR0 value */ lwz r0,PTRACE(r2) andi. r0,r0,PT_PTRACED - bnel- load_4xx_dbcr0 + bnel- load_dbcr0 #endif #ifdef CONFIG_PREEMPT @@ -645,7 +654,7 @@ PPC405_ERR77(0,r1) stwcx. r0,0,r1 /* to clear the reservation */ -#ifndef CONFIG_4xx +#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) lwz r9,_MSR(r1) andi. r10,r9,MSR_RI /* check if this exception occurred */ beql nonrecoverable /* at a bad place (MSR:RI = 0) */ @@ -681,9 +690,9 @@ SYNC RFI -#else /* CONFIG_4xx */ +#else /* !(CONFIG_4xx || CONFIG_BOOKE) */ /* - * This is a bit different on 4xx because 4xx doesn't have + * This is a bit different on 4xx/Book-E because it doesn't have * the RI bit in the MSR. * The TLB miss handler checks if we have interrupted * the exception exit path and restarts it if so @@ -720,6 +729,9 @@ * give the wrong answer). * We have to restore various SPRs that may have been in use at the * time of the critical interrupt. + * + * Note that SPRG6 is used for machine check on CONFIG_BOOKE parts and + * thus not saved in the critical handler */ .globl ret_from_crit_exc ret_from_crit_exc: @@ -866,7 +878,7 @@ * Load the DBCR0 value for a task that is being ptraced, * having first saved away the global DBCR0. */ -load_4xx_dbcr0: +load_dbcr0: mfmsr r0 /* first disable debug exceptions */ rlwinm r0,r0,0,~MSR_DE mtmsr r0 @@ -885,7 +897,7 @@ blr .comm global_dbcr0,8 -#endif /* CONFIG_4xx */ +#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */ do_work: /* r10 contains MSR_KERNEL here */ andi. r0,r9,_TIF_NEED_RESCHED diff -Nru a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/kernel/head_e500.S 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1329 @@ +/* + * arch/ppc/kernel/head_e500.S + * + * Kernel execution entry point code. + * + * Copyright (c) 1995-1996 Gary Thomas + * Initial PowerPC version. + * Copyright (c) 1996 Cort Dougan + * Rewritten for PReP + * Copyright (c) 1996 Paul Mackerras + * Low-level exception handers, MMU support, and rewrite. + * Copyright (c) 1997 Dan Malek + * PowerPC 8xx modifications. + * Copyright (c) 1998-1999 TiVo, Inc. + * PowerPC 403GCX modifications. + * Copyright (c) 1999 Grant Erickson + * PowerPC 403GCX/405GP modifications. + * Copyright 2000 MontaVista Software Inc. + * PPC405 modifications + * PowerPC 403GCX/405GP modifications. + * Author: MontaVista Software, Inc. + * frank_rowand@mvista.com or source@mvista.com + * debbie_chu@mvista.com + * Copyright 2002-2004 MontaVista Software, Inc. + * PowerPC 44x support, Matt Porter + * Copyright 2004 Freescale Semiconductor, Inc + * PowerPC e500 modifications, Kumar Gala + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Macros + */ + +#define SET_IVOR(vector_number, vector_label) \ + li r26,vector_label@l; \ + mtspr SPRN_IVOR##vector_number,r26; \ + sync + +/* As with the other PowerPC ports, it is expected that when code + * execution begins here, the following registers contain valid, yet + * optional, information: + * + * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) + * r4 - Starting address of the init RAM disk + * r5 - Ending address of the init RAM disk + * r6 - Start of kernel command line string (e.g. "mem=128") + * r7 - End of kernel command line string + * + */ + .text +_GLOBAL(_stext) +_GLOBAL(_start) + /* + * Reserve a word at a fixed location to store the address + * of abatron_pteptrs + */ + nop +/* + * Save parameters we are passed + */ + mr r31,r3 + mr r30,r4 + mr r29,r5 + mr r28,r6 + mr r27,r7 + li r24,0 /* CPU number */ + +/* We try to not make any assumptions about how the boot loader + * setup or used the TLBs. We invalidate all mappings from the + * boot loader and load a single entry in TLB1[0] to map the + * first 16M of kernel memory. Any boot info passed from the + * bootloader needs to live in this first 16M. + * + * Requirement on bootloader: + * - The page we're executing in needs to reside in TLB1 and + * have IPROT=1. If not an invalidate broadcast could + * evict the entry we're currently executing in. + * + * r3 = Index of TLB1 were executing in + * r4 = Current MSR[IS] + * r5 = Index of TLB1 temp mapping + * + * Later in mapin_ram we will correctly map lowmem, and resize TLB1[0] + * if needed + */ + +/* 1. Find the index of the entry we're executing in */ + bl invstr /* Find our address */ +invstr: mflr r6 /* Make it accessible */ + mfmsr r7 + rlwinm r4,r7,27,31,31 /* extract MSR[IS] */ + mfspr r7, SPRN_PID0 + slwi r7,r7,16 + or r7,r7,r4 + mtspr SPRN_MAS6,r7 + tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */ + mfspr r7,SPRN_MAS1 + andis. r7,r7,MAS1_VALID@h + bne match_TLB + mfspr r7,SPRN_PID1 + slwi r7,r7,16 + or r7,r7,r4 + mtspr SPRN_MAS6,r7 + tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */ + mfspr r7,SPRN_MAS1 + andis. r7,r7,MAS1_VALID@h + bne match_TLB + mfspr r7, SPRN_PID2 + slwi r7,r7,16 + or r7,r7,r4 + mtspr SPRN_MAS6,r7 + tlbsx 0,r6 /* Fall through, we had to match */ +match_TLB: + mfspr r7,SPRN_MAS0 + rlwinm r3,r7,16,28,31 /* Extract MAS0(Entry) */ + + mfspr r7,SPRN_MAS1 /* Insure IPROT set */ + oris r7,r7,MAS1_IPROT@h + mtspr SPRN_MAS1,r7 + tlbwe + +/* 2. Invalidate all entries except the entry we're executing in */ + mfspr r9,SPRN_TLB1CFG + andi. r9,r9,0xfff + li r6,0 /* Set Entry counter to 0 */ +1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ + rlwimi r7,r6,16,12,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */ + mtspr SPRN_MAS0,r7 + tlbre + mfspr r7,SPRN_MAS1 + rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */ + cmpw r3,r6 + beq skpinv /* Dont update the current execution TLB */ + mtspr SPRN_MAS1,r7 + tlbwe + isync +skpinv: addi r6,r6,1 /* Increment */ + cmpw r6,r9 /* Are we done? */ + bne 1b /* If not, repeat */ + + /* Invalidate TLB0 */ + li r6,0x04 + tlbivax 0,r6 +#ifdef CONFIG_SMP + tlbsync +#endif + /* Invalidate TLB1 */ + li r6,0x0c + tlbivax 0,r6 +#ifdef CONFIG_SMP + tlbsync +#endif + msync + +/* 3. Setup a temp mapping and jump to it */ + andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */ + addi r5, r5, 0x1 + lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ + rlwimi r7,r3,16,12,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ + mtspr SPRN_MAS0,r7 + tlbre + + /* Just modify the entry ID and EPN for the temp mapping */ + lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ + rlwimi r7,r5,16,12,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */ + mtspr SPRN_MAS0,r7 + xori r6,r4,1 /* Setup TMP mapping in the other Address space */ + slwi r6,r6,12 + oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h + ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l + mtspr SPRN_MAS1,r6 + mfspr r6,SPRN_MAS2 + li r7,0 /* temp EPN = 0 */ + rlwimi r7,r6,0,20,31 + mtspr SPRN_MAS2,r7 + tlbwe + + xori r6,r4,1 + slwi r6,r6,5 /* setup new context with other address space */ + bl 1f /* Find our address */ +1: mflr r9 + rlwimi r7,r9,0,20,31 + addi r7,r7,24 + mtspr SRR0,r7 + mtspr SRR1,r6 + rfi + +/* 4. Clear out PIDs & Search info */ + li r6,0 + mtspr SPRN_PID0,r6 + mtspr SPRN_PID1,r6 + mtspr SPRN_PID2,r6 + mtspr SPRN_MAS6,r6 + +/* 5. Invalidate mapping we started in */ + lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ + rlwimi r7,r3,16,12,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ + mtspr SPRN_MAS0,r7 + tlbre + li r6,0 + mtspr SPRN_MAS1,r6 + tlbwe + /* Invalidate TLB1 */ + li r9,0x0c + tlbivax 0,r9 +#ifdef CONFIG_SMP + tlbsync +#endif + msync + +/* 6. Setup KERNELBASE mapping in TLB1[0] */ + lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */ + mtspr SPRN_MAS0,r6 + lis r6,(MAS1_VALID|MAS1_IPROT)@h + ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l + mtspr SPRN_MAS1,r6 + li r7,0 + lis r6,KERNELBASE@h + ori r6,r6,KERNELBASE@l + rlwimi r6,r7,0,20,31 + mtspr SPRN_MAS2,r6 + li r7,(MAS3_SX|MAS3_SW|MAS3_SR) + mtspr SPRN_MAS3,r7 + tlbwe + +/* 7. Jump to KERNELBASE mapping */ + li r7,0 + bl 1f /* Find our address */ +1: mflr r9 + rlwimi r6,r9,0,20,31 + addi r6,r6,24 + mtspr SRR0,r6 + mtspr SRR1,r7 + rfi /* start execution out of TLB1[0] entry */ + +/* 8. Clear out the temp mapping */ + lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ + rlwimi r7,r5,16,12,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */ + mtspr SPRN_MAS0,r7 + tlbre + mtspr SPRN_MAS1,r8 + tlbwe + /* Invalidate TLB1 */ + li r9,0x0c + tlbivax 0,r9 +#ifdef CONFIG_SMP + tlbsync +#endif + msync + + /* Establish the interrupt vector offsets */ + SET_IVOR(0, CriticalInput); + SET_IVOR(1, MachineCheck); + SET_IVOR(2, DataStorage); + SET_IVOR(3, InstructionStorage); + SET_IVOR(4, ExternalInput); + SET_IVOR(5, Alignment); + SET_IVOR(6, Program); + SET_IVOR(7, FloatingPointUnavailable); + SET_IVOR(8, SystemCall); + SET_IVOR(9, AuxillaryProcessorUnavailable); + SET_IVOR(10, Decrementer); + SET_IVOR(11, FixedIntervalTimer); + SET_IVOR(12, WatchdogTimer); + SET_IVOR(13, DataTLBError); + SET_IVOR(14, InstructionTLBError); + SET_IVOR(15, Debug); + SET_IVOR(32, SPEUnavailable); + SET_IVOR(33, SPEFloatingPointData); + SET_IVOR(34, SPEFloatingPointRound); + SET_IVOR(35, PerformanceMonitor); + + /* Establish the interrupt vector base */ + lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ + mtspr SPRN_IVPR,r4 + + /* Setup the defaults for TLB entries */ + li r2,MAS4_TSIZED(BOOKE_PAGESZ_4K) + mtspr SPRN_MAS4, r2 + +#if 0 + /* Enable DOZE */ + mfspr r2,SPRN_HID0 + oris r2,r2,HID0_DOZE@h + mtspr SPRN_HID0, r2 +#endif + + /* + * This is where the main kernel code starts. + */ + + /* ptr to current */ + lis r2,init_task@h + ori r2,r2,init_task@l + + /* ptr to current thread */ + addi r4,r2,THREAD /* init task's THREAD */ + mtspr SPRG3,r4 + + /* stack */ + lis r1,init_thread_union@h + ori r1,r1,init_thread_union@l + li r0,0 + stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) + + bl early_init + + mfspr r3,SPRN_TLB1CFG + andi. r3,r3,0xfff + lis r4,num_tlbcam_entries@ha + stw r3,num_tlbcam_entries@l(r4) +/* + * Decide what sort of machine this is and initialize the MMU. + */ + mr r3,r31 + mr r4,r30 + mr r5,r29 + mr r6,r28 + mr r7,r27 + bl machine_init + bl MMU_init + + /* Setup PTE pointers for the Abatron bdiGDB */ + lis r6, swapper_pg_dir@h + ori r6, r6, swapper_pg_dir@l + lis r5, abatron_pteptrs@h + ori r5, r5, abatron_pteptrs@l + lis r4, KERNELBASE@h + ori r4, r4, KERNELBASE@l + stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */ + stw r6, 0(r5) + + /* Let's move on */ + lis r4,start_kernel@h + ori r4,r4,start_kernel@l + lis r3,MSR_KERNEL@h + ori r3,r3,MSR_KERNEL@l + mtspr SRR0,r4 + mtspr SRR1,r3 + rfi /* change context and jump to start_kernel */ + +/* + * Interrupt vector entry code + * + * The Book E MMUs are always on so we don't need to handle + * interrupts in real mode as with previous PPC processors. In + * this case we handle interrupts in the kernel virtual address + * space. + * + * Interrupt vectors are dynamically placed relative to the + * interrupt prefix as determined by the address of interrupt_base. + * The interrupt vectors offsets are programmed using the labels + * for each interrupt vector entry. + * + * Interrupt vectors must be aligned on a 16 byte boundary. + * We align on a 32 byte cache line boundary for good measure. + */ + +#define NORMAL_EXCEPTION_PROLOG \ + mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ + mtspr SPRN_SPRG1,r11; \ + mtspr SPRN_SPRG4W,r1; \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + beq 1f; \ + mfspr r1,SPRG3; /* if from user, start at top of */\ + lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ + addi r1,r1,THREAD_SIZE; \ +1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ + tophys(r11,r1); \ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mfspr r10,SPRG0; \ + stw r10,GPR10(r11); \ + mfspr r12,SPRG1; \ + stw r12,GPR11(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r10,SPRG4R; \ + mfspr r12,SRR0; \ + stw r10,GPR1(r11); \ + mfspr r9,SRR1; \ + stw r10,0(r11); \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +/* + * Exception prolog for critical exceptions. This is a little different + * from the normal exception prolog above since a critical exception + * can potentially occur at any point during normal exception processing. + * Thus we cannot use the same SPRG registers as the normal prolog above. + * Instead we use a couple of words of memory at low physical addresses. + * This is OK since we don't support SMP on these processors. For Book E + * processors, we also have a reserved register (SPRG2) that is only used + * in critical exceptions so we can free up a GPR to use as the base for + * indirect access to the critical exception save area. This is necessary + * since the MMU is always on and the save area is offset from KERNELBASE. + */ +#define CRITICAL_EXCEPTION_PROLOG \ + mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \ + lis r8,crit_save@ha; \ + stw r10,crit_r10@l(r8); \ + stw r11,crit_r11@l(r8); \ + mfspr r10,SPRG0; \ + stw r10,crit_sprg0@l(r8); \ + mfspr r10,SPRG1; \ + stw r10,crit_sprg1@l(r8); \ + mfspr r10,SPRG4R; \ + stw r10,crit_sprg4@l(r8); \ + mfspr r10,SPRG5R; \ + stw r10,crit_sprg5@l(r8); \ + mfspr r10,SPRG7R; \ + stw r10,crit_sprg7@l(r8); \ + mfspr r10,SPRN_PID; \ + stw r10,crit_pid@l(r8); \ + mfspr r10,SRR0; \ + stw r10,crit_srr0@l(r8); \ + mfspr r10,SRR1; \ + stw r10,crit_srr1@l(r8); \ + mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + lis r11,critical_stack_top@h; \ + ori r11,r11,critical_stack_top@l; \ + beq 1f; \ + /* COMING FROM USER MODE */ \ + mfspr r11,SPRG3; /* if from user, start at top of */\ + lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ + addi r11,r11,THREAD_SIZE; \ +1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ + stw r12,_DEAR(r11); /* since they may have had stuff */\ + mfspr r9,SPRN_ESR; /* in them at the point where the */\ + stw r9,_ESR(r11); /* exception was taken */\ + mfspr r12,CSRR0; \ + stw r1,GPR1(r11); \ + mfspr r9,CSRR1; \ + stw r1,0(r11); \ + tovirt(r1,r11); \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +/* + * Exception prolog for machine check exceptions. This is similar to + * the critical exception prolog, except that machine check exceptions + * have their own save area. For Book E processors, we also have a + * reserved register (SPRG6) that is only used in machine check exceptions + * so we can free up a GPR to use as the base for indirect access to the + * machine check exception save area. This is necessary since the MMU + * is always on and the save area is offset from KERNELBASE. + */ +#define MCHECK_EXCEPTION_PROLOG \ + mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \ + lis r8,mcheck_save@ha; \ + stw r10,mcheck_r10@l(r8); \ + stw r11,mcheck_r11@l(r8); \ + mfspr r10,SPRG0; \ + stw r10,mcheck_sprg0@l(r8); \ + mfspr r10,SPRG1; \ + stw r10,mcheck_sprg1@l(r8); \ + mfspr r10,SPRG4R; \ + stw r10,mcheck_sprg4@l(r8); \ + mfspr r10,SPRG5R; \ + stw r10,mcheck_sprg5@l(r8); \ + mfspr r10,SPRG7R; \ + stw r10,mcheck_sprg7@l(r8); \ + mfspr r10,SPRN_PID; \ + stw r10,mcheck_pid@l(r8); \ + mfspr r10,SRR0; \ + stw r10,mcheck_srr0@l(r8); \ + mfspr r10,SRR1; \ + stw r10,mcheck_srr1@l(r8); \ + mfspr r10,CSRR0; \ + stw r10,mcheck_csrr0@l(r8); \ + mfspr r10,CSRR1; \ + stw r10,mcheck_csrr1@l(r8); \ + mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \ + mfcr r10; /* save CR in r10 for now */\ + mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\ + andi. r11,r11,MSR_PR; \ + lis r11,mcheck_stack_top@h; \ + ori r11,r11,mcheck_stack_top@l; \ + beq 1f; \ + /* COMING FROM USER MODE */ \ + mfspr r11,SPRG3; /* if from user, start at top of */\ + lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ + addi r11,r11,THREAD_SIZE; \ +1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ + stw r10,_CCR(r11); /* save various registers */\ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ + stw r12,_DEAR(r11); /* since they may have had stuff */\ + mfspr r9,SPRN_ESR; /* in them at the point where the */\ + stw r9,_ESR(r11); /* exception was taken */\ + mfspr r12,MCSRR0; \ + stw r1,GPR1(r11); \ + mfspr r9,MCSRR1; \ + stw r1,0(r11); \ + tovirt(r1,r11); \ + rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + +/* + * Exception vectors. + */ +#define START_EXCEPTION(label) \ + .align 5; \ +label: + +#define FINISH_EXCEPTION(func) \ + bl transfer_to_handler_full; \ + .long func; \ + .long ret_from_except_full + +#define EXCEPTION(n, label, hdlr, xfer) \ + START_EXCEPTION(label); \ + NORMAL_EXCEPTION_PROLOG; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + xfer(n, hdlr) + +#define CRITICAL_EXCEPTION(n, label, hdlr) \ + START_EXCEPTION(label); \ + CRITICAL_EXCEPTION_PROLOG; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, transfer_to_handler_full, \ + ret_from_except_full) + +#define MCHECK_EXCEPTION(n, label, hdlr) \ + START_EXCEPTION(label); \ + MCHECK_EXCEPTION_PROLOG; \ + mfspr r5,SPRN_ESR; \ + stw r5,_ESR(r11); \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, mcheck_transfer_to_handler, \ + ret_from_mcheck_exc) + +#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ + li r10,trap; \ + stw r10,TRAP(r11); \ + lis r10,msr@h; \ + ori r10,r10,msr@l; \ + copyee(r10, r9); \ + bl tfer; \ + .long hdlr; \ + .long ret + +#define COPY_EE(d, s) rlwimi d,s,0,16,16 +#define NOCOPY(d, s) + +#define EXC_XFER_STD(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ + ret_from_except) + +#define EXC_XFER_EE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_EE_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ + ret_from_except) + +interrupt_base: + /* Critical Input Interrupt */ + CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException) + + /* Machine Check Interrupt */ + MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException) + + /* Data Storage Interrupt */ + START_EXCEPTION(DataStorage) + mtspr SPRG0, r10 /* Save some working registers */ + mtspr SPRG1, r11 + mtspr SPRG4W, r12 + mtspr SPRG5W, r13 + mfcr r11 + mtspr SPRG7W, r11 + + /* + * Check if it was a store fault, if not then bail + * because a user tried to access a kernel or + * read-protected page. Otherwise, get the + * offending address and handle it. + */ + mfspr r10, SPRN_ESR + andis. r10, r10, ESR_ST@h + beq 2f + + mfspr r10, SPRN_DEAR /* Get faulting address */ + + /* If we are faulting a kernel address, we have to use the + * kernel page tables. + */ + lis r11, TASK_SIZE@h + ori r11, r11, TASK_SIZE@l + cmplw 0, r10, r11 + bge 2f + + /* Get the PGD for the current thread */ +3: + mfspr r11,SPRG3 + lwz r11,PGDIR(r11) +4: + rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ + lwz r11, 0(r11) /* Get L1 entry */ + rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */ + beq 2f /* Bail if no table */ + + rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */ + lwz r11, 0(r12) /* Get Linux PTE */ + + /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */ + andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE + cmpwi 0, r13, _PAGE_RW|_PAGE_USER + bne 2f /* Bail if not */ + + /* Update 'changed'. */ + ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE + stw r11, 0(r12) /* Update Linux page table */ + + /* MAS2 not updated as the entry does exist in the tlb, this + fault taken to detect state transition (eg: COW -> DIRTY) + */ + lis r12, MAS3_RPN@h + ori r12, r12, _PAGE_HWEXEC | MAS3_RPN@l + and r11, r11, r12 + rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */ + ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */ + + /* update search PID in MAS6, AS = 0 */ + mfspr r12, SPRN_PID0 + slwi r12, r12, 16 + mtspr SPRN_MAS6, r12 + + /* find the TLB index that caused the fault. It has to be here. */ + tlbsx 0, r10 + + mtspr SPRN_MAS3,r11 + tlbwe + + /* Done...restore registers and get out of here. */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + rfi /* Force context change */ + +2: + /* + * The bailout. Restore registers to pre-exception conditions + * and call the heavyweights to help us out. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + b data_access + + /* Instruction Storage Interrupt */ + START_EXCEPTION(InstructionStorage) + NORMAL_EXCEPTION_PROLOG + mfspr r5,SPRN_ESR /* Grab the ESR and save it */ + stw r5,_ESR(r11) + mr r4,r12 /* Pass SRR0 as arg2 */ + li r5,0 /* Pass zero as arg3 */ + EXC_XFER_EE_LITE(0x0400, handle_page_fault) + + /* External Input Interrupt */ + EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE) + + /* Alignment Interrupt */ + START_EXCEPTION(Alignment) + NORMAL_EXCEPTION_PROLOG + mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */ + stw r4,_DEAR(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE(0x0600, AlignmentException) + + /* Program Interrupt */ + START_EXCEPTION(Program) + NORMAL_EXCEPTION_PROLOG + mfspr r4,SPRN_ESR /* Grab the ESR and save it */ + stw r4,_ESR(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_STD(0x0700, ProgramCheckException) + + /* Floating Point Unavailable Interrupt */ + EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) + + /* System Call Interrupt */ + START_EXCEPTION(SystemCall) + NORMAL_EXCEPTION_PROLOG + EXC_XFER_EE_LITE(0x0c00, DoSyscall) + + /* Auxillary Processor Unavailable Interrupt */ + EXCEPTION(0x2900, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE) + + /* Decrementer Interrupt */ + START_EXCEPTION(Decrementer) + NORMAL_EXCEPTION_PROLOG + lis r0,TSR_DIS@h /* Setup the DEC interrupt mask */ + mtspr SPRN_TSR,r0 /* Clear the DEC interrupt */ + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_LITE(0x0900, timer_interrupt) + + /* Fixed Internal Timer Interrupt */ + /* TODO: Add FIT support */ + EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE) + + /* Watchdog Timer Interrupt */ + /* TODO: Add watchdog support */ + CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException) + + /* Data TLB Error Interrupt */ + START_EXCEPTION(DataTLBError) + mtspr SPRG0, r10 /* Save some working registers */ + mtspr SPRG1, r11 + mtspr SPRG4W, r12 + mtspr SPRG5W, r13 + mfcr r11 + mtspr SPRG7W, r11 + mfspr r10, SPRN_DEAR /* Get faulting address */ + + /* If we are faulting a kernel address, we have to use the + * kernel page tables. + */ + lis r11, TASK_SIZE@h + ori r11, r11, TASK_SIZE@l + cmplw 5, r10, r11 + blt 5, 3f + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + + mfspr r12,SPRN_MAS1 /* Set TID to 0 */ + li r13,MAS1_TID@l + andc r12,r12,r13 + mtspr SPRN_MAS1,r12 + + b 4f + + /* Get the PGD for the current thread */ +3: + mfspr r11,SPRG3 + lwz r11,PGDIR(r11) + +4: + rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ + lwz r11, 0(r11) /* Get L1 entry */ + rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */ + beq 2f /* Bail if no table */ + + rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */ + lwz r11, 0(r12) /* Get Linux PTE */ + andi. r13, r11, _PAGE_PRESENT + beq 2f + + ori r11, r11, _PAGE_ACCESSED + stw r11, 0(r12) + + /* Jump to common tlb load */ + b finish_tlb_load +2: + /* The bailout. Restore registers to pre-exception conditions + * and call the heavyweights to help us out. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + b data_access + + /* Instruction TLB Error Interrupt */ + /* + * Nearly the same as above, except we get our + * information from different registers and bailout + * to a different point. + */ + START_EXCEPTION(InstructionTLBError) + mtspr SPRG0, r10 /* Save some working registers */ + mtspr SPRG1, r11 + mtspr SPRG4W, r12 + mtspr SPRG5W, r13 + mfcr r11 + mtspr SPRG7W, r11 + mfspr r10, SRR0 /* Get faulting address */ + + /* If we are faulting a kernel address, we have to use the + * kernel page tables. + */ + lis r11, TASK_SIZE@h + ori r11, r11, TASK_SIZE@l + cmplw 5, r10, r11 + blt 5, 3f + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + + mfspr r12,SPRN_MAS1 /* Set TID to 0 */ + li r13,MAS1_TID@l + andc r12,r12,r13 + mtspr SPRN_MAS1,r12 + + b 4f + + /* Get the PGD for the current thread */ +3: + mfspr r11,SPRG3 + lwz r11,PGDIR(r11) + +4: + rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ + lwz r11, 0(r11) /* Get L1 entry */ + rlwinm. r12, r11, 0, 0, 19 /* Extract L2 (pte) base address */ + beq 2f /* Bail if no table */ + + rlwimi r12, r10, 22, 20, 29 /* Compute PTE address */ + lwz r11, 0(r12) /* Get Linux PTE */ + andi. r13, r11, _PAGE_PRESENT + beq 2f + + ori r11, r11, _PAGE_ACCESSED + stw r11, 0(r12) + + /* Jump to common TLB load point */ + b finish_tlb_load + +2: + /* The bailout. Restore registers to pre-exception conditions + * and call the heavyweights to help us out. + */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + b InstructionStorage + +#ifdef CONFIG_SPE + /* SPE Unavailable */ + START_EXCEPTION(SPEUnavailable) + NORMAL_EXCEPTION_PROLOG + bne load_up_spe + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE_LITE(0x2010, KernelSPE) +#else + EXCEPTION(0x2020, SPEUnavailable, UnknownException, EXC_XFER_EE) +#endif /* CONFIG_SPE */ + + /* SPE Floating Point Data */ +#ifdef CONFIG_SPE + EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE); +#else + EXCEPTION(0x2040, SPEFloatingPointData, UnknownException, EXC_XFER_EE) +#endif /* CONFIG_SPE */ + + /* SPE Floating Point Round */ + EXCEPTION(0x2050, SPEFloatingPointRound, UnknownException, EXC_XFER_EE) + + /* Performance Monitor */ + EXCEPTION(0x2060, PerformanceMonitor, UnknownException, EXC_XFER_EE) + +/* Check for a single step debug exception while in an exception + * handler before state has been saved. This is to catch the case + * where an instruction that we are trying to single step causes + * an exception (eg ITLB/DTLB miss) and thus the first instruction of + * the exception handler generates a single step debug exception. + * + * If we get a debug trap on the first instruction of an exception handler, + * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is + * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). + * The exception handler was handling a non-critical interrupt, so it will + * save (and later restore) the MSR via SPRN_SRR1, which will still have + * the MSR_DE bit set. + */ + /* Debug Interrupt */ + START_EXCEPTION(Debug) + CRITICAL_EXCEPTION_PROLOG + + /* + * If this is a single step or branch-taken exception in an + * exception entry sequence, it was probably meant to apply to + * the code where the exception occurred (since exception entry + * doesn't turn off DE automatically). We simulate the effect + * of turning off DE on entry to an exception handler by turning + * off DE in the CSRR1 value and clearing the debug status. + */ + mfspr r10,SPRN_DBSR /* check single-step/branch taken */ + andis. r10,r10,(DBSR_IC|DBSR_BT)@h + beq+ 1f + andi. r0,r9,MSR_PR /* check supervisor */ + beq 2f /* branch if we need to fix it up... */ + + /* continue normal handling for a critical exception... */ +1: mfspr r4,SPRN_DBSR + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_TEMPLATE(DebugException, 0x2002, \ + (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) + + /* here it looks like we got an inappropriate debug exception. */ +2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the CSRR1 value */ + mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */ + /* restore state and get out */ + lwz r10,_CCR(r11) + lwz r0,GPR0(r11) + lwz r1,GPR1(r11) + mtcrf 0x80,r10 + mtspr CSRR0,r12 + mtspr CSRR1,r9 + lwz r9,GPR9(r11) + + mtspr SPRG2,r8; /* SPRG2 only used in criticals */ + lis r8,crit_save@ha; + lwz r10,crit_r10@l(r8) + lwz r11,crit_r11@l(r8) + mfspr r8,SPRG2 + + rfci + b . + +/* + * Local functions + */ + /* + * Data TLB exceptions will bail out to this point + * if they can't resolve the lightweight TLB fault. + */ +data_access: + NORMAL_EXCEPTION_PROLOG + mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ + stw r5,_ESR(r11) + mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ + andis. r10,r5,(ESR_ILK|ESR_DLK)@h + bne 1f + EXC_XFER_EE_LITE(0x0300, handle_page_fault) +1: + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_EE_LITE(0x0300, CacheLockingException) + +/* + + * Both the instruction and data TLB miss get to this + * point to load the TLB. + * r10 - EA of fault + * r11 - TLB (info from Linux PTE) + * r12, r13 - available to use + * CR5 - results of addr < TASK_SIZE + * MAS0, MAS1 - loaded with proper value when we get here + * MAS2, MAS3 - will need additional info from Linux PTE + * Upon exit, we reload everything and RFI. + */ +finish_tlb_load: + /* + * We set execute, because we don't have the granularity to + * properly set this at the page level (Linux problem). + * Many of these bits are software only. Bits we don't set + * here we (properly should) assume have the appropriate value. + */ + + mfspr r12, SPRN_MAS2 + rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ + mtspr SPRN_MAS2, r12 + + bge 5, 1f + + /* addr > TASK_SIZE */ + li r10, (MAS3_UX | MAS3_UW | MAS3_UR) + andi. r13, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC) + andi. r12, r11, _PAGE_USER /* Test for _PAGE_USER */ + iseleq r12, 0, r10 + and r10, r12, r13 + srwi r12, r10, 1 + or r12, r12, r10 /* Copy user perms into supervisor */ + b 2f + + /* addr <= TASK_SIZE */ +1: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */ + ori r12, r12, (MAS3_SX | MAS3_SR) + +2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */ + mtspr SPRN_MAS3, r11 + tlbwe + + /* Done...restore registers and get out of here. */ + mfspr r11, SPRG7R + mtcr r11 + mfspr r13, SPRG5R + mfspr r12, SPRG4R + mfspr r11, SPRG1 + mfspr r10, SPRG0 + rfi /* Force context change */ + +#ifdef CONFIG_SPE +/* Note that the SPE support is closely modeled after the AltiVec + * support. Changes to one are likely to be applicable to the + * other! */ +load_up_spe: +/* + * Disable SPE for the task which had SPE previously, + * and save its SPE registers in its thread_struct. + * Enables SPE for use in the kernel on return. + * On SMP we know the SPE units are free, since we give it up every + * switch. -- Kumar + */ + mfmsr r5 + oris r5,r5,MSR_SPE@h + mtmsr r5 /* enable use of SPE now */ + isync +/* + * For SMP, we don't do lazy SPE switching because it just gets too + * horrendously complex, especially when a task switches from one CPU + * to another. Instead we call giveup_spe in switch_to. + */ +#ifndef CONFIG_SMP + lis r3,last_task_used_spe@ha + lwz r4,last_task_used_spe@l(r3) + cmpi 0,r4,0 + beq 1f + addi r4,r4,THREAD /* want THREAD of last_task_used_spe */ + SAVE_32EVR(0,r10,r4) + evxor evr10, evr10, evr10 /* clear out evr10 */ + evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */ + li r5,THREAD_ACC + evstddx evr10, r4, r5 /* save off accumulator */ + lwz r5,PT_REGS(r4) + lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) + lis r10,MSR_SPE@h + andc r4,r4,r10 /* disable SPE for previous task */ + stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#endif /* CONFIG_SMP */ + /* enable use of SPE after return */ + oris r9,r9,MSR_SPE@h + mfspr r5,SPRG3 /* current task's THREAD (phys) */ + li r4,1 + li r10,THREAD_ACC + stw r4,THREAD_USED_SPE(r5) + evlddx evr4,r10,r5 + evmra evr4,evr4 + REST_32EVR(0,r10,r5) +#ifndef CONFIG_SMP + subi r4,r5,THREAD + stw r4,last_task_used_spe@l(r3) +#endif /* CONFIG_SMP */ + /* restore registers and return */ +2: REST_4GPRS(3, r11) + lwz r10,_CCR(r11) + REST_GPR(1, r11) + mtcr r10 + lwz r10,_LINK(r11) + mtlr r10 + REST_GPR(10, r11) + mtspr SRR1,r9 + mtspr SRR0,r12 + REST_GPR(9, r11) + REST_GPR(12, r11) + lwz r11,GPR11(r11) + SYNC + rfi + + + +/* + * SPE unavailable trap from kernel - print a message, but let + * the task use SPE in the kernel until it returns to user mode. + */ +KernelSPE: + lwz r3,_MSR(r1) + oris r3,r3,MSR_SPE@h + stw r3,_MSR(r1) /* enable use of SPE after return */ + lis r3,87f@h + ori r3,r3,87f@l + mr r4,r2 /* current */ + lwz r5,_NIP(r1) + bl printk + b ret_from_except +87: .string "SPE used in kernel (task=%p, pc=%x) \n" + .align 4,0 + +#endif /* CONFIG_SPE */ + +/* + * Global functions + */ + +/* + * extern void loadcam_entry(unsigned int index) + * + * Load TLBCAM[index] entry in to the L2 CAM MMU + */ +_GLOBAL(loadcam_entry) + lis r4,TLBCAM@ha + addi r4,r4,TLBCAM@l + mulli r5,r3,20 + add r3,r5,r4 + lwz r4,0(r3) + mtspr SPRN_MAS0,r4 + lwz r4,4(r3) + mtspr SPRN_MAS1,r4 + lwz r4,8(r3) + mtspr SPRN_MAS2,r4 + lwz r4,12(r3) + mtspr SPRN_MAS3,r4 + tlbwe + isync + blr + +/* + * extern void giveup_altivec(struct task_struct *prev) + * + * The e500 core does not have an AltiVec unit. + */ +_GLOBAL(giveup_altivec) + blr + +#ifdef CONFIG_SPE +/* + * extern void giveup_spe(struct task_struct *prev) + * + */ +_GLOBAL(giveup_spe) + mfmsr r5 + oris r5,r5,MSR_SPE@h + SYNC + mtmsr r5 /* enable use of SPE now */ + isync + cmpi 0,r3,0 + beqlr- /* if no previous owner, done */ + addi r3,r3,THREAD /* want THREAD of task */ + lwz r5,PT_REGS(r3) + cmpi 0,r5,0 + SAVE_32EVR(0, r4, r3) + evxor evr6, evr6, evr6 /* clear out evr6 */ + evmwumiaa evr6, evr6, evr6 /* evr6 <- ACC = 0 * 0 + ACC */ + li r4,THREAD_ACC + evstddx evr6, r4, r3 /* save off accumulator */ + beq 1f + lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) + lis r3,MSR_SPE@h + andc r4,r4,r3 /* disable SPE for previous task */ + stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#ifndef CONFIG_SMP + li r5,0 + lis r4,last_task_used_spe@ha + stw r5,last_task_used_spe@l(r4) +#endif /* CONFIG_SMP */ + blr +#endif /* CONFIG_SPE */ + +/* + * extern void giveup_fpu(struct task_struct *prev) + * + * The e500 core does not have an FPU. + */ +_GLOBAL(giveup_fpu) + blr + +/* + * extern void abort(void) + * + * At present, this routine just applies a system reset. + */ +_GLOBAL(abort) + li r13,0 + mtspr SPRN_DBCR0,r13 /* disable all debug events */ + mfmsr r13 + ori r13,r13,MSR_DE@l /* Enable Debug Events */ + mtmsr r13 + mfspr r13,SPRN_DBCR0 + lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h + mtspr SPRN_DBCR0,r13 + +_GLOBAL(set_context) + +#ifdef CONFIG_BDI_SWITCH + /* Context switch the PTE pointer for the Abatron BDI2000. + * The PGDIR is the second parameter. + */ + lis r5, abatron_pteptrs@h + ori r5, r5, abatron_pteptrs@l + stw r4, 0x4(r5) +#endif + mtspr SPRN_PID,r3 + isync /* Force context change */ + blr + +/* + * We put a few things here that have to be page-aligned. This stuff + * goes at the beginning of the data segment, which is page-aligned. + */ + .data +_GLOBAL(sdata) +_GLOBAL(empty_zero_page) + .space 4096 +_GLOBAL(swapper_pg_dir) + .space 4096 + + .section .bss +/* Stack for handling critical exceptions from kernel mode */ +critical_stack_bottom: + .space 4096 +critical_stack_top: + .previous + +/* Stack for handling machine check exceptions from kernel mode */ +mcheck_stack_bottom: + .space 4096 +mcheck_stack_top: + .previous + +/* + * This area is used for temporarily saving registers during the + * critical and machine check exception prologs. It must always + * follow the page aligned allocations, so it starts on a page + * boundary, ensuring that all crit_save areas are in a single + * page. + */ + +/* crit_save */ +_GLOBAL(crit_save) + .space 4 +_GLOBAL(crit_r10) + .space 4 +_GLOBAL(crit_r11) + .space 4 +_GLOBAL(crit_sprg0) + .space 4 +_GLOBAL(crit_sprg1) + .space 4 +_GLOBAL(crit_sprg4) + .space 4 +_GLOBAL(crit_sprg5) + .space 4 +_GLOBAL(crit_sprg7) + .space 4 +_GLOBAL(crit_pid) + .space 4 +_GLOBAL(crit_srr0) + .space 4 +_GLOBAL(crit_srr1) + .space 4 + +/* mcheck_save */ +_GLOBAL(mcheck_save) + .space 4 +_GLOBAL(mcheck_r10) + .space 4 +_GLOBAL(mcheck_r11) + .space 4 +_GLOBAL(mcheck_sprg0) + .space 4 +_GLOBAL(mcheck_sprg1) + .space 4 +_GLOBAL(mcheck_sprg4) + .space 4 +_GLOBAL(mcheck_sprg5) + .space 4 +_GLOBAL(mcheck_sprg7) + .space 4 +_GLOBAL(mcheck_pid) + .space 4 +_GLOBAL(mcheck_srr0) + .space 4 +_GLOBAL(mcheck_srr1) + .space 4 +_GLOBAL(mcheck_csrr0) + .space 4 +_GLOBAL(mcheck_csrr1) + .space 4 + +/* + * This space gets a copy of optional info passed to us by the bootstrap + * which is used to pass parameters into the kernel like root=/dev/sda1, etc. + */ +_GLOBAL(cmd_line) + .space 512 + +/* + * Room for two PTE pointers, usually the kernel and current user pointers + * to their respective root page table. + */ +abatron_pteptrs: + .space 8 + + diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc/kernel/irq.c 2004-06-20 13:00:25 -07:00 @@ -628,7 +628,9 @@ static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { - cpumask_t *mask = (cpumask_t *)data, full_count = count, err; + int err; + int full_count = count; + cpumask_t *mask = (cpumask_t *)data; cpumask_t new_value; err = cpumask_parse(buffer, count, new_value); diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc/kernel/misc.S 2004-06-20 13:00:25 -07:00 @@ -419,7 +419,24 @@ ble 1b isync -#else /* !(CONFIG_40x || CONFIG_44x) */ +#elif defined(CONFIG_FSL_BOOKE) + /* Invalidate all entries in TLB0 */ + li r3, 0x04 + tlbivax 0,3 + /* Invalidate all entries in TLB1 */ + li r3, 0x0c + tlbivax 0,3 + /* Invalidate all entries in TLB2 */ + li r3, 0x14 + tlbivax 0,3 + /* Invalidate all entries in TLB3 */ + li r3, 0x1c + tlbivax 0,3 + msync +#ifdef CONFIG_SMP + tlbsync +#endif /* CONFIG_SMP */ +#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ #if defined(CONFIG_SMP) rlwinm r8,r1,0,0,18 lwz r8,TI_CPU(r8) @@ -487,7 +504,20 @@ tlbwe r3, r3, PPC44x_TLB_PAGEID isync 10: -#else /* !(CONFIG_40x || CONFIG_44x) */ +#elif defined(CONFIG_FSL_BOOKE) + rlwinm r4, r3, 0, 0, 19 + ori r5, r4, 0x08 /* TLBSEL = 1 */ + ori r6, r4, 0x10 /* TLBSEL = 2 */ + ori r7, r4, 0x18 /* TLBSEL = 3 */ + tlbivax 0, r4 + tlbivax 0, r5 + tlbivax 0, r6 + tlbivax 0, r7 + msync +#if defined(CONFIG_SMP) + tlbsync +#endif /* CONFIG_SMP */ +#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ #if defined(CONFIG_SMP) rlwinm r8,r1,0,0,18 lwz r8,TI_CPU(r8) @@ -544,6 +574,10 @@ lis r3, KERNELBASE@h iccci 0,r3 #endif +#elif CONFIG_FSL_BOOKE + mfspr r3,SPRN_L1CSR1 + ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR + mtspr SPRN_L1CSR1,r3 #else mfspr r3,PVR rlwinm r3,r3,16,16,31 @@ -1047,7 +1081,7 @@ * and exceptions as if the cpu had performed the load or store. */ -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_E500) _GLOBAL(cvt_fd) lfs 0,0(r3) stfd 0,0(r4) diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c --- a/arch/ppc/kernel/ppc_ksyms.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc/kernel/ppc_ksyms.c 2004-06-20 13:00:25 -07:00 @@ -199,6 +199,10 @@ EXPORT_SYMBOL(last_task_used_altivec); EXPORT_SYMBOL(giveup_altivec); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE +EXPORT_SYMBOL(last_task_used_spe); +EXPORT_SYMBOL(giveup_spe); +#endif /* CONFIG_SPE */ #ifdef CONFIG_SMP EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(smp_hw_index); @@ -324,7 +328,7 @@ EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_free_handler); #endif /* CONFIG_8xx */ -#if defined(CONFIG_8xx) || defined(CONFIG_40x) +#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) EXPORT_SYMBOL(__res); #endif #if defined(CONFIG_8xx) diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc/kernel/process.c 2004-06-20 13:00:24 -07:00 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ struct task_struct *last_task_used_math = NULL; struct task_struct *last_task_used_altivec = NULL; +struct task_struct *last_task_used_spe = NULL; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; @@ -177,6 +179,34 @@ EXPORT_SYMBOL(enable_kernel_altivec); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE +int +dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) +{ + if (regs->msr & MSR_SPE) + giveup_spe(current); + /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */ + memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35); + return 1; +} + +void +enable_kernel_spe(void) +{ + WARN_ON(preemptible()); + +#ifdef CONFIG_SMP + if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) + giveup_spe(current); + else + giveup_spe(NULL); /* just enable SPE for kernel - force */ +#else + giveup_spe(last_task_used_spe); +#endif /* __SMP __ */ +} +EXPORT_SYMBOL(enable_kernel_spe); +#endif /* CONFIG_SPE */ + void enable_kernel_fp(void) { @@ -244,6 +274,17 @@ if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))) giveup_altivec(prev); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + /* + * If the previous thread used spe in the last quantum + * (thus changing spe regs) then save them. + * + * On SMP we always save/restore spe regs just to avoid the + * complexity of changing processors. + */ + if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) + giveup_spe(prev); +#endif /* CONFIG_SPE */ #endif /* CONFIG_SMP */ /* Avoid the trap. On smp this this never happens since @@ -251,6 +292,13 @@ */ if (new->thread.regs && last_task_used_altivec == new) new->thread.regs->msr |= MSR_VEC; +#ifdef CONFIG_SPE + /* Avoid the trap. On smp this this never happens since + * we don't set last_task_used_spe + */ + if (new->thread.regs && last_task_used_spe == new) + new->thread.regs->msr |= MSR_SPE; +#endif /* CONFIG_SPE */ new_thread = &new->thread; old_thread = ¤t->thread; last = _switch(old_thread, new_thread); @@ -354,6 +402,10 @@ if (regs->msr & MSR_VEC) giveup_altivec(current); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + if (regs->msr & MSR_SPE) + giveup_spe(current); +#endif /* CONFIG_SPE */ preempt_enable(); } @@ -438,18 +490,45 @@ current->thread.vrsave = 0; current->thread.used_vr = 0; #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + memset(current->thread.evr, 0, sizeof(current->thread.evr)); + current->thread.acc = 0; + current->thread.spefscr = 0; + current->thread.used_spe = 0; +#endif /* CONFIG_SPE */ } +#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ + | PR_FP_EXC_RES | PR_FP_EXC_INV) + int set_fpexc_mode(struct task_struct *tsk, unsigned int val) { struct pt_regs *regs = tsk->thread.regs; - if (val > PR_FP_EXC_PRECISE) + /* This is a bit hairy. If we are an SPE enabled processor + * (have embedded fp) we store the IEEE exception enable flags in + * fpexc_mode. fpexc_mode is also used for setting FP exception + * mode (asyn, precise, disabled) for 'Classic' FP. */ + if (val & PR_FP_EXC_SW_ENABLE) { +#ifdef CONFIG_SPE + tsk->thread.fpexc_mode = val & + (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); +#else return -EINVAL; - tsk->thread.fpexc_mode = __pack_fe01(val); - if (regs != NULL && (regs->msr & MSR_FP) != 0) - regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) - | tsk->thread.fpexc_mode; +#endif + } else { + /* on a CONFIG_SPE this does not hurt us. The bits that + * __pack_fe01 use do not overlap with bits used for + * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits + * on CONFIG_SPE implementations are reserved so writing to + * them does not change anything */ + if (val > PR_FP_EXC_PRECISE) + return -EINVAL; + tsk->thread.fpexc_mode = __pack_fe01(val); + if (regs != NULL && (regs->msr & MSR_FP) != 0) + regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) + | tsk->thread.fpexc_mode; + } return 0; } @@ -457,7 +536,14 @@ { unsigned int val; - val = __unpack_fe01(tsk->thread.fpexc_mode); + if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) +#ifdef CONFIG_SPE + val = tsk->thread.fpexc_mode; +#else + return -EINVAL; +#endif + else + val = __unpack_fe01(tsk->thread.fpexc_mode); return put_user(val, (unsigned int *) adr); } @@ -506,6 +592,10 @@ if (regs->msr & MSR_VEC) giveup_altivec(current); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + if (regs->msr & MSR_SPE) + giveup_spe(current); +#endif /* CONFIG_SPE */ preempt_enable(); error = do_execve(filename, (char __user *__user *) a1, (char __user *__user *) a2, regs); diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c --- a/arch/ppc/kernel/ptrace.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/kernel/ptrace.c 2004-06-20 13:00:23 -07:00 @@ -35,7 +35,7 @@ /* * Set of msr bits that gdb can change on behalf of a process. */ -#ifdef CONFIG_4xx +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) #define MSR_DEBUGCHANGE 0 #else #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) @@ -131,13 +131,77 @@ } #endif +#ifdef CONFIG_SPE + +/* + * For get_evrregs/set_evrregs functions 'data' has the following layout: + * + * struct { + * u32 evr[32]; + * u64 acc; + * u32 spefscr; + * } + */ + +/* + * Get contents of SPE register state in task TASK. + */ +static inline int get_evrregs(unsigned long *data, struct task_struct *task) +{ + int i; + + if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long))) + return -EFAULT; + + /* copy SPEFSCR */ + if (__put_user(task->thread.spefscr, &data[34])) + return -EFAULT; + + /* copy SPE registers EVR[0] .. EVR[31] */ + for (i = 0; i < 32; i++, data++) + if (__put_user(task->thread.evr[i], data)) + return -EFAULT; + + /* copy ACC */ + if (__put_user64(task->thread.acc, (unsigned long long *)data)) + return -EFAULT; + + return 0; +} + +/* + * Write contents of SPE register state into task TASK. + */ +static inline int set_evrregs(struct task_struct *task, unsigned long *data) +{ + int i; + + if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long))) + return -EFAULT; + + /* copy SPEFSCR */ + if (__get_user(task->thread.spefscr, &data[34])) + return -EFAULT; + + /* copy SPE registers EVR[0] .. EVR[31] */ + for (i = 0; i < 32; i++, data++) + if (__get_user(task->thread.evr[i], data)) + return -EFAULT; + /* copy ACC */ + if (__get_user64(task->thread.acc, (unsigned long long*)data)) + return -EFAULT; + + return 0; +} +#endif /* CONFIG_SPE */ + static inline void set_single_step(struct task_struct *task) { struct pt_regs *regs = task->thread.regs; if (regs != NULL) { -#ifdef CONFIG_4xx +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; /* MSR.DE should already be set */ #else @@ -152,7 +216,7 @@ struct pt_regs *regs = task->thread.regs; if (regs != NULL) { -#ifdef CONFIG_4xx +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) task->thread.dbcr0 = 0; #else regs->msr &= ~MSR_SE; @@ -358,6 +422,23 @@ giveup_altivec(child); preempt_enable(); ret = set_vrregs(child, (unsigned long *)data); + break; +#endif +#ifdef CONFIG_SPE + case PTRACE_GETEVRREGS: + /* Get the child spe register state. */ + if (child->thread.regs->msr & MSR_SPE) + giveup_spe(child); + ret = get_evrregs((unsigned long *)data, child); + break; + + case PTRACE_SETEVRREGS: + /* Set the child spe register state. */ + /* this is to clear the MSR_SPE bit to force a reload + * of register state from memory */ + if (child->thread.regs->msr & MSR_SPE) + giveup_spe(child); + ret = set_evrregs(child, (unsigned long *)data); break; #endif diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c --- a/arch/ppc/kernel/signal.c 2004-06-20 13:00:26 -07:00 +++ b/arch/ppc/kernel/signal.c 2004-06-20 13:00:26 -07:00 @@ -183,8 +183,8 @@ /* * Save the current user registers on the user stack. - * We only save the altivec registers if the process has used - * altivec instructions at some point. + * We only save the altivec/spe registers if the process has used + * altivec/spe instructions at some point. */ static int save_user_regs(struct pt_regs *regs, struct mcontext *frame, int sigret) @@ -198,6 +198,10 @@ if (current->thread.used_vr && (regs->msr & MSR_VEC)) giveup_altivec(current); #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + if (current->thread.used_spe && (regs->msr & MSR_SPE)) + giveup_spe(current); +#endif /* CONFIG_ALTIVEC */ preempt_enable(); if (__copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE) @@ -229,6 +233,24 @@ return 1; #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + /* save spe registers */ + if (current->thread.used_spe) { + if (__copy_to_user(&frame->mc_vregs, current->thread.evr, + ELF_NEVRREG * sizeof(u32))) + return 1; + /* set MSR_SPE in the saved MSR value to indicate that + frame->mc_vregs contains valid data */ + if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR])) + return 1; + } + /* else assert((regs->msr & MSR_SPE) == 0) */ + + /* We always copy to/from spefscr */ + if (__put_user(current->thread.spefscr, (u32 *)&frame->mc_vregs + ELF_NEVRREG)) + return 1; +#endif /* CONFIG_SPE */ + if (sigret) { /* Set up the sigreturn trampoline: li r0,sigret; sc */ if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) @@ -249,7 +271,7 @@ restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig) { unsigned long save_r2; -#ifdef CONFIG_ALTIVEC +#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE) unsigned long msr; #endif @@ -289,6 +311,23 @@ if (__get_user(current->thread.vrsave, (u32 *)&sr->mc_vregs[32])) return 1; #endif /* CONFIG_ALTIVEC */ + +#ifdef CONFIG_SPE + /* force the process to reload the spe registers from + current->thread when it next does spe instructions */ + regs->msr &= ~MSR_SPE; + if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { + /* restore spe registers from the stack */ + if (__copy_from_user(current->thread.evr, &sr->mc_vregs, + sizeof(sr->mc_vregs))) + return 1; + } else if (current->thread.used_spe) + memset(¤t->thread.evr, 0, ELF_NEVRREG * sizeof(u32)); + + /* Always get SPEFSCR back */ + if (__get_user(current->thread.spefscr, (u32 *)&sr->mc_vregs + ELF_NEVRREG)) + return 1; +#endif /* CONFIG_SPE */ return 0; } diff -Nru a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c --- a/arch/ppc/kernel/traps.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/kernel/traps.c 2004-06-20 13:00:23 -07:00 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -171,6 +172,11 @@ /* On 4xx, the reason for the machine check or program exception is in the ESR. */ #define get_reason(regs) ((regs)->dsisr) +#ifndef CONFIG_E500 +#define get_mc_reason(regs) ((regs)->dsisr) +#else +#define get_mc_reason(regs) (mfspr(SPRN_MCSR)) +#endif #define REASON_FP 0 #define REASON_ILLEGAL ESR_PIL #define REASON_PRIVILEGED ESR_PPR @@ -184,6 +190,7 @@ /* On non-4xx, the reason for the machine check or program exception is in the MSR. */ #define get_reason(regs) ((regs)->msr) +#define get_mc_reason(regs) ((regs)->msr) #define REASON_FP 0x100000 #define REASON_ILLEGAL 0x80000 #define REASON_PRIVILEGED 0x40000 @@ -196,7 +203,7 @@ void MachineCheckException(struct pt_regs *regs) { - unsigned long reason = get_reason(regs); + unsigned long reason = get_mc_reason(regs); if (user_mode(regs)) { regs->msr |= MSR_RI; @@ -256,7 +263,37 @@ /* Clear MCSR */ mtspr(SPRN_MCSR, mcsr); } -#else /* !CONFIG_4xx */ +#elif defined (CONFIG_E500) + printk("Machine check in kernel mode.\n"); + printk("Caused by (from MCSR=%lx): ", reason); + + if (reason & MCSR_MCP) + printk("Machine Check Signal\n"); + if (reason & MCSR_ICPERR) + printk("Instruction Cache Parity Error\n"); + if (reason & MCSR_DCP_PERR) + printk("Data Cache Push Parity Error\n"); + if (reason & MCSR_DCPERR) + printk("Data Cache Parity Error\n"); + if (reason & MCSR_GL_CI) + printk("Guarded Load or Cache-Inhibited stwcx.\n"); + if (reason & MCSR_BUS_IAERR) + printk("Bus - Instruction Address Error\n"); + if (reason & MCSR_BUS_RAERR) + printk("Bus - Read Address Error\n"); + if (reason & MCSR_BUS_WAERR) + printk("Bus - Write Address Error\n"); + if (reason & MCSR_BUS_IBERR) + printk("Bus - Instruction Data Error\n"); + if (reason & MCSR_BUS_RBERR) + printk("Bus - Read Data Bus Error\n"); + if (reason & MCSR_BUS_WBERR) + printk("Bus - Read Data Bus Error\n"); + if (reason & MCSR_BUS_IPERR) + printk("Bus - Instruction Parity Error\n"); + if (reason & MCSR_BUS_RPERR) + printk("Bus - Read Parity Error\n"); +#else /* !CONFIG_4xx && !CONFIG_E500 */ printk("Machine check in kernel mode.\n"); printk("Caused by (from SRR1=%lx): ", reason); switch (reason & 0x601F0000) { @@ -682,6 +719,56 @@ } #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_FSL_BOOKE +void CacheLockingException(struct pt_regs *regs, unsigned long address, + unsigned long error_code) +{ + /* We treat cache locking instructions from the user + * as priv ops, in the future we could try to do + * something smarter + */ + if (error_code & (ESR_DLK|ESR_ILK)) + _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); + return; +} +#endif /* CONFIG_FSL_BOOKE */ + +#ifdef CONFIG_SPE +void +SPEFloatingPointException(struct pt_regs *regs) +{ + unsigned long spefscr; + int fpexc_mode; + int code = 0; + + spefscr = current->thread.spefscr; + fpexc_mode = current->thread.fpexc_mode; + + /* Hardware does not neccessarily set sticky + * underflow/overflow/invalid flags */ + if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) { + code = FPE_FLTOVF; + spefscr |= SPEFSCR_FOVFS; + } + else if ((spefscr & SPEFSCR_FUNF) && (fpexc_mode & PR_FP_EXC_UND)) { + code = FPE_FLTUND; + spefscr |= SPEFSCR_FUNFS; + } + else if ((spefscr & SPEFSCR_FDBZ) && (fpexc_mode & PR_FP_EXC_DIV)) + code = FPE_FLTDIV; + else if ((spefscr & SPEFSCR_FINV) && (fpexc_mode & PR_FP_EXC_INV)) { + code = FPE_FLTINV; + spefscr |= SPEFSCR_FINVS; + } + else if ((spefscr & (SPEFSCR_FG | SPEFSCR_FX)) && (fpexc_mode & PR_FP_EXC_RES)) + code = FPE_FLTRES; + + current->thread.spefscr = spefscr; + + _exception(SIGFPE, regs, code, regs->nip); + return; +} +#endif void __init trap_init(void) { diff -Nru a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile --- a/arch/ppc/mm/Makefile 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc/mm/Makefile 2004-06-20 13:00:25 -07:00 @@ -12,3 +12,4 @@ obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o obj-$(CONFIG_40x) += 4xx_mmu.o obj-$(CONFIG_44x) += 44x_mmu.o +obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c --- a/arch/ppc/mm/fault.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/mm/fault.c 2004-06-20 13:00:23 -07:00 @@ -99,7 +99,7 @@ struct mm_struct *mm = current->mm; siginfo_t info; int code = SEGV_MAPERR; -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE) int is_write = error_code & ESR_DST; #else int is_write = 0; @@ -114,20 +114,20 @@ error_code &= 0x48200000; else is_write = error_code & 0x02000000; -#endif /* CONFIG_4xx */ +#endif /* CONFIG_4xx || CONFIG_BOOKE */ #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) if (debugger_fault_handler && TRAP(regs) == 0x300) { debugger_fault_handler(regs); return 0; } -#if !defined(CONFIG_4xx) +#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) if (error_code & 0x00400000) { /* DABR match */ if (debugger_dabr_match(regs)) return 0; } -#endif /* !CONFIG_4xx */ +#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/ #endif /* CONFIG_XMON || CONFIG_KGDB */ if (in_atomic() || mm == NULL) @@ -200,8 +200,8 @@ if (is_write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; -#if defined(CONFIG_4xx) - /* an exec - 4xx allows for per-page execute permission */ +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) + /* an exec - 4xx/Book-E allows for per-page execute permission */ } else if (TRAP(regs) == 0x400) { pte_t *ptep; @@ -214,7 +214,7 @@ goto bad_area; #endif - /* Since 4xx supports per-page execute permission, + /* Since 4xx/Book-E supports per-page execute permission, * we lazily flush dcache to icache. */ ptep = NULL; if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) { diff -Nru a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/mm/fsl_booke_mmu.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,236 @@ +/* + * Modifications by Kumar Gala (kumar.gala@freescale.com) to support + * E500 Book E processors. + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This file contains the routines for initializing the MMU + * on the 4xx series of chips. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void loadcam_entry(unsigned int index); +unsigned int tlbcam_index; +unsigned int num_tlbcam_entries; +static unsigned long __cam0, __cam1, __cam2; +extern unsigned long total_lowmem; +extern unsigned long __max_low_memory; +#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE + +struct tlbcam { + u32 MAS0; + u32 MAS1; + u32 MAS2; + u32 MAS3; + u32 MAS7; +} TLBCAM[NUM_TLBCAMS]; + +struct tlbcamrange { + unsigned long start; + unsigned long limit; + phys_addr_t phys; +} tlbcam_addrs[NUM_TLBCAMS]; + +extern unsigned int tlbcam_index; + +/* + * Return PA for this VA if it is mapped by a CAM, or 0 + */ +unsigned long v_mapped_by_tlbcam(unsigned long va) +{ + int b; + for (b = 0; b < tlbcam_index; ++b) + if (va >= tlbcam_addrs[b].start && va < tlbcam_addrs[b].limit) + return tlbcam_addrs[b].phys + (va - tlbcam_addrs[b].start); + return 0; +} + +/* + * Return VA for a given PA or 0 if not mapped + */ +unsigned long p_mapped_by_tlbcam(unsigned long pa) +{ + int b; + for (b = 0; b < tlbcam_index; ++b) + if (pa >= tlbcam_addrs[b].phys + && pa < (tlbcam_addrs[b].limit-tlbcam_addrs[b].start) + +tlbcam_addrs[b].phys) + return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys); + return 0; +} + +/* + * Set up one of the I/D BAT (block address translation) register pairs. + * The parameters are not checked; in particular size must be a power + * of 4 between 4k and 256M. + */ +void settlbcam(int index, unsigned long virt, phys_addr_t phys, + unsigned int size, int flags, unsigned int pid) +{ + unsigned int tsize, lz; + + asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size)); + tsize = (21 - lz) / 2; + +#ifdef CONFIG_SMP + if ((flags & _PAGE_NO_CACHE) == 0) + flags |= _PAGE_COHERENT; +#endif + + TLBCAM[index].MAS0 = MAS0_TLBSEL | (index << 16); + TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | ((pid << 16) & MAS1_TID); + TLBCAM[index].MAS2 = virt & PAGE_MASK; + + TLBCAM[index].MAS2 |= (flags & _PAGE_WRITETHRU) ? MAS2_W : 0; + TLBCAM[index].MAS2 |= (flags & _PAGE_NO_CACHE) ? MAS2_I : 0; + TLBCAM[index].MAS2 |= (flags & _PAGE_COHERENT) ? MAS2_M : 0; + TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0; + TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0; + + TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR; + TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0); + +#ifndef CONFIG_KGDB /* want user access for breakpoints */ + if (flags & _PAGE_USER) { + TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; + TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); + } +#else + TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; + TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); +#endif + + tlbcam_addrs[index].start = virt; + tlbcam_addrs[index].limit = virt + size - 1; + tlbcam_addrs[index].phys = phys; + + loadcam_entry(index); +} + +void invalidate_tlbcam_entry(int index) +{ + TLBCAM[index].MAS0 = MAS0_TLBSEL | (index << 16); + TLBCAM[index].MAS1 = ~MAS1_VALID; + + loadcam_entry(index); +} + +void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1, + unsigned long cam2) +{ + settlbcam(0, KERNELBASE, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0); + tlbcam_index++; + if (cam1) { + tlbcam_index++; + settlbcam(1, KERNELBASE+cam0, PPC_MEMSTART+cam0, cam1, _PAGE_KERNEL, 0); + } + if (cam2) { + tlbcam_index++; + settlbcam(2, KERNELBASE+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2, _PAGE_KERNEL, 0); + } +} + +/* + * MMU_init_hw does the chip-specific initialization of the MMU hardware. + */ +void __init MMU_init_hw(void) +{ + flush_instruction_cache(); +} + +unsigned long __init mmu_mapin_ram(void) +{ + cam_mapin_ram(__cam0, __cam1, __cam2); + + return __cam0 + __cam1 + __cam2; +} + + +void __init +adjust_total_lowmem(void) +{ + unsigned long max_low_mem = MAX_LOW_MEM; + unsigned long cam_max = 0x10000000; + unsigned long ram; + + /* adjust CAM size to max_low_mem */ + if (max_low_mem < cam_max) + cam_max = max_low_mem; + + /* adjust lowmem size to max_low_mem */ + if (max_low_mem < total_lowmem) + ram = max_low_mem; + else + ram = total_lowmem; + + /* Calculate CAM values */ + __cam0 = 1UL << 2 * (__ilog2(ram) / 2); + if (__cam0 > cam_max) + __cam0 = cam_max; + ram -= __cam0; + if (ram) { + __cam1 = 1UL << 2 * (__ilog2(ram) / 2); + if (__cam1 > cam_max) + __cam1 = cam_max; + ram -= __cam1; + } + if (ram) { + __cam2 = 1UL << 2 * (__ilog2(ram) / 2); + if (__cam2 > cam_max) + __cam2 = cam_max; + ram -= __cam2; + } + + printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb," + " CAM2=%ldMb residual: %ldMb\n", + __cam0 >> 20, __cam1 >> 20, __cam2 >> 20, + (total_lowmem - __cam0 - __cam1 - __cam2) >> 20); + __max_low_memory = max_low_mem = __cam0 + __cam1 + __cam2; +} diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c --- a/arch/ppc/mm/init.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/mm/init.c 2004-06-20 13:00:23 -07:00 @@ -253,6 +253,12 @@ if (__max_memory && total_memory > __max_memory) total_memory = __max_memory; total_lowmem = total_memory; +#ifdef CONFIG_FSL_BOOKE + /* Freescale Book-E parts expect lowmem to be mapped by fixed TLB + * entries, so we need to adjust lowmem to match the amount we can map + * in the fixed entries */ + adjust_total_lowmem(); +#endif /* CONFIG_FSL_BOOKE */ if (total_lowmem > __max_low_memory) { total_lowmem = __max_low_memory; #ifndef CONFIG_HIGHMEM diff -Nru a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h --- a/arch/ppc/mm/mmu_decl.h 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc/mm/mmu_decl.h 2004-06-20 13:00:24 -07:00 @@ -27,6 +27,9 @@ extern void setbat(int index, unsigned long virt, unsigned long phys, unsigned int size, int flags); extern void reserve_phys_mem(unsigned long start, unsigned long size); +extern void settlbcam(int index, unsigned long virt, phys_addr_t phys, + unsigned int size, int flags, unsigned int pid); +extern void invalidate_tlbcam_entry(int index); extern int __map_without_bats; extern unsigned long ioremap_base; @@ -52,6 +55,12 @@ #define flush_HPTE(X, va, pg) _tlbie(va) extern void MMU_init_hw(void); extern unsigned long mmu_mapin_ram(void); + +#elif defined(CONFIG_FSL_BOOKE) +#define flush_HPTE(X, va, pg) _tlbie(va) +extern void MMU_init_hw(void); +extern unsigned long mmu_mapin_ram(void); +extern void adjust_total_lowmem(void); #else /* anything except 4xx or 8xx */ diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c --- a/arch/ppc/mm/pgtable.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/mm/pgtable.c 2004-06-20 13:00:23 -07:00 @@ -42,6 +42,10 @@ #define HAVE_BATS 1 #endif +#if defined(CONFIG_FSL_BOOKE) +#define HAVE_TLBCAM 1 +#endif + extern char etext[], _stext[]; #ifdef CONFIG_SMP @@ -59,6 +63,16 @@ #define p_mapped_by_bats(x) (0UL) #endif /* HAVE_BATS */ +#ifdef HAVE_TLBCAM +extern unsigned int tlbcam_index; +extern unsigned int num_tlbcam_entries; +extern unsigned long v_mapped_by_tlbcam(unsigned long va); +extern unsigned long p_mapped_by_tlbcam(unsigned long pa); +#else /* !HAVE_TLBCAM */ +#define v_mapped_by_tlbcam(x) (0UL) +#define p_mapped_by_tlbcam(x) (0UL) +#endif /* HAVE_TLBCAM */ + #ifdef CONFIG_44x /* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */ #define PGDIR_ORDER 1 @@ -210,6 +224,9 @@ if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ ) goto out; + if ((v = p_mapped_by_tlbcam(p))) + goto out; + if (mem_init_done) { struct vm_struct *area; area = get_vm_area(size, VM_IOREMAP); @@ -300,6 +317,9 @@ /* is x a power of 2? */ #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) +/* is x a power of 4? */ +#define is_power_of_4(x) ((x) != 0 && (((x) & (x-1)) == 0) && (ffs(x) & 1)) + /* * Set up a mapping for a block of I/O. * virt, phys, size must all be page-aligned. @@ -324,6 +344,18 @@ return; } #endif /* HAVE_BATS */ + +#ifdef HAVE_TLBCAM + /* + * Use a CAM for this if possible... + */ + if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size) + && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { + settlbcam(tlbcam_index, virt, phys, size, flags, 0); + ++tlbcam_index; + return; + } +#endif /* HAVE_TLBCAM */ /* No BATs available, put it in the page tables. */ for (i = 0; i < size; i += PAGE_SIZE) diff -Nru a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/Kconfig 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,44 @@ +config 85xx + bool + depends on E500 + default y + +config PPC_INDIRECT_PCI_BE + bool + depends on 85xx + default y + +menu "Freescale 85xx options" + depends on E500 + +choice + prompt "Machine Type" + depends on 85xx + default MPC8540_ADS + +config MPC8540_ADS + bool "MPC8540ADS" + help + This option enables support for the MPC 8540 ADS evaluation board. + +endchoice + +# It's often necessary to know the specific 85xx processor type. +# Fortunately, it is implied (so far) from the board type, so we +# don't need to ask more redundant questions. +config MPC8540 + bool + depends on MPC8540_ADS + default y + +config FSL_OCP + bool + depends on 85xx + default y + +config PPC_GEN550 + bool + depends on MPC8540 + default y + +endmenu diff -Nru a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/Makefile 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,7 @@ +# +# Makefile for the PowerPC 85xx linux kernel. +# + +obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads_common.o mpc8540_ads.o + +obj-$(CONFIG_MPC8540) += mpc8540.o diff -Nru a/arch/ppc/platforms/85xx/mpc8540.c b/arch/ppc/platforms/85xx/mpc8540.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/mpc8540.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,97 @@ +/* + * arch/ppc/platforms/85xx/mpc8540.c + * + * MPC8540 I/O descriptions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +/* These should be defined in platform code */ +extern struct ocp_gfar_data mpc85xx_tsec1_def; +extern struct ocp_gfar_data mpc85xx_tsec2_def; +extern struct ocp_gfar_data mpc85xx_fec_def; +extern struct ocp_mpc_i2c_data mpc85xx_i2c1_def; + +/* We use offsets for paddr since we do not know at compile time + * what CCSRBAR is, platform code should fix this up in + * setup_arch + * + * Only the first IRQ is given even if a device has + * multiple lines associated with ita + */ +struct ocp_def core_ocp[] = { + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = MPC85xx_IIC1_OFFSET, + .irq = MPC85xx_IRQ_IIC1, + .pm = OCP_CPM_NA, + .additions = &mpc85xx_i2c1_def, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_16550, + .index = 0, + .paddr = MPC85xx_UART0_OFFSET, + .irq = MPC85xx_IRQ_DUART, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_16550, + .index = 1, + .paddr = MPC85xx_UART1_OFFSET, + .irq = MPC85xx_IRQ_DUART, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_GFAR, + .index = 0, + .paddr = MPC85xx_ENET1_OFFSET, + .irq = MPC85xx_IRQ_TSEC1_TX, + .pm = OCP_CPM_NA, + .additions = &mpc85xx_tsec1_def, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_GFAR, + .index = 1, + .paddr = MPC85xx_ENET2_OFFSET, + .irq = MPC85xx_IRQ_TSEC2_TX, + .pm = OCP_CPM_NA, + .additions = &mpc85xx_tsec2_def, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_GFAR, + .index = 2, + .paddr = MPC85xx_ENET3_OFFSET, + .irq = MPC85xx_IRQ_FEC, + .pm = OCP_CPM_NA, + .additions = &mpc85xx_fec_def, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_DMA, + .index = 0, + .paddr = MPC85xx_DMA_OFFSET, + .irq = MPC85xx_IRQ_DMA0, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_PERFMON, + .index = 0, + .paddr = MPC85xx_PERFMON_OFFSET, + .irq = MPC85xx_IRQ_PERFMON, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_INVALID + } +}; diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,238 @@ +/* + * arch/ppc/platforms/85xx/mpc8540_ads.c + * + * MPC8540ADS board specific routines + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for linux/serial_core.h */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct ocp_gfar_data mpc85xx_tsec1_def = { + .interruptTransmit = MPC85xx_IRQ_TSEC1_TX, + .interruptError = MPC85xx_IRQ_TSEC1_ERROR, + .interruptReceive = MPC85xx_IRQ_TSEC1_RX, + .interruptPHY = MPC85xx_IRQ_EXT5, + .flags = (GFAR_HAS_GIGABIT | GFAR_HAS_MULTI_INTR + | GFAR_HAS_RMON + | GFAR_HAS_PHY_INTR | GFAR_HAS_COALESCE), + .phyid = 0, + .phyregidx = 0, +}; + +struct ocp_gfar_data mpc85xx_tsec2_def = { + .interruptTransmit = MPC85xx_IRQ_TSEC2_TX, + .interruptError = MPC85xx_IRQ_TSEC2_ERROR, + .interruptReceive = MPC85xx_IRQ_TSEC2_RX, + .interruptPHY = MPC85xx_IRQ_EXT5, + .flags = (GFAR_HAS_GIGABIT | GFAR_HAS_MULTI_INTR + | GFAR_HAS_RMON + | GFAR_HAS_PHY_INTR | GFAR_HAS_COALESCE), + .phyid = 1, + .phyregidx = 0, +}; + +struct ocp_gfar_data mpc85xx_fec_def = { + .interruptTransmit = MPC85xx_IRQ_FEC, + .interruptError = MPC85xx_IRQ_FEC, + .interruptReceive = MPC85xx_IRQ_FEC, + .interruptPHY = MPC85xx_IRQ_EXT5, + .flags = 0, + .phyid = 3, + .phyregidx = 0, +}; + +struct ocp_fs_i2c_data mpc85xx_i2c1_def = { + .flags = FS_I2C_SEPARATE_DFSRR, +}; + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init +mpc8540ads_setup_arch(void) +{ + struct ocp_def *def; + struct ocp_gfar_data *einfo; + bd_t *binfo = (bd_t *) __res; + unsigned int freq; + + /* get the core frequency */ + freq = binfo->bi_intfreq; + + if (ppc_md.progress) + ppc_md.progress("mpc8540ads_setup_arch()", 0); + + /* Set loops_per_jiffy to a half-way reasonable value, + for use until calibrate_delay gets called. */ + loops_per_jiffy = freq / HZ; + +#ifdef CONFIG_PCI + /* setup PCI host bridges */ + mpc85xx_setup_hose(); +#endif + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_SERIAL_8250 + mpc85xx_early_serial_map(); +#endif + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + /* Invalidate the entry we stole earlier the serial ports + * should be properly mapped */ + invalidate_tlbcam_entry(NUM_TLBCAMS - 1); +#endif + + def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 0); + if (def) { + einfo = (struct ocp_gfar_data *) def->additions; + memcpy(einfo->mac_addr, binfo->bi_enetaddr, 6); + } + + def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 1); + if (def) { + einfo = (struct ocp_gfar_data *) def->additions; + memcpy(einfo->mac_addr, binfo->bi_enet1addr, 6); + } + + def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 2); + if (def) { + einfo = (struct ocp_gfar_data *) def->additions; + memcpy(einfo->mac_addr, binfo->bi_enet2addr, 6); + } + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + + ocp_for_each_device(mpc85xx_update_paddr_ocp, &(binfo->bi_immr_base)); +} + +/* ************************************************************************ */ +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + /* parse_bootinfo must always be called first */ + parse_bootinfo(find_bootinfo()); + + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) { + memcpy((void *) __res, (void *) (r3 + KERNELBASE), + sizeof (bd_t)); + } +#ifdef CONFIG_SERIAL_TEXT_DEBUG + { + bd_t *binfo = (bd_t *) __res; + + /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */ + settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base, + binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); + } +#endif + +#if defined(CONFIG_BLK_DEV_INITRD) + /* + * If the init RAM disk has been configured in, and there's a valid + * starting address for it, set it up. + */ + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif /* CONFIG_BLK_DEV_INITRD */ + + /* Copy the kernel command line arguments to a safe place. */ + + if (r6) { + *(char *) (r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *) (r6 + KERNELBASE)); + } + + /* setup the PowerPC module struct */ + ppc_md.setup_arch = mpc8540ads_setup_arch; + ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo; + + ppc_md.init_IRQ = mpc85xx_ads_init_IRQ; + ppc_md.get_irq = openpic_get_irq; + + ppc_md.restart = mpc85xx_restart; + ppc_md.power_off = mpc85xx_power_off; + ppc_md.halt = mpc85xx_halt; + + ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; + + ppc_md.time_init = NULL; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; + ppc_md.calibrate_decr = mpc85xx_calibrate_decr; + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) + ppc_md.progress = gen550_progress; +#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ + + if (ppc_md.progress) + ppc_md.progress("mpc8540ads_init(): exit", 0); + + return; +} diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,30 @@ +/* + * arch/ppc/platforms/85xx/mpc8540_ads.h + * + * MPC8540ADS board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC8540ADS_H__ +#define __MACH_MPC8540ADS_H__ + +#include +#include +#include +#include +#include + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) + +#endif /* __MACH_MPC8540ADS_H__ */ diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,237 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx_ads_common.c + * + * MPC85xx ADS board common routines + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +extern unsigned long total_memory; /* in mm/init */ + +unsigned char __res[sizeof (bd_t)]; + +/* Internal interrupts are all Level Sensitive, and Positive Polarity */ + +static u_char mpc85xx_ads_openpic_initsenses[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ + 0x0, /* External 0: */ +#if defined(CONFIG_PCI) + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 3 */ +#else + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ + 0x0, /* External 4: */ +#endif + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ + 0x0, /* External 6: */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */ + 0x0, /* External 8: */ + 0x0, /* External 9: */ + 0x0, /* External 10: */ + 0x0, /* External 11: */ +}; + +/* ************************************************************************ */ +int +mpc85xx_ads_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + bd_t *binfo = (bd_t *) __res; + unsigned int freq; + + /* get the core frequency */ + freq = binfo->bi_intfreq; + + pvid = mfspr(PVR); + svid = mfspr(SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + + switch (svid & 0xffff0000) { + case SVR_8540: + seq_printf(m, "Machine\t\t: mpc8540ads\n"); + break; + case SVR_8560: + seq_printf(m, "Machine\t\t: mpc8560ads\n"); + break; + default: + seq_printf(m, "Machine\t\t: unknown\n"); + break; + } + seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000, + freq % 1000000); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + + /* Display cpu Pll setting */ + phid1 = mfspr(HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); + + return 0; +} + +void __init +mpc85xx_ads_init_IRQ(void) +{ + bd_t *binfo = (bd_t *) __res; + /* Determine the Physical Address of the OpenPIC regs */ + phys_addr_t OpenPIC_PAddr = + binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; + OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE); + OpenPIC_InitSenses = mpc85xx_ads_openpic_initsenses; + OpenPIC_NumInitSenses = sizeof (mpc85xx_ads_openpic_initsenses); + + /* Skip reserved space and internal sources */ + openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200); + /* Map PIC IRQs 0-11 */ + openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000); + + /* we let openpic interrupts starting from an offset, to + * leave space for cascading interrupts underneath. + */ + openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); + + return; +} + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ + +int +mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * This is little evil, but works around the fact + * that revA boards have IDSEL starting at 18 + * and others boards (older) start at 12 + * + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 2 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, + {PIRQC, PIRQD, PIRQA, PIRQB}, + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 5 */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 12 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, + {PIRQC, PIRQD, PIRQA, PIRQB}, + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 15 */ + {0, 0, 0, 0}, /* -- */ + {0, 0, 0, 0}, /* -- */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 18 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, + {PIRQC, PIRQD, PIRQA, PIRQB}, + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 21 */ + }; + + const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +int +mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +#endif /* CONFIG_PCI */ diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,50 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx_ads_common.h + * + * MPC85XX ADS common board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC85XX_ADS_H__ +#define __MACH_MPC85XX_ADS_H__ + +#include +#include +#include +#include + +#define BOARD_CCSRBAR ((uint)0xe0000000) +#define BCSR_ADDR ((uint)0xf8000000) +#define BCSR_SIZE ((uint)(32 * 1024)) + +extern int mpc85xx_ads_show_cpuinfo(struct seq_file *m); +extern void mpc85xx_ads_init_IRQ(void) __init; +extern void mpc85xx_ads_map_io(void) __init; + +/* PCI interrupt controller */ +#define PIRQA MPC85xx_IRQ_EXT1 +#define PIRQB MPC85xx_IRQ_EXT2 +#define PIRQC MPC85xx_IRQ_EXT3 +#define PIRQD MPC85xx_IRQ_EXT4 + +#define MPC85XX_PCI1_LOWER_IO 0x00000000 +#define MPC85XX_PCI1_UPPER_IO 0x00ffffff + +#define MPC85XX_PCI1_LOWER_MEM 0x80000000 +#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff + +#define MPC85XX_PCI1_IO_BASE 0xe2000000 +#define MPC85XX_PCI1_MEM_OFFSET 0x00000000 + +#define MPC85XX_PCI1_IO_SIZE 0x01000000 + +#endif /* __MACH_MPC85XX_ADS_H__ */ diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile --- a/arch/ppc/syslib/Makefile 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc/syslib/Makefile 2004-06-20 13:00:23 -07:00 @@ -8,6 +8,9 @@ ifdef CONFIG_4xx EXTRA_AFLAGS := -Wa,-m405 endif +ifdef CONFIG_E500 +EXTRA_AFLAGS := -Wa,-me500 +endif CFLAGS_prom_init.o += -fPIC CFLAGS_btext.o += -fPIC @@ -75,3 +78,7 @@ obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o indirect_pci.o obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_BOOKE) += dcr.o +obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o +ifeq ($(CONFIG_85xx),y) +obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o +endif diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c --- a/arch/ppc/syslib/open_pic.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc/syslib/open_pic.c 2004-06-20 13:00:24 -07:00 @@ -28,7 +28,7 @@ #include "open_pic_defs.h" -#ifdef CONFIG_PRPMC800 +#if defined(CONFIG_PRPMC800) || defined(CONFIG_85xx) #define OPENPIC_BIG_ENDIAN #endif diff -Nru a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/syslib/ppc85xx_common.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,46 @@ +/* + * arch/ppc/syslib/ppc85xx_common.c + * + * MPC85xx support routines + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* ************************************************************************ */ +/* Return the value of CCSRBAR for the current board */ + +phys_addr_t +get_ccsrbar(void) +{ + return BOARD_CCSRBAR; +} + +/* ************************************************************************ */ +/* Update the 85xx OCP tables paddr field */ +void +mpc85xx_update_paddr_ocp(struct ocp_device *dev, void *arg) +{ + phys_addr_t ccsrbar; + if (arg) { + ccsrbar = *(phys_addr_t *)arg; + dev->def->paddr += ccsrbar; + } +} + +EXPORT_SYMBOL(get_ccsrbar); diff -Nru a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/syslib/ppc85xx_common.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,29 @@ +/* + * arch/ppc/syslib/ppc85xx_common.h + * + * MPC85xx support routines + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __PPC_SYSLIB_PPC85XX_COMMON_H +#define __PPC_SYSLIB_PPC85XX_COMMON_H + +#include +#include +#include + +/* Provide access to ccsrbar for any modules, etc */ +phys_addr_t get_ccsrbar(void); + +/* Update the 85xx OCP tables paddr field */ +void mpc85xx_update_paddr_ocp(struct ocp_device *dev, void *ccsrbar); + +#endif /* __PPC_SYSLIB_PPC85XX_COMMON_H */ diff -Nru a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/syslib/ppc85xx_setup.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,341 @@ +/* + * arch/ppc/syslib/ppc85xx_setup.c + * + * MPC85XX common board code + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include /* for linux/serial_core.h */ +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Return the amount of memory */ +unsigned long __init +mpc85xx_find_end_of_memory(void) +{ + bd_t *binfo; + + binfo = (bd_t *) __res; + + return binfo->bi_memsize; +} + +/* The decrementer counts at the system (internal) clock freq divided by 8 */ +void __init +mpc85xx_calibrate_decr(void) +{ + bd_t *binfo = (bd_t *) __res; + unsigned int freq, divisor; + + /* get the core frequency */ + freq = binfo->bi_busfreq; + + /* The timebase is updated every 8 bus clocks, HID0[SEL_TBCLK] = 0 */ + divisor = 8; + tb_ticks_per_jiffy = freq / divisor / HZ; + tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000); + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + + /* Enable decrementer interrupt */ + mtspr(SPRN_TCR, TCR_DIE); +} + +#ifdef CONFIG_SERIAL_8250 +void __init +mpc85xx_early_serial_map(void) +{ + struct uart_port serial_req; + bd_t *binfo = (bd_t *) __res; + phys_addr_t duart_paddr = binfo->bi_immr_base + MPC85xx_UART0_OFFSET; + + /* Setup serial port access */ + memset(&serial_req, 0, sizeof (serial_req)); + serial_req.uartclk = binfo->bi_busfreq; + serial_req.line = 0; + serial_req.irq = MPC85xx_IRQ_DUART; + serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + serial_req.iotype = SERIAL_IO_MEM; + serial_req.membase = ioremap(duart_paddr, MPC85xx_UART0_SIZE); + serial_req.mapbase = duart_paddr; + serial_req.regshift = 0; + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + gen550_init(0, &serial_req); +#endif + + if (early_serial_setup(&serial_req) != 0) + printk("Early serial init of port 0 failed\n"); + + /* Assume early_serial_setup() doesn't modify serial_req */ + duart_paddr = binfo->bi_immr_base + MPC85xx_UART1_OFFSET; + serial_req.line = 1; + serial_req.mapbase = duart_paddr; + serial_req.membase = ioremap(duart_paddr, MPC85xx_UART1_SIZE); + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + gen550_init(1, &serial_req); +#endif + + if (early_serial_setup(&serial_req) != 0) + printk("Early serial init of port 1 failed\n"); +} +#endif + +void +mpc85xx_restart(char *cmd) +{ + local_irq_disable(); + abort(); +} + +void +mpc85xx_power_off(void) +{ + local_irq_disable(); + for(;;); +} + +void +mpc85xx_halt(void) +{ + local_irq_disable(); + for(;;); +} + +#ifdef CONFIG_PCI +static void __init +mpc85xx_setup_pci1(struct pci_controller *hose) +{ + volatile struct ccsr_pci *pci; + volatile struct ccsr_guts *guts; + unsigned short temps; + bd_t *binfo = (bd_t *) __res; + + pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI1_OFFSET, + MPC85xx_PCI1_SIZE); + + guts = ioremap(binfo->bi_immr_base + MPC85xx_GUTS_OFFSET, + MPC85xx_GUTS_SIZE); + + early_read_config_word(hose, 0, 0, PCI_COMMAND, &temps); + temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + early_write_config_word(hose, 0, 0, PCI_COMMAND, temps); + +#define PORDEVSR_PCI (0x00800000) /* PCI Mode */ + if (guts->pordevsr & PORDEVSR_PCI) { + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + } else { + /* PCI-X init */ + temps = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ + | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E; + early_write_config_word(hose, 0, 0, PCIX_COMMAND, temps); + } + + /* Disable all windows (except powar0 since its ignored) */ + pci->powar1 = 0; + pci->powar2 = 0; + pci->powar3 = 0; + pci->powar4 = 0; + pci->piwar1 = 0; + pci->piwar2 = 0; + pci->piwar3 = 0; + + /* Setup 512M Phys:PCI 1:1 outbound mem window @ 0x80000000 */ + pci->potar1 = (MPC85XX_PCI1_LOWER_MEM >> 12) & 0x000fffff; + pci->potear1 = 0x00000000; + pci->powbar1 = (MPC85XX_PCI1_LOWER_MEM >> 12) & 0x000fffff; + pci->powar1 = 0x8004401c; /* Enable, Mem R/W, 512M */ + + /* Setup 16M outboud IO windows @ 0xe2000000 */ + pci->potar2 = 0x00000000; + pci->potear2 = 0x00000000; + pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff; + pci->powar2 = 0x80088017; /* Enable, IO R/W, 16M */ + + /* Setup 2G inbound Memory Window @ 0 */ + pci->pitar1 = 0x00000000; + pci->piwbar1 = 0x00000000; + pci->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local + Mem, Snoop R/W, 2G */ +} + + +extern int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin); +extern int mpc85xx_exclude_device(u_char bus, u_char devfn); + +#if CONFIG_85xx_PCI2 +static void __init +mpc85xx_setup_pci2(struct pci_controller *hose) +{ + volatile struct ccsr_pci *pci; + unsigned short temps; + bd_t *binfo = (bd_t *) __res; + + pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI2_OFFSET, + MPC85xx_PCI2_SIZE); + + early_read_config_word(hose, 0, 0, PCI_COMMAND, &temps); + temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + early_write_config_word(hose, 0, 0, PCI_COMMAND, temps); + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + + /* Disable all windows (except powar0 since its ignored) */ + pci->powar1 = 0; + pci->powar2 = 0; + pci->powar3 = 0; + pci->powar4 = 0; + pci->piwar1 = 0; + pci->piwar2 = 0; + pci->piwar3 = 0; + + /* Setup 512M Phys:PCI 1:1 outbound mem window @ 0xa0000000 */ + pci->potar1 = (MPC85XX_PCI2_LOWER_MEM >> 12) & 0x000fffff; + pci->potear1 = 0x00000000; + pci->powbar1 = (MPC85XX_PCI2_LOWER_MEM >> 12) & 0x000fffff; + pci->powar1 = 0x8004401c; /* Enable, Mem R/W, 512M */ + + /* Setup 16M outboud IO windows @ 0xe3000000 */ + pci->potar2 = 0x00000000; + pci->potear2 = 0x00000000; + pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff; + pci->powar2 = 0x80088017; /* Enable, IO R/W, 16M */ + + /* Setup 2G inbound Memory Window @ 0 */ + pci->pitar1 = 0x00000000; + pci->piwbar1 = 0x00000000; + pci->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local + Mem, Snoop R/W, 2G */ +} +#endif /* CONFIG_85xx_PCI2 */ + +void __init +mpc85xx_setup_hose(void) +{ + struct pci_controller *hose_a; +#ifdef CONFIG_85xx_PCI2 + struct pci_controller *hose_b; +#endif + bd_t *binfo = (bd_t *) __res; + + hose_a = pcibios_alloc_controller(); + + if (!hose_a) + return; + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc85xx_map_irq; + + hose_a->first_busno = 0; + hose_a->bus_offset = 0; + hose_a->last_busno = 0xff; + + setup_indirect_pci(hose_a, binfo->bi_immr_base + PCI1_CFG_ADDR_OFFSET, + binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET); + hose_a->set_cfg_type = 1; + + mpc85xx_setup_pci1(hose_a); + + hose_a->pci_mem_offset = MPC85XX_PCI1_MEM_OFFSET; + hose_a->mem_space.start = MPC85XX_PCI1_LOWER_MEM; + hose_a->mem_space.end = MPC85XX_PCI1_UPPER_MEM; + + hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO; + hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO; + hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE; +#if CONFIG_85xx_PCI2 + isa_io_base = + (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE, + MPC85XX_PCI1_IO_SIZE + + MPC85XX_PCI2_IO_SIZE); +#else + isa_io_base = + (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE, + MPC85XX_PCI1_IO_SIZE); +#endif + hose_a->io_base_virt = (void *) isa_io_base; + + /* setup resources */ + pci_init_resource(&hose_a->mem_resources[0], + MPC85XX_PCI1_LOWER_MEM, + MPC85XX_PCI1_UPPER_MEM, + IORESOURCE_MEM, "PCI1 host bridge"); + + pci_init_resource(&hose_a->io_resource, + MPC85XX_PCI1_LOWER_IO, + MPC85XX_PCI1_UPPER_IO, + IORESOURCE_IO, "PCI1 host bridge"); + + ppc_md.pci_exclude_device = mpc85xx_exclude_device; + + hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno); + +#if CONFIG_85xx_PCI2 + hose_b = pcibios_alloc_controller(); + + if (!hose_b) + return; + + hose_b->bus_offset = hose_a->last_busno + 1; + hose_b->first_busno = hose_a->last_busno + 1; + hose_b->last_busno = 0xff; + + setup_indirect_pci(hose_b, binfo->bi_immr_base + PCI2_CFG_ADDR_OFFSET, + binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET); + hose_b->set_cfg_type = 1; + + mpc85xx_setup_pci2(hose_b); + + hose_b->pci_mem_offset = MPC85XX_PCI2_MEM_OFFSET; + hose_b->mem_space.start = MPC85XX_PCI2_LOWER_MEM; + hose_b->mem_space.end = MPC85XX_PCI2_UPPER_MEM; + + hose_b->io_space.start = MPC85XX_PCI2_LOWER_IO; + hose_b->io_space.end = MPC85XX_PCI2_UPPER_IO; + hose_b->io_base_phys = MPC85XX_PCI2_IO_BASE; + hose_b->io_base_virt = (void *) isa_io_base + MPC85XX_PCI1_IO_SIZE; + + /* setup resources */ + pci_init_resource(&hose_b->mem_resources[0], + MPC85XX_PCI2_LOWER_MEM, + MPC85XX_PCI2_UPPER_MEM, + IORESOURCE_MEM, "PCI2 host bridge"); + + pci_init_resource(&hose_b->io_resource, + MPC85XX_PCI2_LOWER_IO, + MPC85XX_PCI2_UPPER_IO, + IORESOURCE_IO, "PCI2 host bridge"); + + hose_b->last_busno = pciauto_bus_scan(hose_b, hose_b->first_busno); +#endif + return; +} +#endif /* CONFIG_PCI */ + + diff -Nru a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/syslib/ppc85xx_setup.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,67 @@ +/* + * arch/ppc/syslib/ppc85xx_setup.h + * + * MPC85XX common board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __PPC_SYSLIB_PPC85XX_SETUP_H +#define __PPC_SYSLIB_PPC85XX_SETUP_H + +#include +#include +#include +#include + +extern unsigned long mpc85xx_find_end_of_memory(void) __init; +extern void mpc85xx_calibrate_decr(void) __init; +extern void mpc85xx_early_serial_map(void) __init; +extern void mpc85xx_restart(char *cmd); +extern void mpc85xx_power_off(void); +extern void mpc85xx_halt(void); +extern void mpc85xx_setup_hose(void) __init; + +/* PCI config */ +#define PCI1_CFG_ADDR_OFFSET (0x8000) +#define PCI1_CFG_DATA_OFFSET (0x8004) + +#define PCI2_CFG_ADDR_OFFSET (0x9000) +#define PCI2_CFG_DATA_OFFSET (0x9004) + +/* Additional register for PCI-X configuration */ +#define PCIX_NEXT_CAP 0x60 +#define PCIX_CAP_ID 0x61 +#define PCIX_COMMAND 0x62 +#define PCIX_STATUS 0x64 + +/* Serial Config */ +#define MPC85XX_0_SERIAL (CCSRBAR + 0x4500) +#define MPC85XX_1_SERIAL (CCSRBAR + 0x4600) + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define RS_TABLE_SIZE 64 +#else +#define RS_TABLE_SIZE 2 +#endif + +#define BASE_BAUD 0 + +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, num, MPC85xx_IRQ_DUART, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: (u8 *)MPC85XX_##num##_SERIAL, \ + io_type: SERIAL_IO_MEM}, + +/* Offset of CPM register space */ +#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) + +#endif /* __PPC_SYSLIB_PPC85XX_SETUP_H */ diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/Kconfig 2004-06-20 13:00:24 -07:00 @@ -198,7 +198,6 @@ config PREEMPT bool "Preemptible Kernel" - depends on BROKEN help This option reduces the latency of the kernel when reacting to real-time or interactive events by allowing a low priority process to diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c 2004-06-20 13:00:26 -07:00 +++ b/arch/ppc64/kernel/align.c 2004-06-20 13:00:26 -07:00 @@ -22,8 +22,6 @@ #include #include -void disable_kernel_fp(void); /* asm function from head.S */ - struct aligninfo { unsigned char len; unsigned char flags; @@ -280,8 +278,11 @@ } /* Force the fprs into the save area so we can reference them */ - if ((flags & F) && (regs->msr & MSR_FP)) - giveup_fpu(current); + if (flags & F) { + if (!user_mode(regs)) + return 0; + flush_fp_to_thread(current); + } /* If we are loading, get the data from user space */ if (flags & LD) { @@ -310,9 +311,11 @@ if (flags & F) { if (nb == 4) { /* Doing stfs, have to convert to single */ + preempt_disable(); enable_kernel_fp(); cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr); disable_kernel_fp(); + preempt_enable(); } else data.dd = current->thread.fpr[reg]; @@ -344,9 +347,11 @@ if (flags & F) { if (nb == 4) { /* Doing lfs, have to convert to double */ + preempt_disable(); enable_kernel_fp(); cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr); disable_kernel_fp(); + preempt_enable(); } else current->thread.fpr[reg] = data.dd; diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c --- a/arch/ppc64/kernel/asm-offsets.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/asm-offsets.c 2004-06-20 13:00:25 -07:00 @@ -48,6 +48,8 @@ DEFINE(THREAD_SHIFT, THREAD_SHIFT); DEFINE(THREAD_SIZE, THREAD_SIZE); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); + DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); /* task_struct->thread */ DEFINE(THREAD, offsetof(struct task_struct, thread)); @@ -99,7 +101,10 @@ DEFINE(PACALPPACA, offsetof(struct paca_struct, xLpPaca)); DEFINE(LPPACA, offsetof(struct paca_struct, xLpPaca)); DEFINE(PACAREGSAV, offsetof(struct paca_struct, xRegSav)); - DEFINE(PACAEXC, offsetof(struct paca_struct, exception_stack)); + DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); + DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); + DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); + DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); DEFINE(PACAGUARD, offsetof(struct paca_struct, guard)); DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0)); DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1)); @@ -136,6 +141,10 @@ DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7])); DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8])); DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9])); + DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10])); + DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11])); + DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12])); + DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13])); DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20])); DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21])); DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22])); @@ -154,7 +163,7 @@ DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); - DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); + DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc64/kernel/entry.S 2004-06-20 13:00:23 -07:00 @@ -35,15 +35,9 @@ #define DO_SOFT_DISABLE #endif -#undef SHOW_SYSCALLS -#undef SHOW_SYSCALLS_TASK - -#ifdef SHOW_SYSCALLS_TASK - .data -show_syscalls_task: - .long -1 -#endif - +/* + * System calls. + */ .section ".toc","aw" .SYS_CALL_TABLE: .tc .sys_call_table[TC],.sys_call_table @@ -51,107 +45,175 @@ .SYS_CALL_TABLE32: .tc .sys_call_table32[TC],.sys_call_table32 +/* This value is used to mark exception frames on the stack. */ +exception_marker: + .tc ID_72656773_68657265[TC],0x7265677368657265 + .section ".text" - .align 3 + .align 7 -/* - * Handle a system call. - */ -_GLOBAL(DoSyscall) +#undef SHOW_SYSCALLS + + .globl SystemCall_common +SystemCall_common: + andi. r10,r12,MSR_PR + mr r10,r1 + addi r1,r1,-INT_FRAME_SIZE + beq- 1f + ld r1,PACAKSAVE(r13) +1: std r10,0(r1) + std r11,_NIP(r1) + std r12,_MSR(r1) + std r0,GPR0(r1) + std r10,GPR1(r1) + std r2,GPR2(r1) + std r3,GPR3(r1) + std r4,GPR4(r1) + std r5,GPR5(r1) + std r6,GPR6(r1) + std r7,GPR7(r1) + std r8,GPR8(r1) + li r11,0 + std r11,GPR9(r1) + std r11,GPR10(r1) + std r11,GPR11(r1) + std r11,GPR12(r1) + std r9,GPR13(r1) + crclr so + mfcr r9 + mflr r10 + li r11,0xc01 + std r9,_CCR(r1) + std r10,_LINK(r1) + std r11,_TRAP(r1) + mfxer r9 + mfctr r10 + std r9,_XER(r1) + std r10,_CTR(r1) std r3,ORIG_GPR3(r1) - ld r11,_CCR(r1) /* Clear SO bit in CR */ - lis r10,0x1000 - andc r11,r11,r10 - std r11,_CCR(r1) + ld r2,PACATOC(r13) + addi r9,r1,STACK_FRAME_OVERHEAD + ld r11,exception_marker@toc(r2) + std r11,-16(r9) /* "regshere" marker */ +#ifdef CONFIG_PPC_ISERIES + /* Hack for handling interrupts when soft-enabling on iSeries */ + cmpdi cr1,r0,0x5555 /* syscall 0x5555 */ + andi. r10,r12,MSR_PR /* from kernel */ + crand 4*cr0+eq,4*cr1+eq,4*cr0+eq + beq HardwareInterrupt_entry + lbz r10,PACAPROCENABLED(r13) + std r10,SOFTE(r1) +#endif + mfmsr r11 + ori r11,r11,MSR_EE + mtmsrd r11,1 + #ifdef SHOW_SYSCALLS -#ifdef SHOW_SYSCALLS_TASK - LOADBASE(r31,show_syscalls_task) - ld r31,show_syscalls_task@l(r31) - ld r10,PACACURRENT(r13) - cmp 0,r10,r31 - bne 1f + bl .do_show_syscall + REST_GPR(0,r1) + REST_4GPRS(3,r1) + REST_2GPRS(7,r1) + addi r9,r1,STACK_FRAME_OVERHEAD #endif - LOADADDR(r3,7f) - ld r4,GPR0(r1) - ld r5,GPR3(r1) - ld r6,GPR4(r1) - ld r7,GPR5(r1) - ld r8,GPR6(r1) - ld r9,GPR7(r1) - bl .printk - LOADADDR(r3,77f) - ld r4,GPR8(r1) - ld r5,GPR9(r1) - ld r6, PACACURRENT(r13) - bl .printk - ld r0,GPR0(r1) - ld r3,GPR3(r1) - ld r4,GPR4(r1) - ld r5,GPR5(r1) - ld r6,GPR6(r1) - ld r7,GPR7(r1) - ld r8,GPR8(r1) -1: -#endif /* SHOW_SYSCALLS */ - clrrdi r10,r1,THREAD_SHIFT - ld r10,TI_FLAGS(r10) + clrrdi r11,r1,THREAD_SHIFT + li r12,0 + ld r10,TI_FLAGS(r11) + stb r12,TI_SC_NOERR(r11) andi. r11,r10,_TIF_SYSCALL_T_OR_A - bne- 50f + bne- syscall_dotrace +syscall_dotrace_cont: cmpli 0,r0,NR_syscalls - bge- 66f + bge- syscall_enosys + +system_call: /* label this so stack traces look sane */ /* * Need to vector to 32 Bit or default sys_call_table here, * based on caller's run-mode / personality. */ - andi. r11,r10,_TIF_32BIT + ld r11,.SYS_CALL_TABLE@toc(2) + andi. r10,r10,_TIF_32BIT beq- 15f - ld r10,.SYS_CALL_TABLE32@toc(2) -/* - * We now zero extend all six arguments (r3 - r8), the compatibility - * layer assumes this. - */ + ld r11,.SYS_CALL_TABLE32@toc(2) clrldi r3,r3,32 clrldi r4,r4,32 clrldi r5,r5,32 clrldi r6,r6,32 clrldi r7,r7,32 clrldi r8,r8,32 - b 17f 15: - ld r10,.SYS_CALL_TABLE@toc(2) -17: slwi r0,r0,3 - ldx r10,r10,r0 /* Fetch system call handler [ptr] */ + slwi r0,r0,3 + ldx r10,r11,r0 /* Fetch system call handler [ptr] */ mtlr r10 - addi r9,r1,STACK_FRAME_OVERHEAD blrl /* Call handler */ -_GLOBAL(ret_from_syscall_1) - std r3,RESULT(r1) /* Save result */ + +syscall_exit: #ifdef SHOW_SYSCALLS -#ifdef SHOW_SYSCALLS_TASK - ld r10, PACACURRENT(13) - cmp 0,r10,r31 - bne 91f -#endif - mr r4,r3 - LOADADDR(r3,79f) - bl .printk - ld r3,RESULT(r1) -91: + std r3,GPR3(r1) + bl .do_show_syscall_exit + ld r3,GPR3(r1) #endif + std r3,RESULT(r1) + ld r5,_CCR(r1) li r10,-_LAST_ERRNO - cmpld 0,r3,r10 - blt 30f + cmpld r3,r10 + clrrdi r12,r1,THREAD_SHIFT + bge- syscall_error +syscall_error_cont: + + /* check for syscall tracing or audit */ + ld r9,TI_FLAGS(r12) + andi. r0,r9,_TIF_SYSCALL_T_OR_A + bne- syscall_exit_trace +syscall_exit_trace_cont: + + /* disable interrupts so current_thread_info()->flags can't change, + and so that we don't get interrupted after loading SRR0/1. */ + ld r8,_MSR(r1) + andi. r10,r8,MSR_RI + beq- unrecov_restore + mfmsr r10 + rldicl r10,r10,48,1 + rotldi r10,r10,16 + mtmsrd r10,1 + ld r9,TI_FLAGS(r12) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED) + bne- syscall_exit_work + ld r7,_NIP(r1) + stdcx. r0,0,r1 /* to clear the reservation */ + andi. r6,r8,MSR_PR + ld r4,_LINK(r1) + beq 1f /* only restore r13 if */ + ld r13,GPR13(r1) /* returning to usermode */ +1: ld r2,GPR2(r1) + ld r1,GPR1(r1) + li r12,MSR_RI + andc r10,r10,r12 + mtmsrd r10,1 /* clear MSR.RI */ + mtlr r4 + mtcr r5 + mtspr SRR0,r7 + mtspr SRR1,r8 + rfid + +syscall_enosys: + li r3,-ENOSYS + std r3,RESULT(r1) + clrrdi r12,r1,THREAD_SHIFT + ld r5,_CCR(r1) + +syscall_error: + lbz r11,TI_SC_NOERR(r12) + cmpi 0,r11,0 + bne- syscall_error_cont neg r3,r3 -22: ld r10,_CCR(r1) /* Set SO bit in CR */ - oris r10,r10,0x1000 - std r10,_CCR(r1) -30: std r3,GPR3(r1) /* Update return value */ - b .ret_from_except -66: li r3,ENOSYS - b 22b + oris r5,r5,0x1000 /* Set SO bit in CR */ + std r5,_CCR(r1) + b syscall_error_cont /* Traced system call support */ -50: addi r3,r1,STACK_FRAME_OVERHEAD +syscall_dotrace: + bl .save_nvgprs + addi r3,r1,STACK_FRAME_OVERHEAD bl .do_syscall_trace_enter ld r0,GPR0(r1) /* Restore original registers */ ld r3,GPR3(r1) @@ -160,65 +222,82 @@ ld r6,GPR6(r1) ld r7,GPR7(r1) ld r8,GPR8(r1) - /* XXX check this - Anton */ - ld r9,GPR9(r1) - cmpli 0,r0,NR_syscalls - bge- 66f -/* - * Need to vector to 32 Bit or default sys_call_table here, - * based on caller's run-mode / personality. - */ + addi r9,r1,STACK_FRAME_OVERHEAD clrrdi r10,r1,THREAD_SHIFT ld r10,TI_FLAGS(r10) - andi. r11,r10,_TIF_32BIT - beq- 55f - ld r10,.SYS_CALL_TABLE32@toc(2) + b syscall_dotrace_cont + +syscall_exit_trace: + std r3,GPR3(r1) + bl .save_nvgprs + bl .do_syscall_trace_leave + REST_NVGPRS(r1) + ld r3,GPR3(r1) + ld r5,_CCR(r1) + clrrdi r12,r1,THREAD_SHIFT + b syscall_exit_trace_cont + +/* Stuff to do on exit from a system call. */ +syscall_exit_work: + std r3,GPR3(r1) + std r5,_CCR(r1) + b .ret_from_except_lite + +/* Save non-volatile GPRs, if not already saved. */ +_GLOBAL(save_nvgprs) + ld r11,_TRAP(r1) + andi. r0,r11,1 + beqlr- + SAVE_NVGPRS(r1) + clrrdi r0,r11,1 + std r0,_TRAP(r1) + blr + /* - * We now zero extend all six arguments (r3 - r8), the compatibility - * layer assumes this. + * The sigsuspend and rt_sigsuspend system calls can call do_signal + * and thus put the process into the stopped state where we might + * want to examine its user state with ptrace. Therefore we need + * to save all the nonvolatile registers (r14 - r31) before calling + * the C code. Similarly, fork, vfork and clone need the full + * register state on the stack so that it can be copied to the child. */ - clrldi r3,r3,32 - clrldi r4,r4,32 - clrldi r5,r5,32 - clrldi r6,r6,32 - clrldi r7,r7,32 - clrldi r8,r8,32 - b 57f -55: - ld r10,.SYS_CALL_TABLE@toc(2) -57: - slwi r0,r0,3 - ldx r10,r10,r0 /* Fetch system call handler [ptr] */ - mtlr r10 - addi r9,r1,STACK_FRAME_OVERHEAD - blrl /* Call handler */ -_GLOBAL(ret_from_syscall_2) - std r3,RESULT(r1) /* Save result */ - li r10,-_LAST_ERRNO - cmpld 0,r3,r10 - blt 60f - neg r3,r3 -57: ld r10,_CCR(r1) /* Set SO bit in CR */ - oris r10,r10,0x1000 - std r10,_CCR(r1) -60: std r3,GPR3(r1) /* Update return value */ - bl .do_syscall_trace_leave - b .ret_from_except -66: li r3,ENOSYS - b 57b -#ifdef SHOW_SYSCALLS -7: .string "syscall %d(%x, %x, %x, %x, %x, " -77: .string "%x, %x), current=%p\n" -79: .string " -> %x\n" - .align 2,0 -#endif +_GLOBAL(ppc32_sigsuspend) + bl .save_nvgprs + bl .sys32_sigsuspend + b syscall_exit + +_GLOBAL(ppc64_rt_sigsuspend) + bl .save_nvgprs + bl .sys_rt_sigsuspend + b syscall_exit + +_GLOBAL(ppc32_rt_sigsuspend) + bl .save_nvgprs + bl .sys32_rt_sigsuspend + b syscall_exit + +_GLOBAL(ppc_fork) + bl .save_nvgprs + bl .sys_fork + b syscall_exit + +_GLOBAL(ppc_vfork) + bl .save_nvgprs + bl .sys_vfork + b syscall_exit + +_GLOBAL(ppc_clone) + bl .save_nvgprs + bl .sys_clone + b syscall_exit - _GLOBAL(ppc32_swapcontext) + bl .save_nvgprs bl .sys32_swapcontext b 80f _GLOBAL(ppc64_swapcontext) + bl .save_nvgprs bl .sys_swapcontext b 80f @@ -233,17 +312,20 @@ _GLOBAL(ppc64_rt_sigreturn) bl .sys_rt_sigreturn -80: clrrdi r4,r1,THREAD_SHIFT +80: cmpdi 0,r3,0 + blt syscall_exit + clrrdi r4,r1,THREAD_SHIFT ld r4,TI_FLAGS(r4) andi. r4,r4,_TIF_SYSCALL_T_OR_A - bne- 81f - cmpi 0,r3,0 - bge .ret_from_except - b .ret_from_syscall_1 -81: cmpi 0,r3,0 - blt .ret_from_syscall_2 + beq+ 81f bl .do_syscall_trace_leave - b .ret_from_except +81: b .ret_from_except + +_GLOBAL(ret_from_fork) + bl .schedule_tail + REST_NVGPRS(r1) + li r3,0 + b syscall_exit /* * This routine switches between two different tasks. The process @@ -263,6 +345,7 @@ * The code which creates the new task context is in 'copy_thread' * in arch/ppc64/kernel/process.c */ + .align 7 _GLOBAL(_switch) mflr r0 std r0,16(r1) @@ -315,7 +398,10 @@ 2: END_FTR_SECTION_IFSET(CPU_FTR_SLB) clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ - addi r7,r7,THREAD_SIZE-INT_FRAME_SIZE + /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE + because we don't need to leave the 288-byte ABI gap at the + top of the kernel stack. */ + addi r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE mr r1,r8 /* start using new stack pointer */ std r7,PACAKSAVE(r13) @@ -350,60 +436,56 @@ addi r1,r1,SWITCH_FRAME_SIZE blr -_GLOBAL(ret_from_fork) - bl .schedule_tail - clrrdi r4,r1,THREAD_SHIFT - ld r4,TI_FLAGS(r4) - andi. r4,r4,_TIF_SYSCALL_T_OR_A - beq+ .ret_from_except - bl .do_syscall_trace_leave - b .ret_from_except - + .align 7 _GLOBAL(ret_from_except) + ld r11,_TRAP(r1) + andi. r0,r11,1 + bne .ret_from_except_lite + REST_NVGPRS(r1) + +_GLOBAL(ret_from_except_lite) /* * Disable interrupts so that current_thread_info()->flags * can't change between when we test it and when we return * from the interrupt. */ mfmsr r10 /* Get current interrupt state */ - li r4,0 - ori r4,r4,MSR_EE - andc r9,r10,r4 /* clear MSR_EE */ + rldicl r9,r10,48,1 /* clear MSR_EE */ + rotldi r9,r9,16 mtmsrd r9,1 /* Update machine state */ +#ifdef CONFIG_PREEMPT + clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */ + li r0,_TIF_NEED_RESCHED /* bits to check */ + ld r3,_MSR(r1) + ld r4,TI_FLAGS(r9) + /* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */ + rlwimi r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING + and. r0,r4,r0 /* check NEED_RESCHED and maybe SIGPENDING */ + bne do_work + +#else /* !CONFIG_PREEMPT */ ld r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR beq restore /* if not, just restore regs and return */ /* Check current_thread_info()->flags */ - clrrdi r3,r1,THREAD_SHIFT - ld r3,TI_FLAGS(r3) - andi. r0,r3,_TIF_USER_WORK_MASK + clrrdi r9,r1,THREAD_SHIFT + ld r4,TI_FLAGS(r9) + andi. r0,r4,_TIF_USER_WORK_MASK bne do_work - - addi r0,r1,INT_FRAME_SIZE /* size of frame */ - ld r4,PACACURRENT(r13) - std r0,THREAD+KSP(r4) /* save kernel stack pointer */ - - /* - * r13 is our per cpu area, only restore it if we are returning to - * userspace - */ - REST_GPR(13,r1) +#endif restore: #ifdef CONFIG_PPC_ISERIES ld r5,SOFTE(r1) - mfspr r4,SPRG3 /* get paca address */ cmpdi 0,r5,0 beq 4f /* Check for pending interrupts (iSeries) */ - /* this is CHECKANYINT except that we already have the paca address */ - ld r3,PACALPPACA+LPPACAANYINT(r4) + ld r3,PACALPPACA+LPPACAANYINT(r13) cmpdi r3,0 beq+ 4f /* skip do_IRQ if no interrupts */ - mfspr r13,SPRG3 /* get paca pointer back */ li r3,0 stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ mtmsrd r10 /* hard-enable again */ @@ -411,13 +493,22 @@ bl .do_IRQ b .ret_from_except /* loop back and handle more */ -4: stb r5,PACAPROCENABLED(r4) +4: stb r5,PACAPROCENABLED(r13) #endif ld r3,_MSR(r1) - andi. r3,r3,MSR_RI + andi. r0,r3,MSR_RI beq- unrecov_restore + andi. r0,r3,MSR_PR + + /* + * r13 is our per cpu area, only restore it if we are returning to + * userspace + */ + beq 1f + REST_GPR(13, r1) +1: ld r3,_CTR(r1) ld r0,_LINK(r1) mtctr r3 @@ -426,8 +517,6 @@ mtspr XER,r3 REST_8GPRS(5, r1) - REST_10GPRS(14, r1) - REST_8GPRS(24, r1) stdcx. r0,0,r1 /* to clear the reservation */ @@ -451,26 +540,62 @@ ld r1,GPR1(r1) rfid + b . -/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ +/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: +#ifdef CONFIG_PREEMPT + andi. r0,r3,MSR_PR /* Returning to user mode? */ + bne user_work + /* Check that preempt_count() == 0 and interrupts are enabled */ + lwz r8,TI_PREEMPT(r9) + cmpwi cr1,r8,0 +#ifdef CONFIG_PPC_ISERIES + ld r0,SOFTE(r1) + cmpdi r0,0 +#else + andi. r0,r3,MSR_EE +#endif + crandc eq,cr1*4+eq,eq + bne restore + /* here we are preempting the current task */ +1: lis r0,PREEMPT_ACTIVE@h + stw r0,TI_PREEMPT(r9) +#ifdef CONFIG_PPC_ISERIES + li r0,1 + stb r0,PACAPROCENABLED(r13) +#endif + mtmsrd r10,1 /* reenable interrupts */ + bl .schedule + mfmsr r10 + clrrdi r9,r1,THREAD_SHIFT + rldicl r10,r10,48,1 /* disable interrupts again */ + li r0,0 + rotldi r10,r10,16 + mtmsrd r10,1 + ld r4,TI_FLAGS(r9) + andi. r0,r4,_TIF_NEED_RESCHED + bne 1b + stw r0,TI_PREEMPT(r9) + b restore + +user_work: +#endif /* Enable interrupts */ mtmsrd r10,1 - andi. r0,r3,_TIF_NEED_RESCHED + andi. r0,r4,_TIF_NEED_RESCHED beq 1f bl .schedule - b .ret_from_except + b .ret_from_except_lite -1: andi. r0,r3,_TIF_SIGPENDING - beq .ret_from_except +1: bl .save_nvgprs li r3,0 addi r4,r1,STACK_FRAME_OVERHEAD bl .do_signal b .ret_from_except unrecov_restore: - mfspr r13,SPRG3 addi r3,r1,STACK_FRAME_OVERHEAD bl .unrecoverable_exception b unrecov_restore @@ -488,7 +613,7 @@ mflr r0 std r0,16(r1) stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */ - + /* Because RTAS is running in 32b mode, it clobbers the high order half * of all registers that it saves. We therefore save those registers * RTAS might touch to the stack. (r0, r3-r13 are caller saved) diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/kernel/head.S 2004-06-20 13:00:24 -07:00 @@ -40,15 +40,6 @@ #define DO_SOFT_DISABLE #endif -/* copy saved SOFTE bit or EE bit from saved MSR depending - * if we are doing soft-disable or not - */ -#ifdef DO_SOFT_DISABLE -#define DO_COPY_EE() ld r20,SOFTE(r1) -#else -#define DO_COPY_EE() rldicl r20,r23,49,63 -#endif - /* * hcall interface to pSeries LPAR */ @@ -177,11 +168,18 @@ #endif #endif +/* This value is used to mark exception frames on the stack. */ + .section ".toc","aw" +exception_marker: + .tc ID_72656773_68657265[TC],0x7265677368657265 + .text + /* * The following macros define the code that appears as * the prologue to each of the exception handlers. They * are split into two parts to allow a single kernel binary - * to be used for pSeries, and iSeries. + * to be used for pSeries and iSeries. + * LOL. One day... - paulus */ /* @@ -194,81 +192,55 @@ * This is the start of the interrupt handlers for pSeries * This code runs with relocation off. */ -#define EX_SRR0 0 -#define EX_SRR1 8 -#define EX_R20 16 -#define EX_R21 24 -#define EX_R22 32 -#define EX_R23 40 +#define EX_R9 0 +#define EX_R10 8 +#define EX_R11 16 +#define EX_R12 24 +#define EX_R13 32 +#define EX_SRR0 40 #define EX_DAR 48 #define EX_DSISR 56 #define EX_CCR 60 -#define EX_TRAP 60 -#define EXCEPTION_PROLOG_PSERIES(n,label) \ - mtspr SPRG2,r20; /* use SPRG2 as scratch reg */ \ - mtspr SPRG1,r21; /* save r21 */ \ - mfspr r20,SPRG3; /* get paca virt addr */ \ - ld r21,PACAEXCSP(r20); /* get exception stack ptr */ \ - addi r21,r21,EXC_FRAME_SIZE; /* make exception frame */ \ - std r22,EX_R22(r21); /* Save r22 in exc. frame */ \ - li r22,n; /* Save the ex # in exc. frame*/ \ - stw r22,EX_TRAP(r21); /* */ \ - std r23,EX_R23(r21); /* Save r23 in exc. frame */ \ - mfspr r22,SRR0; /* EA of interrupted instr */ \ - std r22,EX_SRR0(r21); /* Save SRR0 in exc. frame */ \ - mfspr r23,SRR1; /* machine state at interrupt */ \ - std r23,EX_SRR1(r21); /* Save SRR1 in exc. frame */ \ - \ - mfspr r23,DAR; /* Save DAR in exc. frame */ \ - std r23,EX_DAR(r21); \ - mfspr r23,DSISR; /* Save DSISR in exc. frame */ \ - stw r23,EX_DSISR(r21); \ - mfspr r23,SPRG2; /* Save r20 in exc. frame */ \ - std r23,EX_R20(r21); \ - \ - clrrdi r22,r20,60; /* Get 0xc part of the vaddr */ \ - ori r22,r22,(label)@l; /* add in the vaddr offset */ \ - /* assumes *_common < 16b */ \ - mfmsr r23; \ - rotldi r23,r23,4; \ - ori r23,r23,0x32B; /* Set IR, DR, RI, SF, ISF, HV*/ \ - rotldi r23,r23,60; /* for generic handlers */ \ - mtspr SRR0,r22; \ - mtspr SRR1,r23; \ - mfcr r23; /* save CR in r23 */ \ +#define EXCEPTION_PROLOG_PSERIES(area, label) \ + mfspr r13,SPRG3; /* get paca address into r13 */ \ + std r9,area+EX_R9(r13); /* save r9 - r12 */ \ + std r10,area+EX_R10(r13); \ + std r11,area+EX_R11(r13); \ + std r12,area+EX_R12(r13); \ + mfspr r9,SPRG1; \ + std r9,area+EX_R13(r13); \ + mfcr r9; \ + clrrdi r12,r13,32; /* get high part of &label */ \ + mfmsr r10; \ + mfspr r11,SRR0; /* save SRR0 */ \ + ori r12,r12,(label)@l; /* virt addr of handler */ \ + ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ + mtspr SRR0,r12; \ + mfspr r12,SRR1; /* and SRR1 */ \ + mtspr SRR1,r10; \ rfid /* * This is the start of the interrupt handlers for iSeries * This code runs with relocation on. */ -#define EXCEPTION_PROLOG_ISERIES(n) \ - mtspr SPRG2,r20; /* use SPRG2 as scratch reg */ \ - mtspr SPRG1,r21; /* save r21 */ \ - mfspr r20,SPRG3; /* get paca */ \ - ld r21,PACAEXCSP(r20); /* get exception stack ptr */ \ - addi r21,r21,EXC_FRAME_SIZE; /* make exception frame */ \ - std r22,EX_R22(r21); /* save r22 on exception frame */ \ - li r22,n; /* Save the ex # in exc. frame */ \ - stw r22,EX_TRAP(r21); /* */ \ - std r23,EX_R23(r21); /* Save r23 in exc. frame */ \ - ld r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */ \ - std r22,EX_SRR0(r21); /* save SRR0 in exc. frame */ \ - ld r23,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */ \ - std r23,EX_SRR1(r21); /* save SRR1 in exc. frame */ \ - \ - mfspr r23,DAR; /* Save DAR in exc. frame */ \ - std r23,EX_DAR(r21); \ - mfspr r23,DSISR; /* Save DSISR in exc. frame */ \ - stw r23,EX_DSISR(r21); \ - mfspr r23,SPRG2; /* Save r20 in exc. frame */ \ - std r23,EX_R20(r21); \ - \ - mfmsr r22; /* set MSR.RI */ \ - ori r22,r22,MSR_RI; \ - mtmsrd r22,1; \ - mfcr r23; /* save CR in r23 */ +#define EXCEPTION_PROLOG_ISERIES_1(area) \ + mfspr r13,SPRG3; /* get paca address into r13 */ \ + std r9,area+EX_R9(r13); /* save r9 - r12 */ \ + std r10,area+EX_R10(r13); \ + std r11,area+EX_R11(r13); \ + std r12,area+EX_R12(r13); \ + mfspr r9,SPRG1; \ + std r9,area+EX_R13(r13); \ + mfcr r9 + +#define EXCEPTION_PROLOG_ISERIES_2 \ + mfmsr r10; \ + ld r11,LPPACA+LPPACASRR0(r13); \ + ld r12,LPPACA+LPPACASRR1(r13); \ + ori r10,r10,MSR_RI; \ + mtmsrd r10,1 /* * The common exception prolog is used for all except a few exceptions @@ -276,107 +248,154 @@ * to take another exception from the point where we first touch the * kernel stack onwards. * - * On entry r20 points to the paca and r21 points to the exception - * frame on entry, r23 contains the saved CR, and relocation is on. - */ -#define EXCEPTION_PROLOG_COMMON \ - mfspr r22,SPRG1; /* Save r21 in exc. frame */ \ - std r22,EX_R21(r21); \ - std r21,PACAEXCSP(r20); /* update exception stack ptr */ \ - ld r22,EX_SRR1(r21); /* Get SRR1 from exc. frame */ \ - andi. r22,r22,MSR_PR; /* Set CR for later branch */ \ - mr r22,r1; /* Save r1 */ \ - subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ - beq- 1f; \ - ld r1,PACAKSAVE(r20); /* kernel stack to use */ \ -1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ - bge cr1,bad_stack; /* abort if it is */ \ - std r22,GPR1(r1); /* save r1 in stackframe */ \ - std r22,0(r1); /* make stack chain pointer */ \ - std r23,_CCR(r1); /* save CR in stackframe */ \ - ld r22,EX_R20(r21); /* move r20 to stackframe */ \ - std r22,GPR20(r1); \ - ld r23,EX_R21(r21); /* move r21 to stackframe */ \ - std r23,GPR21(r1); \ - ld r22,EX_R22(r21); /* move r22 to stackframe */ \ - std r22,GPR22(r1); \ - ld r23,EX_R23(r21); /* move r23 to stackframe */ \ - std r23,GPR23(r1); \ - mflr r22; /* save LR in stackframe */ \ - std r22,_LINK(r1); \ - mfctr r23; /* save CTR in stackframe */ \ - std r23,_CTR(r1); \ - mfspr r22,XER; /* save XER in stackframe */ \ - std r22,_XER(r1); \ - ld r23,EX_DAR(r21); /* move DAR to stackframe */ \ - std r23,_DAR(r1); \ - lwz r22,EX_DSISR(r21); /* move DSISR to stackframe */ \ - std r22,_DSISR(r1); \ - lbz r22,PACAPROCENABLED(r20); \ - std r22,SOFTE(r1); \ - ld r22,EX_SRR0(r21); /* get SRR0 from exc. frame */ \ - ld r23,EX_SRR1(r21); /* get SRR1 from exc. frame */ \ - addi r21,r21,-EXC_FRAME_SIZE;/* pop off exception frame */ \ - std r21,PACAEXCSP(r20); \ - SAVE_GPR(0, r1); /* save r0 in stackframe */ \ - SAVE_8GPRS(2, r1); /* save r2 - r13 in stackframe */ \ - SAVE_4GPRS(10, r1); \ - ld r2,PACATOC(r20); \ - mr r13,r20 - -/* - * Note: code which follows this uses cr0.eq (set if from kernel), - * r1, r22 (SRR0), and r23 (SRR1). - */ + * On entry r13 points to the paca, r9-r13 are saved in the paca, + * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and + * SRR1, and relocation is on. + */ +#define EXCEPTION_PROLOG_COMMON(n, area) \ + andi. r10,r12,MSR_PR; /* See if coming from user */ \ + mr r10,r1; /* Save r1 */ \ + subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ + beq- 1f; \ + ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ +1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ + bge- cr1,bad_stack; /* abort if it is */ \ + std r9,_CCR(r1); /* save CR in stackframe */ \ + std r11,_NIP(r1); /* save SRR0 in stackframe */ \ + std r12,_MSR(r1); /* save SRR1 in stackframe */ \ + std r10,0(r1); /* make stack chain pointer */ \ + std r0,GPR0(r1); /* save r0 in stackframe */ \ + std r10,GPR1(r1); /* save r1 in stackframe */ \ + std r2,GPR2(r1); /* save r2 in stackframe */ \ + SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ + SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ + ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ + ld r10,area+EX_R10(r13); \ + std r9,GPR9(r1); \ + std r10,GPR10(r1); \ + ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ + ld r10,area+EX_R12(r13); \ + ld r11,area+EX_R13(r13); \ + std r9,GPR11(r1); \ + std r10,GPR12(r1); \ + std r11,GPR13(r1); \ + ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ + mflr r9; /* save LR in stackframe */ \ + std r9,_LINK(r1); \ + mfctr r10; /* save CTR in stackframe */ \ + std r10,_CTR(r1); \ + mfspr r11,XER; /* save XER in stackframe */ \ + std r11,_XER(r1); \ + li r9,(n)+1; \ + std r9,_TRAP(r1); /* set trap number */ \ + li r10,0; \ + ld r11,exception_marker@toc(r2); \ + std r10,RESULT(r1); /* clear regs->result */ \ + std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ /* * Exception vectors. */ -#define STD_EXCEPTION_PSERIES(n, label ) \ - . = n; \ - .globl label##_Pseries; \ -label##_Pseries: \ - EXCEPTION_PROLOG_PSERIES( n, label##_common ) - -#define STD_EXCEPTION_ISERIES( n, label ) \ - .globl label##_Iseries; \ -label##_Iseries: \ - EXCEPTION_PROLOG_ISERIES( n ); \ +#define STD_EXCEPTION_PSERIES(n, label ) \ + . = n; \ + .globl label##_Pseries; \ +label##_Pseries: \ + mtspr SPRG1,r13; /* save r13 */ \ + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) + +#define STD_EXCEPTION_ISERIES(n, label, area) \ + .globl label##_Iseries; \ +label##_Iseries: \ + mtspr SPRG1,r13; /* save r13 */ \ + EXCEPTION_PROLOG_ISERIES_1(area); \ + EXCEPTION_PROLOG_ISERIES_2; \ b label##_common -#define MASKABLE_EXCEPTION_ISERIES( n, label ) \ - .globl label##_Iseries; \ -label##_Iseries: \ - EXCEPTION_PROLOG_ISERIES( n ); \ - lbz r22,PACAPROFENABLED(r20); \ - cmpi 0,r22,0; \ - bne- label##_Iseries_profile; \ -label##_Iseries_prof_ret: \ - lbz r22,PACAPROCENABLED(r20); \ - cmpi 0,r22,0; \ - beq- label##_Iseries_masked; \ - b label##_common; \ -label##_Iseries_profile: \ - std r24,48(r21); \ - std r25,56(r21); \ - mflr r24; \ - bl do_profile; \ - mtlr r24; \ - ld r24,48(r21); \ - ld r25,56(r21); \ +#define MASKABLE_EXCEPTION_ISERIES( n, label ) \ + .globl label##_Iseries; \ +label##_Iseries: \ + mtspr SPRG1,r13; /* save r13 */ \ + EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ + lbz r10,PACAPROFENABLED(r13); \ + cmpwi r10,0; \ + bne- label##_Iseries_profile; \ +label##_Iseries_prof_ret: \ + lbz r10,PACAPROCENABLED(r13); \ + cmpwi 0,r10,0; \ + beq- label##_Iseries_masked; \ + EXCEPTION_PROLOG_ISERIES_2; \ + b label##_common; \ +label##_Iseries_profile: \ + ld r12,LPPACA+LPPACASRR1(r13); \ + andi. r12,r12,MSR_PR; /* Test if in kernel */ \ + bne label##_Iseries_prof_ret; \ + ld r11,LPPACA+LPPACASRR0(r13); \ + ld r12,PACAPROFSTEXT(r13); /* _stext */ \ + subf r11,r12,r11; /* offset into kernel */ \ + lwz r12,PACAPROFSHIFT(r13); \ + srd r11,r11,r12; \ + lwz r12,PACAPROFLEN(r13); /* profile table length - 1 */ \ + cmpd r11,r12; /* off end? */ \ + ble 1f; \ + mr r11,r12; /* force into last entry */ \ +1: sldi r11,r11,2; /* convert to offset */ \ + ld r12,PACAPROFBUFFER(r13);/* profile buffer */ \ + add r12,r12,r11; \ +2: lwarx r11,0,r12; /* atomically increment */ \ + addi r11,r11,1; \ + stwcx. r11,0,r12; \ + bne- 2b; \ b label##_Iseries_prof_ret +#ifdef DO_SOFT_DISABLE +#define DISABLE_INTS \ + lbz r10,PACAPROCENABLED(r13); \ + li r11,0; \ + std r10,SOFTE(r1); \ + mfmsr r10; \ + stb r11,PACAPROCENABLED(r13); \ + ori r10,r10,MSR_EE; \ + mtmsrd r10,1 + +#define ENABLE_INTS \ + lbz r10,PACAPROCENABLED(r13); \ + mfmsr r11; \ + std r10,SOFTE(r1); \ + ori r11,r11,MSR_EE; \ + mtmsrd r11,1 + +#else /* hard enable/disable interrupts */ +#define DISABLE_INTS + +#define ENABLE_INTS \ + ld r12,_MSR(r1); \ + mfmsr r11; \ + rlwimi r11,r12,0,MSR_EE; \ + mtmsrd r11,1 + +#endif + #define STD_EXCEPTION_COMMON( trap, label, hdlr ) \ - .globl label##_common; \ -label##_common: \ - EXCEPTION_PROLOG_COMMON; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r20,0; \ - li r6,trap; \ - bl .save_remaining_regs; \ - bl hdlr; \ + .align 7; \ + .globl label##_common; \ +label##_common: \ + EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ + DISABLE_INTS; \ + bl .save_nvgprs; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + bl hdlr; \ b .ret_from_except +#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \ + .align 7; \ + .globl label##_common; \ +label##_common: \ + EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ + DISABLE_INTS; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + bl hdlr; \ + b .ret_from_except_lite + /* * Start of pSeries system interrupt routines */ @@ -385,9 +404,45 @@ __start_interrupts: STD_EXCEPTION_PSERIES( 0x100, SystemReset ) - STD_EXCEPTION_PSERIES( 0x200, MachineCheck ) - STD_EXCEPTION_PSERIES( 0x300, DataAccess ) - STD_EXCEPTION_PSERIES( 0x380, DataAccessSLB ) + + . = 0x200 + .globl MachineCheck_Pseries +_MachineCheckPseries: + mtspr SPRG1,r13 /* save r13 */ + EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common) + + . = 0x300 + .globl DataAccess_Pseries +DataAccess_Pseries: + mtspr SPRG1,r13 +BEGIN_FTR_SECTION + mtspr SPRG2,r12 + mfspr r13,DAR + mfspr r12,DSISR + srdi r13,r13,60 + rlwimi r13,r12,16,0x20 + mfcr r12 + cmpwi r13,0x2c + beq .do_stab_bolted_Pseries + mtcrf 0x80,r12 + mfspr r12,SPRG2 +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, DataAccess_common) + + . = 0x380 + .globl DataAccessSLB_Pseries +DataAccessSLB_Pseries: + mtspr SPRG1,r13 + mtspr SPRG2,r12 + mfspr r13,DAR + mfcr r12 + srdi r13,r13,60 + cmpdi r13,0xc + beq .do_slb_bolted_Pseries + mtcrf 0x80,r12 + mfspr r12,SPRG2 + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, DataAccessSLB_common) + STD_EXCEPTION_PSERIES( 0x400, InstructionAccess ) STD_EXCEPTION_PSERIES( 0x480, InstructionAccessSLB ) STD_EXCEPTION_PSERIES( 0x500, HardwareInterrupt ) @@ -397,7 +452,23 @@ STD_EXCEPTION_PSERIES( 0x900, Decrementer ) STD_EXCEPTION_PSERIES( 0xa00, Trap_0a ) STD_EXCEPTION_PSERIES( 0xb00, Trap_0b ) - STD_EXCEPTION_PSERIES( 0xc00, SystemCall ) + + . = 0xc00 + .globl SystemCall_Pseries +SystemCall_Pseries: + mr r9,r13 + mfmsr r10 + mfspr r13,SPRG3 + mfspr r11,SRR0 + clrrdi r12,r13,32 + oris r12,r12,SystemCall_common@h + ori r12,r12,SystemCall_common@l + mtspr SRR0,r12 + ori r10,r10,MSR_IR|MSR_DR|MSR_RI + mfspr r12,SRR1 + mtspr SRR1,r10 + rfid + STD_EXCEPTION_PSERIES( 0xd00, SingleStep ) STD_EXCEPTION_PSERIES( 0xe00, Trap_0e ) @@ -407,25 +478,26 @@ * trickery is thus necessary */ . = 0xf00 - b .PerformanceMonitor_Pseries - . = 0xf20 - b .AltivecUnavailable_Pseries + b PerformanceMonitor_Pseries + + STD_EXCEPTION_PSERIES(0xf20, AltivecUnavailable) STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint ) STD_EXCEPTION_PSERIES( 0x1700, AltivecAssist ) - /* Here are the "moved" performance monitor and - * altivec unavailable exceptions - */ - . = 0x3000 - .globl PerformanceMonitor_Pseries; -.PerformanceMonitor_Pseries: - EXCEPTION_PROLOG_PSERIES(0xf00, PerformanceMonitor_common) + /* moved from 0xf00 */ + STD_EXCEPTION_PSERIES(0x3000, PerformanceMonitor) . = 0x3100 - .globl AltivecUnavailable_Pseries; -.AltivecUnavailable_Pseries: - EXCEPTION_PROLOG_PSERIES(0xf20, AltivecUnavailable_common) +_GLOBAL(do_stab_bolted_Pseries) + mtcrf 0x80,r12 + mfspr r12,SPRG2 + EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) + +_GLOBAL(do_slb_bolted_Pseries) + mtcrf 0x80,r12 + mfspr r12,SPRG2 + EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_slb_bolted) /* Space for the naca. Architected to be located at real address @@ -484,31 +556,82 @@ /*** ISeries-LPAR interrupt handlers ***/ - STD_EXCEPTION_ISERIES( 0x200, MachineCheck ) - STD_EXCEPTION_ISERIES( 0x300, DataAccess ) - STD_EXCEPTION_ISERIES( 0x380, DataAccessSLB ) - STD_EXCEPTION_ISERIES( 0x400, InstructionAccess ) - STD_EXCEPTION_ISERIES( 0x480, InstructionAccessSLB ) - MASKABLE_EXCEPTION_ISERIES( 0x500, HardwareInterrupt ) - STD_EXCEPTION_ISERIES( 0x600, Alignment ) - STD_EXCEPTION_ISERIES( 0x700, ProgramCheck ) - STD_EXCEPTION_ISERIES( 0x800, FPUnavailable ) - MASKABLE_EXCEPTION_ISERIES( 0x900, Decrementer ) - STD_EXCEPTION_ISERIES( 0xa00, Trap_0a ) - STD_EXCEPTION_ISERIES( 0xb00, Trap_0b ) - STD_EXCEPTION_ISERIES( 0xc00, SystemCall ) - STD_EXCEPTION_ISERIES( 0xd00, SingleStep ) - STD_EXCEPTION_ISERIES( 0xe00, Trap_0e ) - STD_EXCEPTION_ISERIES( 0xf00, PerformanceMonitor ) + STD_EXCEPTION_ISERIES(0x200, MachineCheck, PACA_EXMC) + + .globl DataAccess_Iseries +DataAccess_Iseries: + mtspr SPRG1,r13 +BEGIN_FTR_SECTION + mtspr SPRG2,r12 + mfspr r13,DAR + mfspr r12,DSISR + srdi r13,r13,60 + rlwimi r13,r12,16,0x20 + mfcr r12 + cmpwi r13,0x2c + beq .do_stab_bolted_Iseries + mtcrf 0x80,r12 + mfspr r12,SPRG2 +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) + EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN) + EXCEPTION_PROLOG_ISERIES_2 + b DataAccess_common + +.do_stab_bolted_Iseries: + mtcrf 0x80,r12 + mfspr r12,SPRG2 + EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + EXCEPTION_PROLOG_ISERIES_2 + b .do_stab_bolted + + .globl DataAccessSLB_Iseries +DataAccessSLB_Iseries: + mtspr SPRG1,r13 /* save r13 */ + mtspr SPRG2,r12 + mfspr r13,DAR + mfcr r12 + srdi r13,r13,60 + cmpdi r13,0xc + beq .do_slb_bolted_Iseries + mtcrf 0x80,r12 + mfspr r12,SPRG2 + EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN) + EXCEPTION_PROLOG_ISERIES_2 + b DataAccessSLB_common + +.do_slb_bolted_Iseries: + mtcrf 0x80,r12 + mfspr r12,SPRG2 + EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + EXCEPTION_PROLOG_ISERIES_2 + b .do_slb_bolted + + STD_EXCEPTION_ISERIES(0x400, InstructionAccess, PACA_EXGEN) + STD_EXCEPTION_ISERIES(0x480, InstructionAccessSLB, PACA_EXGEN) + MASKABLE_EXCEPTION_ISERIES(0x500, HardwareInterrupt) + STD_EXCEPTION_ISERIES(0x600, Alignment, PACA_EXGEN) + STD_EXCEPTION_ISERIES(0x700, ProgramCheck, PACA_EXGEN) + STD_EXCEPTION_ISERIES(0x800, FPUnavailable, PACA_EXGEN) + MASKABLE_EXCEPTION_ISERIES(0x900, Decrementer) + STD_EXCEPTION_ISERIES(0xa00, Trap_0a, PACA_EXGEN) + STD_EXCEPTION_ISERIES(0xb00, Trap_0b, PACA_EXGEN) + + .globl SystemCall_Iseries +SystemCall_Iseries: + mr r9,r13 + mfspr r13,SPRG3 + EXCEPTION_PROLOG_ISERIES_2 + b SystemCall_common + + STD_EXCEPTION_ISERIES( 0xd00, SingleStep, PACA_EXGEN) + STD_EXCEPTION_ISERIES( 0xe00, Trap_0e, PACA_EXGEN) + STD_EXCEPTION_ISERIES( 0xf00, PerformanceMonitor, PACA_EXGEN) .globl SystemReset_Iseries SystemReset_Iseries: mfspr r13,SPRG3 /* Get paca address */ - mfmsr r24 - ori r24,r24,MSR_RI - mtmsrd r24 /* RI on */ lhz r24,PACAPACAINDEX(r13) /* Get processor # */ - cmpi 0,r24,0 /* Are we processor 0? */ + cmpwi 0,r24,0 /* Are we processor 0? */ beq .__start_initialization_iSeries /* Start up the first processor */ mfspr r4,CTRLF li r5,RUNLATCH /* Turn off the run light */ @@ -527,7 +650,7 @@ addi r1,r3,THREAD_SIZE subi r1,r1,STACK_FRAME_OVERHEAD - cmpi 0,r23,0 + cmpwi 0,r23,0 beq iseries_secondary_smp_loop /* Loop until told to go */ #ifdef SECONDARY_PROCESSORS bne .__secondary_start /* Loop until told to go */ @@ -552,28 +675,29 @@ b 1b /* If SMP not configured, secondaries * loop forever */ - .globl HardwareInterrupt_Iseries_masked -HardwareInterrupt_Iseries_masked: - b maskable_exception_exit - .globl Decrementer_Iseries_masked Decrementer_Iseries_masked: - li r22,1 - stb r22,PACALPPACA+LPPACADECRINT(r20) - lwz r22,PACADEFAULTDECR(r20) - mtspr DEC,r22 -maskable_exception_exit: - mtcrf 0xff,r23 /* Restore regs and free exception frame */ - ld r22,EX_SRR0(r21) - ld r23,EX_SRR1(r21) - mtspr SRR0,r22 - mtspr SRR1,r23 - ld r22,EX_R22(r21) - ld r23,EX_R23(r21) - mfspr r21,SPRG1 - mfspr r20,SPRG2 + li r11,1 + stb r11,PACALPPACA+LPPACADECRINT(r13) + lwz r12,PACADEFAULTDECR(r13) + mtspr DEC,r12 + /* fall through */ + + .globl HardwareInterrupt_Iseries_masked +HardwareInterrupt_Iseries_masked: + mtcrf 0x80,r9 /* Restore regs */ + ld r11,LPPACA+LPPACASRR0(r13) + ld r12,LPPACA+LPPACASRR1(r13) + mtspr SRR0,r11 + mtspr SRR1,r12 + ld r9,PACA_EXGEN+EX_R9(r13) + ld r10,PACA_EXGEN+EX_R10(r13) + ld r11,PACA_EXGEN+EX_R11(r13) + ld r12,PACA_EXGEN+EX_R12(r13) + ld r13,PACA_EXGEN+EX_R13(r13) rfid #endif + /* * Data area reserved for FWNMI option. */ @@ -587,10 +711,12 @@ . = 0x8000 .globl SystemReset_FWNMI SystemReset_FWNMI: - EXCEPTION_PROLOG_PSERIES(0x100, SystemReset_common) + mtspr SPRG1,r13 /* save r13 */ + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, SystemReset_common) .globl MachineCheck_FWNMI MachineCheck_FWNMI: - EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common) + mtspr SPRG1,r13 /* save r13 */ + EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common) /* * Space for the initial segment table @@ -609,8 +735,22 @@ /*** Common interrupt handlers ***/ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) - STD_EXCEPTION_COMMON( 0x200, MachineCheck, .MachineCheckException ) - STD_EXCEPTION_COMMON( 0x900, Decrementer, .timer_interrupt ) + + /* + * Machine check is different because we use a different + * save area: PACA_EXMC instead of PACA_EXGEN. + */ + .align 7 + .globl MachineCheck_common +MachineCheck_common: + EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) + DISABLE_INTS + bl .save_nvgprs + addi r3,r1,STACK_FRAME_OVERHEAD + bl .MachineCheckException + b .ret_from_except + + STD_EXCEPTION_COMMON_LITE(0x900, Decrementer, .timer_interrupt) STD_EXCEPTION_COMMON( 0xa00, Trap_0a, .UnknownException ) STD_EXCEPTION_COMMON( 0xb00, Trap_0b, .UnknownException ) STD_EXCEPTION_COMMON( 0xd00, SingleStep, .SingleStepException ) @@ -624,65 +764,56 @@ #endif /* - * Here the exception frame is filled out and we have detected that - * the kernel stack pointer is bad. R23 contains the saved CR, r20 - * points to the paca, r21 points to the exception frame, and r22 - * contains the (bad) kernel stack pointer. + * Here we have detected that the kernel stack pointer is bad. + * R9 contains the saved CR, r13 points to the paca, + * r10 contains the (bad) kernel stack pointer, + * r11 and r12 contain the saved SRR0 and SRR1. * We switch to using the paca guard page as an emergency stack, - * save the registers on there, and call kernel_bad_stack(), - * which panics. + * save the registers there, and call kernel_bad_stack(), which panics. */ bad_stack: - addi r1,r20,8192-64-INT_FRAME_SIZE - std r22,GPR1(r1) - std r23,_CCR(r1) - ld r22,EX_R20(r21) - std r22,GPR20(r1) - ld r23,EX_R21(r21) - std r23,GPR21(r1) - ld r22,EX_R22(r21) - std r22,GPR22(r1) - ld r23,EX_R23(r21) - std r23,GPR23(r1) - ld r23,EX_DAR(r21) - std r23,_DAR(r1) - lwz r22,EX_DSISR(r21) - std r22,_DSISR(r1) - lwz r23,EX_TRAP(r21) - std r23,TRAP(r1) - ld r22,EX_SRR0(r21) - ld r23,EX_SRR1(r21) - std r22,_NIP(r1) - std r23,_MSR(r1) - addi r21,r21,-EXC_FRAME_SIZE - std r21,PACAEXCSP(r20) - mflr r22 - std r22,_LINK(r1) - mfctr r23 - std r23,_CTR(r1) - mfspr r22,XER - std r22,_XER(r1) + addi r1,r13,8192-64-INT_FRAME_SIZE + std r9,_CCR(r1) + std r10,GPR1(r1) + std r11,_NIP(r1) + std r12,_MSR(r1) + mfspr r11,DAR + mfspr r12,DSISR + std r11,_DAR(r1) + std r12,_DSISR(r1) + mflr r10 + mfctr r11 + mfxer r12 + std r10,_LINK(r1) + std r11,_CTR(r1) + std r12,_XER(r1) SAVE_GPR(0, r1) - SAVE_10GPRS(2, r1) - SAVE_8GPRS(12, r1) - SAVE_8GPRS(24, r1) - addi r21,r1,INT_FRAME_SIZE - std r21,0(r1) - li r22,0 - std r22,0(r21) - ld r2,PACATOC(r20) - mr r13,r20 + SAVE_GPR(2,r1) + SAVE_4GPRS(3,r1) + SAVE_2GPRS(7,r1) + SAVE_10GPRS(12,r1) + SAVE_10GPRS(22,r1) + addi r11,r1,INT_FRAME_SIZE + std r11,0(r1) + li r12,0 + std r12,0(r11) + ld r2,PACATOC(r13) 1: addi r3,r1,STACK_FRAME_OVERHEAD bl .kernel_bad_stack b 1b /* - * Return from an exception which is handled without calling - * save_remaining_regs. The caller is assumed to have done - * EXCEPTION_PROLOG_COMMON. + * Return from an exception with minimal checks. + * The caller is assumed to have done EXCEPTION_PROLOG_COMMON. + * If interrupts have been enabled, or anything has been + * done that might have changed the scheduling status of + * any task or sent any task a signal, you should use + * ret_from_except or ret_from_except_lite instead of this. */ fast_exception_return: - andi. r3,r23,MSR_RI /* check if RI is set */ + ld r12,_MSR(r1) + ld r11,_NIP(r1) + andi. r3,r12,MSR_RI /* check if RI is set */ beq- unrecov_fer ld r3,_CCR(r1) ld r4,_LINK(r1) @@ -691,244 +822,178 @@ mtcr r3 mtlr r4 mtctr r5 - mtspr XER,r6 + mtxer r6 REST_GPR(0, r1) REST_8GPRS(2, r1) - REST_4GPRS(10, r1) - mfmsr r20 - li r21, MSR_RI - andc r20,r20,r21 - mtmsrd r20,1 - - mtspr SRR1,r23 - mtspr SRR0,r22 - REST_4GPRS(20, r1) + mfmsr r10 + clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ + mtmsrd r10,1 + + mtspr SRR1,r12 + mtspr SRR0,r11 + REST_4GPRS(10, r1) ld r1,GPR1(r1) rfid unrecov_fer: - li r6,0x4000 - li r20,0 - bl .save_remaining_regs + bl .save_nvgprs 1: addi r3,r1,STACK_FRAME_OVERHEAD bl .unrecoverable_exception b 1b /* - * Here r20 points to the PACA, r21 to the exception frame, - * r23 contains the saved CR. - * r20 - r23, SRR0 and SRR1 are saved in the exception frame. + * Here r13 points to the paca, r9 contains the saved CR, + * SRR0 and SRR1 are saved in r11 and r12, + * r9 - r13 are saved in paca->exgen. */ + .align 7 .globl DataAccess_common DataAccess_common: -BEGIN_FTR_SECTION - mfspr r22,DAR - srdi r22,r22,60 - cmpi 0,r22,0xc - - /* Segment fault on a bolted segment. Go off and map that segment. */ - beq- .do_stab_bolted -END_FTR_SECTION_IFCLR(CPU_FTR_SLB) -stab_bolted_user_return: - EXCEPTION_PROLOG_COMMON - ld r3,_DSISR(r1) - andis. r0,r3,0xa450 /* weird error? */ - bne 1f /* if not, try to put a PTE */ - andis. r0,r3,0x0020 /* Is it a page table fault? */ - rlwinm r4,r3,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ - ld r3,_DAR(r1) /* into the hash table */ - -BEGIN_FTR_SECTION - beq+ 2f /* If so handle it */ - li r4,0x300 /* Trap number */ - bl .do_stab_SI - b 1f -END_FTR_SECTION_IFCLR(CPU_FTR_SLB) - -2: li r5,0x300 - bl .do_hash_page_DSI /* Try to handle as hpte fault */ -1: - ld r4,_DAR(r1) - ld r5,_DSISR(r1) - addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - li r6,0x300 - bl .save_remaining_regs - bl .do_page_fault - b .ret_from_except + mfspr r10,DAR + std r10,PACA_EXGEN+EX_DAR(r13) + mfspr r10,DSISR + stw r10,PACA_EXGEN+EX_DSISR(r13) + EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) + ld r3,PACA_EXGEN+EX_DAR(r13) + lwz r4,PACA_EXGEN+EX_DSISR(r13) + li r5,0x300 + b .do_hash_page /* Try to handle as hpte fault */ + .align 7 .globl DataAccessSLB_common DataAccessSLB_common: - mfspr r22,DAR - srdi r22,r22,60 - cmpi 0,r22,0xc - - /* Segment fault on a bolted segment. Go off and map that segment. */ - beq .do_slb_bolted - - EXCEPTION_PROLOG_COMMON - ld r3,_DAR(r1) - li r4,0x380 /* Exception vector */ + mfspr r10,DAR + std r10,PACA_EXGEN+EX_DAR(r13) + EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) + ld r3,PACA_EXGEN+EX_DAR(r13) + std r3,_DAR(r1) bl .slb_allocate - or. r3,r3,r3 /* Check return code */ + cmpdi r3,0 /* Check return code */ beq fast_exception_return /* Return if we succeeded */ - addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - ld r4,_DAR(r1) - li r6,0x380 li r5,0 - bl .save_remaining_regs - bl .do_page_fault - b .ret_from_except + std r5,_DSISR(r1) + b .handle_page_fault + .align 7 .globl InstructionAccess_common InstructionAccess_common: - EXCEPTION_PROLOG_COMMON - -BEGIN_FTR_SECTION - andis. r0,r23,0x0020 /* no ste found? */ - beq+ 2f - mr r3,r22 /* SRR0 at interrupt */ - li r4,0x400 /* Trap number */ - bl .do_stab_SI - b 1f -END_FTR_SECTION_IFCLR(CPU_FTR_SLB) - -2: mr r3,r22 + EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) + ld r3,_NIP(r1) + andis. r4,r12,0x5820 li r5,0x400 - bl .do_hash_page_ISI /* Try to handle as hpte fault */ -1: - mr r4,r22 - rlwinm r5,r23,0,4,4 /* We only care about PR in error_code */ - addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - li r6,0x400 - bl .save_remaining_regs - bl .do_page_fault - b .ret_from_except + b .do_hash_page /* Try to handle as hpte fault */ + .align 7 .globl InstructionAccessSLB_common InstructionAccessSLB_common: - EXCEPTION_PROLOG_COMMON - mr r3,r22 /* SRR0 = NIA */ - li r4,0x480 /* Exception vector */ + EXCEPTION_PROLOG_COMMON(0x480, PACA_EXGEN) + ld r3,_NIP(r1) /* SRR0 = NIA */ bl .slb_allocate or. r3,r3,r3 /* Check return code */ beq+ fast_exception_return /* Return if we succeeded */ - addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - mr r4,r22 /* SRR0 = NIA */ - li r6,0x480 + ld r4,_NIP(r1) li r5,0 - bl .save_remaining_regs - bl .do_page_fault - b .ret_from_except + std r4,_DAR(r1) + std r5,_DSISR(r1) + b .handle_page_fault + .align 7 .globl HardwareInterrupt_common + .globl HardwareInterrupt_entry HardwareInterrupt_common: - EXCEPTION_PROLOG_COMMON + EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) HardwareInterrupt_entry: + DISABLE_INTS addi r3,r1,STACK_FRAME_OVERHEAD - li r20,0 - li r6,0x500 - bl .save_remaining_regs bl .do_IRQ - b .ret_from_except + b .ret_from_except_lite + .align 7 .globl Alignment_common Alignment_common: - EXCEPTION_PROLOG_COMMON + mfspr r10,DAR + std r10,PACA_EXGEN+EX_DAR(r13) + mfspr r10,DSISR + stw r10,PACA_EXGEN+EX_DSISR(r13) + EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN) + ld r3,PACA_EXGEN+EX_DAR(r13) + lwz r4,PACA_EXGEN+EX_DSISR(r13) + std r3,_DAR(r1) + std r4,_DSISR(r1) + bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - li r6,0x600 - bl .save_remaining_regs + ENABLE_INTS bl .AlignmentException b .ret_from_except + .align 7 .globl ProgramCheck_common ProgramCheck_common: - EXCEPTION_PROLOG_COMMON + EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) + bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - li r6,0x700 - bl .save_remaining_regs + ENABLE_INTS bl .ProgramCheckException b .ret_from_except + .align 7 .globl FPUnavailable_common FPUnavailable_common: - EXCEPTION_PROLOG_COMMON + EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) bne .load_up_fpu /* if from user, just load it up */ + bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - li r6,0x800 - bl .save_remaining_regs + ENABLE_INTS bl .KernelFPUnavailableException BUG_OPCODE + .align 7 .globl AltivecUnavailable_common AltivecUnavailable_common: - EXCEPTION_PROLOG_COMMON + EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN) #ifdef CONFIG_ALTIVEC - bne .load_up_altivec /* if from user, just load it up */ + bne .load_up_altivec /* if from user, just load it up */ #endif + bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD - DO_COPY_EE() - li r6,0xf20 - bl .save_remaining_regs -#ifdef CONFIG_ALTIVEC - bl .KernelAltivecUnavailableException -#else - bl .UnknownException -#endif - BUG_OPCODE + ENABLE_INTS + bl .AltivecUnavailableException + b .ret_from_except - .globl SystemCall_common -SystemCall_common: - EXCEPTION_PROLOG_COMMON -#ifdef CONFIG_PPC_ISERIES - cmpi 0,r0,0x5555 /* Special syscall to handle pending */ - bne+ 1f /* interrupts */ - andi. r6,r23,MSR_PR /* Only allowed from kernel */ - beq+ HardwareInterrupt_entry -1: -#endif - DO_COPY_EE() - li r6,0xC00 - bl .save_remaining_regs - bl .DoSyscall - b .ret_from_except +/* + * Hash table stuff + */ + .align 7 +_GLOBAL(do_hash_page) + std r3,_DAR(r1) + std r4,_DSISR(r1) + + andis. r0,r4,0xa450 /* weird error? */ + bne- .handle_page_fault /* if not, try to insert a HPTE */ +BEGIN_FTR_SECTION + andis. r0,r4,0x0020 /* Is it a segment table fault? */ + bne- .do_ste_alloc /* If so handle it */ +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) -_GLOBAL(do_hash_page_ISI) - li r4,0 -_GLOBAL(do_hash_page_DSI) /* * We need to set the _PAGE_USER bit if MSR_PR is set or if we are * accessing a userspace segment (even from the kernel). We assume * kernel addresses always have the high bit set. */ - rotldi r0,r3,15 /* Move high bit into MSR_PR position */ - orc r0,r23,r0 - rlwimi r4,r0,32-13,30,30 /* Insert into _PAGE_USER */ + rlwinm r4,r4,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ + rotldi r0,r3,15 /* Move high bit into MSR_PR posn */ + orc r0,r12,r0 /* MSR_PR | ~high_bit */ + rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ ori r4,r4,1 /* add _PAGE_PRESENT */ - mflr r21 /* Save LR in r21 */ - -#ifdef DO_SOFT_DISABLE /* - * We hard enable here (but first soft disable) so that the hash_page - * code can spin on the hash_table_lock with problem on a shared - * processor. + * On iSeries, we soft-disable interrupts here, then + * hard-enable interrupts so that the hash_page code can spin on + * the hash_table_lock without problems on a shared processor. */ - li r0,0 - stb r0,PACAPROCENABLED(r20) /* Soft Disabled */ - - mfmsr r0 - ori r0,r0,MSR_EE - mtmsrd r0,1 /* Hard Enable */ -#endif + DISABLE_INTS /* * r3 contains the faulting address @@ -937,184 +1002,159 @@ * * at return r3 = 0 for success */ - bl .hash_page /* build HPTE if possible */ + cmpdi r3,0 /* see if hash_page succeeded */ #ifdef DO_SOFT_DISABLE /* - * Now go back to hard disabled. + * If we had interrupts soft-enabled at the point where the + * DSI/ISI occurred, and an interrupt came in during hash_page, + * handle it now. + * We jump to ret_from_except_lite rather than fast_exception_return + * because ret_from_except_lite will check for and handle pending + * interrupts if necessary. */ - mfmsr r0 - li r4,0 - ori r4,r4,MSR_EE - andc r0,r0,r4 - mtmsrd r0,1 /* Hard Disable */ - - ld r0,SOFTE(r1) - cmpdi 0,r0,0 /* See if we will soft enable in */ - /* save_remaining_regs */ - beq 5f - CHECKANYINT(r4,r5) - bne- HardwareInterrupt_entry /* Convert this DSI into an External */ - /* to process interrupts which occurred */ - /* during hash_page */ -5: - stb r0,PACAPROCENABLED(r20) /* Restore soft enable/disable status */ + beq .ret_from_except_lite + /* + * hash_page couldn't handle it, set soft interrupt enable back + * to what it was before the trap. Note that .local_irq_restore + * handles any interrupts pending at this point. + */ + ld r3,SOFTE(r1) + bl .local_irq_restore + b 11f +#else + beq+ fast_exception_return /* Return from exception on success */ + /* fall through */ #endif - or. r3,r3,r3 /* Check return code */ - beq fast_exception_return /* Return from exception on success */ - mtlr r21 /* restore LR */ - blr /* Return to DSI or ISI on failure */ +/* Here we have a page fault that hash_page can't handle. */ +_GLOBAL(handle_page_fault) + ENABLE_INTS +11: ld r4,_DAR(r1) + ld r5,_DSISR(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl .do_page_fault + cmpdi r3,0 + beq+ .ret_from_except_lite + bl .save_nvgprs + mr r5,r3 + addi r3,r1,STACK_FRAME_OVERHEAD + lwz r4,_DAR(r1) + bl .bad_page_fault + b .ret_from_except + + /* here we have a segment miss */ +_GLOBAL(do_ste_alloc) + bl .ste_allocate /* try to insert stab entry */ + cmpdi r3,0 + beq+ fast_exception_return + b .handle_page_fault /* - * r20 points to the PACA, r21 to the exception frame, - * r23 contains the saved CR. - * r20 - r23, SRR0 and SRR1 are saved in the exception frame. + * r13 points to the PACA, r9 contains the saved CR, + * r11 and r12 contain the saved SRR0 and SRR1. + * r9 - r13 are saved in paca->exslb. * We assume we aren't going to take any exceptions during this procedure. + * We assume (DAR >> 60) == 0xc. */ + .align 7 _GLOBAL(do_stab_bolted) - stw r23,EX_CCR(r21) /* save CR in exc. frame */ + stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ + std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ - mfspr r22,DSISR - andis. r22,r22,0x0020 - beq- stab_bolted_user_return + /* Hash to the primary group */ + ld r10,PACASTABVIRT(r13) + mfspr r11,DAR + srdi r11,r11,28 + rldimi r10,r11,7,52 /* r10 = first ste of the group */ + /* Calculate VSID */ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ - mfspr r21,DAR - rldicl r20,r21,36,51 - sldi r20,r20,15 - srdi r21,r21,60 - or r20,r20,r21 + rldic r11,r11,15,36 + ori r11,r11,0xc /* VSID_RANDOMIZER */ - li r21,9 - sldi r21,r21,32 - oris r21,r21,58231 - ori r21,r21,39831 + li r9,9 + sldi r9,r9,32 + oris r9,r9,58231 + ori r9,r9,39831 - mulld r20,r20,r21 - clrldi r20,r20,28 /* r20 = vsid */ - - mfsprg r21,3 - ld r21,PACASTABVIRT(r21) - - /* Hash to the primary group */ - mfspr r22,DAR - rldicl r22,r22,36,59 - rldicr r22,r22,7,56 - or r21,r21,r22 /* r21 = first ste of the group */ + mulld r9,r11,r9 + rldic r9,r9,12,16 /* r9 = vsid << 12 */ /* Search the primary group for a free entry */ - li r22,0 -1: - ld r23,0(r21) /* Test valid bit of the current ste */ - rldicl r23,r23,57,63 - cmpwi r23,0 - bne 2f - li r23,0 - rldimi r23,r20,12,0 /* Insert the new vsid value */ - std r23,8(r21) /* Put new entry back into the stab */ - eieio /* Order vsid update */ - li r23,0 - mfspr r20,DAR /* Get the new esid */ - rldicl r20,r20,36,28 /* Permits a full 36b of ESID */ - rldimi r23,r20,28,0 /* Insert the new esid value */ - ori r23,r23,144 /* Turn on valid and kp */ - std r23,0(r21) /* Put new entry back into the stab */ - sync /* Order the update */ - b 3f -2: - addi r22,r22,1 - addi r21,r21,16 - cmpldi r22,7 - ble 1b +1: ld r11,0(r10) /* Test valid bit of the current ste */ + andi. r11,r11,0x80 + beq 2f + addi r10,r10,16 + andi. r11,r10,0x70 + bne 1b /* Stick for only searching the primary group for now. */ /* At least for now, we use a very simple random castout scheme */ /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ - mftb r22 - andi. r22,r22,7 - ori r22,r22,1 - sldi r22,r22,4 + mftb r11 + rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ + ori r11,r11,0x10 - /* r21 currently points to and ste one past the group of interest */ + /* r10 currently points to an ste one past the group of interest */ /* make it point to the randomly selected entry */ - subi r21,r21,128 - or r21,r21,r22 /* r21 is the entry to invalidate */ + subi r10,r10,128 + or r10,r10,r11 /* r10 is the entry to invalidate */ isync /* mark the entry invalid */ - ld r23,0(r21) - li r22,-129 - and r23,r23,r22 - std r23,0(r21) + ld r11,0(r10) + rldicl r11,r11,56,1 /* clear the valid bit */ + rotldi r11,r11,8 + std r11,0(r10) sync - li r23,0 - rldimi r23,r20,12,0 - std r23,8(r21) + clrrdi r11,r11,28 /* Get the esid part of the ste */ + slbie r11 + +2: std r9,8(r10) /* Store the vsid part of the ste */ eieio - ld r22,0(r21) /* Get the esid part of the ste */ - li r23,0 - mfspr r20,DAR /* Get the new esid */ - rldicl r20,r20,36,28 /* Permits a full 32b of ESID */ - rldimi r23,r20,28,0 /* Insert the new esid value */ - ori r23,r23,144 /* Turn on valid and kp */ - std r23,0(r21) /* Put new entry back into the stab */ - - rldicl r22,r22,36,28 - rldicr r22,r22,28,35 - slbie r22 + mfspr r11,DAR /* Get the new esid */ + clrrdi r11,r11,28 /* Permits a full 32b of ESID */ + ori r11,r11,0x90 /* Turn on valid and kp */ + std r11,0(r10) /* Put new entry back into the stab */ + sync -3: /* All done -- return from exception. */ - mfsprg r20,3 /* Load the PACA pointer */ - ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */ - addi r21,r21,EXC_FRAME_SIZE - lwz r23,EX_CCR(r21) /* get saved CR */ - - ld r22,EX_SRR1(r21) - andi. r22,r22,MSR_RI - beq- unrecov_stab - - /* note that this is almost identical to maskable_exception_exit */ - mtcr r23 /* restore CR */ - - mfmsr r22 - li r23, MSR_RI - andc r22,r22,r23 - mtmsrd r22,1 - - ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ - ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ - mtspr SRR0,r22 - mtspr SRR1,r23 - ld r22,EX_R22(r21) /* restore r22 and r23 */ - ld r23,EX_R23(r21) - mfspr r20,SPRG2 - mfspr r21,SPRG1 - rfid + lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ + ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ -unrecov_stab: - EXCEPTION_PROLOG_COMMON - li r6,0x4100 - li r20,0 - bl .save_remaining_regs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl .unrecoverable_exception - b 1b + andi. r10,r12,MSR_RI + beq- unrecov_slb + + mtcrf 0x80,r9 /* restore CR */ + + mfmsr r10 + clrrdi r10,r10,2 + mtmsrd r10,1 + + mtspr SRR0,r11 + mtspr SRR1,r12 + ld r9,PACA_EXSLB+EX_R9(r13) + ld r10,PACA_EXSLB+EX_R10(r13) + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) + rfid /* - * r20 points to the PACA, r21 to the exception frame, - * r23 contains the saved CR. - * r20 - r23, SRR0 and SRR1 are saved in the exception frame. + * r13 points to the PACA, r9 contains the saved CR, + * r11 and r12 contain the saved SRR0 and SRR1. + * r9 - r13 are saved in paca->exslb. * We assume we aren't going to take any exceptions during this procedure. */ /* XXX note fix masking in get_kernel_vsid to match */ _GLOBAL(do_slb_bolted) - stw r23,EX_CCR(r21) /* save CR in exc. frame */ + stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ + std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ /* * We take the next entry, round robin. Previously we tried @@ -1122,15 +1162,15 @@ * we dont have any LRU information to help us choose a slot. */ - /* r20 = paca */ -1: ld r22,PACASTABRR(r20) - addi r21,r22,1 - cmpdi r21,SLB_NUM_ENTRIES + /* r13 = paca */ +1: ld r10,PACASTABRR(r13) + addi r9,r10,1 + cmpdi r9,SLB_NUM_ENTRIES blt+ 2f - li r21,2 /* dont touch slot 0 or 1 */ -2: std r21,PACASTABRR(r20) + li r9,2 /* dont touch slot 0 or 1 */ +2: std r9,PACASTABRR(r13) - /* r20 = paca, r22 = entry */ + /* r13 = paca, r10 = entry */ /* * Never cast out the segment for our kernel stack. Since we @@ -1139,8 +1179,8 @@ * which gets invalidated due to a tlbie from another cpu at a * non recoverable point (after setting srr0/1) - Anton */ - slbmfee r21,r22 - srdi r21,r21,27 + slbmfee r9,r10 + srdi r9,r9,27 /* * Use paca->ksave as the value of the kernel stack pointer, * because this is valid at all times. @@ -1150,74 +1190,71 @@ * switch (between updating r1 and updating paca->ksave), * we check against both r1 and paca->ksave. */ - srdi r23,r1,27 - ori r23,r23,1 - cmpd r23,r21 + srdi r11,r1,27 + ori r11,r11,1 + cmpd r11,r9 beq- 1b - ld r23,PACAKSAVE(r20) - srdi r23,r23,27 - ori r23,r23,1 - cmpd r23,r21 + ld r11,PACAKSAVE(r13) + srdi r11,r11,27 + ori r11,r11,1 + cmpd r11,r9 beq- 1b - /* r20 = paca, r22 = entry */ + /* r13 = paca, r10 = entry */ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ - mfspr r21,DAR - rldicl r23,r21,36,51 - sldi r23,r23,15 - srdi r21,r21,60 - or r23,r23,r21 + mfspr r9,DAR + rldicl r11,r9,36,51 + sldi r11,r11,15 + srdi r9,r9,60 + or r11,r11,r9 /* VSID_RANDOMIZER */ - li r21,9 - sldi r21,r21,32 - oris r21,r21,58231 - ori r21,r21,39831 + li r9,9 + sldi r9,r9,32 + oris r9,r9,58231 + ori r9,r9,39831 /* vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK */ - mulld r23,r23,r21 - clrldi r23,r23,28 + mulld r11,r11,r9 + clrldi r11,r11,28 - /* r20 = paca, r22 = entry, r23 = vsid */ + /* r13 = paca, r10 = entry, r11 = vsid */ /* Put together slb word1 */ - sldi r23,r23,12 + sldi r11,r11,12 BEGIN_FTR_SECTION /* set kp and c bits */ - ori r23,r23,0x480 + ori r11,r11,0x480 END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) BEGIN_FTR_SECTION /* set kp, l and c bits */ - ori r23,r23,0x580 + ori r11,r11,0x580 END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) - /* r20 = paca, r22 = entry, r23 = slb word1 */ + /* r13 = paca, r10 = entry, r11 = slb word1 */ /* Put together slb word0 */ - mfspr r21,DAR - rldicr r21,r21,0,35 /* get the new esid */ - oris r21,r21,2048 /* set valid bit */ - rldimi r21,r22,0,52 /* insert entry */ + mfspr r9,DAR + clrrdi r9,r9,28 /* get the new esid */ + oris r9,r9,0x800 /* set valid bit */ + rldimi r9,r10,0,52 /* insert entry */ - /* r20 = paca, r21 = slb word0, r23 = slb word1 */ + /* r13 = paca, r9 = slb word0, r11 = slb word1 */ /* * No need for an isync before or after this slbmte. The exception * we enter with and the rfid we exit with are context synchronizing . */ - slbmte r23,r21 + slbmte r11,r9 /* All done -- return from exception. */ - ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */ - addi r21,r21,EXC_FRAME_SIZE - lwz r23,EX_CCR(r21) /* get saved CR */ - /* note that this is almost identical to maskable_exception_exit */ - - ld r22,EX_SRR1(r21) - andi. r22,r22,MSR_RI - beq- unrecov_stab + lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ + ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_slb /* * Until everyone updates binutils hardwire the POWER4 optimised @@ -1226,124 +1263,32 @@ #if 0 .machine push .machine "power4" - mtcrf 0x80,r23 + mtcrf 0x80,r9 .machine pop #else - .long 0x7ef80120 + .long 0x7d380120 #endif - mfmsr r22 - li r23, MSR_RI - andc r22,r22,r23 - mtmsrd r22,1 - - ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ - ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ - mtspr SRR0,r22 - mtspr SRR1,r23 - ld r22,EX_R22(r21) /* restore r22 and r23 */ - ld r23,EX_R23(r21) - ld r20,EX_R20(r21) - mfspr r21,SPRG1 + mfmsr r10 + clrrdi r10,r10,2 + mtmsrd r10,1 + + mtspr SRR0,r11 + mtspr SRR1,r12 + ld r9,PACA_EXSLB+EX_R9(r13) + ld r10,PACA_EXSLB+EX_R10(r13) + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) rfid -_GLOBAL(do_stab_SI) - mflr r21 /* Save LR in r21 */ - - /* - * r3 contains the faulting address - * r4 contains the required access permissions - * - * at return r3 = 0 for success - */ - - bl .ste_allocate /* build STE if possible */ - or. r3,r3,r3 /* Check return code */ - beq fast_exception_return /* Return from exception on success */ - mtlr r21 /* restore LR */ - blr /* Return to DSI or ISI on failure */ - -/* - * This code finishes saving the registers to the exception frame. - * Address translation is already on. - */ -_GLOBAL(save_remaining_regs) - /* - * Save the rest of the registers into the pt_regs structure - */ - std r22,_NIP(r1) - std r23,_MSR(r1) - std r6,TRAP(r1) - ld r6,GPR6(r1) - SAVE_2GPRS(14, r1) - SAVE_4GPRS(16, r1) - SAVE_8GPRS(24, r1) - - /* Set the marker value "regshere" just before the reg values */ - SET_REG_TO_CONST(r22, 0x7265677368657265) - std r22,STACK_FRAME_OVERHEAD-16(r1) - - /* - * Clear the RESULT field - */ - li r22,0 - std r22,RESULT(r1) - - /* - * Test if from user state; result will be tested later - */ - andi. r23,r23,MSR_PR /* Set CR for later branch */ - - /* - * Indicate that r1 contains the kernel stack and - * get the Kernel TOC pointer from the paca - */ - ld r2,PACATOC(r13) /* Get Kernel TOC pointer */ - - /* - * If from user state, update THREAD.regs - */ - beq 2f /* Modify THREAD.regs if from user */ - addi r23,r1,STACK_FRAME_OVERHEAD - ld r22, PACACURRENT(r13) - std r23,THREAD+PT_REGS(r22) -2: - SET_REG_TO_CONST(r22, MSR_KERNEL) - -#ifdef DO_SOFT_DISABLE - stb r20,PACAPROCENABLED(r13) /* possibly soft enable */ - ori r22,r22,MSR_EE /* always hard enable */ -#else - rldimi r22,r20,15,48 /* Insert desired EE value */ -#endif - - mtmsrd r22,1 - blr - -/* - * Kernel profiling with soft disable on iSeries - */ -do_profile: - ld r22,8(r21) /* Get SRR1 */ - andi. r22,r22,MSR_PR /* Test if in kernel */ - bnelr /* return if not in kernel */ - ld r22,0(r21) /* Get SRR0 */ - ld r25,PACAPROFSTEXT(r20) /* _stext */ - subf r22,r25,r22 /* offset into kernel */ - lwz r25,PACAPROFSHIFT(r20) - srd r22,r22,r25 - lwz r25,PACAPROFLEN(r20) /* length of profile table (-1) */ - cmp 0,r22,r25 /* off end? */ - ble 1f - mr r22,r25 /* force into last entry */ -1: sldi r22,r22,2 /* convert to offset into buffer */ - ld r25,PACAPROFBUFFER(r20) /* profile buffer */ - add r25,r25,r22 -2: lwarx r22,0,r25 /* atomically increment */ - addi r22,r22,1 - stwcx. r22,0,r25 - bne- 2b - blr +unrecov_slb: + EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b /* @@ -1375,7 +1320,7 @@ addi r1,r1,0x1000 subi r1,r1,STACK_FRAME_OVERHEAD - cmpi 0,r23,0 + cmpwi 0,r23,0 #ifdef CONFIG_SMP #ifdef SECONDARY_PROCESSORS bne .__secondary_start @@ -1594,9 +1539,9 @@ * */ #ifndef CONFIG_SMP - LOADBASE(r3,last_task_used_math) - ld r4,last_task_used_math@l(r3) - cmpi 0,r4,0 + ld r3,last_task_used_math@got(r2) + ld r4,0(r3) + cmpdi 0,r4,0 beq 1f /* Save FP state to last_task_used_math's THREAD struct */ addi r4,r4,THREAD @@ -1606,8 +1551,8 @@ /* Disable FP for last_task_used_math */ ld r5,PT_REGS(r4) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) - li r20,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r20 + li r6,MSR_FP|MSR_FE0|MSR_FE1 + andc r4,r4,r6 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: #endif /* CONFIG_SMP */ @@ -1615,15 +1560,16 @@ ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ ld r4,THREAD_FPEXC_MODE(r5) - ori r23,r23,MSR_FP - or r23,r23,r4 + ori r12,r12,MSR_FP + or r12,r12,r4 + std r12,_MSR(r1) lfd fr0,THREAD_FPSCR(r5) mtfsf 0xff,fr0 REST_32FPRS(0, r5) #ifndef CONFIG_SMP /* Update last_task_used_math to 'current' */ subi r4,r5,THREAD /* Back to 'current' */ - std r4,last_task_used_math@l(r3) + std r4,0(r3) #endif /* CONFIG_SMP */ /* restore registers and return */ b fast_exception_return @@ -1651,11 +1597,11 @@ ori r5,r5,MSR_FP mtmsrd r5 /* enable use of fpu now */ isync - cmpi 0,r3,0 + cmpdi 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ ld r5,PT_REGS(r3) - cmpi 0,r5,0 + cmpdi 0,r5,0 SAVE_32FPRS(0, r3) mffs fr0 stfd fr0,THREAD_FPSCR(r3) @@ -1667,8 +1613,8 @@ 1: #ifndef CONFIG_SMP li r5,0 - LOADBASE(r4,last_task_used_math) - std r5,last_task_used_math@l(r4) + ld r4,last_task_used_math@got(r2) + std r5,0(r4) #endif /* CONFIG_SMP */ blr @@ -1699,9 +1645,9 @@ * avoid saving all of the VREGs here... */ #ifndef CONFIG_SMP - LOADBASE(r3,last_task_used_altivec) - ld r4,last_task_used_altivec@l(r3) - cmpi 0,r4,0 + ld r3,last_task_used_altivec@got(r2) + ld r4,0(r3) + cmpdi 0,r4,0 beq 1f /* Save VMX state to last_task_used_altivec's THREAD struct */ addi r4,r4,THREAD @@ -1712,8 +1658,8 @@ /* Disable VMX for last_task_used_altivec */ ld r5,PT_REGS(r4) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) - lis r20,MSR_VEC@h - andc r4,r4,r20 + lis r6,MSR_VEC@h + andc r4,r4,r6 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: #endif /* CONFIG_SMP */ @@ -1723,7 +1669,7 @@ * all 1's */ mfspr r4,SPRN_VRSAVE - cmpi 0,r4,0 + cmpdi 0,r4,0 bne+ 1f li r4,-1 mtspr SPRN_VRSAVE,r4 @@ -1731,7 +1677,8 @@ /* enable use of VMX after return */ ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ - oris r23,r23,MSR_VEC@h + oris r12,r12,MSR_VEC@h + std r12,_MSR(r1) li r4,1 li r10,THREAD_VSCR stw r4,THREAD_USED_VR(r5) @@ -1740,7 +1687,7 @@ #ifndef CONFIG_SMP /* Update last_task_used_math to 'current' */ subi r4,r5,THREAD /* Back to 'current' */ - std r4,last_task_used_altivec@l(r3) + std r4,0(r3) #endif /* CONFIG_SMP */ /* restore registers and return */ b fast_exception_return @@ -1768,11 +1715,11 @@ oris r5,r5,MSR_VEC@h mtmsrd r5 /* enable use of VMX now */ isync - cmpi 0,r3,0 + cmpdi 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ ld r5,PT_REGS(r3) - cmpi 0,r5,0 + cmpdi 0,r5,0 SAVE_32VRS(0,r4,r3) mfvscr vr0 li r4,THREAD_VSCR @@ -1785,8 +1732,8 @@ 1: #ifndef CONFIG_SMP li r5,0 - LOADBASE(r4,last_task_used_altivec) - std r5,last_task_used_altivec@l(r4) + ld r4,last_task_used_altivec@got(r2) + std r5,0(r4) #endif /* CONFIG_SMP */ blr @@ -1885,8 +1832,9 @@ LOADADDR(r3,current_set) sldi r28,r24,3 /* get current_set[cpu#] */ ldx r1,r3,r28 - addi r1,r1,THREAD_SIZE - subi r1,r1,STACK_FRAME_OVERHEAD + addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD + li r0,0 + std r0,0(r1) std r1,PACAKSAVE(r13) ld r3,PACASTABREAL(r13) /* get raddr of segment table */ @@ -1943,7 +1891,7 @@ #endif /* - * This subroutine clobbers r11, r12 and the LR + * This subroutine clobbers r11 and r12 */ _GLOBAL(enable_64b_mode) mfmsr r11 /* grab the current MSR */ @@ -2144,7 +2092,6 @@ std r4,PACACURRENT(r13) std r2,PACATOC(r13) - li r5,0 std r1,PACAKSAVE(r13) /* Restore the parms passed in from the bootloader. */ diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/iSeries_setup.c 2004-06-20 13:00:25 -07:00 @@ -357,15 +357,14 @@ HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256, HvLpDma_Direction_RemoteToLocal); - p = q = cmd_line + 255; - while (p > cmd_line) { - if ((*p == 0) || (*p == ' ') || (*p == '\n')) - --p; - else + p = cmd_line; + q = cmd_line + 255; + while( p < q ) { + if (!*p || *p == '\n') break; + ++p; } - if (p < q) - *(p + 1) = 0; + *p = 0; if (strstr(cmd_line, "dprofile=")) { for (q = cmd_line; (p = strstr(q, "dprofile=")) != 0; ) { diff -Nru a/arch/ppc64/kernel/init_task.c b/arch/ppc64/kernel/init_task.c --- a/arch/ppc64/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc64/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -4,6 +4,7 @@ #include #include #include +#include #include static struct fs_struct init_fs = INIT_FS; diff -Nru a/arch/ppc64/kernel/mf_proc.c b/arch/ppc64/kernel/mf_proc.c --- a/arch/ppc64/kernel/mf_proc.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/kernel/mf_proc.c 2004-06-20 13:00:24 -07:00 @@ -25,33 +25,26 @@ { int len = count; char *p; - + + if (off) { + *eof = 1; + return 0; + } + len = mf_getCmdLine(page, &len, (u64)data); - p = page + len - 1; - while (p > page) { - if ((*p == 0) || (*p == ' ')) - --p; - else + p = page; + while (len < (count - 1)) { + if (!*p || *p == '\n') break; + p++; + len++; } - if (*p != '\n') { - ++p; - *p = '\n'; - } - ++p; + *p = '\n'; + p++; *p = 0; - len = p - page; - - len -= off; - if (len < count) { - *eof = 1; - if (len <= 0) - return 0; - } else - len = count; - *start = page + off; - return len; + + return p - page; } #if 0 diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/misc.S 2004-06-20 13:00:25 -07:00 @@ -85,16 +85,17 @@ cmpw 0,r3,r5 beqlr /* are we enabling interrupts? */ - cmpi 0,r3,0 + cmpdi 0,r3,0 stb r3,PACAPROCENABLED(r13) beqlr /* Check pending interrupts */ /* A decrementer, IPI or PMC interrupt may have occurred * while we were in the hypervisor (which enables) */ - CHECKANYINT(r4,r5) + ld r4,PACALPPACA+LPPACAANYINT(r13) + cmpdi r4,0 beqlr - /* + /* * Handle pending interrupts in interrupt context */ li r0,0x5555 @@ -608,7 +609,7 @@ _GLOBAL(sys_call_table32) .llong .sys_restart_syscall /* 0 */ .llong .sys_exit - .llong .sys_fork + .llong .ppc_fork .llong .sys_read .llong .sys_write .llong .sys32_open /* 5 */ @@ -678,7 +679,7 @@ .llong .sys32_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys32_sigsuspend + .llong .ppc32_sigsuspend .llong .compat_sys_sigpending .llong .sys32_sethostname .llong .compat_sys_setrlimit /* 75 */ @@ -726,7 +727,7 @@ .llong .sys32_ipc .llong .sys_fsync .llong .ppc32_sigreturn - .llong .sys_clone /* 120 */ + .llong .ppc_clone /* 120 */ .llong .sys32_setdomainname .llong .ppc64_newuname .llong .sys_ni_syscall /* old modify_ldt syscall */ @@ -784,7 +785,7 @@ .llong .sys32_rt_sigpending /* 175 */ .llong .sys32_rt_sigtimedwait .llong .sys32_rt_sigqueueinfo - .llong .sys32_rt_sigsuspend + .llong .ppc32_rt_sigsuspend .llong .sys32_pread64 .llong .sys32_pwrite64 /* 180 */ .llong .sys_chown @@ -795,7 +796,7 @@ .llong .sys32_sendfile .llong .sys_ni_syscall /* reserved for streams1 */ .llong .sys_ni_syscall /* reserved for streams2 */ - .llong .sys_vfork + .llong .ppc_vfork .llong .compat_sys_getrlimit /* 190 */ .llong .sys32_readahead .llong .sys32_mmap2 @@ -880,7 +881,7 @@ _GLOBAL(sys_call_table) .llong .sys_restart_syscall /* 0 */ .llong .sys_exit - .llong .sys_fork + .llong .ppc_fork .llong .sys_read .llong .sys_write .llong .sys_open /* 5 */ @@ -998,7 +999,7 @@ .llong .sys_ipc .llong .sys_fsync .llong .sys_ni_syscall - .llong .sys_clone /* 120 */ + .llong .ppc_clone /* 120 */ .llong .sys_setdomainname .llong .ppc64_newuname .llong .sys_ni_syscall /* old modify_ldt syscall */ @@ -1056,7 +1057,7 @@ .llong .sys_rt_sigpending /* 175 */ .llong .sys_rt_sigtimedwait .llong .sys_rt_sigqueueinfo - .llong .sys_rt_sigsuspend + .llong .ppc64_rt_sigsuspend .llong .sys_pread64 .llong .sys_pwrite64 /* 180 */ .llong .sys_chown @@ -1067,7 +1068,7 @@ .llong .sys_sendfile64 .llong .sys_ni_syscall /* reserved for streams1 */ .llong .sys_ni_syscall /* reserved for streams2 */ - .llong .sys_vfork + .llong .ppc_vfork .llong .sys_getrlimit /* 190 */ .llong .sys_readahead .llong .sys_ni_syscall /* 32bit only mmap2 */ diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/pacaData.c 2004-06-20 13:00:25 -07:00 @@ -62,8 +62,6 @@ .xDesc = 0xd397d9e2, /* "LpRS" */ \ .xSize = sizeof(struct ItLpRegSave) \ }, \ - .exception_sp = \ - (&paca[number].exception_stack[0]) - EXC_FRAME_SIZE, \ } struct paca_struct paca[] __page_aligned = { diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/process.c 2004-06-20 13:00:25 -07:00 @@ -65,8 +65,43 @@ .page_table_lock = SPIN_LOCK_UNLOCKED, }; +/* + * Make sure the floating-point register state in the + * the thread_struct is up to date for task tsk. + */ +void flush_fp_to_thread(struct task_struct *tsk) +{ + if (tsk->thread.regs) { + /* + * We need to disable preemption here because if we didn't, + * another process could get scheduled after the regs->msr + * test but before we have finished saving the FP registers + * to the thread_struct. That process could take over the + * FPU, and then when we get scheduled again we would store + * bogus values for the remaining FP registers. + */ + preempt_disable(); + if (tsk->thread.regs->msr & MSR_FP) { +#ifdef CONFIG_SMP + /* + * This should only ever be called for current or + * for a stopped child process. Since we save away + * the FP register state on context switch on SMP, + * there is something wrong if a stopped child appears + * to still have its FP state in the CPU registers. + */ + BUG_ON(tsk != current); +#endif + giveup_fpu(current); + } + preempt_enable(); + } +} + void enable_kernel_fp(void) { + WARN_ON(preemptible()); + #ifdef CONFIG_SMP if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) giveup_fpu(current); @@ -80,12 +115,9 @@ int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) { - struct pt_regs *regs = tsk->thread.regs; - - if (!regs) + if (!tsk->thread.regs) return 0; - if (tsk == current && (regs->msr & MSR_FP)) - giveup_fpu(current); + flush_fp_to_thread(current); memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); @@ -96,6 +128,8 @@ void enable_kernel_altivec(void) { + WARN_ON(preemptible()); + #ifdef CONFIG_SMP if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) giveup_altivec(current); @@ -107,10 +141,29 @@ } EXPORT_SYMBOL(enable_kernel_altivec); +/* + * Make sure the VMX/Altivec register state in the + * the thread_struct is up to date for task tsk. + */ +void flush_altivec_to_thread(struct task_struct *tsk) +{ +#ifdef CONFIG_ALTIVEC + if (tsk->thread.regs) { + preempt_disable(); + if (tsk->thread.regs->msr & MSR_VEC) { +#ifdef CONFIG_SMP + BUG_ON(tsk != current); +#endif + giveup_altivec(current); + } + preempt_enable(); + } +#endif +} + int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) { - if (regs->msr & MSR_VEC) - giveup_altivec(current); + flush_altivec_to_thread(current); memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); return 1; } @@ -166,6 +219,7 @@ void show_regs(struct pt_regs * regs) { int i; + unsigned long trap; printk("NIP: %016lX XER: %016lX LR: %016lX\n", regs->nip, regs->xer, regs->link); @@ -176,7 +230,8 @@ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, regs->msr&MSR_IR ? 1 : 0, regs->msr&MSR_DR ? 1 : 0); - if (regs->trap == 0x300 || regs->trap == 0x380 || regs->trap == 0x600) + trap = TRAP(regs); + if (trap == 0x300 || trap == 0x380 || trap == 0x600) printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr); printk("TASK: %p[%d] '%s' THREAD: %p", current, current->pid, current->comm, current->thread_info); @@ -191,6 +246,8 @@ } printk("%016lX ", regs->gpr[i]); + if (i == 13 && !FULL_REGS(regs)) + break; } printk("\n"); /* @@ -245,16 +302,8 @@ */ void prepare_to_copy(struct task_struct *tsk) { - struct pt_regs *regs = tsk->thread.regs; - - if (regs == NULL) - return; - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ + flush_fp_to_thread(current); + flush_altivec_to_thread(current); } /* @@ -439,12 +488,8 @@ error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ + flush_fp_to_thread(current); + flush_altivec_to_thread(current); error = do_execve(filename, (char __user * __user *) a1, (char __user * __user *) a2, regs); diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c --- a/arch/ppc64/kernel/ptrace.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/ptrace.c 2004-06-20 13:00:25 -07:00 @@ -119,8 +119,7 @@ if (index < PT_FPR0) { tmp = get_reg(child, (int)index); } else { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; } ret = put_user(tmp,(unsigned long __user *) data); @@ -152,8 +151,7 @@ if (index < PT_FPR0) { ret = put_reg(child, index, data); } else { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; ret = 0; } @@ -245,8 +243,7 @@ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned long __user *tmp = (unsigned long __user *)addr; - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); for (i = 0; i < 32; i++) { ret = put_user(*reg, tmp); @@ -263,8 +260,7 @@ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned long __user *tmp = (unsigned long __user *)addr; - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); for (i = 0; i < 32; i++) { ret = get_user(*reg, tmp); diff -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c --- a/arch/ppc64/kernel/ptrace32.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/kernel/ptrace32.c 2004-06-20 13:00:24 -07:00 @@ -136,8 +136,7 @@ if (index < PT_FPR0) { tmp = get_reg(child, index); } else { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); /* * the user space code considers the floating point * to be an array of unsigned int (32 bits) - the @@ -179,8 +178,7 @@ break; if (numReg >= PT_FPR0) { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; } else { /* register within PT_REGS struct */ tmp = get_reg(child, numReg); @@ -244,8 +242,7 @@ if (index < PT_FPR0) { ret = put_reg(child, index, data); } else { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); /* * the user space code considers the floating point * to be an array of unsigned int (32 bits) - the @@ -283,8 +280,7 @@ || ((numReg > PT_CCR) && (numReg < PT_FPR0))) break; if (numReg >= PT_FPR0) { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); } if (numReg == PT_MSR) data = (data & MSR_DEBUGCHANGE) @@ -379,8 +375,7 @@ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned int __user *tmp = (unsigned int __user *)addr; - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); for (i = 0; i < 32; i++) { ret = put_user(*reg, tmp); @@ -397,8 +392,7 @@ unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; unsigned int __user *tmp = (unsigned int __user *)addr; - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); + flush_fp_to_thread(child); for (i = 0; i < 32; i++) { ret = get_user(*reg, tmp); diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc64/kernel/rtas.c 2004-06-20 13:00:23 -07:00 @@ -68,10 +68,11 @@ void call_rtas_display_status(char c) { - struct rtas_args *args = &(get_paca()->xRtas); + struct rtas_args *args; unsigned long s; spin_lock_irqsave(&rtas.lock, s); + args = &(get_paca()->xRtas); args->token = 10; args->nargs = 1; @@ -145,7 +146,7 @@ va_list list; int i, logit = 0; unsigned long s; - struct rtas_args *rtas_args = &(get_paca()->xRtas); + struct rtas_args *rtas_args; long ret; PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n"); @@ -158,6 +159,7 @@ /* Gotta do something different here, use global lock for now... */ spin_lock_irqsave(&rtas.lock, s); + rtas_args = &(get_paca()->xRtas); rtas_args->token = token; rtas_args->nargs = nargs; diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc64/kernel/signal.c 2004-06-20 13:00:23 -07:00 @@ -131,8 +131,7 @@ #endif long err = 0; - if (regs->msr & MSR_FP) - giveup_fpu(current); + flush_fp_to_thread(current); /* Make sure signal doesn't get spurrious FP exceptions */ current->thread.fpscr = 0; @@ -141,9 +140,8 @@ err |= __put_user(v_regs, &sc->v_regs); /* save altivec registers */ - if (current->thread.used_vr) { - if (regs->msr & MSR_VEC) - giveup_altivec(current); + if (current->thread.used_vr) { + flush_altivec_to_thread(current); /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128)); /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) @@ -530,13 +528,13 @@ struct k_sigaction *ka = ¤t->sighand->action[signr-1]; /* Whee! Actually deliver the signal. */ - if (regs->trap == 0x0C00) + if (TRAP(regs) == 0x0C00) syscall_restart(regs, ka); handle_signal(signr, ka, &info, oldset, regs); return 1; } - if (regs->trap == 0x0C00) { /* System Call! */ + if (TRAP(regs) == 0x0C00) { /* System Call! */ if ((int)regs->result == -ERESTARTNOHAND || (int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTNOINTR) { diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/signal32.c 2004-06-20 13:00:25 -07:00 @@ -130,11 +130,10 @@ { elf_greg_t64 *gregs = (elf_greg_t64 *)regs; int i, err = 0; - - /* Make sure floating point registers are stored in regs */ - if (regs->msr & MSR_FP) - giveup_fpu(current); - + + /* Make sure floating point registers are stored in regs */ + flush_fp_to_thread(current); + /* save general and floating-point registers */ for (i = 0; i <= PT_RESULT; i ++) err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]); @@ -148,8 +147,7 @@ #ifdef CONFIG_ALTIVEC /* save altivec registers */ if (current->thread.used_vr) { - if (regs->msr & MSR_VEC) - giveup_altivec(current); + flush_altivec_to_thread(current); if (__copy_to_user(&frame->mc_vregs, current->thread.vr, ELF_NVRREG32 * sizeof(vector128))) return 1; @@ -934,7 +932,7 @@ ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; - if (regs->trap == 0x0C00 /* System Call! */ + if (TRAP(regs) == 0x0C00 /* System Call! */ && regs->ccr & 0x10000000 /* error signalled */ && ((ret = regs->gpr[3]) == ERESTARTSYS || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/sys_ppc32.c 2004-06-20 13:00:25 -07:00 @@ -617,12 +617,8 @@ error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ + flush_fp_to_thread(current); + flush_altivec_to_thread(current); error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs); diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/kernel/syscalls.c 2004-06-20 13:00:25 -07:00 @@ -237,5 +237,19 @@ return secs; } +void do_show_syscall(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, unsigned long r8, + struct pt_regs *regs) +{ + printk("syscall %ld(%lx, %lx, %lx, %lx, %lx, %lx) regs=%p current=%p" + " cpu=%d\n", regs->gpr[0], r3, r4, r5, r6, r7, r8, regs, + current, smp_processor_id()); +} + +void do_show_syscall_exit(unsigned long r3) +{ + printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id()); +} + /* Only exists on P-series. */ cond_syscall(ppc_rtas); diff -Nru a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c --- a/arch/ppc64/kernel/sysfs.c 2004-06-20 13:00:23 -07:00 +++ b/arch/ppc64/kernel/sysfs.c 2004-06-20 13:00:23 -07:00 @@ -325,6 +325,16 @@ #ifdef CONFIG_NUMA parent = &node_devices[cpu_to_node(cpu)]; #endif + /* + * For now, we just see if the system supports making + * the RTAS calls for CPU hotplug. But, there may be a + * more comprehensive way to do this for an individual + * CPU. For instance, the boot cpu might never be valid + * for hotplugging. + */ + if (systemcfg->platform != PLATFORM_PSERIES_LPAR) + c->no_control = 1; + register_cpu(c, cpu, parent); register_cpu_pmc(&c->sysdev); diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/kernel/traps.c 2004-06-20 13:00:24 -07:00 @@ -308,8 +308,7 @@ siginfo_t info; unsigned long fpscr; - if (regs->msr & MSR_FP) - giveup_fpu(current); + flush_fp_to_thread(current); fpscr = current->thread.fpscr; @@ -442,8 +441,22 @@ die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); } -void KernelAltivecUnavailableException(struct pt_regs *regs) +void AltivecUnavailableException(struct pt_regs *regs) { +#ifndef CONFIG_ALTIVEC + if (user_mode(regs)) { + /* A user program has executed an altivec instruction, + but this kernel doesn't support altivec. */ + siginfo_t info; + + memset(&info, 0, sizeof(info)); + info.si_signo = SIGILL; + info.si_code = ILL_ILLOPC; + info.si_addr = (void *) regs->nip; + _exception(SIGILL, &info, regs); + return; + } +#endif printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); @@ -531,8 +544,7 @@ void AltivecAssistException(struct pt_regs *regs) { - if (regs->msr & MSR_VEC) - giveup_altivec(current); + flush_altivec_to_thread(current); /* XXX quick hack for now: set the non-Java bit in the VSCR */ current->thread.vscr.u[3] |= 0x10000; } diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/mm/fault.c 2004-06-20 13:00:25 -07:00 @@ -80,36 +80,45 @@ * - DSISR for a non-SLB data access fault, * - SRR1 & 0x08000000 for a non-SLB instruction access fault * - 0 any SLB fault. + * The return value is 0 if the fault was handled, or the signal + * number if this is a kernel fault that can't be handled here. */ -void do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code) +int do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code) { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; siginfo_t info; unsigned long code = SEGV_MAPERR; unsigned long is_write = error_code & 0x02000000; + unsigned long trap = TRAP(regs); - if (regs->trap == 0x300 || regs->trap == 0x380) { + if (trap == 0x300 || trap == 0x380) { if (debugger_fault_handler(regs)) - return; + return 0; } /* On a kernel SLB miss we can only check for a valid exception entry */ - if (!user_mode(regs) && (regs->trap == 0x380)) { - bad_page_fault(regs, address, SIGSEGV); - return; - } + if (!user_mode(regs) && (trap == 0x380 || address >= TASK_SIZE)) + return SIGSEGV; if (error_code & 0x00400000) { if (debugger_dabr_match(regs)) - return; + return 0; } if (in_atomic() || mm == NULL) { - bad_page_fault(regs, address, SIGSEGV); - return; + if (!user_mode(regs)) + return SIGSEGV; + /* in_atomic() in user mode is really bad, + as is current->mm == NULL. */ + printk(KERN_EMERG "Page fault in user mode with" + "in_atomic() = %d mm = %p\n", in_atomic(), mm); + printk(KERN_EMERG "NIP = %lx MSR = %lx\n", + regs->nip, regs->msr); + die("Weird page fault", regs, SIGSEGV); } + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -195,7 +204,7 @@ } up_read(&mm->mmap_sem); - return; + return 0; bad_area: up_read(&mm->mmap_sem); @@ -207,11 +216,10 @@ info.si_code = code; info.si_addr = (void *) address; force_sig_info(SIGSEGV, &info, current); - return; + return 0; } - bad_page_fault(regs, address, SIGSEGV); - return; + return SIGSEGV; /* * We ran out of memory, or some other thing happened to us that made @@ -227,18 +235,19 @@ printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); - bad_page_fault(regs, address, SIGKILL); - return; + return SIGKILL; do_sigbus: up_read(&mm->mmap_sem); - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *)address; - force_sig_info (SIGBUS, &info, current); - if (!user_mode(regs)) - bad_page_fault(regs, address, SIGBUS); + if (user_mode(regs)) { + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info(SIGBUS, &info, current); + return 0; + } + return SIGBUS; } /* diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c --- a/arch/ppc64/mm/hash_utils.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/mm/hash_utils.c 2004-06-20 13:00:24 -07:00 @@ -251,6 +251,7 @@ struct mm_struct *mm; pte_t *ptep; int ret; + int cpu; int user_region = 0; int local = 0; cpumask_t tmp; @@ -302,7 +303,8 @@ if (pgdir == NULL) return 1; - tmp = cpumask_of_cpu(smp_processor_id()); + cpu = get_cpu(); + tmp = cpumask_of_cpu(cpu); if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) local = 1; @@ -311,11 +313,13 @@ ret = hash_huge_page(mm, access, ea, vsid, local); else { ptep = find_linux_pte(pgdir, ea); - if (ptep == NULL) + if (ptep == NULL) { + put_cpu(); return 1; + } ret = __hash_page(ea, access, vsid, ptep, trap, local); } - + put_cpu(); return ret; } diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c --- a/arch/ppc64/mm/hugetlbpage.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/mm/hugetlbpage.c 2004-06-20 13:00:24 -07:00 @@ -375,6 +375,7 @@ unsigned long addr; hugepte_t *ptep; struct page *page; + int cpu; int local = 0; cpumask_t tmp; @@ -383,7 +384,8 @@ BUG_ON((end % HPAGE_SIZE) != 0); /* XXX are there races with checking cpu_vm_mask? - Anton */ - tmp = cpumask_of_cpu(smp_processor_id()); + cpu = get_cpu(); + tmp = cpumask_of_cpu(cpu); if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) local = 1; @@ -406,6 +408,7 @@ put_page(page); } + put_cpu(); mm->rss -= (end - start) >> PAGE_SHIFT; } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/mm/init.c 2004-06-20 13:00:24 -07:00 @@ -764,6 +764,7 @@ void *pgdir; pte_t *ptep; int local = 0; + int cpu; cpumask_t tmp; /* handle i-cache coherency */ @@ -794,12 +795,14 @@ vsid = get_vsid(vma->vm_mm->context.id, ea); - tmp = cpumask_of_cpu(smp_processor_id()); + cpu = get_cpu(); + tmp = cpumask_of_cpu(cpu); if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) local = 1; __hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep, 0x300, local); + put_cpu(); } void * reserve_phb_iospace(unsigned long size) diff -Nru a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c --- a/arch/ppc64/mm/tlb.c 2004-06-20 13:00:24 -07:00 +++ b/arch/ppc64/mm/tlb.c 2004-06-20 13:00:24 -07:00 @@ -41,6 +41,33 @@ DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); unsigned long pte_freelist_forced_free; +void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage) +{ + /* This is safe as we are holding page_table_lock */ + cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); + struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); + + if (atomic_read(&tlb->mm->mm_users) < 2 || + cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) { + pte_free(ptepage); + return; + } + + if (*batchp == NULL) { + *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); + if (*batchp == NULL) { + pte_free_now(ptepage); + return; + } + (*batchp)->index = 0; + } + (*batchp)->pages[(*batchp)->index++] = ptepage; + if ((*batchp)->index == PTE_FREELIST_SIZE) { + pte_free_submit(*batchp); + *batchp = NULL; + } +} + /* * Update the MMU hash table to correspond with a change to * a Linux PTE. If wrprot is true, it is permissible to @@ -91,12 +118,15 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) { int i; - cpumask_t tmp = cpumask_of_cpu(smp_processor_id()); + int cpu; + cpumask_t tmp; int local = 0; BUG_ON(in_interrupt()); + cpu = get_cpu(); i = batch->index; + tmp = cpumask_of_cpu(cpu); if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) local = 1; @@ -106,6 +136,7 @@ else flush_hash_range(batch->context, i, local); batch->index = 0; + put_cpu(); } #ifdef CONFIG_SMP diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c 2004-06-20 13:00:25 -07:00 +++ b/arch/ppc64/xmon/xmon.c 2004-06-20 13:00:25 -07:00 @@ -44,9 +44,6 @@ static int xmon_gate; #endif /* CONFIG_SMP */ -#define TRAP(regs) ((regs)->trap) -#define FULL_REGS(regs) 1 - static unsigned long in_xmon = 0; static unsigned long adrs; diff -Nru a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c --- a/arch/s390/kernel/init_task.c 2004-06-20 13:00:25 -07:00 +++ b/arch/s390/kernel/init_task.c 2004-06-20 13:00:25 -07:00 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c --- a/arch/sh/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/sh/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c --- a/arch/sparc/kernel/init_task.c 2004-06-20 13:00:24 -07:00 +++ b/arch/sparc/kernel/init_task.c 2004-06-20 13:00:24 -07:00 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c --- a/arch/sparc64/kernel/init_task.c 2004-06-20 13:00:26 -07:00 +++ b/arch/sparc64/kernel/init_task.c 2004-06-20 13:00:26 -07:00 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c --- a/arch/um/kernel/init_task.c 2004-06-20 13:00:26 -07:00 +++ b/arch/um/kernel/init_task.c 2004-06-20 13:00:26 -07:00 @@ -9,6 +9,7 @@ #include "linux/sched.h" #include "linux/init_task.h" #include "linux/version.h" +#include "linux/mqueue.h" #include "asm/uaccess.h" #include "asm/pgtable.h" #include "user_util.h" diff -Nru a/arch/v850/kernel/init_task.c b/arch/v850/kernel/init_task.c --- a/arch/v850/kernel/init_task.c 2004-06-20 13:00:23 -07:00 +++ b/arch/v850/kernel/init_task.c 2004-06-20 13:00:23 -07:00 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile --- a/arch/x86_64/Makefile 2004-06-20 13:00:25 -07:00 +++ b/arch/x86_64/Makefile 2004-06-20 13:00:25 -07:00 @@ -37,6 +37,8 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -e stext +CHECK := $(CHECK) -D__x86_64__=1 + cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,) cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=nocona,) CFLAGS += $(cflags-y) diff -Nru a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c --- a/arch/x86_64/kernel/e820.c 2004-06-20 13:00:23 -07:00 +++ b/arch/x86_64/kernel/e820.c 2004-06-20 13:00:23 -07:00 @@ -34,7 +34,7 @@ */ unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT; -extern struct resource code_resource, data_resource, vram_resource; +extern struct resource code_resource, data_resource; /* Check for some hardcoded bad areas that early boot is not allowed to touch */ static inline int bad_addr(unsigned long *addrp, unsigned long size) diff -Nru a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c --- a/arch/x86_64/kernel/init_task.c 2004-06-20 13:00:24 -07:00 +++ b/arch/x86_64/kernel/init_task.c 2004-06-20 13:00:24 -07:00 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c --- a/arch/x86_64/kernel/mpparse.c 2004-06-20 13:00:24 -07:00 +++ b/arch/x86_64/kernel/mpparse.c 2004-06-20 13:00:24 -07:00 @@ -716,7 +716,7 @@ } mp_ioapic_routing[MAX_IO_APICS]; -static int __init mp_find_ioapic ( +static int mp_find_ioapic ( int gsi) { int i = 0; @@ -861,6 +861,7 @@ for (idx = 0; idx < mp_irq_entries; idx++) if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS && + (mp_irqs[idx].mpc_dstapic == ioapic) && (mp_irqs[idx].mpc_srcbusirq == i || mp_irqs[idx].mpc_dstirq == i)) break; @@ -888,91 +889,54 @@ return; } - -extern FADT_DESCRIPTOR acpi_fadt; - -#ifdef CONFIG_ACPI_PCI - -void __init mp_parse_prt (void) +void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) { - struct list_head *node = NULL; - struct acpi_prt_entry *entry = NULL; int ioapic = -1; int ioapic_pin = 0; - int gsi = 0; int idx, bit = 0; - int edge_level = 0; - int active_high_low = 0; - /* - * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all static (IOAPIC-direct) entries. - */ - list_for_each(node, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); + if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) + return; - /* Need to get gsi for dynamic entry */ - if (entry->link.handle) { - gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); - if (!gsi) - continue; - } else { - /* Hardwired GSI. Assume PCI standard settings */ - gsi = entry->link.index; - edge_level = 1; - active_high_low = 1; - } +#ifdef CONFIG_ACPI_BUS + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == gsi) + return; +#endif - /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_fadt.sci_int == gsi) { - /* we still need to set up the entry's irq */ - acpi_gsi_to_irq(gsi, &entry->irq); - continue; - } + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) { + printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); + return; + } - ioapic = mp_find_ioapic(gsi); - if (ioapic < 0) - continue; - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start; - - /* - * Avoid pin reprogramming. PRTs typically include entries - * with redundant pin->gsi mappings (but unique PCI devices); - * we only only program the IOAPIC on the first. - */ - bit = ioapic_pin % 32; - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); - if (idx > 3) { - printk(KERN_ERR "Invalid reference to IOAPIC pin " - "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, - ioapic_pin); - continue; - } - if ((1<irq); - continue; - } + ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start; - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq); - } - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n", - entry->id.segment, entry->id.bus, - entry->id.device, ('A' + entry->pin), - mp_ioapic_routing[ioapic].apic_id, ioapic_pin, - entry->irq); + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->gsi mappings (but unique PCI devices); + * we only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + return; + } + if ((1< upper || !checksum(rom, length)) + if (!length || start + length > upper || !romchecksum(rom, length)) continue; adapter_rom_resources[i].start = start; @@ -555,13 +557,13 @@ probe_roms(); e820_reserve_resources(); - request_resource(&iomem_resource, &vram_resource); + request_resource(&iomem_resource, &video_ram_resource); { unsigned i; /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, standard_io_resources+i); + request_resource(&ioport_resource, &standard_io_resources[i]); } /* Will likely break when you have unassigned resources with more diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c --- a/arch/x86_64/mm/numa.c 2004-06-20 13:00:25 -07:00 +++ b/arch/x86_64/mm/numa.c 2004-06-20 13:00:25 -07:00 @@ -182,7 +182,7 @@ numnodes = 1; for (i = 0; i < NR_CPUS; i++) cpu_to_node[i] = 0; - node_to_cpumask[0] = 1; + node_to_cpumask[0] = cpumask_of_cpu(0); setup_node_bootmem(0, start_pfn< #include #include -#ifdef CONFIG_X86_IO_APIC -#include -#endif -#ifdef CONFIG_IOSAPIC -# include -#endif #include #include @@ -50,10 +44,6 @@ struct acpi_prt_list acpi_prt; -#ifdef CONFIG_X86 -extern void eisa_set_level_irq(unsigned int irq); -#endif - /* -------------------------------------------------------------------------- PCI IRQ Routing Table (PRT) Support @@ -237,12 +227,18 @@ PCI Interrupt Routing Support -------------------------------------------------------------------------- */ -int -acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin) +static int +acpi_pci_irq_lookup ( + struct pci_bus *bus, + int device, + int pin, + int *edge_level, + int *active_high_low) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); int bus_nr = bus->number; + int irq; ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); @@ -255,28 +251,30 @@ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); return_VALUE(0); } - - if (!entry->irq && entry->link.handle) { - entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, NULL, NULL); - if (!entry->irq) { + + if (entry->link.handle) { + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low); + if (!irq) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); return_VALUE(0); } - } - else if (!entry->irq) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n")); - return_VALUE(0); + } else { + irq = entry->link.index; + *edge_level = ACPI_LEVEL_SENSITIVE; + *active_high_low = ACPI_ACTIVE_LOW; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); - return_VALUE(entry->irq); + return_VALUE(irq); } static int acpi_pci_irq_derive ( struct pci_dev *dev, - int pin) + int pin, + int *edge_level, + int *active_high_low) { struct pci_dev *bridge = dev; int irq = 0; @@ -308,8 +306,8 @@ pin = bridge_pin; } - irq = acpi_pci_irq_lookup(bridge->bus, - PCI_SLOT(bridge->devfn), pin); + irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), + pin, edge_level, active_high_low); } if (!irq) { @@ -330,6 +328,8 @@ { int irq = 0; u8 pin = 0; + int edge_level = ACPI_LEVEL_SENSITIVE; + int active_high_low = ACPI_ACTIVE_LOW; ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); @@ -352,21 +352,22 @@ * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin); + irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (!irq) - irq = acpi_pci_irq_derive(dev, pin); + irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. */ if (!irq) { - printk(KERN_WARNING PREFIX "No IRQ known for interrupt pin %c of device %s", ('A' + pin), pci_name(dev)); + printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI", + pci_name(dev), ('A' + pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq && (dev->irq <= 0xF)) { printk(" - using IRQ %d\n", dev->irq); @@ -378,62 +379,14 @@ } } - dev->irq = irq; + dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", pci_name(dev), dev->irq)); - - /* - * Make sure all (legacy) PCI IRQs are set as level-triggered. - */ -#ifdef CONFIG_X86 - { - static u16 irq_mask; - if ((dev->irq < 16) && !((1 << dev->irq) & irq_mask)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Setting IRQ %d as level-triggered\n", dev->irq)); - irq_mask |= (1 << dev->irq); - eisa_set_level_irq(dev->irq); - } - } -#endif -#ifdef CONFIG_IOSAPIC - if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC) - iosapic_enable_intr(dev->irq); -#endif + printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u " + "(%s, %s) -> IRQ %d\n", + pci_name(dev), 'A' + pin, irq, + (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", + (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", + dev->irq); return_VALUE(dev->irq); -} - - -int __init -acpi_pci_irq_init (void) -{ - struct pci_dev *dev = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_irq_init"); - - if (!acpi_prt.count) { - printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ " - "routing entries\n"); - return_VALUE(-ENODEV); - } - - /* Make sure all link devices have a valid IRQ. */ - if (acpi_pci_link_check()) { - return_VALUE(-ENODEV); - } - -#ifdef CONFIG_X86_IO_APIC - /* Program IOAPICs using data from PRT entries. */ - if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) - mp_parse_prt(); -#endif -#ifdef CONFIG_IOSAPIC - if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC) - iosapic_parse_prt(); -#endif - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) - acpi_pci_irq_enable(dev); - - return_VALUE(0); } diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- a/drivers/acpi/pci_link.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/acpi/pci_link.c 2004-06-20 13:00:23 -07:00 @@ -308,31 +308,12 @@ struct acpi_resource end; } resource; struct acpi_buffer buffer = {sizeof(resource)+1, &resource}; - int i = 0; - int valid = 0; ACPI_FUNCTION_TRACE("acpi_pci_link_set"); if (!link || !irq) return_VALUE(-EINVAL); - /* We don't check irqs the first time around */ - if (link->irq.setonboot) { - /* See if we're already at the target IRQ. */ - if (irq == link->irq.active) - return_VALUE(0); - - /* Make sure the target IRQ in the list of possible IRQs. */ - for (i=0; iirq.possible_count; i++) { - if (irq == link->irq.possible[i]) - valid = 1; - } - if (!valid) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq)); - return_VALUE(-EINVAL); - } - } - memset(&resource, 0, sizeof(resource)); switch(link->irq.resource_type) { @@ -487,13 +468,13 @@ }; int -acpi_pci_link_check (void) +acpi_irq_penalty_init(void) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; int i = 0; - ACPI_FUNCTION_TRACE("acpi_pci_link_check"); + ACPI_FUNCTION_TRACE("acpi_irq_penalty_init"); /* * Update penalties to facilitate IRQ balancing. @@ -703,6 +684,9 @@ acpi_link.count++; end: + /* disable all links -- to be activated on use */ + acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + if (result) kfree(link); diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c --- a/drivers/acpi/pci_root.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/acpi/pci_root.c 2004-06-20 13:00:23 -07:00 @@ -113,6 +113,40 @@ } } +static acpi_status +get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data) +{ + int *busnr = (int *)data; + struct acpi_resource_address64 address; + + if (resource->id != ACPI_RSTYPE_ADDRESS16 && + resource->id != ACPI_RSTYPE_ADDRESS32 && + resource->id != ACPI_RSTYPE_ADDRESS64) + return AE_OK; + + acpi_resource_to_address64(resource, &address); + if ((address.address_length > 0) && + (address.resource_type == ACPI_BUS_NUMBER_RANGE)) + *busnr = address.min_address_range; + + return AE_OK; +} + +static acpi_status +try_get_root_bridge_busnr(acpi_handle handle, int *busnum) +{ + acpi_status status; + + *busnum = -1; + status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum); + if (ACPI_FAILURE(status)) + return status; + /* Check if we really get a bus number from _CRS */ + if (*busnum == -1) + return AE_ERROR; + return AE_OK; +} + static int acpi_pci_root_add ( struct acpi_device *device) @@ -190,9 +224,22 @@ /* Some systems have wrong _BBN */ list_for_each_entry(tmp, &acpi_pci_roots, node) { if ((tmp->id.segment == root->id.segment) - && (tmp->id.bus == root->id.bus)) + && (tmp->id.bus == root->id.bus)) { + int bus = 0; + acpi_status status; + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Wrong _BBN value, please reboot and using option 'pci=noacpi'\n")); + + status = try_get_root_bridge_busnr(root->handle, &bus); + if (ACPI_FAILURE(status)) + break; + if (bus != root->id.bus) { + printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus); + root->id.bus = bus; + } + break; + } } /* * Device & Function diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c --- a/drivers/acpi/tables.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/acpi/tables.c 2004-06-20 13:00:24 -07:00 @@ -131,7 +131,7 @@ { struct acpi_table_ioapic *p = (struct acpi_table_ioapic*) header; - printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n", + printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", p->id, p->address, p->global_irq_base); } break; @@ -185,8 +185,8 @@ { struct acpi_table_iosapic *p = (struct acpi_table_iosapic*) header; - printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n", - p->id, p->global_irq_base, (void *) (unsigned long) p->address); + printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", + p->id, (void *) (unsigned long) p->address, p->global_irq_base); } break; diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c --- a/drivers/acpi/thermal.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/acpi/thermal.c 2004-06-20 13:00:25 -07:00 @@ -289,6 +289,13 @@ status = acpi_get_handle(tz->handle, "_SCP", &handle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); + status = acpi_get_handle(tz->handle, "_PSV", &handle); + if(!ACPI_FAILURE(status)) { + tz->cooling_mode = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", + mode?"passive":"active")); + return_VALUE(0); + } return_VALUE(-ENODEV); } diff -Nru a/drivers/base/cpu.c b/drivers/base/cpu.c --- a/drivers/base/cpu.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/base/cpu.c 2004-06-20 13:00:24 -07:00 @@ -58,6 +58,8 @@ /* * register_cpu - Setup a driverfs device for a CPU. + * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to + * generate a control file in sysfs for this CPU. * @num - CPU number to use when creating the device. * * Initialize and register the CPU device. @@ -75,7 +77,7 @@ error = sysfs_create_link(&root->sysdev.kobj, &cpu->sysdev.kobj, kobject_name(&cpu->sysdev.kobj)); - if (!error) + if (!error && !cpu->no_control) register_cpu_control(cpu); return error; } diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig --- a/drivers/block/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/drivers/block/Kconfig 2004-06-20 13:00:23 -07:00 @@ -6,7 +6,7 @@ config BLK_DEV_FD tristate "Normal floppy disk support" - depends on (!X86_PC9800 && !ARCH_S390 && !M68K && !IA64) || Q40 || (SUN3X && BROKEN) + depends on (!ARCH_S390 && !M68K && !IA64) || Q40 || (SUN3X && BROKEN) ---help--- If you want to use the floppy disk drive(s) of your PC under Linux, say Y. Information about this driver, especially important for IBM @@ -25,13 +25,6 @@ config ATARI_FLOPPY tristate "Atari floppy support" depends on ATARI - -config BLK_DEV_FD98 - tristate "NEC PC-9800 floppy disk support" - depends on X86_PC9800 - ---help--- - If you want to use the floppy disk drive(s) of NEC PC-9801/PC-9821, - say Y. config BLK_DEV_SWIM_IOP bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)" diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/block/cciss.c 2004-06-20 13:00:26 -07:00 @@ -479,6 +479,148 @@ return 0; } +#ifdef CONFIG_COMPAT +/* for AMD 64 bit kernel compatibility with 32-bit userland ioctls */ +extern long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); +extern int +register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, + unsigned int, unsigned long, struct file *)); +extern int unregister_ioctl32_conversion(unsigned int cmd); + +static int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, struct file *file); +static int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg, + struct file *file); + +typedef int (*handler_type) (unsigned int, unsigned int, unsigned long, struct file *); + +static struct ioctl32_map { + unsigned int cmd; + handler_type handler; + int registered; +} cciss_ioctl32_map[] = { + { CCISS_GETPCIINFO, (handler_type) sys_ioctl, 0 }, + { CCISS_GETINTINFO, (handler_type) sys_ioctl, 0 }, + { CCISS_SETINTINFO, (handler_type) sys_ioctl, 0 }, + { CCISS_GETNODENAME, (handler_type) sys_ioctl, 0 }, + { CCISS_SETNODENAME, (handler_type) sys_ioctl, 0 }, + { CCISS_GETHEARTBEAT, (handler_type) sys_ioctl, 0 }, + { CCISS_GETBUSTYPES, (handler_type) sys_ioctl, 0 }, + { CCISS_GETFIRMVER, (handler_type) sys_ioctl, 0 }, + { CCISS_GETDRIVVER, (handler_type) sys_ioctl, 0 }, + { CCISS_REVALIDVOLS, (handler_type) sys_ioctl, 0 }, + { CCISS_PASSTHRU32, cciss_ioctl32_passthru, 0 }, + { CCISS_DEREGDISK, (handler_type) sys_ioctl, 0 }, + { CCISS_REGNEWDISK, (handler_type) sys_ioctl, 0 }, + { CCISS_REGNEWD, (handler_type) sys_ioctl, 0 }, + { CCISS_RESCANDISK, (handler_type) sys_ioctl, 0 }, + { CCISS_GETLUNINFO, (handler_type) sys_ioctl, 0 }, + { CCISS_BIG_PASSTHRU32, cciss_ioctl32_big_passthru, 0 }, +}; +#define NCCISS_IOCTL32_ENTRIES (sizeof(cciss_ioctl32_map) / sizeof(cciss_ioctl32_map[0])) +static void register_cciss_ioctl32(void) +{ + int i, rc; + + for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) { + rc = register_ioctl32_conversion( + cciss_ioctl32_map[i].cmd, + cciss_ioctl32_map[i].handler); + if (rc != 0) { + printk(KERN_WARNING "cciss: failed to register " + "32 bit compatible ioctl 0x%08x\n", + cciss_ioctl32_map[i].cmd); + cciss_ioctl32_map[i].registered = 0; + } else + cciss_ioctl32_map[i].registered = 1; + } +} +static void unregister_cciss_ioctl32(void) +{ + int i, rc; + + for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) { + if (!cciss_ioctl32_map[i].registered) + continue; + rc = unregister_ioctl32_conversion( + cciss_ioctl32_map[i].cmd); + if (rc == 0) { + cciss_ioctl32_map[i].registered = 0; + continue; + } + printk(KERN_WARNING "cciss: failed to unregister " + "32 bit compatible ioctl 0x%08x\n", + cciss_ioctl32_map[i].cmd); + } +} +int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, + struct file *file) +{ + IOCTL32_Command_struct *arg32 = + (IOCTL32_Command_struct *) arg; + IOCTL_Command_struct arg64; + mm_segment_t old_fs; + int err; + unsigned long cp; + + err = 0; + err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info)); + err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request)); + err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info)); + err |= get_user(arg64.buf_size, &arg32->buf_size); + err |= get_user(cp, &arg32->buf); + arg64.buf = (BYTE *)cp; + + if (err) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) &arg64); + set_fs(old_fs); + if (err) + return err; + err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info)); + if (err) + return -EFAULT; + return err; +} +int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg, + struct file *file) +{ + BIG_IOCTL32_Command_struct *arg32 = + (BIG_IOCTL32_Command_struct *) arg; + BIG_IOCTL_Command_struct arg64; + mm_segment_t old_fs; + int err; + unsigned long cp; + + err = 0; + err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info)); + err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request)); + err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info)); + err |= get_user(arg64.buf_size, &arg32->buf_size); + err |= get_user(arg64.malloc_size, &arg32->malloc_size); + err |= get_user(cp, &arg32->buf); + arg64.buf = (BYTE *)cp; + + if (err) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) &arg64); + set_fs(old_fs); + if (err) + return err; + err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info)); + if (err) + return -EFAULT; + return err; +} +#else +static inline void register_cciss_ioctl32(void) {} +static inline void unregister_cciss_ioctl32(void) {} +#endif /* * ioctl */ @@ -2728,6 +2870,7 @@ static int __init init_cciss_module(void) { + register_cciss_ioctl32(); return ( cciss_init()); } @@ -2735,6 +2878,7 @@ { int i; + unregister_cciss_ioctl32(); pci_unregister_driver(&cciss_pci_driver); /* double check that all controller entrys have been removed */ for (i=0; i< MAX_CTLR; i++) diff -Nru a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c --- a/drivers/block/cfq-iosched.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/block/cfq-iosched.c 2004-06-20 13:00:25 -07:00 @@ -59,6 +59,14 @@ unsigned int max_queued; mempool_t *crq_pool; + + request_queue_t *queue; + + /* + * tunables + */ + unsigned int cfq_quantum; + unsigned int cfq_queued; }; struct cfq_queue { @@ -89,7 +97,8 @@ static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq); static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid); -static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq); +static void cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct cfq_rq *crq); /* * lots of deadline iosched dupes, can be abstracted later... @@ -206,8 +215,7 @@ return; } - cfq_del_crq_rb(cfqq, __alias); - cfq_dispatch_sort(cfqd->dispatch, __alias); + cfq_dispatch_sort(cfqd, cfqq, __alias); goto retry; } @@ -321,11 +329,16 @@ cfq_remove_request(q, next); } -static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq) +static void +cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct cfq_rq *crq) { - struct list_head *entry = head; + struct list_head *head = cfqd->dispatch, *entry = head; struct request *__rq; + cfq_del_crq_rb(cfqq, crq); + cfq_remove_merge_hints(cfqd->queue, crq); + if (!list_empty(head)) { __rq = list_entry_rq(head->next); @@ -352,9 +365,7 @@ { struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list)); - cfq_del_crq_rb(cfqq, crq); - cfq_remove_merge_hints(q, crq); - cfq_dispatch_sort(cfqd->dispatch, crq); + cfq_dispatch_sort(cfqd, cfqq, crq); } static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd) @@ -385,7 +396,7 @@ ret = 1; } - if ((queued < cfq_quantum) && good_queues) + if ((queued < cfqd->cfq_quantum) && good_queues) goto restart; return ret; @@ -556,7 +567,7 @@ cfqq = cfq_find_cfq_hash(cfqd, current->tgid); if (cfqq) { - int limit = (q->nr_requests - cfq_queued) / cfqd->busy_queues; + int limit = (q->nr_requests - cfqd->cfq_queued) / cfqd->busy_queues; if (limit < 3) limit = 3; @@ -574,6 +585,8 @@ { struct cfq_data *cfqd = q->elevator.elevator_data; struct cfq_rq *crq = RQ_DATA(rq); + struct request_list *rl; + int other_rw; if (crq) { BUG_ON(q->last_merge == rq); @@ -582,6 +595,23 @@ mempool_free(crq, cfqd->crq_pool); rq->elevator_private = NULL; } + + /* + * work-around for may_queue "bug": if a read gets issued and refused + * to queue because writes ate all the allowed slots and no other + * reads are pending for this queue, it could get stuck infinitely + * since freed_request() only checks the waitqueue for writes when + * freeing them. or vice versa for a single write vs many reads. + * so check here whether "the other" data direction might be able + * to queue and wake them + */ + rl = &q->rq; + other_rw = rq_data_dir(rq) ^ 1; + if (rl->count[other_rw] <= q->nr_requests) { + smp_mb(); + if (waitqueue_active(&rl->wait[other_rw])) + wake_up(&rl->wait[other_rw]); + } } static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) @@ -643,6 +673,7 @@ cfqd->dispatch = &q->queue_head; e->elevator_data = cfqd; + cfqd->queue = q; /* * just set it to some high value, we want anyone to be able to queue @@ -651,6 +682,9 @@ cfqd->max_queued = q->nr_requests; q->nr_requests = 8192; + cfqd->cfq_queued = cfq_queued; + cfqd->cfq_quantum = cfq_quantum; + return 0; out_crqpool: kfree(cfqd->cfq_hash); @@ -685,8 +719,110 @@ subsys_initcall(cfq_slab_setup); +/* + * sysfs parts below --> + */ +struct cfq_fs_entry { + struct attribute attr; + ssize_t (*show)(struct cfq_data *, char *); + ssize_t (*store)(struct cfq_data *, const char *, size_t); +}; + +static ssize_t +cfq_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +cfq_var_store(unsigned int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ +{ \ + return cfq_var_show(__VAR, (page)); \ +} +SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum); +SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ +{ \ + int ret = cfq_var_store(__PTR, (page), count); \ + if (*(__PTR) < (MIN)) \ + *(__PTR) = (MIN); \ + else if (*(__PTR) > (MAX)) \ + *(__PTR) = (MAX); \ + return ret; \ +} +STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, INT_MAX); +STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, INT_MAX); +#undef STORE_FUNCTION + +static struct cfq_fs_entry cfq_quantum_entry = { + .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_quantum_show, + .store = cfq_quantum_store, +}; +static struct cfq_fs_entry cfq_queued_entry = { + .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_queued_show, + .store = cfq_queued_store, +}; + +static struct attribute *default_attrs[] = { + &cfq_quantum_entry.attr, + &cfq_queued_entry.attr, + NULL, +}; + +#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr) + +static ssize_t +cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct cfq_fs_entry *entry = to_cfq(attr); + + if (!entry->show) + return 0; + + return entry->show(e->elevator_data, page); +} + +static ssize_t +cfq_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct cfq_fs_entry *entry = to_cfq(attr); + + if (!entry->store) + return -EINVAL; + + return entry->store(e->elevator_data, page, length); +} + +static struct sysfs_ops cfq_sysfs_ops = { + .show = cfq_attr_show, + .store = cfq_attr_store, +}; + +struct kobj_type cfq_ktype = { + .sysfs_ops = &cfq_sysfs_ops, + .default_attrs = default_attrs, +}; + elevator_t iosched_cfq = { .elevator_name = "cfq", + .elevator_ktype = &cfq_ktype, .elevator_merge_fn = cfq_merge, .elevator_merged_fn = cfq_merged_request, .elevator_merge_req_fn = cfq_merged_requests, diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c --- a/drivers/block/elevator.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/block/elevator.c 2004-06-20 13:00:25 -07:00 @@ -181,6 +181,14 @@ rq->q = q; q->elevator.elevator_add_req_fn(q, rq, where); + + if (blk_queue_plugged(q)) { + int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight; + + if (nrq == q->unplug_thresh) + __generic_unplug_device(q); + } + } void elv_add_request(request_queue_t *q, struct request *rq, int where, diff -Nru a/drivers/block/floppy98.c b/drivers/block/floppy98.c --- a/drivers/block/floppy98.c 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,4682 +0,0 @@ -/* - * linux/drivers/block/floppy.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1993, 1994 Alain Knaff - * Copyright (C) 1998 Alan Cox - */ -/* - * 02.12.91 - Changed to static variables to indicate need for reset - * and recalibrate. This makes some things easier (output_byte reset - * checking etc), and means less interrupt jumping in case of errors, - * so the code is hopefully easier to understand. - */ - -/* - * This file is certainly a mess. I've tried my best to get it working, - * but I don't like programming floppies, and I have only one anyway. - * Urgel. I should check for more errors, and do more graceful error - * recovery. Seems there are problems with several drives. I've tried to - * correct them. No promises. - */ - -/* - * As with hd.c, all routines within this file can (and will) be called - * by interrupts, so extreme caution is needed. A hardware interrupt - * handler may not sleep, or a kernel panic will happen. Thus I cannot - * call "floppy-on" directly, but have to set a special timer interrupt - * etc. - */ - -/* - * 28.02.92 - made track-buffering routines, based on the routines written - * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus. - */ - -/* - * Automatic floppy-detection and formatting written by Werner Almesberger - * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with - * the floppy-change signal detection. - */ - -/* - * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed - * FDC data overrun bug, added some preliminary stuff for vertical - * recording support. - * - * 1992/9/17: Added DMA allocation & DMA functions. -- hhb. - * - * TODO: Errors are still not counted properly. - */ - -/* 1992/9/20 - * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl) - * modeled after the freeware MS-DOS program fdformat/88 V1.8 by - * Christoph H. Hochst\"atter. - * I have fixed the shift values to the ones I always use. Maybe a new - * ioctl() should be created to be able to modify them. - * There is a bug in the driver that makes it impossible to format a - * floppy as the first thing after bootup. - */ - -/* - * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and - * this helped the floppy driver as well. Much cleaner, and still seems to - * work. - */ - -/* 1994/6/24 --bbroad-- added the floppy table entries and made - * minor modifications to allow 2.88 floppies to be run. - */ - -/* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more - * disk types. - */ - -/* - * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger - * format bug fixes, but unfortunately some new bugs too... - */ - -/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write - * errors to allow safe writing by specialized programs. - */ - -/* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks - * by defining bit 1 of the "stretch" parameter to mean put sectors on the - * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's - * drives are "upside-down"). - */ - -/* - * 1995/8/26 -- Andreas Busse -- added Mips support. - */ - -/* - * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent - * features to asm/floppy.h. - */ - -/* - * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of - * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting & - * use of '0' for NULL. - */ - -/* - * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation - * failures. - */ - -/* - * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives. - */ - -/* - * 1999/01/19 -- N.Fujita & Linux/98 Project -- Added code for NEC PC-9800 - * series. - */ - -/* - * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24 - * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were - * being used to store jiffies, which are unsigned longs). - */ - -/* - * 2000/08/28 -- Arnaldo Carvalho de Melo - * - get rid of check_region - * - s/suser/capable/ - */ - -/* - * 2001/08/26 -- Paul Gortmaker - fix insmod oops on machines with no - * floppy controller (lingering task on list after module is gone... boom.) - */ - -/* - * 2002/02/07 -- Anton Altaparmakov - Fix io ports reservation to correct range - * (0x3f2-0x3f5, 0x3f7). This fix is a bit of a hack but the proper fix - * requires many non-obvious changes in arch dependent code. - */ - -/* - * 2002/10/12 -- Osamu Tomita - * split code from floppy.c - * support NEC PC-9800 only - */ - -#define FLOPPY_SANITY_CHECK -#undef FLOPPY_SILENT_DCL_CLEAR - -/* -#define PC9800_DEBUG_FLOPPY -#define PC9800_DEBUG_FLOPPY2 -*/ - -#define REALLY_SLOW_IO - -#define DEBUGT 2 -#define DCL_DEBUG /* debug disk change line */ - -/* do print messages for unexpected interrupts */ -static int print_unex=1; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for the compatibility eject ioctl */ -#include - -/* - * 1998/1/21 -- Richard Gooch -- devfs support - */ - - -#include -#define FLOPPY98_MOTOR_MASK 0x08 - -#include -#define FD98_STATUS (0 + FD_IOPORT ) -#define FD98_DATA (2 + FD_IOPORT ) -#define FD_MODE (4 + FD_IOPORT ) -#define FD_MODE_CHANGE 0xbe -#define FD_EMODE_CHANGE 0x4be - -#include -#include -#include -#include -#include -#include -#include -#include /* CMOS defines */ -#include -#include -#include -#include -#include -#include /* for invalidate_buffers() */ - -/* - * PS/2 floppies have much slower step rates than regular floppies. - * It's been recommended that take about 1/4 of the default speed - * in some more extreme cases. - */ -static int slow_floppy; - -#include -#include -#include -#include -#include - -#ifndef DEFAULT_FLOPPY_IRQ -# define DEFAULT_FLOPPY_IRQ 11 -#endif -#ifndef DEFAULT_FLOPPY_DMA -# define DEFAULT_FLOPPY_DMA 2 -#endif - -static int FLOPPY_IRQ=DEFAULT_FLOPPY_IRQ; -static int FLOPPY_DMA=DEFAULT_FLOPPY_DMA; -static int can_use_virtual_dma=2; -static int auto_detect_mode = 0; -static int retry_auto_detect = 0; -#define FD_AFTER_RESET_DELAY 1000 - -/* ======= - * can use virtual DMA: - * 0 = use of virtual DMA disallowed by config - * 1 = use of virtual DMA prescribed by config - * 2 = no virtual DMA preference configured. By default try hard DMA, - * but fall back on virtual DMA when not enough memory available - */ - -static int use_virtual_dma; -/* ======= - * use virtual DMA - * 0 using hard DMA - * 1 using virtual DMA - * This variable is set to virtual when a DMA mem problem arises, and - * reset back in floppy_grab_irq_and_dma. - * It is not safe to reset it in other circumstances, because the floppy - * driver may have several buffers in use at once, and we do currently not - * record each buffers capabilities - */ - -static spinlock_t floppy_lock = SPIN_LOCK_UNLOCKED; -static struct completion device_release; - -static unsigned short virtual_dma_port=0x3f0; -irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static int set_mode(char mask, char data); -static void register_devfs_entries (int drive) __init; - -#define K_64 0x10000 /* 64KB */ - -/* the following is the mask of allowed drives. By default units 2 and - * 3 of both floppy controllers are disabled, because switching on the - * motor of these drives causes system hangs on some PCI computers. drive - * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if - * a drive is allowed. - * - * NOTE: This must come before we include the arch floppy header because - * some ports reference this variable from there. -DaveM - */ - -static int allowed_drive_mask = 0x0f; - -#include - -static int irqdma_allocated; - -#define LOCAL_END_REQUEST -#define DEVICE_NAME "floppy" - -#include -#include /* for the compatibility eject ioctl */ -#include - -static struct request *current_req; -static struct request_queue *floppy_queue; - -#ifndef fd_get_dma_residue -#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) -#endif - -/* Dma Memory related stuff */ - -#ifndef fd_dma_mem_free -#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size)) -#endif - -#ifndef fd_dma_mem_alloc -#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size)) -#endif - -static inline void fallback_on_nodma_alloc(char **addr, size_t l) -{ -#ifdef FLOPPY_CAN_FALLBACK_ON_NODMA - if (*addr) - return; /* we have the memory */ - if (can_use_virtual_dma != 2) - return; /* no fallback allowed */ - printk("DMA memory shortage. Temporarily falling back on virtual DMA\n"); - *addr = (char *) nodma_mem_alloc(l); -#else - return; -#endif -} - -/* End dma memory related stuff */ - -static unsigned long fake_change; -static int initialising=1; - -#define ITYPE(x) (((x)>>2) & 0x1f) -#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) -#define UNIT(x) ((x) & 0x03) /* drive on fdc */ -#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ -#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) - /* reverse mapping from unit and fdc to drive */ -#define DP (&drive_params[current_drive]) -#define DRS (&drive_state[current_drive]) -#define DRWE (&write_errors[current_drive]) -#define FDCS (&fdc_state[fdc]) -#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags)) -#define SETF(x) (set_bit(x##_BIT, &DRS->flags)) -#define TESTF(x) (test_bit(x##_BIT, &DRS->flags)) - -#define UDP (&drive_params[drive]) -#define UDRS (&drive_state[drive]) -#define UDRWE (&write_errors[drive]) -#define UFDCS (&fdc_state[FDC(drive)]) -#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags)) -#define USETF(x) (set_bit(x##_BIT, &UDRS->flags)) -#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags)) - -#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args) - -#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2) -#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) - -#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x))) - -/* read/write */ -#define COMMAND raw_cmd->cmd[0] -#define DR_SELECT raw_cmd->cmd[1] -#define TRACK raw_cmd->cmd[2] -#define HEAD raw_cmd->cmd[3] -#define SECTOR raw_cmd->cmd[4] -#define SIZECODE raw_cmd->cmd[5] -#define SECT_PER_TRACK raw_cmd->cmd[6] -#define GAP raw_cmd->cmd[7] -#define SIZECODE2 raw_cmd->cmd[8] -#define NR_RW 9 - -/* format */ -#define F_SIZECODE raw_cmd->cmd[2] -#define F_SECT_PER_TRACK raw_cmd->cmd[3] -#define F_GAP raw_cmd->cmd[4] -#define F_FILL raw_cmd->cmd[5] -#define NR_F 6 - -/* - * Maximum disk size (in kilobytes). This default is used whenever the - * current disk size is unknown. - * [Now it is rather a minimum] - */ -#define MAX_DISK_SIZE 4 /* 3984*/ - - -/* - * globals used by 'result()' - */ -#define MAX_REPLIES 16 -static unsigned char reply_buffer[MAX_REPLIES]; -static int inr; /* size of reply buffer, when called from interrupt */ -#define ST0 (reply_buffer[0]) -#define ST1 (reply_buffer[1]) -#define ST2 (reply_buffer[2]) -#define ST3 (reply_buffer[0]) /* result of GETSTATUS */ -#define R_TRACK (reply_buffer[3]) -#define R_HEAD (reply_buffer[4]) -#define R_SECTOR (reply_buffer[5]) -#define R_SIZECODE (reply_buffer[6]) - -#define SEL_DLY (2*HZ/100) - -/* - * this struct defines the different floppy drive types. - */ -static struct { - struct floppy_drive_params params; - const char *name; /* name printed while booting */ -} default_drive_params[]= { -/* NOTE: the time values in jiffies should be in msec! - CMOS drive type - | Maximum data rate supported by drive type - | | Head load time, msec - | | | Head unload time, msec (not used) - | | | | Step rate interval, usec - | | | | | Time needed for spinup time (jiffies) - | | | | | | Timeout for spinning down (jiffies) - | | | | | | | Spindown offset (where disk stops) - | | | | | | | | Select delay - | | | | | | | | | RPS - | | | | | | | | | | Max number of tracks - | | | | | | | | | | | Interrupt timeout - | | | | | | | | | | | | Max nonintlv. sectors - | | | | | | | | | | | | | -Max Errors- flags */ -{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0, - 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" }, - -{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0, - 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/ - -{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0, - 0, { 2, 6, 4, 0, 0, 0, 0, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/ - -{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, - 0, { 4, 6, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/ - -{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, - 0, { 7,10, 2, 4, 6, 0, 0, 0}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/ - -{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, - 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/ - -{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, - 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/ -/* | --autodetected formats--- | | | - * read_track | | Name printed when booting - * | Native format - * Frequency of disk change checks */ -}; - -static struct floppy_drive_params drive_params[N_DRIVE]; -static struct floppy_drive_struct drive_state[N_DRIVE]; -static struct floppy_write_errors write_errors[N_DRIVE]; -static struct timer_list motor_off_timer[N_DRIVE]; -static struct gendisk *disks[N_DRIVE]; -static struct block_device *opened_bdev[N_DRIVE]; -static DECLARE_MUTEX(open_lock); -static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; - -/* - * This struct defines the different floppy types. - * - * Bit 0 of 'stretch' tells if the tracks need to be doubled for some - * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch' - * tells if the disk is in Commodore 1581 format, which means side 0 sectors - * are located on side 1 of the disk but with a side 0 ID, and vice-versa. - * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the - * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical - * side 0 is on physical side 0 (but with the misnamed sector IDs). - * 'stretch' should probably be renamed to something more general, like - * 'options'. Other parameters should be self-explanatory (see also - * setfdprm(8)). - */ -/* - Size - | Sectors per track - | | Head - | | | Tracks - | | | | Stretch - | | | | | Gap 1 size - | | | | | | Data rate, | 0x40 for perp - | | | | | | | Spec1 (stepping rate, head unload - | | | | | | | | /fmt gap (gap2) */ -static struct floppy_struct floppy_type[32] = { - { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */ -#if 0 - { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */ -#else - { 2464,16,2,77,0,0x35,0x48,0xDF,0x74,"d360" }, /* 1 1.25MB 98 */ -#endif - { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */ - { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */ - { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */ - { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */ - { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */ - { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */ - { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */ - { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */ - - { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */ - { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */ - { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */ - { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */ - { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */ - { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */ - { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */ - { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */ - { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */ - { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */ - - { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */ - { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */ - { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */ - { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */ - { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */ - { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */ - { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */ - { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */ - { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */ - - { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */ - { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ - { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ -}; - -#define NUMBER(x) (sizeof(x) / sizeof(*(x))) -#define SECTSIZE (_FD_SECTSIZE(*floppy)) - -/* Auto-detection: Disk type used until the next media change occurs. */ -static struct floppy_struct *current_type[N_DRIVE]; - -/* - * User-provided type information. current_type points to - * the respective entry of this array. - */ -static struct floppy_struct user_params[N_DRIVE]; - -static sector_t floppy_sizes[256]; - -/* - * The driver is trying to determine the correct media format - * while probing is set. rw_interrupt() clears it after a - * successful access. - */ -static int probing; - -/* Synchronization of FDC access. */ -#define FD_COMMAND_NONE -1 -#define FD_COMMAND_ERROR 2 -#define FD_COMMAND_OKAY 3 - -static volatile int command_status = FD_COMMAND_NONE; -static unsigned long fdc_busy; -static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); -static DECLARE_WAIT_QUEUE_HEAD(command_done); - -#define NO_SIGNAL (!interruptible || !signal_pending(current)) -#define CALL(x) if ((x) == -EINTR) return -EINTR -#define ECALL(x) if ((ret = (x))) return ret; -#define _WAIT(x,i) CALL(ret=wait_til_done((x),i)) -#define WAIT(x) _WAIT((x),interruptible) -#define IWAIT(x) _WAIT((x),1) - -/* Errors during formatting are counted here. */ -static int format_errors; - -/* Format request descriptor. */ -static struct format_descr format_req; - -/* - * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps - * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc), - * H is head unload time (1=16ms, 2=32ms, etc) - */ - -/* - * Track buffer - * Because these are written to by the DMA controller, they must - * not contain a 64k byte boundary crossing, or data will be - * corrupted/lost. - */ -static char *floppy_track_buffer; -static int max_buffer_sectors; - -static int *errors; -typedef void (*done_f)(int); -static struct cont_t { - void (*interrupt)(void); /* this is called after the interrupt of the - * main command */ - void (*redo)(void); /* this is called to retry the operation */ - void (*error)(void); /* this is called to tally an error */ - done_f done; /* this is called to say if the operation has - * succeeded/failed */ -} *cont; - -static void floppy_ready(void); -static void floppy_start(void); -static void process_fd_request(void); -static void recalibrate_floppy(void); -static void floppy_shutdown(unsigned long); - -static int floppy_grab_irq_and_dma(void); -static void floppy_release_irq_and_dma(void); - -/* - * The "reset" variable should be tested whenever an interrupt is scheduled, - * after the commands have been sent. This is to ensure that the driver doesn't - * get wedged when the interrupt doesn't come because of a failed command. - * reset doesn't need to be tested before sending commands, because - * output_byte is automatically disabled when reset is set. - */ -#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } } -static void reset_fdc(void); - -/* - * These are global variables, as that's the easiest way to give - * information to interrupts. They are the data used for the current - * request. - */ -#define NO_TRACK -1 -#define NEED_1_RECAL -2 -#define NEED_2_RECAL -3 - -static int usage_count; - -/* buffer related variables */ -static int buffer_track = -1; -static int buffer_drive = -1; -static int buffer_min = -1; -static int buffer_max = -1; - -/* fdc related variables, should end up in a struct */ -static struct floppy_fdc_state fdc_state[N_FDC]; -static int fdc; /* current fdc */ - -static struct floppy_struct *_floppy = floppy_type; -static unsigned char current_drive; -static long current_count_sectors; -static unsigned char fsector_t; /* sector in track */ -static unsigned char in_sector_offset; /* offset within physical sector, - * expressed in units of 512 bytes */ - -#ifndef fd_eject -static inline int fd_eject(int drive) -{ - return -EINVAL; -} -#endif - -#ifdef DEBUGT -static long unsigned debugtimer; -#endif - -/* - * Debugging - * ========= - */ -static inline void set_debugt(void) -{ -#ifdef DEBUGT - debugtimer = jiffies; -#endif -} - -static inline void debugt(const char *message) -{ -#ifdef DEBUGT - if (DP->flags & DEBUGT) - printk("%s dtime=%lu\n", message, jiffies-debugtimer); -#endif -} - -typedef void (*timeout_fn)(unsigned long); -static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0); - -static const char *timeout_message; - -#ifdef FLOPPY_SANITY_CHECK -static void is_alive(const char *message) -{ - /* this routine checks whether the floppy driver is "alive" */ - if (fdc_busy && command_status < 2 && !timer_pending(&fd_timeout)){ - DPRINT("timeout handler died: %s\n",message); - } -} -#endif - -static void (*do_floppy)(void) = NULL; - -#ifdef FLOPPY_SANITY_CHECK - -#define OLOGSIZE 20 - -static void (*lasthandler)(void); -static unsigned long interruptjiffies; -static unsigned long resultjiffies; -static int resultsize; -static unsigned long lastredo; - -static struct output_log { - unsigned char data; - unsigned char status; - unsigned long jiffies; -} output_log[OLOGSIZE]; - -static int output_log_pos; -#endif - -#define current_reqD -1 -#define MAXTIMEOUT -2 - -static void reschedule_timeout(int drive, const char *message, int marg) -{ - unsigned long delay; - - if (drive == current_reqD) - drive = current_drive; - if (drive < 0 || drive > N_DRIVE) { - delay = 20UL*HZ; - drive=0; - } else - delay = UDP->timeout; - mod_timer(&fd_timeout, delay + jiffies); - if (UDP->flags & FD_DEBUG){ - DPRINT("reschedule timeout "); - printk(message, marg); - printk("\n"); - } - timeout_message = message; -} - -static int maximum(int a, int b) -{ - if (a > b) - return a; - else - return b; -} -#define INFBOUND(a,b) (a)=maximum((a),(b)); - -static int minimum(int a, int b) -{ - if (a < b) - return a; - else - return b; -} -#define SUPBOUND(a,b) (a)=minimum((a),(b)); - - -/* - * Bottom half floppy driver. - * ========================== - * - * This part of the file contains the code talking directly to the hardware, - * and also the main service loop (seek-configure-spinup-command) - */ - -/* - * disk change. - * This routine is responsible for maintaining the FD_DISK_CHANGE flag, - * and the last_checked date. - * - * last_checked is the date of the last check which showed 'no disk change' - * FD_DISK_CHANGE is set under two conditions: - * 1. The floppy has been changed after some i/o to that floppy already - * took place. - * 2. No floppy disk is in the drive. This is done in order to ensure that - * requests are quickly flushed in case there is no disk in the drive. It - * follows that FD_DISK_CHANGE can only be cleared if there is a disk in - * the drive. - * - * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet. - * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on - * each seek. If a disk is present, the disk change line should also be - * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk - * change line is set, this means either that no disk is in the drive, or - * that it has been removed since the last seek. - * - * This means that we really have a third possibility too: - * The floppy has been changed after the last seek. - */ - -static int disk_change(int drive) -{ - return UTESTF(FD_DISK_CHANGED); -} - -static int set_mode(char mask, char data) -{ - register unsigned char newdor, olddor; - - olddor = FDCS->dor; - newdor = (olddor & mask) | data; - if (newdor != olddor) { - FDCS->dor = newdor; - fd_outb(newdor, FD_MODE); - } - - if (newdor & FLOPPY98_MOTOR_MASK) - floppy_grab_irq_and_dma(); - - if (olddor & FLOPPY98_MOTOR_MASK) - floppy_release_irq_and_dma(); - - return olddor; -} - -static void twaddle(void) -{ - if (DP->select_delay) - return; - - fd_outb(FDCS->dor & 0xf7, FD_MODE); - fd_outb(FDCS->dor, FD_MODE); - DRS->select_date = jiffies; -} - -/* reset all driver information about the current fdc. This is needed after - * a reset, and after a raw command. */ -static void reset_fdc_info(int mode) -{ - int drive; - - FDCS->spec1 = FDCS->spec2 = -1; - FDCS->need_configure = 1; - FDCS->perp_mode = 1; - FDCS->rawcmd = 0; - for (drive = 0; drive < N_DRIVE; drive++) - if (FDC(drive) == fdc && - (mode || UDRS->track != NEED_1_RECAL)) - UDRS->track = NEED_2_RECAL; -} - -/* selects the fdc and drive, and enables the fdc's input/dma. */ -static void set_fdc(int drive) -{ - fdc = 0; - current_drive = drive; - set_mode(~0, 0x10); - if (FDCS->rawcmd == 2) - reset_fdc_info(1); - - if (fd_inb(FD98_STATUS) != STATUS_READY) - FDCS->reset = 1; -} - -/* locks the driver */ -static int _lock_fdc(int drive, int interruptible, int line) -{ - if (!usage_count){ - printk(KERN_ERR "Trying to lock fdc while usage count=0 at line %d\n", line); - return -1; - } - if(floppy_grab_irq_and_dma()==-1) - return -EBUSY; - - if (test_and_set_bit(0, &fdc_busy)) { - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(&fdc_wait, &wait); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - if (!test_and_set_bit(0, &fdc_busy)) - break; - - schedule(); - - if (!NO_SIGNAL) { - remove_wait_queue(&fdc_wait, &wait); - return -EINTR; - } - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&fdc_wait, &wait); - } - command_status = FD_COMMAND_NONE; - - reschedule_timeout(drive, "lock fdc", 0); - set_fdc(drive); - return 0; -} - -#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__) - -#define LOCK_FDC(drive,interruptible) \ -if (lock_fdc(drive,interruptible)) return -EINTR; - - -/* unlocks the driver */ -static inline void unlock_fdc(void) -{ - raw_cmd = 0; - if (!fdc_busy) - DPRINT("FDC access conflict!\n"); - - if (do_floppy) - DPRINT("device interrupt still active at FDC release: %p!\n", - do_floppy); - command_status = FD_COMMAND_NONE; - del_timer(&fd_timeout); - cont = NULL; - clear_bit(0, &fdc_busy); - floppy_release_irq_and_dma(); - wake_up(&fdc_wait); -} - -#ifndef CONFIG_PC9800_MOTOR_OFF /* tomita */ - -/* switches the motor off after a given timeout */ -static void motor_off_callback(unsigned long nr) -{ - printk(KERN_DEBUG "fdc%lu: turn off motor\n", nr); -} - -/* schedules motor off */ -static void floppy_off(unsigned int drive) -{ -} - -#else /* CONFIG_PC9800_MOTOR_OFF */ - -/* switches the motor off after a given timeout */ -static void motor_off_callback(unsigned long fdc) -{ - printk(KERN_DEBUG "fdc%u: turn off motor\n", (unsigned int) fdc); - - fd_outb(0, FD_MODE); /* MTON = 0 */ -} - -static struct timer_list motor_off_timer[N_FDC] = { - { data: 0, function: motor_off_callback }, -#if N_FDC > 1 - { data: 1, function: motor_off_callback }, -#endif -#if N_FDC > 2 -# error "N_FDC > 2; please fix initializer for motor_off_timer[]" -#endif -}; - -/* schedules motor off */ -static void floppy_off(unsigned int drive) -{ - unsigned long volatile delta; - register int fdc = FDC(drive); - - if (!(FDCS->dor & (0x10 << UNIT(drive)))) - return; - - del_timer(motor_off_timer + fdc); - -#if 0 - /* make spindle stop in a position which minimizes spinup time - * next time */ - if (UDP->rps){ - delta = jiffies - UDRS->first_read_date + HZ - - UDP->spindown_offset; - delta = ((delta * UDP->rps) % HZ) / UDP->rps; - motor_off_timer[drive].expires = jiffies + UDP->spindown - delta; - } -#else - if (UDP->rps) - motor_off_timer[drive].expires = jiffies + UDP->spindown; -#endif - - add_timer(motor_off_timer + fdc); -} - -#endif /* CONFIG_PC9800_MOTOR_OFF */ - -/* - * cycle through all N_DRIVE floppy drives, for disk change testing. - * stopping at current drive. This is done before any long operation, to - * be sure to have up to date disk change information. - */ -static void scandrives(void) -{ - int i, drive, saved_drive; - - if (DP->select_delay) - return; - - saved_drive = current_drive; - for (i=0; i < N_DRIVE; i++){ - drive = (saved_drive + i + 1) % N_DRIVE; - if (UDRS->fd_ref == 0 || UDP->select_delay != 0) - continue; /* skip closed drives */ - set_fdc(drive); - } - set_fdc(saved_drive); -} - -static void empty(void) -{ -} - -static DECLARE_WORK(floppy_work, NULL, NULL); - -static void schedule_bh(void (*handler) (void)) -{ - PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL); - schedule_work(&floppy_work); -} - -static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0); - -static void cancel_activity(void) -{ - do_floppy = NULL; - PREPARE_WORK(&floppy_work, (void*)(void*)empty, NULL); - del_timer(&fd_timer); -} - -/* this function makes sure that the disk stays in the drive during the - * transfer */ -static void fd_watchdog(void) -{ -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("calling disk change from watchdog\n"); - } -#endif - - if (disk_change(current_drive)){ - DPRINT("disk removed during i/o\n"); - cancel_activity(); - cont->done(0); - reset_fdc(); - } else { - del_timer(&fd_timer); - fd_timer.function = (timeout_fn) fd_watchdog; - fd_timer.expires = jiffies + HZ / 10; - add_timer(&fd_timer); - } -} - -static void main_command_interrupt(void) -{ - del_timer(&fd_timer); - cont->interrupt(); -} - -/* waits for a delay (spinup or select) to pass */ -static int fd_wait_for_completion(unsigned long delay, timeout_fn function) -{ - if (FDCS->reset){ - reset_fdc(); /* do the reset during sleep to win time - * if we don't need to sleep, it's a good - * occasion anyways */ - return 1; - } - - if ((signed) (jiffies - delay) < 0){ - del_timer(&fd_timer); - fd_timer.function = function; - fd_timer.expires = delay; - add_timer(&fd_timer); - return 1; - } - return 0; -} - -static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED; -static int hlt_disabled; -static void floppy_disable_hlt(void) -{ - unsigned long flags; - - spin_lock_irqsave(&floppy_hlt_lock, flags); - if (!hlt_disabled) { - hlt_disabled=1; -#ifdef HAVE_DISABLE_HLT - disable_hlt(); -#endif - } - spin_unlock_irqrestore(&floppy_hlt_lock, flags); -} - -static void floppy_enable_hlt(void) -{ - unsigned long flags; - - spin_lock_irqsave(&floppy_hlt_lock, flags); - if (hlt_disabled){ - hlt_disabled=0; -#ifdef HAVE_DISABLE_HLT - enable_hlt(); -#endif - } - spin_unlock_irqrestore(&floppy_hlt_lock, flags); -} - - -static void setup_DMA(void) -{ - unsigned long f; - -#ifdef FLOPPY_SANITY_CHECK - if (raw_cmd->length == 0){ - int i; - - printk("zero dma transfer size:"); - for (i=0; i < raw_cmd->cmd_count; i++) - printk("%x,", raw_cmd->cmd[i]); - printk("\n"); - cont->done(0); - FDCS->reset = 1; - return; - } - if (((unsigned long) raw_cmd->kernel_data) % 512){ - printk("non aligned address: %p\n", raw_cmd->kernel_data); - cont->done(0); - FDCS->reset=1; - return; - } -#endif - f=claim_dma_lock(); - fd_disable_dma(); -#ifdef fd_dma_setup - if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, - (raw_cmd->flags & FD_RAW_READ)? - DMA_MODE_READ : DMA_MODE_WRITE, - FDCS->address) < 0) { - release_dma_lock(f); - cont->done(0); - FDCS->reset=1; - return; - } - release_dma_lock(f); -#else - fd_clear_dma_ff(); - fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length); - fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ)? - DMA_MODE_READ : DMA_MODE_WRITE); - fd_set_dma_addr(raw_cmd->kernel_data); - fd_set_dma_count(raw_cmd->length); - virtual_dma_port = FDCS->address; - fd_enable_dma(); - release_dma_lock(f); -#endif - floppy_disable_hlt(); -} - -static void show_floppy(void); - -/* waits until the fdc becomes ready */ - -#ifdef PC9800_DEBUG_FLOPPY -#define READY_DELAY 10000000 -#else -#define READY_DELAY 100000 -#endif - -static int wait_til_ready(void) -{ - int counter, status; - if (FDCS->reset) - return -1; - for (counter = 0; counter < READY_DELAY; counter++) { - status = fd_inb(FD98_STATUS); - if (status & STATUS_READY) - return status; - } - if (!initialising) { - DPRINT("Getstatus times out (%x) on fdc %d\n", - status, fdc); - show_floppy(); - } - FDCS->reset = 1; - return -1; -} - -/* sends a command byte to the fdc */ -static int output_byte(char byte) -{ - int status; - - if ((status = wait_til_ready()) < 0) - return -1; - if ((status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY){ - fd_outb(byte,FD98_DATA); -#ifdef FLOPPY_SANITY_CHECK - output_log[output_log_pos].data = byte; - output_log[output_log_pos].status = status; - output_log[output_log_pos].jiffies = jiffies; - output_log_pos = (output_log_pos + 1) % OLOGSIZE; -#endif - return 0; - } - FDCS->reset = 1; - if (!initialising) { - DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", - byte, fdc, status); - show_floppy(); - } - return -1; -} -#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;} - -/* gets the response from the fdc */ -static int result(void) -{ - int i, status=0; - - for(i=0; i < MAX_REPLIES; i++) { - if ((status = wait_til_ready()) < 0) - break; - status &= STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA; - if ((status & ~STATUS_BUSY) == STATUS_READY){ -#ifdef FLOPPY_SANITY_CHECK - resultjiffies = jiffies; - resultsize = i; -#endif - return i; - } - if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) - reply_buffer[i] = fd_inb(FD98_DATA); - else - break; - } - if (!initialising) { - DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", - fdc, status, i); - show_floppy(); - } - FDCS->reset = 1; - return -1; -} - -static int fifo_depth = 0xa; -static int no_fifo; - -#define NOMINAL_DTR 500 - -/* Issue a "SPECIFY" command to set the step rate time, head unload time, - * head load time, and DMA disable flag to values needed by floppy. - * - * The value "dtr" is the data transfer rate in Kbps. It is needed - * to account for the data rate-based scaling done by the 82072 and 82077 - * FDC types. This parameter is ignored for other types of FDCs (i.e. - * 8272a). - * - * Note that changing the data transfer rate has a (probably deleterious) - * effect on the parameters subject to scaling for 82072/82077 FDCs, so - * fdc_specify is called again after each data transfer rate - * change. - * - * srt: 1000 to 16000 in microseconds - * hut: 16 to 240 milliseconds - * hlt: 2 to 254 milliseconds - * - * These values are rounded up to the next highest available delay time. - */ -static void fdc_specify(void) -{ - output_byte(FD_SPECIFY); - output_byte(FDCS->spec1 = 0xdf); - output_byte(FDCS->spec2 = 0x24); -} - -static void tell_sector(void) -{ - printk(": track %d, head %d, sector %d, size %d", - R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); -} /* tell_sector */ - -static int auto_detect_mode_pc9800(void) -{ -#ifdef PC9800_DEBUG_FLOPPY - printk("auto_detect_mode_pc9800: retry_auto_detect=%d\n", - retry_auto_detect); -#endif - if (retry_auto_detect > 4) { - retry_auto_detect = 0; - return 1; - } - - switch ((int)(_floppy - floppy_type)) { - case 2: - _floppy = floppy_type + 4; - break; - - case 4: - case 6: - _floppy = floppy_type + 7; - break; - - case 7: - case 10: - _floppy = floppy_type + 2; - break; - - default: - _floppy = floppy_type + 7; - } - - retry_auto_detect++; - return 0; -} - -static void access_mode_change_pc9800(void); - -/* - * OK, this error interpreting routine is called after a - * DMA read/write has succeeded - * or failed, so we check the results, and copy any buffers. - * hhb: Added better error reporting. - * ak: Made this into a separate routine. - */ -static int interpret_errors(void) -{ - char bad; - - if (inr!=7) { - DPRINT("-- FDC reply error"); - FDCS->reset = 1; - return 1; - } - - /* check IC to find cause of interrupt */ - switch (ST0 & ST0_INTR) { - case 0x40: /* error occurred during command execution */ - if (ST1 & ST1_EOC) - return 0; /* occurs with pseudo-DMA */ - bad = 1; - if (ST1 & ST1_WP) { - DPRINT("Drive is write protected\n"); - CLEARF(FD_DISK_WRITABLE); - cont->done(0); - bad = 2; - } else if (ST1 & ST1_ND) { - SETF(FD_NEED_TWADDLE); - } else if (ST1 & ST1_OR) { - if (DP->flags & FTD_MSG) - DPRINT("Over/Underrun - retrying\n"); - bad = 0; - }else if (*errors >= DP->max_errors.reporting){ - if (ST0 & ST0_ECE) { - printk("Recalibrate failed!"); - } else if (ST2 & ST2_CRC) { - printk("data CRC error"); - tell_sector(); - } else if (ST1 & ST1_CRC) { - printk("CRC error"); - tell_sector(); - } else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) { - if (auto_detect_mode) { - bad = (char)auto_detect_mode_pc9800(); - access_mode_change_pc9800(); - } - - if (bad) { - printk("floppy error: MA: _floppy - floppy_type=%d\n", (int)(_floppy - floppy_type)); - printk("bad=%d\n", (int)bad); - if (!probing) { - printk("sector not found"); - tell_sector(); - } else - printk("probe failed..."); - } - } else if (ST2 & ST2_WC) { /* seek error */ - printk("wrong cylinder"); - } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ - printk("bad cylinder"); - } else { - printk("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", ST0, ST1, ST2); - tell_sector(); - } - printk("\n"); - - } - if (ST2 & ST2_WC || ST2 & ST2_BC) - /* wrong cylinder => recal */ - DRS->track = NEED_2_RECAL; - return bad; - case 0x80: /* invalid command given */ - DPRINT("Invalid FDC command given!\n"); - cont->done(0); - return 2; - case 0xc0: - SETF(FD_DISK_CHANGED); - SETF(FD_DISK_WRITABLE); - DPRINT("Abnormal termination caused by polling\n"); - cont->error(); - return 2; - default: /* (0) Normal command termination */ - auto_detect_mode = 0; - return 0; - } -} - -/* - * This routine is called when everything should be correctly set up - * for the transfer (i.e. floppy motor is on, the correct floppy is - * selected, and the head is sitting on the right track). - */ -static void setup_rw_floppy(void) -{ - int i,r, flags,dflags; - unsigned long ready_date; - timeout_fn function; - - access_mode_change_pc9800(); - flags = raw_cmd->flags; - if (flags & (FD_RAW_READ | FD_RAW_WRITE)) - flags |= FD_RAW_INTR; - - if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){ - ready_date = DRS->spinup_date + DP->spinup; - /* If spinup will take a long time, rerun scandrives - * again just before spinup completion. Beware that - * after scandrives, we must again wait for selection. - */ - if ((signed) (ready_date - jiffies) > DP->select_delay){ - ready_date -= DP->select_delay; - function = (timeout_fn) floppy_start; - } else - function = (timeout_fn) setup_rw_floppy; - - /* wait until the floppy is spinning fast enough */ - if (fd_wait_for_completion(ready_date,function)) - return; - } - dflags = DRS->flags; - - if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE)) - setup_DMA(); - - if (flags & FD_RAW_INTR) - do_floppy = main_command_interrupt; - - r=0; - for (i=0; i< raw_cmd->cmd_count; i++) - r|=output_byte(raw_cmd->cmd[i]); - -#ifdef DEBUGT - debugt("rw_command: "); -#endif - if (r){ - cont->error(); - reset_fdc(); - return; - } - - if (!(flags & FD_RAW_INTR)){ - inr = result(); - cont->interrupt(); - } else if (flags & FD_RAW_NEED_DISK) - fd_watchdog(); -} - -static int blind_seek; - -/* - * This is the routine called after every seek (or recalibrate) interrupt - * from the floppy controller. - */ -static void seek_interrupt(void) -{ -#ifdef DEBUGT - debugt("seek interrupt:"); -#endif - if (inr != 2 || (ST0 & 0xF8) != 0x20) { - DRS->track = NEED_2_RECAL; - cont->error(); - cont->redo(); - return; - } - if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek){ -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("clearing NEWCHANGE flag because of effective seek\n"); - DPRINT("jiffies=%lu\n", jiffies); - } -#endif - CLEARF(FD_DISK_NEWCHANGE); /* effective seek */ - CLEARF(FD_DISK_CHANGED); /* effective seek */ - DRS->select_date = jiffies; - } - DRS->track = ST1; - floppy_ready(); -} - -static void check_wp(void) -{ - if (TESTF(FD_VERIFY)) { - /* check write protection */ - output_byte(FD_GETSTATUS); - output_byte(UNIT(current_drive)); - if (result() != 1){ - FDCS->reset = 1; - return; - } - CLEARF(FD_VERIFY); - CLEARF(FD_NEED_TWADDLE); -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("checking whether disk is write protected\n"); - DPRINT("wp=%x\n",ST3 & 0x40); - } -#endif - if (!(ST3 & 0x40)) - SETF(FD_DISK_WRITABLE); - else - CLEARF(FD_DISK_WRITABLE); - } -} - -static void seek_floppy(void) -{ - int track; - - blind_seek=0; - -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("calling disk change from seek\n"); - } -#endif - - if (!TESTF(FD_DISK_NEWCHANGE) && - disk_change(current_drive) && - (raw_cmd->flags & FD_RAW_NEED_DISK)){ - /* the media changed flag should be cleared after the seek. - * If it isn't, this means that there is really no disk in - * the drive. - */ - SETF(FD_DISK_CHANGED); - cont->done(0); - cont->redo(); - return; - } - if (DRS->track <= NEED_1_RECAL){ - recalibrate_floppy(); - return; - } else if (TESTF(FD_DISK_NEWCHANGE) && - (raw_cmd->flags & FD_RAW_NEED_DISK) && - (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { - /* we seek to clear the media-changed condition. Does anybody - * know a more elegant way, which works on all drives? */ - if (raw_cmd->track) - track = raw_cmd->track - 1; - else { - if (DP->flags & FD_SILENT_DCL_CLEAR){ - blind_seek = 1; - raw_cmd->flags |= FD_RAW_NEED_SEEK; - } - track = 1; - } - } else { - check_wp(); - if (raw_cmd->track != DRS->track && - (raw_cmd->flags & FD_RAW_NEED_SEEK)) - track = raw_cmd->track; - else { - setup_rw_floppy(); - return; - } - } - - do_floppy = seek_interrupt; - output_byte(FD_SEEK); - output_byte(UNIT(current_drive)); - LAST_OUT(track); -#ifdef DEBUGT - debugt("seek command:"); -#endif -} - -static void recal_interrupt(void) -{ -#ifdef DEBUGT - debugt("recal interrupt:"); -#endif - if (inr !=2) - FDCS->reset = 1; - else if (ST0 & ST0_ECE) { - switch(DRS->track){ - case NEED_1_RECAL: -#ifdef DEBUGT - debugt("recal interrupt need 1 recal:"); -#endif - /* after a second recalibrate, we still haven't - * reached track 0. Probably no drive. Raise an - * error, as failing immediately might upset - * computers possessed by the Devil :-) */ - cont->error(); - cont->redo(); - return; - case NEED_2_RECAL: -#ifdef DEBUGT - debugt("recal interrupt need 2 recal:"); -#endif - /* If we already did a recalibrate, - * and we are not at track 0, this - * means we have moved. (The only way - * not to move at recalibration is to - * be already at track 0.) Clear the - * new change flag */ -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("clearing NEWCHANGE flag because of second recalibrate\n"); - } -#endif - - CLEARF(FD_DISK_NEWCHANGE); - DRS->select_date = jiffies; - /* fall through */ - default: -#ifdef DEBUGT - debugt("recal interrupt default:"); -#endif - /* Recalibrate moves the head by at - * most 80 steps. If after one - * recalibrate we don't have reached - * track 0, this might mean that we - * started beyond track 80. Try - * again. */ - DRS->track = NEED_1_RECAL; - break; - } - } else - DRS->track = ST1; - floppy_ready(); -} - -static void print_result(char *message, int inr) -{ - int i; - - DPRINT("%s ", message); - if (inr >= 0) - for (i=0; i= N_FDC || FDCS->address == -1){ - /* we don't even know which FDC is the culprit */ - printk("DOR0=%x\n", fdc_state[0].dor); - printk("floppy interrupt on bizarre fdc %d\n",fdc); - printk("handler=%p\n", handler); - is_alive("bizarre fdc"); - return IRQ_NONE; - } - - FDCS->reset = 0; - /* We have to clear the reset flag here, because apparently on boxes - * with level triggered interrupts (PS/2, Sparc, ...), it is needed to - * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the - * emission of the SENSEI's. - * It is OK to emit floppy commands because we are in an interrupt - * handler here, and thus we have to fear no interference of other - * activity. - */ - - do_print = !handler && print_unex && !initialising; - - inr = result(); - if (inr && do_print) - print_result("unexpected interrupt", inr); - if (inr == 0){ - do { - output_byte(FD_SENSEI); - inr = result(); - if ((ST0 & ST0_INTR) == 0xC0) { - int drive = ST0 & ST0_DS; - - /* Attention Interrupt. */ - if (ST0 & ST0_NR) { -#ifdef PC9800_DEBUG_FLOPPY - if (do_print) - printk(KERN_DEBUG - "floppy debug: floppy ejected (drive %d)\n", - drive); -#endif - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); - } else { -#ifdef PC9800_DEBUG_FLOPPY - if (do_print) - printk(KERN_DEBUG - "floppy debug: floppy inserted (drive %d)\n", - drive); -#endif - } - } /* Attention Interrupt */ -#ifdef PC9800_DEBUG_FLOPPY - else { - printk(KERN_DEBUG - "floppy debug : unknown interrupt\n"); - } -#endif - } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2); - } - if (handler) { - schedule_bh(handler); - } else { -#if 0 - FDCS->reset = 1; -#endif - } - is_alive("normal interrupt end"); - - /* FIXME! Was it really for us? */ - return IRQ_HANDLED; -} - -static void recalibrate_floppy(void) -{ -#ifdef DEBUGT - debugt("recalibrate floppy:"); -#endif - do_floppy = recal_interrupt; - output_byte(FD_RECALIBRATE); - LAST_OUT(UNIT(current_drive)); -} - -/* - * Must do 4 FD_SENSEIs after reset because of ``drive polling''. - */ -static void reset_interrupt(void) -{ -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy debug: reset interrupt\n"); -#endif -#ifdef DEBUGT - debugt("reset interrupt:"); -#endif - result(); /* get the status ready for set_fdc */ - if (FDCS->reset) { - printk("reset set in interrupt, calling %p\n", cont->error); - cont->error(); /* a reset just after a reset. BAD! */ - } - cont->redo(); -} - -/* - * reset is done by pulling bit 2 of DOR low for a while (old FDCs), - * or by setting the self clearing bit 7 of STATUS (newer FDCs) - */ -static void reset_fdc(void) -{ - unsigned long flags; - -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy debug: reset_fdc\n"); -#endif - - do_floppy = reset_interrupt; - FDCS->reset = 0; - reset_fdc_info(0); - - /* Pseudo-DMA may intercept 'reset finished' interrupt. */ - /* Irrelevant for systems with true DMA (i386). */ - - flags=claim_dma_lock(); - fd_disable_dma(); - release_dma_lock(flags); - - fd_outb(FDCS->dor | 0x80, FD_MODE); - udelay(FD_RESET_DELAY); - fd_outb(FDCS->dor, FD_MODE); - udelay(FD_AFTER_RESET_DELAY); -} - -static void show_floppy(void) -{ - int i; - - printk("\n"); - printk("floppy driver state\n"); - printk("-------------------\n"); - printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n", - jiffies, interruptjiffies, jiffies-interruptjiffies, lasthandler); - - -#ifdef FLOPPY_SANITY_CHECK - printk("timeout_message=%s\n", timeout_message); - printk("last output bytes:\n"); - for (i=0; i < OLOGSIZE; i++) - printk("%2x %2x %lu\n", - output_log[(i+output_log_pos) % OLOGSIZE].data, - output_log[(i+output_log_pos) % OLOGSIZE].status, - output_log[(i+output_log_pos) % OLOGSIZE].jiffies); - printk("last result at %lu\n", resultjiffies); - printk("last redo_fd_request at %lu\n", lastredo); - for (i=0; ireset = 1; - if (cont){ - cont->done(0); - cont->redo(); /* this will recall reset when needed */ - } else { - printk("no cont in shutdown!\n"); - process_fd_request(); - } - is_alive("floppy shutdown"); -} -/*typedef void (*timeout_fn)(unsigned long);*/ - -static void access_mode_change_pc9800(void) -{ - static int access_mode, mode_change_now, old_mode, new_set = 1; -#ifdef PC9800_DEBUG_FLOPPY2 - printk("enter access_mode_change\n"); -#endif - access_mode = mode_change_now = 0; - if (DP->cmos==4) { - switch ((int)(_floppy - &floppy_type[0])) { - case 1: - case 2: - new_set = 1; - access_mode = 2; - break; - - case 4: - case 6: - new_set = 1; - access_mode = 3; - break; - - case 7: - case 10: - new_set = 1; - access_mode = 1; - break; - - default: - access_mode = 1; - break; - } - - old_mode = fd_inb(FD_MODE_CHANGE) & 3; - - switch (access_mode) { - case 1: - if ((old_mode & 2) == 0) { - fd_outb(old_mode | 2, FD_MODE_CHANGE); - mode_change_now = 1; - } else { - fd_outb(current_drive << 5, FD_EMODE_CHANGE); - if (fd_inb(FD_EMODE_CHANGE) == 0xff) - return; - } - - fd_outb((current_drive << 5) | 0x11, FD_EMODE_CHANGE); - mode_change_now = 1; - break; - - case 2: - if ((old_mode & 2) == 0) { - fd_outb(old_mode | 2, FD_MODE_CHANGE); - mode_change_now = 1; - } else { - fd_outb(current_drive << 5, FD_EMODE_CHANGE); - if ((fd_inb(FD_EMODE_CHANGE) & 1) == 0) - return; - fd_outb((current_drive << 5) | 0x10, FD_EMODE_CHANGE); - mode_change_now = 1; - } - - break; - - case 3: - if ((old_mode & 2) == 0) - return; - fd_outb(current_drive << 5, FD_EMODE_CHANGE); - if (fd_inb(FD_EMODE_CHANGE) & 1) - fd_outb((current_drive << 5) | 0x10, FD_EMODE_CHANGE); - fd_outb(old_mode & 0xfd, FD_MODE_CHANGE); - mode_change_now = 1; - break; - - default: - break; - } - } else { - switch ((int)(_floppy - &floppy_type[0])) { - case 1: - case 2: - new_set = 1; - access_mode = 2; - break; - - case 4: - case 6: - new_set = 1; - access_mode = 3; - break; - - default: - switch (DP->cmos) { - case 2: - access_mode = 2; - break; - - case 3: - access_mode = 3; - break; - - default: - break; - } - - break; - } - - old_mode = fd_inb(FD_MODE_CHANGE) & 3; - - switch (access_mode) { - case 2: - if ((old_mode & 2) == 0) { - fd_outb(old_mode | 2, FD_MODE_CHANGE); - mode_change_now = 1; - } - - break; - - case 3: - if (old_mode & 2) { - fd_outb(old_mode & 0xfd, FD_MODE_CHANGE); - mode_change_now = 1; - } - - break; - - default: - break; - } - } -#ifdef PC9800_DEBUG_FLOPPY2 - printk("floppy debug: DP->cmos=%d\n", DP->cmos); - printk("floppy debug: mode_change_now=%d\n", mode_change_now); - printk("floppy debug: access_mode=%d\n", access_mode); - printk("floppy debug: old_mode=%d\n", old_mode); - printk("floppy debug: _floppy - &floppy_type[0]=%d\n", (int)(_floppy - &floppy_type[0])); -#endif /* PC9800_DEBUG_FLOPPY2 */ - if(mode_change_now) - reset_fdc(); -} - -/* start motor, check media-changed condition and write protection */ -static int start_motor(void (*function)(void) ) -{ - access_mode_change_pc9800(); - set_mode(~0, 0x8); - - /* wait_for_completion also schedules reset if needed. */ - return(fd_wait_for_completion(DRS->select_date+DP->select_delay, - (timeout_fn) function)); -} - -static void floppy_ready(void) -{ - CHECK_RESET; - if (start_motor(floppy_ready)) return; - -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("calling disk change from floppy_ready\n"); - } -#endif - if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && - disk_change(current_drive) && - !DP->select_delay) - twaddle(); /* this clears the dcl on certain drive/controller - * combinations */ - -#ifdef fd_chose_dma_mode - if ((raw_cmd->flags & FD_RAW_READ) || - (raw_cmd->flags & FD_RAW_WRITE)) - { - unsigned long flags = claim_dma_lock(); - fd_chose_dma_mode(raw_cmd->kernel_data, - raw_cmd->length); - release_dma_lock(flags); - } -#endif - -#if 0 - access_mode_change_pc9800(); -#endif - if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){ - fdc_specify(); /* must be done here because of hut, hlt ... */ - seek_floppy(); - } else { - if ((raw_cmd->flags & FD_RAW_READ) || - (raw_cmd->flags & FD_RAW_WRITE)) - fdc_specify(); - setup_rw_floppy(); - } -} - -static void floppy_start(void) -{ - reschedule_timeout(current_reqD, "floppy start", 0); - - scandrives(); -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("setting NEWCHANGE in floppy_start\n"); - } -#endif - SETF(FD_DISK_NEWCHANGE); - floppy_ready(); -} - -/* - * ======================================================================== - * here ends the bottom half. Exported routines are: - * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc, - * start_motor, reset_fdc, reset_fdc_info, interpret_errors. - * Initialization also uses output_byte, result, set_dor, floppy_interrupt - * and set_dor. - * ======================================================================== - */ -/* - * General purpose continuations. - * ============================== - */ - -static void do_wakeup(void) -{ - reschedule_timeout(MAXTIMEOUT, "do wakeup", 0); - cont = 0; - command_status += 2; - wake_up(&command_done); -} - -static struct cont_t wakeup_cont={ - empty, - do_wakeup, - empty, - (done_f)empty -}; - - -static struct cont_t intr_cont={ - empty, - process_fd_request, - empty, - (done_f) empty -}; - -static int wait_til_done(void (*handler)(void), int interruptible) -{ - int ret; - - schedule_bh((void *)(void *)handler); - - if (command_status < 2 && NO_SIGNAL) { - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&command_done, &wait); - for (;;) { - set_current_state(interruptible? - TASK_INTERRUPTIBLE: - TASK_UNINTERRUPTIBLE); - - if (command_status >= 2 || !NO_SIGNAL) - break; - - is_alive("wait_til_done"); - - schedule(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&command_done, &wait); - } - - if (command_status < 2){ - cancel_activity(); - cont = &intr_cont; - reset_fdc(); - return -EINTR; - } - -#ifdef PC9800_DEBUG_FLOPPY - if (command_status != FD_COMMAND_OKAY) - printk("floppy check: wait_til_done out:%d\n", command_status); -#endif - if (FDCS->reset) - command_status = FD_COMMAND_ERROR; - if (command_status == FD_COMMAND_OKAY) - ret=0; - else - ret=-EIO; - command_status = FD_COMMAND_NONE; - return ret; -} - -static void generic_done(int result) -{ - command_status = result; - cont = &wakeup_cont; -} - -static void generic_success(void) -{ - cont->done(1); -} - -static void generic_failure(void) -{ - cont->done(0); -} - -static void success_and_wakeup(void) -{ - generic_success(); - cont->redo(); -} - - -/* - * formatting and rw support. - * ========================== - */ - -static int next_valid_format(void) -{ - int probed_format; - - probed_format = DRS->probed_format; - while(1){ - if (probed_format >= 8 || - !DP->autodetect[probed_format]){ - DRS->probed_format = 0; - return 1; - } - if (floppy_type[DP->autodetect[probed_format]].sect){ - DRS->probed_format = probed_format; - return 0; - } - probed_format++; - } -} - -static void bad_flp_intr(void) -{ - if (probing){ - DRS->probed_format++; - if (!next_valid_format()) - return; - } - (*errors)++; - INFBOUND(DRWE->badness, *errors); - if (*errors > DP->max_errors.abort) - cont->done(0); - if (*errors > DP->max_errors.reset) - FDCS->reset = 1; - else if (*errors > DP->max_errors.recal) - DRS->track = NEED_2_RECAL; -} - -static void set_floppy(int drive) -{ - int type = ITYPE(UDRS->fd_device); - if (type) { - auto_detect_mode = 0; - _floppy = floppy_type + type; - } else if (auto_detect_mode == 0) { - auto_detect_mode = 1; - retry_auto_detect = 0; - _floppy = current_type[drive]; - } -#ifdef PC9800_DEBUG_FLOPPY2 - printk("set_floppy: set floppy type=%d\n", (int)(_floppy - floppy_type)); -#endif -} - -/* - * formatting support. - * =================== - */ -static void format_interrupt(void) -{ - switch (interpret_errors()){ - case 1: - cont->error(); - case 2: - break; - case 0: - cont->done(1); - } - cont->redo(); -} - -#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2) -#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1)) -#define CT(x) ((x) | 0xc0) -static void setup_format_params(int track) -{ - struct fparm { - unsigned char track,head,sect,size; - } *here = (struct fparm *)floppy_track_buffer; - int il,n; - int count,head_shift,track_shift; - - raw_cmd = &default_raw_cmd; - raw_cmd->track = track; - - raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | - FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; - raw_cmd->rate = _floppy->rate & 0x43; - raw_cmd->cmd_count = NR_F; - COMMAND = FM_MODE(_floppy,FD_FORMAT); - DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy,format_req.head); - F_SIZECODE = FD_SIZECODE(_floppy); - F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE; - F_GAP = _floppy->fmt_gap; - F_FILL = FD_FILL_BYTE; - - raw_cmd->kernel_data = floppy_track_buffer; - raw_cmd->length = 4 * F_SECT_PER_TRACK; - - /* allow for about 30ms for data transport per track */ - head_shift = (F_SECT_PER_TRACK + 5) / 6; - - /* a ``cylinder'' is two tracks plus a little stepping time */ - track_shift = 2 * head_shift + 3; - - /* position of logical sector 1 on this track */ - n = (track_shift * format_req.track + head_shift * format_req.head) - % F_SECT_PER_TRACK; - - /* determine interleave */ - il = 1; - if (_floppy->fmt_gap < 0x22) - il++; - - /* initialize field */ - for (count = 0; count < F_SECT_PER_TRACK; ++count) { - here[count].track = format_req.track; - here[count].head = format_req.head; - here[count].sect = 0; - here[count].size = F_SIZECODE; - } - /* place logical sectors */ - for (count = 1; count <= F_SECT_PER_TRACK; ++count) { - here[n].sect = count; - n = (n+il) % F_SECT_PER_TRACK; - if (here[n].sect) { /* sector busy, find next free sector */ - ++n; - if (n>= F_SECT_PER_TRACK) { - n-=F_SECT_PER_TRACK; - while (here[n].sect) ++n; - } - } - } -} - -static void redo_format(void) -{ - buffer_track = -1; - setup_format_params(format_req.track << STRETCH(_floppy)); - floppy_start(); -#ifdef DEBUGT - debugt("queue format request"); -#endif -} - -static struct cont_t format_cont={ - format_interrupt, - redo_format, - bad_flp_intr, - generic_done }; - -static int do_format(int drive, struct format_descr *tmp_format_req) -{ - int ret; - - LOCK_FDC(drive,1); - set_floppy(drive); - if (!_floppy || - _floppy->track > DP->tracks || - tmp_format_req->track >= _floppy->track || - tmp_format_req->head >= _floppy->head || - (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) || - !_floppy->fmt_gap) { - process_fd_request(); - return -EINVAL; - } - format_req = *tmp_format_req; - format_errors = 0; - cont = &format_cont; - errors = &format_errors; - IWAIT(redo_format); - process_fd_request(); - return ret; -} - -/* - * Buffer read/write and support - * ============================= - */ - -static void floppy_end_request(struct request *req, int uptodate) -{ - if (end_that_request_first(req, uptodate, current_count_sectors)) - return; - add_disk_randomness(req->rq_disk); - floppy_off((long)req->rq_disk->private_data); - blkdev_dequeue_request(req); - end_that_request_last(req); - - /* We're done with the request */ - current_req = NULL; -} - - -/* new request_done. Can handle physical sectors which are smaller than a - * logical buffer */ -static void request_done(int uptodate) -{ - struct request_queue *q = floppy_queue; - struct request *req = current_req; - unsigned long flags; - int block; - - probing = 0; - reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate); - - if (!req) { - printk("floppy.c: no request in request_done\n"); - return; - } - - if (uptodate){ - /* maintain values for invalidation on geometry - * change */ - block = current_count_sectors + req->sector; - INFBOUND(DRS->maxblock, block); - if (block > _floppy->sect) - DRS->maxtrack = 1; - - /* unlock chained buffers */ - spin_lock_irqsave(q->queue_lock, flags); - floppy_end_request(req, 1); - spin_unlock_irqrestore(q->queue_lock, flags); - } else { - if (rq_data_dir(req) == WRITE) { - /* record write error information */ - DRWE->write_errors++; - if (DRWE->write_errors == 1) { - DRWE->first_error_sector = req->sector; - DRWE->first_error_generation = DRS->generation; - } - DRWE->last_error_sector = req->sector; - DRWE->last_error_generation = DRS->generation; - } - spin_lock_irqsave(q->queue_lock, flags); - floppy_end_request(req, 0); - spin_unlock_irqrestore(q->queue_lock, flags); - } -} - -/* Interrupt handler evaluating the result of the r/w operation */ -static void rw_interrupt(void) -{ - int nr_sectors, ssize, eoc, heads; - - if (R_HEAD >= 2) { - /* some Toshiba floppy controllers occasionnally seem to - * return bogus interrupts after read/write operations, which - * can be recognized by a bad head number (>= 2) */ - return; - } - - if (!DRS->first_read_date) - DRS->first_read_date = jiffies; - - nr_sectors = 0; - CODE2SIZE; - - if (ST1 & ST1_EOC) - eoc = 1; - else - eoc = 0; - - if (COMMAND & 0x80) - heads = 2; - else - heads = 1; - - nr_sectors = (((R_TRACK-TRACK) * heads + - R_HEAD-HEAD) * SECT_PER_TRACK + - R_SECTOR-SECTOR + eoc) << SIZECODE >> 2; - -#ifdef FLOPPY_SANITY_CHECK - if (nr_sectors / ssize > - (in_sector_offset + current_count_sectors + ssize - 1) / ssize) { - DPRINT("long rw: %x instead of %lx\n", - nr_sectors, current_count_sectors); - printk("rs=%d s=%d\n", R_SECTOR, SECTOR); - printk("rh=%d h=%d\n", R_HEAD, HEAD); - printk("rt=%d t=%d\n", R_TRACK, TRACK); - printk("heads=%d eoc=%d\n", heads, eoc); - printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, - fsector_t, ssize); - printk("in_sector_offset=%d\n", in_sector_offset); - } -#endif - - nr_sectors -= in_sector_offset; - INFBOUND(nr_sectors,0); - SUPBOUND(current_count_sectors, nr_sectors); - - switch (interpret_errors()){ - case 2: - cont->redo(); - return; - case 1: - if (!current_count_sectors){ - cont->error(); - cont->redo(); - return; - } - break; - case 0: - if (!current_count_sectors){ - cont->redo(); - return; - } - current_type[current_drive] = _floppy; - floppy_sizes[TOMINOR(current_drive) ]= _floppy->size; - break; - } - - if (probing) { - if (DP->flags & FTD_MSG) - DPRINT("Auto-detected floppy type %s in fd%d\n", - _floppy->name,current_drive); - current_type[current_drive] = _floppy; - floppy_sizes[TOMINOR(current_drive)] = _floppy->size; - probing = 0; - } - - if (CT(COMMAND) != FD_READ || - raw_cmd->kernel_data == current_req->buffer){ - /* transfer directly from buffer */ - cont->done(1); - } else if (CT(COMMAND) == FD_READ){ - buffer_track = raw_cmd->track; - buffer_drive = current_drive; - INFBOUND(buffer_max, nr_sectors + fsector_t); - } - cont->redo(); -} - -/* Compute maximal contiguous buffer size. */ -static int buffer_chain_size(void) -{ - struct bio *bio; - struct bio_vec *bv; - int size, i; - char *base; - - base = bio_data(current_req->bio); - size = 0; - - rq_for_each_bio(bio, current_req) { - bio_for_each_segment(bv, bio, i) { - if (page_address(bv->bv_page) + bv->bv_offset != base + size) - break; - - size += bv->bv_len; - } - } - - return size >> 9; -} - -/* Compute the maximal transfer size */ -static int transfer_size(int ssize, int max_sector, int max_size) -{ - SUPBOUND(max_sector, fsector_t + max_size); - - /* alignment */ - max_sector -= (max_sector % _floppy->sect) % ssize; - - /* transfer size, beginning not aligned */ - current_count_sectors = max_sector - fsector_t ; - - return max_sector; -} - -/* - * Move data from/to the track buffer to/from the buffer cache. - */ -static void copy_buffer(int ssize, int max_sector, int max_sector_2) -{ - int remaining; /* number of transferred 512-byte sectors */ - struct bio_vec *bv; - struct bio *bio; - char *buffer, *dma_buffer; - int size, i; - - max_sector = transfer_size(ssize, - minimum(max_sector, max_sector_2), - current_req->nr_sectors); - - if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE && - buffer_max > fsector_t + current_req->nr_sectors) - current_count_sectors = minimum(buffer_max - fsector_t, - current_req->nr_sectors); - - remaining = current_count_sectors << 9; -#ifdef FLOPPY_SANITY_CHECK - if ((remaining >> 9) > current_req->nr_sectors && - CT(COMMAND) == FD_WRITE){ - DPRINT("in copy buffer\n"); - printk("current_count_sectors=%ld\n", current_count_sectors); - printk("remaining=%d\n", remaining >> 9); - printk("current_req->nr_sectors=%ld\n",current_req->nr_sectors); - printk("current_req->current_nr_sectors=%u\n", - current_req->current_nr_sectors); - printk("max_sector=%d\n", max_sector); - printk("ssize=%d\n", ssize); - } -#endif - - buffer_max = maximum(max_sector, buffer_max); - - dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9); - - size = current_req->current_nr_sectors << 9; - - rq_for_each_bio(bio, current_req) { - bio_for_each_segment(bv, bio, i) { - if (!remaining) - break; - - size = bv->bv_len; - SUPBOUND(size, remaining); - - buffer = page_address(bv->bv_page) + bv->bv_offset; -#ifdef FLOPPY_SANITY_CHECK - if (dma_buffer + size > - floppy_track_buffer + (max_buffer_sectors << 10) || - dma_buffer < floppy_track_buffer){ - DPRINT("buffer overrun in copy buffer %d\n", - (int) ((floppy_track_buffer - dma_buffer) >>9)); - printk("fsector_t=%d buffer_min=%d\n", - fsector_t, buffer_min); - printk("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(COMMAND) == FD_READ) - printk("read\n"); - if (CT(COMMAND) == FD_WRITE) - printk("write\n"); - break; - } - if (((unsigned long)buffer) % 512) - DPRINT("%p buffer not aligned\n", buffer); -#endif - if (CT(COMMAND) == FD_READ) - memcpy(buffer, dma_buffer, size); - else - memcpy(dma_buffer, buffer, size); - - remaining -= size; - dma_buffer += size; - } - } -#ifdef FLOPPY_SANITY_CHECK - if (remaining){ - if (remaining > 0) - max_sector -= remaining >> 9; - DPRINT("weirdness: remaining %d\n", remaining>>9); - } -#endif -} - -#if 0 -static inline int check_dma_crossing(char *start, - unsigned long length, char *message) -{ - if (CROSS_64KB(start, length)) { - printk("DMA xfer crosses 64KB boundary in %s %p-%p\n", - message, start, start+length); - return 1; - } else - return 0; -} -#endif - -/* work around a bug in pseudo DMA - * (on some FDCs) pseudo DMA does not stop when the CPU stops - * sending data. Hence we need a different way to signal the - * transfer length: We use SECT_PER_TRACK. Unfortunately, this - * does not work with MT, hence we can only transfer one head at - * a time - */ -static void virtualdmabug_workaround(void) -{ - int hard_sectors, end_sector; - - if(CT(COMMAND) == FD_WRITE) { - COMMAND &= ~0x80; /* switch off multiple track mode */ - - hard_sectors = raw_cmd->length >> (7 + SIZECODE); - end_sector = SECTOR + hard_sectors - 1; -#ifdef FLOPPY_SANITY_CHECK - if(end_sector > SECT_PER_TRACK) { - printk("too many sectors %d > %d\n", - end_sector, SECT_PER_TRACK); - return; - } -#endif - SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points - * to end of transfer */ - } -} - -/* - * Formulate a read/write request. - * this routine decides where to load the data (directly to buffer, or to - * tmp floppy area), how much data to load (the size of the buffer, the whole - * track, or a single sector) - * All floppy_track_buffer handling goes in here. If we ever add track buffer - * allocation on the fly, it should be done here. No other part should need - * modification. - */ - -static int make_raw_rw_request(void) -{ - int aligned_sector_t; - int max_sector, max_size, tracksize, ssize; - - if(max_buffer_sectors == 0) { - printk("VFS: Block I/O scheduled on unopened device\n"); - return 0; - } - - set_fdc((long)current_req->rq_disk->private_data); - - raw_cmd = &default_raw_cmd; - raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK | - FD_RAW_NEED_SEEK; - raw_cmd->cmd_count = NR_RW; - if (rq_data_dir(current_req) == READ) { - raw_cmd->flags |= FD_RAW_READ; - COMMAND = FM_MODE(_floppy,FD_READ); - } else if (rq_data_dir(current_req) == WRITE){ - raw_cmd->flags |= FD_RAW_WRITE; - COMMAND = FM_MODE(_floppy,FD_WRITE); - } else { - DPRINT("make_raw_rw_request: unknown command\n"); - return 0; - } - - max_sector = _floppy->sect * _floppy->head; - - TRACK = (int)current_req->sector / max_sector; - fsector_t = (int)current_req->sector % max_sector; - if (_floppy->track && TRACK >= _floppy->track) { - if (current_req->current_nr_sectors & 1) { - current_count_sectors = 1; - return 1; - } else - return 0; - } - HEAD = fsector_t / _floppy->sect; - - if (((_floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) && - fsector_t < _floppy->sect) - max_sector = _floppy->sect; - - /* 2M disks have phantom sectors on the first track */ - if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)){ - max_sector = 2 * _floppy->sect / 3; - if (fsector_t >= max_sector){ - current_count_sectors = minimum(_floppy->sect - fsector_t, - current_req->nr_sectors); - return 1; - } - SIZECODE = 2; - } else - SIZECODE = FD_SIZECODE(_floppy); - raw_cmd->rate = _floppy->rate & 0x43; - if ((_floppy->rate & FD_2M) && - (TRACK || HEAD) && - raw_cmd->rate == 2) - raw_cmd->rate = 1; - - if (SIZECODE) - SIZECODE2 = 0xff; - else - SIZECODE2 = 0x80; - raw_cmd->track = TRACK << STRETCH(_floppy); - DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy,HEAD); - GAP = _floppy->gap; - CODE2SIZE; - SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; - SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + 1; - - /* tracksize describes the size which can be filled up with sectors - * of size ssize. - */ - tracksize = _floppy->sect - _floppy->sect % ssize; - if (tracksize < _floppy->sect){ - SECT_PER_TRACK ++; - if (tracksize <= fsector_t % _floppy->sect) - SECTOR--; - - /* if we are beyond tracksize, fill up using smaller sectors */ - while (tracksize <= fsector_t % _floppy->sect){ - while(tracksize + ssize > _floppy->sect){ - SIZECODE--; - ssize >>= 1; - } - SECTOR++; SECT_PER_TRACK ++; - tracksize += ssize; - } - max_sector = HEAD * _floppy->sect + tracksize; - } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) { - max_sector = _floppy->sect; - } else if (!HEAD && CT(COMMAND) == FD_WRITE) { - /* for virtual DMA bug workaround */ - max_sector = _floppy->sect; - } - - in_sector_offset = (fsector_t % _floppy->sect) % ssize; - aligned_sector_t = fsector_t - in_sector_offset; - max_size = current_req->nr_sectors; - if ((raw_cmd->track == buffer_track) && - (current_drive == buffer_drive) && - (fsector_t >= buffer_min) && (fsector_t < buffer_max)) { - /* data already in track buffer */ - if (CT(COMMAND) == FD_READ) { - copy_buffer(1, max_sector, buffer_max); - return 1; - } - } else if (in_sector_offset || current_req->nr_sectors < ssize){ - if (CT(COMMAND) == FD_WRITE){ - if (fsector_t + current_req->nr_sectors > ssize && - fsector_t + current_req->nr_sectors < ssize + ssize) - max_size = ssize + ssize; - else - max_size = ssize; - } - raw_cmd->flags &= ~FD_RAW_WRITE; - raw_cmd->flags |= FD_RAW_READ; - COMMAND = FM_MODE(_floppy,FD_READ); - } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) { - unsigned long dma_limit; - int direct, indirect; - - indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) - - fsector_t; - - /* - * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide - * on a 64 bit machine! - */ - max_size = buffer_chain_size(); - dma_limit = (MAX_DMA_ADDRESS - ((unsigned long) current_req->buffer)) >> 9; - if ((unsigned long) max_size > dma_limit) { - max_size = dma_limit; - } - /* 64 kb boundaries */ - if (CROSS_64KB(current_req->buffer, max_size << 9)) - max_size = (K_64 - - ((unsigned long)current_req->buffer) % K_64)>>9; - direct = transfer_size(ssize,max_sector,max_size) - fsector_t; - /* - * We try to read tracks, but if we get too many errors, we - * go back to reading just one sector at a time. - * - * This means we should be able to read a sector even if there - * are other bad sectors on this track. - */ - if (!direct || - (indirect * 2 > direct * 3 && - *errors < DP->max_errors.read_track && - /*!TESTF(FD_NEED_TWADDLE) &&*/ - ((!probing || (DP->read_track&(1<probed_format)))))){ - max_size = current_req->nr_sectors; - } else { - raw_cmd->kernel_data = current_req->buffer; - raw_cmd->length = current_count_sectors << 9; - if (raw_cmd->length == 0){ - DPRINT("zero dma transfer attempted from make_raw_request\n"); - DPRINT("indirect=%d direct=%d fsector_t=%d", - indirect, direct, fsector_t); - return 0; - } -/* check_dma_crossing(raw_cmd->kernel_data, - raw_cmd->length, - "end of make_raw_request [1]");*/ - - virtualdmabug_workaround(); - return 2; - } - } - - if (CT(COMMAND) == FD_READ) - max_size = max_sector; /* unbounded */ - - /* claim buffer track if needed */ - if (buffer_track != raw_cmd->track || /* bad track */ - buffer_drive !=current_drive || /* bad drive */ - fsector_t > buffer_max || - fsector_t < buffer_min || - ((CT(COMMAND) == FD_READ || - (!in_sector_offset && current_req->nr_sectors >= ssize))&& - max_sector > 2 * max_buffer_sectors + buffer_min && - max_size + fsector_t > 2 * max_buffer_sectors + buffer_min) - /* not enough space */){ - buffer_track = -1; - buffer_drive = current_drive; - buffer_max = buffer_min = aligned_sector_t; - } - raw_cmd->kernel_data = floppy_track_buffer + - ((aligned_sector_t-buffer_min)<<9); - - if (CT(COMMAND) == FD_WRITE){ - /* copy write buffer to track buffer. - * if we get here, we know that the write - * is either aligned or the data already in the buffer - * (buffer will be overwritten) */ -#ifdef FLOPPY_SANITY_CHECK - if (in_sector_offset && buffer_track == -1) - DPRINT("internal error offset !=0 on write\n"); -#endif - buffer_track = raw_cmd->track; - buffer_drive = current_drive; - copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min); - } else - transfer_size(ssize, max_sector, - 2*max_buffer_sectors+buffer_min-aligned_sector_t); - - /* round up current_count_sectors to get dma xfer size */ - raw_cmd->length = in_sector_offset+current_count_sectors; - raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1; - raw_cmd->length <<= 9; -#ifdef FLOPPY_SANITY_CHECK - /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length, - "end of make_raw_request");*/ - if ((raw_cmd->length < current_count_sectors << 9) || - (raw_cmd->kernel_data != current_req->buffer && - CT(COMMAND) == FD_WRITE && - (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max || - aligned_sector_t < buffer_min)) || - raw_cmd->length % (128 << SIZECODE) || - raw_cmd->length <= 0 || current_count_sectors <= 0){ - DPRINT("fractionary current count b=%lx s=%lx\n", - raw_cmd->length, current_count_sectors); - if (raw_cmd->kernel_data != current_req->buffer) - printk("addr=%d, length=%ld\n", - (int) ((raw_cmd->kernel_data - - floppy_track_buffer) >> 9), - current_count_sectors); - printk("st=%d ast=%d mse=%d msi=%d\n", - fsector_t, aligned_sector_t, max_sector, max_size); - printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); - printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", - COMMAND, SECTOR, HEAD, TRACK); - printk("buffer drive=%d\n", buffer_drive); - printk("buffer track=%d\n", buffer_track); - printk("buffer_min=%d\n", buffer_min); - printk("buffer_max=%d\n", buffer_max); - return 0; - } - - if (raw_cmd->kernel_data != current_req->buffer){ - if (raw_cmd->kernel_data < floppy_track_buffer || - current_count_sectors < 0 || - raw_cmd->length < 0 || - raw_cmd->kernel_data + raw_cmd->length > - floppy_track_buffer + (max_buffer_sectors << 10)){ - DPRINT("buffer overrun in schedule dma\n"); - printk("fsector_t=%d buffer_min=%d current_count=%ld\n", - fsector_t, buffer_min, - raw_cmd->length >> 9); - printk("current_count_sectors=%ld\n", - current_count_sectors); - if (CT(COMMAND) == FD_READ) - printk("read\n"); - if (CT(COMMAND) == FD_WRITE) - printk("write\n"); - return 0; - } - } else if (raw_cmd->length > current_req->nr_sectors << 9 || - current_count_sectors > current_req->nr_sectors){ - DPRINT("buffer overrun in direct transfer\n"); - return 0; - } else if (raw_cmd->length < current_count_sectors << 9){ - DPRINT("more sectors than bytes\n"); - printk("bytes=%ld\n", raw_cmd->length >> 9); - printk("sectors=%ld\n", current_count_sectors); - } - if (raw_cmd->length == 0){ - DPRINT("zero dma transfer attempted from make_raw_request\n"); - return 0; - } -#endif - - virtualdmabug_workaround(); - return 2; -} - -static void redo_fd_request(void) -{ -#define REPEAT {request_done(0); continue; } - int drive; - int tmp; - - lastredo = jiffies; - if (current_drive < N_DRIVE) - floppy_off(current_drive); - - for (;;) { - if (!current_req) { - struct request *req; - - spin_lock_irq(floppy_queue->queue_lock); - req = elv_next_request(floppy_queue); - spin_unlock_irq(floppy_queue->queue_lock); - if (!req) { - do_floppy = NULL; - unlock_fdc(); - return; - } - current_req = req; - } - drive = (long)current_req->rq_disk->private_data; - set_fdc(drive); - reschedule_timeout(current_reqD, "redo fd request", 0); - - set_floppy(drive); - raw_cmd = & default_raw_cmd; - raw_cmd->flags = 0; - if (start_motor(redo_fd_request)) return; - disk_change(current_drive); - if (test_bit(current_drive, &fake_change) || - TESTF(FD_DISK_CHANGED)){ - DPRINT("disk absent or changed during operation\n"); - REPEAT; - } - if (!_floppy) { /* Autodetection */ - if (!probing){ - DRS->probed_format = 0; - if (next_valid_format()){ - DPRINT("no autodetectable formats\n"); - _floppy = NULL; - REPEAT; - } - } - probing = 1; - _floppy = floppy_type+DP->autodetect[DRS->probed_format]; - } else - probing = 0; - errors = & (current_req->errors); - tmp = make_raw_rw_request(); - if (tmp < 2){ - request_done(tmp); - continue; - } - - if (TESTF(FD_NEED_TWADDLE)) - twaddle(); - schedule_bh( (void *)(void *) floppy_start); -#ifdef DEBUGT - debugt("queue fd request"); -#endif - return; - } -#undef REPEAT -} - -static struct cont_t rw_cont={ - rw_interrupt, - redo_fd_request, - bad_flp_intr, - request_done }; - -static void process_fd_request(void) -{ - cont = &rw_cont; - schedule_bh( (void *)(void *) redo_fd_request); -} - -static void do_fd_request(request_queue_t * q) -{ - if(max_buffer_sectors == 0) { - printk("VFS: do_fd_request called on non-open device\n"); - return; - } - - if (usage_count == 0) { - printk("warning: usage count=0, current_req=%p exiting\n", current_req); - printk("sect=%ld flags=%lx\n", (long)current_req->sector, current_req->flags); - return; - } - if (fdc_busy){ - /* fdc busy, this new request will be treated when the - current one is done */ - is_alive("do fd request, old request running"); - return; - } - lock_fdc(MAXTIMEOUT,0); - process_fd_request(); - is_alive("do fd request"); -} - -static struct cont_t poll_cont={ - success_and_wakeup, - floppy_ready, - generic_failure, - generic_done }; - -static int poll_drive(int interruptible, int flag) -{ - int ret; - /* no auto-sense, just clear dcl */ - raw_cmd = &default_raw_cmd; - raw_cmd->flags= flag; - raw_cmd->track=0; - raw_cmd->cmd_count=0; - cont = &poll_cont; -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("setting NEWCHANGE in poll_drive\n"); - } -#endif - SETF(FD_DISK_NEWCHANGE); - WAIT(floppy_ready); - return ret; -} - -/* - * User triggered reset - * ==================== - */ - -static void reset_intr(void) -{ - printk("weird, reset interrupt called\n"); -} - -static struct cont_t reset_cont={ - reset_intr, - success_and_wakeup, - generic_failure, - generic_done }; - -static int user_reset_fdc(int drive, int arg, int interruptible) -{ - int ret; - - ret=0; - LOCK_FDC(drive,interruptible); - if (arg == FD_RESET_ALWAYS) - FDCS->reset=1; - if (FDCS->reset){ - cont = &reset_cont; - WAIT(reset_fdc); - } - process_fd_request(); - return ret; -} - -/* - * Misc Ioctl's and support - * ======================== - */ -static inline int fd_copyout(void *param, const void *address, unsigned long size) -{ - return copy_to_user(param,address, size) ? -EFAULT : 0; -} - -static inline int fd_copyin(void *param, void *address, unsigned long size) -{ - return copy_from_user(address, param, size) ? -EFAULT : 0; -} - -#define _COPYOUT(x) (copy_to_user((void *)param, &(x), sizeof(x)) ? -EFAULT : 0) -#define _COPYIN(x) (copy_from_user(&(x), (void *)param, sizeof(x)) ? -EFAULT : 0) - -#define COPYOUT(x) ECALL(_COPYOUT(x)) -#define COPYIN(x) ECALL(_COPYIN(x)) - -static inline const char *drive_name(int type, int drive) -{ - struct floppy_struct *floppy; - - if (type) - floppy = floppy_type + type; - else { - if (UDP->native_format) - floppy = floppy_type + UDP->native_format; - else - return "(null)"; - } - if (floppy->name) - return floppy->name; - else - return "(null)"; -} - - -/* raw commands */ -static void raw_cmd_done(int flag) -{ - int i; - - if (!flag) { - raw_cmd->flags |= FD_RAW_FAILURE; - raw_cmd->flags |= FD_RAW_HARDFAILURE; - } else { - raw_cmd->reply_count = inr; - if (raw_cmd->reply_count > MAX_REPLIES) - raw_cmd->reply_count=0; - for (i=0; i< raw_cmd->reply_count; i++) - raw_cmd->reply[i] = reply_buffer[i]; - - if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) - { - unsigned long flags; - flags=claim_dma_lock(); - raw_cmd->length = fd_get_dma_residue(); - release_dma_lock(flags); - } - - if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) && - (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0))) - raw_cmd->flags |= FD_RAW_FAILURE; - - if (disk_change(current_drive)) - raw_cmd->flags |= FD_RAW_DISK_CHANGE; - else - raw_cmd->flags &= ~FD_RAW_DISK_CHANGE; - if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER) - motor_off_callback(current_drive); - - if (raw_cmd->next && - (!(raw_cmd->flags & FD_RAW_FAILURE) || - !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) && - ((raw_cmd->flags & FD_RAW_FAILURE) || - !(raw_cmd->flags &FD_RAW_STOP_IF_SUCCESS))) { - raw_cmd = raw_cmd->next; - return; - } - } - generic_done(flag); -} - - -static struct cont_t raw_cmd_cont={ - success_and_wakeup, - floppy_start, - generic_failure, - raw_cmd_done -}; - -static inline int raw_cmd_copyout(int cmd, char *param, - struct floppy_raw_cmd *ptr) -{ - int ret; - - while(ptr) { - COPYOUT(*ptr); - param += sizeof(struct floppy_raw_cmd); - if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length){ - if (ptr->length>=0 && ptr->length<=ptr->buffer_length) - ECALL(fd_copyout(ptr->data, - ptr->kernel_data, - ptr->buffer_length - - ptr->length)); - } - ptr = ptr->next; - } - return 0; -} - - -static void raw_cmd_free(struct floppy_raw_cmd **ptr) -{ - struct floppy_raw_cmd *next,*this; - - this = *ptr; - *ptr = 0; - while(this) { - if (this->buffer_length) { - fd_dma_mem_free((unsigned long)this->kernel_data, - this->buffer_length); - this->buffer_length = 0; - } - next = this->next; - kfree(this); - this = next; - } -} - - -static inline int raw_cmd_copyin(int cmd, char *param, - struct floppy_raw_cmd **rcmd) -{ - struct floppy_raw_cmd *ptr; - int ret; - int i; - - *rcmd = 0; - while(1) { - ptr = (struct floppy_raw_cmd *) - kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); - if (!ptr) - return -ENOMEM; - *rcmd = ptr; - COPYIN(*ptr); - ptr->next = 0; - ptr->buffer_length = 0; - param += sizeof(struct floppy_raw_cmd); - if (ptr->cmd_count > 33) - /* the command may now also take up the space - * initially intended for the reply & the - * reply count. Needed for long 82078 commands - * such as RESTORE, which takes ... 17 command - * bytes. Murphy's law #137: When you reserve - * 16 bytes for a structure, you'll one day - * discover that you really need 17... - */ - return -EINVAL; - - for (i=0; i< 16; i++) - ptr->reply[i] = 0; - ptr->resultcode = 0; - ptr->kernel_data = 0; - - if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { - if (ptr->length <= 0) - return -EINVAL; - ptr->kernel_data =(char*)fd_dma_mem_alloc(ptr->length); - fallback_on_nodma_alloc(&ptr->kernel_data, - ptr->length); - if (!ptr->kernel_data) - return -ENOMEM; - ptr->buffer_length = ptr->length; - } - if (ptr->flags & FD_RAW_WRITE) - ECALL(fd_copyin(ptr->data, ptr->kernel_data, - ptr->length)); - rcmd = & (ptr->next); - if (!(ptr->flags & FD_RAW_MORE)) - return 0; - ptr->rate &= 0x43; - } -} - - -static int raw_cmd_ioctl(int cmd, void *param) -{ - int drive, ret, ret2; - struct floppy_raw_cmd *my_raw_cmd; - - if (FDCS->rawcmd <= 1) - FDCS->rawcmd = 1; - for (drive= 0; drive < N_DRIVE; drive++){ - if (FDC(drive) != fdc) - continue; - if (drive == current_drive){ - if (UDRS->fd_ref > 1){ - FDCS->rawcmd = 2; - break; - } - } else if (UDRS->fd_ref){ - FDCS->rawcmd = 2; - break; - } - } - - if (FDCS->reset) - return -EIO; - - ret = raw_cmd_copyin(cmd, param, &my_raw_cmd); - if (ret) { - raw_cmd_free(&my_raw_cmd); - return ret; - } - - raw_cmd = my_raw_cmd; - cont = &raw_cmd_cont; - ret=wait_til_done(floppy_start,1); -#ifdef DCL_DEBUG - if (DP->flags & FD_DEBUG){ - DPRINT("calling disk change from raw_cmd ioctl\n"); - } -#endif - - if (ret != -EINTR && FDCS->reset) - ret = -EIO; - - DRS->track = NO_TRACK; - - ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd); - if (!ret) - ret = ret2; - raw_cmd_free(&my_raw_cmd); - return ret; -} - -static int invalidate_drive(struct block_device *bdev) -{ - /* invalidate the buffer track to force a reread */ - set_bit((long)bdev->bd_disk->private_data, &fake_change); - process_fd_request(); - check_disk_change(bdev); - return 0; -} - - -static inline void clear_write_error(int drive) -{ - CLEARSTRUCT(UDRWE); -} - -static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, - int drive, int type, struct block_device *bdev) -{ - int cnt; - - /* sanity checking for parameters.*/ - if (g->sect <= 0 || - g->head <= 0 || - g->track <= 0 || - g->track > UDP->tracks>>STRETCH(g) || - /* check if reserved bits are set */ - (g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0) - return -EINVAL; - if (type){ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - down(&open_lock); - LOCK_FDC(drive,1); - floppy_type[type] = *g; - floppy_type[type].name="user format"; - for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) - floppy_sizes[cnt]= floppy_sizes[cnt+0x80]= - floppy_type[type].size+1; - process_fd_request(); - for (cnt = 0; cnt < N_DRIVE; cnt++) { - struct block_device *bdev = opened_bdev[cnt]; - if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) - continue; - __invalidate_device(bdev, 0); - } - up(&open_lock); - } else { - LOCK_FDC(drive,1); - if (cmd != FDDEFPRM) - /* notice a disk change immediately, else - * we lose our settings immediately*/ - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - user_params[drive] = *g; - if (buffer_drive == drive) - SUPBOUND(buffer_max, user_params[drive].sect); - current_type[drive] = &user_params[drive]; - floppy_sizes[drive] = user_params[drive].size; - if (cmd == FDDEFPRM) - DRS->keep_data = -1; - else - DRS->keep_data = 1; - /* invalidation. Invalidate only when needed, i.e. - * when there are already sectors in the buffer cache - * whose number will change. This is useful, because - * mtools often changes the geometry of the disk after - * looking at the boot block */ - if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack) - invalidate_drive(bdev); - else - process_fd_request(); - } - return 0; -} - -/* handle obsolete ioctl's */ -static int ioctl_table[]= { - FDCLRPRM, - FDSETPRM, - FDDEFPRM, - FDGETPRM, - FDMSGON, - FDMSGOFF, - FDFMTBEG, - FDFMTTRK, - FDFMTEND, - FDSETEMSGTRESH, - FDFLUSH, - FDSETMAXERRS, - FDGETMAXERRS, - FDGETDRVTYP, - FDSETDRVPRM, - FDGETDRVPRM, - FDGETDRVSTAT, - FDPOLLDRVSTAT, - FDRESET, - FDGETFDCSTAT, - FDWERRORCLR, - FDWERRORGET, - FDRAWCMD, - FDEJECT, - FDTWADDLE -}; - -static inline int normalize_ioctl(int *cmd, int *size) -{ - int i; - - for (i=0; i < ARRAY_SIZE(ioctl_table); i++) { - if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)){ - *size = _IOC_SIZE(*cmd); - *cmd = ioctl_table[i]; - if (*size > _IOC_SIZE(*cmd)) { - printk("ioctl not yet supported\n"); - return -EFAULT; - } - return 0; - } - } - return -EINVAL; -} - -static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) -{ - if (type) - *g = &floppy_type[type]; - else { - LOCK_FDC(drive,0); - CALL(poll_drive(0,0)); - process_fd_request(); - *g = current_type[drive]; - } - if (!*g) - return -ENODEV; - return 0; -} - -static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long param) -{ -#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data) -#define OUT(c,x) case c: outparam = (const char *) (x); break -#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 - - int drive = (long)inode->i_bdev->bd_disk->private_data; - int i, type = ITYPE(UDRS->fd_device); - int ret; - int size; - union inparam { - struct floppy_struct g; /* geometry */ - struct format_descr f; - struct floppy_max_errors max_errors; - struct floppy_drive_params dp; - } inparam; /* parameters coming from user space */ - const char *outparam; /* parameters passed back to user space */ - - /* convert compatibility eject ioctls into floppy eject ioctl. - * We do this in order to provide a means to eject floppy disks before - * installing the new fdutils package */ - if (cmd == CDROMEJECT || /* CD-ROM eject */ - cmd == 0x6470 /* SunOS floppy eject */) { - DPRINT("obsolete eject ioctl\n"); - DPRINT("please use floppycontrol --eject\n"); - cmd = FDEJECT; - } - - /* generic block device ioctls */ - switch(cmd) { - /* the following have been inspired by the corresponding - * code for other block devices. */ - struct floppy_struct *g; - case HDIO_GETGEO: - { - struct hd_geometry loc; - ECALL(get_floppy_geometry(drive, type, &g)); - loc.heads = g->head; - loc.sectors = g->sect; - loc.cylinders = g->track; - loc.start = 0; - return _COPYOUT(loc); - } - } - - /* convert the old style command into a new style command */ - if ((cmd & 0xff00) == 0x0200) { - ECALL(normalize_ioctl(&cmd, &size)); - } else - return -EINVAL; - - /* permission checks */ - if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) || - ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) - return -EPERM; - - /* copyin */ - CLEARSTRUCT(&inparam); - if (_IOC_DIR(cmd) & _IOC_WRITE) - ECALL(fd_copyin((void *)param, &inparam, size)) - - switch (cmd) { - case FDEJECT: - if (UDRS->fd_ref != 1) - /* somebody else has this drive open */ - return -EBUSY; - LOCK_FDC(drive,1); - - /* do the actual eject. Fails on - * non-Sparc architectures */ - ret=fd_eject(UNIT(drive)); - - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); - process_fd_request(); - return ret; - case FDCLRPRM: - LOCK_FDC(drive,1); - current_type[drive] = NULL; - floppy_sizes[drive] = MAX_DISK_SIZE << 1; - UDRS->keep_data = 0; - return invalidate_drive(inode->i_bdev); - case FDSETPRM: - case FDDEFPRM: - return set_geometry(cmd, & inparam.g, - drive, type, inode->i_bdev); - case FDGETPRM: - ECALL(get_floppy_geometry(drive, type, - (struct floppy_struct**) - &outparam)); - break; - - case FDMSGON: - UDP->flags |= FTD_MSG; - return 0; - case FDMSGOFF: - UDP->flags &= ~FTD_MSG; - return 0; - - case FDFMTBEG: - LOCK_FDC(drive,1); - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - if (ret & FD_VERIFY) { - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - } - - if (ret & FD_VERIFY) { - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - } - - if (ret & FD_VERIFY) { - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - } - - if (ret & FD_VERIFY) { - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - } - - if(ret & FD_VERIFY){ - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - ret = UDRS->flags; - } - process_fd_request(); - if (ret & FD_VERIFY) - return -ENODEV; - if (!(ret & FD_DISK_WRITABLE)) - return -EROFS; - return 0; - case FDFMTTRK: - if (UDRS->fd_ref != 1) - return -EBUSY; - return do_format(drive, &inparam.f); - case FDFMTEND: - case FDFLUSH: - LOCK_FDC(drive,1); - return invalidate_drive(inode->i_bdev); - - case FDSETEMSGTRESH: - UDP->max_errors.reporting = - (unsigned short) (param & 0x0f); - return 0; - OUT(FDGETMAXERRS, &UDP->max_errors); - IN(FDSETMAXERRS, &UDP->max_errors, max_errors); - - case FDGETDRVTYP: - outparam = drive_name(type,drive); - SUPBOUND(size,strlen(outparam)+1); - break; - - IN(FDSETDRVPRM, UDP, dp); - OUT(FDGETDRVPRM, UDP); - - case FDPOLLDRVSTAT: - LOCK_FDC(drive,1); - CALL(poll_drive(1, FD_RAW_NEED_DISK)); - process_fd_request(); - /* fall through */ - OUT(FDGETDRVSTAT, UDRS); - - case FDRESET: - return user_reset_fdc(drive, (int)param, 1); - - OUT(FDGETFDCSTAT,UFDCS); - - case FDWERRORCLR: - CLEARSTRUCT(UDRWE); - return 0; - OUT(FDWERRORGET,UDRWE); - - case FDRAWCMD: - if (type) - return -EINVAL; - LOCK_FDC(drive,1); - set_floppy(drive); - CALL(i = raw_cmd_ioctl(cmd,(void *) param)); - process_fd_request(); - return i; - - case FDTWADDLE: - LOCK_FDC(drive,1); - twaddle(); - process_fd_request(); - return 0; - - default: - return -EINVAL; - } - - if (_IOC_DIR(cmd) & _IOC_READ) - return fd_copyout((void *)param, outparam, size); - else - return 0; -#undef OUT -#undef IN -} - -static void __init config_types(void) -{ - int first=1; - int drive; - extern struct fd_info { - unsigned char dummy[4 * 6]; - unsigned char fd_types[8]; - } drive_info; - - for (drive = 0; drive < 4; drive++) - UDP->cmos = drive_info.fd_types[drive]; - - /* XXX */ - /* additional physical CMOS drive detection should go here */ - - for (drive=0; drive < N_DRIVE; drive++){ - unsigned int type = UDP->cmos; - struct floppy_drive_params *params; - const char *name = NULL; - static char temparea[32]; - - if (type < NUMBER(default_drive_params)) { - params = &default_drive_params[type].params; - if (type) { - name = default_drive_params[type].name; - allowed_drive_mask |= 1 << drive; - } - else - allowed_drive_mask &= ~(1 << drive); - } else { - params = &default_drive_params[0].params; - sprintf(temparea, "unknown type %d (usb?)", type); - name = temparea; - } - if (name) { - const char * prepend = ","; - if (first) { - prepend = KERN_INFO "Floppy drive(s):"; - first = 0; - } - printk("%s fd%d is %s", prepend, drive, name); - register_devfs_entries (drive); - } - *UDP = *params; - } - if (!first) - printk("\n"); -} - -static int floppy_release(struct inode * inode, struct file * filp) -{ - int drive = (long)inode->i_bdev->bd_disk->private_data; - - down(&open_lock); - if (UDRS->fd_ref < 0) - UDRS->fd_ref=0; - else if (!UDRS->fd_ref--) { - DPRINT("floppy_release with fd_ref == 0"); - UDRS->fd_ref = 0; - } - if (!UDRS->fd_ref) - opened_bdev[drive] = NULL; - floppy_release_irq_and_dma(); - up(&open_lock); - return 0; -} - -/* - * floppy_open check for aliasing (/dev/fd0 can be the same as - * /dev/PS0 etc), and disallows simultaneous access to the same - * drive with different device numbers. - */ -#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0) - -static int floppy_open(struct inode * inode, struct file * filp) -{ - int drive = (long)inode->i_bdev->bd_disk->private_data; - int old_dev; - int try; - int res = -EBUSY; - char *tmp; - -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy open: start\n"); -#endif - filp->private_data = (void*) 0; - -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy open: drive=%d, current_drive=%d, UDP->cmos=%d\n" - "floppy open: FDCS={spec1=%d, spec2=%d, dtr=%d, version=%d, dor=%d, address=%lu}\n", - drive, current_drive, UDP->cmos, FDCS->spec1, FDCS->spec2, - FDCS->dtr, FDCS->version, FDCS->dor, FDCS->address); - if (_floppy) { - printk("floppy open: _floppy={size=%d, sect=%d, head=%d, track=%d, spec1=%d}\n", - _floppy->size, _floppy->sect, _floppy->head, - _floppy->track, _floppy->spec1); - } else { - printk("floppy open: _floppy=NULL\n"); - } -#endif /* PC9800_DEBUG_FLOPPY */ - - down(&open_lock); - old_dev = UDRS->fd_device; - if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev) - goto out2; - - if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){ - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); - } - - if (UDRS->fd_ref == -1 || - (UDRS->fd_ref && (filp->f_flags & O_EXCL))) - goto out2; - - if (floppy_grab_irq_and_dma()) - goto out2; - - if (filp->f_flags & O_EXCL) - UDRS->fd_ref = -1; - else - UDRS->fd_ref++; - - opened_bdev[drive] = inode->i_bdev; - - res = -ENXIO; - - if (!floppy_track_buffer){ - /* if opening an ED drive, reserve a big buffer, - * else reserve a small one */ - if ((UDP->cmos == 6) || (UDP->cmos == 5)) - try = 64; /* Only 48 actually useful */ - else - try = 32; /* Only 24 actually useful */ - - tmp=(char *)fd_dma_mem_alloc(1024 * try); - if (!tmp && !floppy_track_buffer) { - try >>= 1; /* buffer only one side */ - INFBOUND(try, 16); - tmp= (char *)fd_dma_mem_alloc(1024*try); - } - if (!tmp && !floppy_track_buffer) { - fallback_on_nodma_alloc(&tmp, 2048 * try); - } - if (!tmp && !floppy_track_buffer) { - DPRINT("Unable to allocate DMA memory\n"); - goto out; - } - if (floppy_track_buffer) { - if (tmp) - fd_dma_mem_free((unsigned long)tmp,try*1024); - } else { - buffer_min = buffer_max = -1; - floppy_track_buffer = tmp; - max_buffer_sectors = try; - } - } - - UDRS->fd_device = iminor(inode); - set_capacity(disks[drive], floppy_sizes[iminor(inode)]); - if (old_dev != -1 && old_dev != iminor(inode)) { - if (buffer_drive == drive) - buffer_track = -1; - } - -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy open: floppy.c:%d passed\n", __LINE__); -#endif - - - /* Allow ioctls if we have write-permissions even if read-only open. - * Needed so that programs such as fdrawcmd still can work on write - * protected disks */ - if (filp->f_mode & 2 || permission(filp->f_dentry->d_inode,2,NULL) == 0) - filp->private_data = (void*) 8; - - if (UFDCS->rawcmd == 1) - UFDCS->rawcmd = 2; - -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy open: floppy.c:%d passed\n", __LINE__); -#endif - - if (!(filp->f_flags & O_NDELAY)) { - if (filp->f_mode & 3) { - UDRS->last_checked = 0; - check_disk_change(inode->i_bdev); - if (UTESTF(FD_DISK_CHANGED)) - goto out; - } - res = -EROFS; - if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE))) - goto out; -#ifdef PC9800_DEBUG_FLOPPY - printk("floppy open: end normally\n"); -#endif - } - up(&open_lock); - return 0; -out: - if (UDRS->fd_ref < 0) - UDRS->fd_ref=0; - else - UDRS->fd_ref--; - if (!UDRS->fd_ref) - opened_bdev[drive] = NULL; - floppy_release_irq_and_dma(); -out2: - up(&open_lock); - return res; -} - -/* - * Check if the disk has been changed or if a change has been faked. - */ -static int check_floppy_change(struct gendisk *disk) -{ - int drive = (long)disk->private_data; - -#ifdef PC9800_DEBUG_FLOPPY - printk("check_floppy_change: MINOR=%d\n", minor(dev)); -#endif - - if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) - return 1; - - if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) { - if(floppy_grab_irq_and_dma()) { - return 1; - } - - lock_fdc(drive,0); - poll_drive(0,0); - process_fd_request(); - floppy_release_irq_and_dma(); - } - - if (UTESTF(FD_DISK_CHANGED) || - UTESTF(FD_VERIFY) || - test_bit(drive, &fake_change) || - (!ITYPE(UDRS->fd_device) && !current_type[drive])) - return 1; - return 0; -} - -/* - * This implements "read block 0" for floppy_revalidate(). - * Needed for format autodetection, checking whether there is - * a disk in the drive, and whether that disk is writable. - */ - -static int floppy_rb0_complete(struct bio *bio, unsigned int bytes_done, int err) -{ - if (bio->bi_size) - return 1; - - complete((struct completion*)bio->bi_private); - return 0; -} - -static int __floppy_read_block_0(struct block_device *bdev) -{ - struct bio bio; - struct bio_vec bio_vec; - struct completion complete; - struct page *page; - size_t size; - - page = alloc_page(GFP_NOIO); - if (!page) { - process_fd_request(); - return -ENOMEM; - } - - size = bdev->bd_block_size; - if (!size) - size = 1024; - - bio_init(&bio); - bio.bi_io_vec = &bio_vec; - bio_vec.bv_page = page; - bio_vec.bv_len = size; - bio_vec.bv_offset = 0; - bio.bi_vcnt = 1; - bio.bi_idx = 0; - bio.bi_size = size; - bio.bi_bdev = bdev; - bio.bi_sector = 0; - init_completion(&complete); - bio.bi_private = &complete; - bio.bi_end_io = floppy_rb0_complete; - - submit_bio(READ, &bio); - generic_unplug_device(bdev_get_queue(bdev)); - process_fd_request(); - wait_for_completion(&complete); - - __free_page(page); - - return 0; -} - -/* revalidate the floppy disk, i.e. trigger format autodetection by reading - * the bootblock (block 0). "Autodetection" is also needed to check whether - * there is a disk in the drive at all... Thus we also do it for fixed - * geometry formats */ -static int floppy_revalidate(struct gendisk *disk) -{ - int drive=(long)disk->private_data; -#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device)) - int cf; - int res = 0; - - if (UTESTF(FD_DISK_CHANGED) || - UTESTF(FD_VERIFY) || - test_bit(drive, &fake_change) || - NO_GEOM){ - if(usage_count == 0) { - printk("VFS: revalidate called on non-open device.\n"); - return -EFAULT; - } - lock_fdc(drive,0); - cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); - if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){ - process_fd_request(); /*already done by another thread*/ - return 0; - } - UDRS->maxblock = 0; - UDRS->maxtrack = 0; - if (buffer_drive == drive) - buffer_track = -1; - clear_bit(drive, &fake_change); - UCLEARF(FD_DISK_CHANGED); - if (cf) - UDRS->generation++; - if (NO_GEOM){ - /* auto-sensing */ - res = __floppy_read_block_0(opened_bdev[drive]); - } else { - if (cf) - poll_drive(0, FD_RAW_NEED_DISK); - process_fd_request(); - } - } - set_capacity(disk, floppy_sizes[UDRS->fd_device]); - return res; -} - -static struct block_device_operations floppy_fops = { - .owner = THIS_MODULE, - .open = floppy_open, - .release = floppy_release, - .ioctl = fd_ioctl, - .media_changed = check_floppy_change, - .revalidate_disk= floppy_revalidate, -}; - -static char *table[] = -{"", -#if 0 - "d360", -#else - "h1232", -#endif - "h1200", "u360", "u720", "h360", "h720", - "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410", - "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743", - "h880", "u1040", "u1120", "h1600", "u1760", "u1920", - "u3200", "u3520", "u3840", "u1840", "u800", "u1600", -NULL -}; - -static int t360[] = { - 1,0 -}; -static int t1200[] = { - 2,5,6,10,12,14,16,18,20,23,0 -}; -static int t3in[] = { - 8, 9,26,27,28, 7,11,15,19,24,25, - 29,31, 3, 4,13,17,21,22,30, 0 -}; - -static int *table_sup[] = { - NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in -}; - -static void __init register_devfs_entries (int drive) -{ - int base_minor = (drive < 4) ? drive : (124 + drive); - - if (UDP->cmos < NUMBER(default_drive_params)) { - int i = 0; - do { - int minor = base_minor + (table_sup[UDP->cmos][i] << 2); - - devfs_mk_bdev(MKDEV(FLOPPY_MAJOR, minor), - S_IFBLK|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, - "floppy/%d%s", - drive, table[table_sup[UDP->cmos][i]]); - } while (table_sup[UDP->cmos][i++]); - } -} - -/* - * Floppy Driver initialization - * ============================= - */ - -static inline char __init get_fdc_version(void) -{ - return FDC_8272A; -} - -/* lilo configuration */ - -static void __init floppy_set_flags(int *ints,int param, int param2) -{ - int i; - - for (i=0; i < ARRAY_SIZE(default_drive_params); i++){ - if (param) - default_drive_params[i].params.flags |= param2; - else - default_drive_params[i].params.flags &= ~param2; - } - DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); -} - -static void __init daring(int *ints,int param, int param2) -{ - int i; - - for (i=0; i < ARRAY_SIZE(default_drive_params); i++){ - if (param){ - default_drive_params[i].params.select_delay = 0; - default_drive_params[i].params.flags |= FD_SILENT_DCL_CLEAR; - } else { - default_drive_params[i].params.select_delay = 2*HZ/100; - default_drive_params[i].params.flags &= ~FD_SILENT_DCL_CLEAR; - } - } - DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); -} - -static void __init set_cmos(int *ints, int dummy, int dummy2) -{ - int current_drive=0; - - if (ints[0] != 2){ - DPRINT("wrong number of parameters for CMOS\n"); - return; - } - current_drive = ints[1]; - if (current_drive < 0 || current_drive >= 8){ - DPRINT("bad drive for set_cmos\n"); - return; - } -#if N_FDC > 1 - if (current_drive >= 4 && !FDC2) - FDC2 = 0x370; -#endif - DP->cmos = ints[2]; - DPRINT("setting CMOS code to %d\n", ints[2]); -} - -static struct param_table { - const char *name; - void (*fn)(int *ints, int param, int param2); - int *var; - int def_param; - int param2; -} config_params[]={ - { "allowed_drive_mask", 0, &allowed_drive_mask, 0xff, 0}, /* obsolete */ - { "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */ - { "irq", 0, &FLOPPY_IRQ, DEFAULT_FLOPPY_IRQ, 0 }, - { "dma", 0, &FLOPPY_DMA, DEFAULT_FLOPPY_DMA, 0 }, - - { "daring", daring, 0, 1, 0}, -#if N_FDC > 1 - { "two_fdc", 0, &FDC2, 0x370, 0 }, - { "one_fdc", 0, &FDC2, 0, 0 }, -#endif - { "broken_dcl", floppy_set_flags, 0, 1, FD_BROKEN_DCL }, - { "messages", floppy_set_flags, 0, 1, FTD_MSG }, - { "silent_dcl_clear", floppy_set_flags, 0, 1, FD_SILENT_DCL_CLEAR }, - { "debug", floppy_set_flags, 0, 1, FD_DEBUG }, - - { "nodma", 0, &can_use_virtual_dma, 1, 0 }, - { "yesdma", 0, &can_use_virtual_dma, 0, 0 }, - - { "fifo_depth", 0, &fifo_depth, 0xa, 0 }, - { "nofifo", 0, &no_fifo, 0x20, 0 }, - { "usefifo", 0, &no_fifo, 0, 0 }, - - { "cmos", set_cmos, 0, 0, 0 }, - { "slow", 0, &slow_floppy, 1, 0 }, - - { "unexpected_interrupts", 0, &print_unex, 1, 0 }, - { "no_unexpected_interrupts", 0, &print_unex, 0, 0 }, - - EXTRA_FLOPPY_PARAMS -}; - -static int __init floppy_setup(char *str) -{ - int i; - int param; - int ints[11]; - - str = get_options(str,ARRAY_SIZE(ints),ints); - if (str) { - for (i=0; i< ARRAY_SIZE(config_params); i++){ - if (strcmp(str,config_params[i].name) == 0){ - if (ints[0]) - param = ints[1]; - else - param = config_params[i].def_param; - if (config_params[i].fn) - config_params[i]. - fn(ints,param, - config_params[i].param2); - if (config_params[i].var) { - DPRINT("%s=%d\n", str, param); - *config_params[i].var = param; - } - return 1; - } - } - } - if (str) { - DPRINT("unknown floppy option [%s]\n", str); - - DPRINT("allowed options are:"); - for (i=0; i< ARRAY_SIZE(config_params); i++) - printk(" %s",config_params[i].name); - printk("\n"); - } else - DPRINT("botched floppy option\n"); - DPRINT("Read linux/Documentation/floppy.txt\n"); - return 0; -} - -static int have_no_fdc= -ENODEV; - -static void floppy_device_release(struct device *dev) -{ - complete(&device_release); -} - -static struct platform_device floppy_device = { - .name = "floppy", - .id = 0, - .dev = { - .release = floppy_device_release, - }, -}; - -static struct kobject *floppy_find(dev_t dev, int *part, void *data) -{ - int drive = (*part&3) | ((*part&0x80) >> 5); - if (drive >= N_DRIVE || - !(allowed_drive_mask & (1 << drive)) || - fdc_state[FDC(drive)].version == FDC_NONE) - return NULL; - if (((*part>>2) & 0x1f) >= NUMBER(floppy_type)) - return NULL; - *part = 0; - return get_disk(disks[drive]); -} - -int __init floppy_init(void) -{ - int i,unit,drive; - int err; - - raw_cmd = NULL; - FDC1 = 0x90; - - for (i=0; imajor = FLOPPY_MAJOR; - disks[i]->first_minor = TOMINOR(i); - disks[i]->fops = &floppy_fops; - sprintf(disks[i]->disk_name, "fd%d", i); - } - - blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, - floppy_find, NULL, NULL); - - for (i=0; i<256; i++) - if (ITYPE(i)) - floppy_sizes[i] = floppy_type[ITYPE(i)].size; - else - floppy_sizes[i] = MAX_DISK_SIZE << 1; - - floppy_queue = blk_init_queue(do_fd_request, &floppy_lock); - if (!floppy_queue) - goto out_queue; - - reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); - config_types(); - - for (i = 0; i < N_FDC; i++) { - fdc = i; - CLEARSTRUCT(FDCS); - FDCS->dtr = -1; - FDCS->dor = 0; - } - - if ((fd_inb(FD_MODE_CHANGE) & 1) == 0) - FDC1 = 0xc8; - - use_virtual_dma = can_use_virtual_dma & 1; - fdc_state[0].address = FDC1; - if (fdc_state[0].address == -1) { - err = -ENODEV; - goto out1; - } -#if N_FDC > 1 - fdc_state[1].address = FDC2; -#endif - - fdc = 0; /* reset fdc in case of unexpected interrupt */ - if (floppy_grab_irq_and_dma()){ - err = -EBUSY; - goto out1; - } - - /* initialise drive state */ - for (drive = 0; drive < N_DRIVE; drive++) { - CLEARSTRUCT(UDRS); - CLEARSTRUCT(UDRWE); - USETF(FD_DISK_NEWCHANGE); - USETF(FD_DISK_CHANGED); - USETF(FD_VERIFY); - UDRS->fd_device = -1; - floppy_track_buffer = NULL; - max_buffer_sectors = 0; - } - - for (i = 0; i < N_FDC; i++) { - fdc = i; - FDCS->driver_version = FD_DRIVER_VERSION; - for (unit=0; unit<4; unit++) - FDCS->track[unit] = 0; - if (FDCS->address == -1) - continue; - FDCS->rawcmd = 2; - user_reset_fdc(-1, FD_RESET_ALWAYS, 0); - - /* Try to determine the floppy controller type */ - FDCS->version = get_fdc_version(); - if (FDCS->version == FDC_NONE){ - /* free ioports reserved by floppy_grab_irq_and_dma() */ - release_region(FDCS->address, 1); - release_region(FDCS->address + 2, 1); - release_region(FDCS->address + 4, 1); - release_region(0xbe, 1); - release_region(0x4be, 1); - FDCS->address = -1; - continue; - } - if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A) - can_use_virtual_dma = 0; - - have_no_fdc = 0; - /* Not all FDCs seem to be able to handle the version command - * properly, so force a reset for the standard FDC clones, - * to avoid interrupt garbage. - */ - user_reset_fdc(-1,FD_RESET_ALWAYS,0); - } - fdc=0; - del_timer(&fd_timeout); - current_drive = 0; - floppy_release_irq_and_dma(); -#if 0 /* no message */ - initialising=0; -#endif - if (have_no_fdc) { - DPRINT("no floppy controllers found\n"); - flush_scheduled_work(); - if (usage_count) - floppy_release_irq_and_dma(); - err = have_no_fdc; - goto out2; - } - - for (drive = 0; drive < N_DRIVE; drive++) { - init_timer(&motor_off_timer[drive]); - motor_off_timer[drive].data = drive; - motor_off_timer[drive].function = motor_off_callback; - if (!(allowed_drive_mask & (1 << drive))) - continue; - if (fdc_state[FDC(drive)].version == FDC_NONE) - continue; - /* to be cleaned up... */ - disks[drive]->private_data = (void*)(long)drive; - disks[drive]->queue = floppy_queue; - add_disk(disks[drive]); - } - - platform_device_register(&floppy_device); - return 0; - -out1: - del_timer_sync(&fd_timeout); -out2: - blk_cleanup_queue(floppy_queue); -out_queue: - blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); - unregister_blkdev(FLOPPY_MAJOR,"fd"); -out: - for (i=0; iaddress != -1){ - static char floppy[] = "floppy"; - if (!request_region(FDCS->address, 1, floppy)) - goto cleanup0; - - if (!request_region(FDCS->address + 2, 1, floppy)) { - release_region(FDCS->address, 1); - goto cleanup0; - } - - if (!request_region(FDCS->address + 4, 1, floppy)) { - release_region(FDCS->address, 1); - release_region(FDCS->address + 2, 1); - goto cleanup0; - } - - if (fdc == 0) { /* internal FDC */ - if (request_region(0xbe, 1, "floppy mode change")) { - if (request_region(0x4be, 1, "floppy ex. mode change")) - continue; - else - DPRINT("Floppy io-port 0x4be in use\n"); - - release_region(0xbe, 1); - } else - DPRINT("Floppy io-port 0xbe in use\n"); - - release_region(FDCS->address, 1); - release_region(FDCS->address + 2, 1); - release_region(FDCS->address + 4, 1); - } - - goto cleanup1; - } - } - for (fdc=0; fdc< N_FDC; fdc++){ - if (FDCS->address != -1){ - reset_fdc_info(1); - fd_outb(FDCS->dor, FD_MODE); - } - } - fdc = 0; - fd_outb((FDCS->dor & 8), FD_MODE); - - for (fdc = 0; fdc < N_FDC; fdc++) - if (FDCS->address != -1) - fd_outb(FDCS->dor, FD_MODE); - /* - * The driver will try and free resources and relies on us - * to know if they were allocated or not. - */ - fdc = 0; - irqdma_allocated = 1; - return 0; - -cleanup0: - DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address); -cleanup1: - fd_free_irq(); - fd_free_dma(); - while(--fdc >= 0) { - release_region(FDCS->address, 1); - release_region(FDCS->address + 2, 1); - release_region(FDCS->address + 4, 1); - if (fdc == 0) { - release_region(0x00be, 1); - release_region(0x04be, 1); - } - } - spin_lock_irqsave(&floppy_usage_lock, flags); - usage_count--; - spin_unlock_irqrestore(&floppy_usage_lock, flags); - return -1; -} - -static void floppy_release_irq_and_dma(void) -{ - int old_fdc; -#ifdef FLOPPY_SANITY_CHECK - int drive; -#endif - long tmpsize; - unsigned long tmpaddr; - unsigned long flags; - - spin_lock_irqsave(&floppy_usage_lock, flags); - if (--usage_count){ - spin_unlock_irqrestore(&floppy_usage_lock, flags); - return; - } - spin_unlock_irqrestore(&floppy_usage_lock, flags); - if(irqdma_allocated) - { - fd_disable_dma(); - fd_free_dma(); - fd_free_irq(); - irqdma_allocated=0; - } - fd_outb(0, FD_MODE); - floppy_enable_hlt(); - - if (floppy_track_buffer && max_buffer_sectors) { - tmpsize = max_buffer_sectors*1024; - tmpaddr = (unsigned long)floppy_track_buffer; - floppy_track_buffer = NULL; - max_buffer_sectors = 0; - buffer_min = buffer_max = -1; - fd_dma_mem_free(tmpaddr, tmpsize); - } - -#ifdef FLOPPY_SANITY_CHECK - for (drive=0; drive < N_FDC * 4; drive++) - if (timer_pending(motor_off_timer + drive)) - printk("motor off timer %d still active\n", drive); - - if (timer_pending(&fd_timeout)) - printk("floppy timer still active:%s\n", timeout_message); - if (timer_pending(&fd_timer)) - printk("auxiliary floppy timer still active\n"); - if (floppy_work.pending) - printk("work still pending\n"); -#endif - old_fdc = fdc; - for (fdc = 0; fdc < N_FDC; fdc++) - if (FDCS->address != -1) { - release_region(FDCS->address, 1); - release_region(FDCS->address + 2, 1); - release_region(FDCS->address + 4, 1); - if (fdc == 0) { - release_region(0xbe, 1); - release_region(0x4be, 1); - } - } - fdc = old_fdc; -} - - -#ifdef MODULE - -char *floppy; - -static void unregister_devfs_entries (int drive) -{ - int i; - - if (UDP->cmos < NUMBER(default_drive_params)) { - i = 0; - do { - devfs_remove("floppy/%d%s", drive, table[table_sup[UDP->cmos][i]]); - } while (table_sup[UDP->cmos][i++]); - } -} - -static void __init parse_floppy_cfg_string(char *cfg) -{ - char *ptr; - - while(*cfg) { - for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++); - if (*cfg) { - *cfg = '\0'; - cfg++; - } - if (*ptr) - floppy_setup(ptr); - } -} - -int init_module(void) -{ - printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n"); - - if (floppy) - parse_floppy_cfg_string(floppy); - return floppy_init(); -} - -void cleanup_module(void) -{ - int drive; - - init_completion(&device_release); - platform_device_unregister(&floppy_device); - blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); - unregister_blkdev(FLOPPY_MAJOR, "fd"); - - for (drive = 0; drive < N_DRIVE; drive++) { - del_timer_sync(&motor_off_timer[drive]); - - if ((allowed_drive_mask & (1 << drive)) && - fdc_state[FDC(drive)].version != FDC_NONE) { - del_gendisk(disks[drive]); - unregister_devfs_entries(drive); - } - put_disk(disks[drive]); - } - devfs_remove("floppy"); - - del_timer_sync(&fd_timeout); - del_timer_sync(&fd_timer); - blk_cleanup_queue(floppy_queue); - - if (usage_count) - floppy_release_irq_and_dma(); - - /* eject disk, if any */ - fd_eject(0); - - wait_for_completion(&device_release); -} - -MODULE_PARM(floppy,"s"); -MODULE_PARM(FLOPPY_IRQ,"i"); -MODULE_PARM(FLOPPY_DMA,"i"); -MODULE_AUTHOR("Osamu Tomita"); -MODULE_SUPPORTED_DEVICE("fd"); -MODULE_LICENSE("GPL"); - -#else - -__setup ("floppy=", floppy_setup); -module_init(floppy_init) -#endif diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/block/ll_rw_blk.c 2004-06-20 13:00:23 -07:00 @@ -1123,7 +1123,7 @@ /* * remove the plug and let it rip.. */ -static inline void __generic_unplug_device(request_queue_t *q) +inline void __generic_unplug_device(request_queue_t *q) { if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) return; @@ -1137,6 +1137,7 @@ if (elv_next_request(q)) q->request_fn(q); } +EXPORT_SYMBOL(__generic_unplug_device); /** * generic_unplug_device - fire a request queue @@ -2280,13 +2281,9 @@ out: if (freereq) __blk_put_request(q, freereq); + if (bio_sync(bio)) + __generic_unplug_device(q); - if (blk_queue_plugged(q)) { - int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight; - - if (nrq == q->unplug_thresh || bio_sync(bio)) - __generic_unplug_device(q); - } spin_unlock_irq(q->queue_lock); return 0; diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c --- a/drivers/cdrom/cdrom.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/cdrom/cdrom.c 2004-06-20 13:00:23 -07:00 @@ -508,6 +508,8 @@ unsigned char buffer[16]; int ret; + *write = 0; + init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); cgc.cmd[0] = GPCMD_GET_CONFIGURATION; @@ -521,8 +523,10 @@ mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)]; *write = mfd->write; - if ((ret = cdrom_mrw_probe_pc(cdi))) + if ((ret = cdrom_mrw_probe_pc(cdi))) { + *write = 0; return ret; + } return 0; } @@ -822,8 +826,30 @@ */ static int cdrom_open_write(struct cdrom_device_info *cdi) { + int mrw, mrw_write, ram_write; int ret = 1; + mrw = 0; + if (!cdrom_is_mrw(cdi, &mrw_write)) + mrw = 1; + + (void) cdrom_is_random_writable(cdi, &ram_write); + + if (mrw) + cdi->mask &= ~CDC_MRW; + else + cdi->mask |= CDC_MRW; + + if (mrw_write) + cdi->mask &= ~CDC_MRW_W; + else + cdi->mask |= CDC_MRW_W; + + if (ram_write) + cdi->mask &= ~CDC_RAM; + else + cdi->mask |= CDC_RAM; + if (CDROM_CAN(CDC_MRW_W)) ret = cdrom_mrw_open_write(cdi); else if (CDROM_CAN(CDC_DVD_RAM)) @@ -866,6 +892,9 @@ if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS)) { ret = cdi->ops->open(cdi, 1); } else { + ret = open_for_data(cdi); + if (ret) + goto err; if (fp->f_mode & FMODE_WRITE) { ret = -EROFS; if (!CDROM_CAN(CDC_RAM)) @@ -873,7 +902,6 @@ if (cdrom_open_write(cdi)) goto err; } - ret = open_for_data(cdi); } if (ret) diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/Kconfig 2004-06-20 13:00:23 -07:00 @@ -586,17 +586,6 @@ console. This driver allows each pSeries partition to have a console which is accessed via the HMC. -config PC9800_OLDLP - tristate "NEC PC-9800 old-style printer port support" - depends on X86_PC9800 && !PARPORT - ---help--- - If you intend to attach a printer to the parallel port of NEC PC-9801 - /PC-9821 with OLD compatibility mode, Say Y. - -config PC9800_OLDLP_CONSOLE - bool "Support for console on line printer" - depends on PC9800_OLDLP - config QIC02_TAPE tristate "QIC-02 tape support" help @@ -740,7 +729,7 @@ config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 && !M68K + depends on !PPC32 && !PARISC && !IA64 && !M68K ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -793,15 +782,6 @@ bool "EFI Real Time Clock Services" depends on IA64 -config RTC98 - tristate "NEC PC-9800 Real Time Clock Support" - depends on X86_PC9800 - default y - ---help--- - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - config H8 bool "Tadpole ANA H8 Support (OBSOLETE)" depends on OBSOLETE && ALPHA_BOOK1 @@ -956,6 +936,33 @@ The raw driver is deprecated and may be removed from 2.7 kernels. Applications should simply open the device (eg /dev/hda1) with the O_DIRECT flag. + +config HPET + bool "HPET - High Precision Event Timer" if (X86 || IA64) + default n + depends on ACPI + help + If you say Y here, you will have a device named "/dev/hpet/XX" for + each timer supported by the HPET. The timers are + non-periodioc and/or periodic. + +config HPET_RTC_IRQ + bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC + default n + depends on HPET + help + If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It + is assumed the platform called hpet_alloc with the RTC IRQ values for + the HPET timers. + +config HPET_NOMMAP + bool "HPET - Control mmap capability." + default n + depends on HPET + help + If you say Y here, then the mmap interface for the HPET driver returns ENOSYS. + Some hardware implementations might not want all the memory in the page the + HPET control registers reside to be exposed. config MAX_RAW_DEVS int "Maximum number of RAW devices to support (1-8192)" diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile 2004-06-20 13:00:26 -07:00 +++ b/drivers/char/Makefile 2004-06-20 13:00:26 -07:00 @@ -47,13 +47,13 @@ obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o -obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o +obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) diff -Nru a/drivers/char/applicom.c b/drivers/char/applicom.c --- a/drivers/char/applicom.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/applicom.c 2004-06-20 13:00:25 -07:00 @@ -105,8 +105,8 @@ static unsigned int ReadErrorCount; /* number of read error */ static unsigned int DeviceErrorCount; /* number of device error */ -static ssize_t ac_read (struct file *, char *, size_t, loff_t *); -static ssize_t ac_write (struct file *, const char *, size_t, loff_t *); +static ssize_t ac_read (struct file *, char __user *, size_t, loff_t *); +static ssize_t ac_write (struct file *, const char __user *, size_t, loff_t *); static int ac_ioctl(struct inode *, struct file *, unsigned int, unsigned long); static irqreturn_t ac_interrupt(int, void *, struct pt_regs *); @@ -343,7 +343,7 @@ __initcall(applicom_init); #endif -static ssize_t ac_write(struct file *file, const char *buf, size_t count, loff_t * ppos) +static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { unsigned int NumCard; /* Board number 1 -> 8 */ unsigned int IndexCard; /* Index board number 0 -> 7 */ @@ -467,7 +467,7 @@ return 0; } -static int do_ac_read(int IndexCard, char *buf, +static int do_ac_read(int IndexCard, char __user *buf, struct st_ram_io *st_loc, struct mailbox *mailbox) { unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC; @@ -521,7 +521,7 @@ return (sizeof(struct st_ram_io) + sizeof(struct mailbox)); } -static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr) +static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_t *ptr) { unsigned long flags; unsigned int i; @@ -689,6 +689,7 @@ int ret = 0; volatile unsigned char byte_reset_it; struct st_ram_io *adgl; + void __user *argp = (void __user *)arg; /* In general, the device is only openable by root anyway, so we're not particularly concerned that bogus ioctls can flood the console. */ @@ -697,7 +698,7 @@ if (!adgl) return -ENOMEM; - if (copy_from_user(adgl, (void *)arg,sizeof(struct st_ram_io))) { + if (copy_from_user(adgl, argp, sizeof(struct st_ram_io))) { kfree(adgl); return -EFAULT; } @@ -721,7 +722,7 @@ pmem = apbs[IndexCard].RamIO; for (i = 0; i < sizeof(struct st_ram_io); i++) ((unsigned char *)adgl)[i]=readb(pmem++); - if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io))) + if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) ret = -EFAULT; break; case 1: @@ -742,7 +743,7 @@ (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + (readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) ); - if (copy_to_user((void *)arg, adgl, sizeof(struct st_ram_io))) + if (copy_to_user(argp, adgl, sizeof(struct st_ram_io))) ret = -EFAULT; break; case 2: @@ -768,7 +769,7 @@ pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC; adgl->tic_owner_to_pc = readb(pmem++); adgl->numcard_owner_to_pc = readb(pmem); - if (copy_to_user((void *)arg, adgl,sizeof(struct st_ram_io))) + if (copy_to_user(argp, adgl,sizeof(struct st_ram_io))) ret = -EFAULT; break; case 5: diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c --- a/drivers/char/cyclades.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/cyclades.c 2004-06-20 13:00:23 -07:00 @@ -676,8 +676,6 @@ #include #include -#define cy_put_user put_user - static void cy_throttle (struct tty_struct *tty); static void cy_send_xchar (struct tty_struct *tty, char ch); @@ -3536,7 +3534,7 @@ static int get_serial_info(struct cyclades_port * info, - struct serial_struct * retinfo) + struct serial_struct __user * retinfo) { struct serial_struct tmp; struct cyclades_card *cinfo = &cy_card[info->card]; @@ -3559,7 +3557,7 @@ static int set_serial_info(struct cyclades_port * info, - struct serial_struct * new_info) + struct serial_struct __user * new_info) { struct serial_struct new_serial; struct cyclades_port old_info; @@ -3613,7 +3611,7 @@ * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct cyclades_port *info, unsigned int *value) +static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) { int card, chip, channel, index; unsigned char status; @@ -3638,7 +3636,7 @@ /* Not supported yet */ return -EINVAL; } - return cy_put_user(result, (unsigned long *) value); + return put_user(result, (unsigned long __user *) value); } static int @@ -3916,7 +3914,7 @@ } /* cy_break */ static int -get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon) +get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) { if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) @@ -3961,7 +3959,7 @@ static int -get_threshold(struct cyclades_port * info, unsigned long *value) +get_threshold(struct cyclades_port * info, unsigned long __user *value) { unsigned char *base_addr; int card,channel,chip,index; @@ -3978,7 +3976,7 @@ + (cy_chip_offset[chip]<default_threshold,value); + return put_user(info->default_threshold,value); }/* get_default_threshold */ @@ -4029,7 +4027,7 @@ static int -get_timeout(struct cyclades_port * info, unsigned long *value) +get_timeout(struct cyclades_port * info, unsigned long __user *value) { unsigned char *base_addr; int card,channel,chip,index; @@ -4046,7 +4044,7 @@ + (cy_chip_offset[chip]<default_timeout,value); + return put_user(info->default_timeout,value); }/* get_default_timeout */ /* @@ -4079,9 +4077,10 @@ { struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; struct cyclades_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct *p_cuser; /* user space */ + struct serial_icounter_struct __user *p_cuser; /* user space */ int ret_val = 0; unsigned long flags; + void __user *argp = (void __user *)arg; if (serial_paranoia_check(info, tty->name, "cy_ioctl")) return -ENODEV; @@ -4093,31 +4092,31 @@ switch (cmd) { case CYGETMON: - ret_val = get_mon_info(info, (struct cyclades_monitor *)arg); + ret_val = get_mon_info(info, argp); break; case CYGETTHRESH: - ret_val = get_threshold(info, (unsigned long *)arg); + ret_val = get_threshold(info, argp); break; case CYSETTHRESH: - ret_val = set_threshold(info, (unsigned long)arg); + ret_val = set_threshold(info, arg); break; case CYGETDEFTHRESH: - ret_val = get_default_threshold(info, (unsigned long *)arg); + ret_val = get_default_threshold(info, argp); break; case CYSETDEFTHRESH: - ret_val = set_default_threshold(info, (unsigned long)arg); + ret_val = set_default_threshold(info, arg); break; case CYGETTIMEOUT: - ret_val = get_timeout(info, (unsigned long *)arg); + ret_val = get_timeout(info, argp); break; case CYSETTIMEOUT: - ret_val = set_timeout(info, (unsigned long)arg); + ret_val = set_timeout(info, arg); break; case CYGETDEFTIMEOUT: - ret_val = get_default_timeout(info, (unsigned long *)arg); + ret_val = get_default_timeout(info, argp); break; case CYSETDEFTIMEOUT: - ret_val = set_default_timeout(info, (unsigned long)arg); + ret_val = set_default_timeout(info, arg); break; case CYSETRFLOW: info->rflow = (int)arg; @@ -4134,7 +4133,7 @@ ret_val = info->rtsdtr_inv; break; case CYGETCARDINFO: - if (copy_to_user((void *)arg, (void *)&cy_card[info->card], + if (copy_to_user(argp, &cy_card[info->card], sizeof (struct cyclades_card))) { ret_val = -EFAULT; break; @@ -4161,13 +4160,13 @@ ret_val = info->closing_wait / (HZ/100); break; case TIOCGSERIAL: - ret_val = get_serial_info(info, (struct serial_struct *) arg); + ret_val = get_serial_info(info, argp); break; case TIOCSSERIAL: - ret_val = set_serial_info(info, (struct serial_struct *) arg); + ret_val = set_serial_info(info, argp); break; case TIOCSERGETLSR: /* Get line status register */ - ret_val = get_lsr_info(info, (unsigned int *) arg); + ret_val = get_lsr_info(info, argp); break; /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change @@ -4215,7 +4214,7 @@ CY_LOCK(info, flags); cnow = info->icount; CY_UNLOCK(info, flags); - p_cuser = (struct serial_icounter_struct *) arg; + p_cuser = argp; ret_val = put_user(cnow.cts, &p_cuser->cts); if (ret_val) return ret_val; ret_val = put_user(cnow.dsr, &p_cuser->dsr); diff -Nru a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c --- a/drivers/char/drm/sis_mm.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/drm/sis_mm.c 2004-06-20 13:00:25 -07:00 @@ -113,7 +113,7 @@ DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); - DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); return retval; } @@ -130,7 +130,7 @@ if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) retval = DRM_ERR(EINVAL); - sis_free(fb.free); + sis_free((u32)fb.free); DRM_DEBUG("free fb, offset = %lu\n", fb.free); diff -Nru a/drivers/char/hpet.c b/drivers/char/hpet.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/char/hpet.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1076 @@ +/* + * Intel & MS High Precision Event Timer Implementation. + * Contributors: + * Venki Pallipadi + * Bob Picco + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * The High Precision Event Timer driver. + * This driver is closely modelled after the rtc.c driver. + * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm + */ +#define HPET_USER_FREQ (64) +#define HPET_DRIFT (500) + +static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; + +/* A lock for concurrent access by app and isr hpet activity. */ +static spinlock_t hpet_lock = SPIN_LOCK_UNLOCKED; +/* A lock for concurrent intermodule access to hpet and isr hpet activity. */ +static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED; + +struct hpet_dev { + struct hpets *hd_hpets; + struct hpet *hd_hpet; + struct hpet_timer *hd_timer; + unsigned long hd_ireqfreq; + unsigned long hd_irqdata; + wait_queue_head_t hd_waitqueue; + struct fasync_struct *hd_async_queue; + struct hpet_task *hd_task; + unsigned int hd_flags; + unsigned int hd_irq; + unsigned int hd_hdwirq; +}; + +struct hpets { + struct hpets *hp_next; + struct hpet *hp_hpet; + unsigned long hp_period; + unsigned long hp_delta; + unsigned int hp_ntimer; + unsigned int hp_which; + struct hpet_dev hp_dev[1]; +}; + +static struct hpets *hpets; + +#define HPET_OPEN 0x0001 +#define HPET_IE 0x0002 /* interrupt enabled */ +#define HPET_PERIODIC 0x0004 + +#if BITS_PER_LONG == 64 +#define write_counter(V, MC) writeq(V, MC) +#define read_counter(MC) readq(MC) +#else +#define write_counter(V, MC) writel(V, MC) +#define read_counter(MC) readl(MC) +#endif + +#ifndef readq +static unsigned long long __inline readq(void *addr) +{ + return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL); +} +#endif + +#ifndef writeq +static void __inline writeq(unsigned long long v, void *addr) +{ + writel(v & 0xffffffff, addr); + writel(v >> 32, addr + 4); +} +#endif + +static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs) +{ + struct hpet_dev *devp; + unsigned long isr; + + devp = data; + + spin_lock(&hpet_lock); + devp->hd_irqdata++; + + /* + * For non-periodic timers, increment the accumulator. + * This has the effect of treating non-periodic like periodic. + */ + if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) { + unsigned long m, t; + + t = devp->hd_ireqfreq; + m = read_counter(&devp->hd_hpet->hpet_mc); + write_counter(t + m + devp->hd_hpets->hp_delta, + &devp->hd_timer->hpet_compare); + } + + isr = (1 << (devp - devp->hd_hpets->hp_dev)); + writeq(isr, &devp->hd_hpet->hpet_isr); + spin_unlock(&hpet_lock); + + spin_lock(&hpet_task_lock); + if (devp->hd_task) + devp->hd_task->ht_func(devp->hd_task->ht_data); + spin_unlock(&hpet_task_lock); + + wake_up_interruptible(&devp->hd_waitqueue); + + kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); + + return IRQ_HANDLED; +} + +static int hpet_open(struct inode *inode, struct file *file) +{ + struct hpet_dev *devp; + struct hpets *hpetp; + int i; + + spin_lock_irq(&hpet_lock); + + for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) + for (i = 0; i < hpetp->hp_ntimer; i++) + if (hpetp->hp_dev[i].hd_flags & HPET_OPEN + || hpetp->hp_dev[i].hd_task) + continue; + else { + devp = &hpetp->hp_dev[i]; + break; + } + + if (!devp) { + spin_unlock_irq(&hpet_lock); + return -EBUSY; + } + + file->private_data = devp; + devp->hd_irqdata = 0; + devp->hd_flags |= HPET_OPEN; + spin_unlock_irq(&hpet_lock); + + return 0; +} + +static ssize_t +hpet_read(struct file *file, char *buf, size_t count, loff_t * ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + struct hpet_dev *devp; + + devp = file->private_data; + if (!devp->hd_ireqfreq) + return -EIO; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&devp->hd_waitqueue, &wait); + + do { + __set_current_state(TASK_INTERRUPTIBLE); + + spin_lock_irq(&hpet_lock); + data = devp->hd_irqdata; + devp->hd_irqdata = 0; + spin_unlock_irq(&hpet_lock); + + if (data) + break; + else if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } else if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + + } while (1); + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + out: + current->state = TASK_RUNNING; + remove_wait_queue(&devp->hd_waitqueue, &wait); + + return retval; +} + +static unsigned int hpet_poll(struct file *file, poll_table * wait) +{ + unsigned long v; + struct hpet_dev *devp; + + devp = file->private_data; + + if (!devp->hd_ireqfreq) + return 0; + + poll_wait(file, &devp->hd_waitqueue, wait); + + spin_lock_irq(&hpet_lock); + v = devp->hd_irqdata; + spin_unlock_irq(&hpet_lock); + + if (v != 0) + return POLLIN | POLLRDNORM; + + return 0; +} + +static int hpet_mmap(struct file *file, struct vm_area_struct *vma) +{ +#ifdef CONFIG_HPET_NOMMAP + return -ENOSYS; +#else + struct hpet_dev *devp; + unsigned long addr; + + if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff) + return -EINVAL; + + if (vma->vm_flags & VM_WRITE) + return -EPERM; + + devp = file->private_data; + addr = (unsigned long)devp->hd_hpet; + + if (addr & (PAGE_SIZE - 1)) + return -ENOSYS; + + vma->vm_flags |= VM_IO; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + addr = __pa(addr); + + if (remap_page_range + (vma, vma->vm_start, addr, PAGE_SIZE, vma->vm_page_prot)) { + printk(KERN_ERR "remap_page_range failed in hpet.c\n"); + return -EAGAIN; + } + + return 0; +#endif +} + +static int hpet_fasync(int fd, struct file *file, int on) +{ + struct hpet_dev *devp; + + devp = file->private_data; + + if (fasync_helper(fd, file, on, &devp->hd_async_queue) >= 0) + return 0; + else + return -EIO; +} + +static int hpet_release(struct inode *inode, struct file *file) +{ + struct hpet_dev *devp; + struct hpet_timer *timer; + int irq = 0; + + devp = file->private_data; + timer = devp->hd_timer; + + spin_lock_irq(&hpet_lock); + + writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), + &timer->hpet_config); + + irq = devp->hd_irq; + devp->hd_irq = 0; + + devp->hd_ireqfreq = 0; + + if (devp->hd_flags & HPET_PERIODIC + && readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) { + unsigned long v; + + v = readq(&timer->hpet_config); + v ^= Tn_TYPE_CNF_MASK; + writeq(v, &timer->hpet_config); + } + + devp->hd_flags &= ~(HPET_OPEN | HPET_IE | HPET_PERIODIC); + spin_unlock_irq(&hpet_lock); + + if (irq) + free_irq(irq, devp); + + if (file->f_flags & FASYNC) + hpet_fasync(-1, file, 0); + + file->private_data = 0; + return 0; +} + +static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int); + +static int +hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct hpet_dev *devp; + + devp = file->private_data; + return hpet_ioctl_common(devp, cmd, arg, 0); +} + +static int hpet_ioctl_ieon(struct hpet_dev *devp) +{ + struct hpet_timer *timer; + struct hpet *hpet; + struct hpets *hpetp; + int irq; + unsigned long g, v, t, m; + unsigned long flags, isr; + + timer = devp->hd_timer; + hpet = devp->hd_hpet; + hpetp = devp->hd_hpets; + + v = readq(&timer->hpet_config); + spin_lock_irq(&hpet_lock); + + if (devp->hd_flags & HPET_IE) { + spin_unlock_irq(&hpet_lock); + return -EBUSY; + } + + devp->hd_flags |= HPET_IE; + spin_unlock_irq(&hpet_lock); + + t = readq(&timer->hpet_config); + irq = devp->hd_hdwirq; + + if (irq) { + char name[7]; + + sprintf(name, "hpet%d", (int)(devp - hpetp->hp_dev)); + + if (request_irq + (irq, hpet_interrupt, SA_INTERRUPT, name, (void *)devp)) { + printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); + irq = 0; + } + } + + if (irq == 0) { + spin_lock_irq(&hpet_lock); + devp->hd_flags ^= HPET_IE; + spin_unlock_irq(&hpet_lock); + return -EIO; + } + + devp->hd_irq = irq; + t = devp->hd_ireqfreq; + v = readq(&timer->hpet_config); + g = v | Tn_INT_ENB_CNF_MASK; + + if (devp->hd_flags & HPET_PERIODIC) { + write_counter(t, &timer->hpet_compare); + g |= Tn_TYPE_CNF_MASK; + v |= Tn_TYPE_CNF_MASK; + writeq(v, &timer->hpet_config); + v |= Tn_VAL_SET_CNF_MASK; + writeq(v, &timer->hpet_config); + local_irq_save(flags); + m = read_counter(&hpet->hpet_mc); + write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); + } else { + local_irq_save(flags); + m = read_counter(&hpet->hpet_mc); + write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); + } + + isr = (1 << (devp - hpets->hp_dev)); + writeq(isr, &hpet->hpet_isr); + writeq(g, &timer->hpet_config); + local_irq_restore(flags); + + return 0; +} + +static inline unsigned long hpet_time_div(unsigned long dis) +{ + unsigned long long m = 1000000000000000ULL; + + do_div(m, dis); + + return (unsigned long)m; +} + +static int +hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) +{ + struct hpet_timer *timer; + struct hpet *hpet; + struct hpets *hpetp; + int err; + unsigned long v; + + switch (cmd) { + case HPET_IE_OFF: + case HPET_INFO: + case HPET_EPI: + case HPET_DPI: + case HPET_IRQFREQ: + timer = devp->hd_timer; + hpet = devp->hd_hpet; + hpetp = devp->hd_hpets; + break; + case HPET_IE_ON: + return hpet_ioctl_ieon(devp); + default: + return -EINVAL; + } + + err = 0; + + switch (cmd) { + case HPET_IE_OFF: + if ((devp->hd_flags & HPET_IE) == 0) + break; + v = readq(&timer->hpet_config); + v &= ~Tn_INT_ENB_CNF_MASK; + writeq(v, &timer->hpet_config); + if (devp->hd_irq) { + free_irq(devp->hd_irq, devp); + devp->hd_irq = 0; + } + devp->hd_flags ^= HPET_IE; + break; + case HPET_INFO: + { + struct hpet_info info; + + info.hi_ireqfreq = hpet_time_div(hpetp->hp_period * + devp->hd_ireqfreq); + info.hi_flags = + readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; + info.hi_hpet = devp->hd_hpets->hp_which; + info.hi_timer = devp - devp->hd_hpets->hp_dev; + if (copy_to_user((void *)arg, &info, sizeof(info))) + err = -EFAULT; + break; + } + case HPET_EPI: + v = readq(&timer->hpet_config); + if ((v & Tn_PER_INT_CAP_MASK) == 0) { + err = -ENXIO; + break; + } + devp->hd_flags |= HPET_PERIODIC; + break; + case HPET_DPI: + v = readq(&timer->hpet_config); + if ((v & Tn_PER_INT_CAP_MASK) == 0) { + err = -ENXIO; + break; + } + if (devp->hd_flags & HPET_PERIODIC && + readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) { + v = readq(&timer->hpet_config); + v ^= Tn_TYPE_CNF_MASK; + writeq(v, &timer->hpet_config); + } + devp->hd_flags &= ~HPET_PERIODIC; + break; + case HPET_IRQFREQ: + if (!kernel && (arg > hpet_max_freq) && + !capable(CAP_SYS_RESOURCE)) { + err = -EACCES; + break; + } + + if (arg & (arg - 1)) { + err = -EINVAL; + break; + } + + devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg); + } + + return err; +} + +static struct file_operations hpet_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = hpet_read, + .poll = hpet_poll, + .ioctl = hpet_ioctl, + .open = hpet_open, + .release = hpet_release, + .fasync = hpet_fasync, + .mmap = hpet_mmap, +}; + +EXPORT_SYMBOL(hpet_alloc); +EXPORT_SYMBOL(hpet_register); +EXPORT_SYMBOL(hpet_unregister); +EXPORT_SYMBOL(hpet_control); + +int hpet_register(struct hpet_task *tp, int periodic) +{ + unsigned int i; + u64 mask; + struct hpet_timer *timer; + struct hpet_dev *devp; + struct hpets *hpetp; + + switch (periodic) { + case 1: + mask = Tn_PER_INT_CAP_MASK; + break; + case 0: + mask = 0; + break; + default: + return -EINVAL; + } + + spin_lock_irq(&hpet_task_lock); + spin_lock(&hpet_lock); + + for (devp = 0, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) + for (timer = hpetp->hp_hpet->hpet_timers, i = 0; + i < hpetp->hp_ntimer; i++, timer++) { + if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK) + != mask) + continue; + + devp = &hpetp->hp_dev[i]; + + if (devp->hd_flags & HPET_OPEN || devp->hd_task) { + devp = 0; + continue; + } + + tp->ht_opaque = devp; + devp->hd_task = tp; + break; + } + + spin_unlock(&hpet_lock); + spin_unlock_irq(&hpet_task_lock); + + if (tp->ht_opaque) + return 0; + else + return -EBUSY; +} + +static inline int hpet_tpcheck(struct hpet_task *tp) +{ + struct hpet_dev *devp; + struct hpets *hpetp; + + devp = tp->ht_opaque; + + if (!devp) + return -ENXIO; + + for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) + if (devp >= hpetp->hp_dev + && devp < (hpetp->hp_dev + hpetp->hp_ntimer) + && devp->hd_hpet == hpetp->hp_hpet) + return 0; + + return -ENXIO; +} + +int hpet_unregister(struct hpet_task *tp) +{ + struct hpet_dev *devp; + struct hpet_timer *timer; + int err; + + if ((err = hpet_tpcheck(tp))) + return err; + + spin_lock_irq(&hpet_task_lock); + spin_lock(&hpet_lock); + + devp = tp->ht_opaque; + if (devp->hd_task != tp) { + spin_unlock(&hpet_lock); + spin_unlock_irq(&hpet_task_lock); + return -ENXIO; + } + + timer = devp->hd_timer; + writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), + &timer->hpet_config); + devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC); + devp->hd_task = 0; + spin_unlock(&hpet_lock); + spin_unlock_irq(&hpet_task_lock); + + return 0; +} + +int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) +{ + struct hpet_dev *devp; + int err; + + if ((err = hpet_tpcheck(tp))) + return err; + + spin_lock_irq(&hpet_lock); + devp = tp->ht_opaque; + if (devp->hd_task != tp) { + spin_unlock_irq(&hpet_lock); + return -ENXIO; + } + spin_unlock_irq(&hpet_lock); + return hpet_ioctl_common(devp, cmd, arg, 1); +} + +#ifdef CONFIG_TIME_INTERPOLATION + +static unsigned long hpet_offset, last_wall_hpet; +static long hpet_nsecs_per_cycle, hpet_cycles_per_sec; + +static unsigned long hpet_getoffset(void) +{ + return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) - + last_wall_hpet) * hpet_nsecs_per_cycle; +} + +static void hpet_update(long delta) +{ + unsigned long mc; + unsigned long offset; + + mc = read_counter(&hpets->hp_hpet->hpet_mc); + offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle; + + if (delta < 0 || (unsigned long)delta < offset) + hpet_offset = offset - delta; + else + hpet_offset = 0; + last_wall_hpet = mc; +} + +static void hpet_reset(void) +{ + hpet_offset = 0; + last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc); +} + +static struct time_interpolator hpet_interpolator = { + .get_offset = hpet_getoffset, + .update = hpet_update, + .reset = hpet_reset +}; + +#endif + +static ctl_table hpet_table[] = { + { + .ctl_name = 1, + .procname = "max-user-freq", + .data = &hpet_max_freq, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + {.ctl_name = 0} +}; + +static ctl_table hpet_root[] = { + { + .ctl_name = 1, + .procname = "hpet", + .maxlen = 0, + .mode = 0555, + .child = hpet_table, + }, + {.ctl_name = 0} +}; + +static ctl_table dev_root[] = { + { + .ctl_name = CTL_DEV, + .procname = "dev", + .maxlen = 0, + .mode = 0555, + .child = hpet_root, + }, + {.ctl_name = 0} +}; + +static struct ctl_table_header *sysctl_header; + +static void *hpet_start(struct seq_file *s, loff_t * pos) +{ + struct hpets *hpetp; + loff_t n; + + for (n = *pos, hpetp = hpets; hpetp; hpetp = hpetp->hp_next) + if (!n--) + return hpetp; + + return 0; +} + +static void *hpet_next(struct seq_file *s, void *v, loff_t * pos) +{ + struct hpets *hpetp; + + hpetp = v; + ++*pos; + return hpetp->hp_next; +} + +static void hpet_stop(struct seq_file *s, void *v) +{ + return; +} + +static int hpet_show(struct seq_file *s, void *v) +{ + struct hpets *hpetp; + struct hpet *hpet; + u64 cap, vendor, period; + + hpetp = v; + hpet = hpetp->hp_hpet; + + cap = readq(&hpet->hpet_cap); + period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> + HPET_COUNTER_CLK_PERIOD_SHIFT; + vendor = (cap & HPET_VENDOR_ID_MASK) >> HPET_VENDOR_ID_SHIFT; + + seq_printf(s, + "HPET%d period = %d 10**-15 vendor = 0x%x number timer = %d\n", + hpetp->hp_which, (u32) period, (u32) vendor, + hpetp->hp_ntimer); + + return 0; +} + +static struct seq_operations hpet_seq_ops = { + .start = hpet_start, + .next = hpet_next, + .stop = hpet_stop, + .show = hpet_show +}; + +static int hpet_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &hpet_seq_ops); +} + +static struct file_operations hpet_proc_fops = { + .open = hpet_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +/* + * Adjustment for when arming the timer with + * initial conditions. That is, main counter + * ticks expired before interrupts are enabled. + */ +#define TICK_CALIBRATE (1000UL) + +static unsigned long __init hpet_calibrate(struct hpets *hpetp) +{ + struct hpet_timer *timer; + unsigned long t, m, count, i, flags, start; + struct hpet_dev *devp; + int j; + struct hpet *hpet; + + for (timer = 0, j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; + j++, devp++) + if ((devp->hd_flags & HPET_OPEN) == 0) { + timer = devp->hd_timer; + break; + } + + if (!timer) + return 0; + + hpet = hpets->hp_hpet; + t = read_counter(&timer->hpet_compare); + + i = 0; + count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE); + + local_irq_save(flags); + + start = read_counter(&hpet->hpet_mc); + + do { + m = read_counter(&hpet->hpet_mc); + write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); + } while (i++, (m - start) < count); + + local_irq_restore(flags); + + return (m - start) / i; +} + +int __init hpet_alloc(struct hpet_data *hdp) +{ + u64 cap, mcfg; + struct hpet_dev *devp; + u32 i, ntimer; + struct hpets *hpetp; + size_t siz; + struct hpet *hpet; + static struct hpets *last __initdata = (struct hpets *)0; + + /* + * hpet_alloc can be called by platform dependent code. + * if platform dependent code has allocated the hpet + * ACPI also reports hpet, then we catch it here. + */ + for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) + if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address)) + return 0; + + siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * + sizeof(struct hpet_dev)); + + hpetp = kmalloc(siz, GFP_KERNEL); + + if (!hpetp) + return -ENOMEM; + + memset(hpetp, 0, siz); + + hpetp->hp_which = hpet_nhpet++; + hpetp->hp_hpet = (struct hpet *)hdp->hd_address; + + hpetp->hp_ntimer = hdp->hd_nirqs; + + for (i = 0; i < hdp->hd_nirqs; i++) + hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; + + hpet = hpetp->hp_hpet; + + cap = readq(&hpet->hpet_cap); + + ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1; + + if (hpetp->hp_ntimer != ntimer) { + printk(KERN_WARNING "hpet: number irqs doesn't agree" + " with number of timers\n"); + kfree(hpetp); + return -ENODEV; + } + + if (last) + last->hp_next = hpetp; + else + hpets = hpetp; + + last = hpetp; + + hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> + HPET_COUNTER_CLK_PERIOD_SHIFT; + + mcfg = readq(&hpet->hpet_config); + if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { + write_counter(0L, &hpet->hpet_mc); + mcfg |= HPET_ENABLE_CNF_MASK; + writeq(mcfg, &hpet->hpet_config); + } + + for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; + i++, hpet_ntimer++, devp++) { + unsigned long v; + struct hpet_timer *timer; + + timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; + v = readq(&timer->hpet_config); + + devp->hd_hpets = hpetp; + devp->hd_hpet = hpet; + devp->hd_timer = timer; + + /* + * If the timer was reserved by platform code, + * then make timer unavailable for opens. + */ + if (hdp->hd_state & (1 << i)) { + devp->hd_flags = HPET_OPEN; + continue; + } + + init_waitqueue_head(&devp->hd_waitqueue); + } + + hpetp->hp_delta = hpet_calibrate(hpetp); + + return 0; +} + +static acpi_status __init hpet_resources(struct acpi_resource *res, void *data) +{ + struct hpet_data *hdp; + acpi_status status; + struct acpi_resource_address64 addr; + struct hpets *hpetp; + + hdp = data; + + status = acpi_resource_to_address64(res, &addr); + + if (ACPI_SUCCESS(status)) { + unsigned long size; + + size = addr.max_address_range - addr.min_address_range + 1; + hdp->hd_address = + (unsigned long)ioremap(addr.min_address_range, size); + + for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) + if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address)) + return -EBUSY; + } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { + struct acpi_resource_ext_irq *irqp; + int i; + + irqp = &res->data.extended_irq; + + if (irqp->number_of_interrupts > 0) { + hdp->hd_nirqs = irqp->number_of_interrupts; + + for (i = 0; i < hdp->hd_nirqs; i++) +#ifdef CONFIG_IA64 + hdp->hd_irq[i] = + acpi_register_gsi(irqp->interrupts[i], + irqp->edge_level, + irqp->active_high_low); +#else + hdp->hd_irq[i] = irqp->interrupts[i]; +#endif + } + } + + return AE_OK; +} + +static int __init hpet_acpi_add(struct acpi_device *device) +{ + acpi_status result; + struct hpet_data data; + + memset(&data, 0, sizeof(data)); + + result = + acpi_walk_resources(device->handle, METHOD_NAME__CRS, + hpet_resources, &data); + + if (ACPI_FAILURE(result)) + return -ENODEV; + + if (!data.hd_address || !data.hd_nirqs) { + printk("%s: no address or irqs in _CRS\n", __FUNCTION__); + return -ENODEV; + } + + return hpet_alloc(&data); +} + +static int __init hpet_acpi_remove(struct acpi_device *device, int type) +{ + return 0; +} + +static struct acpi_driver hpet_acpi_driver __initdata = { + .name = "hpet", + .class = "", + .ids = "PNP0103", + .ops = { + .add = hpet_acpi_add, + .remove = hpet_acpi_remove, + }, +}; + +static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; + +static int __init hpet_init(void) +{ + struct proc_dir_entry *entry; + + (void)acpi_bus_register_driver(&hpet_acpi_driver); + + if (hpets) { + if (misc_register(&hpet_misc)) + return -ENODEV; + + entry = create_proc_entry("driver/hpet", 0, 0); + + if (entry) + entry->proc_fops = &hpet_proc_fops; + + sysctl_header = register_sysctl_table(dev_root, 0); + +#ifdef CONFIG_TIME_INTERPOLATION + { + struct hpet *hpet; + + hpet = hpets->hp_hpet; + hpet_cycles_per_sec = hpet_time_div(hpets->hp_period); + hpet_interpolator.frequency = hpet_cycles_per_sec; + hpet_interpolator.drift = hpet_cycles_per_sec * + HPET_DRIFT / 1000000; + hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec; + register_time_interpolator(&hpet_interpolator); + } +#endif + return 0; + } else + return -ENODEV; +} + +static void __exit hpet_exit(void) +{ + acpi_bus_unregister_driver(&hpet_acpi_driver); + + if (hpets) { + unregister_sysctl_table(sysctl_header); + remove_proc_entry("driver/hpet", NULL); + } + + return; +} + +module_init(hpet_init); +module_exit(hpet_exit); +MODULE_AUTHOR("Bob Picco "); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c --- a/drivers/char/ipmi/ipmi_bt_sm.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/ipmi/ipmi_bt_sm.c 2004-06-20 13:00:25 -07:00 @@ -31,7 +31,7 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_BT_VERSION "v31" +#define IPMI_BT_VERSION "v32" static int bt_debug = 0x00; /* Production value 0, see following flags */ diff -Nru a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c --- a/drivers/char/ipmi/ipmi_devintf.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/ipmi/ipmi_devintf.c 2004-06-20 13:00:25 -07:00 @@ -45,7 +45,7 @@ #include #include -#define IPMI_DEVINTF_VERSION "v31" +#define IPMI_DEVINTF_VERSION "v32" struct ipmi_file_private { @@ -199,7 +199,7 @@ goto out; } - if (copy_from_user(&msgdata, + if (copy_from_user(msgdata, req->msg.data, req->msg.data_len)) { @@ -231,6 +231,7 @@ { int rv = -EINVAL; struct ipmi_file_private *priv = file->private_data; + void __user *arg = (void __user *)data; switch (cmd) { @@ -238,7 +239,7 @@ { struct ipmi_req req; - if (copy_from_user(&req, (void *) data, sizeof(req))) { + if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } @@ -254,7 +255,7 @@ { struct ipmi_req_settime req; - if (copy_from_user(&req, (void *) data, sizeof(req))) { + if (copy_from_user(&req, arg, sizeof(req))) { rv = -EFAULT; break; } @@ -277,7 +278,7 @@ rv = 0; - if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) { + if (copy_from_user(&rsp, arg, sizeof(rsp))) { rv = -EFAULT; break; } @@ -344,7 +345,7 @@ rsp.msg.data_len = 0; } - if (copy_to_user((void *) data, &rsp, sizeof(rsp))) { + if (copy_to_user(arg, &rsp, sizeof(rsp))) { rv = -EFAULT; goto recv_putback_on_err; } @@ -371,7 +372,7 @@ { struct ipmi_cmdspec val; - if (copy_from_user(&val, (void *) data, sizeof(val))) { + if (copy_from_user(&val, arg, sizeof(val))) { rv = -EFAULT; break; } @@ -384,7 +385,7 @@ { struct ipmi_cmdspec val; - if (copy_from_user(&val, (void *) data, sizeof(val))) { + if (copy_from_user(&val, arg, sizeof(val))) { rv = -EFAULT; break; } @@ -397,7 +398,7 @@ { int val; - if (copy_from_user(&val, (void *) data, sizeof(val))) { + if (copy_from_user(&val, arg, sizeof(val))) { rv = -EFAULT; break; } @@ -410,7 +411,7 @@ { unsigned int val; - if (copy_from_user(&val, (void *) data, sizeof(val))) { + if (copy_from_user(&val, arg, sizeof(val))) { rv = -EFAULT; break; } @@ -426,7 +427,7 @@ val = ipmi_get_my_address(priv->user); - if (copy_to_user((void *) data, &val, sizeof(val))) { + if (copy_to_user(arg, &val, sizeof(val))) { rv = -EFAULT; break; } @@ -438,7 +439,7 @@ { unsigned int val; - if (copy_from_user(&val, (void *) data, sizeof(val))) { + if (copy_from_user(&val, arg, sizeof(val))) { rv = -EFAULT; break; } @@ -454,7 +455,7 @@ val = ipmi_get_my_LUN(priv->user); - if (copy_to_user((void *) data, &val, sizeof(val))) { + if (copy_to_user(arg, &val, sizeof(val))) { rv = -EFAULT; break; } @@ -465,7 +466,7 @@ { struct ipmi_timing_parms parms; - if (copy_from_user(&parms, (void *) data, sizeof(parms))) { + if (copy_from_user(&parms, arg, sizeof(parms))) { rv = -EFAULT; break; } @@ -483,7 +484,7 @@ parms.retries = priv->default_retries; parms.retry_time_ms = priv->default_retry_time_ms; - if (copy_to_user((void *) data, &parms, sizeof(parms))) { + if (copy_to_user(arg, &parms, sizeof(parms))) { rv = -EFAULT; break; } diff -Nru a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c --- a/drivers/char/ipmi/ipmi_kcs_sm.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/ipmi/ipmi_kcs_sm.c 2004-06-20 13:00:23 -07:00 @@ -42,7 +42,7 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_KCS_VERSION "v31" +#define IPMI_KCS_VERSION "v32" /* Set this if you want a printout of why the state machine was hosed when it gets hosed. */ diff -Nru a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c --- a/drivers/char/ipmi/ipmi_msghandler.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/ipmi/ipmi_msghandler.c 2004-06-20 13:00:24 -07:00 @@ -46,7 +46,7 @@ #include #include -#define IPMI_MSGHANDLER_VERSION "v31" +#define IPMI_MSGHANDLER_VERSION "v32" struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); @@ -1648,6 +1648,22 @@ /* It's the one we want */ if (msg->rsp[2] != 0) { /* Got an error from the channel, just go on. */ + + if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) { + /* If the MC does not support this + command, that is legal. We just + assume it has one IPMB at channel + zero. */ + intf->channels[0].medium + = IPMI_CHANNEL_MEDIUM_IPMB; + intf->channels[0].protocol + = IPMI_CHANNEL_PROTOCOL_IPMB; + rv = -ENOSYS; + + intf->curr_channel = IPMI_MAX_CHANNELS; + wake_up(&intf->waitq); + goto out; + } goto next_channel; } if (msg->rsp_size < 6) { @@ -1671,10 +1687,20 @@ wake_up(&intf->waitq); printk(KERN_WARNING "ipmi_msghandler: Error sending" - "channel information: 0x%x\n", + "channel information: %d\n", rv); } } + out: + return; +} + +void ipmi_poll_interface(ipmi_user_t user) +{ + ipmi_smi_t intf = user->intf; + + if (intf->handlers->poll) + intf->handlers->poll(intf->send_info); } int ipmi_register_smi(struct ipmi_smi_handlers *handlers, @@ -3154,6 +3180,7 @@ EXPORT_SYMBOL(ipmi_request_settime); EXPORT_SYMBOL(ipmi_request_supply_msgs); EXPORT_SYMBOL(ipmi_request_with_source); +EXPORT_SYMBOL(ipmi_poll_interface); EXPORT_SYMBOL(ipmi_register_smi); EXPORT_SYMBOL(ipmi_unregister_smi); EXPORT_SYMBOL(ipmi_register_for_cmd); diff -Nru a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c --- a/drivers/char/ipmi/ipmi_si_intf.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/ipmi/ipmi_si_intf.c 2004-06-20 13:00:23 -07:00 @@ -76,7 +76,7 @@ #include "ipmi_si_sm.h" #include -#define IPMI_SI_VERSION "v31" +#define IPMI_SI_VERSION "v32" /* Measure times between events in the driver. */ #undef DEBUG_TIMING @@ -712,6 +712,13 @@ spin_unlock_irqrestore(&(smi_info->si_lock), flags); } +static void poll(void *send_info) +{ + struct smi_info *smi_info = send_info; + + smi_event_handler(smi_info, 0); +} + static void request_events(void *send_info) { struct smi_info *smi_info = send_info; @@ -851,7 +858,8 @@ .owner = THIS_MODULE, .sender = sender, .request_events = request_events, - .set_run_to_completion = set_run_to_completion + .set_run_to_completion = set_run_to_completion, + .poll = poll, }; /* There can be 4 IO ports passed in (with or without IRQs), 4 addresses, @@ -1848,6 +1856,21 @@ atomic_set(&new_smi->req_events, 0); new_smi->run_to_completion = 0; + new_smi->interrupt_disabled = 0; + new_smi->timer_stopped = 0; + new_smi->stop_operation = 0; + + /* The ipmi_register_smi() code does some operations to + determine the channel information, so we must be ready to + handle operations before it is called. This means we have + to stop the timer if we get an error after this point. */ + init_timer(&(new_smi->si_timer)); + new_smi->si_timer.data = (long) new_smi; + new_smi->si_timer.function = smi_timeout; + new_smi->last_timeout_jiffies = jiffies; + new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; + add_timer(&(new_smi->si_timer)); + rv = ipmi_register_smi(&handlers, new_smi, new_smi->ipmi_version_major, @@ -1857,7 +1880,7 @@ printk(KERN_ERR "ipmi_si: Unable to register device: error %d\n", rv); - goto out_err; + goto out_err_stop_timer; } rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", @@ -1867,7 +1890,7 @@ printk(KERN_ERR "ipmi_si: Unable to create proc entry: %d\n", rv); - goto out_err; + goto out_err_stop_timer; } rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", @@ -1877,7 +1900,7 @@ printk(KERN_ERR "ipmi_si: Unable to create proc entry: %d\n", rv); - goto out_err; + goto out_err_stop_timer; } start_clear_flags(new_smi); @@ -1886,34 +1909,40 @@ if (new_smi->irq) new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; - new_smi->interrupt_disabled = 0; - new_smi->timer_stopped = 0; - new_smi->stop_operation = 0; - - init_timer(&(new_smi->si_timer)); - new_smi->si_timer.data = (long) new_smi; - new_smi->si_timer.function = smi_timeout; - new_smi->last_timeout_jiffies = jiffies; - new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; - add_timer(&(new_smi->si_timer)); - *smi = new_smi; printk(" IPMI %s interface initialized\n", si_type[intf_num]); return 0; + out_err_stop_timer: + new_smi->stop_operation = 1; + + /* Wait for the timer to stop. This avoids problems with race + conditions removing the timer here. */ + while (!new_smi->timer_stopped) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + out_err: if (new_smi->intf) ipmi_unregister_smi(new_smi->intf); new_smi->irq_cleanup(new_smi); + + /* Wait until we know that we are out of any interrupt + handlers might have been running before we freed the + interrupt. */ + synchronize_kernel(); + if (new_smi->si_sm) { if (new_smi->handlers) new_smi->handlers->cleanup(new_smi->si_sm); kfree(new_smi->si_sm); } new_smi->io_cleanup(new_smi); + return rv; } diff -Nru a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c --- a/drivers/char/ipmi/ipmi_smic_sm.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/ipmi/ipmi_smic_sm.c 2004-06-20 13:00:24 -07:00 @@ -46,7 +46,7 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_SMIC_VERSION "v31" +#define IPMI_SMIC_VERSION "v32" /* smic_debug is a bit-field * SMIC_DEBUG_ENABLE - turned on for now diff -Nru a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c --- a/drivers/char/ipmi/ipmi_watchdog.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/char/ipmi/ipmi_watchdog.c 2004-06-20 13:00:26 -07:00 @@ -51,7 +51,7 @@ #include #endif -#define IPMI_WATCHDOG_VERSION "v31" +#define IPMI_WATCHDOG_VERSION "v32" /* * The IPMI command/response information for the watchdog timer. @@ -515,40 +515,37 @@ static int ipmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; int i; int val; switch(cmd) { case WDIOC_GETSUPPORT: - i = copy_to_user((void*)arg, &ident, sizeof(ident)); + i = copy_to_user(argp, &ident, sizeof(ident)); return i ? -EFAULT : 0; case WDIOC_SETTIMEOUT: - i = copy_from_user(&val, (void *) arg, sizeof(int)); + i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; timeout = val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); case WDIOC_GETTIMEOUT: - i = copy_to_user((void *) arg, - &timeout, - sizeof(timeout)); + i = copy_to_user(argp, &timeout, sizeof(timeout)); if (i) return -EFAULT; return 0; case WDIOC_SET_PRETIMEOUT: - i = copy_from_user(&val, (void *) arg, sizeof(int)); + i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; pretimeout = val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); case WDIOC_GET_PRETIMEOUT: - i = copy_to_user((void *) arg, - &pretimeout, - sizeof(pretimeout)); + i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); if (i) return -EFAULT; return 0; @@ -557,7 +554,7 @@ return ipmi_heartbeat(); case WDIOC_SETOPTIONS: - i = copy_from_user(&val, (void *) arg, sizeof(int)); + i = copy_from_user(&val, argp, sizeof(int)); if (i) return -EFAULT; if (val & WDIOS_DISABLECARD) @@ -576,7 +573,7 @@ case WDIOC_GETSTATUS: val = 0; - i = copy_to_user((void *) arg, &val, sizeof(val)); + i = copy_to_user(argp, &val, sizeof(val)); if (i) return -EFAULT; return 0; @@ -587,7 +584,7 @@ } static ssize_t ipmi_write(struct file *file, - const char *buf, + const char __user *buf, size_t len, loff_t *ppos) { @@ -607,7 +604,7 @@ } static ssize_t ipmi_read(struct file *file, - char *buf, + char __user *buf, size_t count, loff_t *ppos) { @@ -883,14 +880,12 @@ /* On a panic, if we have a panic timeout, make sure that the thing reboots, even if it hangs during that panic. */ - if (watchdog_user && !panic_event_handled && (panic_timeout > 0)) { + if (watchdog_user && !panic_event_handled) { /* Make sure the panic doesn't hang, and make sure we do this only once. */ panic_event_handled = 1; - timeout = panic_timeout + 120; - if (timeout > 255) - timeout = 255; + timeout = 255; pretimeout = 0; ipmi_watchdog_state = WDOG_TIMEOUT_RESET; panic_halt_ipmi_set_timeout(); diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/istallion.c 2004-06-20 13:00:25 -07:00 @@ -851,7 +851,7 @@ i = tty_unregister_driver(stli_serial); if (i) { printk("STALLION: failed to un-register tty driver, " - "errno=%d,%d\n", -i); + "errno=%d\n", -i); restore_flags(flags); return; } diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c --- a/drivers/char/keyboard.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/char/keyboard.c 2004-06-20 13:00:26 -07:00 @@ -52,13 +52,12 @@ /* * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on. - * This seems a good reason to start with NumLock off. On PC9800 and HIL keyboards + * This seems a good reason to start with NumLock off. On HIL keyboards * of PARISC machines however there is no NumLock key and everyone expects the keypad * to be used for numbers. */ -#if defined(CONFIG_X86_PC9800) || \ - defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD)) +#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD)) #define KBD_DEFLEDS (1 << VC_NUMLOCK) #else #define KBD_DEFLEDS 0 diff -Nru a/drivers/char/lp_old98.c b/drivers/char/lp_old98.c --- a/drivers/char/lp_old98.c 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,537 +0,0 @@ -/* - * linux/drivers/char/lp_old98.c - * - * printer port driver for ancient PC-9800s with no bidirectional port support - * - * Copyright (C) 1998,99 Kousuke Takai , - * Kyoto University Microcomputer Club - * - * This driver is based on and has compatibility with `lp.c', - * generic PC printer port driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -/* - * I/O port numbers - */ -#define LP_PORT_DATA 0x40 -#define LP_PORT_STATUS (LP_PORT_DATA + 2) -#define LP_PORT_STROBE (LP_PORT_DATA + 4) -#define LP_PORT_CONTROL (LP_PORT_DATA + 6) - -#define LP_PORT_H98MODE 0x0448 -#define LP_PORT_EXTMODE 0x0149 - -/* - * bit mask for I/O - */ -#define LP_MASK_nBUSY (1 << 2) -#define LP_MASK_nSTROBE (1 << 7) - -#define LP_CONTROL_ASSERT_STROBE (0x0e) -#define LP_CONTROL_NEGATE_STROBE (0x0f) - -/* - * Acceptable maximum value for non-privileged user for LPCHARS ioctl. - */ -#define LP_CHARS_NOPRIV_MAX 65535 - -#define DC1 '\x11' -#define DC3 '\x13' - -/* PC-9800s have at least and at most one old-style printer port. */ -static struct lp_struct lp = { - .flags = LP_EXIST | LP_ABORTOPEN, - .chars = LP_INIT_CHAR, - .time = LP_INIT_TIME, - .wait = LP_INIT_WAIT, -}; - -static int dc1_check; -static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED; - - -#undef LP_OLD98_DEBUG - -#ifdef CONFIG_PC9800_OLDLP_CONSOLE -static struct console lp_old98_console; /* defined later */ -static short saved_console_flags; -#endif - -static DECLARE_WAIT_QUEUE_HEAD (lp_old98_waitq); - -static void lp_old98_timer_function(unsigned long data) -{ - if (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) - wake_up_interruptible(&lp_old98_waitq); - else { - struct timer_list *t = (struct timer_list *) data; - - t->expires = jiffies + 1; - add_timer(t); - } -} - -static inline int lp_old98_wait_ready(void) -{ - struct timer_list timer; - - init_timer(&timer); - timer.function = lp_old98_timer_function; - timer.expires = jiffies + 1; - timer.data = (unsigned long)&timer; - add_timer(&timer); - interruptible_sleep_on(&lp_old98_waitq); - del_timer(&timer); - return signal_pending(current); -} - -static inline int lp_old98_char(char lpchar) -{ - unsigned long count = 0; -#ifdef LP_STATS - int tmp; -#endif - - while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) { - count++; - if (count >= lp.chars) - return 0; - } - - outb(lpchar, LP_PORT_DATA); - -#ifdef LP_STATS - /* - * Update lp statsistics here (and between next two outb()'s). - * Time to compute it is part of storobe delay. - */ - if (count > lp.stats.maxwait) { -#ifdef LP_OLD98_DEBUG - printk(KERN_DEBUG "lp_old98: success after %d counts.\n", - count); -#endif - lp.stats.maxwait = count; - } - count *= 256; - tmp = count - lp.stats.meanwait; - if (tmp < 0) - tmp = -tmp; -#endif - ndelay(lp.wait); - - /* negate PSTB# (activate strobe) */ - outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL); - -#ifdef LP_STATS - lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256; - lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128; - lp.stats.chars ++; -#endif - - ndelay(lp.wait); - - /* assert PSTB# (deactivate strobe) */ - outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL); - - return 1; -} - -static ssize_t lp_old98_write(struct file * file, - const char * buf, size_t count, - loff_t *dummy) -{ - unsigned long total_bytes_written = 0; - - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - -#ifdef LP_STATS - if (jiffies - lp.lastcall > lp.time) - lp.runchars = 0; - lp.lastcall = jiffies; -#endif - - do { - unsigned long bytes_written = 0; - unsigned long copy_size - = (count < LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE); - - if (__copy_from_user(lp.lp_buffer, buf, copy_size)) - return -EFAULT; - - while (bytes_written < copy_size) { - if (lp_old98_char(lp.lp_buffer[bytes_written])) - bytes_written ++; - else { -#ifdef LP_STATS - int rc = lp.runchars + bytes_written; - - if (rc > lp.stats.maxrun) - lp.stats.maxrun = rc; - - lp.stats.sleeps ++; -#endif -#ifdef LP_OLD98_DEBUG - printk(KERN_DEBUG - "lp_old98: sleeping at %d characters" - " for %d jiffies\n", - lp.runchars, lp.time); - lp.runchars = 0; -#endif - if (lp_old98_wait_ready()) - return ((total_bytes_written - + bytes_written) - ? : -EINTR); - } - } - total_bytes_written += bytes_written; - buf += bytes_written; -#ifdef LP_STATS - lp.runchars += bytes_written; -#endif - count -= bytes_written; - } while (count > 0); - - return total_bytes_written; -} - -static int lp_old98_open(struct inode * inode, struct file * file) -{ - if (iminor(inode) != 0) - return -ENXIO; - - if (lp.flags & LP_BUSY) - return -EBUSY; - - if (dc1_check && (lp.flags & LP_ABORTOPEN) - && !(file->f_flags & O_NONBLOCK)) { - /* - * Check whether printer is on-line. - * PC-9800's old style port have only BUSY# as status input, - * so that it is impossible to distinguish that the printer is - * ready and that the printer is off-line or not connected - * (in both case BUSY# is in the same state). So: - * - * (1) output DC1 (0x11) to printer port and do strobe. - * (2) watch BUSY# line for a while. If BUSY# is pulled - * down, the printer will be ready. Otherwise, - * it will be off-line (or not connected, or power-off, - * ...). - * - * The source of this procedure: - * Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI: - * `PC-9801 Super Technique', Ascii, 1992. - */ - int count; - unsigned long flags; - - /* interrupts while check is fairly bad */ - spin_lock_irqsave(&lp_old98_lock, flags); - - if (!lp_old98_char(DC1)) { - spin_unlock_irqrestore(&lp_old98_lock, flags); - return -EBUSY; - } - count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check; - while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) { - if (--count == 0) { - spin_unlock_irqrestore(&lp_old98_lock, flags); - return -ENODEV; - } - } - spin_unlock_irqrestore(&lp_old98_lock, flags); - } - - if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - - lp.flags |= LP_BUSY; - -#ifdef CONFIG_PC9800_OLDLP_CONSOLE - saved_console_flags = lp_old98_console.flags; - lp_old98_console.flags &= ~CON_ENABLED; -#endif - return 0; -} - -static int lp_old98_release(struct inode * inode, struct file * file) -{ - kfree(lp.lp_buffer); - lp.lp_buffer = NULL; - lp.flags &= ~LP_BUSY; -#ifdef CONFIG_PC9800_OLDLP_CONSOLE - lp_old98_console.flags = saved_console_flags; -#endif - return 0; -} - -static int lp_old98_init_device(void) -{ - unsigned char data; - - if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) { - printk(KERN_INFO - "lp_old98: shutting down extended parallel port mode...\n"); - outb(data & ~0x10, LP_PORT_EXTMODE); - } -#ifdef PC98_HW_H98 - if ((pc98_hw_flags & PC98_HW_H98) - && ((data = inb(LP_PORT_H98MODE)) & 0x01)) { - printk(KERN_INFO - "lp_old98: shutting down H98 full centronics mode...\n"); - outb(data & ~0x01, LP_PORT_H98MODE); - } -#endif - return 0; -} - -static int lp_old98_ioctl(struct inode *inode, struct file *file, - unsigned int command, unsigned long arg) -{ - int retval = 0; - - switch (command) { - case LPTIME: - lp.time = arg * HZ/100; - break; - case LPCHAR: - lp.chars = arg; - break; - case LPABORT: - if (arg) - lp.flags |= LP_ABORT; - else - lp.flags &= ~LP_ABORT; - break; - case LPABORTOPEN: - if (arg) - lp.flags |= LP_ABORTOPEN; - else - lp.flags &= ~LP_ABORTOPEN; - break; - case LPCAREFUL: - /* do nothing */ - break; - case LPWAIT: - lp.wait = arg; - break; - case LPGETIRQ: - retval = put_user(0, (int *)arg); - break; - case LPGETSTATUS: - /* - * convert PC-9800's status to IBM PC's one, so that tunelp(8) - * works in the same way on this driver. - */ - retval = put_user((inb(LP_PORT_STATUS) & LP_MASK_nBUSY) - ? (LP_PBUSY | LP_PERRORP) : LP_PERRORP, - (int *)arg); - break; - case LPRESET: - retval = lp_old98_init_device(); - break; -#ifdef LP_STATS - case LPGETSTATS: - if (copy_to_user((struct lp_stats *)arg, &lp.stats, - sizeof(struct lp_stats))) - retval = -EFAULT; - else if (suser()) - memset(&lp.stats, 0, sizeof(struct lp_stats)); - break; -#endif - case LPGETFLAGS: - retval = put_user(lp.flags, (int *)arg); - break; - case LPSETIRQ: - default: - retval = -EINVAL; - } - return retval; -} - -static struct file_operations lp_old98_fops = { - .owner = THIS_MODULE, - .write = lp_old98_write, - .ioctl = lp_old98_ioctl, - .open = lp_old98_open, - .release = lp_old98_release, -}; - -/* - * Support for console on lp_old98 - */ -#ifdef CONFIG_PC9800_OLDLP_CONSOLE - -static inline void io_delay(void) -{ - unsigned char dummy; /* actually not output */ - - asm volatile ("out%B0 %0,%1" : "=a"(dummy) : "N"(0x5f)); -} - -static void lp_old98_console_write(struct console *console, - const char *s, unsigned int count) -{ - int i; - static unsigned int timeout_run = 0; - - while (count) { - /* wait approx 1.2 seconds */ - for (i = 2000000; !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY); - io_delay()) - if (!--i) { - if (++timeout_run >= 10) - /* disable forever... */ - console->flags &= ~CON_ENABLED; - return; - } - - timeout_run = 0; - - if (*s == '\n') { - outb('\r', LP_PORT_DATA); - io_delay(); - io_delay(); - outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL); - io_delay(); - io_delay(); - outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL); - io_delay(); - io_delay(); - for (i = 1000000; - !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY); - io_delay()) - if (!--i) - return; - } - - outb(*s++, LP_PORT_DATA); - io_delay(); - io_delay(); - outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL); - io_delay(); - io_delay(); - outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL); - io_delay(); - io_delay(); - - --count; - } -} - -static struct console lp_old98_console = { - .name = "lp_old98", - .write = lp_old98_console_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -#endif /* console on lp_old98 */ - -static int __init lp_old98_init(void) -{ - char *errmsg = "I/O ports already occupied, giving up."; - -#ifdef PC98_HW_H98 - if (pc98_hw_flags & PC98_HW_H98) - if (!request_region(LP_PORT_H98MODE, 1, "lp_old98") - goto err1; -#endif - if (!request_region(LP_PORT_DATA, 1, "lp_old98")) - goto err2; - if (!request_region(LP_PORT_STATUS, 1, "lp_old98")) - goto err3; - if (!request_region(LP_PORT_STROBE, 1, "lp_old98")) - goto err4; - if (!request_region(LP_PORT_EXTMODE, 1, "lp_old98")) - goto err5; - if (!register_chrdev(LP_MAJOR, "lp", &lp_old98_fops)) { -#ifdef CONFIG_PC9800_OLDLP_CONSOLE - register_console(&lp_old98_console); - printk(KERN_INFO "lp_old98: console ready\n"); -#endif - /* - * rest are not needed by this driver, - * but for locking out other printer drivers... - */ - lp_old98_init_device(); - return 0; - } else - errmsg = "unable to register device"; - - release_region(LP_PORT_EXTMODE, 1); -err5: - release_region(LP_PORT_STROBE, 1); -err4: - release_region(LP_PORT_STATUS, 1); -err3: - release_region(LP_PORT_DATA, 1); -err2: -#ifdef PC98_HW_H98 - if (pc98_hw_flags & PC98_HW_H98) - release_region(LP_PORT_H98MODE, 1); - -err1: -#endif - printk(KERN_ERR "lp_old98: %s\n", errmsg); - return -EBUSY; -} - -static void __exit lp_old98_exit(void) -{ -#ifdef CONFIG_PC9800_OLDLP_CONSOLE - unregister_console(&lp_old98_console); -#endif - unregister_chrdev(LP_MAJOR, "lp"); - - release_region(LP_PORT_DATA, 1); - release_region(LP_PORT_STATUS, 1); - release_region(LP_PORT_STROBE, 1); -#ifdef PC98_HW_H98 - if (pc98_hw_flags & PC98_HW_H98) - release_region(LP_PORT_H98MODE, 1); -#endif - release_region(LP_PORT_EXTMODE, 1); -} - -#ifndef MODULE -static int __init lp_old98_setup(char *str) -{ - int ints[4]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] > 0) - dc1_check = ints[1]; - return 1; -} -__setup("lp_old98_dc1_check=", lp_old98_setup); -#endif - -MODULE_PARM(dc1_check, "i"); -MODULE_AUTHOR("Kousuke Takai "); -MODULE_DESCRIPTION("PC-9800 old printer port driver"); -MODULE_LICENSE("GPL"); - -module_init(lp_old98_init); -module_exit(lp_old98_exit); diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/mem.c 2004-06-20 13:00:24 -07:00 @@ -26,7 +26,6 @@ #include #include -#include #ifdef CONFIG_IA64 # include diff -Nru a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c --- a/drivers/char/mwave/3780i.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/mwave/3780i.c 2004-06-20 13:00:25 -07:00 @@ -467,10 +467,10 @@ } -int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr) { - unsigned short *pusBuffer = pvBuffer; + unsigned short __user *pusBuffer = pvBuffer; unsigned short val; @@ -508,10 +508,10 @@ } int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO, - void *pvBuffer, unsigned uCount, + void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr) { - unsigned short *pusBuffer = pvBuffer; + unsigned short __user *pusBuffer = pvBuffer; unsigned short val; @@ -549,10 +549,10 @@ } -int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr) { - unsigned short *pusBuffer = pvBuffer; + unsigned short __user *pusBuffer = pvBuffer; PRINTK_5(TRACE_3780I, @@ -590,10 +590,10 @@ } -int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr) { - unsigned short *pusBuffer = pvBuffer; + unsigned short __user *pusBuffer = pvBuffer; PRINTK_5(TRACE_3780I, "3780i::dsp3780I_ReadIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n", @@ -637,10 +637,10 @@ } -int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr) { - unsigned short *pusBuffer = pvBuffer; + unsigned short __user *pusBuffer = pvBuffer; PRINTK_5(TRACE_3780I, "3780i::dsp3780I_WriteIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n", diff -Nru a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h --- a/drivers/char/mwave/3780i.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/mwave/3780i.h 2004-06-20 13:00:25 -07:00 @@ -323,16 +323,16 @@ int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings); int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings); int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings); -int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr); int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO, - void *pvBuffer, unsigned uCount, + void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr); -int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr); -int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr); -int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void *pvBuffer, +int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer, unsigned uCount, unsigned long ulDSPAddr); unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO, unsigned long ulMsaAddr); diff -Nru a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c --- a/drivers/char/mwave/mwavedd.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/mwave/mwavedd.c 2004-06-20 13:00:23 -07:00 @@ -121,6 +121,7 @@ { unsigned int retval = 0; pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; + void __user *arg = (void __user *)ioarg; PRINTK_5(TRACE_MWAVE, "mwavedd::mwave_ioctl, entry inode %x file %x cmd %x arg %x\n", @@ -164,8 +165,7 @@ " retval %x from tp3780I_QueryAbilities\n", retval); if (retval == 0) { - if( copy_to_user((char *) ioarg, - (char *) &rAbilities, + if( copy_to_user(arg, &rAbilities, sizeof(MW_ABILITIES)) ) return -EFAULT; } @@ -179,13 +179,12 @@ case IOCTL_MW_READ_DATA: case IOCTL_MW_READCLEAR_DATA: { MW_READWRITE rReadData; - unsigned short *pusBuffer = 0; + unsigned short __user *pusBuffer = 0; - if( copy_from_user((char *) &rReadData, - (char *) ioarg, + if( copy_from_user(&rReadData, arg, sizeof(MW_READWRITE)) ) return -EFAULT; - pusBuffer = (unsigned short *) (rReadData.pBuf); + pusBuffer = (unsigned short __user *) (rReadData.pBuf); PRINTK_4(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," @@ -193,7 +192,7 @@ rReadData.ulDataLength, ioarg, pusBuffer); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, - (void *) pusBuffer, + pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress); } @@ -201,12 +200,12 @@ case IOCTL_MW_READ_INST: { MW_READWRITE rReadData; - unsigned short *pusBuffer = 0; + unsigned short __user *pusBuffer = 0; - if( copy_from_user((char *) &rReadData, (char *) ioarg, + if( copy_from_user(&rReadData, arg, sizeof(MW_READWRITE)) ) return -EFAULT; - pusBuffer = (unsigned short *) (rReadData.pBuf); + pusBuffer = (unsigned short __user *) (rReadData.pBuf); PRINTK_4(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_READ_INST," @@ -222,13 +221,12 @@ case IOCTL_MW_WRITE_DATA: { MW_READWRITE rWriteData; - unsigned short *pusBuffer = 0; + unsigned short __user *pusBuffer = 0; - if( copy_from_user((char *) &rWriteData, - (char *) ioarg, + if( copy_from_user(&rWriteData, arg, sizeof(MW_READWRITE)) ) return -EFAULT; - pusBuffer = (unsigned short *) (rWriteData.pBuf); + pusBuffer = (unsigned short __user *) (rWriteData.pBuf); PRINTK_4(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA," @@ -244,13 +242,12 @@ case IOCTL_MW_WRITE_INST: { MW_READWRITE rWriteData; - unsigned short *pusBuffer = 0; + unsigned short __user *pusBuffer = 0; - if( copy_from_user((char *) &rWriteData, - (char *) ioarg, + if( copy_from_user(&rWriteData, arg, sizeof(MW_READWRITE)) ) return -EFAULT; - pusBuffer = (unsigned short *) (rWriteData.pBuf); + pusBuffer = (unsigned short __user *)(rWriteData.pBuf); PRINTK_4(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST," @@ -388,7 +385,7 @@ } -static ssize_t mwave_read(struct file *file, char *buf, size_t count, +static ssize_t mwave_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { PRINTK_5(TRACE_MWAVE, @@ -399,7 +396,7 @@ } -static ssize_t mwave_write(struct file *file, const char *buf, +static ssize_t mwave_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { PRINTK_5(TRACE_MWAVE, diff -Nru a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c --- a/drivers/char/mwave/tp3780i.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/mwave/tp3780i.c 2004-06-20 13:00:23 -07:00 @@ -522,7 +522,7 @@ } int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode, - void *pvBuffer, unsigned int uCount, + void __user *pvBuffer, unsigned int uCount, unsigned long ulDSPAddr) { int retval = 0; @@ -558,7 +558,7 @@ int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode, - void *pvBuffer, unsigned int uCount, + void __user *pvBuffer, unsigned int uCount, unsigned long ulDSPAddr) { int retval = 0; diff -Nru a/drivers/char/mwave/tp3780i.h b/drivers/char/mwave/tp3780i.h --- a/drivers/char/mwave/tp3780i.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/mwave/tp3780i.h 2004-06-20 13:00:23 -07:00 @@ -93,10 +93,10 @@ int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities); int tp3780I_Cleanup(THINKPAD_BD_DATA * pBDData); int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode, - void *pvBuffer, unsigned int uCount, + void __user *pvBuffer, unsigned int uCount, unsigned long ulDSPAddr); int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode, - void *pvBuffer, unsigned int uCount, + void __user *pvBuffer, unsigned int uCount, unsigned long ulDSPAddr); diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/char/rtc.c 2004-06-20 13:00:26 -07:00 @@ -97,6 +97,11 @@ static int rtc_irq = PCI_IRQ_NONE; #endif +#ifdef CONFIG_HPET_RTC_IRQ +#undef RTC_IRQ +#define RTC_IRQ 0 +#endif + #ifdef RTC_IRQ static int rtc_has_irq = 1; #endif diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c --- a/drivers/char/synclinkmp.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/synclinkmp.c 2004-06-20 13:00:23 -07:00 @@ -567,17 +567,17 @@ /* ioctl handlers */ -static int get_stats(SLMP_INFO *info, struct mgsl_icount *user_icount); -static int get_params(SLMP_INFO *info, MGSL_PARAMS *params); -static int set_params(SLMP_INFO *info, MGSL_PARAMS *params); -static int get_txidle(SLMP_INFO *info, int*idle_mode); +static int get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount); +static int get_params(SLMP_INFO *info, MGSL_PARAMS __user *params); +static int set_params(SLMP_INFO *info, MGSL_PARAMS __user *params); +static int get_txidle(SLMP_INFO *info, int __user *idle_mode); static int set_txidle(SLMP_INFO *info, int idle_mode); static int tx_enable(SLMP_INFO *info, int enable); static int tx_abort(SLMP_INFO *info); static int rx_enable(SLMP_INFO *info, int enable); static int map_status(int signals); static int modem_input_wait(SLMP_INFO *info,int arg); -static int wait_mgsl_event(SLMP_INFO *info, int *mask_ptr); +static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); static int tiocmget(struct tty_struct *tty, struct file *file); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); @@ -692,7 +692,7 @@ * This allows remote debugging of dynamically loadable modules. */ static void* synclinkmp_get_text_ptr(void); -static void* synclinkmp_get_text_ptr() {return synclinkmp_get_text_ptr;} +static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;} static inline int sanity_check(SLMP_INFO *info, char *name, const char *routine) @@ -1333,8 +1333,9 @@ SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; int error; struct mgsl_icount cnow; /* kernel counter temps */ - struct serial_icounter_struct *p_cuser; /* user space */ + struct serial_icounter_struct __user *p_cuser; /* user space */ unsigned long flags; + void __user *argp = (void __user *)arg; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__, @@ -1351,23 +1352,23 @@ switch (cmd) { case MGSL_IOCGPARAMS: - return get_params(info,(MGSL_PARAMS *)arg); + return get_params(info, argp); case MGSL_IOCSPARAMS: - return set_params(info,(MGSL_PARAMS *)arg); + return set_params(info, argp); case MGSL_IOCGTXIDLE: - return get_txidle(info,(int*)arg); + return get_txidle(info, argp); case MGSL_IOCSTXIDLE: - return set_txidle(info,(int)arg); + return set_txidle(info, (int)arg); case MGSL_IOCTXENABLE: - return tx_enable(info,(int)arg); + return tx_enable(info, (int)arg); case MGSL_IOCRXENABLE: - return rx_enable(info,(int)arg); + return rx_enable(info, (int)arg); case MGSL_IOCTXABORT: return tx_abort(info); case MGSL_IOCGSTATS: - return get_stats(info,(struct mgsl_icount*)arg); + return get_stats(info, argp); case MGSL_IOCWAITEVENT: - return wait_mgsl_event(info,(int*)arg); + return wait_mgsl_event(info, argp); case MGSL_IOCLOOPTXDONE: return 0; // TODO: Not supported, need to document /* Wait for modem input (DCD,RI,DSR,CTS) change @@ -1386,7 +1387,7 @@ spin_lock_irqsave(&info->lock,flags); cnow = info->icount; spin_unlock_irqrestore(&info->lock,flags); - p_cuser = (struct serial_icounter_struct *) arg; + p_cuser = argp; PUT_USER(error,cnow.cts, &p_cuser->cts); if (error) return error; PUT_USER(error,cnow.dsr, &p_cuser->dsr); @@ -2762,7 +2763,7 @@ program_hw(info); } -static int get_stats(SLMP_INFO * info, struct mgsl_icount *user_icount) +static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) { int err; @@ -2781,7 +2782,7 @@ return 0; } -static int get_params(SLMP_INFO * info, MGSL_PARAMS *user_params) +static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params) { int err; if (debug_level >= DEBUG_LEVEL_INFO) @@ -2799,7 +2800,7 @@ return 0; } -static int set_params(SLMP_INFO * info, MGSL_PARAMS *new_params) +static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params) { unsigned long flags; MGSL_PARAMS tmp_params; @@ -2825,7 +2826,7 @@ return 0; } -static int get_txidle(SLMP_INFO * info, int*idle_mode) +static int get_txidle(SLMP_INFO * info, int __user *idle_mode) { int err; @@ -2938,7 +2939,7 @@ /* wait for specified event to occur */ -static int wait_mgsl_event(SLMP_INFO * info, int * mask_ptr) +static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) { unsigned long flags; int s; diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/tty_io.c 2004-06-20 13:00:24 -07:00 @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,8 @@ #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ extern int pty_limit; /* Config limit on Unix98 ptys */ +static DEFINE_IDR(allocated_ptys); +static DECLARE_MUTEX(allocated_ptys_lock); #endif extern void disable_early_printk(void); @@ -1065,6 +1068,7 @@ { struct tty_struct *tty, *o_tty; int pty_master, tty_closing, o_tty_closing, do_sleep; + int devpts_master; int idx; char buf[64]; @@ -1079,6 +1083,7 @@ idx = tty->index; pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER); + devpts_master = pty_master && (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM); o_tty = tty->link; #ifdef TTY_PARANOIA_CHECK @@ -1295,11 +1300,21 @@ o_tty->ldisc = ldiscs[N_TTY]; } - /* + /* * The release_mem function takes care of the details of clearing * the slots and preserving the termios structure. */ release_mem(tty, idx); + +#ifdef CONFIG_UNIX98_PTYS + /* Make this pty number available for reallocation */ + if (devpts_master) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, idx); + up(&allocated_ptys_lock); + } +#endif + } /* @@ -1322,8 +1337,12 @@ int index; dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; + retry_open: noctty = filp->f_flags & O_NOCTTY; + index = -1; + retval = 0; + if (device == MKDEV(TTYAUX_MAJOR,0)) { if (!current->signal->tty) return -ENXIO; @@ -1361,24 +1380,40 @@ #ifdef CONFIG_UNIX98_PTYS if (device == MKDEV(TTYAUX_MAJOR,2)) { + int idr_ret; + /* find a device that is not in use. */ - static int next_ptmx_dev = 0; - retval = -1; + down(&allocated_ptys_lock); + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + up(&allocated_ptys_lock); + return -ENOMEM; + } + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + up(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + return -ENOMEM; + return -EIO; + } + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return -EIO; + } + up(&allocated_ptys_lock); + driver = ptm_driver; - while (driver->refcount < pty_limit) { - index = next_ptmx_dev; - next_ptmx_dev = (next_ptmx_dev+1) % driver->num; - if (!init_dev(driver, index, &tty)) - goto ptmx_found; /* ok! */ + retval = init_dev(driver, index, &tty); + if (retval) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return retval; } - return -EIO; /* no free ptys */ - ptmx_found: + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - if (devpts_pty_new(tty->link)) { - /* BADNESS - need to destroy both ptm and pts! */ - return -ENOMEM; - } - noctty = 1; + if (devpts_pty_new(tty->link)) + retval = -ENOMEM; } else #endif { @@ -1400,10 +1435,12 @@ #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "opening %s...", tty->name); #endif - if (tty->driver->open) - retval = tty->driver->open(tty, filp); - else - retval = -ENODEV; + if (!retval) { + if (tty->driver->open) + retval = tty->driver->open(tty, filp); + else + retval = -ENODEV; + } filp->f_flags = saved_flags; if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) @@ -1413,6 +1450,14 @@ #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "error %d in opening %s...", retval, tty->name); +#endif + +#ifdef CONFIG_UNIX98_PTYS + if (index != -1) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + } #endif release_dev(filp); diff -Nru a/drivers/char/upd4990a.c b/drivers/char/upd4990a.c --- a/drivers/char/upd4990a.c 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,432 +0,0 @@ -/* - * NEC PC-9800 Real Time Clock interface for Linux - * - * Copyright (C) 1997-2001 Linux/98 project, - * Kyoto University Microcomputer Club. - * - * Based on: - * drivers/char/rtc.c by Paul Gortmaker - * - * Changes: - * 2001-02-09 Call check_region on rtc_init and do not request I/O 0033h. - * Call del_timer and release_region on rtc_exit. -- tak - * 2001-07-14 Rewrite and split to - * and . - * Introduce a lot of spin_lock/unlock (&rtc_lock). - */ - -#define RTC98_VERSION "1.2" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * We sponge a minor off of the misc major. No need slurping - * up another valuable major dev number for this. If you add - * an ioctl, make sure you don't conflict with SPARC's RTC - * ioctls. - */ - -static struct fasync_struct *rtc_async_queue; - -static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); - -static struct timer_list rtc_uie_timer; -static u8 old_refclk; - -static int rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - -static int rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -/* - * Bits in rtc_status. (5 bits of room for future expansion) - */ - -#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -#define RTC_TIMER_ON 0x02 /* not used */ -#define RTC_UIE_TIMER_ON 0x04 /* UIE emulation timer is active */ - -/* - * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is - * protected by the big kernel lock. However, ioctl can still disable the timer - * in rtc_status and then with del_timer after the interrupt has read - * rtc_status but before mod_timer is called, which would then reenable the - * timer (but you would need to have an awful timing before you'd trip on it) - */ -static unsigned char rtc_status; /* bitmapped status byte. */ -static unsigned long rtc_irq_data; /* our output to the world */ - -static const unsigned char days_in_mo[] = -{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -extern spinlock_t rtc_lock; /* defined in arch/i386/kernel/time.c */ - -static void rtc_uie_intr(unsigned long data) -{ - u8 refclk, tmp; - - /* Kernel timer does del_timer internally before calling - each timer entry, so this is unnecessary. - del_timer(&rtc_uie_timer); */ - spin_lock(&rtc_lock); - - /* Detect rising edge of 1Hz reference clock. */ - refclk = UPD4990A_READ_DATA(); - tmp = old_refclk & refclk; - old_refclk = ~refclk; - if (!(tmp & 1)) - rtc_irq_data += 0x100; - - spin_unlock(&rtc_lock); - - if (!(tmp & 1)) { - /* Now do the rest of the actions */ - wake_up_interruptible(&rtc_wait); - kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); - } - - rtc_uie_timer.expires = jiffies + 1; - add_timer(&rtc_uie_timer); -} - -/* - * Now all the various file operations that we export. - */ - -static ssize_t rtc_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long data; - ssize_t retval = 0; - - if (count < sizeof(unsigned long)) - return -EINVAL; - - add_wait_queue(&rtc_wait, &wait); - - set_current_state(TASK_INTERRUPTIBLE); - - do { - /* First make it right. Then make it fast. Putting this whole - * block within the parentheses of a while would be too - * confusing. And no, xchg() is not the answer. */ - spin_lock_irq(&rtc_lock); - data = rtc_irq_data; - rtc_irq_data = 0; - spin_unlock_irq(&rtc_lock); - - if (data != 0) - break; - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto out; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - goto out; - } - schedule(); - } while (1); - - retval = put_user(data, (unsigned long *)buf); - if (!retval) - retval = sizeof(unsigned long); - out: - set_current_state(TASK_RUNNING); - remove_wait_queue(&rtc_wait, &wait); - - return retval; -} - -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct rtc_time wtime; - struct upd4990a_raw_data raw; - - switch (cmd) { - case RTC_UIE_OFF: /* Mask ints from RTC updates. */ - spin_lock_irq(&rtc_lock); - if (rtc_status & RTC_UIE_TIMER_ON) { - rtc_status &= ~RTC_UIE_TIMER_ON; - del_timer(&rtc_uie_timer); - } - spin_unlock_irq(&rtc_lock); - return 0; - - case RTC_UIE_ON: /* Allow ints for RTC updates. */ - spin_lock_irq(&rtc_lock); - rtc_irq_data = 0; - if (!(rtc_status & RTC_UIE_TIMER_ON)) { - rtc_status |= RTC_UIE_TIMER_ON; - rtc_uie_timer.expires = jiffies + 1; - add_timer(&rtc_uie_timer); - } - /* Just in case... */ - upd4990a_serial_command(UPD4990A_REGISTER_HOLD); - old_refclk = ~UPD4990A_READ_DATA(); - spin_unlock_irq(&rtc_lock); - return 0; - - case RTC_RD_TIME: /* Read the time/date from RTC */ - spin_lock_irq(&rtc_lock); - upd4990a_get_time(&raw, 0); - spin_unlock_irq(&rtc_lock); - - wtime.tm_sec = BCD2BIN(raw.sec); - wtime.tm_min = BCD2BIN(raw.min); - wtime.tm_hour = BCD2BIN(raw.hour); - wtime.tm_mday = BCD2BIN(raw.mday); - wtime.tm_mon = raw.mon - 1; /* convert to 0-base */ - wtime.tm_wday = raw.wday; - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - if ((wtime.tm_year = BCD2BIN(raw.year)) < 95) - wtime.tm_year += 100; - - wtime.tm_isdst = 0; - break; - - case RTC_SET_TIME: /* Set the RTC */ - { - int leap_yr; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&wtime, (struct rtc_time *) arg, - sizeof (struct rtc_time))) - return -EFAULT; - - /* Valid year is 1995 - 2094, inclusive. */ - if (wtime.tm_year < 95 || wtime.tm_year > 194) - return -EINVAL; - - if (wtime.tm_mon > 11 || wtime.tm_mday == 0) - return -EINVAL; - - /* For acceptable year domain (1995 - 2094), - this IS sufficient. */ - leap_yr = !(wtime.tm_year % 4); - - if (wtime.tm_mday > (days_in_mo[wtime.tm_mon] - + (wtime.tm_mon == 2 && leap_yr))) - return -EINVAL; - - if (wtime.tm_hour >= 24 - || wtime.tm_min >= 60 || wtime.tm_sec >= 60) - return -EINVAL; - - if (wtime.tm_wday > 6) - return -EINVAL; - - raw.sec = BIN2BCD(wtime.tm_sec); - raw.min = BIN2BCD(wtime.tm_min); - raw.hour = BIN2BCD(wtime.tm_hour); - raw.mday = BIN2BCD(wtime.tm_mday); - raw.mon = wtime.tm_mon + 1; - raw.wday = wtime.tm_wday; - raw.year = BIN2BCD(wtime.tm_year % 100); - - spin_lock_irq(&rtc_lock); - upd4990a_set_time(&raw, 0); - spin_unlock_irq(&rtc_lock); - - return 0; - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -} - -/* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. - */ - -static int rtc_open(struct inode *inode, struct file *file) -{ - spin_lock_irq(&rtc_lock); - - if(rtc_status & RTC_IS_OPEN) - goto out_busy; - - rtc_status |= RTC_IS_OPEN; - - rtc_irq_data = 0; - spin_unlock_irq(&rtc_lock); - return 0; - - out_busy: - spin_unlock_irq(&rtc_lock); - return -EBUSY; -} - -static int rtc_fasync(int fd, struct file *filp, int on) -{ - return fasync_helper(fd, filp, on, &rtc_async_queue); -} - -static int rtc_release(struct inode *inode, struct file *file) -{ - del_timer(&rtc_uie_timer); - - if (file->f_flags & FASYNC) - rtc_fasync(-1, file, 0); - - rtc_irq_data = 0; - - /* No need for locking -- nobody else can do anything until this rmw is - * committed, and no timer is running. */ - rtc_status &= ~(RTC_IS_OPEN | RTC_UIE_TIMER_ON); - return 0; -} - -static unsigned int rtc_poll(struct file *file, poll_table *wait) -{ - unsigned long l; - - poll_wait(file, &rtc_wait, wait); - - spin_lock_irq(&rtc_lock); - l = rtc_irq_data; - spin_unlock_irq(&rtc_lock); - - if (l != 0) - return POLLIN | POLLRDNORM; - return 0; -} - -/* - * The various file operations we support. - */ - -static struct file_operations rtc_fops = { - .owner = THIS_MODULE, - .read = rtc_read, - .poll = rtc_poll, - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, - .fasync = rtc_fasync, -}; - -static struct miscdevice rtc_dev= -{ - .minor = RTC_MINOR, - .name = "rtc", - .fops = &rtc_fops, -}; - -static int __init rtc_init(void) -{ - int err = 0; - - if (!request_region(UPD4990A_IO, 1, "rtc")) { - printk(KERN_ERR "upd4990a: could not acquire I/O port %#x\n", - UPD4990A_IO); - return -EBUSY; - } - - err = misc_register(&rtc_dev); - if (err) { - printk(KERN_ERR "upd4990a: can't misc_register() on minor=%d\n", - RTC_MINOR); - release_region(UPD4990A_IO, 1); - return err; - } - -#if 0 - printk(KERN_INFO "\xB6\xDA\xDD\xC0\xDE \xC4\xDE\xB9\xB2 Driver\n"); /* Calender Clock Driver */ -#else - printk(KERN_INFO - "Real Time Clock driver for NEC PC-9800 v" RTC98_VERSION "\n"); -#endif - create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL); - - init_timer(&rtc_uie_timer); - rtc_uie_timer.function = rtc_uie_intr; - - return 0; -} - -module_init (rtc_init); - -static void __exit rtc_exit(void) -{ - del_timer(&rtc_uie_timer); - release_region(UPD4990A_IO, 1); - remove_proc_entry("driver/rtc", NULL); - misc_deregister(&rtc_dev); -} - -module_exit (rtc_exit); - -/* - * Info exported via "/proc/driver/rtc". - */ - -static inline int rtc_get_status(char *buf) -{ - char *p; - unsigned int year; - struct upd4990a_raw_data data; - - p = buf; - - upd4990a_get_time(&data, 0); - - /* - * There is no way to tell if the luser has the RTC set for local - * time or for Universal Standard Time (GMT). Probably local though. - */ - if ((year = BCD2BIN(data.year) + 1900) < 1995) - year += 100; - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", - BCD2BIN(data.hour), BCD2BIN(data.min), - BCD2BIN(data.sec), - year, data.mon, BCD2BIN(data.mday)); - - return p - buf; -} - -static int rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = rtc_get_status(page); - - if (len <= off + count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} diff -Nru a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c --- a/drivers/char/watchdog/acquirewdt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/acquirewdt.c 2004-06-20 13:00:25 -07:00 @@ -111,7 +111,7 @@ * /dev/watchdog handling. */ -static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -146,6 +146,8 @@ unsigned long arg) { int options, retval = -EINVAL; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -156,22 +158,22 @@ switch(cmd) { case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: acq_keepalive(); return 0; case WDIOC_GETTIMEOUT: - return put_user(WATCHDOG_HEARTBEAT, (int *)arg); + return put_user(WATCHDOG_HEARTBEAT, p); case WDIOC_SETOPTIONS: { - if (get_user(options, (int *)arg)) + if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) diff -Nru a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c --- a/drivers/char/watchdog/advantechwdt.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/watchdog/advantechwdt.c 2004-06-20 13:00:24 -07:00 @@ -100,7 +100,7 @@ } static ssize_t -advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -130,6 +130,8 @@ unsigned long arg) { int new_timeout; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, @@ -138,20 +140,20 @@ switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: advwdt_ping(); break; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) + if (get_user(new_timeout, p)) return -EFAULT; if ((new_timeout < 1) || (new_timeout > 63)) return -EINVAL; @@ -160,13 +162,13 @@ /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) + if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { diff -Nru a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c --- a/drivers/char/watchdog/alim1535_wdt.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/alim1535_wdt.c 2004-06-20 13:00:23 -07:00 @@ -138,7 +138,7 @@ * the next close to turn off the watchdog. */ -static ssize_t ali_write(struct file *file, const char *data, +static ssize_t ali_write(struct file *file, const char __user *data, size_t len, loff_t * ppos) { /* Can't seek (pwrite) on this device */ @@ -184,6 +184,8 @@ static int ali_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | @@ -194,12 +196,12 @@ switch (cmd) { case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *) arg, &ident, + return copy_to_user(argp, &ident, sizeof (ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *) arg); + return put_user(0, p); case WDIOC_KEEPALIVE: ali_keepalive(); @@ -209,7 +211,7 @@ { int new_options, retval = -EINVAL; - if (get_user (new_options, (int *) arg)) + if (get_user (new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { @@ -229,7 +231,7 @@ { int new_timeout; - if (get_user(new_timeout, (int *) arg)) + if (get_user(new_timeout, p)) return -EFAULT; if (ali_settimer(new_timeout)) @@ -240,7 +242,7 @@ } case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); default: return -ENOIOCTLCMD; diff -Nru a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c --- a/drivers/char/watchdog/alim7101_wdt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/alim7101_wdt.c 2004-06-20 13:00:25 -07:00 @@ -148,7 +148,7 @@ * /dev/watchdog handling */ -static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) +static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { /* We can't seek */ if(ppos != &file->f_pos) @@ -203,6 +203,8 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, @@ -213,10 +215,10 @@ switch(cmd) { case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; @@ -224,7 +226,7 @@ { int new_options, retval = -EINVAL; - if(get_user(new_options, (int *)arg)) + if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { @@ -243,7 +245,7 @@ { int new_timeout; - if(get_user(new_timeout, (int *)arg)) + if(get_user(new_timeout, p)) return -EFAULT; if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ @@ -254,7 +256,7 @@ /* Fall through */ } case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); default: return -ENOIOCTLCMD; } diff -Nru a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c --- a/drivers/char/watchdog/cpu5wdt.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/cpu5wdt.c 2004-06-20 13:00:23 -07:00 @@ -145,6 +145,7 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; unsigned int value; static struct watchdog_info ident = { @@ -159,15 +160,15 @@ case WDIOC_GETSTATUS: value = inb(port + CPU5WDT_STATUS_REG); value = (value >> 2) & 1; - if ( copy_to_user((int *)arg, (int *)&value, sizeof(int)) ) + if ( copy_to_user(argp, &value, sizeof(int)) ) return -EFAULT; break; case WDIOC_GETSUPPORT: - if ( copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ) + if ( copy_to_user(argp, &ident, sizeof(ident)) ) return -EFAULT; break; case WDIOC_SETOPTIONS: - if ( copy_from_user(&value, (int *)arg, sizeof(int)) ) + if ( copy_from_user(&value, argp, sizeof(int)) ) return -EFAULT; switch(value) { case WDIOS_ENABLECARD: @@ -185,7 +186,7 @@ return 0; } -static ssize_t cpu5wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { if ( !count ) return -EIO; diff -Nru a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c --- a/drivers/char/watchdog/eurotechwdt.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/eurotechwdt.c 2004-06-20 13:00:23 -07:00 @@ -196,8 +196,8 @@ * write of data will do, as we we don't define content meaning. */ -static ssize_t eurwdt_write(struct file *file, const char *buf, size_t count, -loff_t *ppos) +static ssize_t eurwdt_write(struct file *file, const char __user *buf, +size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -237,6 +237,8 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, @@ -251,19 +253,18 @@ return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident)) ? -EFAULT : 0; + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *) arg); + return put_user(0, p); case WDIOC_KEEPALIVE: eurwdt_ping(); return 0; case WDIOC_SETTIMEOUT: - if (copy_from_user(&time, (int *) arg, sizeof(int))) + if (copy_from_user(&time, p, sizeof(int))) return -EFAULT; /* Sanity check */ @@ -275,10 +276,10 @@ /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(eurwdt_timeout, (int *)arg); + return put_user(eurwdt_timeout, p); case WDIOC_SETOPTIONS: - if (get_user(options, (int *)arg)) + if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { eurwdt_disable_timer(); diff -Nru a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c --- a/drivers/char/watchdog/i8xx_tco.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/i8xx_tco.c 2004-06-20 13:00:23 -07:00 @@ -212,7 +212,7 @@ return 0; } -static ssize_t i8xx_tco_write (struct file *file, const char *data, +static ssize_t i8xx_tco_write (struct file *file, const char __user *data, size_t len, loff_t * ppos) { /* Can't seek (pwrite) on this device */ @@ -249,6 +249,8 @@ { int new_options, retval = -EINVAL; int new_heartbeat; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | @@ -259,12 +261,12 @@ switch (cmd) { case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *) arg, &ident, + return copy_to_user(argp, &ident, sizeof (ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user (0, (int *) arg); + return put_user (0, p); case WDIOC_KEEPALIVE: tco_timer_keepalive (); @@ -272,7 +274,7 @@ case WDIOC_SETOPTIONS: { - if (get_user (new_options, (int *) arg)) + if (get_user (new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { @@ -291,7 +293,7 @@ case WDIOC_SETTIMEOUT: { - if (get_user(new_heartbeat, (int *) arg)) + if (get_user(new_heartbeat, p)) return -EFAULT; if (tco_timer_set_heartbeat(new_heartbeat)) @@ -302,7 +304,7 @@ } case WDIOC_GETTIMEOUT: - return put_user(heartbeat, (int *)arg); + return put_user(heartbeat, p); default: return -ENOIOCTLCMD; diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c --- a/drivers/char/watchdog/ib700wdt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/ib700wdt.c 2004-06-20 13:00:25 -07:00 @@ -139,7 +139,7 @@ } static ssize_t -ibwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -170,6 +170,8 @@ unsigned long arg) { int i, new_margin; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, @@ -179,19 +181,19 @@ switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: - return put_user(0, (int *) arg); + return put_user(0, p); case WDIOC_KEEPALIVE: ibwdt_ping(); break; case WDIOC_SETTIMEOUT: - if (get_user(new_margin, (int *)arg)) + if (get_user(new_margin, p)) return -EFAULT; if ((new_margin < 0) || (new_margin > 30)) return -EINVAL; @@ -203,7 +205,7 @@ /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(wd_times[wd_margin], (int *)arg); + return put_user(wd_times[wd_margin], p); break; default: diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c --- a/drivers/char/watchdog/machzwd.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/machzwd.c 2004-06-20 13:00:23 -07:00 @@ -302,7 +302,7 @@ } } -static ssize_t zf_write(struct file *file, const char *buf, size_t count, +static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ @@ -352,15 +352,16 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; switch(cmd){ case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, - &zf_info, sizeof(zf_info))) + if (copy_to_user(argp, &zf_info, sizeof(zf_info))) return -EFAULT; break; case WDIOC_GETSTATUS: - return put_user(0, (int *) arg); + return put_user(0, p); case WDIOC_KEEPALIVE: zf_ping(0); diff -Nru a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c --- a/drivers/char/watchdog/mixcomwd.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/mixcomwd.c 2004-06-20 13:00:23 -07:00 @@ -134,7 +134,7 @@ } -static ssize_t mixcomwd_write(struct file *file, const char *data, size_t len, loff_t *ppos) +static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { if (ppos != &file->f_pos) { return -ESPIPE; @@ -164,6 +164,8 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; int status; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -178,13 +180,12 @@ if (!nowayout) { status|=mixcomwd_timer_alive; } - if (copy_to_user((int *)arg, &status, sizeof(int))) { + if (copy_to_user(p, &status, sizeof(int))) { return -EFAULT; } break; case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident))) { + if (copy_to_user(argp, &ident, sizeof(ident))) { return -EFAULT; } break; diff -Nru a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c --- a/drivers/char/watchdog/pcwd_pci.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/pcwd_pci.c 2004-06-20 13:00:23 -07:00 @@ -258,7 +258,7 @@ * /dev/watchdog handling */ -static ssize_t pcipcwd_write(struct file *file, const char *data, +static ssize_t pcipcwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { /* Can't seek (pwrite) on this device */ @@ -293,6 +293,8 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_OVERHEAT | WDIOF_CARDRESET | @@ -305,7 +307,7 @@ switch (cmd) { case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *) arg, &ident, + return copy_to_user(argp, &ident, sizeof (ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: @@ -314,11 +316,11 @@ pcipcwd_get_status(&status); - return put_user(status, (int *) arg); + return put_user(status, p); } case WDIOC_GETBOOTSTATUS: - return put_user(pcipcwd_private.boot_status, (int *) arg); + return put_user(pcipcwd_private.boot_status, p); case WDIOC_GETTEMP: { @@ -327,7 +329,7 @@ if (pcipcwd_get_temperature(&temperature)) return -EFAULT; - return put_user(temperature, (int *) arg); + return put_user(temperature, p); } case WDIOC_KEEPALIVE: @@ -338,7 +340,7 @@ { int new_options, retval = -EINVAL; - if (get_user (new_options, (int *) arg)) + if (get_user (new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { @@ -363,7 +365,7 @@ { int new_heartbeat; - if (get_user(new_heartbeat, (int *) arg)) + if (get_user(new_heartbeat, p)) return -EFAULT; if (pcipcwd_set_heartbeat(new_heartbeat)) @@ -374,7 +376,7 @@ } case WDIOC_GETTIMEOUT: - return put_user(heartbeat, (int *)arg); + return put_user(heartbeat, p); default: return -ENOIOCTLCMD; @@ -413,7 +415,7 @@ * /dev/temperature handling */ -static ssize_t pcipcwd_temp_read(struct file *file, char *data, +static ssize_t pcipcwd_temp_read(struct file *file, char __user *data, size_t len, loff_t *ppos) { int temperature; diff -Nru a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c --- a/drivers/char/watchdog/pcwd_usb.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/pcwd_usb.c 2004-06-20 13:00:23 -07:00 @@ -326,7 +326,7 @@ * /dev/watchdog handling */ -static ssize_t usb_pcwd_write(struct file *file, const char *data, +static ssize_t usb_pcwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { /* Can't seek (pwrite) on this device */ @@ -361,6 +361,8 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | @@ -371,12 +373,12 @@ switch (cmd) { case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *) arg, &ident, + return copy_to_user(argp, &ident, sizeof (ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *) arg); + return put_user(0, p); case WDIOC_GETTEMP: { @@ -385,7 +387,7 @@ if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) return -EFAULT; - return put_user(temperature, (int *) arg); + return put_user(temperature, p); } case WDIOC_KEEPALIVE: @@ -396,7 +398,7 @@ { int new_options, retval = -EINVAL; - if (get_user (new_options, (int *) arg)) + if (get_user (new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { @@ -416,7 +418,7 @@ { int new_heartbeat; - if (get_user(new_heartbeat, (int *) arg)) + if (get_user(new_heartbeat, p)) return -EFAULT; if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) @@ -427,7 +429,7 @@ } case WDIOC_GETTIMEOUT: - return put_user(heartbeat, (int *)arg); + return put_user(heartbeat, p); default: return -ENOIOCTLCMD; @@ -466,7 +468,7 @@ * /dev/temperature handling */ -static ssize_t usb_pcwd_temperature_read(struct file *file, char *data, +static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data, size_t len, loff_t *ppos) { int temperature; @@ -478,7 +480,7 @@ if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) return -EFAULT; - if (copy_to_user (data, &temperature, 1)) + if (copy_to_user(data, &temperature, 1)) return -EFAULT; return 1; diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c --- a/drivers/char/watchdog/sbc60xxwdt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/sbc60xxwdt.c 2004-06-20 13:00:25 -07:00 @@ -166,7 +166,7 @@ * /dev/watchdog handling */ -static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) +static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { /* We can't seek */ if(ppos != &file->f_pos) @@ -230,6 +230,8 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident= { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, @@ -242,10 +244,10 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; @@ -253,7 +255,7 @@ { int new_options, retval = -EINVAL; - if(get_user(new_options, (int *)arg)) + if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { @@ -272,7 +274,7 @@ { int new_timeout; - if(get_user(new_timeout, (int *)arg)) + if(get_user(new_timeout, p)) return -EFAULT; if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ @@ -283,7 +285,7 @@ /* Fall through */ } case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); } } diff -Nru a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c --- a/drivers/char/watchdog/sc1200wdt.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/char/watchdog/sc1200wdt.c 2004-06-20 13:00:23 -07:00 @@ -174,6 +174,8 @@ static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int new_timeout; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 0, @@ -185,22 +187,22 @@ return -ENOIOCTLCMD; /* Keep Pavel Machek amused ;) */ case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident)) + if (copy_to_user(argp, &ident, sizeof ident)) return -EFAULT; return 0; case WDIOC_GETSTATUS: - return put_user(sc1200wdt_status(), (int *)arg); + return put_user(sc1200wdt_status(), p); case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: sc1200wdt_write_data(WDTO, timeout); return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) + if (get_user(new_timeout, p)) return -EFAULT; /* the API states this is given in secs */ @@ -213,13 +215,13 @@ /* fall through and return the new timeout */ case WDIOC_GETTIMEOUT: - return put_user(timeout * 60, (int *)arg); + return put_user(timeout * 60, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) + if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { @@ -254,7 +256,7 @@ } -static ssize_t sc1200wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) +static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { if (ppos != &file->f_pos) return -ESPIPE; diff -Nru a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c --- a/drivers/char/watchdog/sc520_wdt.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/watchdog/sc520_wdt.c 2004-06-20 13:00:24 -07:00 @@ -225,7 +225,7 @@ * /dev/watchdog handling */ -static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) +static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { /* We can't seek */ if(ppos != &file->f_pos) @@ -285,6 +285,8 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, @@ -296,10 +298,10 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; @@ -307,7 +309,7 @@ { int new_options, retval = -EINVAL; - if(get_user(new_options, (int *)arg)) + if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { @@ -326,7 +328,7 @@ { int new_timeout; - if(get_user(new_timeout, (int *)arg)) + if(get_user(new_timeout, p)) return -EFAULT; if(wdt_set_heartbeat(new_timeout)) @@ -336,7 +338,7 @@ /* Fall through */ } case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); } } diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c --- a/drivers/char/watchdog/scx200_wdt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/scx200_wdt.c 2004-06-20 13:00:25 -07:00 @@ -132,7 +132,7 @@ .notifier_call = scx200_wdt_notify_sys, }; -static ssize_t scx200_wdt_write(struct file *file, const char *data, +static ssize_t scx200_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { if (ppos != &file->f_pos) @@ -163,6 +163,8 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .identity = "NatSemi SCx200 Watchdog", .firmware_version = 1, @@ -174,20 +176,19 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - if(copy_to_user((struct watchdog_info *)arg, &ident, - sizeof(ident))) + if(copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - if (put_user(0, (int *)arg)) + if (put_user(0, p)) return -EFAULT; return 0; case WDIOC_KEEPALIVE: scx200_wdt_ping(); return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_margin, (int *)arg)) + if (get_user(new_margin, p)) return -EFAULT; if (new_margin < 1) return -EINVAL; @@ -195,7 +196,7 @@ scx200_wdt_update_margin(); scx200_wdt_ping(); case WDIOC_GETTIMEOUT: - if (put_user(margin, (int *)arg)) + if (put_user(margin, p)) return -EFAULT; return 0; } diff -Nru a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c --- a/drivers/char/watchdog/softdog.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/watchdog/softdog.c 2004-06-20 13:00:24 -07:00 @@ -161,7 +161,7 @@ return 0; } -static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -194,6 +194,8 @@ static int softdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; int new_margin; static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | @@ -206,23 +208,23 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0,(int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: softdog_keepalive(); return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_margin, (int *)arg)) + if (get_user(new_margin, p)) return -EFAULT; if (softdog_set_heartbeat(new_margin)) return -EINVAL; softdog_keepalive(); /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(soft_margin, (int *)arg); + return put_user(soft_margin, p); } } diff -Nru a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c --- a/drivers/char/watchdog/w83627hf_wdt.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/watchdog/w83627hf_wdt.c 2004-06-20 13:00:24 -07:00 @@ -142,7 +142,7 @@ } static ssize_t -wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -171,6 +171,8 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; int new_timeout; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, @@ -180,20 +182,20 @@ switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdt_ping(); break; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) + if (get_user(new_timeout, p)) return -EFAULT; if (wdt_set_heartbeat(new_timeout)) return -EINVAL; @@ -201,13 +203,13 @@ /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) + if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { diff -Nru a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c --- a/drivers/char/watchdog/w83877f_wdt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/w83877f_wdt.c 2004-06-20 13:00:25 -07:00 @@ -188,7 +188,7 @@ * /dev/watchdog handling */ -static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos) +static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { /* We can't seek */ if(ppos != &file->f_pos) @@ -249,6 +249,8 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident= { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, @@ -261,10 +263,10 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; @@ -272,7 +274,7 @@ { int new_options, retval = -EINVAL; - if(get_user(new_options, (int *)arg)) + if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { @@ -291,7 +293,7 @@ { int new_timeout; - if(get_user(new_timeout, (int *)arg)) + if(get_user(new_timeout, p)) return -EFAULT; if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ @@ -302,7 +304,7 @@ /* Fall through */ } case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); } } diff -Nru a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c --- a/drivers/char/watchdog/wafer5823wdt.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/char/watchdog/wafer5823wdt.c 2004-06-20 13:00:26 -07:00 @@ -95,7 +95,7 @@ inb_p(wdt_stop); } -static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, loff_t * ppos) +static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -128,6 +128,8 @@ unsigned long arg) { int new_timeout; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, @@ -136,21 +138,20 @@ switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user - ((struct watchdog_info *) arg, &ident, sizeof (ident))) + if (copy_to_user(argp, &ident, sizeof (ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wafwdt_ping(); break; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) + if (get_user(new_timeout, p)) return -EFAULT; if ((new_timeout < 1) || (new_timeout > 255)) return -EINVAL; @@ -159,13 +160,13 @@ wafwdt_start(); /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); + return put_user(timeout, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) + if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { diff -Nru a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c --- a/drivers/char/watchdog/wdt.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/char/watchdog/wdt.c 2004-06-20 13:00:24 -07:00 @@ -286,7 +286,7 @@ * write of data will do, as we we don't define content meaning. */ -static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -327,6 +327,8 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; + int __user *p = argp; int new_heartbeat; int status; @@ -351,18 +353,18 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: wdt_get_status(&status); - return put_user(status,(int *)arg); + return put_user(status, p); case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdt_ping(); return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_heartbeat, (int *)arg)) + if (get_user(new_heartbeat, p)) return -EFAULT; if (wdt_set_heartbeat(new_heartbeat)) @@ -371,7 +373,7 @@ wdt_ping(); /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(heartbeat, (int *)arg); + return put_user(heartbeat, p); } } @@ -435,7 +437,7 @@ * farenheit. It was designed by an imperial measurement luddite. */ -static ssize_t wdt_temp_read(struct file *file, char *buf, size_t count, loff_t *ptr) +static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) { int temperature; diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c --- a/drivers/char/watchdog/wdt_pci.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/char/watchdog/wdt_pci.c 2004-06-20 13:00:25 -07:00 @@ -331,7 +331,7 @@ * write of data will do, as we we don't define content meaning. */ -static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t wdtpci_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) @@ -374,6 +374,8 @@ { int new_heartbeat; int status; + void __user *argp = (void __user *)arg; + int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT| @@ -396,18 +398,18 @@ default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: wdtpci_get_status(&status); - return put_user(status,(int *)arg); + return put_user(status, p); case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, p); case WDIOC_KEEPALIVE: wdtpci_ping(); return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_heartbeat, (int *)arg)) + if (get_user(new_heartbeat, p)) return -EFAULT; if (wdtpci_set_heartbeat(new_heartbeat)) @@ -416,7 +418,7 @@ wdtpci_ping(); /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(heartbeat, (int *)arg); + return put_user(heartbeat, p); } } @@ -484,7 +486,7 @@ * fahrenheit. It was designed by an imperial measurement luddite. */ -static ssize_t wdtpci_temp_read(struct file *file, char *buf, size_t count, loff_t *ptr) +static ssize_t wdtpci_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) { int temperature; diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/i2c/i2c-core.c 2004-06-20 13:00:23 -07:00 @@ -126,7 +126,13 @@ goto out_unlock; } - id = idr_get_new(&i2c_adapter_idr, NULL); + res = idr_get_new(&i2c_adapter_idr, NULL, &id); + if (res < 0) { + if (res == -EAGAIN) + res = -ENOMEM; + goto out_unlock; + } + adap->nr = id & MAX_ID_MASK; init_MUTEX(&adap->bus_lock); init_MUTEX(&adap->clist_lock); @@ -162,7 +168,7 @@ dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr); - out_unlock: +out_unlock: up(&core_lists); return res; } diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig 2004-06-20 13:00:24 -07:00 +++ b/drivers/ide/Kconfig 2004-06-20 13:00:24 -07:00 @@ -97,25 +97,7 @@ config BLK_DEV_HD_IDE bool "Use old disk-only driver on primary interface" - depends on ((X86 && X86_PC9800!=y) || SH_MPC1211) - ---help--- - There are two drivers for MFM/RLL/IDE disks. Most people use just - the new enhanced driver by itself. This option however installs the - old hard disk driver to control the primary IDE/disk interface in - the system, leaving the new enhanced IDE driver to take care of only - the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from - having an IDE/ATAPI CD-ROM or tape drive connected to the primary - IDE interface. Choosing this option may be useful for older systems - which have MFM/RLL/ESDI controller+drives at the primary port - address (0x1f0), along with IDE drives at the secondary/3rd/4th port - addresses. - - Normally, just say N here; you will then use the new driver for all - 4 interfaces. - -config BLK_DEV_HD_IDE98 - bool "Use old disk-only driver on primary interface" - depends on X86 && X86_PC9800 + depends on (X86 || SH_MPC1211) ---help--- There are two drivers for MFM/RLL/IDE disks. Most people use just the new enhanced driver by itself. This option however installs the diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile 2004-06-20 13:00:24 -07:00 +++ b/drivers/ide/Makefile 2004-06-20 13:00:24 -07:00 @@ -29,7 +29,6 @@ ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o # built-in only drivers from legacy/ -ide-core-$(CONFIG_BLK_DEV_IDE_PC9800) += legacy/pc9800.o ide-core-$(CONFIG_BLK_DEV_BUDDHA) += legacy/buddha.o ide-core-$(CONFIG_BLK_DEV_FALCON_IDE) += legacy/falconide.o ide-core-$(CONFIG_BLK_DEV_GAYLE) += legacy/gayle.o diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/ide/ide-cd.c 2004-06-20 13:00:24 -07:00 @@ -2816,7 +2816,6 @@ return 0; } - /* * Close down the device. Invalidate all cached blocks. */ @@ -2890,12 +2889,6 @@ devinfo->mask |= CDC_CLOSE_TRAY; if (!CDROM_CONFIG_FLAGS(drive)->mo_drive) devinfo->mask |= CDC_MO_DRIVE; - if (!CDROM_CONFIG_FLAGS(drive)->mrw) - devinfo->mask |= CDC_MRW; - if (!CDROM_CONFIG_FLAGS(drive)->mrw_w) - devinfo->mask |= CDC_MRW_W; - if (!CDROM_CONFIG_FLAGS(drive)->ram) - devinfo->mask |= CDC_RAM; devinfo->disk = drive->disk; return register_cdrom(devinfo); @@ -2932,7 +2925,7 @@ struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; struct atapi_capabilities_page cap; - int nslots = 1, mrw_write = 0, ram_write = 0; + int nslots = 1; if (drive->media == ide_optical) { CDROM_CONFIG_FLAGS(drive)->mo_drive = 1; @@ -2961,17 +2954,6 @@ if (ide_cdrom_get_capabilities(drive, &cap)) return 0; - if (!cdrom_is_mrw(cdi, &mrw_write)) { - CDROM_CONFIG_FLAGS(drive)->mrw = 1; - if (mrw_write) { - CDROM_CONFIG_FLAGS(drive)->mrw_w = 1; - CDROM_CONFIG_FLAGS(drive)->ram = 1; - } - } - if (!cdrom_is_random_writable(cdi, &ram_write)) - if (ram_write) - CDROM_CONFIG_FLAGS(drive)->ram = 1; - if (cap.lock == 0) CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; if (cap.eject) @@ -3050,9 +3032,6 @@ printk(" CD%s%s", (CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", (CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : ""); - - if (CDROM_CONFIG_FLAGS(drive)->mrw || CDROM_CONFIG_FLAGS(drive)->mrw_w) - printk(" CD-MR%s", CDROM_CONFIG_FLAGS(drive)->mrw_w ? "W" : ""); if (CDROM_CONFIG_FLAGS(drive)->is_changer) printk(" changer w/%d slots", nslots); diff -Nru a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h --- a/drivers/ide/ide-cd.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/ide/ide-cd.h 2004-06-20 13:00:26 -07:00 @@ -79,8 +79,6 @@ __u8 dvd : 1; /* Drive is a DVD-ROM */ __u8 dvd_r : 1; /* Drive can write DVD-R */ __u8 dvd_ram : 1; /* Drive can write DVD-RAM */ - __u8 mrw : 1; /* drive can read mrw */ - __u8 mrw_w : 1; /* drive can write mrw */ __u8 ram : 1; /* generic WRITE (dvd-ram/mrw) */ __u8 test_write : 1; /* Drive can fake writes */ __u8 supp_disc_present : 1; /* Changer can report exact contents diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c --- a/drivers/ide/ide-proc.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/ide/ide-proc.c 2004-06-20 13:00:24 -07:00 @@ -321,7 +321,6 @@ case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; case ide_pmac: name = "mac-io"; break; - case ide_pc9800: name = "pc9800"; break; default: name = "(unknown)"; break; } len = sprintf(page, "%s\n", name); diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/ide/ide-tape.c 2004-06-20 13:00:24 -07:00 @@ -2674,7 +2674,7 @@ return __idetape_kmalloc_stage(tape, 0, 0); } -static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char *buf, int n) +static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n) { struct idetape_bh *bh = tape->bh; int count; @@ -2701,7 +2701,7 @@ tape->bh = bh; } -static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape_stage_t *stage, int n) +static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n) { struct idetape_bh *bh = tape->bh; int count; @@ -3610,6 +3610,7 @@ { idetape_tape_t *tape = drive->driver_data; idetape_config_t config; + void __user *argp = (void __user *)arg; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) @@ -3617,7 +3618,7 @@ #endif /* IDETAPE_DEBUG_LOG */ switch (cmd) { case 0x0340: - if (copy_from_user ((char *) &config, (char *) arg, sizeof (idetape_config_t))) + if (copy_from_user(&config, argp, sizeof (idetape_config_t))) return -EFAULT; tape->best_dsc_rw_frequency = config.dsc_rw_frequency; tape->max_stages = config.nr_stages; @@ -3625,7 +3626,7 @@ case 0x0350: config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency; config.nr_stages = tape->max_stages; - if (copy_to_user((char *) arg, (char *) &config, sizeof (idetape_config_t))) + if (copy_to_user(argp, &config, sizeof (idetape_config_t))) return -EFAULT; break; default: @@ -3747,7 +3748,7 @@ * will no longer hit performance. * This is not applicable to Onstream. */ -static ssize_t idetape_chrdev_read (struct file *file, char *buf, +static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, size_t count, loff_t *ppos) { ide_drive_t *drive = file->private_data; @@ -3810,7 +3811,7 @@ return actually_read; } -static ssize_t idetape_chrdev_write (struct file *file, const char *buf, +static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ide_drive_t *drive = file->private_data; @@ -4127,6 +4128,7 @@ struct mtget mtget; struct mtpos mtpos; int block_offset = 0, position = tape->first_frame_position; + void __user *argp = (void __user *)arg; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) @@ -4146,7 +4148,7 @@ } switch (cmd) { case MTIOCTOP: - if (copy_from_user((char *) &mtop, (char *) arg, sizeof (struct mtop))) + if (copy_from_user(&mtop, argp, sizeof (struct mtop))) return -EFAULT; return (idetape_mtioctop(drive,mtop.mt_op,mtop.mt_count)); case MTIOCGET: @@ -4157,12 +4159,12 @@ if (tape->drv_write_prot) { mtget.mt_gstat |= GMT_WR_PROT(0xffffffff); } - if (copy_to_user((char *) arg,(char *) &mtget, sizeof(struct mtget))) + if (copy_to_user(argp, &mtget, sizeof(struct mtget))) return -EFAULT; return 0; case MTIOCPOS: mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; - if (copy_to_user((char *) arg,(char *) &mtpos, sizeof(struct mtpos))) + if (copy_to_user(argp, &mtpos, sizeof(struct mtpos))) return -EFAULT; return 0; default: diff -Nru a/drivers/ide/legacy/hd98.c b/drivers/ide/legacy/hd98.c --- a/drivers/ide/legacy/hd98.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,883 +0,0 @@ -/* - * Copyright (C) 1991, 1992 Linus Torvalds - * - * This is the low-level hd interrupt support. It traverses the - * request-list, using interrupts to jump between functions. As - * all the functions are called within interrupts, we may not - * sleep. Special care is recommended. - * - * modified by Drew Eckhardt to check nr of hd's from the CMOS. - * - * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug - * in the early extended-partition checks and added DM partitions - * - * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", - * and general streamlining by Mark Lord. - * - * Removed 99% of above. Use Mark's ide driver for those options. - * This is now a lightweight ST-506 driver. (Paul Gortmaker) - * - * Modified 1995 Russell King for ARM processor. - * - * Bugfix: max_sectors must be <= 255 or the wheels tend to come - * off in a hurry once you queue things up - Paul G. 02/2001 - */ - -/* Uncomment the following if you want verbose error reports. */ -/* #define VERBOSE_ERRORS */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* CMOS defines */ -#include -#include -#include - -#define REALLY_SLOW_IO -#include -#include -#include - -#include "io_ports.h" - -#ifdef __arm__ -#undef HD_IRQ -#endif -#include -#ifdef __arm__ -#define HD_IRQ IRQ_HARDDISK -#endif - -/* Hd controller regster ports */ - -#define HD_DATA 0x640 /* _CTL when writing */ -#define HD_ERROR 0x642 /* see err-bits */ -#define HD_NSECTOR 0x644 /* nr of sectors to read/write */ -#define HD_SECTOR 0x646 /* starting sector */ -#define HD_LCYL 0x648 /* starting cylinder */ -#define HD_HCYL 0x64a /* high byte of starting cyl */ -#define HD_CURRENT 0x64c /* 101dhhhh , d=drive, hhhh=head */ -#define HD_STATUS 0x64e /* see status-bits */ -#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ -#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ -#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ - -#define HD_CMD 0x74c /* used for resets */ -#define HD_ALTSTATUS 0x74c /* same as HD_STATUS but doesn't clear irq */ - -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SERVICE_STAT SEEK_STAT -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED; -static struct request_queue *hd_queue; - -#define CURRENT elv_next_request(hd_queue) - -#define TIMEOUT_VALUE (6*HZ) -#define HD_DELAY 0 - -#define MAX_ERRORS 16 /* Max read/write errors/sector */ -#define RESET_FREQ 8 /* Reset controller every 8th retry */ -#define RECAL_FREQ 4 /* Recalibrate every 4th retry */ -#define MAX_HD 2 - -#define STAT_OK (READY_STAT|SEEK_STAT) -#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) - -static void recal_intr(void); -static void bad_rw_intr(void); - -static int reset; -static int hd_error; - -/* - * This struct defines the HD's and their types. - */ -struct hd_i_struct { - unsigned int head,sect,cyl,wpcom,lzone,ctl; - int unit; - int recalibrate; - int special_op; -}; - -#ifdef HD_TYPE -static struct hd_i_struct hd_info[] = { HD_TYPE }; -static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); -#else -static struct hd_i_struct hd_info[MAX_HD]; -static int NR_HD; -#endif - -static struct gendisk *hd_gendisk[MAX_HD]; - -static struct timer_list device_timer; - -#define TIMEOUT_VALUE (6*HZ) - -#define SET_TIMER \ - do { \ - mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ - } while (0) - -static void (*do_hd)(void) = NULL; -#define SET_HANDLER(x) \ -if ((do_hd = (x)) != NULL) \ - SET_TIMER; \ -else \ - del_timer(&device_timer); - - -#if (HD_DELAY > 0) -unsigned long last_req; - -unsigned long read_timer(void) -{ - extern spinlock_t i8253_lock; - unsigned long t, flags; - int i; - - spin_lock_irqsave(&i8253_lock, flags); - t = jiffies * 11932; - outb_p(0, PIT_MODE); - i = inb_p(PIT_CH0); - i |= inb(PIT_CH0) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); - return(t - i); -} -#endif - -void __init hd_setup(char *str, int *ints) -{ - int hdind = 0; - - if (ints[0] != 3) - return; - if (hd_info[0].head != 0) - hdind=1; - hd_info[hdind].head = ints[2]; - hd_info[hdind].sect = ints[3]; - hd_info[hdind].cyl = ints[1]; - hd_info[hdind].wpcom = 0; - hd_info[hdind].lzone = ints[1]; - hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); - NR_HD = hdind+1; -} - -static void dump_status (const char *msg, unsigned int stat) -{ - char *name = CURRENT ? - CURRENT->rq_dev->bd_disk->disk_name : - "hd?"; -#ifdef VERBOSE_ERRORS - printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); - if (stat & BUSY_STAT) printk("Busy "); - if (stat & READY_STAT) printk("DriveReady "); - if (stat & WRERR_STAT) printk("WriteFault "); - if (stat & SEEK_STAT) printk("SeekComplete "); - if (stat & DRQ_STAT) printk("DataRequest "); - if (stat & ECC_STAT) printk("CorrectedError "); - if (stat & INDEX_STAT) printk("Index "); - if (stat & ERR_STAT) printk("Error "); - printk("}\n"); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = inb(HD_ERROR); - printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff); - if (hd_error & BBD_ERR) printk("BadSector "); - if (hd_error & ECC_ERR) printk("UncorrectableError "); - if (hd_error & ID_ERR) printk("SectorIdNotFound "); - if (hd_error & ABRT_ERR) printk("DriveStatusError "); - if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); - if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); - printk("}"); - if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { - printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), - inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); - if (CURRENT) - printk(", sector=%ld", CURRENT->sector); - } - printk("\n"); - } -#else - printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff); - if ((stat & ERR_STAT) == 0) { - hd_error = 0; - } else { - hd_error = inb(HD_ERROR); - printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff); - } -#endif -} - -void check_status(void) -{ - int i = inb(HD_STATUS); - - if (!OK_STATUS(i)) { - dump_status("check_status", i); - bad_rw_intr(); - } -} - -static int controller_busy(void) -{ - int retries = 100000; - unsigned char status; - - do { - status = inb(HD_STATUS); - } while ((status & BUSY_STAT) && --retries); - return status; -} - -static int status_ok(void) -{ - unsigned char status = inb(HD_STATUS); - - if (status & BUSY_STAT) - return 1; /* Ancient, but does it make sense??? */ - if (status & WRERR_STAT) - return 0; - if (!(status & READY_STAT)) - return 0; - if (!(status & SEEK_STAT)) - return 0; - return 1; -} - -static int controller_ready(unsigned int drive, unsigned int head) -{ - int retry = 100; - - do { - if (controller_busy() & BUSY_STAT) - return 0; - outb(0xA0 | (drive<<4) | head, HD_CURRENT); - if (status_ok()) - return 1; - } while (--retry); - return 0; -} - -static void hd_out(struct hd_i_struct *disk, - unsigned int nsect, - unsigned int sect, - unsigned int head, - unsigned int cyl, - unsigned int cmd, - void (*intr_addr)(void)) -{ - unsigned short port; - -#if (HD_DELAY > 0) - while (read_timer() - last_req < HD_DELAY) - /* nothing */; -#endif - if (reset) - return; - if (!controller_ready(disk->unit, head)) { - reset = 1; - return; - } - SET_HANDLER(intr_addr); - outb(disk->ctl,HD_CMD); - port=HD_DATA + 2; - outb(disk->wpcom>>2, port); port += 2; - outb(nsect, port); port += 2; - outb(sect, port); port += 2; - outb(cyl, port); port += 2; - outb(cyl>>8, port); port += 2; - outb(0xA0|(disk->unit<<4)|head, port); port += 2; - outb(cmd, port); -} - -static void hd_request (void); - -static int drive_busy(void) -{ - unsigned int i; - unsigned char c; - - for (i = 0; i < 500000 ; i++) { - c = inb(HD_STATUS); - if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) - return 0; - } - dump_status("reset timed out", c); - return 1; -} - -static void reset_controller(void) -{ - int i; - - outb(4,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - outb(hd_info[0].ctl & 0x0f,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - if (drive_busy()) - printk("hd: controller still busy\n"); - else if ((hd_error = inb(HD_ERROR)) != 1) - printk("hd: controller reset failed: %02x\n",hd_error); -} - -static void reset_hd(void) -{ - static int i; - -repeat: - if (reset) { - reset = 0; - i = -1; - reset_controller(); - } else { - check_status(); - if (reset) - goto repeat; - } - if (++i < NR_HD) { - struct hd_i_struct *disk = &hd_info[i]; - disk->special_op = disk->recalibrate = 1; - hd_out(disk, disk->sect, disk->sect, disk->head-1, - disk->cyl, WIN_SPECIFY, &reset_hd); - if (reset) - goto repeat; - } else - hd_request(); -} - -/* - * Ok, don't know what to do with the unexpected interrupts: on some machines - * doing a reset and a retry seems to result in an eternal loop. Right now I - * ignore it, and just set the timeout. - * - * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the - * drive enters "idle", "standby", or "sleep" mode, so if the status looks - * "good", we just ignore the interrupt completely. - */ -void unexpected_hd_interrupt(void) -{ - unsigned int stat = inb(HD_STATUS); - - if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { - dump_status ("unexpected interrupt", stat); - SET_TIMER; - } -} - -/* - * bad_rw_intr() now tries to be a bit smarter and does things - * according to the error returned by the controller. - * -Mika Liljeberg (liljeber@cs.Helsinki.FI) - */ -static void bad_rw_intr(void) -{ - struct request *req = CURRENT; - struct hd_i_struct *disk; - - if (!req) - return; - disk = req->rq_disk->private_data; - if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { - end_request(req, 0); - disk->special_op = disk->recalibrate = 1; - } else if (req->errors % RESET_FREQ == 0) - reset = 1; - else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0) - disk->special_op = disk->recalibrate = 1; - /* Otherwise just retry */ -} - -static inline int wait_DRQ(void) -{ - int retries = 100000, stat; - - while (--retries > 0) - if ((stat = inb(HD_STATUS)) & DRQ_STAT) - return 0; - dump_status("wait_DRQ", stat); - return -1; -} - -static void read_intr(void) -{ - int i, retries = 100000; - struct request *req; - - do { - i = (unsigned) inb(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if (i & DRQ_STAT) - goto ok_to_read; - } while (--retries > 0); - dump_status("read_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_read: - req = CURRENT; - insw(HD_DATA,req->buffer,256); - req->sector++; - req->buffer += 512; - req->errors = 0; - i = --req->nr_sectors; - --req->current_nr_sectors; -#ifdef DEBUG - printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n", - req->rq_disk->disk_name, req->sector, req->nr_sectors, - req->buffer+512); -#endif - if (req->current_nr_sectors <= 0) - end_request(req, 1); - if (i > 0) { - SET_HANDLER(&read_intr); - return; - } - (void) inb(HD_STATUS); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - if (CURRENT) - hd_request(); - return; -} - -static void write_intr(void) -{ - int i; - int retries = 100000; - struct request *req = CURRENT; - - do { - i = (unsigned) inb(HD_STATUS); - if (i & BUSY_STAT) - continue; - if (!OK_STATUS(i)) - break; - if ((req->nr_sectors <= 1) || (i & DRQ_STAT)) - goto ok_to_write; - } while (--retries > 0); - dump_status("write_intr", i); - bad_rw_intr(); - hd_request(); - return; -ok_to_write: - req->sector++; - i = --req->nr_sectors; - --req->current_nr_sectors; - req->buffer += 512; - if (!i || (req->bio && req->current_nr_sectors < 1)) - end_request(req, 1); - if (i > 0) { - SET_HANDLER(&write_intr); - outsw(HD_DATA,req->buffer,256); - local_irq_enable(); - } else { -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); - } - return; -} - -static void recal_intr(void) -{ - check_status(); -#if (HD_DELAY > 0) - last_req = read_timer(); -#endif - hd_request(); -} - -/* - * This is another of the error-routines I don't know what to do with. The - * best idea seems to just set reset, and start all over again. - */ -static void hd_times_out(unsigned long dummy) -{ - do_hd = NULL; - - if (!CURRENT) - return; - - disable_irq(HD_IRQ); - local_irq_enable(); - reset = 1; - printk("%s: timeout\n", CURRENT->rq_disk->disk_name); - if (++CURRENT->errors >= MAX_ERRORS) { -#ifdef DEBUG - printk("%s: too many errors\n", CURRENT->rq_disk->disk_name); -#endif - end_request(CURRENT, 0); - } - local_irq_disable(); - hd_request(); - enable_irq(HD_IRQ); -} - -int do_special_op(struct hd_i_struct *disk, struct request *req) -{ - if (disk->recalibrate) { - disk->recalibrate = 0; - hd_out(disk, disk->sect,0,0,0,WIN_RESTORE,&recal_intr); - return reset; - } - if (disk->head > 16) { - printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); - end_request(req, 0); - } - disk->special_op = 0; - return 1; -} - -/* - * The driver enables interrupts as much as possible. In order to do this, - * (a) the device-interrupt is disabled before entering hd_request(), - * and (b) the timeout-interrupt is disabled before the sti(). - * - * Interrupts are still masked (by default) whenever we are exchanging - * data/cmds with a drive, because some drives seem to have very poor - * tolerance for latency during I/O. The IDE driver has support to unmask - * interrupts for non-broken hardware, so use that driver if required. - */ -static void hd_request(void) -{ - unsigned int block, nsect, sec, track, head, cyl; - struct hd_i_struct *disk; - struct request *req; - - if (do_hd) - return; -repeat: - del_timer(&device_timer); - local_irq_enable(); - - if (!CURRENT) { - do_hd = NULL; - return; - } - req = CURRENT; - - if (reset) { - local_irq_disable(); - reset_hd(); - return; - } - disk = req->rq_disk->private_data; - block = req->sector; - nsect = req->nr_sectors; - if (block >= get_capacity(req->rq_disk) || - ((block+nsect) > get_capacity(req->rq_disk))) { - printk("%s: bad access: block=%d, count=%d\n", - req->rq_disk->disk_name, block, nsect); - end_request(req, 0); - goto repeat; - } - - if (disk->special_op) { - if (do_special_op(disk, req)) - goto repeat; - return; - } - sec = block % disk->sect + 1; - track = block / disk->sect; - head = track % disk->head; - cyl = track / disk->head; -#ifdef DEBUG - printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n", - req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ", - cyl, head, sec, nsect, req->buffer); -#endif - if (req->flags & REQ_CMD) { - switch (rq_data_dir(req)) { - case READ: - hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr); - if (reset) - goto repeat; - break; - case WRITE: - hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr); - if (reset) - goto repeat; - if (wait_DRQ()) { - bad_rw_intr(); - goto repeat; - } - outsw(HD_DATA,req->buffer,256); - break; - default: - printk("unknown hd-command\n"); - end_request(req, 0); - break; - } - } -} - -static void do_hd_request (request_queue_t * q) -{ - disable_irq(HD_IRQ); - hd_request(); - enable_irq(HD_IRQ); -} - -static int hd_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; - struct hd_geometry *loc = (struct hd_geometry *) arg; - struct hd_geometry g; - - if (cmd != HDIO_GETGEO) - return -EINVAL; - if (!loc) - return -EINVAL; - g.heads = disk->head; - g.sectors = disk->sect; - g.cylinders = disk->cyl; - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ - -static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - void (*handler)(void) = do_hd; - - do_hd = NULL; - del_timer(&device_timer); - if (!handler) - handler = unexpected_hd_interrupt; - handler(); - local_irq_enable(); -} - -static struct block_device_operations hd_fops = { - .ioctl = hd_ioctl, -}; - -/* - * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags - * means we run the IRQ-handler with interrupts disabled: this is bad for - * interrupt latency, but anything else has led to problems on some - * machines. - * - * We enable interrupts in some of the routines after making sure it's - * safe. - */ - -static int __init hd_init(void) -{ - int drive; - if (register_blkdev(HD_MAJOR,"hd")) { - printk("hd: unable to get major %d for hard disk\n",HD_MAJOR); - return -1; - } - hd_queue = blk_init_queue(do_hd_request, &hd_lock); - if (!hd_queue) { - unregister_blkdev(HD_MAJOR,"hd"); - return -1; - } - blk_queue_max_sectors(hd_queue, 255); - init_timer(&device_timer); - device_timer.function = hd_times_out; - blk_queue_hardsect_size(hd_queue, 512); - -#ifdef __i386__ - if (!NR_HD) { - extern struct drive_info drive_info; - unsigned char *BIOS = (unsigned char *) &drive_info; - unsigned long flags; -#ifndef CONFIG_X86_PC9800 - int cmos_disks; -#endif - - for (drive=0 ; drive<2 ; drive++) { - hd_info[drive].cyl = *(unsigned short *) BIOS; - hd_info[drive].head = *(3+BIOS); - hd_info[drive].sect = *(2+BIOS); - hd_info[drive].wpcom = 0; - hd_info[drive].ctl = *(3+BIOS) > 8 ? 8 : 0; - hd_info[drive].lzone = *(unsigned short *) BIOS; - if (hd_info[drive].cyl && NR_HD == drive) - NR_HD++; - BIOS += 6; - } - - } -#endif /* __i386__ */ -#ifdef __arm__ - if (!NR_HD) { - /* We don't know anything about the drive. This means - * that you *MUST* specify the drive parameters to the - * kernel yourself. - */ - printk("hd: no drives specified - use hd=cyl,head,sectors" - " on kernel command line\n"); - } -#endif - if (!NR_HD) - goto out; - - for (drive=0 ; drive < NR_HD ; drive++) { - struct gendisk *disk = alloc_disk(64); - struct hd_i_struct *p = &hd_info[drive]; - if (!disk) - goto Enomem; - disk->major = HD_MAJOR; - disk->first_minor = drive << 6; - disk->fops = &hd_fops; - sprintf(disk->disk_name, "hd%c", 'a'+drive); - disk->private_data = p; - set_capacity(disk, p->head * p->sect * p->cyl); - disk->queue = hd_queue; - p->unit = drive; - hd_gendisk[drive] = disk; - printk ("%s: %luMB, CHS=%d/%d/%d\n", - disk->disk_name, (unsigned long)get_capacity(disk)/2048, - p->cyl, p->head, p->sect); - } - - if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { - printk("hd: unable to get IRQ%d for the hard disk driver\n", - HD_IRQ); - goto out1; - } - - if (!request_region(HD_DATA, 2, "hd(data)")) { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - NR_HD = 0; - free_irq(HD_IRQ, NULL); - return; - } - - if (!request_region(HD_DATA + 2, 1, "hd")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - goto out2; - } - - if (!request_region(HD_DATA + 4, 1, "hd")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - goto out3; - } - - if (!request_region(HD_DATA + 6, 1, "hd")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - goto out4; - } - - if (!request_region(HD_DATA + 8, 1, "hd")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - goto out5; - } - - if (!request_region(HD_DATA + 10, 1, "hd")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - goto out6; - } - - if (!request_region(HD_DATA + 12, 1, "hd")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); - goto out7; - } - - if (!request_region(HD_CMD, 1, "hd(cmd)")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); - goto out8; - } - - if (!request_region(HD_CMD + 2, 1, "hd(cmd)")) - { - printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); - goto out9; - } - - for(drive=0; drive < NR_HD; drive++) - add_disk(hd_gendisk[drive]); - return 0; - -out9: - release_region(HD_CMD, 1); -out8: - release_region(HD_DATA + 12, 1); -out7: - release_region(HD_DATA + 10, 1); -out6: - release_region(HD_DATA + 8, 1); -out5: - release_region(HD_DATA + 6, 1); -out4: - release_region(HD_DATA + 4, 1); -out3: - release_region(HD_DATA + 2, 1); -out2: - release_region(HD_DATA, 2); - free_irq(HD_IRQ, NULL); -out1: - for (drive = 0; drive < NR_HD; drive++) - put_disk(hd_gendisk[drive]); - NR_HD = 0; -out: - del_timer(&device_timer); - unregister_blkdev(HD_MAJOR,"hd"); - blk_cleanup_queue(hd_queue); - return -1; -Enomem: - while (drive--) - put_disk(hd_gendisk[drive]); - goto out; -} - -static int parse_hd_setup (char *line) { - int ints[6]; - - (void) get_options(line, ARRAY_SIZE(ints), ints); - hd_setup(NULL, ints); - - return 1; -} -__setup("hd=", parse_hd_setup); - -module_init(hd_init); diff -Nru a/drivers/ide/legacy/pc9800.c b/drivers/ide/legacy/pc9800.c --- a/drivers/ide/legacy/pc9800.c 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,84 +0,0 @@ -/* - * ide_pc9800.c - * - * Copyright (C) 1997-2000 Linux/98 project, - * Kyoto University Microcomputer Club. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#define PC9800_IDE_BANKSELECT 0x432 - -#undef PC9800_IDE_DEBUG - -static void pc9800_select(ide_drive_t *drive) -{ -#ifdef PC9800_IDE_DEBUG - byte old; - - /* Too noisy: */ - /* printk(KERN_DEBUG "pc9800_select(%s)\n", drive->name); */ - - outb(0x80, PC9800_IDE_BANKSELECT); - old = inb(PC9800_IDE_BANKSELECT); - if (old != HWIF(drive)->index) - printk(KERN_DEBUG "ide-pc9800: switching bank #%d -> #%d\n", - old, HWIF(drive)->index); -#endif - outb(HWIF(drive)->index, PC9800_IDE_BANKSELECT); -} - -void __init ide_probe_for_pc9800(void) -{ - u8 saved_bank; - - if (!PC9800_9821_P() /* || !PC9821_IDEIF_DOUBLE_P() */) - return; - - if (!request_region(PC9800_IDE_BANKSELECT, 1, "ide0/1 bank")) { - printk(KERN_ERR - "ide: bank select port (%#x) is already occupied!\n", - PC9800_IDE_BANKSELECT); - return; - } - - /* Do actual probing. */ - if ((saved_bank = inb(PC9800_IDE_BANKSELECT)) == (u8) ~0 - || (outb(saved_bank ^ 1, PC9800_IDE_BANKSELECT), - /* Next outb is dummy for reading status. */ - outb(0x80, PC9800_IDE_BANKSELECT), - inb(PC9800_IDE_BANKSELECT) != (saved_bank ^ 1))) { - printk(KERN_INFO - "ide: pc9800 type bank selecting port not found\n"); - release_region(PC9800_IDE_BANKSELECT, 1); - return; - } - - /* Restore original value, just in case. */ - outb(saved_bank, PC9800_IDE_BANKSELECT); - - /* These ports are reseved by IDE I/F. */ - if (!request_region(0x430, 1, "ide") || - !request_region(0x435, 1, "ide")) { - printk(KERN_WARNING - "ide: IO port 0x430 and 0x435 are reserved for IDE" - " the card using these ports may not work\n"); - } - - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET] == HD_DATA && - ide_hwifs[1].io_ports[IDE_DATA_OFFSET] == HD_DATA) { - ide_hwifs[0].chipset = ide_pc9800; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[0].selectproc = pc9800_select; - ide_hwifs[1].chipset = ide_pc9800; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].selectproc = pc9800_select; - } -} diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c --- a/drivers/ieee1394/eth1394.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/ieee1394/eth1394.c 2004-06-20 13:00:25 -07:00 @@ -431,9 +431,12 @@ if (!node) return -ENOMEM; - node_info = kmalloc(sizeof(struct eth1394_node_info), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!node_info) { + kfree(node); + return -ENOMEM; + } spin_lock_init(&node_info->pdg.lock); INIT_LIST_HEAD(&node_info->pdg.list); diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c --- a/drivers/input/joydev.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/input/joydev.c 2004-06-20 13:00:24 -07:00 @@ -191,12 +191,12 @@ return 0; } -static ssize_t joydev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos) +static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { return -EINVAL; } -static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct joydev_list *list = file->private_data; struct joydev *joydev = list->joydev; @@ -291,6 +291,7 @@ struct joydev_list *list = file->private_data; struct joydev *joydev = list->joydev; struct input_dev *dev = joydev->handle.dev; + void __user *argp = (void __user *)arg; int i, j; if (!joydev->exist) return -ENODEV; @@ -298,34 +299,34 @@ switch (cmd) { case JS_SET_CAL: - return copy_from_user(&joydev->glue.JS_CORR, (struct JS_DATA_TYPE *) arg, + return copy_from_user(&joydev->glue.JS_CORR, argp, sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; case JS_GET_CAL: - return copy_to_user((struct JS_DATA_TYPE *) arg, &joydev->glue.JS_CORR, + return copy_to_user(argp, &joydev->glue.JS_CORR, sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; case JS_SET_TIMEOUT: - return get_user(joydev->glue.JS_TIMEOUT, (int *) arg); + return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); case JS_GET_TIMEOUT: - return put_user(joydev->glue.JS_TIMEOUT, (int *) arg); + return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); case JS_SET_TIMELIMIT: - return get_user(joydev->glue.JS_TIMELIMIT, (long *) arg); + return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); case JS_GET_TIMELIMIT: - return put_user(joydev->glue.JS_TIMELIMIT, (long *) arg); + return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); case JS_SET_ALL: - return copy_from_user(&joydev->glue, (struct JS_DATA_SAVE_TYPE *) arg, + return copy_from_user(&joydev->glue, argp, sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; case JS_GET_ALL: - return copy_to_user((struct JS_DATA_SAVE_TYPE *) arg, &joydev->glue, + return copy_to_user(argp, &joydev->glue, sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; case JSIOCGVERSION: - return put_user(JS_VERSION, (__u32 *) arg); + return put_user(JS_VERSION, (__u32 __user *) arg); case JSIOCGAXES: - return put_user(joydev->nabs, (__u8 *) arg); + return put_user(joydev->nabs, (__u8 __user *) arg); case JSIOCGBUTTONS: - return put_user(joydev->nkey, (__u8 *) arg); + return put_user(joydev->nkey, (__u8 __user *) arg); case JSIOCSCORR: - if (copy_from_user(joydev->corr, (struct js_corr *)arg, + if (copy_from_user(joydev->corr, argp, sizeof(struct js_corr) * joydev->nabs)) return -EFAULT; for (i = 0; i < joydev->nabs; i++) { @@ -334,10 +335,10 @@ } return 0; case JSIOCGCORR: - return copy_to_user((struct js_corr *) arg, joydev->corr, + return copy_to_user(argp, joydev->corr, sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; case JSIOCSAXMAP: - if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX)) + if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * ABS_MAX)) return -EFAULT; for (i = 0; i < joydev->nabs; i++) { if (joydev->abspam[i] > ABS_MAX) return -EINVAL; @@ -345,10 +346,10 @@ } return 0; case JSIOCGAXMAP: - return copy_to_user((__u8 *) arg, joydev->abspam, + return copy_to_user(argp, joydev->abspam, sizeof(__u8) * ABS_MAX) ? -EFAULT : 0; case JSIOCSBTNMAP: - if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC))) + if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC))) return -EFAULT; for (i = 0; i < joydev->nkey; i++) { if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL; @@ -356,7 +357,7 @@ } return 0; case JSIOCGBTNMAP: - return copy_to_user((__u16 *) arg, joydev->keypam, + return copy_to_user(argp, joydev->keypam, sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0; default: if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { @@ -364,7 +365,7 @@ if (!dev->name) return 0; len = strlen(dev->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - if (copy_to_user((char *) arg, dev->name, len)) return -EFAULT; + if (copy_to_user(argp, dev->name, len)) return -EFAULT; return len; } } diff -Nru a/drivers/input/keyboard/98kbd.c b/drivers/input/keyboard/98kbd.c --- a/drivers/input/keyboard/98kbd.c 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,391 +0,0 @@ -/* - * drivers/input/keyboard/98kbd.c - * - * PC-9801 keyboard driver for Linux - * - * Based on atkbd.c and xtkbd.c written by Vojtech Pavlik - * - * Copyright (c) 2002 Osamu Tomita - * Copyright (c) 1999-2001 Vojtech Pavlik - */ - -/* - * 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 - -MODULE_AUTHOR("Osamu Tomita "); -MODULE_DESCRIPTION("PC-9801 keyboard driver"); -MODULE_LICENSE("GPL"); - -#define KBD98_KEY 0x7f -#define KBD98_RELEASE 0x80 - -static unsigned char kbd98_keycode[256] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 43, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 41, 26, 28, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 27, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 12, 57, 92,109,104,110,111,103,105,106,108,102,107, - 74, 98, 71, 72, 73, 55, 75, 76, 77, 78, 79, 80, 81,117, 82,121, - 83, 94, 87, 88,183,184,185, 0, 0, 0, 0, 0, 0, 0,102, 0, - 99,133, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 0, 0, 0, - 54, 58, 42, 56, 29 -}; - -struct jis_kbd_conv { - unsigned char scancode; - struct { - unsigned char shift; - unsigned char keycode; - } emul[2]; -}; - -static struct jis_kbd_conv kbd98_jis[] = { - {0x02, {{0, 3}, {1, 40}}}, - {0x06, {{0, 7}, {1, 8}}}, - {0x07, {{0, 8}, {0, 40}}}, - {0x08, {{0, 9}, {1, 10}}}, - {0x09, {{0, 10}, {1, 11}}}, - {0x0a, {{0, 11}, {1, 255}}}, - {0x0b, {{0, 12}, {0, 13}}}, - {0x0c, {{1, 7}, {0, 41}}}, - {0x1a, {{1, 3}, {1, 41}}}, - {0x26, {{0, 39}, {1, 13}}}, - {0x27, {{1, 39}, {1, 9}}}, - {0x33, {{0, 255}, {1, 12}}}, - {0xff, {{0, 255}, {1, 255}}} /* terminater */ -}; - -#define KBD98_CMD_SETEXKEY 0x1095 /* Enable/Disable Windows, Appli key */ -#define KBD98_CMD_SETRATE 0x109c /* Set typematic rate */ -#define KBD98_CMD_SETLEDS 0x109d /* Set keyboard leds */ -#define KBD98_CMD_GETLEDS 0x119d /* Get keyboard leds */ -#define KBD98_CMD_GETID 0x019f - -#define KBD98_RET_ACK 0xfa -#define KBD98_RET_NAK 0xfc /* Command NACK, send the cmd again */ - -#define KBD98_KEY_JIS_EMUL 253 -#define KBD98_KEY_UNKNOWN 254 -#define KBD98_KEY_NULL 255 - -static char *kbd98_name = "PC-9801 Keyboard"; - -struct kbd98 { - unsigned char keycode[256]; - struct input_dev dev; - struct serio *serio; - char phys[32]; - unsigned char cmdbuf[4]; - unsigned char cmdcnt; - signed char ack; - unsigned char shift; - struct { - unsigned char scancode; - unsigned char keycode; - } emul; - struct jis_kbd_conv jis[16]; -}; - -irqreturn_t kbd98_interrupt(struct serio *serio, unsigned char data, - unsigned int flags, struct pt_regs *regs) -{ - struct kbd98 *kbd98 = serio->private; - unsigned char scancode, keycode; - int press, i; - - switch (data) { - case KBD98_RET_ACK: - kbd98->ack = 1; - goto out; - case KBD98_RET_NAK: - kbd98->ack = -1; - goto out; - } - - if (kbd98->cmdcnt) { - kbd98->cmdbuf[--kbd98->cmdcnt] = data; - goto out; - } - - scancode = data & KBD98_KEY; - keycode = kbd98->keycode[scancode]; - press = !(data & KBD98_RELEASE); - if (kbd98->emul.scancode != KBD98_KEY_UNKNOWN - && scancode != kbd98->emul.scancode) { - input_report_key(&kbd98->dev, kbd98->emul.keycode, 0); - kbd98->emul.scancode = KBD98_KEY_UNKNOWN; - } - - if (keycode == KEY_RIGHTSHIFT) - kbd98->shift = press; - - switch (keycode) { - case KEY_2: - case KEY_6: - case KEY_7: - case KEY_8: - case KEY_9: - case KEY_0: - case KEY_MINUS: - case KEY_EQUAL: - case KEY_GRAVE: - case KEY_SEMICOLON: - case KEY_APOSTROPHE: - /* emulation: JIS keyboard to US101 keyboard */ - i = 0; - while (kbd98->jis[i].scancode != 0xff) { - if (scancode == kbd98->jis[i].scancode) - break; - i ++; - } - - keycode = kbd98->jis[i].emul[kbd98->shift].keycode; - if (keycode == KBD98_KEY_NULL) - break; - - if (press) { - kbd98->emul.scancode = scancode; - kbd98->emul.keycode = keycode; - if (kbd98->jis[i].emul[kbd98->shift].shift - != kbd98->shift) - input_report_key(&kbd98->dev, - KEY_RIGHTSHIFT, - !(kbd98->shift)); - } - - input_report_key(&kbd98->dev, keycode, press); - if (!press) { - if (kbd98->jis[i].emul[kbd98->shift].shift - != kbd98->shift) - input_report_key(&kbd98->dev, - KEY_RIGHTSHIFT, - kbd98->shift); - kbd98->emul.scancode = KBD98_KEY_UNKNOWN; - } - - input_sync(&kbd98->dev); - break; - - case KEY_CAPSLOCK: - input_report_key(&kbd98->dev, keycode, 1); - input_sync(&kbd98->dev); - input_report_key(&kbd98->dev, keycode, 0); - input_sync(&kbd98->dev); - break; - - case KBD98_KEY_NULL: - break; - - case 0: - printk(KERN_WARNING "kbd98.c: Unknown key (scancode %#x) %s.\n", - data & KBD98_KEY, data & KBD98_RELEASE ? "released" : "pressed"); - break; - - default: - input_report_key(&kbd98->dev, keycode, press); - input_sync(&kbd98->dev); - break; - } - -out: - return IRQ_HANDLED; -} - -/* - * kbd98_sendbyte() sends a byte to the keyboard, and waits for - * acknowledge. It doesn't handle resends according to the keyboard - * protocol specs, because if these are needed, the keyboard needs - * replacement anyway, and they only make a mess in the protocol. - */ - -static int kbd98_sendbyte(struct kbd98 *kbd98, unsigned char byte) -{ - int timeout = 10000; /* 100 msec */ - kbd98->ack = 0; - - if (serio_write(kbd98->serio, byte)) - return -1; - - while (!kbd98->ack && timeout--) udelay(10); - - return -(kbd98->ack <= 0); -} - -/* - * kbd98_command() sends a command, and its parameters to the keyboard, - * then waits for the response and puts it in the param array. - */ - -static int kbd98_command(struct kbd98 *kbd98, unsigned char *param, int command) -{ - int timeout = 50000; /* 500 msec */ - int send = (command >> 12) & 0xf; - int receive = (command >> 8) & 0xf; - int i; - - kbd98->cmdcnt = receive; - - if (command & 0xff) - if (kbd98_sendbyte(kbd98, command & 0xff)) - return (kbd98->cmdcnt = 0) - 1; - - for (i = 0; i < send; i++) - if (kbd98_sendbyte(kbd98, param[i])) - return (kbd98->cmdcnt = 0) - 1; - - while (kbd98->cmdcnt && timeout--) udelay(10); - - if (param) - for (i = 0; i < receive; i++) - param[i] = kbd98->cmdbuf[(receive - 1) - i]; - - if (kbd98->cmdcnt) - return (kbd98->cmdcnt = 0) - 1; - - return 0; -} - -/* - * Event callback from the input module. Events that change the state of - * the hardware are processed here. - */ - -static int kbd98_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - struct kbd98 *kbd98 = dev->private; - char param[2]; - - switch (type) { - - case EV_LED: - - if (__PC9800SCA_TEST_BIT(0x481, 3)) { - /* 98note with Num Lock key */ - /* keep Num Lock status */ - *param = 0x60; - if (kbd98_command(kbd98, param, - KBD98_CMD_GETLEDS)) - printk(KERN_DEBUG - "kbd98: Get keyboard LED" - " status Error\n"); - - *param &= 1; - } else { - /* desktop PC-9801 */ - *param = 1; /* Always set Num Lock */ - } - - *param |= 0x70 - | (test_bit(LED_CAPSL, dev->led) ? 4 : 0) - | (test_bit(LED_KANA, dev->led) ? 8 : 0); - kbd98_command(kbd98, param, KBD98_CMD_SETLEDS); - - return 0; - } - - return -1; -} - -void kbd98_connect(struct serio *serio, struct serio_dev *dev) -{ - struct kbd98 *kbd98; - int i; - - if ((serio->type & SERIO_TYPE) != SERIO_PC9800) - return; - - if (!(kbd98 = kmalloc(sizeof(struct kbd98), GFP_KERNEL))) - return; - - memset(kbd98, 0, sizeof(struct kbd98)); - kbd98->emul.scancode = KBD98_KEY_UNKNOWN; - - kbd98->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); - kbd98->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_KANA); - - kbd98->serio = serio; - - init_input_dev(&kbd98->dev); - kbd98->dev.keycode = kbd98->keycode; - kbd98->dev.keycodesize = sizeof(unsigned char); - kbd98->dev.keycodemax = ARRAY_SIZE(kbd98_keycode); - kbd98->dev.event = kbd98_event; - kbd98->dev.private = kbd98; - - serio->private = kbd98; - - if (serio_open(serio, dev)) { - kfree(kbd98); - return; - } - - memcpy(kbd98->jis, kbd98_jis, sizeof(kbd98_jis)); - memcpy(kbd98->keycode, kbd98_keycode, sizeof(kbd98->keycode)); - for (i = 0; i < 255; i++) - set_bit(kbd98->keycode[i], kbd98->dev.keybit); - clear_bit(0, kbd98->dev.keybit); - - sprintf(kbd98->phys, "%s/input0", serio->phys); - - kbd98->dev.name = kbd98_name; - kbd98->dev.phys = kbd98->phys; - kbd98->dev.id.bustype = BUS_XTKBD; - kbd98->dev.id.vendor = 0x0002; - kbd98->dev.id.product = 0x0001; - kbd98->dev.id.version = 0x0100; - - input_register_device(&kbd98->dev); - - printk(KERN_INFO "input: %s on %s\n", kbd98_name, serio->phys); -} - -void kbd98_disconnect(struct serio *serio) -{ - struct kbd98 *kbd98 = serio->private; - input_unregister_device(&kbd98->dev); - serio_close(serio); - kfree(kbd98); -} - -struct serio_dev kbd98_dev = { - .interrupt = kbd98_interrupt, - .connect = kbd98_connect, - .disconnect = kbd98_disconnect -}; - -int __init kbd98_init(void) -{ - serio_register_device(&kbd98_dev); - return 0; -} - -void __exit kbd98_exit(void) -{ - serio_unregister_device(&kbd98_dev); -} - -module_init(kbd98_init); -module_exit(kbd98_exit); diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig --- a/drivers/input/keyboard/Kconfig 2004-06-20 13:00:26 -07:00 +++ b/drivers/input/keyboard/Kconfig 2004-06-20 13:00:26 -07:00 @@ -96,15 +96,3 @@ To compile this driver as a module, choose M here: the module will be called amikbd. - -config KEYBOARD_98KBD - tristate "NEC PC-9800 Keyboard support" - depends on X86_PC9800 && INPUT && INPUT_KEYBOARD - select SERIO - help - Say Y here if you want to use the NEC PC-9801/PC-9821 keyboard (or - compatible) on your system. - - To compile this driver as a module, choose M here: the - module will be called 98kbd. - diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- a/drivers/input/keyboard/atkbd.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/input/keyboard/atkbd.c 2004-06-20 13:00:25 -07:00 @@ -288,7 +288,7 @@ atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3); goto out; case ATKBD_RET_ERR: - printk(KERN_WARNING "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); + printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); goto out; } diff -Nru a/drivers/input/misc/98spkr.c b/drivers/input/misc/98spkr.c --- a/drivers/input/misc/98spkr.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,96 +0,0 @@ -/* - * PC-9800 Speaker beeper driver for Linux - * - * Copyright (c) 2002 Osamu Tomita - * Copyright (c) 2002 Vojtech Pavlik - * Copyright (c) 1992 Orest Zborowski - * - */ - -/* - * 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 - -MODULE_AUTHOR("Osamu Tomita "); -MODULE_DESCRIPTION("PC-9800 Speaker beeper driver"); -MODULE_LICENSE("GPL"); - -static char spkr98_name[] = "PC-9801 Speaker"; -static char spkr98_phys[] = "isa3fdb/input0"; -static struct input_dev spkr98_dev; - -spinlock_t i8253_beep_lock = SPIN_LOCK_UNLOCKED; - -static int spkr98_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - unsigned int count = 0; - unsigned long flags; - - if (type != EV_SND) - return -1; - - switch (code) { - case SND_BELL: if (value) value = 1000; - case SND_TONE: break; - default: return -1; - } - - if (value > 20 && value < 32767) - count = PIT_TICK_RATE / value; - - spin_lock_irqsave(&i8253_beep_lock, flags); - - if (count) { - outb(0x76, 0x3fdf); - outb(0, 0x5f); - outb(count & 0xff, 0x3fdb); - outb(0, 0x5f); - outb((count >> 8) & 0xff, 0x3fdb); - /* beep on */ - outb(6, 0x37); - } else { - /* beep off */ - outb(7, 0x37); - } - - spin_unlock_irqrestore(&i8253_beep_lock, flags); - - return 0; -} - -static int __init spkr98_init(void) -{ - spkr98_dev.evbit[0] = BIT(EV_SND); - spkr98_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - spkr98_dev.event = spkr98_event; - - spkr98_dev.name = spkr98_name; - spkr98_dev.phys = spkr98_phys; - spkr98_dev.id.bustype = BUS_ISA; - spkr98_dev.id.vendor = 0x001f; - spkr98_dev.id.product = 0x0001; - spkr98_dev.id.version = 0x0100; - - input_register_device(&spkr98_dev); - - printk(KERN_INFO "input: %s\n", spkr98_name); - - return 0; -} - -static void __exit spkr98_exit(void) -{ - input_unregister_device(&spkr98_dev); -} - -module_init(spkr98_init); -module_exit(spkr98_exit); diff -Nru a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig --- a/drivers/input/misc/Kconfig 2004-06-20 13:00:24 -07:00 +++ b/drivers/input/misc/Kconfig 2004-06-20 13:00:24 -07:00 @@ -40,10 +40,6 @@ tristate "M68k Beeper support" depends on M68K && INPUT && INPUT_MISC -config INPUT_98SPKR - tristate "PC-9800 Speaker support" - depends on X86_PC9800 && INPUT && INPUT_MISC - config INPUT_UINPUT tristate "User level driver support" depends on INPUT && INPUT_MISC diff -Nru a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c --- a/drivers/input/misc/uinput.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/input/misc/uinput.c 2004-06-20 13:00:25 -07:00 @@ -166,7 +166,7 @@ return retval; } -static int uinput_alloc_device(struct file *file, const char *buffer, size_t count) +static int uinput_alloc_device(struct file *file, const char __user *buffer, size_t count) { struct uinput_user_dev *user_dev; struct input_dev *dev; @@ -226,7 +226,7 @@ return retval; } -static ssize_t uinput_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct uinput_device *udev = file->private_data; @@ -243,7 +243,7 @@ return count; } -static ssize_t uinput_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct uinput_device *udev = file->private_data; int retval = 0; diff -Nru a/drivers/input/mouse/98busmouse.c b/drivers/input/mouse/98busmouse.c --- a/drivers/input/mouse/98busmouse.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,197 +0,0 @@ -/* - * - * Copyright (c) 2002 Osamu Tomita - * - * Based on the work of: - * James Banks Matthew Dillon - * David Giller Nathan Laredo - * Linus Torvalds Johan Myreen - * Cliff Matthews Philip Blundell - * Russell King Vojtech Pavlik - */ - -/* - * NEC PC-9801 Bus Mouse Driver for Linux - */ - -/* - * 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 - -MODULE_AUTHOR("Osamu Tomita "); -MODULE_DESCRIPTION("PC-9801 busmouse driver"); -MODULE_LICENSE("GPL"); - -#define PC98BM_BASE 0x7fd9 -#define PC98BM_DATA_PORT PC98BM_BASE + 0 -/* PC98BM_SIGNATURE_PORT does not exist */ -#define PC98BM_CONTROL_PORT PC98BM_BASE + 4 -/* PC98BM_INTERRUPT_PORT does not exist */ -#define PC98BM_CONFIG_PORT PC98BM_BASE + 6 - -#define PC98BM_ENABLE_IRQ 0x00 -#define PC98BM_DISABLE_IRQ 0x10 -#define PC98BM_READ_X_LOW 0x80 -#define PC98BM_READ_X_HIGH 0xa0 -#define PC98BM_READ_Y_LOW 0xc0 -#define PC98BM_READ_Y_HIGH 0xe0 - -#define PC98BM_DEFAULT_MODE 0x93 -/* PC98BM_CONFIG_BYTE is not used */ -/* PC98BM_SIGNATURE_BYTE is not used */ - -#define PC98BM_TIMER_PORT 0xbfdb -#define PC98BM_DEFAULT_TIMER_VAL 0x00 - -#define PC98BM_IRQ 13 - -static int pc98bm_irq = PC98BM_IRQ; -module_param_named(irq, pc98bm_irq, uint, 0); -MODULE_PARM_DESC(irq, "IRQ number (13=default)"); - -__obsolete_setup("pc98bm_irq="); - -static int pc98bm_used = 0; - -static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs); - -static int pc98bm_open(struct input_dev *dev) -{ - if (pc98bm_used++) - return 0; - if (request_irq(pc98bm_irq, pc98bm_interrupt, 0, "98busmouse", NULL)) { - pc98bm_used--; - printk(KERN_ERR "98busmouse.c: Can't allocate irq %d\n", pc98bm_irq); - return -EBUSY; - } - outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT); - return 0; -} - -static void pc98bm_close(struct input_dev *dev) -{ - if (--pc98bm_used) - return; - outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT); - free_irq(pc98bm_irq, NULL); -} - -static struct input_dev pc98bm_dev = { - .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, - .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) }, - .relbit = { BIT(REL_X) | BIT(REL_Y) }, - .open = pc98bm_open, - .close = pc98bm_close, - .name = "PC-9801 bus mouse", - .phys = "isa7fd9/input0", - .id = { - .bustype = BUS_ISA, - .vendor = 0x0004, - .product = 0x0001, - .version = 0x0100, - }, -}; - -static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - char dx, dy; - unsigned char buttons; - - outb(PC98BM_READ_X_LOW, PC98BM_CONTROL_PORT); - dx = (inb(PC98BM_DATA_PORT) & 0xf); - outb(PC98BM_READ_X_HIGH, PC98BM_CONTROL_PORT); - dx |= (inb(PC98BM_DATA_PORT) & 0xf) << 4; - outb(PC98BM_READ_Y_LOW, PC98BM_CONTROL_PORT); - dy = (inb(PC98BM_DATA_PORT) & 0xf); - outb(PC98BM_READ_Y_HIGH, PC98BM_CONTROL_PORT); - buttons = inb(PC98BM_DATA_PORT); - dy |= (buttons & 0xf) << 4; - buttons = ~buttons >> 5; - - input_report_rel(&pc98bm_dev, REL_X, dx); - input_report_rel(&pc98bm_dev, REL_Y, dy); - input_report_key(&pc98bm_dev, BTN_RIGHT, buttons & 1); - input_report_key(&pc98bm_dev, BTN_MIDDLE, buttons & 2); - input_report_key(&pc98bm_dev, BTN_LEFT, buttons & 4); - input_sync(&pc98bm_dev); - - outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT); - - return IRQ_HANDLED; -} - -static int __init pc98bm_init(void) -{ - int i; - - for (i = 0; i <= 6; i += 2) { - if (!request_region(PC98BM_BASE + i, 1, "98busmouse")) { - printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_BASE + i); - while (i > 0) { - i -= 2; - release_region(PC98BM_BASE + i, 1); - } - - return -EBUSY; - } - - } - - if (!request_region(PC98BM_TIMER_PORT, 1, "98busmouse")) { - printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_TIMER_PORT); - for (i = 0; i <= 6; i += 2) - release_region(PC98BM_BASE + i, 1); - - return -EBUSY; - } - - outb(PC98BM_DEFAULT_MODE, PC98BM_CONFIG_PORT); - outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT); - - outb(PC98BM_DEFAULT_TIMER_VAL, PC98BM_TIMER_PORT); - - input_register_device(&pc98bm_dev); - - printk(KERN_INFO "input: PC-9801 bus mouse at %#x irq %d\n", PC98BM_BASE, pc98bm_irq); - - return 0; -} - -static void __exit pc98bm_exit(void) -{ - int i; - - input_unregister_device(&pc98bm_dev); - for (i = 0; i <= 6; i += 2) - release_region(PC98BM_BASE + i, 1); - - release_region(PC98BM_TIMER_PORT, 1); -} - -module_init(pc98bm_init); -module_exit(pc98bm_exit); diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig --- a/drivers/input/mouse/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/input/mouse/Kconfig 2004-06-20 13:00:25 -07:00 @@ -130,14 +130,3 @@ described in the source file). This driver should, in theory, also work with the digitizer DEC produced, but it isn't tested with that (I don't have the hardware yet). - -config MOUSE_PC9800 - tristate "NEC PC-9800 busmouse" - depends on X86_PC9800 && INPUT && INPUT_MOUSE && ISA - help - Say Y here if you have NEC PC-9801/PC-9821 computer and want its - native mouse supported. - - To compile this driver as a module, choose M here: the - module will be called 98busmouse. - diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile --- a/drivers/input/mouse/Makefile 2004-06-20 13:00:23 -07:00 +++ b/drivers/input/mouse/Makefile 2004-06-20 13:00:23 -07:00 @@ -10,7 +10,6 @@ obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o -obj-$(CONFIG_MOUSE_PC9800) += 98busmouse.o obj-$(CONFIG_MOUSE_PS2) += psmouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o diff -Nru a/drivers/input/serio/98kbd-io.c b/drivers/input/serio/98kbd-io.c --- a/drivers/input/serio/98kbd-io.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,179 +0,0 @@ -/* - * NEC PC-9801 keyboard controller driver for Linux - * - * Copyright (c) 1999-2002 Osamu Tomita - * Based on i8042.c written by Vojtech Pavlik - */ - -/* - * 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 - -MODULE_AUTHOR("Osamu Tomita "); -MODULE_DESCRIPTION("NEC PC-9801 keyboard controller driver"); -MODULE_LICENSE("GPL"); - -/* - * Names. - */ - -#define KBD98_PHYS_DESC "isa0041/serio0" - -/* - * IRQs. - */ - -#define KBD98_IRQ 1 - -/* - * Register numbers. - */ - -#define KBD98_COMMAND_REG 0x43 -#define KBD98_STATUS_REG 0x43 -#define KBD98_DATA_REG 0x41 - -spinlock_t kbd98io_lock = SPIN_LOCK_UNLOCKED; - -static struct serio kbd98_port; -extern struct pt_regs *kbd_pt_regs; - -static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs); - -/* - * kbd98_flush() flushes all data that may be in the keyboard buffers - */ - -static int kbd98_flush(void) -{ - unsigned long flags; - - spin_lock_irqsave(&kbd98io_lock, flags); - - while (inb(KBD98_STATUS_REG) & 0x02) /* RxRDY */ - inb(KBD98_DATA_REG); - - if (inb(KBD98_STATUS_REG) & 0x38) - printk("98kbd-io: Keyboard error!\n"); - - spin_unlock_irqrestore(&kbd98io_lock, flags); - - return 0; -} - -/* - * kbd98_write() sends a byte out through the keyboard interface. - */ - -static int kbd98_write(struct serio *port, unsigned char c) -{ - unsigned long flags; - - spin_lock_irqsave(&kbd98io_lock, flags); - - outb(0, 0x5f); /* wait */ - outb(0x17, KBD98_COMMAND_REG); /* enable send command */ - outb(0, 0x5f); /* wait */ - outb(c, KBD98_DATA_REG); - outb(0, 0x5f); /* wait */ - outb(0x16, KBD98_COMMAND_REG); /* disable send command */ - outb(0, 0x5f); /* wait */ - - spin_unlock_irqrestore(&kbd98io_lock, flags); - - return 0; -} - -/* - * kbd98_open() is called when a port is open by the higher layer. - * It allocates the interrupt and enables in in the chip. - */ - -static int kbd98_open(struct serio *port) -{ - kbd98_flush(); - - if (request_irq(KBD98_IRQ, kbd98io_interrupt, 0, "kbd98", NULL)) { - printk(KERN_ERR "98kbd-io.c: Can't get irq %d for %s, unregistering the port.\n", KBD98_IRQ, "KBD"); - serio_unregister_port(port); - return -1; - } - - return 0; -} - -static void kbd98_close(struct serio *port) -{ - free_irq(KBD98_IRQ, NULL); - - kbd98_flush(); -} - -/* - * Structures for registering the devices in the serio.c module. - */ - -static struct serio kbd98_port = -{ - .type = SERIO_PC9800, - .write = kbd98_write, - .open = kbd98_open, - .close = kbd98_close, - .driver = NULL, - .name = "PC-9801 Kbd Port", - .phys = KBD98_PHYS_DESC, -}; - -/* - * kbd98io_interrupt() is the most important function in this driver - - * it handles the interrupts from keyboard, and sends incoming bytes - * to the upper layers. - */ - -static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - unsigned char data; - - spin_lock_irqsave(&kbd98io_lock, flags); - - data = inb(KBD98_DATA_REG); - spin_unlock_irqrestore(&kbd98io_lock, flags); - serio_interrupt(&kbd98_port, data, 0, regs); - - return IRQ_HANDLED; -} - -int __init kbd98io_init(void) -{ - serio_register_port(&kbd98_port); - - printk(KERN_INFO "serio: PC-9801 %s port at %#lx,%#lx irq %d\n", - "KBD", - (unsigned long) KBD98_DATA_REG, - (unsigned long) KBD98_COMMAND_REG, - KBD98_IRQ); - - return 0; -} - -void __exit kbd98io_exit(void) -{ - serio_unregister_port(&kbd98_port); -} - -module_init(kbd98io_init); -module_exit(kbd98io_exit); diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig --- a/drivers/input/serio/Kconfig 2004-06-20 13:00:24 -07:00 +++ b/drivers/input/serio/Kconfig 2004-06-20 13:00:24 -07:00 @@ -97,16 +97,6 @@ tristate "Intel SA1111 keyboard controller" depends on SA1111 && SERIO -config SERIO_98KBD - tristate "NEC PC-9800 keyboard controller" - depends on X86_PC9800 && SERIO - help - Say Y here if you have the NEC PC-9801/PC-9821 and want to use its - standard keyboard connected to its keyboard controller. - - To compile this driver as a module, choose M here: the - module will be called 98kbd-io. - config SERIO_GSCPS2 tristate "HP GSC PS/2 keyboard and PS/2 mouse controller" depends on GSC && SERIO diff -Nru a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c --- a/drivers/input/serio/ambakmi.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/input/serio/ambakmi.c 2004-06-20 13:00:25 -07:00 @@ -18,17 +18,19 @@ #include #include #include +#include #include #include #include #include +#include #define KMI_BASE (kmi->base) struct amba_kmi_port { struct serio io; - struct amba_kmi_port *next; + struct clk *clk; unsigned char *base; unsigned int irq; unsigned int divisor; @@ -67,21 +69,38 @@ static int amba_kmi_open(struct serio *io) { struct amba_kmi_port *kmi = io->driver; + unsigned int divisor; int ret; - writeb(kmi->divisor, KMICLKDIV); + ret = clk_use(kmi->clk); + if (ret) + goto out; + + ret = clk_enable(kmi->clk); + if (ret) + goto clk_unuse; + + divisor = clk_get_rate(kmi->clk) / 8000000 - 1; + writeb(divisor, KMICLKDIV); writeb(KMICR_EN, KMICR); ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi); if (ret) { printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq); writeb(0, KMICR); - return ret; + goto clk_disable; } writeb(KMICR_EN | KMICR_RXINTREN, KMICR); return 0; + + clk_disable: + clk_disable(kmi->clk); + clk_unuse: + clk_unuse(kmi->clk); + out: + return ret; } static void amba_kmi_close(struct serio *io) @@ -91,6 +110,8 @@ writeb(0, KMICR); free_irq(kmi->irq, kmi); + clk_disable(kmi->clk); + clk_unuse(kmi->clk); } static int amba_kmi_probe(struct amba_device *dev, void *id) @@ -124,14 +145,20 @@ goto out; } - kmi->irq = dev->irq[0]; - kmi->divisor = 24 / 8 - 1; + kmi->clk = clk_get(&dev->dev, "KMIREFCLK"); + if (IS_ERR(kmi->clk)) { + ret = PTR_ERR(kmi->clk); + goto unmap; + } + kmi->irq = dev->irq[0]; amba_set_drvdata(dev, kmi); serio_register_port(&kmi->io); return 0; + unmap: + iounmap(kmi->base); out: kfree(kmi); amba_release_regions(dev); @@ -145,6 +172,7 @@ amba_set_drvdata(dev, NULL); serio_unregister_port(&kmi->io); + clk_put(kmi->clk); iounmap(kmi->base); kfree(kmi); amba_release_regions(dev); diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c --- a/drivers/input/tsdev.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/input/tsdev.c 2004-06-20 13:00:26 -07:00 @@ -151,7 +151,7 @@ return 0; } -static ssize_t tsdev_read(struct file *file, char *buffer, size_t count, +static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) { struct tsdev_list *list = file->private_data; diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig --- a/drivers/md/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/drivers/md/Kconfig 2004-06-20 13:00:23 -07:00 @@ -180,5 +180,25 @@ If unsure, say N. +config DM_SNAPSHOT + tristate "Snapshot target (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + Allow volume managers to take writeable snapshots of a device. + +config DM_MIRROR + tristate "Mirror target (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + Allow volume managers to mirror logical volumes, also + needed for live data migration tools such as 'pvmove'. + +config DM_ZERO + tristate "Zero target (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + A target that discards writes, and returns all zeroes for + reads. Useful in some recovery situations. + endmenu diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile --- a/drivers/md/Makefile 2004-06-20 13:00:24 -07:00 +++ b/drivers/md/Makefile 2004-06-20 13:00:24 -07:00 @@ -3,7 +3,9 @@ # dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ - dm-ioctl.o + dm-ioctl.o dm-io.o kcopyd.o +dm-snapshot-objs := dm-snap.o dm-exception-store.o +dm-mirror-objs := dm-log.o dm-raid1.o raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \ raid6int1.o raid6int2.o raid6int4.o \ raid6int8.o raid6int16.o raid6int32.o \ @@ -24,6 +26,9 @@ obj-$(CONFIG_BLK_DEV_MD) += md.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o +obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o +obj-$(CONFIG_DM_MIRROR) += dm-mirror.o +obj-$(CONFIG_DM_ZERO) += dm-zero.o quiet_cmd_unroll = UNROLL $@ cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \ diff -Nru a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-exception-store.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,648 @@ +/* + * dm-snapshot.c + * + * Copyright (C) 2001-2002 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" +#include "dm-snap.h" +#include "dm-io.h" +#include "kcopyd.h" + +#include +#include +#include +#include + +/*----------------------------------------------------------------- + * Persistent snapshots, by persistent we mean that the snapshot + * will survive a reboot. + *---------------------------------------------------------------*/ + +/* + * We need to store a record of which parts of the origin have + * been copied to the snapshot device. The snapshot code + * requires that we copy exception chunks to chunk aligned areas + * of the COW store. It makes sense therefore, to store the + * metadata in chunk size blocks. + * + * There is no backward or forward compatibility implemented, + * snapshots with different disk versions than the kernel will + * not be usable. It is expected that "lvcreate" will blank out + * the start of a fresh COW device before calling the snapshot + * constructor. + * + * The first chunk of the COW device just contains the header. + * After this there is a chunk filled with exception metadata, + * followed by as many exception chunks as can fit in the + * metadata areas. + * + * All on disk structures are in little-endian format. The end + * of the exceptions info is indicated by an exception with a + * new_chunk of 0, which is invalid since it would point to the + * header chunk. + */ + +/* + * Magic for persistent snapshots: "SnAp" - Feeble isn't it. + */ +#define SNAP_MAGIC 0x70416e53 + +/* + * The on-disk version of the metadata. + */ +#define SNAPSHOT_DISK_VERSION 1 + +struct disk_header { + uint32_t magic; + + /* + * Is this snapshot valid. There is no way of recovering + * an invalid snapshot. + */ + uint32_t valid; + + /* + * Simple, incrementing version. no backward + * compatibility. + */ + uint32_t version; + + /* In sectors */ + uint32_t chunk_size; +}; + +struct disk_exception { + uint64_t old_chunk; + uint64_t new_chunk; +}; + +struct commit_callback { + void (*callback)(void *, int success); + void *context; +}; + +/* + * The top level structure for a persistent exception store. + */ +struct pstore { + struct dm_snapshot *snap; /* up pointer to my snapshot */ + int version; + int valid; + uint32_t chunk_size; + uint32_t exceptions_per_area; + + /* + * Now that we have an asynchronous kcopyd there is no + * need for large chunk sizes, so it wont hurt to have a + * whole chunks worth of metadata in memory at once. + */ + void *area; + + /* + * Used to keep track of which metadata area the data in + * 'chunk' refers to. + */ + uint32_t current_area; + + /* + * The next free chunk for an exception. + */ + uint32_t next_free; + + /* + * The index of next free exception in the current + * metadata area. + */ + uint32_t current_committed; + + atomic_t pending_count; + uint32_t callback_count; + struct commit_callback *callbacks; +}; + +static inline unsigned int sectors_to_pages(unsigned int sectors) +{ + return sectors / (PAGE_SIZE >> 9); +} + +static int alloc_area(struct pstore *ps) +{ + int r = -ENOMEM; + size_t len; + + len = ps->chunk_size << SECTOR_SHIFT; + + /* + * Allocate the chunk_size block of memory that will hold + * a single metadata area. + */ + ps->area = vmalloc(len); + if (!ps->area) + return r; + + return 0; +} + +static void free_area(struct pstore *ps) +{ + vfree(ps->area); +} + +/* + * Read or write a chunk aligned and sized block of data from a device. + */ +static int chunk_io(struct pstore *ps, uint32_t chunk, int rw) +{ + struct io_region where; + unsigned long bits; + + where.bdev = ps->snap->cow->bdev; + where.sector = ps->chunk_size * chunk; + where.count = ps->chunk_size; + + return dm_io_sync_vm(1, &where, rw, ps->area, &bits); +} + +/* + * Read or write a metadata area. Remembering to skip the first + * chunk which holds the header. + */ +static int area_io(struct pstore *ps, uint32_t area, int rw) +{ + int r; + uint32_t chunk; + + /* convert a metadata area index to a chunk index */ + chunk = 1 + ((ps->exceptions_per_area + 1) * area); + + r = chunk_io(ps, chunk, rw); + if (r) + return r; + + ps->current_area = area; + return 0; +} + +static int zero_area(struct pstore *ps, uint32_t area) +{ + memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); + return area_io(ps, area, WRITE); +} + +static int read_header(struct pstore *ps, int *new_snapshot) +{ + int r; + struct disk_header *dh; + + r = chunk_io(ps, 0, READ); + if (r) + return r; + + dh = (struct disk_header *) ps->area; + + if (le32_to_cpu(dh->magic) == 0) { + *new_snapshot = 1; + + } else if (le32_to_cpu(dh->magic) == SNAP_MAGIC) { + *new_snapshot = 0; + ps->valid = le32_to_cpu(dh->valid); + ps->version = le32_to_cpu(dh->version); + ps->chunk_size = le32_to_cpu(dh->chunk_size); + + } else { + DMWARN("Invalid/corrupt snapshot"); + r = -ENXIO; + } + + return r; +} + +static int write_header(struct pstore *ps) +{ + struct disk_header *dh; + + memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); + + dh = (struct disk_header *) ps->area; + dh->magic = cpu_to_le32(SNAP_MAGIC); + dh->valid = cpu_to_le32(ps->valid); + dh->version = cpu_to_le32(ps->version); + dh->chunk_size = cpu_to_le32(ps->chunk_size); + + return chunk_io(ps, 0, WRITE); +} + +/* + * Access functions for the disk exceptions, these do the endian conversions. + */ +static struct disk_exception *get_exception(struct pstore *ps, uint32_t index) +{ + if (index >= ps->exceptions_per_area) + return NULL; + + return ((struct disk_exception *) ps->area) + index; +} + +static int read_exception(struct pstore *ps, + uint32_t index, struct disk_exception *result) +{ + struct disk_exception *e; + + e = get_exception(ps, index); + if (!e) + return -EINVAL; + + /* copy it */ + result->old_chunk = le64_to_cpu(e->old_chunk); + result->new_chunk = le64_to_cpu(e->new_chunk); + + return 0; +} + +static int write_exception(struct pstore *ps, + uint32_t index, struct disk_exception *de) +{ + struct disk_exception *e; + + e = get_exception(ps, index); + if (!e) + return -EINVAL; + + /* copy it */ + e->old_chunk = cpu_to_le64(de->old_chunk); + e->new_chunk = cpu_to_le64(de->new_chunk); + + return 0; +} + +/* + * Registers the exceptions that are present in the current area. + * 'full' is filled in to indicate if the area has been + * filled. + */ +static int insert_exceptions(struct pstore *ps, int *full) +{ + int r; + unsigned int i; + struct disk_exception de; + + /* presume the area is full */ + *full = 1; + + for (i = 0; i < ps->exceptions_per_area; i++) { + r = read_exception(ps, i, &de); + + if (r) + return r; + + /* + * If the new_chunk is pointing at the start of + * the COW device, where the first metadata area + * is we know that we've hit the end of the + * exceptions. Therefore the area is not full. + */ + if (de.new_chunk == 0LL) { + ps->current_committed = i; + *full = 0; + break; + } + + /* + * Keep track of the start of the free chunks. + */ + if (ps->next_free <= de.new_chunk) + ps->next_free = de.new_chunk + 1; + + /* + * Otherwise we add the exception to the snapshot. + */ + r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk); + if (r) + return r; + } + + return 0; +} + +static int read_exceptions(struct pstore *ps) +{ + uint32_t area; + int r, full = 1; + + /* + * Keeping reading chunks and inserting exceptions until + * we find a partially full area. + */ + for (area = 0; full; area++) { + r = area_io(ps, area, READ); + if (r) + return r; + + r = insert_exceptions(ps, &full); + if (r) + return r; + } + + return 0; +} + +static inline struct pstore *get_info(struct exception_store *store) +{ + return (struct pstore *) store->context; +} + +static void persistent_fraction_full(struct exception_store *store, + sector_t *numerator, sector_t *denominator) +{ + *numerator = get_info(store)->next_free * store->snap->chunk_size; + *denominator = get_dev_size(store->snap->cow->bdev); +} + +static void persistent_destroy(struct exception_store *store) +{ + struct pstore *ps = get_info(store); + + dm_io_put(sectors_to_pages(ps->chunk_size)); + vfree(ps->callbacks); + free_area(ps); + kfree(ps); +} + +static int persistent_read_metadata(struct exception_store *store) +{ + int r, new_snapshot; + struct pstore *ps = get_info(store); + + /* + * Read the snapshot header. + */ + r = read_header(ps, &new_snapshot); + if (r) + return r; + + /* + * Do we need to setup a new snapshot ? + */ + if (new_snapshot) { + r = write_header(ps); + if (r) { + DMWARN("write_header failed"); + return r; + } + + r = zero_area(ps, 0); + if (r) { + DMWARN("zero_area(0) failed"); + return r; + } + + } else { + /* + * Sanity checks. + */ + if (!ps->valid) { + DMWARN("snapshot is marked invalid"); + return -EINVAL; + } + + if (ps->version != SNAPSHOT_DISK_VERSION) { + DMWARN("unable to handle snapshot disk version %d", + ps->version); + return -EINVAL; + } + + /* + * Read the metadata. + */ + r = read_exceptions(ps); + if (r) + return r; + } + + return 0; +} + +static int persistent_prepare(struct exception_store *store, + struct exception *e) +{ + struct pstore *ps = get_info(store); + uint32_t stride; + sector_t size = get_dev_size(store->snap->cow->bdev); + + /* Is there enough room ? */ + if (size < ((ps->next_free + 1) * store->snap->chunk_size)) + return -ENOSPC; + + e->new_chunk = ps->next_free; + + /* + * Move onto the next free pending, making sure to take + * into account the location of the metadata chunks. + */ + stride = (ps->exceptions_per_area + 1); + if ((++ps->next_free % stride) == 1) + ps->next_free++; + + atomic_inc(&ps->pending_count); + return 0; +} + +static void persistent_commit(struct exception_store *store, + struct exception *e, + void (*callback) (void *, int success), + void *callback_context) +{ + int r; + unsigned int i; + struct pstore *ps = get_info(store); + struct disk_exception de; + struct commit_callback *cb; + + de.old_chunk = e->old_chunk; + de.new_chunk = e->new_chunk; + write_exception(ps, ps->current_committed++, &de); + + /* + * Add the callback to the back of the array. This code + * is the only place where the callback array is + * manipulated, and we know that it will never be called + * multiple times concurrently. + */ + cb = ps->callbacks + ps->callback_count++; + cb->callback = callback; + cb->context = callback_context; + + /* + * If there are no more exceptions in flight, or we have + * filled this metadata area we commit the exceptions to + * disk. + */ + if (atomic_dec_and_test(&ps->pending_count) || + (ps->current_committed == ps->exceptions_per_area)) { + r = area_io(ps, ps->current_area, WRITE); + if (r) + ps->valid = 0; + + for (i = 0; i < ps->callback_count; i++) { + cb = ps->callbacks + i; + cb->callback(cb->context, r == 0 ? 1 : 0); + } + + ps->callback_count = 0; + } + + /* + * Have we completely filled the current area ? + */ + if (ps->current_committed == ps->exceptions_per_area) { + ps->current_committed = 0; + r = zero_area(ps, ps->current_area + 1); + if (r) + ps->valid = 0; + } +} + +static void persistent_drop(struct exception_store *store) +{ + struct pstore *ps = get_info(store); + + ps->valid = 0; + if (write_header(ps)) + DMWARN("write header failed"); +} + +int dm_create_persistent(struct exception_store *store, uint32_t chunk_size) +{ + int r; + struct pstore *ps; + + r = dm_io_get(sectors_to_pages(chunk_size)); + if (r) + return r; + + /* allocate the pstore */ + ps = kmalloc(sizeof(*ps), GFP_KERNEL); + if (!ps) { + r = -ENOMEM; + goto bad; + } + + ps->snap = store->snap; + ps->valid = 1; + ps->version = SNAPSHOT_DISK_VERSION; + ps->chunk_size = chunk_size; + ps->exceptions_per_area = (chunk_size << SECTOR_SHIFT) / + sizeof(struct disk_exception); + ps->next_free = 2; /* skipping the header and first area */ + ps->current_committed = 0; + + r = alloc_area(ps); + if (r) + goto bad; + + /* + * Allocate space for all the callbacks. + */ + ps->callback_count = 0; + atomic_set(&ps->pending_count, 0); + ps->callbacks = dm_vcalloc(ps->exceptions_per_area, + sizeof(*ps->callbacks)); + + if (!ps->callbacks) { + r = -ENOMEM; + goto bad; + } + + store->destroy = persistent_destroy; + store->read_metadata = persistent_read_metadata; + store->prepare_exception = persistent_prepare; + store->commit_exception = persistent_commit; + store->drop_snapshot = persistent_drop; + store->fraction_full = persistent_fraction_full; + store->context = ps; + + return 0; + + bad: + dm_io_put(sectors_to_pages(chunk_size)); + if (ps) { + if (ps->area) + free_area(ps); + + kfree(ps); + } + return r; +} + +/*----------------------------------------------------------------- + * Implementation of the store for non-persistent snapshots. + *---------------------------------------------------------------*/ +struct transient_c { + sector_t next_free; +}; + +static void transient_destroy(struct exception_store *store) +{ + kfree(store->context); +} + +static int transient_read_metadata(struct exception_store *store) +{ + return 0; +} + +static int transient_prepare(struct exception_store *store, struct exception *e) +{ + struct transient_c *tc = (struct transient_c *) store->context; + sector_t size = get_dev_size(store->snap->cow->bdev); + + if (size < (tc->next_free + store->snap->chunk_size)) + return -1; + + e->new_chunk = sector_to_chunk(store->snap, tc->next_free); + tc->next_free += store->snap->chunk_size; + + return 0; +} + +static void transient_commit(struct exception_store *store, + struct exception *e, + void (*callback) (void *, int success), + void *callback_context) +{ + /* Just succeed */ + callback(callback_context, 1); +} + +static void transient_fraction_full(struct exception_store *store, + sector_t *numerator, sector_t *denominator) +{ + *numerator = ((struct transient_c *) store->context)->next_free; + *denominator = get_dev_size(store->snap->cow->bdev); +} + +int dm_create_transient(struct exception_store *store, + struct dm_snapshot *s, int blocksize) +{ + struct transient_c *tc; + + memset(store, 0, sizeof(*store)); + store->destroy = transient_destroy; + store->read_metadata = transient_read_metadata; + store->prepare_exception = transient_prepare; + store->commit_exception = transient_commit; + store->fraction_full = transient_fraction_full; + store->snap = s; + + tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); + if (!tc) + return -ENOMEM; + + tc->next_free = 0; + store->context = tc; + + return 0; +} diff -Nru a/drivers/md/dm-io.c b/drivers/md/dm-io.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-io.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,647 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the GPL. + */ + +#include "dm-io.h" + +#include +#include +#include +#include +#include + +#define BIO_POOL_SIZE 256 + + +/*----------------------------------------------------------------- + * Bio set, move this to bio.c + *---------------------------------------------------------------*/ +#define BV_NAME_SIZE 16 +struct biovec_pool { + int nr_vecs; + char name[BV_NAME_SIZE]; + kmem_cache_t *slab; + mempool_t *pool; + atomic_t allocated; /* FIXME: debug */ +}; + +#define BIOVEC_NR_POOLS 6 +struct bio_set { + char name[BV_NAME_SIZE]; + kmem_cache_t *bio_slab; + mempool_t *bio_pool; + struct biovec_pool pools[BIOVEC_NR_POOLS]; +}; + +static void bio_set_exit(struct bio_set *bs) +{ + unsigned i; + struct biovec_pool *bp; + + if (bs->bio_pool) + mempool_destroy(bs->bio_pool); + + if (bs->bio_slab) + kmem_cache_destroy(bs->bio_slab); + + for (i = 0; i < BIOVEC_NR_POOLS; i++) { + bp = bs->pools + i; + if (bp->pool) + mempool_destroy(bp->pool); + + if (bp->slab) + kmem_cache_destroy(bp->slab); + } +} + +static void mk_name(char *str, size_t len, const char *prefix, unsigned count) +{ + snprintf(str, len, "%s-%u", prefix, count); +} + +static int bio_set_init(struct bio_set *bs, const char *slab_prefix, + unsigned pool_entries, unsigned scale) +{ + /* FIXME: this must match bvec_index(), why not go the + * whole hog and have a pool per power of 2 ? */ + static unsigned _vec_lengths[BIOVEC_NR_POOLS] = { + 1, 4, 16, 64, 128, BIO_MAX_PAGES + }; + + + unsigned i, size; + struct biovec_pool *bp; + + /* zero the bs so we can tear down properly on error */ + memset(bs, 0, sizeof(*bs)); + + /* + * Set up the bio pool. + */ + snprintf(bs->name, sizeof(bs->name), "%s-bio", slab_prefix); + + bs->bio_slab = kmem_cache_create(bs->name, sizeof(struct bio), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!bs->bio_slab) { + DMWARN("can't init bio slab"); + goto bad; + } + + bs->bio_pool = mempool_create(pool_entries, mempool_alloc_slab, + mempool_free_slab, bs->bio_slab); + if (!bs->bio_pool) { + DMWARN("can't init bio pool"); + goto bad; + } + + /* + * Set up the biovec pools. + */ + for (i = 0; i < BIOVEC_NR_POOLS; i++) { + bp = bs->pools + i; + bp->nr_vecs = _vec_lengths[i]; + atomic_set(&bp->allocated, 1); /* FIXME: debug */ + + + size = bp->nr_vecs * sizeof(struct bio_vec); + + mk_name(bp->name, sizeof(bp->name), slab_prefix, i); + bp->slab = kmem_cache_create(bp->name, size, 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!bp->slab) { + DMWARN("can't init biovec slab cache"); + goto bad; + } + + if (i >= scale) + pool_entries >>= 1; + + bp->pool = mempool_create(pool_entries, mempool_alloc_slab, + mempool_free_slab, bp->slab); + if (!bp->pool) { + DMWARN("can't init biovec mempool"); + goto bad; + } + } + + return 0; + + bad: + bio_set_exit(bs); + return -ENOMEM; +} + +/* FIXME: blech */ +static inline unsigned bvec_index(unsigned nr) +{ + switch (nr) { + case 1: return 0; + case 2 ... 4: return 1; + case 5 ... 16: return 2; + case 17 ... 64: return 3; + case 65 ... 128:return 4; + case 129 ... BIO_MAX_PAGES: return 5; + } + + BUG(); + return 0; +} + +static inline void bs_bio_init(struct bio *bio) +{ + bio->bi_next = NULL; + bio->bi_flags = 1 << BIO_UPTODATE; + bio->bi_rw = 0; + bio->bi_vcnt = 0; + bio->bi_idx = 0; + bio->bi_phys_segments = 0; + bio->bi_hw_segments = 0; + bio->bi_size = 0; + bio->bi_max_vecs = 0; + bio->bi_end_io = NULL; + atomic_set(&bio->bi_cnt, 1); + bio->bi_private = NULL; +} + +static unsigned _bio_count = 0; +struct bio *bio_set_alloc(struct bio_set *bs, int gfp_mask, int nr_iovecs) +{ + struct biovec_pool *bp; + struct bio_vec *bv = NULL; + unsigned long idx; + struct bio *bio; + + bio = mempool_alloc(bs->bio_pool, gfp_mask); + if (unlikely(!bio)) + return NULL; + + bio_init(bio); + + if (likely(nr_iovecs)) { + idx = bvec_index(nr_iovecs); + bp = bs->pools + idx; + bv = mempool_alloc(bp->pool, gfp_mask); + if (!bv) { + mempool_free(bio, bs->bio_pool); + return NULL; + } + + memset(bv, 0, bp->nr_vecs * sizeof(*bv)); + bio->bi_flags |= idx << BIO_POOL_OFFSET; + bio->bi_max_vecs = bp->nr_vecs; + atomic_inc(&bp->allocated); + } + + bio->bi_io_vec = bv; + return bio; +} + +static void bio_set_free(struct bio_set *bs, struct bio *bio) +{ + struct biovec_pool *bp = bs->pools + BIO_POOL_IDX(bio); + + if (atomic_dec_and_test(&bp->allocated)) + BUG(); + + mempool_free(bio->bi_io_vec, bp->pool); + mempool_free(bio, bs->bio_pool); +} + +/*----------------------------------------------------------------- + * dm-io proper + *---------------------------------------------------------------*/ +static struct bio_set _bios; + +/* FIXME: can we shrink this ? */ +struct io { + unsigned long error; + atomic_t count; + struct task_struct *sleeper; + io_notify_fn callback; + void *context; +}; + +/* + * io contexts are only dynamically allocated for asynchronous + * io. Since async io is likely to be the majority of io we'll + * have the same number of io contexts as buffer heads ! (FIXME: + * must reduce this). + */ +static unsigned _num_ios; +static mempool_t *_io_pool; + +static void *alloc_io(int gfp_mask, void *pool_data) +{ + return kmalloc(sizeof(struct io), gfp_mask); +} + +static void free_io(void *element, void *pool_data) +{ + kfree(element); +} + +static unsigned int pages_to_ios(unsigned int pages) +{ + return 4 * pages; /* too many ? */ +} + +static int resize_pool(unsigned int new_ios) +{ + int r = 0; + + if (_io_pool) { + if (new_ios == 0) { + /* free off the pool */ + mempool_destroy(_io_pool); + _io_pool = NULL; + bio_set_exit(&_bios); + + } else { + /* resize the pool */ + r = mempool_resize(_io_pool, new_ios, GFP_KERNEL); + } + + } else { + /* create new pool */ + _io_pool = mempool_create(new_ios, alloc_io, free_io, NULL); + if (!_io_pool) + r = -ENOMEM; + + r = bio_set_init(&_bios, "dm-io", 512, 1); + if (r) { + mempool_destroy(_io_pool); + _io_pool = NULL; + } + } + + if (!r) + _num_ios = new_ios; + + return r; +} + +int dm_io_get(unsigned int num_pages) +{ + return resize_pool(_num_ios + pages_to_ios(num_pages)); +} + +void dm_io_put(unsigned int num_pages) +{ + resize_pool(_num_ios - pages_to_ios(num_pages)); +} + +/*----------------------------------------------------------------- + * We need to keep track of which region a bio is doing io for. + * In order to save a memory allocation we store this the last + * bvec which we know is unused (blech). + *---------------------------------------------------------------*/ +static inline void bio_set_region(struct bio *bio, unsigned region) +{ + bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region; +} + +static inline unsigned bio_get_region(struct bio *bio) +{ + return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len; +} + +/*----------------------------------------------------------------- + * We need an io object to keep track of the number of bios that + * have been dispatched for a particular io. + *---------------------------------------------------------------*/ +static void dec_count(struct io *io, unsigned int region, int error) +{ + if (error) + set_bit(region, &io->error); + + if (atomic_dec_and_test(&io->count)) { + if (io->sleeper) + wake_up_process(io->sleeper); + + else { + int r = io->error; + io_notify_fn fn = io->callback; + void *context = io->context; + + mempool_free(io, _io_pool); + fn(r, context); + } + } +} + +/* FIXME Move this to bio.h? */ +static void zero_fill_bio(struct bio *bio) +{ + unsigned long flags; + struct bio_vec *bv; + int i; + + bio_for_each_segment(bv, bio, i) { + char *data = bvec_kmap_irq(bv, &flags); + memset(data, 0, bv->bv_len); + flush_dcache_page(bv->bv_page); + bvec_kunmap_irq(data, &flags); + } +} + +static int endio(struct bio *bio, unsigned int done, int error) +{ + struct io *io = (struct io *) bio->bi_private; + + /* keep going until we've finished */ + if (bio->bi_size) + return 1; + + if (error && bio_data_dir(bio) == READ) + zero_fill_bio(bio); + + dec_count(io, bio_get_region(bio), error); + bio_put(bio); + + return 0; +} + +static void bio_dtr(struct bio *bio) +{ + _bio_count--; + bio_set_free(&_bios, bio); +} + +/*----------------------------------------------------------------- + * These little objects provide an abstraction for getting a new + * destination page for io. + *---------------------------------------------------------------*/ +struct dpages { + void (*get_page)(struct dpages *dp, + struct page **p, unsigned long *len, unsigned *offset); + void (*next_page)(struct dpages *dp); + + unsigned context_u; + void *context_ptr; +}; + +/* + * Functions for getting the pages from a list. + */ +static void list_get_page(struct dpages *dp, + struct page **p, unsigned long *len, unsigned *offset) +{ + unsigned o = dp->context_u; + struct page_list *pl = (struct page_list *) dp->context_ptr; + + *p = pl->page; + *len = PAGE_SIZE - o; + *offset = o; +} + +static void list_next_page(struct dpages *dp) +{ + struct page_list *pl = (struct page_list *) dp->context_ptr; + dp->context_ptr = pl->next; + dp->context_u = 0; +} + +static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offset) +{ + dp->get_page = list_get_page; + dp->next_page = list_next_page; + dp->context_u = offset; + dp->context_ptr = pl; +} + +/* + * Functions for getting the pages from a bvec. + */ +static void bvec_get_page(struct dpages *dp, + struct page **p, unsigned long *len, unsigned *offset) +{ + struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr; + *p = bvec->bv_page; + *len = bvec->bv_len; + *offset = bvec->bv_offset; +} + +static void bvec_next_page(struct dpages *dp) +{ + struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr; + dp->context_ptr = bvec + 1; +} + +static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec) +{ + dp->get_page = bvec_get_page; + dp->next_page = bvec_next_page; + dp->context_ptr = bvec; +} + +static void vm_get_page(struct dpages *dp, + struct page **p, unsigned long *len, unsigned *offset) +{ + *p = vmalloc_to_page(dp->context_ptr); + *offset = dp->context_u; + *len = PAGE_SIZE - dp->context_u; +} + +static void vm_next_page(struct dpages *dp) +{ + dp->context_ptr += PAGE_SIZE - dp->context_u; + dp->context_u = 0; +} + +static void vm_dp_init(struct dpages *dp, void *data) +{ + dp->get_page = vm_get_page; + dp->next_page = vm_next_page; + dp->context_u = ((unsigned long) data) & (PAGE_SIZE - 1); + dp->context_ptr = data; +} + +/*----------------------------------------------------------------- + * IO routines that accept a list of pages. + *---------------------------------------------------------------*/ +static void do_region(int rw, unsigned int region, struct io_region *where, + struct dpages *dp, struct io *io) +{ + struct bio *bio; + struct page *page; + unsigned long len; + unsigned offset; + unsigned num_bvecs; + sector_t remaining = where->count; + + while (remaining) { + /* + * Allocate a suitably sized bio, we add an extra + * bvec for bio_get/set_region(). + */ + num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2; + _bio_count++; + bio = bio_set_alloc(&_bios, GFP_NOIO, num_bvecs); + bio->bi_sector = where->sector + (where->count - remaining); + bio->bi_bdev = where->bdev; + bio->bi_end_io = endio; + bio->bi_private = io; + bio->bi_destructor = bio_dtr; + bio_set_region(bio, region); + + /* + * Try and add as many pages as possible. + */ + while (remaining) { + dp->get_page(dp, &page, &len, &offset); + len = min(len, to_bytes(remaining)); + if (!bio_add_page(bio, page, len, offset)) + break; + + offset = 0; + remaining -= to_sector(len); + dp->next_page(dp); + } + + atomic_inc(&io->count); + submit_bio(rw, bio); + } +} + +static void dispatch_io(int rw, unsigned int num_regions, + struct io_region *where, struct dpages *dp, + struct io *io, int sync) +{ + int i; + struct dpages old_pages = *dp; + + if (sync) + rw |= (1 << BIO_RW_SYNC); + + /* + * For multiple regions we need to be careful to rewind + * the dp object for each call to do_region. + */ + for (i = 0; i < num_regions; i++) { + *dp = old_pages; + if (where[i].count) + do_region(rw, i, where + i, dp, io); + } + + /* + * Drop the extra refence that we were holding to avoid + * the io being completed too early. + */ + dec_count(io, 0, 0); +} + +static int sync_io(unsigned int num_regions, struct io_region *where, + int rw, struct dpages *dp, unsigned long *error_bits) +{ + struct io io; + + if (num_regions > 1 && rw != WRITE) { + WARN_ON(1); + return -EIO; + } + + io.error = 0; + atomic_set(&io.count, 1); /* see dispatch_io() */ + io.sleeper = current; + + dispatch_io(rw, num_regions, where, dp, &io, 1); + + while (1) { + set_current_state(TASK_UNINTERRUPTIBLE); + + if (!atomic_read(&io.count) || signal_pending(current)) + break; + + io_schedule(); + } + set_current_state(TASK_RUNNING); + + if (atomic_read(&io.count)) + return -EINTR; + + *error_bits = io.error; + return io.error ? -EIO : 0; +} + +static int async_io(unsigned int num_regions, struct io_region *where, int rw, + struct dpages *dp, io_notify_fn fn, void *context) +{ + struct io *io; + + if (num_regions > 1 && rw != WRITE) { + WARN_ON(1); + fn(1, context); + return -EIO; + } + + io = mempool_alloc(_io_pool, GFP_NOIO); + io->error = 0; + atomic_set(&io->count, 1); /* see dispatch_io() */ + io->sleeper = NULL; + io->callback = fn; + io->context = context; + + dispatch_io(rw, num_regions, where, dp, io, 0); + return 0; +} + +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits) +{ + struct dpages dp; + list_dp_init(&dp, pl, offset); + return sync_io(num_regions, where, rw, &dp, error_bits); +} + +int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, unsigned long *error_bits) +{ + struct dpages dp; + bvec_dp_init(&dp, bvec); + return sync_io(num_regions, where, rw, &dp, error_bits); +} + +int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits) +{ + struct dpages dp; + vm_dp_init(&dp, data); + return sync_io(num_regions, where, rw, &dp, error_bits); +} + +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context) +{ + struct dpages dp; + list_dp_init(&dp, pl, offset); + return async_io(num_regions, where, rw, &dp, fn, context); +} + +int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, io_notify_fn fn, void *context) +{ + struct dpages dp; + bvec_dp_init(&dp, bvec); + return async_io(num_regions, where, rw, &dp, fn, context); +} + +int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context) +{ + struct dpages dp; + vm_dp_init(&dp, data); + return async_io(num_regions, where, rw, &dp, fn, context); +} + +EXPORT_SYMBOL(dm_io_get); +EXPORT_SYMBOL(dm_io_put); +EXPORT_SYMBOL(dm_io_sync); +EXPORT_SYMBOL(dm_io_async); +EXPORT_SYMBOL(dm_io_sync_bvec); +EXPORT_SYMBOL(dm_io_async_bvec); +EXPORT_SYMBOL(dm_io_sync_vm); +EXPORT_SYMBOL(dm_io_async_vm); diff -Nru a/drivers/md/dm-io.h b/drivers/md/dm-io.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-io.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the GPL. + */ + +#ifndef _DM_IO_H +#define _DM_IO_H + +#include "dm.h" + +/* FIXME make this configurable */ +#define DM_MAX_IO_REGIONS 8 + +struct io_region { + struct block_device *bdev; + sector_t sector; + sector_t count; +}; + +struct page_list { + struct page_list *next; + struct page *page; +}; + + +/* + * 'error' is a bitset, with each bit indicating whether an error + * occurred doing io to the corresponding region. + */ +typedef void (*io_notify_fn)(unsigned long error, void *context); + + +/* + * Before anyone uses the IO interface they should call + * dm_io_get(), specifying roughly how many pages they are + * expecting to perform io on concurrently. + * + * This function may block. + */ +int dm_io_get(unsigned int num_pages); +void dm_io_put(unsigned int num_pages); + +/* + * Synchronous IO. + * + * Please ensure that the rw flag in the next two functions is + * either READ or WRITE, ie. we don't take READA. Any + * regions with a zero count field will be ignored. + */ +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits); + +int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, unsigned long *error_bits); + +int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits); + +/* + * Aynchronous IO. + * + * The 'where' array may be safely allocated on the stack since + * the function takes a copy. + */ +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context); + +int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, io_notify_fn fn, void *context); + +int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context); + +#endif diff -Nru a/drivers/md/dm-log.c b/drivers/md/dm-log.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-log.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#include +#include +#include +#include + +#include "dm-log.h" +#include "dm-io.h" + +static LIST_HEAD(_log_types); +static spinlock_t _lock = SPIN_LOCK_UNLOCKED; + +int dm_register_dirty_log_type(struct dirty_log_type *type) +{ + if (!try_module_get(type->module)) + return -EINVAL; + + spin_lock(&_lock); + type->use_count = 0; + list_add(&type->list, &_log_types); + spin_unlock(&_lock); + + return 0; +} + +int dm_unregister_dirty_log_type(struct dirty_log_type *type) +{ + spin_lock(&_lock); + + if (type->use_count) + DMWARN("Attempt to unregister a log type that is still in use"); + else { + list_del(&type->list); + module_put(type->module); + } + + spin_unlock(&_lock); + + return 0; +} + +static struct dirty_log_type *get_type(const char *type_name) +{ + struct dirty_log_type *type; + + spin_lock(&_lock); + list_for_each_entry (type, &_log_types, list) + if (!strcmp(type_name, type->name)) { + type->use_count++; + spin_unlock(&_lock); + return type; + } + + spin_unlock(&_lock); + return NULL; +} + +static void put_type(struct dirty_log_type *type) +{ + spin_lock(&_lock); + type->use_count--; + spin_unlock(&_lock); +} + +struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti, + unsigned int argc, char **argv) +{ + struct dirty_log_type *type; + struct dirty_log *log; + + log = kmalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return NULL; + + type = get_type(type_name); + if (!type) { + kfree(log); + return NULL; + } + + log->type = type; + if (type->ctr(log, ti, argc, argv)) { + kfree(log); + put_type(type); + return NULL; + } + + return log; +} + +void dm_destroy_dirty_log(struct dirty_log *log) +{ + log->type->dtr(log); + put_type(log->type); + kfree(log); +} + +/*----------------------------------------------------------------- + * Persistent and core logs share a lot of their implementation. + * FIXME: need a reload method to be called from a resume + *---------------------------------------------------------------*/ +/* + * Magic for persistent mirrors: "MiRr" + */ +#define MIRROR_MAGIC 0x4D695272 + +/* + * The on-disk version of the metadata. + */ +#define MIRROR_DISK_VERSION 1 +#define LOG_OFFSET 2 + +struct log_header { + uint32_t magic; + + /* + * Simple, incrementing version. no backward + * compatibility. + */ + uint32_t version; + sector_t nr_regions; +}; + +struct log_c { + struct dm_target *ti; + int touched; + sector_t region_size; + unsigned int region_count; + region_t sync_count; + + unsigned bitset_uint32_count; + uint32_t *clean_bits; + uint32_t *sync_bits; + uint32_t *recovering_bits; /* FIXME: this seems excessive */ + + int sync_search; + + /* + * Disk log fields + */ + struct dm_dev *log_dev; + struct log_header header; + + struct io_region header_location; + struct log_header *disk_header; + + struct io_region bits_location; + uint32_t *disk_bits; +}; + +/* + * The touched member needs to be updated every time we access + * one of the bitsets. + */ +static inline int log_test_bit(uint32_t *bs, unsigned bit) +{ + return test_bit(bit, (unsigned long *) bs) ? 1 : 0; +} + +static inline void log_set_bit(struct log_c *l, + uint32_t *bs, unsigned bit) +{ + set_bit(bit, (unsigned long *) bs); + l->touched = 1; +} + +static inline void log_clear_bit(struct log_c *l, + uint32_t *bs, unsigned bit) +{ + clear_bit(bit, (unsigned long *) bs); + l->touched = 1; +} + +/*---------------------------------------------------------------- + * Header IO + *--------------------------------------------------------------*/ +static void header_to_disk(struct log_header *core, struct log_header *disk) +{ + disk->magic = cpu_to_le32(core->magic); + disk->version = cpu_to_le32(core->version); + disk->nr_regions = cpu_to_le64(core->nr_regions); +} + +static void header_from_disk(struct log_header *core, struct log_header *disk) +{ + core->magic = le32_to_cpu(disk->magic); + core->version = le32_to_cpu(disk->version); + core->nr_regions = le64_to_cpu(disk->nr_regions); +} + +static int read_header(struct log_c *log) +{ + int r; + unsigned long ebits; + + r = dm_io_sync_vm(1, &log->header_location, READ, + log->disk_header, &ebits); + if (r) + return r; + + header_from_disk(&log->header, log->disk_header); + + if (log->header.magic != MIRROR_MAGIC) { + log->header.magic = MIRROR_MAGIC; + log->header.version = MIRROR_DISK_VERSION; + log->header.nr_regions = 0; + } + + if (log->header.version != MIRROR_DISK_VERSION) { + DMWARN("incompatible disk log version"); + return -EINVAL; + } + + return 0; +} + +static inline int write_header(struct log_c *log) +{ + unsigned long ebits; + + header_to_disk(&log->header, log->disk_header); + return dm_io_sync_vm(1, &log->header_location, WRITE, + log->disk_header, &ebits); +} + +/*---------------------------------------------------------------- + * Bits IO + *--------------------------------------------------------------*/ +static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count) +{ + unsigned i; + + for (i = 0; i < count; i++) + core[i] = le32_to_cpu(disk[i]); +} + +static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count) +{ + unsigned i; + + /* copy across the clean/dirty bitset */ + for (i = 0; i < count; i++) + disk[i] = cpu_to_le32(core[i]); +} + +static int read_bits(struct log_c *log) +{ + int r; + unsigned long ebits; + + r = dm_io_sync_vm(1, &log->bits_location, READ, + log->disk_bits, &ebits); + if (r) + return r; + + bits_to_core(log->clean_bits, log->disk_bits, + log->bitset_uint32_count); + return 0; +} + +static int write_bits(struct log_c *log) +{ + unsigned long ebits; + bits_to_disk(log->clean_bits, log->disk_bits, + log->bitset_uint32_count); + return dm_io_sync_vm(1, &log->bits_location, WRITE, + log->disk_bits, &ebits); +} + +/*---------------------------------------------------------------- + * constructor/destructor + *--------------------------------------------------------------*/ +#define BYTE_SHIFT 3 +static int core_ctr(struct dirty_log *log, struct dm_target *ti, + unsigned int argc, char **argv) +{ + struct log_c *lc; + sector_t region_size; + unsigned int region_count; + size_t bitset_size; + + if (argc != 1) { + DMWARN("wrong number of arguments to log_c"); + return -EINVAL; + } + + if (sscanf(argv[0], SECTOR_FORMAT, ®ion_size) != 1) { + DMWARN("invalid region size string"); + return -EINVAL; + } + + region_count = dm_div_up(ti->len, region_size); + + lc = kmalloc(sizeof(*lc), GFP_KERNEL); + if (!lc) { + DMWARN("couldn't allocate core log"); + return -ENOMEM; + } + + lc->ti = ti; + lc->touched = 0; + lc->region_size = region_size; + lc->region_count = region_count; + + /* + * Work out how many words we need to hold the bitset. + */ + bitset_size = dm_round_up(region_count, + sizeof(*lc->clean_bits) << BYTE_SHIFT); + bitset_size >>= BYTE_SHIFT; + + lc->bitset_uint32_count = bitset_size / 4; + lc->clean_bits = vmalloc(bitset_size); + if (!lc->clean_bits) { + DMWARN("couldn't allocate clean bitset"); + kfree(lc); + return -ENOMEM; + } + memset(lc->clean_bits, -1, bitset_size); + + lc->sync_bits = vmalloc(bitset_size); + if (!lc->sync_bits) { + DMWARN("couldn't allocate sync bitset"); + vfree(lc->clean_bits); + kfree(lc); + return -ENOMEM; + } + memset(lc->sync_bits, 0, bitset_size); + lc->sync_count = 0; + + lc->recovering_bits = vmalloc(bitset_size); + if (!lc->recovering_bits) { + DMWARN("couldn't allocate sync bitset"); + vfree(lc->sync_bits); + vfree(lc->clean_bits); + kfree(lc); + return -ENOMEM; + } + memset(lc->recovering_bits, 0, bitset_size); + lc->sync_search = 0; + log->context = lc; + return 0; +} + +static void core_dtr(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + vfree(lc->clean_bits); + vfree(lc->sync_bits); + vfree(lc->recovering_bits); + kfree(lc); +} + +static int disk_ctr(struct dirty_log *log, struct dm_target *ti, + unsigned int argc, char **argv) +{ + int r; + size_t size; + struct log_c *lc; + struct dm_dev *dev; + + if (argc != 2) { + DMWARN("wrong number of arguments to log_d"); + return -EINVAL; + } + + r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */, + FMODE_READ | FMODE_WRITE, &dev); + if (r) + return r; + + r = core_ctr(log, ti, argc - 1, argv + 1); + if (r) { + dm_put_device(ti, dev); + return r; + } + + lc = (struct log_c *) log->context; + lc->log_dev = dev; + + /* setup the disk header fields */ + lc->header_location.bdev = lc->log_dev->bdev; + lc->header_location.sector = 0; + lc->header_location.count = 1; + + /* + * We can't read less than this amount, even though we'll + * not be using most of this space. + */ + lc->disk_header = vmalloc(1 << SECTOR_SHIFT); + if (!lc->disk_header) + goto bad; + + /* setup the disk bitset fields */ + lc->bits_location.bdev = lc->log_dev->bdev; + lc->bits_location.sector = LOG_OFFSET; + + size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), + 1 << SECTOR_SHIFT); + lc->bits_location.count = size >> SECTOR_SHIFT; + lc->disk_bits = vmalloc(size); + if (!lc->disk_bits) { + vfree(lc->disk_header); + goto bad; + } + return 0; + + bad: + dm_put_device(ti, lc->log_dev); + core_dtr(log); + return -ENOMEM; +} + +static void disk_dtr(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + dm_put_device(lc->ti, lc->log_dev); + vfree(lc->disk_header); + vfree(lc->disk_bits); + core_dtr(log); +} + +static int count_bits32(uint32_t *addr, unsigned size) +{ + int count = 0, i; + + for (i = 0; i < size; i++) { + count += hweight32(*(addr+i)); + } + return count; +} + +static int disk_resume(struct dirty_log *log) +{ + int r; + unsigned i; + struct log_c *lc = (struct log_c *) log->context; + size_t size = lc->bitset_uint32_count * sizeof(uint32_t); + + /* read the disk header */ + r = read_header(lc); + if (r) + return r; + + /* read the bits */ + r = read_bits(lc); + if (r) + return r; + + /* zero any new bits if the mirror has grown */ + for (i = lc->header.nr_regions; i < lc->region_count; i++) + /* FIXME: amazingly inefficient */ + log_clear_bit(lc, lc->clean_bits, i); + + /* copy clean across to sync */ + memcpy(lc->sync_bits, lc->clean_bits, size); + lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count); + + /* write the bits */ + r = write_bits(lc); + if (r) + return r; + + /* set the correct number of regions in the header */ + lc->header.nr_regions = lc->region_count; + + /* write the new header */ + return write_header(lc); +} + +static sector_t core_get_region_size(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + return lc->region_size; +} + +static int core_is_clean(struct dirty_log *log, region_t region) +{ + struct log_c *lc = (struct log_c *) log->context; + return log_test_bit(lc->clean_bits, region); +} + +static int core_in_sync(struct dirty_log *log, region_t region, int block) +{ + struct log_c *lc = (struct log_c *) log->context; + return log_test_bit(lc->sync_bits, region); +} + +static int core_flush(struct dirty_log *log) +{ + /* no op */ + return 0; +} + +static int disk_flush(struct dirty_log *log) +{ + int r; + struct log_c *lc = (struct log_c *) log->context; + + /* only write if the log has changed */ + if (!lc->touched) + return 0; + + r = write_bits(lc); + if (!r) + lc->touched = 0; + + return r; +} + +static void core_mark_region(struct dirty_log *log, region_t region) +{ + struct log_c *lc = (struct log_c *) log->context; + log_clear_bit(lc, lc->clean_bits, region); +} + +static void core_clear_region(struct dirty_log *log, region_t region) +{ + struct log_c *lc = (struct log_c *) log->context; + log_set_bit(lc, lc->clean_bits, region); +} + +static int core_get_resync_work(struct dirty_log *log, region_t *region) +{ + struct log_c *lc = (struct log_c *) log->context; + + if (lc->sync_search >= lc->region_count) + return 0; + + do { + *region = find_next_zero_bit((unsigned long *) lc->sync_bits, + lc->region_count, + lc->sync_search); + lc->sync_search = *region + 1; + + if (*region == lc->region_count) + return 0; + + } while (log_test_bit(lc->recovering_bits, *region)); + + log_set_bit(lc, lc->recovering_bits, *region); + return 1; +} + +static void core_complete_resync_work(struct dirty_log *log, region_t region, + int success) +{ + struct log_c *lc = (struct log_c *) log->context; + + log_clear_bit(lc, lc->recovering_bits, region); + if (success) { + log_set_bit(lc, lc->sync_bits, region); + lc->sync_count++; + } +} + +static region_t core_get_sync_count(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + + return lc->sync_count; +} + +static struct dirty_log_type _core_type = { + .name = "core", + .module = THIS_MODULE, + .ctr = core_ctr, + .dtr = core_dtr, + .get_region_size = core_get_region_size, + .is_clean = core_is_clean, + .in_sync = core_in_sync, + .flush = core_flush, + .mark_region = core_mark_region, + .clear_region = core_clear_region, + .get_resync_work = core_get_resync_work, + .complete_resync_work = core_complete_resync_work, + .get_sync_count = core_get_sync_count +}; + +static struct dirty_log_type _disk_type = { + .name = "disk", + .module = THIS_MODULE, + .ctr = disk_ctr, + .dtr = disk_dtr, + .suspend = disk_flush, + .resume = disk_resume, + .get_region_size = core_get_region_size, + .is_clean = core_is_clean, + .in_sync = core_in_sync, + .flush = disk_flush, + .mark_region = core_mark_region, + .clear_region = core_clear_region, + .get_resync_work = core_get_resync_work, + .complete_resync_work = core_complete_resync_work, + .get_sync_count = core_get_sync_count +}; + +int __init dm_dirty_log_init(void) +{ + int r; + + r = dm_register_dirty_log_type(&_core_type); + if (r) + DMWARN("couldn't register core log"); + + r = dm_register_dirty_log_type(&_disk_type); + if (r) { + DMWARN("couldn't register disk type"); + dm_unregister_dirty_log_type(&_core_type); + } + + return r; +} + +void dm_dirty_log_exit(void) +{ + dm_unregister_dirty_log_type(&_disk_type); + dm_unregister_dirty_log_type(&_core_type); +} + +EXPORT_SYMBOL(dm_register_dirty_log_type); +EXPORT_SYMBOL(dm_unregister_dirty_log_type); +EXPORT_SYMBOL(dm_create_dirty_log); +EXPORT_SYMBOL(dm_destroy_dirty_log); diff -Nru a/drivers/md/dm-log.h b/drivers/md/dm-log.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-log.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#ifndef DM_DIRTY_LOG +#define DM_DIRTY_LOG + +#include "dm.h" + +typedef sector_t region_t; + +struct dirty_log_type; + +struct dirty_log { + struct dirty_log_type *type; + void *context; +}; + +struct dirty_log_type { + struct list_head list; + const char *name; + struct module *module; + unsigned int use_count; + + int (*ctr)(struct dirty_log *log, struct dm_target *ti, + unsigned int argc, char **argv); + void (*dtr)(struct dirty_log *log); + + /* + * There are times when we don't want the log to touch + * the disk. + */ + int (*suspend)(struct dirty_log *log); + int (*resume)(struct dirty_log *log); + + /* + * Retrieves the smallest size of region that the log can + * deal with. + */ + sector_t (*get_region_size)(struct dirty_log *log); + + /* + * A predicate to say whether a region is clean or not. + * May block. + */ + int (*is_clean)(struct dirty_log *log, region_t region); + + /* + * Returns: 0, 1, -EWOULDBLOCK, < 0 + * + * A predicate function to check the area given by + * [sector, sector + len) is in sync. + * + * If -EWOULDBLOCK is returned the state of the region is + * unknown, typically this will result in a read being + * passed to a daemon to deal with, since a daemon is + * allowed to block. + */ + int (*in_sync)(struct dirty_log *log, region_t region, int can_block); + + /* + * Flush the current log state (eg, to disk). This + * function may block. + */ + int (*flush)(struct dirty_log *log); + + /* + * Mark an area as clean or dirty. These functions may + * block, though for performance reasons blocking should + * be extremely rare (eg, allocating another chunk of + * memory for some reason). + */ + void (*mark_region)(struct dirty_log *log, region_t region); + void (*clear_region)(struct dirty_log *log, region_t region); + + /* + * Returns: <0 (error), 0 (no region), 1 (region) + * + * The mirrord will need perform recovery on regions of + * the mirror that are in the NOSYNC state. This + * function asks the log to tell the caller about the + * next region that this machine should recover. + * + * Do not confuse this function with 'in_sync()', one + * tells you if an area is synchronised, the other + * assigns recovery work. + */ + int (*get_resync_work)(struct dirty_log *log, region_t *region); + + /* + * This notifies the log that the resync of an area has + * been completed. The log should then mark this region + * as CLEAN. + */ + void (*complete_resync_work)(struct dirty_log *log, + region_t region, int success); + + /* + * Returns the number of regions that are in sync. + */ + region_t (*get_sync_count)(struct dirty_log *log); +}; + +int dm_register_dirty_log_type(struct dirty_log_type *type); +int dm_unregister_dirty_log_type(struct dirty_log_type *type); + + +/* + * Make sure you use these two functions, rather than calling + * type->constructor/destructor() directly. + */ +struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti, + unsigned int argc, char **argv); +void dm_destroy_dirty_log(struct dirty_log *log); + +/* + * init/exit functions. + */ +int dm_dirty_log_init(void); +void dm_dirty_log_exit(void); + +#endif diff -Nru a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-raid1.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1278 @@ +/* + * Copyright (C) 2003 Sistina Software Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" +#include "dm-bio-list.h" +#include "dm-io.h" +#include "dm-log.h" +#include "kcopyd.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct workqueue_struct *_kmirrord_wq; +static struct work_struct _kmirrord_work; + +static inline void wake(void) +{ + queue_work(_kmirrord_wq, &_kmirrord_work); +} + +/*----------------------------------------------------------------- + * Region hash + * + * The mirror splits itself up into discrete regions. Each + * region can be in one of three states: clean, dirty, + * nosync. There is no need to put clean regions in the hash. + * + * In addition to being present in the hash table a region _may_ + * be present on one of three lists. + * + * clean_regions: Regions on this list have no io pending to + * them, they are in sync, we are no longer interested in them, + * they are dull. rh_update_states() will remove them from the + * hash table. + * + * quiesced_regions: These regions have been spun down, ready + * for recovery. rh_recovery_start() will remove regions from + * this list and hand them to kmirrord, which will schedule the + * recovery io with kcopyd. + * + * recovered_regions: Regions that kcopyd has successfully + * recovered. rh_update_states() will now schedule any delayed + * io, up the recovery_count, and remove the region from the + * hash. + * + * There are 2 locks: + * A rw spin lock 'hash_lock' protects just the hash table, + * this is never held in write mode from interrupt context, + * which I believe means that we only have to disable irqs when + * doing a write lock. + * + * An ordinary spin lock 'region_lock' that protects the three + * lists in the region_hash, with the 'state', 'list' and + * 'bhs_delayed' fields of the regions. This is used from irq + * context, so all other uses will have to suspend local irqs. + *---------------------------------------------------------------*/ +struct mirror_set; +struct region_hash { + struct mirror_set *ms; + sector_t region_size; + unsigned region_shift; + + /* holds persistent region state */ + struct dirty_log *log; + + /* hash table */ + rwlock_t hash_lock; + mempool_t *region_pool; + unsigned int mask; + unsigned int nr_buckets; + struct list_head *buckets; + + spinlock_t region_lock; + struct semaphore recovery_count; + struct list_head clean_regions; + struct list_head quiesced_regions; + struct list_head recovered_regions; +}; + +enum { + RH_CLEAN, + RH_DIRTY, + RH_NOSYNC, + RH_RECOVERING +}; + +struct region { + struct region_hash *rh; /* FIXME: can we get rid of this ? */ + region_t key; + int state; + + struct list_head hash_list; + struct list_head list; + + atomic_t pending; + struct bio_list delayed_bios; +}; + +/* + * Conversion fns + */ +static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) +{ + return bio->bi_sector >> rh->region_shift; +} + +static inline sector_t region_to_sector(struct region_hash *rh, region_t region) +{ + return region << rh->region_shift; +} + +/* FIXME move this */ +static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); + +static void *region_alloc(int gfp_mask, void *pool_data) +{ + return kmalloc(sizeof(struct region), gfp_mask); +} + +static void region_free(void *element, void *pool_data) +{ + kfree(element); +} + +#define MIN_REGIONS 64 +#define MAX_RECOVERY 1 +static int rh_init(struct region_hash *rh, struct mirror_set *ms, + struct dirty_log *log, sector_t region_size, + region_t nr_regions) +{ + unsigned int nr_buckets, max_buckets; + size_t i; + + /* + * Calculate a suitable number of buckets for our hash + * table. + */ + max_buckets = nr_regions >> 6; + for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1) + ; + nr_buckets >>= 1; + + rh->ms = ms; + rh->log = log; + rh->region_size = region_size; + rh->region_shift = ffs(region_size) - 1; + rwlock_init(&rh->hash_lock); + rh->mask = nr_buckets - 1; + rh->nr_buckets = nr_buckets; + + rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets)); + if (!rh->buckets) { + DMERR("unable to allocate region hash memory"); + return -ENOMEM; + } + + for (i = 0; i < nr_buckets; i++) + INIT_LIST_HEAD(rh->buckets + i); + + spin_lock_init(&rh->region_lock); + sema_init(&rh->recovery_count, 0); + INIT_LIST_HEAD(&rh->clean_regions); + INIT_LIST_HEAD(&rh->quiesced_regions); + INIT_LIST_HEAD(&rh->recovered_regions); + + rh->region_pool = mempool_create(MIN_REGIONS, region_alloc, + region_free, NULL); + if (!rh->region_pool) { + vfree(rh->buckets); + rh->buckets = NULL; + return -ENOMEM; + } + + return 0; +} + +static void rh_exit(struct region_hash *rh) +{ + unsigned int h; + struct region *reg, *nreg; + + BUG_ON(!list_empty(&rh->quiesced_regions)); + for (h = 0; h < rh->nr_buckets; h++) { + list_for_each_entry_safe(reg, nreg, rh->buckets + h, hash_list) { + BUG_ON(atomic_read(®->pending)); + mempool_free(reg, rh->region_pool); + } + } + + if (rh->log) + dm_destroy_dirty_log(rh->log); + if (rh->region_pool) + mempool_destroy(rh->region_pool); + vfree(rh->buckets); +} + +#define RH_HASH_MULT 2654435387U + +static inline unsigned int rh_hash(struct region_hash *rh, region_t region) +{ + return (unsigned int) ((region * RH_HASH_MULT) >> 12) & rh->mask; +} + +static struct region *__rh_lookup(struct region_hash *rh, region_t region) +{ + struct region *reg; + + list_for_each_entry (reg, rh->buckets + rh_hash(rh, region), hash_list) + if (reg->key == region) + return reg; + + return NULL; +} + +static void __rh_insert(struct region_hash *rh, struct region *reg) +{ + unsigned int h = rh_hash(rh, reg->key); + list_add(®->hash_list, rh->buckets + h); +} + +static struct region *__rh_alloc(struct region_hash *rh, region_t region) +{ + struct region *reg, *nreg; + + read_unlock(&rh->hash_lock); + nreg = mempool_alloc(rh->region_pool, GFP_NOIO); + nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? + RH_CLEAN : RH_NOSYNC; + nreg->rh = rh; + nreg->key = region; + + INIT_LIST_HEAD(&nreg->list); + + atomic_set(&nreg->pending, 0); + bio_list_init(&nreg->delayed_bios); + write_lock_irq(&rh->hash_lock); + + reg = __rh_lookup(rh, region); + if (reg) + /* we lost the race */ + mempool_free(nreg, rh->region_pool); + + else { + __rh_insert(rh, nreg); + if (nreg->state == RH_CLEAN) { + spin_lock_irq(&rh->region_lock); + list_add(&nreg->list, &rh->clean_regions); + spin_unlock_irq(&rh->region_lock); + } + reg = nreg; + } + write_unlock_irq(&rh->hash_lock); + read_lock(&rh->hash_lock); + + return reg; +} + +static inline struct region *__rh_find(struct region_hash *rh, region_t region) +{ + struct region *reg; + + reg = __rh_lookup(rh, region); + if (!reg) + reg = __rh_alloc(rh, region); + + return reg; +} + +static int rh_state(struct region_hash *rh, region_t region, int may_block) +{ + int r; + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + if (reg) + return reg->state; + + /* + * The region wasn't in the hash, so we fall back to the + * dirty log. + */ + r = rh->log->type->in_sync(rh->log, region, may_block); + + /* + * Any error from the dirty log (eg. -EWOULDBLOCK) gets + * taken as a RH_NOSYNC + */ + return r == 1 ? RH_CLEAN : RH_NOSYNC; +} + +static inline int rh_in_sync(struct region_hash *rh, + region_t region, int may_block) +{ + int state = rh_state(rh, region, may_block); + return state == RH_CLEAN || state == RH_DIRTY; +} + +static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list) +{ + struct bio *bio; + + while ((bio = bio_list_pop(bio_list))) { + queue_bio(ms, bio, WRITE); + } +} + +static void rh_update_states(struct region_hash *rh) +{ + struct region *reg, *next; + + LIST_HEAD(clean); + LIST_HEAD(recovered); + + /* + * Quickly grab the lists. + */ + write_lock_irq(&rh->hash_lock); + spin_lock(&rh->region_lock); + if (!list_empty(&rh->clean_regions)) { + list_splice(&rh->clean_regions, &clean); + INIT_LIST_HEAD(&rh->clean_regions); + + list_for_each_entry (reg, &clean, list) { + rh->log->type->clear_region(rh->log, reg->key); + list_del(®->hash_list); + } + } + + if (!list_empty(&rh->recovered_regions)) { + list_splice(&rh->recovered_regions, &recovered); + INIT_LIST_HEAD(&rh->recovered_regions); + + list_for_each_entry (reg, &recovered, list) + list_del(®->hash_list); + } + spin_unlock(&rh->region_lock); + write_unlock_irq(&rh->hash_lock); + + /* + * All the regions on the recovered and clean lists have + * now been pulled out of the system, so no need to do + * any more locking. + */ + list_for_each_entry_safe (reg, next, &recovered, list) { + rh->log->type->clear_region(rh->log, reg->key); + rh->log->type->complete_resync_work(rh->log, reg->key, 1); + dispatch_bios(rh->ms, ®->delayed_bios); + up(&rh->recovery_count); + mempool_free(reg, rh->region_pool); + } + + if (!list_empty(&recovered)) + rh->log->type->flush(rh->log); + + list_for_each_entry_safe (reg, next, &clean, list) + mempool_free(reg, rh->region_pool); +} + +static void rh_inc(struct region_hash *rh, region_t region) +{ + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + if (reg->state == RH_CLEAN) { + rh->log->type->mark_region(rh->log, reg->key); + + spin_lock_irq(&rh->region_lock); + reg->state = RH_DIRTY; + list_del_init(®->list); /* take off the clean list */ + spin_unlock_irq(&rh->region_lock); + } + + atomic_inc(®->pending); + read_unlock(&rh->hash_lock); +} + +static void rh_inc_pending(struct region_hash *rh, struct bio_list *bios) +{ + struct bio *bio; + + for (bio = bios->head; bio; bio = bio->bi_next) + rh_inc(rh, bio_to_region(rh, bio)); +} + +static void rh_dec(struct region_hash *rh, region_t region) +{ + unsigned long flags; + struct region *reg; + int should_wake = 0; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + if (atomic_dec_and_test(®->pending)) { + spin_lock_irqsave(&rh->region_lock, flags); + if (reg->state == RH_RECOVERING) { + list_add_tail(®->list, &rh->quiesced_regions); + } else { + reg->state = RH_CLEAN; + list_add(®->list, &rh->clean_regions); + } + spin_unlock_irqrestore(&rh->region_lock, flags); + should_wake = 1; + } + + if (should_wake) + wake(); +} + +/* + * Starts quiescing a region in preparation for recovery. + */ +static int __rh_recovery_prepare(struct region_hash *rh) +{ + int r; + struct region *reg; + region_t region; + + /* + * Ask the dirty log what's next. + */ + r = rh->log->type->get_resync_work(rh->log, ®ion); + if (r <= 0) + return r; + + /* + * Get this region, and start it quiescing by setting the + * recovering flag. + */ + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + read_unlock(&rh->hash_lock); + + spin_lock_irq(&rh->region_lock); + reg->state = RH_RECOVERING; + + /* Already quiesced ? */ + if (atomic_read(®->pending)) + list_del_init(®->list); + + else { + list_del_init(®->list); + list_add(®->list, &rh->quiesced_regions); + } + spin_unlock_irq(&rh->region_lock); + + return 1; +} + +static void rh_recovery_prepare(struct region_hash *rh) +{ + while (!down_trylock(&rh->recovery_count)) + if (__rh_recovery_prepare(rh) <= 0) { + up(&rh->recovery_count); + break; + } +} + +/* + * Returns any quiesced regions. + */ +static struct region *rh_recovery_start(struct region_hash *rh) +{ + struct region *reg = NULL; + + spin_lock_irq(&rh->region_lock); + if (!list_empty(&rh->quiesced_regions)) { + reg = list_entry(rh->quiesced_regions.next, + struct region, list); + list_del_init(®->list); /* remove from the quiesced list */ + } + spin_unlock_irq(&rh->region_lock); + + return reg; +} + +/* FIXME: success ignored for now */ +static void rh_recovery_end(struct region *reg, int success) +{ + struct region_hash *rh = reg->rh; + + spin_lock_irq(&rh->region_lock); + list_add(®->list, ®->rh->recovered_regions); + spin_unlock_irq(&rh->region_lock); + + wake(); +} + +static void rh_flush(struct region_hash *rh) +{ + rh->log->type->flush(rh->log); +} + +static void rh_delay(struct region_hash *rh, struct bio *bio) +{ + struct region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, bio_to_region(rh, bio)); + bio_list_add(®->delayed_bios, bio); + read_unlock(&rh->hash_lock); +} + +static void rh_stop_recovery(struct region_hash *rh) +{ + int i; + + /* wait for any recovering regions */ + for (i = 0; i < MAX_RECOVERY; i++) + down(&rh->recovery_count); +} + +static void rh_start_recovery(struct region_hash *rh) +{ + int i; + + for (i = 0; i < MAX_RECOVERY; i++) + up(&rh->recovery_count); + + wake(); +} + +/*----------------------------------------------------------------- + * Mirror set structures. + *---------------------------------------------------------------*/ +struct mirror { + atomic_t error_count; + struct dm_dev *dev; + sector_t offset; +}; + +struct mirror_set { + struct dm_target *ti; + struct list_head list; + struct region_hash rh; + struct kcopyd_client *kcopyd_client; + + spinlock_t lock; /* protects the next two lists */ + struct bio_list reads; + struct bio_list writes; + + /* recovery */ + region_t nr_regions; + int in_sync; + + unsigned int nr_mirrors; + struct mirror mirror[0]; +}; + +/* + * Every mirror should look like this one. + */ +#define DEFAULT_MIRROR 0 + +/* + * This is yucky. We squirrel the mirror_set struct away inside + * bi_next for write buffers. This is safe since the bh + * doesn't get submitted to the lower levels of block layer. + */ +static struct mirror_set *bio_get_ms(struct bio *bio) +{ + return (struct mirror_set *) bio->bi_next; +} + +static void bio_set_ms(struct bio *bio, struct mirror_set *ms) +{ + bio->bi_next = (struct bio *) ms; +} + +/*----------------------------------------------------------------- + * Recovery. + * + * When a mirror is first activated we may find that some regions + * are in the no-sync state. We have to recover these by + * recopying from the default mirror to all the others. + *---------------------------------------------------------------*/ +static void recovery_complete(int read_err, unsigned int write_err, + void *context) +{ + struct region *reg = (struct region *) context; + + /* FIXME: better error handling */ + rh_recovery_end(reg, read_err || write_err); +} + +static int recover(struct mirror_set *ms, struct region *reg) +{ + int r; + unsigned int i; + struct io_region from, to[ms->nr_mirrors - 1], *dest; + struct mirror *m; + unsigned long flags = 0; + + /* fill in the source */ + m = ms->mirror + DEFAULT_MIRROR; + from.bdev = m->dev->bdev; + from.sector = m->offset + region_to_sector(reg->rh, reg->key); + if (reg->key == (ms->nr_regions - 1)) { + /* + * The final region may be smaller than + * region_size. + */ + from.count = ms->ti->len & (reg->rh->region_size - 1); + if (!from.count) + from.count = reg->rh->region_size; + } else + from.count = reg->rh->region_size; + + /* fill in the destinations */ + for (i = 0, dest = to; i < ms->nr_mirrors; i++) { + if (i == DEFAULT_MIRROR) + continue; + + m = ms->mirror + i; + dest->bdev = m->dev->bdev; + dest->sector = m->offset + region_to_sector(reg->rh, reg->key); + dest->count = from.count; + dest++; + } + + /* hand to kcopyd */ + set_bit(KCOPYD_IGNORE_ERROR, &flags); + r = kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags, + recovery_complete, reg); + + return r; +} + +static void do_recovery(struct mirror_set *ms) +{ + int r; + struct region *reg; + struct dirty_log *log = ms->rh.log; + + /* + * Start quiescing some regions. + */ + rh_recovery_prepare(&ms->rh); + + /* + * Copy any already quiesced regions. + */ + while ((reg = rh_recovery_start(&ms->rh))) { + r = recover(ms, reg); + if (r) + rh_recovery_end(reg, 0); + } + + /* + * Update the in sync flag. + */ + if (!ms->in_sync && + (log->type->get_sync_count(log) == ms->nr_regions)) { + /* the sync is complete */ + dm_table_event(ms->ti->table); + ms->in_sync = 1; + } +} + +/*----------------------------------------------------------------- + * Reads + *---------------------------------------------------------------*/ +static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector) +{ + /* FIXME: add read balancing */ + return ms->mirror + DEFAULT_MIRROR; +} + +/* + * remap a buffer to a particular mirror. + */ +static void map_bio(struct mirror_set *ms, struct mirror *m, struct bio *bio) +{ + bio->bi_bdev = m->dev->bdev; + bio->bi_sector = m->offset + (bio->bi_sector - ms->ti->begin); +} + +static void do_reads(struct mirror_set *ms, struct bio_list *reads) +{ + region_t region; + struct bio *bio; + struct mirror *m; + + while ((bio = bio_list_pop(reads))) { + region = bio_to_region(&ms->rh, bio); + + /* + * We can only read balance if the region is in sync. + */ + if (rh_in_sync(&ms->rh, region, 0)) + m = choose_mirror(ms, bio->bi_sector); + else + m = ms->mirror + DEFAULT_MIRROR; + + map_bio(ms, m, bio); + generic_make_request(bio); + } +} + +/*----------------------------------------------------------------- + * Writes. + * + * We do different things with the write io depending on the + * state of the region that it's in: + * + * SYNC: increment pending, use kcopyd to write to *all* mirrors + * RECOVERING: delay the io until recovery completes + * NOSYNC: increment pending, just write to the default mirror + *---------------------------------------------------------------*/ +static void write_callback(unsigned long error, void *context) +{ + unsigned int i; + int uptodate = 1; + struct bio *bio = (struct bio *) context; + struct mirror_set *ms; + + ms = bio_get_ms(bio); + bio_set_ms(bio, NULL); + + /* + * NOTE: We don't decrement the pending count here, + * instead it is done by the targets endio function. + * This way we handle both writes to SYNC and NOSYNC + * regions with the same code. + */ + + if (error) { + /* + * only error the io if all mirrors failed. + * FIXME: bogus + */ + uptodate = 0; + for (i = 0; i < ms->nr_mirrors; i++) + if (!test_bit(i, &error)) { + uptodate = 1; + break; + } + } + bio_endio(bio, bio->bi_size, 0); +} + +static void do_write(struct mirror_set *ms, struct bio *bio) +{ + unsigned int i; + struct io_region io[ms->nr_mirrors]; + struct mirror *m; + + for (i = 0; i < ms->nr_mirrors; i++) { + m = ms->mirror + i; + + io[i].bdev = m->dev->bdev; + io[i].sector = m->offset + (bio->bi_sector - ms->ti->begin); + io[i].count = bio->bi_size >> 9; + } + + bio_set_ms(bio, ms); + dm_io_async_bvec(ms->nr_mirrors, io, WRITE, + bio->bi_io_vec + bio->bi_idx, + write_callback, bio); +} + +static void do_writes(struct mirror_set *ms, struct bio_list *writes) +{ + int state; + struct bio *bio; + struct bio_list sync, nosync, recover, *this_list = NULL; + + if (!writes->head) + return; + + /* + * Classify each write. + */ + bio_list_init(&sync); + bio_list_init(&nosync); + bio_list_init(&recover); + + while ((bio = bio_list_pop(writes))) { + state = rh_state(&ms->rh, bio_to_region(&ms->rh, bio), 1); + switch (state) { + case RH_CLEAN: + case RH_DIRTY: + this_list = &sync; + break; + + case RH_NOSYNC: + this_list = &nosync; + break; + + case RH_RECOVERING: + this_list = &recover; + break; + } + + bio_list_add(this_list, bio); + } + + /* + * Increment the pending counts for any regions that will + * be written to (writes to recover regions are going to + * be delayed). + */ + rh_inc_pending(&ms->rh, &sync); + rh_inc_pending(&ms->rh, &nosync); + rh_flush(&ms->rh); + + /* + * Dispatch io. + */ + while ((bio = bio_list_pop(&sync))) + do_write(ms, bio); + + while ((bio = bio_list_pop(&recover))) + rh_delay(&ms->rh, bio); + + while ((bio = bio_list_pop(&nosync))) { + map_bio(ms, ms->mirror + DEFAULT_MIRROR, bio); + generic_make_request(bio); + } +} + +/*----------------------------------------------------------------- + * kmirrord + *---------------------------------------------------------------*/ +static LIST_HEAD(_mirror_sets); +static DECLARE_RWSEM(_mirror_sets_lock); + +static void do_mirror(struct mirror_set *ms) +{ + struct bio_list reads, writes; + + spin_lock(&ms->lock); + reads = ms->reads; + writes = ms->writes; + bio_list_init(&ms->reads); + bio_list_init(&ms->writes); + spin_unlock(&ms->lock); + + rh_update_states(&ms->rh); + do_recovery(ms); + do_reads(ms, &reads); + do_writes(ms, &writes); +} + +static void do_work(void *ignored) +{ + struct mirror_set *ms; + + down_read(&_mirror_sets_lock); + list_for_each_entry (ms, &_mirror_sets, list) + do_mirror(ms); + up_read(&_mirror_sets_lock); +} + +/*----------------------------------------------------------------- + * Target functions + *---------------------------------------------------------------*/ +static struct mirror_set *alloc_context(unsigned int nr_mirrors, + sector_t region_size, + struct dm_target *ti, + struct dirty_log *dl) +{ + size_t len; + struct mirror_set *ms = NULL; + + if (array_too_big(sizeof(*ms), sizeof(ms->mirror[0]), nr_mirrors)) + return NULL; + + len = sizeof(*ms) + (sizeof(ms->mirror[0]) * nr_mirrors); + + ms = kmalloc(len, GFP_KERNEL); + if (!ms) { + ti->error = "dm-mirror: Cannot allocate mirror context"; + return NULL; + } + + memset(ms, 0, len); + spin_lock_init(&ms->lock); + + ms->ti = ti; + ms->nr_mirrors = nr_mirrors; + ms->nr_regions = dm_div_up(ti->len, region_size); + ms->in_sync = 0; + + if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { + ti->error = "dm-mirror: Error creating dirty region hash"; + kfree(ms); + return NULL; + } + + return ms; +} + +static void free_context(struct mirror_set *ms, struct dm_target *ti, + unsigned int m) +{ + while (m--) + dm_put_device(ti, ms->mirror[m].dev); + + rh_exit(&ms->rh); + kfree(ms); +} + +static inline int _check_region_size(struct dm_target *ti, sector_t size) +{ + return !(size % (PAGE_SIZE >> 9) || (size & (size - 1)) || + size > ti->len); +} + +static int get_mirror(struct mirror_set *ms, struct dm_target *ti, + unsigned int mirror, char **argv) +{ + sector_t offset; + + if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) { + ti->error = "dm-mirror: Invalid offset"; + return -EINVAL; + } + + if (dm_get_device(ti, argv[0], offset, ti->len, + dm_table_get_mode(ti->table), + &ms->mirror[mirror].dev)) { + ti->error = "dm-mirror: Device lookup failure"; + return -ENXIO; + } + + ms->mirror[mirror].offset = offset; + + return 0; +} + +static int add_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_add_tail(&ms->list, &_mirror_sets); + up_write(&_mirror_sets_lock); + wake(); + + return 0; +} + +static void del_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_del(&ms->list); + up_write(&_mirror_sets_lock); +} + +/* + * Create dirty log: log_type #log_params + */ +static struct dirty_log *create_dirty_log(struct dm_target *ti, + unsigned int argc, char **argv, + unsigned int *args_used) +{ + unsigned int param_count; + struct dirty_log *dl; + + if (argc < 2) { + ti->error = "dm-mirror: Insufficient mirror log arguments"; + return NULL; + } + + if (sscanf(argv[1], "%u", ¶m_count) != 1) { + ti->error = "dm-mirror: Invalid mirror log argument count"; + return NULL; + } + + *args_used = 2 + param_count; + + if (argc < *args_used) { + ti->error = "dm-mirror: Insufficient mirror log arguments"; + return NULL; + } + + dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2); + if (!dl) { + ti->error = "dm-mirror: Error creating mirror dirty log"; + return NULL; + } + + if (!_check_region_size(ti, dl->type->get_region_size(dl))) { + ti->error = "dm-mirror: Invalid region size"; + dm_destroy_dirty_log(dl); + return NULL; + } + + return dl; +} + +/* + * Construct a mirror mapping: + * + * log_type #log_params + * #mirrors [mirror_path offset]{2,} + * + * For now, #log_params = 1, log_type = "core" + * + */ +#define DM_IO_PAGES 64 +static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + int r; + unsigned int nr_mirrors, m, args_used; + struct mirror_set *ms; + struct dirty_log *dl; + + dl = create_dirty_log(ti, argc, argv, &args_used); + if (!dl) + return -EINVAL; + + argv += args_used; + argc -= args_used; + + if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 || + nr_mirrors < 2) { + ti->error = "dm-mirror: Invalid number of mirrors"; + dm_destroy_dirty_log(dl); + return -EINVAL; + } + + argv++, argc--; + + if (argc != nr_mirrors * 2) { + ti->error = "dm-mirror: Wrong number of mirror arguments"; + dm_destroy_dirty_log(dl); + return -EINVAL; + } + + ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl); + if (!ms) { + dm_destroy_dirty_log(dl); + return -ENOMEM; + } + + /* Get the mirror parameter sets */ + for (m = 0; m < nr_mirrors; m++) { + r = get_mirror(ms, ti, m, argv); + if (r) { + free_context(ms, ti, m); + return r; + } + argv += 2; + argc -= 2; + } + + ti->private = ms; + + r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); + if (r) { + free_context(ms, ti, ms->nr_mirrors); + return r; + } + + add_mirror_set(ms); + return 0; +} + +static void mirror_dtr(struct dm_target *ti) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + + del_mirror_set(ms); + kcopyd_client_destroy(ms->kcopyd_client); + free_context(ms, ti, ms->nr_mirrors); +} + +static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw) +{ + int should_wake = 0; + struct bio_list *bl; + + bl = (rw == WRITE) ? &ms->writes : &ms->reads; + spin_lock(&ms->lock); + should_wake = !(bl->head); + bio_list_add(bl, bio); + spin_unlock(&ms->lock); + + if (should_wake) + wake(); +} + +/* + * Mirror mapping function + */ +static int mirror_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + int r, rw = bio_rw(bio); + struct mirror *m; + struct mirror_set *ms = ti->private; + + map_context->ll = bio->bi_sector >> ms->rh.region_shift; + + if (rw == WRITE) { + queue_bio(ms, bio, rw); + return 0; + } + + r = ms->rh.log->type->in_sync(ms->rh.log, + bio_to_region(&ms->rh, bio), 0); + if (r < 0 && r != -EWOULDBLOCK) + return r; + + if (r == -EWOULDBLOCK) /* FIXME: ugly */ + r = 0; + + /* + * We don't want to fast track a recovery just for a read + * ahead. So we just let it silently fail. + * FIXME: get rid of this. + */ + if (!r && rw == READA) + return -EIO; + + if (!r) { + /* Pass this io over to the daemon */ + queue_bio(ms, bio, rw); + return 0; + } + + m = choose_mirror(ms, bio->bi_sector); + if (!m) + return -EIO; + + map_bio(ms, m, bio); + return 1; +} + +static int mirror_end_io(struct dm_target *ti, struct bio *bio, + int error, union map_info *map_context) +{ + int rw = bio_rw(bio); + struct mirror_set *ms = (struct mirror_set *) ti->private; + region_t region = map_context->ll; + + /* + * We need to dec pending if this was a write. + */ + if (rw == WRITE) + rh_dec(&ms->rh, region); + + return 0; +} + +static void mirror_suspend(struct dm_target *ti) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + struct dirty_log *log = ms->rh.log; + rh_stop_recovery(&ms->rh); + if (log->type->suspend && log->type->suspend(log)) + /* FIXME: need better error handling */ + DMWARN("log suspend failed"); +} + +static void mirror_resume(struct dm_target *ti) +{ + struct mirror_set *ms = (struct mirror_set *) ti->private; + struct dirty_log *log = ms->rh.log; + if (log->type->resume && log->type->resume(log)) + /* FIXME: need better error handling */ + DMWARN("log resume failed"); + rh_start_recovery(&ms->rh); +} + +static int mirror_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) +{ + char buffer[32]; + unsigned int m, sz = 0; + struct mirror_set *ms = (struct mirror_set *) ti->private; + +#define EMIT(x...) sz += ((sz >= maxlen) ? \ + 0 : scnprintf(result + sz, maxlen - sz, x)) + + switch (type) { + case STATUSTYPE_INFO: + EMIT("%d ", ms->nr_mirrors); + + for (m = 0; m < ms->nr_mirrors; m++) { + format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev); + EMIT("%s ", buffer); + } + + EMIT(SECTOR_FORMAT "/" SECTOR_FORMAT, + ms->rh.log->type->get_sync_count(ms->rh.log), + ms->nr_regions); + break; + + case STATUSTYPE_TABLE: + EMIT("%s 1 " SECTOR_FORMAT " %d ", + ms->rh.log->type->name, ms->rh.region_size, + ms->nr_mirrors); + + for (m = 0; m < ms->nr_mirrors; m++) { + format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev); + EMIT("%s " SECTOR_FORMAT " ", + buffer, ms->mirror[m].offset); + } + } + + return 0; +} + +static struct target_type mirror_target = { + .name = "mirror", + .version = {1, 0, 1}, + .module = THIS_MODULE, + .ctr = mirror_ctr, + .dtr = mirror_dtr, + .map = mirror_map, + .end_io = mirror_end_io, + .suspend = mirror_suspend, + .resume = mirror_resume, + .status = mirror_status, +}; + +static int __init dm_mirror_init(void) +{ + int r; + + r = dm_dirty_log_init(); + if (r) + return r; + + _kmirrord_wq = create_workqueue("kmirrord"); + if (!_kmirrord_wq) { + DMERR("couldn't start kmirrord"); + dm_dirty_log_exit(); + return r; + } + INIT_WORK(&_kmirrord_work, do_work, NULL); + + r = dm_register_target(&mirror_target); + if (r < 0) { + DMERR("%s: Failed to register mirror target", + mirror_target.name); + dm_dirty_log_exit(); + destroy_workqueue(_kmirrord_wq); + } + + return r; +} + +static void __exit dm_mirror_exit(void) +{ + int r; + + r = dm_unregister_target(&mirror_target); + if (r < 0) + DMERR("%s: unregister failed %d", mirror_target.name, r); + + destroy_workqueue(_kmirrord_wq); + dm_dirty_log_exit(); +} + +/* Module hooks */ +module_init(dm_mirror_init); +module_exit(dm_mirror_exit); + +MODULE_DESCRIPTION(DM_NAME " mirror target"); +MODULE_AUTHOR("Joe Thornber"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-snap.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1213 @@ +/* + * dm-snapshot.c + * + * Copyright (C) 2001-2002 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm-snap.h" +#include "dm-bio-list.h" +#include "kcopyd.h" + +/* + * The percentage increment we will wake up users at + */ +#define WAKE_UP_PERCENT 5 + +/* + * kcopyd priority of snapshot operations + */ +#define SNAPSHOT_COPY_PRIORITY 2 + +/* + * Each snapshot reserves this many pages for io + */ +#define SNAPSHOT_PAGES 256 + +struct pending_exception { + struct exception e; + + /* + * Origin buffers waiting for this to complete are held + * in a bio list + */ + struct bio_list origin_bios; + struct bio_list snapshot_bios; + + /* + * Other pending_exceptions that are processing this + * chunk. When this list is empty, we know we can + * complete the origins. + */ + struct list_head siblings; + + /* Pointer back to snapshot context */ + struct dm_snapshot *snap; + + /* + * 1 indicates the exception has already been sent to + * kcopyd. + */ + int started; +}; + +/* + * Hash table mapping origin volumes to lists of snapshots and + * a lock to protect it + */ +static kmem_cache_t *exception_cache; +static kmem_cache_t *pending_cache; +static mempool_t *pending_pool; + +/* + * One of these per registered origin, held in the snapshot_origins hash + */ +struct origin { + /* The origin device */ + struct block_device *bdev; + + struct list_head hash_list; + + /* List of snapshots for this origin */ + struct list_head snapshots; +}; + +/* + * Size of the hash table for origin volumes. If we make this + * the size of the minors list then it should be nearly perfect + */ +#define ORIGIN_HASH_SIZE 256 +#define ORIGIN_MASK 0xFF +static struct list_head *_origins; +static struct rw_semaphore _origins_lock; + +static int init_origin_hash(void) +{ + int i; + + _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head), + GFP_KERNEL); + if (!_origins) { + DMERR("Device mapper: Snapshot: unable to allocate memory"); + return -ENOMEM; + } + + for (i = 0; i < ORIGIN_HASH_SIZE; i++) + INIT_LIST_HEAD(_origins + i); + init_rwsem(&_origins_lock); + + return 0; +} + +static void exit_origin_hash(void) +{ + kfree(_origins); +} + +static inline unsigned int origin_hash(struct block_device *bdev) +{ + return bdev->bd_dev & ORIGIN_MASK; +} + +static struct origin *__lookup_origin(struct block_device *origin) +{ + struct list_head *ol; + struct origin *o; + + ol = &_origins[origin_hash(origin)]; + list_for_each_entry (o, ol, hash_list) + if (bdev_equal(o->bdev, origin)) + return o; + + return NULL; +} + +static void __insert_origin(struct origin *o) +{ + struct list_head *sl = &_origins[origin_hash(o->bdev)]; + list_add_tail(&o->hash_list, sl); +} + +/* + * Make a note of the snapshot and its origin so we can look it + * up when the origin has a write on it. + */ +static int register_snapshot(struct dm_snapshot *snap) +{ + struct origin *o; + struct block_device *bdev = snap->origin->bdev; + + down_write(&_origins_lock); + o = __lookup_origin(bdev); + + if (!o) { + /* New origin */ + o = kmalloc(sizeof(*o), GFP_KERNEL); + if (!o) { + up_write(&_origins_lock); + return -ENOMEM; + } + + /* Initialise the struct */ + INIT_LIST_HEAD(&o->snapshots); + o->bdev = bdev; + + __insert_origin(o); + } + + list_add_tail(&snap->list, &o->snapshots); + + up_write(&_origins_lock); + return 0; +} + +static void unregister_snapshot(struct dm_snapshot *s) +{ + struct origin *o; + + down_write(&_origins_lock); + o = __lookup_origin(s->origin->bdev); + + list_del(&s->list); + if (list_empty(&o->snapshots)) { + list_del(&o->hash_list); + kfree(o); + } + + up_write(&_origins_lock); +} + +/* + * Implementation of the exception hash tables. + */ +static int init_exception_table(struct exception_table *et, uint32_t size) +{ + unsigned int i; + + et->hash_mask = size - 1; + et->table = dm_vcalloc(size, sizeof(struct list_head)); + if (!et->table) + return -ENOMEM; + + for (i = 0; i < size; i++) + INIT_LIST_HEAD(et->table + i); + + return 0; +} + +static void exit_exception_table(struct exception_table *et, kmem_cache_t *mem) +{ + struct list_head *slot; + struct exception *ex, *next; + int i, size; + + size = et->hash_mask + 1; + for (i = 0; i < size; i++) { + slot = et->table + i; + + list_for_each_entry_safe (ex, next, slot, hash_list) + kmem_cache_free(mem, ex); + } + + vfree(et->table); +} + +static inline uint32_t exception_hash(struct exception_table *et, chunk_t chunk) +{ + return chunk & et->hash_mask; +} + +static void insert_exception(struct exception_table *eh, struct exception *e) +{ + struct list_head *l = &eh->table[exception_hash(eh, e->old_chunk)]; + list_add(&e->hash_list, l); +} + +static inline void remove_exception(struct exception *e) +{ + list_del(&e->hash_list); +} + +/* + * Return the exception data for a sector, or NULL if not + * remapped. + */ +static struct exception *lookup_exception(struct exception_table *et, + chunk_t chunk) +{ + struct list_head *slot; + struct exception *e; + + slot = &et->table[exception_hash(et, chunk)]; + list_for_each_entry (e, slot, hash_list) + if (e->old_chunk == chunk) + return e; + + return NULL; +} + +static inline struct exception *alloc_exception(void) +{ + struct exception *e; + + e = kmem_cache_alloc(exception_cache, GFP_NOIO); + if (!e) + e = kmem_cache_alloc(exception_cache, GFP_ATOMIC); + + return e; +} + +static inline void free_exception(struct exception *e) +{ + kmem_cache_free(exception_cache, e); +} + +static inline struct pending_exception *alloc_pending_exception(void) +{ + return mempool_alloc(pending_pool, GFP_NOIO); +} + +static inline void free_pending_exception(struct pending_exception *pe) +{ + mempool_free(pe, pending_pool); +} + +int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new) +{ + struct exception *e; + + e = alloc_exception(); + if (!e) + return -ENOMEM; + + e->old_chunk = old; + e->new_chunk = new; + insert_exception(&s->complete, e); + return 0; +} + +/* + * Hard coded magic. + */ +static int calc_max_buckets(void) +{ + /* use a fixed size of 2MB */ + unsigned long mem = 2 * 1024 * 1024; + mem /= sizeof(struct list_head); + + return mem; +} + +/* + * Rounds a number down to a power of 2. + */ +static inline uint32_t round_down(uint32_t n) +{ + while (n & (n - 1)) + n &= (n - 1); + return n; +} + +/* + * Allocate room for a suitable hash table. + */ +static int init_hash_tables(struct dm_snapshot *s) +{ + sector_t hash_size, cow_dev_size, origin_dev_size, max_buckets; + + /* + * Calculate based on the size of the original volume or + * the COW volume... + */ + cow_dev_size = get_dev_size(s->cow->bdev); + origin_dev_size = get_dev_size(s->origin->bdev); + max_buckets = calc_max_buckets(); + + hash_size = min(origin_dev_size, cow_dev_size) >> s->chunk_shift; + hash_size = min(hash_size, max_buckets); + + /* Round it down to a power of 2 */ + hash_size = round_down(hash_size); + if (init_exception_table(&s->complete, hash_size)) + return -ENOMEM; + + /* + * Allocate hash table for in-flight exceptions + * Make this smaller than the real hash table + */ + hash_size >>= 3; + if (hash_size < 64) + hash_size = 64; + + if (init_exception_table(&s->pending, hash_size)) { + exit_exception_table(&s->complete, exception_cache); + return -ENOMEM; + } + + return 0; +} + +/* + * Round a number up to the nearest 'size' boundary. size must + * be a power of 2. + */ +static inline ulong round_up(ulong n, ulong size) +{ + size--; + return (n + size) & ~size; +} + +/* + * Construct a snapshot mapping:

+ */ +static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + struct dm_snapshot *s; + unsigned long chunk_size; + int r = -EINVAL; + char persistent; + char *origin_path; + char *cow_path; + char *value; + int blocksize; + + if (argc < 4) { + ti->error = "dm-snapshot: requires exactly 4 arguments"; + r = -EINVAL; + goto bad1; + } + + origin_path = argv[0]; + cow_path = argv[1]; + persistent = toupper(*argv[2]); + + if (persistent != 'P' && persistent != 'N') { + ti->error = "Persistent flag is not P or N"; + r = -EINVAL; + goto bad1; + } + + chunk_size = simple_strtoul(argv[3], &value, 10); + if (chunk_size == 0 || value == NULL) { + ti->error = "Invalid chunk size"; + r = -EINVAL; + goto bad1; + } + + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) { + ti->error = "Cannot allocate snapshot context private " + "structure"; + r = -ENOMEM; + goto bad1; + } + + r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin); + if (r) { + ti->error = "Cannot get origin device"; + goto bad2; + } + + r = dm_get_device(ti, cow_path, 0, 0, + FMODE_READ | FMODE_WRITE, &s->cow); + if (r) { + dm_put_device(ti, s->origin); + ti->error = "Cannot get COW device"; + goto bad2; + } + + /* + * Chunk size must be multiple of page size. Silently + * round up if it's not. + */ + chunk_size = round_up(chunk_size, PAGE_SIZE >> 9); + + /* Validate the chunk size against the device block size */ + blocksize = s->cow->bdev->bd_disk->queue->hardsect_size; + if (chunk_size % (blocksize >> 9)) { + ti->error = "Chunk size is not a multiple of device blocksize"; + r = -EINVAL; + goto bad3; + } + + /* Check chunk_size is a power of 2 */ + if (chunk_size & (chunk_size - 1)) { + ti->error = "Chunk size is not a power of 2"; + r = -EINVAL; + goto bad3; + } + + s->chunk_size = chunk_size; + s->chunk_mask = chunk_size - 1; + s->type = persistent; + s->chunk_shift = ffs(chunk_size) - 1; + + s->valid = 1; + s->have_metadata = 0; + s->last_percent = 0; + init_rwsem(&s->lock); + s->table = ti->table; + + /* Allocate hash table for COW data */ + if (init_hash_tables(s)) { + ti->error = "Unable to allocate hash table space"; + r = -ENOMEM; + goto bad3; + } + + /* + * Check the persistent flag - done here because we need the iobuf + * to check the LV header + */ + s->store.snap = s; + + if (persistent == 'P') + r = dm_create_persistent(&s->store, chunk_size); + else + r = dm_create_transient(&s->store, s, blocksize); + + if (r) { + ti->error = "Couldn't create exception store"; + r = -EINVAL; + goto bad4; + } + + r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client); + if (r) { + ti->error = "Could not create kcopyd client"; + goto bad5; + } + + /* Add snapshot to the list of snapshots for this origin */ + if (register_snapshot(s)) { + r = -EINVAL; + ti->error = "Cannot register snapshot origin"; + goto bad6; + } + + ti->private = s; + ti->split_io = chunk_size; + + return 0; + + bad6: + kcopyd_client_destroy(s->kcopyd_client); + + bad5: + s->store.destroy(&s->store); + + bad4: + exit_exception_table(&s->pending, pending_cache); + exit_exception_table(&s->complete, exception_cache); + + bad3: + dm_put_device(ti, s->cow); + dm_put_device(ti, s->origin); + + bad2: + kfree(s); + + bad1: + return r; +} + +static void snapshot_dtr(struct dm_target *ti) +{ + struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + + unregister_snapshot(s); + + exit_exception_table(&s->pending, pending_cache); + exit_exception_table(&s->complete, exception_cache); + + /* Deallocate memory used */ + s->store.destroy(&s->store); + + dm_put_device(ti, s->origin); + dm_put_device(ti, s->cow); + kcopyd_client_destroy(s->kcopyd_client); + kfree(s); +} + +/* + * Flush a list of buffers. + */ +static void flush_bios(struct bio *bio) +{ + struct bio *n; + + while (bio) { + n = bio->bi_next; + bio->bi_next = NULL; + generic_make_request(bio); + bio = n; + } +} + +/* + * Error a list of buffers. + */ +static void error_bios(struct bio *bio) +{ + struct bio *n; + + while (bio) { + n = bio->bi_next; + bio->bi_next = NULL; + bio_io_error(bio, bio->bi_size); + bio = n; + } +} + +static struct bio *__flush_bios(struct pending_exception *pe) +{ + struct pending_exception *sibling; + + if (list_empty(&pe->siblings)) + return bio_list_get(&pe->origin_bios); + + sibling = list_entry(pe->siblings.next, + struct pending_exception, siblings); + + list_del(&pe->siblings); + + /* This is fine as long as kcopyd is single-threaded. If kcopyd + * becomes multi-threaded, we'll need some locking here. + */ + bio_list_merge(&sibling->origin_bios, &pe->origin_bios); + + return NULL; +} + +static void pending_complete(struct pending_exception *pe, int success) +{ + struct exception *e; + struct dm_snapshot *s = pe->snap; + struct bio *flush = NULL; + + if (success) { + e = alloc_exception(); + if (!e) { + DMWARN("Unable to allocate exception."); + down_write(&s->lock); + s->store.drop_snapshot(&s->store); + s->valid = 0; + flush = __flush_bios(pe); + up_write(&s->lock); + + error_bios(bio_list_get(&pe->snapshot_bios)); + goto out; + } + *e = pe->e; + + /* + * Add a proper exception, and remove the + * in-flight exception from the list. + */ + down_write(&s->lock); + insert_exception(&s->complete, e); + remove_exception(&pe->e); + flush = __flush_bios(pe); + + /* Submit any pending write bios */ + up_write(&s->lock); + + flush_bios(bio_list_get(&pe->snapshot_bios)); + } else { + /* Read/write error - snapshot is unusable */ + down_write(&s->lock); + if (s->valid) + DMERR("Error reading/writing snapshot"); + s->store.drop_snapshot(&s->store); + s->valid = 0; + remove_exception(&pe->e); + flush = __flush_bios(pe); + up_write(&s->lock); + + error_bios(bio_list_get(&pe->snapshot_bios)); + + dm_table_event(s->table); + } + + out: + free_pending_exception(pe); + + if (flush) + flush_bios(flush); +} + +static void commit_callback(void *context, int success) +{ + struct pending_exception *pe = (struct pending_exception *) context; + pending_complete(pe, success); +} + +/* + * Called when the copy I/O has finished. kcopyd actually runs + * this code so don't block. + */ +static void copy_callback(int read_err, unsigned int write_err, void *context) +{ + struct pending_exception *pe = (struct pending_exception *) context; + struct dm_snapshot *s = pe->snap; + + if (read_err || write_err) + pending_complete(pe, 0); + + else + /* Update the metadata if we are persistent */ + s->store.commit_exception(&s->store, &pe->e, commit_callback, + pe); +} + +/* + * Dispatches the copy operation to kcopyd. + */ +static inline void start_copy(struct pending_exception *pe) +{ + struct dm_snapshot *s = pe->snap; + struct io_region src, dest; + struct block_device *bdev = s->origin->bdev; + sector_t dev_size; + + dev_size = get_dev_size(bdev); + + src.bdev = bdev; + src.sector = chunk_to_sector(s, pe->e.old_chunk); + src.count = min(s->chunk_size, dev_size - src.sector); + + dest.bdev = s->cow->bdev; + dest.sector = chunk_to_sector(s, pe->e.new_chunk); + dest.count = src.count; + + /* Hand over to kcopyd */ + kcopyd_copy(s->kcopyd_client, + &src, 1, &dest, 0, copy_callback, pe); +} + +/* + * Looks to see if this snapshot already has a pending exception + * for this chunk, otherwise it allocates a new one and inserts + * it into the pending table. + * + * NOTE: a write lock must be held on snap->lock before calling + * this. + */ +static struct pending_exception * +__find_pending_exception(struct dm_snapshot *s, struct bio *bio) +{ + struct exception *e; + struct pending_exception *pe; + chunk_t chunk = sector_to_chunk(s, bio->bi_sector); + + /* + * Is there a pending exception for this already ? + */ + e = lookup_exception(&s->pending, chunk); + if (e) { + /* cast the exception to a pending exception */ + pe = container_of(e, struct pending_exception, e); + + } else { + /* + * Create a new pending exception, we don't want + * to hold the lock while we do this. + */ + up_write(&s->lock); + pe = alloc_pending_exception(); + down_write(&s->lock); + + e = lookup_exception(&s->pending, chunk); + if (e) { + free_pending_exception(pe); + pe = container_of(e, struct pending_exception, e); + } else { + pe->e.old_chunk = chunk; + bio_list_init(&pe->origin_bios); + bio_list_init(&pe->snapshot_bios); + INIT_LIST_HEAD(&pe->siblings); + pe->snap = s; + pe->started = 0; + + if (s->store.prepare_exception(&s->store, &pe->e)) { + free_pending_exception(pe); + s->valid = 0; + return NULL; + } + + insert_exception(&s->pending, &pe->e); + } + } + + return pe; +} + +static inline void remap_exception(struct dm_snapshot *s, struct exception *e, + struct bio *bio) +{ + bio->bi_bdev = s->cow->bdev; + bio->bi_sector = chunk_to_sector(s, e->new_chunk) + + (bio->bi_sector & s->chunk_mask); +} + +static int snapshot_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + struct exception *e; + struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + int r = 1; + chunk_t chunk; + struct pending_exception *pe; + + chunk = sector_to_chunk(s, bio->bi_sector); + + /* Full snapshots are not usable */ + if (!s->valid) + return -1; + + /* + * Write to snapshot - higher level takes care of RW/RO + * flags so we should only get this if we are + * writeable. + */ + if (bio_rw(bio) == WRITE) { + + /* FIXME: should only take write lock if we need + * to copy an exception */ + down_write(&s->lock); + + /* If the block is already remapped - use that, else remap it */ + e = lookup_exception(&s->complete, chunk); + if (e) { + remap_exception(s, e, bio); + up_write(&s->lock); + + } else { + pe = __find_pending_exception(s, bio); + + if (!pe) { + if (s->store.drop_snapshot) + s->store.drop_snapshot(&s->store); + s->valid = 0; + r = -EIO; + up_write(&s->lock); + } else { + remap_exception(s, &pe->e, bio); + bio_list_add(&pe->snapshot_bios, bio); + + if (!pe->started) { + /* this is protected by snap->lock */ + pe->started = 1; + up_write(&s->lock); + start_copy(pe); + } else + up_write(&s->lock); + r = 0; + } + } + + } else { + /* + * FIXME: this read path scares me because we + * always use the origin when we have a pending + * exception. However I can't think of a + * situation where this is wrong - ejt. + */ + + /* Do reads */ + down_read(&s->lock); + + /* See if it it has been remapped */ + e = lookup_exception(&s->complete, chunk); + if (e) + remap_exception(s, e, bio); + else + bio->bi_bdev = s->origin->bdev; + + up_read(&s->lock); + } + + return r; +} + +static void snapshot_resume(struct dm_target *ti) +{ + struct dm_snapshot *s = (struct dm_snapshot *) ti->private; + + if (s->have_metadata) + return; + + if (s->store.read_metadata(&s->store)) { + down_write(&s->lock); + s->valid = 0; + up_write(&s->lock); + } + + s->have_metadata = 1; +} + +static int snapshot_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) +{ + struct dm_snapshot *snap = (struct dm_snapshot *) ti->private; + char cow[32]; + char org[32]; + + switch (type) { + case STATUSTYPE_INFO: + if (!snap->valid) + snprintf(result, maxlen, "Invalid"); + else { + if (snap->store.fraction_full) { + sector_t numerator, denominator; + snap->store.fraction_full(&snap->store, + &numerator, + &denominator); + snprintf(result, maxlen, + SECTOR_FORMAT "/" SECTOR_FORMAT, + numerator, denominator); + } + else + snprintf(result, maxlen, "Unknown"); + } + break; + + case STATUSTYPE_TABLE: + /* + * kdevname returns a static pointer so we need + * to make private copies if the output is to + * make sense. + */ + format_dev_t(cow, snap->cow->bdev->bd_dev); + format_dev_t(org, snap->origin->bdev->bd_dev); + snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT, org, cow, + snap->type, snap->chunk_size); + break; + } + + return 0; +} + +/*----------------------------------------------------------------- + * Origin methods + *---------------------------------------------------------------*/ +static void list_merge(struct list_head *l1, struct list_head *l2) +{ + struct list_head *l1_n, *l2_p; + + l1_n = l1->next; + l2_p = l2->prev; + + l1->next = l2; + l2->prev = l1; + + l2_p->next = l1_n; + l1_n->prev = l2_p; +} + +static int __origin_write(struct list_head *snapshots, struct bio *bio) +{ + int r = 1, first = 1; + struct dm_snapshot *snap; + struct exception *e; + struct pending_exception *pe, *last = NULL; + chunk_t chunk; + + /* Do all the snapshots on this origin */ + list_for_each_entry (snap, snapshots, list) { + + /* Only deal with valid snapshots */ + if (!snap->valid) + continue; + + down_write(&snap->lock); + + /* + * Remember, different snapshots can have + * different chunk sizes. + */ + chunk = sector_to_chunk(snap, bio->bi_sector); + + /* + * Check exception table to see if block + * is already remapped in this snapshot + * and trigger an exception if not. + */ + e = lookup_exception(&snap->complete, chunk); + if (!e) { + pe = __find_pending_exception(snap, bio); + if (!pe) { + snap->store.drop_snapshot(&snap->store); + snap->valid = 0; + + } else { + if (last) + list_merge(&pe->siblings, + &last->siblings); + + last = pe; + r = 0; + } + } + + up_write(&snap->lock); + } + + /* + * Now that we have a complete pe list we can start the copying. + */ + if (last) { + pe = last; + do { + down_write(&pe->snap->lock); + if (first) + bio_list_add(&pe->origin_bios, bio); + if (!pe->started) { + pe->started = 1; + up_write(&pe->snap->lock); + start_copy(pe); + } else + up_write(&pe->snap->lock); + first = 0; + pe = list_entry(pe->siblings.next, + struct pending_exception, siblings); + + } while (pe != last); + } + + return r; +} + +/* + * Called on a write from the origin driver. + */ +static int do_origin(struct dm_dev *origin, struct bio *bio) +{ + struct origin *o; + int r = 1; + + down_read(&_origins_lock); + o = __lookup_origin(origin->bdev); + if (o) + r = __origin_write(&o->snapshots, bio); + up_read(&_origins_lock); + + return r; +} + +/* + * Origin: maps a linear range of a device, with hooks for snapshotting. + */ + +/* + * Construct an origin mapping: + * The context for an origin is merely a 'struct dm_dev *' + * pointing to the real device. + */ +static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + int r; + struct dm_dev *dev; + + if (argc != 1) { + ti->error = "dm-origin: incorrect number of arguments"; + return -EINVAL; + } + + r = dm_get_device(ti, argv[0], 0, ti->len, + dm_table_get_mode(ti->table), &dev); + if (r) { + ti->error = "Cannot get target device"; + return r; + } + + ti->private = dev; + return 0; +} + +static void origin_dtr(struct dm_target *ti) +{ + struct dm_dev *dev = (struct dm_dev *) ti->private; + dm_put_device(ti, dev); +} + +static int origin_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + struct dm_dev *dev = (struct dm_dev *) ti->private; + bio->bi_bdev = dev->bdev; + + /* Only tell snapshots if this is a write */ + return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; +} + +#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) + +/* + * Set the target "split_io" field to the minimum of all the snapshots' + * chunk sizes. + */ +static void origin_resume(struct dm_target *ti) +{ + struct dm_dev *dev = (struct dm_dev *) ti->private; + struct dm_snapshot *snap; + struct origin *o; + chunk_t chunk_size = 0; + + down_read(&_origins_lock); + o = __lookup_origin(dev->bdev); + if (o) + list_for_each_entry (snap, &o->snapshots, list) + chunk_size = min_not_zero(chunk_size, snap->chunk_size); + up_read(&_origins_lock); + + ti->split_io = chunk_size; +} + +static int origin_status(struct dm_target *ti, status_type_t type, char *result, + unsigned int maxlen) +{ + struct dm_dev *dev = (struct dm_dev *) ti->private; + char buffer[32]; + + switch (type) { + case STATUSTYPE_INFO: + result[0] = '\0'; + break; + + case STATUSTYPE_TABLE: + format_dev_t(buffer, dev->bdev->bd_dev); + snprintf(result, maxlen, "%s", buffer); + break; + } + + return 0; +} + +static struct target_type origin_target = { + .name = "snapshot-origin", + .version = {1, 0, 1}, + .module = THIS_MODULE, + .ctr = origin_ctr, + .dtr = origin_dtr, + .map = origin_map, + .resume = origin_resume, + .status = origin_status, +}; + +static struct target_type snapshot_target = { + .name = "snapshot", + .version = {1, 0, 1}, + .module = THIS_MODULE, + .ctr = snapshot_ctr, + .dtr = snapshot_dtr, + .map = snapshot_map, + .resume = snapshot_resume, + .status = snapshot_status, +}; + +static int __init dm_snapshot_init(void) +{ + int r; + + r = dm_register_target(&snapshot_target); + if (r) { + DMERR("snapshot target register failed %d", r); + return r; + } + + r = dm_register_target(&origin_target); + if (r < 0) { + DMERR("Device mapper: Origin: register failed %d\n", r); + goto bad1; + } + + r = init_origin_hash(); + if (r) { + DMERR("init_origin_hash failed."); + goto bad2; + } + + exception_cache = kmem_cache_create("dm-snapshot-ex", + sizeof(struct exception), + __alignof__(struct exception), + 0, NULL, NULL); + if (!exception_cache) { + DMERR("Couldn't create exception cache."); + r = -ENOMEM; + goto bad3; + } + + pending_cache = + kmem_cache_create("dm-snapshot-in", + sizeof(struct pending_exception), + __alignof__(struct pending_exception), + 0, NULL, NULL); + if (!pending_cache) { + DMERR("Couldn't create pending cache."); + r = -ENOMEM; + goto bad4; + } + + pending_pool = mempool_create(128, mempool_alloc_slab, + mempool_free_slab, pending_cache); + if (!pending_pool) { + DMERR("Couldn't create pending pool."); + r = -ENOMEM; + goto bad5; + } + + return 0; + + bad5: + kmem_cache_destroy(pending_cache); + bad4: + kmem_cache_destroy(exception_cache); + bad3: + exit_origin_hash(); + bad2: + dm_unregister_target(&origin_target); + bad1: + dm_unregister_target(&snapshot_target); + return r; +} + +static void __exit dm_snapshot_exit(void) +{ + int r; + + r = dm_unregister_target(&snapshot_target); + if (r) + DMERR("snapshot unregister failed %d", r); + + r = dm_unregister_target(&origin_target); + if (r) + DMERR("origin unregister failed %d", r); + + exit_origin_hash(); + mempool_destroy(pending_pool); + kmem_cache_destroy(pending_cache); + kmem_cache_destroy(exception_cache); +} + +/* Module hooks */ +module_init(dm_snapshot_init); +module_exit(dm_snapshot_exit); + +MODULE_DESCRIPTION(DM_NAME " snapshot target"); +MODULE_AUTHOR("Joe Thornber"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-snap.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,161 @@ +/* + * dm-snapshot.c + * + * Copyright (C) 2001-2002 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#ifndef DM_SNAPSHOT_H +#define DM_SNAPSHOT_H + +#include "dm.h" +#include + +struct exception_table { + uint32_t hash_mask; + struct list_head *table; +}; + +/* + * The snapshot code deals with largish chunks of the disk at a + * time. Typically 64k - 256k. + */ +/* FIXME: can we get away with limiting these to a uint32_t ? */ +typedef sector_t chunk_t; + +/* + * An exception is used where an old chunk of data has been + * replaced by a new one. + */ +struct exception { + struct list_head hash_list; + + chunk_t old_chunk; + chunk_t new_chunk; +}; + +/* + * Abstraction to handle the meta/layout of exception stores (the + * COW device). + */ +struct exception_store { + + /* + * Destroys this object when you've finished with it. + */ + void (*destroy) (struct exception_store *store); + + /* + * The target shouldn't read the COW device until this is + * called. + */ + int (*read_metadata) (struct exception_store *store); + + /* + * Find somewhere to store the next exception. + */ + int (*prepare_exception) (struct exception_store *store, + struct exception *e); + + /* + * Update the metadata with this exception. + */ + void (*commit_exception) (struct exception_store *store, + struct exception *e, + void (*callback) (void *, int success), + void *callback_context); + + /* + * The snapshot is invalid, note this in the metadata. + */ + void (*drop_snapshot) (struct exception_store *store); + + /* + * Return how full the snapshot is. + */ + void (*fraction_full) (struct exception_store *store, + sector_t *numerator, + sector_t *denominator); + + struct dm_snapshot *snap; + void *context; +}; + +struct dm_snapshot { + struct rw_semaphore lock; + struct dm_table *table; + + struct dm_dev *origin; + struct dm_dev *cow; + + /* List of snapshots per Origin */ + struct list_head list; + + /* Size of data blocks saved - must be a power of 2 */ + chunk_t chunk_size; + chunk_t chunk_mask; + chunk_t chunk_shift; + + /* You can't use a snapshot if this is 0 (e.g. if full) */ + int valid; + int have_metadata; + + /* Used for display of table */ + char type; + + /* The last percentage we notified */ + int last_percent; + + struct exception_table pending; + struct exception_table complete; + + /* The on disk metadata handler */ + struct exception_store store; + + struct kcopyd_client *kcopyd_client; +}; + +/* + * Used by the exception stores to load exceptions hen + * initialising. + */ +int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new); + +/* + * Constructor and destructor for the default persistent + * store. + */ +int dm_create_persistent(struct exception_store *store, uint32_t chunk_size); + +int dm_create_transient(struct exception_store *store, + struct dm_snapshot *s, int blocksize); + +/* + * Return the number of sectors in the device. + */ +static inline sector_t get_dev_size(struct block_device *bdev) +{ + return bdev->bd_inode->i_size >> SECTOR_SHIFT; +} + +static inline chunk_t sector_to_chunk(struct dm_snapshot *s, sector_t sector) +{ + return (sector & ~s->chunk_mask) >> s->chunk_shift; +} + +static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk) +{ + return chunk << s->chunk_shift; +} + +static inline int bdev_equal(struct block_device *lhs, struct block_device *rhs) +{ + /* + * There is only ever one instance of a particular block + * device so we can compare pointers safely. + */ + return lhs == rhs; +} + +#endif diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c --- a/drivers/md/dm-table.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/md/dm-table.c 2004-06-20 13:00:26 -07:00 @@ -400,7 +400,7 @@ struct dm_dev dd_copy; dev_t dev = dd->bdev->bd_dev; - memcpy(&dd_copy, dd, sizeof(dd_copy)); + dd_copy = *dd; dd->mode |= new_mode; dd->bdev = NULL; @@ -408,7 +408,7 @@ if (!r) close_dev(&dd_copy); else - memcpy(dd, &dd_copy, sizeof(dd_copy)); + *dd = dd_copy; return r; } diff -Nru a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/dm-zero.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2003 Christophe Saout + * + * This file is released under the GPL. + */ + +#include "dm.h" + +#include +#include +#include + +/* + * Construct a dummy mapping that only returns zeros + */ +static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + if (argc != 0) { + ti->error = "dm-zero: No arguments required"; + return -EINVAL; + } + + return 0; +} + +/* + * Fills the bio pages with zeros + */ +static void zero_fill_bio(struct bio *bio) +{ + unsigned long flags; + struct bio_vec *bv; + int i; + + bio_for_each_segment(bv, bio, i) { + char *data = bvec_kmap_irq(bv, &flags); + memset(data, 0, bv->bv_len); + flush_dcache_page(bv->bv_page); + bvec_kunmap_irq(data, &flags); + } +} + +/* + * Return zeros only on reads + */ +static int zero_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + switch(bio_rw(bio)) { + case READ: + zero_fill_bio(bio); + break; + case READA: + /* readahead of null bytes only wastes buffer cache */ + return -EIO; + case WRITE: + /* writes get silently dropped */ + break; + } + + bio_endio(bio, bio->bi_size, 0); + + /* accepted bio, don't make new request */ + return 0; +} + +static struct target_type zero_target = { + .name = "zero", + .version = {1, 0, 0}, + .module = THIS_MODULE, + .ctr = zero_ctr, + .map = zero_map, +}; + +int __init dm_zero_init(void) +{ + int r = dm_register_target(&zero_target); + + if (r < 0) + DMERR("zero: register failed %d", r); + + return r; +} + +void __exit dm_zero_exit(void) +{ + int r = dm_unregister_target(&zero_target); + + if (r < 0) + DMERR("zero: unregister failed %d", r); +} + +module_init(dm_zero_init) +module_exit(dm_zero_exit) + +MODULE_AUTHOR("Christophe Saout "); +MODULE_DESCRIPTION(DM_NAME " dummy target returning zeros"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/md/dm.c 2004-06-20 13:00:25 -07:00 @@ -394,7 +394,7 @@ struct bio_vec *bv = bio->bi_io_vec + idx; clone = bio_alloc(GFP_NOIO, 1); - memcpy(clone->bi_io_vec, bv, sizeof(*bv)); + *clone->bi_io_vec = *bv; clone->bi_sector = sector; clone->bi_bdev = bio->bi_bdev; diff -Nru a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/kcopyd.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,699 @@ +/* + * Copyright (C) 2002 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + * + * Kcopyd provides a simple interface for copying an area of one + * block-device to one or more other block-devices, with an asynchronous + * completion notification. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcopyd.h" + +/* FIXME: this is only needed for the DMERR macros */ +#include "dm.h" + +static struct workqueue_struct *_kcopyd_wq; +static struct work_struct _kcopyd_work; + +static inline void wake(void) +{ + queue_work(_kcopyd_wq, &_kcopyd_work); +} + +/*----------------------------------------------------------------- + * Each kcopyd client has its own little pool of preallocated + * pages for kcopyd io. + *---------------------------------------------------------------*/ +struct kcopyd_client { + struct list_head list; + + spinlock_t lock; + struct page_list *pages; + unsigned int nr_pages; + unsigned int nr_free_pages; +}; + +static struct page_list *alloc_pl(void) +{ + struct page_list *pl; + + pl = kmalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) + return NULL; + + pl->page = alloc_page(GFP_KERNEL); + if (!pl->page) { + kfree(pl); + return NULL; + } + + return pl; +} + +static void free_pl(struct page_list *pl) +{ + __free_page(pl->page); + kfree(pl); +} + +static int kcopyd_get_pages(struct kcopyd_client *kc, + unsigned int nr, struct page_list **pages) +{ + struct page_list *pl; + + spin_lock(&kc->lock); + if (kc->nr_free_pages < nr) { + spin_unlock(&kc->lock); + return -ENOMEM; + } + + kc->nr_free_pages -= nr; + for (*pages = pl = kc->pages; --nr; pl = pl->next) + ; + + kc->pages = pl->next; + pl->next = 0; + + spin_unlock(&kc->lock); + + return 0; +} + +static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl) +{ + struct page_list *cursor; + + spin_lock(&kc->lock); + for (cursor = pl; cursor->next; cursor = cursor->next) + kc->nr_free_pages++; + + kc->nr_free_pages++; + cursor->next = kc->pages; + kc->pages = pl; + spin_unlock(&kc->lock); +} + +/* + * These three functions resize the page pool. + */ +static void drop_pages(struct page_list *pl) +{ + struct page_list *next; + + while (pl) { + next = pl->next; + free_pl(pl); + pl = next; + } +} + +static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr) +{ + unsigned int i; + struct page_list *pl = NULL, *next; + + for (i = 0; i < nr; i++) { + next = alloc_pl(); + if (!next) { + if (pl) + drop_pages(pl); + return -ENOMEM; + } + next->next = pl; + pl = next; + } + + kcopyd_put_pages(kc, pl); + kc->nr_pages += nr; + return 0; +} + +static void client_free_pages(struct kcopyd_client *kc) +{ + BUG_ON(kc->nr_free_pages != kc->nr_pages); + drop_pages(kc->pages); + kc->pages = NULL; + kc->nr_free_pages = kc->nr_pages = 0; +} + +/*----------------------------------------------------------------- + * kcopyd_jobs need to be allocated by the *clients* of kcopyd, + * for this reason we use a mempool to prevent the client from + * ever having to do io (which could cause a deadlock). + *---------------------------------------------------------------*/ +struct kcopyd_job { + struct kcopyd_client *kc; + struct list_head list; + unsigned long flags; + + /* + * Error state of the job. + */ + int read_err; + unsigned int write_err; + + /* + * Either READ or WRITE + */ + int rw; + struct io_region source; + + /* + * The destinations for the transfer. + */ + unsigned int num_dests; + struct io_region dests[KCOPYD_MAX_REGIONS]; + + sector_t offset; + unsigned int nr_pages; + struct page_list *pages; + + /* + * Set this to ensure you are notified when the job has + * completed. 'context' is for callback to use. + */ + kcopyd_notify_fn fn; + void *context; + + /* + * These fields are only used if the job has been split + * into more manageable parts. + */ + struct semaphore lock; + atomic_t sub_jobs; + sector_t progress; +}; + +/* FIXME: this should scale with the number of pages */ +#define MIN_JOBS 512 + +static kmem_cache_t *_job_cache; +static mempool_t *_job_pool; + +/* + * We maintain three lists of jobs: + * + * i) jobs waiting for pages + * ii) jobs that have pages, and are waiting for the io to be issued. + * iii) jobs that have completed. + * + * All three of these are protected by job_lock. + */ +static spinlock_t _job_lock = SPIN_LOCK_UNLOCKED; + +static LIST_HEAD(_complete_jobs); +static LIST_HEAD(_io_jobs); +static LIST_HEAD(_pages_jobs); + +static int jobs_init(void) +{ + _job_cache = kmem_cache_create("kcopyd-jobs", + sizeof(struct kcopyd_job), + __alignof__(struct kcopyd_job), + 0, NULL, NULL); + if (!_job_cache) + return -ENOMEM; + + _job_pool = mempool_create(MIN_JOBS, mempool_alloc_slab, + mempool_free_slab, _job_cache); + if (!_job_pool) { + kmem_cache_destroy(_job_cache); + return -ENOMEM; + } + + return 0; +} + +static void jobs_exit(void) +{ + BUG_ON(!list_empty(&_complete_jobs)); + BUG_ON(!list_empty(&_io_jobs)); + BUG_ON(!list_empty(&_pages_jobs)); + + mempool_destroy(_job_pool); + kmem_cache_destroy(_job_cache); + _job_pool = NULL; + _job_cache = NULL; +} + +/* + * Functions to push and pop a job onto the head of a given job + * list. + */ +static inline struct kcopyd_job *pop(struct list_head *jobs) +{ + struct kcopyd_job *job = NULL; + unsigned long flags; + + spin_lock_irqsave(&_job_lock, flags); + + if (!list_empty(jobs)) { + job = list_entry(jobs->next, struct kcopyd_job, list); + list_del(&job->list); + } + spin_unlock_irqrestore(&_job_lock, flags); + + return job; +} + +static inline void push(struct list_head *jobs, struct kcopyd_job *job) +{ + unsigned long flags; + + spin_lock_irqsave(&_job_lock, flags); + list_add_tail(&job->list, jobs); + spin_unlock_irqrestore(&_job_lock, flags); +} + +/* + * These three functions process 1 item from the corresponding + * job list. + * + * They return: + * < 0: error + * 0: success + * > 0: can't process yet. + */ +static int run_complete_job(struct kcopyd_job *job) +{ + void *context = job->context; + int read_err = job->read_err; + unsigned int write_err = job->write_err; + kcopyd_notify_fn fn = job->fn; + + kcopyd_put_pages(job->kc, job->pages); + mempool_free(job, _job_pool); + fn(read_err, write_err, context); + return 0; +} + +static void complete_io(unsigned long error, void *context) +{ + struct kcopyd_job *job = (struct kcopyd_job *) context; + + if (error) { + if (job->rw == WRITE) + job->write_err &= error; + else + job->read_err = 1; + + if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) { + push(&_complete_jobs, job); + wake(); + return; + } + } + + if (job->rw == WRITE) + push(&_complete_jobs, job); + + else { + job->rw = WRITE; + push(&_io_jobs, job); + } + + wake(); +} + +/* + * Request io on as many buffer heads as we can currently get for + * a particular job. + */ +static int run_io_job(struct kcopyd_job *job) +{ + int r; + + if (job->rw == READ) + r = dm_io_async(1, &job->source, job->rw, + job->pages, + job->offset, complete_io, job); + + else + r = dm_io_async(job->num_dests, job->dests, job->rw, + job->pages, + job->offset, complete_io, job); + + return r; +} + +static int run_pages_job(struct kcopyd_job *job) +{ + int r; + + job->nr_pages = dm_div_up(job->dests[0].count + job->offset, + PAGE_SIZE >> 9); + r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages); + if (!r) { + /* this job is ready for io */ + push(&_io_jobs, job); + return 0; + } + + if (r == -ENOMEM) + /* can't complete now */ + return 1; + + return r; +} + +/* + * Run through a list for as long as possible. Returns the count + * of successful jobs. + */ +static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *)) +{ + struct kcopyd_job *job; + int r, count = 0; + + while ((job = pop(jobs))) { + + r = fn(job); + + if (r < 0) { + /* error this rogue job */ + if (job->rw == WRITE) + job->write_err = (unsigned int) -1; + else + job->read_err = 1; + push(&_complete_jobs, job); + break; + } + + if (r > 0) { + /* + * We couldn't service this job ATM, so + * push this job back onto the list. + */ + push(jobs, job); + break; + } + + count++; + } + + return count; +} + +/* + * kcopyd does this every time it's woken up. + */ +static void do_work(void *ignored) +{ + /* + * The order that these are called is *very* important. + * complete jobs can free some pages for pages jobs. + * Pages jobs when successful will jump onto the io jobs + * list. io jobs call wake when they complete and it all + * starts again. + */ + process_jobs(&_complete_jobs, run_complete_job); + process_jobs(&_pages_jobs, run_pages_job); + process_jobs(&_io_jobs, run_io_job); +} + +/* + * If we are copying a small region we just dispatch a single job + * to do the copy, otherwise the io has to be split up into many + * jobs. + */ +static void dispatch_job(struct kcopyd_job *job) +{ + push(&_pages_jobs, job); + wake(); +} + +#define SUB_JOB_SIZE 128 +static void segment_complete(int read_err, + unsigned int write_err, void *context) +{ + /* FIXME: tidy this function */ + sector_t progress = 0; + sector_t count = 0; + struct kcopyd_job *job = (struct kcopyd_job *) context; + + down(&job->lock); + + /* update the error */ + if (read_err) + job->read_err = 1; + + if (write_err) + job->write_err &= write_err; + + /* + * Only dispatch more work if there hasn't been an error. + */ + if ((!job->read_err && !job->write_err) || + test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) { + /* get the next chunk of work */ + progress = job->progress; + count = job->source.count - progress; + if (count) { + if (count > SUB_JOB_SIZE) + count = SUB_JOB_SIZE; + + job->progress += count; + } + } + up(&job->lock); + + if (count) { + int i; + struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO); + + *sub_job = *job; + sub_job->source.sector += progress; + sub_job->source.count = count; + + for (i = 0; i < job->num_dests; i++) { + sub_job->dests[i].sector += progress; + sub_job->dests[i].count = count; + } + + sub_job->fn = segment_complete; + sub_job->context = job; + dispatch_job(sub_job); + + } else if (atomic_dec_and_test(&job->sub_jobs)) { + + /* + * To avoid a race we must keep the job around + * until after the notify function has completed. + * Otherwise the client may try and stop the job + * after we've completed. + */ + job->fn(read_err, write_err, job->context); + mempool_free(job, _job_pool); + } +} + +/* + * Create some little jobs that will do the move between + * them. + */ +#define SPLIT_COUNT 8 +static void split_job(struct kcopyd_job *job) +{ + int i; + + atomic_set(&job->sub_jobs, SPLIT_COUNT); + for (i = 0; i < SPLIT_COUNT; i++) + segment_complete(0, 0u, job); +} + +int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, + unsigned int num_dests, struct io_region *dests, + unsigned int flags, kcopyd_notify_fn fn, void *context) +{ + struct kcopyd_job *job; + + /* + * Allocate a new job. + */ + job = mempool_alloc(_job_pool, GFP_NOIO); + + /* + * set up for the read. + */ + job->kc = kc; + job->flags = flags; + job->read_err = 0; + job->write_err = 0; + job->rw = READ; + + job->source = *from; + + job->num_dests = num_dests; + memcpy(&job->dests, dests, sizeof(*dests) * num_dests); + + job->offset = 0; + job->nr_pages = 0; + job->pages = NULL; + + job->fn = fn; + job->context = context; + + if (job->source.count < SUB_JOB_SIZE) + dispatch_job(job); + + else { + init_MUTEX(&job->lock); + job->progress = 0; + split_job(job); + } + + return 0; +} + +/* + * Cancels a kcopyd job, eg. someone might be deactivating a + * mirror. + */ +int kcopyd_cancel(struct kcopyd_job *job, int block) +{ + /* FIXME: finish */ + return -1; +} + +/*----------------------------------------------------------------- + * Unit setup + *---------------------------------------------------------------*/ +static DECLARE_MUTEX(_client_lock); +static LIST_HEAD(_clients); + +static int client_add(struct kcopyd_client *kc) +{ + down(&_client_lock); + list_add(&kc->list, &_clients); + up(&_client_lock); + return 0; +} + +static void client_del(struct kcopyd_client *kc) +{ + down(&_client_lock); + list_del(&kc->list); + up(&_client_lock); +} + +static DECLARE_MUTEX(kcopyd_init_lock); +static int kcopyd_clients = 0; + +static int kcopyd_init(void) +{ + int r; + + down(&kcopyd_init_lock); + + if (kcopyd_clients) { + /* Already initialized. */ + kcopyd_clients++; + up(&kcopyd_init_lock); + return 0; + } + + r = jobs_init(); + if (r) { + up(&kcopyd_init_lock); + return r; + } + + _kcopyd_wq = create_singlethread_workqueue("kcopyd"); + if (!_kcopyd_wq) { + jobs_exit(); + up(&kcopyd_init_lock); + return -ENOMEM; + } + + kcopyd_clients++; + INIT_WORK(&_kcopyd_work, do_work, NULL); + up(&kcopyd_init_lock); + return 0; +} + +static void kcopyd_exit(void) +{ + down(&kcopyd_init_lock); + kcopyd_clients--; + if (!kcopyd_clients) { + jobs_exit(); + destroy_workqueue(_kcopyd_wq); + _kcopyd_wq = NULL; + } + up(&kcopyd_init_lock); +} + +int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) +{ + int r = 0; + struct kcopyd_client *kc; + + r = kcopyd_init(); + if (r) + return r; + + kc = kmalloc(sizeof(*kc), GFP_KERNEL); + if (!kc) { + kcopyd_exit(); + return -ENOMEM; + } + + kc->lock = SPIN_LOCK_UNLOCKED; + kc->pages = NULL; + kc->nr_pages = kc->nr_free_pages = 0; + r = client_alloc_pages(kc, nr_pages); + if (r) { + kfree(kc); + kcopyd_exit(); + return r; + } + + r = dm_io_get(nr_pages); + if (r) { + client_free_pages(kc); + kfree(kc); + kcopyd_exit(); + return r; + } + + r = client_add(kc); + if (r) { + dm_io_put(nr_pages); + client_free_pages(kc); + kfree(kc); + kcopyd_exit(); + return r; + } + + *result = kc; + return 0; +} + +void kcopyd_client_destroy(struct kcopyd_client *kc) +{ + dm_io_put(kc->nr_pages); + client_free_pages(kc); + client_del(kc); + kfree(kc); + kcopyd_exit(); +} + +EXPORT_SYMBOL(kcopyd_client_create); +EXPORT_SYMBOL(kcopyd_client_destroy); +EXPORT_SYMBOL(kcopyd_copy); +EXPORT_SYMBOL(kcopyd_cancel); diff -Nru a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/kcopyd.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 Sistina Software + * + * This file is released under the GPL. + * + * Kcopyd provides a simple interface for copying an area of one + * block-device to one or more other block-devices, with an asynchronous + * completion notification. + */ + +#ifndef DM_KCOPYD_H +#define DM_KCOPYD_H + +#include "dm-io.h" + +/* FIXME: make this configurable */ +#define KCOPYD_MAX_REGIONS 8 + +#define KCOPYD_IGNORE_ERROR 1 + +/* + * To use kcopyd you must first create a kcopyd client object. + */ +struct kcopyd_client; +int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result); +void kcopyd_client_destroy(struct kcopyd_client *kc); + +/* + * Submit a copy job to kcopyd. This is built on top of the + * previous three fns. + * + * read_err is a boolean, + * write_err is a bitset, with 1 bit for each destination region + */ +typedef void (*kcopyd_notify_fn)(int read_err, + unsigned int write_err, void *context); + +int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, + unsigned int num_dests, struct io_region *dests, + unsigned int flags, kcopyd_notify_fn fn, void *context); + +#endif diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c --- a/drivers/md/raid1.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/md/raid1.c 2004-06-20 13:00:24 -07:00 @@ -376,7 +376,8 @@ * device if no resync is going on, or below the resync window. * We take the first readable disk when above the resync window. */ - if (!conf->mddev->in_sync && (this_sector + sectors >= conf->next_resync)) { + if (conf->mddev->recovery_cp < MaxSector && + (this_sector + sectors >= conf->next_resync)) { /* make sure that disk is operational */ new_disk = 0; diff -Nru a/drivers/message/fusion/isense.c b/drivers/message/fusion/isense.c --- a/drivers/message/fusion/isense.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/message/fusion/isense.c 2004-06-20 13:00:24 -07:00 @@ -56,14 +56,6 @@ #include #include #include -#if defined (__sparc__) -#include -#endif - -/* Hmmm, avoid undefined spinlock_t on lk-2.2.14-5.0 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -#include -#endif #define MODULEAUTHOR "Steven J. Ralston" #define COPYRIGHT "Copyright (c) 2001-2004 " MODULEAUTHOR diff -Nru a/drivers/message/fusion/linux_compat.h b/drivers/message/fusion/linux_compat.h --- a/drivers/message/fusion/linux_compat.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/message/fusion/linux_compat.h 2004-06-20 13:00:24 -07:00 @@ -2,196 +2,7 @@ #ifndef FUSION_LINUX_COMPAT_H #define FUSION_LINUX_COMPAT_H -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include -#include -#include -#include - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#ifndef rwlock_init -#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) -#endif - -#define SET_NICE(current,x) do {(current)->nice = (x);} while (0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) - typedef unsigned int dma_addr_t; -# endif -#else -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42) - typedef unsigned int dma_addr_t; -# endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* This block snipped from lk-2.2.18/include/linux/init.h { */ -/* - * Used for initialization calls.. - */ -typedef int (*initcall_t)(void); -typedef void (*exitcall_t)(void); - -#define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) -#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit"))) - -extern initcall_t __initcall_start, __initcall_end; - -#define __initcall(fn) \ - static initcall_t __initcall_##fn __init_call = fn -#define __exitcall(fn) \ - static exitcall_t __exitcall_##fn __exit_call = fn - -#ifdef MODULE -/* These macros create a dummy inline: gcc 2.9x does not count alias - as usage, hence the `unused function' warning when __init functions - are declared static. We use the dummy __*_module_inline functions - both to kill the warning and check the type of the init/cleanup - function. */ -typedef int (*__init_module_func_t)(void); -typedef void (*__cleanup_module_func_t)(void); -#define module_init(x) \ - int init_module(void) __attribute__((alias(#x))); \ - static inline __init_module_func_t __init_module_inline(void) \ - { return x; } -#define module_exit(x) \ - void cleanup_module(void) __attribute__((alias(#x))); \ - static inline __cleanup_module_func_t __cleanup_module_inline(void) \ - { return x; } - -#else -#define module_init(x) __initcall(x); -#define module_exit(x) __exitcall(x); -#endif -/* } block snipped from lk-2.2.18/include/linux/init.h */ - -/* This block snipped from lk-2.2.18/include/linux/sched.h { */ -/* - * Used prior to schedule_timeout calls.. - */ -#define __set_current_state(state_value) do { current->state = state_value; } while (0) -#ifdef CONFIG_SMP -#define set_current_state(state_value) do { __set_current_state(state_value); mb(); } while (0) -#else -#define set_current_state(state_value) __set_current_state(state_value) -#endif -/* } block snipped from lk-2.2.18/include/linux/sched.h */ - -/* procfs compat stuff... */ -#define proc_mkdir(x,y) create_proc_entry(x, S_IFDIR, y) - -/* MUTEX compat stuff... */ -#define DECLARE_MUTEX(name) struct semaphore name=MUTEX -#define DECLARE_MUTEX_LOCKED(name) struct semaphore name=MUTEX_LOCKED -#define init_MUTEX(x) *(x)=MUTEX -#define init_MUTEX_LOCKED(x) *(x)=MUTEX_LOCKED - -/* Wait queues. */ -#define DECLARE_WAIT_QUEUE_HEAD(name) \ - struct wait_queue * (name) = NULL -#define DECLARE_WAITQUEUE(name, task) \ - struct wait_queue (name) = { (task), NULL } - -#if defined(__sparc__) && defined(__sparc_v9__) -/* The sparc64 ioremap implementation is wrong in 2.2.x, - * but fixing it would break all of the drivers which - * workaround it. Fixed in 2.3.x onward. -DaveM - */ -#define ARCH_IOREMAP(base) ((unsigned long) (base)) -#else -#define ARCH_IOREMAP(base) ioremap(base) -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#else /* LINUX_VERSION_CODE must be >= KERNEL_VERSION(2,2,18) */ - -/* No ioremap bugs in >2.3.x kernels. */ -#define ARCH_IOREMAP(base) ioremap(base) - -/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) */ - - -/* - * Inclined to use: - * #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) - * here, but MODULE_LICENSE defined in 2.4.9-6 and 2.4.9-13 - * breaks the rule:-( - */ -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(license) -#endif - - -/* PCI/driver subsystem { */ -#define PCI_BASEADDR_FLAGS(idx) resource[idx].flags -#define PCI_BASEADDR_START(idx) resource[idx].start -#define PCI_BASEADDR_SIZE(dev,idx) (dev)->resource[idx].end - (dev)->resource[idx].start + 1 - -/* Compatability for the 2.3.x PCI DMA API. */ -#ifndef PCI_DMA_BIDIRECTIONAL -/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#define PCI_DMA_BIDIRECTIONAL 0 -#define PCI_DMA_TODEVICE 1 -#define PCI_DMA_FROMDEVICE 2 -#define PCI_DMA_NONE 3 - -#ifdef __KERNEL__ -#include -/* Pure 2^n version of get_order */ -static __inline__ int __get_order(unsigned long size) -{ - int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} -#endif - -#define pci_alloc_consistent(hwdev, size, dma_handle) \ -({ void *__ret = (void *)__get_free_pages(GFP_ATOMIC, __get_order(size)); \ - if (__ret != NULL) { \ - memset(__ret, 0, size); \ - *(dma_handle) = virt_to_bus(__ret); \ - } \ - __ret; \ -}) - -#define pci_free_consistent(hwdev, size, vaddr, dma_handle) \ - free_pages((unsigned long)vaddr, __get_order(size)) - -#define pci_map_single(hwdev, ptr, size, direction) \ - virt_to_bus(ptr); - -#define pci_unmap_single(hwdev, dma_addr, size, direction) \ - do { /* Nothing to do */ } while (0) - -#define pci_map_sg(hwdev, sg, nents, direction) (nents) -#define pci_unmap_sg(hwdev, sg, nents, direction) \ - do { /* Nothing to do */ } while(0) - -#define sg_dma_address(sg) (virt_to_bus((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) - -/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#endif /* PCI_DMA_BIDIRECTIONAL */ - - -#define mpt_work_struct work_struct -#define MPT_INIT_WORK(_task, _func, _data) INIT_WORK(_task, _func, _data) -#define mpt_sync_irq(_irq) synchronize_irq(_irq) /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* _LINUX_COMPAT_H */ - diff -Nru a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h --- a/drivers/message/fusion/lsi/mpi_type.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/message/fusion/lsi/mpi_type.h 2004-06-20 13:00:25 -07:00 @@ -47,18 +47,13 @@ typedef unsigned short U16; -#if defined(unix) || defined(__arm) || defined(ALPHA) - - typedef signed int S32; - typedef unsigned int U32; - -#else - - typedef signed long S32; - typedef unsigned long U32; - -#endif +typedef int32_t S32; +typedef u_int32_t U32; +/* + * The only way crap below could work on big-endian boxen would be if it + * wasn't used at all. + */ typedef struct _S64 { diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c --- a/drivers/message/fusion/mptbase.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/message/fusion/mptbase.c 2004-06-20 13:00:23 -07:00 @@ -1311,14 +1311,14 @@ mem_phys = msize = 0; port = psize = 0; for (ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { - if (pdev->PCI_BASEADDR_FLAGS(ii) & PCI_BASE_ADDRESS_SPACE_IO) { + if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) { /* Get I/O space! */ - port = pdev->PCI_BASEADDR_START(ii); - psize = PCI_BASEADDR_SIZE(pdev,ii); + port = pci_resource_start(pdev, ii); + psize = pci_resource_len(pdev,ii); } else { /* Get memmap */ - mem_phys = pdev->PCI_BASEADDR_START(ii); - msize = PCI_BASEADDR_SIZE(pdev,ii); + mem_phys = pci_resource_start(pdev, ii); + msize = pci_resource_len(pdev,ii); break; } } @@ -1524,7 +1524,7 @@ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); ioc->active = 0; - mpt_sync_irq(pdev->irq); + synchronize_irq(pdev->irq); /* Clear any lingering interrupt */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -3799,7 +3799,8 @@ /* Prime reply FIFO... */ dprintk((KERN_INFO MYNAM ": %s.reply_alloc @ %p[%p], sz=%d bytes\n", - ioc->name, mem, (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz)); + ioc->name, ioc->reply_alloc, + (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz)); b = (unsigned long) ioc->reply_alloc; b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */ @@ -3812,7 +3813,8 @@ /* Request FIFO - WE manage this! */ dprintk((KERN_INFO MYNAM ": %s.req_alloc @ %p[%p], sz=%d bytes\n", - ioc->name, mem, (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz)); + ioc->name, ioc->req_alloc, + (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz)); b = (unsigned long) ioc->req_alloc; b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */ diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h --- a/drivers/message/fusion/mptbase.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/message/fusion/mptbase.h 2004-06-20 13:00:23 -07:00 @@ -55,7 +55,11 @@ #define MPTBASE_H_INCLUDED /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include "linux_compat.h" /* linux-2.2.x (vs. -2.4.x) tweaks */ +#include +#include +#include +#include + #include "scsi3.h" /* SCSI defines */ #include "lsi/mpi_type.h" @@ -81,8 +85,8 @@ #define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.06" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.06" +#define MPT_LINUX_VERSION_COMMON "3.01.07" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.07" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c --- a/drivers/message/fusion/mptctl.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/message/fusion/mptctl.c 2004-06-20 13:00:23 -07:00 @@ -83,6 +83,7 @@ #include #include #include +#include #include #include @@ -102,9 +103,6 @@ #define my_VERSION MPT_LINUX_VERSION_COMMON #define MYNAM "mptctl" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62) -EXPORT_NO_SYMBOLS; -#endif MODULE_AUTHOR(MODULEAUTHOR); MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); @@ -144,8 +142,8 @@ /* * Private function calls. */ -static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local); -static int mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen); +static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr); +static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen); static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags, struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc); static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma, @@ -547,38 +545,6 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * struct file_operations functionality. - * Members: - * llseek, write, read, ioctl, open, release - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) -static loff_t -mptctl_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} -#define no_llseek mptctl_llseek -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static ssize_t -mptctl_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - printk(KERN_ERR MYNAM ": ioctl WRITE not yet supported\n"); - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static ssize_t -mptctl_read(struct file *file, char *buf, size_t count, loff_t *ptr) -{ - printk(KERN_ERR MYNAM ": ioctl READ not yet supported\n"); - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* * MPT ioctl handler * cmd - specify the particular IOCTL command to be issued * arg - data specific to the command. Must not be null. @@ -586,7 +552,7 @@ static int mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - mpt_ioctl_header *uhdr = (mpt_ioctl_header *) arg; + mpt_ioctl_header __user *uhdr = (void __user *) arg; mpt_ioctl_header khdr; int iocnum; unsigned iocnumX; @@ -599,7 +565,7 @@ if (copy_from_user(&khdr, uhdr, sizeof(khdr))) { printk(KERN_ERR "%s::mptctl_ioctl() @%d - " "Unable to copy mpt_ioctl_header data @ %p\n", - __FILE__, __LINE__, (void*)uhdr); + __FILE__, __LINE__, uhdr); return -EFAULT; } ret = -ENXIO; /* (-6) No such device or address */ @@ -671,7 +637,7 @@ static int mptctl_do_reset(unsigned long arg) { - struct mpt_ioctl_diag_reset *urinfo = (struct mpt_ioctl_diag_reset *) arg; + struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg; struct mpt_ioctl_diag_reset krinfo; MPT_ADAPTER *iocp; @@ -680,7 +646,7 @@ if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) { printk(KERN_ERR "%s@%d::mptctl_do_reset - " "Unable to copy mpt_ioctl_diag_reset struct @ %p\n", - __FILE__, __LINE__, (void*)urinfo); + __FILE__, __LINE__, urinfo); return -EFAULT; } @@ -700,21 +666,6 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int mptctl_open(struct inode *inode, struct file *file) -{ - /* - * Should support multiple management users - */ - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int mptctl_release(struct inode *inode, struct file *file) -{ - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * MPT FW download function. Cast the arg into the mpt_fw_xfer structure. * This structure contains: iocnum, firmware length (bytes), @@ -734,14 +685,14 @@ static int mptctl_fw_download(unsigned long arg) { - struct mpt_fw_xfer *ufwdl = (struct mpt_fw_xfer *) arg; + struct mpt_fw_xfer __user *ufwdl = (void __user *) arg; struct mpt_fw_xfer kfwdl; dctlprintk((KERN_INFO "mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) { printk(KERN_ERR "%s@%d::_ioctl_fwdl - " "Unable to copy mpt_fw_xfer struct @ %p\n", - __FILE__, __LINE__, (void*)ufwdl); + __FILE__, __LINE__, ufwdl); return -EFAULT; } @@ -763,7 +714,7 @@ * -ENOMSG if FW upload returned bad status */ static int -mptctl_do_fw_download(int ioc, char *ufwbuf, size_t fwlen) +mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) { FWDownload_t *dlmsg; MPT_FRAME_HDR *mf; @@ -892,7 +843,7 @@ if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { printk(KERN_ERR "%s@%d::_ioctl_fwdl - " "Unable to copy f/w buffer hunk#%d @ %p\n", - __FILE__, __LINE__, n, (void*)ufwbuf); + __FILE__, __LINE__, n, ufwbuf); goto fwdl_out; } fw_bytes_copied += bl->len; @@ -1198,7 +1149,7 @@ static int mptctl_getiocinfo (unsigned long arg, unsigned int data_size) { - struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg; + struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_iocinfo *karg; MPT_ADAPTER *ioc; struct pci_dev *pdev; @@ -1238,7 +1189,7 @@ if (copy_from_user(karg, uarg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); kfree(karg); return -EFAULT; } @@ -1278,10 +1229,8 @@ karg->pciId = pdev->device; pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); karg->hwRev = revision; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) karg->subSystemDevice = pdev->subsystem_device; karg->subSystemVendor = pdev->subsystem_vendor; -#endif if (cim_rev == 1) { /* Get the PCI bus, device, and function numbers for the IOC @@ -1335,10 +1284,10 @@ /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, karg, data_size)) { + if (copy_to_user((char __user *)arg, karg, data_size)) { printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); kfree(karg); return -EFAULT; } @@ -1360,7 +1309,7 @@ static int mptctl_gettargetinfo (unsigned long arg) { - struct mpt_ioctl_targetinfo *uarg = (struct mpt_ioctl_targetinfo *) arg; + struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo karg; MPT_ADAPTER *ioc; struct Scsi_Host *sh; @@ -1382,7 +1331,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to read in mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1500,21 +1449,21 @@ /* Copy part of the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, + if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_targetinfo))) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); kfree(pmem); return -EFAULT; } /* Copy the remaining data from kernel memory to user memory */ - if (copy_to_user((char *) uarg->targetInfo, pmem, numBytes)) { + if (copy_to_user(uarg->targetInfo, pmem, numBytes)) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, (void*)pdata); + __FILE__, __LINE__, pdata); kfree(pmem); return -EFAULT; } @@ -1535,7 +1484,7 @@ static int mptctl_readtest (unsigned long arg) { - struct mpt_ioctl_test *uarg = (struct mpt_ioctl_test *) arg; + struct mpt_ioctl_test __user *uarg = (void __user *) arg; struct mpt_ioctl_test karg; MPT_ADAPTER *ioc; int iocnum; @@ -1544,7 +1493,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to read in mpt_ioctl_test struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1571,10 +1520,10 @@ /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_test))) { + if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) { printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to write out mpt_ioctl_test struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1595,7 +1544,7 @@ static int mptctl_eventquery (unsigned long arg) { - struct mpt_ioctl_eventquery *uarg = (struct mpt_ioctl_eventquery *) arg; + struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg; struct mpt_ioctl_eventquery karg; MPT_ADAPTER *ioc; int iocnum; @@ -1604,7 +1553,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to read in mpt_ioctl_eventquery struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1620,10 +1569,10 @@ /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) { + if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) { printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to write out mpt_ioctl_eventquery struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } return 0; @@ -1633,7 +1582,7 @@ static int mptctl_eventenable (unsigned long arg) { - struct mpt_ioctl_eventenable *uarg = (struct mpt_ioctl_eventenable *) arg; + struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg; struct mpt_ioctl_eventenable karg; MPT_ADAPTER *ioc; int iocnum; @@ -1642,7 +1591,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { printk(KERN_ERR "%s@%d::mptctl_eventenable - " "Unable to read in mpt_ioctl_eventenable struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1680,7 +1629,7 @@ static int mptctl_eventreport (unsigned long arg) { - struct mpt_ioctl_eventreport *uarg = (struct mpt_ioctl_eventreport *) arg; + struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg; struct mpt_ioctl_eventreport karg; MPT_ADAPTER *ioc; int iocnum; @@ -1690,7 +1639,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to read in mpt_ioctl_eventreport struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1716,10 +1665,10 @@ /* Copy the data from kernel memory to user memory */ numBytes = max * sizeof(MPT_IOCTL_EVENTS); - if (copy_to_user((char *) uarg->eventData, ioc->events, numBytes)) { + if (copy_to_user(uarg->eventData, ioc->events, numBytes)) { printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to write out mpt_ioctl_eventreport struct @ %p\n", - __FILE__, __LINE__, (void*)ioc->events); + __FILE__, __LINE__, ioc->events); return -EFAULT; } @@ -1730,7 +1679,7 @@ static int mptctl_replace_fw (unsigned long arg) { - struct mpt_ioctl_replace_fw *uarg = (struct mpt_ioctl_replace_fw *) arg; + struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg; struct mpt_ioctl_replace_fw karg; MPT_ADAPTER *ioc; fw_image_t **fwmem = NULL; @@ -1744,7 +1693,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1774,7 +1723,7 @@ if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) { printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw image @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); mpt_free_fw_memory(ioc, fwmem); return -EFAULT; @@ -1819,7 +1768,7 @@ static int mptctl_mpt_command (unsigned long arg) { - struct mpt_ioctl_command *uarg = (struct mpt_ioctl_command *) arg; + struct mpt_ioctl_command __user *uarg = (void __user *) arg; struct mpt_ioctl_command karg; MPT_ADAPTER *ioc; int iocnum; @@ -1830,7 +1779,7 @@ if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) { printk(KERN_ERR "%s@%d::mptctl_mpt_command - " "Unable to read in mpt_ioctl_command struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1841,7 +1790,7 @@ return -ENODEV; } - rc = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0); + rc = mptctl_do_mpt_command (karg, &uarg->MF); return rc; } @@ -1859,7 +1808,7 @@ * -EPERM if SCSI I/O and target is untagged */ static int -mptctl_do_mpt_command (struct mpt_ioctl_command karg, char *mfPtr, int local) +mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) { MPT_ADAPTER *ioc; MPT_FRAME_HDR *mf = NULL; @@ -1923,23 +1872,15 @@ /* Copy the request frame * Reset the saved message context. + * Request frame in user space */ - if (local) { - /* Request frame in kernel space - */ - memcpy((char *)mf, (char *) mfPtr, karg.dataSgeOffset * 4); - } else { - /* Request frame in user space - */ - if (copy_from_user((char *)mf, (char *) mfPtr, - karg.dataSgeOffset * 4)){ - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " - "Unable to read MF from mpt_ioctl_command struct @ %p\n", - __FILE__, __LINE__, (void*)mfPtr); - rc = -EFAULT; - goto done_free_mem; - } - } + if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Unable to read MF from mpt_ioctl_command struct @ %p\n", + __FILE__, __LINE__, mfPtr); + rc = -EFAULT; + goto done_free_mem; + } hdr->MsgContext = cpu_to_le32(msgContext); @@ -2220,7 +2161,7 @@ "%s@%d::mptctl_do_mpt_command - Unable " "to read user data " "struct @ %p\n", - __FILE__, __LINE__,(void*)karg.dataOutBufPtr); + __FILE__, __LINE__,karg.dataOutBufPtr); rc = -EFAULT; goto done_free_mem; } @@ -2321,12 +2262,12 @@ } if (sz > 0) { - if (copy_to_user((char *)karg.replyFrameBufPtr, + if (copy_to_user(karg.replyFrameBufPtr, &ioc->ioctl->ReplyFrame, sz)){ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write out reply frame %p\n", - __FILE__, __LINE__, (void*)karg.replyFrameBufPtr); + __FILE__, __LINE__, karg.replyFrameBufPtr); rc = -ENODATA; goto done_free_mem; } @@ -2338,11 +2279,11 @@ if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) { sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); if (sz > 0) { - if (copy_to_user((char *)karg.senseDataPtr, ioc->ioctl->sense, sz)) { + if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write sense data to user %p\n", __FILE__, __LINE__, - (void*)karg.senseDataPtr); + karg.senseDataPtr); rc = -ENODATA; goto done_free_mem; } @@ -2355,12 +2296,12 @@ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) && (karg.dataInSize > 0) && (bufIn.kptr)) { - if (copy_to_user((char *)karg.dataInBufPtr, + if (copy_to_user(karg.dataInBufPtr, bufIn.kptr, karg.dataInSize)) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write data to user %p\n", __FILE__, __LINE__, - (void*)karg.dataInBufPtr); + karg.dataInBufPtr); rc = -ENODATA; } } @@ -2413,7 +2354,7 @@ static int mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) { - hp_host_info_t *uarg = (hp_host_info_t *) arg; + hp_host_info_t __user *uarg = (void __user *) arg; MPT_ADAPTER *ioc; struct pci_dev *pdev; char *pbuf; @@ -2437,7 +2378,7 @@ if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) { printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " "Unable to read in hp_host_info struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2455,10 +2396,8 @@ karg.vendor = pdev->vendor; karg.device = pdev->device; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) karg.subsystem_id = pdev->subsystem_device; karg.subsystem_vendor = pdev->subsystem_vendor; -#endif karg.devfn = pdev->devfn; karg.bus = pdev->bus->number; @@ -2540,7 +2479,7 @@ break; } - karg.base_io_addr = pdev->PCI_BASEADDR_START(0); + karg.base_io_addr = pci_resource_start(pdev, 0); if ((int)ioc->chip_type <= (int) FC929) karg.bus_phys_width = HP_BUS_WIDTH_UNK; @@ -2576,11 +2515,10 @@ /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, - sizeof(hp_host_info_t))) { + if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) { printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - " "Unable to write out hp_host_info @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2602,7 +2540,7 @@ static int mptctl_hp_targetinfo(unsigned long arg) { - hp_target_info_t *uarg = (hp_target_info_t *) arg; + hp_target_info_t __user *uarg = (void __user *) arg; SCSIDevicePage0_t *pg0_alloc; SCSIDevicePage3_t *pg3_alloc; MPT_ADAPTER *ioc; @@ -2619,7 +2557,7 @@ if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) { printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " "Unable to read in hp_host_targetinfo struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2727,10 +2665,10 @@ /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) { + if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) { printk(KERN_ERR "%s@%d::mptctl_hp_target_info - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2739,20 +2677,10 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51) -#define owner_THIS_MODULE .owner = THIS_MODULE, -#else -#define owner_THIS_MODULE -#endif - static struct file_operations mptctl_fops = { - owner_THIS_MODULE + .owner = THIS_MODULE, .llseek = no_llseek, - .read = mptctl_read, - .write = mptctl_write, .ioctl = mptctl_ioctl, - .open = mptctl_open, - .release = mptctl_release, }; static struct miscdevice mptctl_miscdev = { @@ -2800,7 +2728,7 @@ dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n")); - if (copy_from_user(&kfw32, (char *)arg, sizeof(kfw32))) + if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32))) return -EFAULT; /* Verify intended MPT adapter */ @@ -2817,7 +2745,7 @@ kfw.iocnum = iocnum; kfw.fwlen = kfw32.fwlen; - kfw.bufp = (void *)(unsigned long)kfw32.bufp; + kfw.bufp = compat_ptr(kfw32.bufp); ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); @@ -2831,7 +2759,7 @@ unsigned long arg, struct file *filp) { struct mpt_ioctl_command32 karg32; - struct mpt_ioctl_command32 *uarg = (struct mpt_ioctl_command32 *) arg; + struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg; struct mpt_ioctl_command karg; MPT_ADAPTER *iocp = NULL; int iocnum, iocnumX; @@ -2840,7 +2768,7 @@ dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n")); - if (copy_from_user(&karg32, (char *)arg, sizeof(karg32))) + if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) return -EFAULT; /* Verify intended MPT adapter */ @@ -2866,14 +2794,14 @@ karg.maxSenseBytes = karg32.maxSenseBytes; karg.dataSgeOffset = karg32.dataSgeOffset; - karg.replyFrameBufPtr = (char *)(unsigned long)karg32.replyFrameBufPtr; - karg.dataInBufPtr = (char *)(unsigned long)karg32.dataInBufPtr; - karg.dataOutBufPtr = (char *)(unsigned long)karg32.dataOutBufPtr; - karg.senseDataPtr = (char *)(unsigned long)karg32.senseDataPtr; + karg.replyFrameBufPtr = (char __user *)(unsigned long)karg32.replyFrameBufPtr; + karg.dataInBufPtr = (char __user *)(unsigned long)karg32.dataInBufPtr; + karg.dataOutBufPtr = (char __user *)(unsigned long)karg32.dataOutBufPtr; + karg.senseDataPtr = (char __user *)(unsigned long)karg32.senseDataPtr; /* Pass new structure to do_mpt_command */ - ret = mptctl_do_mpt_command (karg, (char *) &uarg->MF, 0); + ret = mptctl_do_mpt_command (karg, &uarg->MF); up(&mptctl_syscall_sem_ioc[iocp->id]); diff -Nru a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h --- a/drivers/message/fusion/mptctl.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/message/fusion/mptctl.h 2004-06-20 13:00:24 -07:00 @@ -115,7 +115,7 @@ struct mpt_fw_xfer { unsigned int iocnum; /* IOC unit number */ unsigned int fwlen; - void *bufp; /* Pointer to firmware buffer */ + void __user *bufp; /* Pointer to firmware buffer */ }; #if defined(__KERNEL__) && defined(CONFIG_COMPAT) @@ -332,10 +332,10 @@ struct mpt_ioctl_command { mpt_ioctl_header hdr; int timeout; /* optional (seconds) */ - char *replyFrameBufPtr; - char *dataInBufPtr; - char *dataOutBufPtr; - char *senseDataPtr; + char __user *replyFrameBufPtr; + char __user *dataInBufPtr; + char __user *dataOutBufPtr; + char __user *senseDataPtr; int maxReplyBytes; int dataInSize; int dataOutSize; diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c --- a/drivers/message/fusion/mptlan.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/message/fusion/mptlan.c 2004-06-20 13:00:24 -07:00 @@ -133,7 +133,7 @@ u32 total_received; struct net_device_stats stats; /* Per device statistics */ - struct mpt_work_struct post_buckets_task; + struct work_struct post_buckets_task; unsigned long post_buckets_active; }; @@ -880,18 +880,9 @@ if (test_and_set_bit(0, &priv->post_buckets_active) == 0) { if (priority) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41) schedule_work(&priv->post_buckets_task); -#else - queue_task(&priv->post_buckets_task, &tq_immediate); - mark_bh(IMMEDIATE_BH); -#endif } else { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,41) schedule_delayed_work(&priv->post_buckets_task, 1); -#else - queue_task(&priv->post_buckets_task, &tq_timer); -#endif dioprintk((KERN_INFO MYNAM ": post_buckets queued on " "timer.\n")); } @@ -1391,8 +1382,8 @@ priv->mpt_dev = mpt_dev; priv->pnum = pnum; - memset(&priv->post_buckets_task, 0, sizeof(struct mpt_work_struct)); - MPT_INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev); + memset(&priv->post_buckets_task, 0, sizeof(struct work_struct)); + INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev); priv->post_buckets_active = 0; dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n", @@ -1566,10 +1557,6 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,59) -MODULE_PARM(tx_max_out_p, "i"); -MODULE_PARM(max_buckets_out, "i"); // Debug stuff. FIXME! -#endif module_init(mpt_lan_init); module_exit(mpt_lan_exit); diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/message/fusion/mptscsih.c 2004-06-20 13:00:26 -07:00 @@ -74,6 +74,8 @@ #include /* for mdelay */ #include /* needed for in_interrupt() proto */ #include /* notifier code */ +#include +#include #include "../../scsi/scsi.h" #include @@ -185,7 +187,7 @@ static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); -static struct mpt_work_struct mptscsih_rstTask; +static struct work_struct mptscsih_rstTask; #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); @@ -231,7 +233,7 @@ static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED; static int dvtaskQ_active = 0; static int dvtaskQ_release = 0; -static struct mpt_work_struct mptscsih_dvTask; +static struct work_struct mptscsih_dvTask; #endif /* @@ -249,31 +251,7 @@ static Scsi_Cmnd *foo_to[8]; #endif -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* see mptscsih.h */ - -static struct scsi_host_template driver_template = { - .proc_name = "mptscsih", - .proc_info = x_scsi_proc_info, - .name = "MPT SCSI Host", - .info = x_scsi_info, - .queuecommand = x_scsi_queuecommand, - .slave_alloc = x_scsi_slave_alloc, - .slave_configure = x_scsi_slave_configure, - .slave_destroy = x_scsi_slave_destroy, - .eh_abort_handler = x_scsi_abort, - .eh_device_reset_handler = x_scsi_dev_reset, - .eh_bus_reset_handler = x_scsi_bus_reset, - .eh_host_reset_handler = x_scsi_host_reset, - .bios_param = x_scsi_bios_param, - .can_queue = MPT_SCSI_CAN_QUEUE, - .this_id = -1, - .sg_tablesize = MPT_SCSI_SG_DEPTH, - .max_sectors = MPT_SCSI_MAX_SECTORS, - .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, - .use_clustering = ENABLE_CLUSTERING, -}; +static struct scsi_host_template driver_template; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -1459,7 +1437,6 @@ } sh->max_lun = MPT_LAST_LUN + 1; - sh->max_sectors = MPT_SCSI_MAX_SECTORS; sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; @@ -1800,8 +1777,8 @@ } dprintk((MYIOC_s_INFO_FMT - "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n", - hd->ioc->name, sz1, szchain, sz3, sztarget)); + "Free'd ScsiLookup (%d) Target (%d+%d) memory\n", + hd->ioc->name, sz1, sz3, sztarget)); dprintk(("Free'd done and free Q (%d) memory\n", szQ)); /* NULL the Scsi_Host pointer @@ -1879,9 +1856,9 @@ if (!dvtaskQ_active) { dvtaskQ_active = 1; spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - MPT_INIT_WORK(&mptscsih_dvTask, + INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); - SCHEDULE_TASK(&mptscsih_dvTask); + schedule_work(&mptscsih_dvTask); } else { spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } @@ -1902,7 +1879,6 @@ #endif }; - /* SCSI host fops start here... */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** @@ -2434,9 +2410,9 @@ if (!dvtaskQ_active) { dvtaskQ_active = 1; spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); + INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); - SCHEDULE_TASK(&mptscsih_dvTask); + schedule_work(&mptscsih_dvTask); } else { spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } @@ -3905,6 +3881,29 @@ return 1; /* currently means nothing really */ } +static struct scsi_host_template driver_template = { + .proc_name = "mptscsih", + .proc_info = mptscsih_proc_info, + .name = "MPT SCSI Host", + .info = mptscsih_info, + .queuecommand = mptscsih_qcmd, + .slave_alloc = mptscsih_slave_alloc, + .slave_configure = mptscsih_slave_configure, + .slave_destroy = mptscsih_slave_destroy, + .eh_abort_handler = mptscsih_abort, + .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_SCSI_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, +}; + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Private data... @@ -4950,8 +4949,8 @@ /* Call the reset handler. Already had a TM request * timeout - so issue a diagnostic reset */ - MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd); - SCHEDULE_TASK(&mptscsih_rstTask); + INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd); + schedule_work(&mptscsih_rstTask); return; } diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h --- a/drivers/message/fusion/mptscsih.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/message/fusion/mptscsih.h 2004-06-20 13:00:26 -07:00 @@ -108,75 +108,4 @@ MPTSCSIH_SAF_TE, \ } - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Various bits and pieces broke within the lk-2.4.0-testN series:-( - * So here are various HACKS to work around them. - */ - -/* - * tq_scheduler disappeared @ lk-2.4.0-test12 - * (right when newly defined TQ_ACTIVE) - * tq_struct reworked in 2.5.41. Include workqueue.h. - */ -# include -# include -#define SCHEDULE_TASK(x) \ - if (schedule_work(x) == 0) { \ - /*MOD_DEC_USE_COUNT*/; \ - } - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#define x_scsi_info mptscsih_info -#define x_scsi_queuecommand mptscsih_qcmd -#define x_scsi_abort mptscsih_abort -#define x_scsi_bus_reset mptscsih_bus_reset -#define x_scsi_dev_reset mptscsih_dev_reset -#define x_scsi_host_reset mptscsih_host_reset -#define x_scsi_bios_param mptscsih_bios_param - -#define x_scsi_slave_alloc mptscsih_slave_alloc -#define x_scsi_slave_configure mptscsih_slave_configure -#define x_scsi_slave_destroy mptscsih_slave_destroy -#define x_scsi_proc_info mptscsih_proc_info - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MPT SCSI Host / Initiator decls... - */ -extern const char *x_scsi_info(struct Scsi_Host *); -extern int x_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -extern int x_scsi_abort(Scsi_Cmnd *); -extern int x_scsi_bus_reset(Scsi_Cmnd *); -extern int x_scsi_dev_reset(Scsi_Cmnd *); -extern int x_scsi_host_reset(Scsi_Cmnd *); -extern int x_scsi_bios_param(struct scsi_device * sdev, struct block_device *bdev, - sector_t capacity, int geom[]); -extern int x_scsi_slave_alloc(Scsi_Device *); -extern int x_scsi_slave_configure(Scsi_Device *); -extern void x_scsi_slave_destroy(Scsi_Device *); -extern int x_scsi_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* include/scsi/scsi.h may not be quite complete... */ -#ifndef RESERVE_10 -#define RESERVE_10 0x56 #endif -#ifndef RELEASE_10 -#define RELEASE_10 0x57 -#endif -#ifndef PERSISTENT_RESERVE_IN -#define PERSISTENT_RESERVE_IN 0x5e -#endif -#ifndef PERSISTENT_RESERVE_OUT -#define PERSISTENT_RESERVE_OUT 0x5f -#endif - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#endif - diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/message/i2o/i2o_block.c 2004-06-20 13:00:25 -07:00 @@ -280,8 +280,8 @@ { struct i2o_controller *c = dev->controller; int tid = dev->tid; - unsigned long msg; - unsigned long mptr; + void *msg; + void *mptr; u64 offset; struct request *req = ireq->req; int count = req->nr_sectors<<9; @@ -291,7 +291,7 @@ // printk(KERN_INFO "i2ob_send called\n"); /* Map the message to a virtual address */ - msg = c->mem_offset + m; + msg = c->msg_virt + m; sgnum = i2ob_build_sglist(dev, ireq); @@ -479,7 +479,7 @@ /* Now flush the message by making it a NOP */ m[0]&=0x00FFFFFF; m[0]|=(I2O_CMD_UTIL_NOP)<<24; - i2o_post_message(c, ((unsigned long)m) - c->mem_offset); + i2o_post_message(c, (unsigned long) m - (unsigned long) c->msg_virt); return; } diff -Nru a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c --- a/drivers/message/i2o/i2o_config.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/message/i2o/i2o_config.c 2004-06-20 13:00:25 -07:00 @@ -97,7 +97,7 @@ u32 *msg = (u32 *)m; if (msg[0] & MSG_FAIL) { - u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]); + u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]); printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n"); diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c --- a/drivers/message/i2o/i2o_core.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/message/i2o/i2o_core.c 2004-06-20 13:00:25 -07:00 @@ -354,7 +354,7 @@ if (msg[0] & MSG_FAIL) // Fail bit is set { - u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]); + u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]); i2o_report_status(KERN_INFO, "i2o_core", msg); i2o_dump_message(preserved_msg); @@ -1794,7 +1794,7 @@ m=i2o_wait_message(c, "AdapterReset"); if(m==0xFFFFFFFF) return -ETIMEDOUT; - msg=(u32 *)(c->mem_offset+m); + msg=(u32 *)(c->msg_virt+m); status = pci_alloc_consistent(c->pdev, 4, &status_phys); if(status == NULL) { @@ -1923,7 +1923,7 @@ m=i2o_wait_message(c, "StatusGet"); if(m==0xFFFFFFFF) return -ETIMEDOUT; - msg=(u32 *)(c->mem_offset+m); + msg=(u32 *)(c->msg_virt+m); msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID; @@ -2344,7 +2344,7 @@ m=i2o_wait_message(c, "OutboundInit"); if(m==0xFFFFFFFF) return -ETIMEDOUT; - msg=(u32 *)(c->mem_offset+m); + msg=(u32 *)(c->msg_virt+m); status = pci_alloc_consistent(c->pdev, 4, &status_phys); if (status==NULL) { @@ -2618,7 +2618,7 @@ sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ?? sys_tbl->iops[count].iop_capabilities = iop->status_block->iop_capabilities; - sys_tbl->iops[count].inbound_low = iop->post_port; + sys_tbl->iops[count].inbound_low = (u32)iop->post_port; sys_tbl->iops[count].inbound_high = 0; // FIXME: 64-bit support count++; @@ -2666,7 +2666,7 @@ c->name); return -ETIMEDOUT; } - msg = (u32 *)(c->mem_offset + m); + msg = (u32 *)(c->msg_virt + m); memcpy_toio(msg, data, len); i2o_post_message(c,m); return 0; @@ -3592,7 +3592,9 @@ I2O_IRQ_WRITE32(c,0xFFFFFFFF); if(c->irq > 0) free_irq(c->irq, c); - iounmap(((u8 *)c->post_port)-0x40); + iounmap(c->base_virt); + if(c->raptor) + iounmap(c->msg_virt); #ifdef CONFIG_MTRR if(c->mtrr_reg0 > 0) @@ -3633,9 +3635,12 @@ { struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller), GFP_KERNEL); - unsigned long mem; - u32 memptr = 0; - u32 size; + void *bar0_virt; + void *bar1_virt; + unsigned long bar0_phys = 0; + unsigned long bar1_phys = 0; + unsigned long bar0_size = 0; + unsigned long bar1_size = 0; int i; @@ -3646,37 +3651,9 @@ } memset(c, 0, sizeof(*c)); - for(i=0; i<6; i++) - { - /* Skip I/O spaces */ - if(!(pci_resource_flags(dev, i) & IORESOURCE_IO)) - { - memptr = pci_resource_start(dev, i); - break; - } - } - - if(i==6) - { - printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n"); - kfree(c); - return -EINVAL; - } - - size = dev->resource[i].end-dev->resource[i].start+1; - /* Map the I2O controller */ - - printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size); - mem = (unsigned long)ioremap(memptr, size); - if(mem==0) - { - printk(KERN_ERR "i2o: Unable to map controller.\n"); - kfree(c); - return -EINVAL; - } - c->irq = -1; c->dpt = 0; + c->raptor = 0; c->short_req = 0; c->pdev = dev; @@ -3684,13 +3661,6 @@ c->context_list_lock = SPIN_LOCK_UNLOCKED; #endif - c->irq_mask = mem+0x34; - c->post_port = mem+0x40; - c->reply_port = mem+0x44; - - c->mem_phys = memptr; - c->mem_offset = mem; - /* * Cards that fall apart if you hit them with large I/O * loads... @@ -3701,6 +3671,7 @@ c->short_req = 1; printk(KERN_INFO "I2O: Symbios FC920 workarounds activated.\n"); } + if(dev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { c->promise = 1; @@ -3712,15 +3683,85 @@ * them */ - if(dev->vendor == PCI_VENDOR_ID_DPT) + if(dev->vendor == PCI_VENDOR_ID_DPT) { c->dpt=1; + if(dev->device == 0xA511) + c->raptor=1; + } + + for(i=0; i<6; i++) + { + /* Skip I/O spaces */ + if(!(pci_resource_flags(dev, i) & IORESOURCE_IO)) + { + if(!bar0_phys) + { + bar0_phys = pci_resource_start(dev, i); + bar0_size = pci_resource_len(dev, i); + if(!c->raptor) + break; + } + else + { + bar1_phys = pci_resource_start(dev, i); + bar1_size = pci_resource_len(dev, i); + break; + } + } + } + + if(i==6) + { + printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n"); + kfree(c); + return -EINVAL; + } + + + /* Map the I2O controller */ + if(!c->raptor) + printk(KERN_INFO "i2o: PCI I2O controller at %08lX size=%ld\n", bar0_phys, bar0_size); + else + printk(KERN_INFO "i2o: PCI I2O controller\n BAR0 at 0x%08lX size=%ld\n BAR1 at 0x%08lX size=%ld\n", bar0_phys, bar0_size, bar1_phys, bar1_size); + + bar0_virt = ioremap(bar0_phys, bar0_size); + if(bar0_virt==0) + { + printk(KERN_ERR "i2o: Unable to map controller.\n"); + kfree(c); + return -EINVAL; + } + + if(c->raptor) + { + bar1_virt = ioremap(bar1_phys, bar1_size); + if(bar1_virt==0) + { + printk(KERN_ERR "i2o: Unable to map controller.\n"); + kfree(c); + iounmap(bar0_virt); + return -EINVAL; + } + } else { + bar1_virt = bar0_virt; + bar1_phys = bar0_phys; + bar1_size = bar0_size; + } + + c->irq_mask = bar0_virt+0x34; + c->post_port = bar0_virt+0x40; + c->reply_port = bar0_virt+0x44; + + c->base_phys = bar0_phys; + c->base_virt = bar0_virt; + c->msg_phys = bar1_phys; + c->msg_virt = bar1_virt; /* * Enable Write Combining MTRR for IOP's memory region */ #ifdef CONFIG_MTRR - c->mtrr_reg0 = - mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1); + c->mtrr_reg0 = mtrr_add(c->base_phys, bar0_size, MTRR_TYPE_WRCOMB, 1); /* * If it is an INTEL i960 I/O processor then set the first 64K to * Uncacheable since the region contains the Messaging unit which @@ -3730,14 +3771,16 @@ if(dev->vendor == PCI_VENDOR_ID_INTEL || dev->vendor == PCI_VENDOR_ID_DPT) { printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); - c->mtrr_reg1 = mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1); + c->mtrr_reg1 = mtrr_add(c->base_phys, 65536, MTRR_TYPE_UNCACHABLE, 1); if(c->mtrr_reg1< 0) { printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n"); - mtrr_del(c->mtrr_reg0, c->mem_phys, size); + mtrr_del(c->mtrr_reg0, c->msg_phys, bar1_size); c->mtrr_reg0 = -1; } } + if(c->raptor) + c->mtrr_reg1 = mtrr_add(c->msg_phys, bar1_size, MTRR_TYPE_WRCOMB, 1); #endif @@ -3749,7 +3792,9 @@ { printk(KERN_ERR "i2o: Unable to install controller.\n"); kfree(c); - iounmap((void *)mem); + iounmap(bar0_virt); + if(c->raptor) + iounmap(bar1_virt); return i; } @@ -3764,7 +3809,9 @@ c->name, dev->irq); c->irq = -1; i2o_delete_controller(c); - iounmap((void *)mem); + iounmap(bar0_virt); + if(c->raptor) + iounmap(bar1_virt); return -EBUSY; } } @@ -3797,10 +3844,12 @@ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O) + if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O && + (dev->vendor!=PCI_VENDOR_ID_DPT || dev->device!=0xA511)) continue; - if((dev->class&0xFF)>1) + if((dev->class>>8)==PCI_CLASS_INTELLIGENT_I2O && + (dev->class&0xFF)>1) { printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n"); continue; diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c --- a/drivers/message/i2o/i2o_scsi.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/message/i2o/i2o_scsi.c 2004-06-20 13:00:25 -07:00 @@ -59,9 +59,11 @@ #include #include #include -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include +#include +#include +#include #define VERSION_STRING "Version 0.1.2" @@ -186,7 +188,7 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg) { - Scsi_Cmnd *current_command; + struct scsi_cmnd *current_command; spinlock_t *lock; u32 *m = (u32 *)msg; u8 as,ds,st; @@ -230,7 +232,7 @@ { spin_unlock_irqrestore(&retry_lock, flags); /* Create a scsi error for this */ - current_command = (Scsi_Cmnd *)i2o_context_list_get(m[3], c); + current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c); if(!current_command) return; @@ -277,7 +279,7 @@ return; } - current_command = (Scsi_Cmnd *)i2o_context_list_get(m[3], c); + current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c); /* * Is this a control request coming back - eg an abort ? @@ -330,10 +332,17 @@ */ current_command->result = DID_OK << 16 | ds; - if (current_command->use_sg) - pci_unmap_sg(c->pdev, (struct scatterlist *)current_command->buffer, current_command->use_sg, scsi_to_pci_dma_dir(current_command->sc_data_direction)); - else if (current_command->request_bufflen) - pci_unmap_single(c->pdev, (dma_addr_t)((long)current_command->SCp.ptr), current_command->request_bufflen, scsi_to_pci_dma_dir(current_command->sc_data_direction)); + if (current_command->use_sg) { + pci_unmap_sg(c->pdev, + (struct scatterlist *)current_command->buffer, + current_command->use_sg, + current_command->sc_data_direction); + } else if (current_command->request_bufflen) { + pci_unmap_single(c->pdev, + (dma_addr_t)((long)current_command->SCp.ptr), + current_command->request_bufflen, + current_command->sc_data_direction); + } lock = current_command->device->host->host_lock; spin_lock_irqsave(lock, flags); @@ -461,7 +470,7 @@ * scsi controller and then let the enumeration fake up the rest */ -static int i2o_scsi_detect(Scsi_Host_Template * tpnt) +static int i2o_scsi_detect(struct scsi_host_template * tpnt) { struct Scsi_Host *shpnt = NULL; int i; @@ -592,12 +601,13 @@ * Locks: takes the controller lock on error path only */ -static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) +static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, + void (*done) (struct scsi_cmnd *)) { int i; int tid; struct i2o_controller *c; - Scsi_Cmnd *current_command; + struct scsi_cmnd *current_command; struct Scsi_Host *host; struct i2o_scsi_host *hostdata; u32 *msg, *mptr; @@ -659,7 +669,7 @@ if(m==0xFFFFFFFF) return 1; - msg = (u32 *)(c->mem_offset + m); + msg = (u32 *)(c->msg_virt + m); /* * Put together a scsi execscb message @@ -668,19 +678,14 @@ len = SCpnt->request_bufflen; direction = 0x00000000; // SGL IN (osm<--iop) - if(SCpnt->sc_data_direction == SCSI_DATA_NONE) + if (SCpnt->sc_data_direction == DMA_NONE) { scsidir = 0x00000000; // DATA NO XFER - else if(SCpnt->sc_data_direction == SCSI_DATA_WRITE) - { - direction=0x04000000; // SGL OUT (osm-->iop) - scsidir =0x80000000; // DATA OUT (iop-->dev) - } - else if(SCpnt->sc_data_direction == SCSI_DATA_READ) - { - scsidir =0x40000000; // DATA IN (iop<--dev) - } - else - { + } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { + direction = 0x04000000; // SGL OUT (osm-->iop) + scsidir = 0x80000000; // DATA OUT (iop-->dev) + } else if(SCpnt->sc_data_direction == DMA_FROM_DEVICE) { + scsidir = 0x40000000; // DATA IN (iop<--dev) + } else { /* Unknown - kill the command */ SCpnt->result = DID_NO_CONNECT << 16; @@ -768,7 +773,7 @@ len = 0; sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + SCpnt->sc_data_direction); /* FIXME: handle fail */ if(!sg_count) @@ -840,7 +845,7 @@ dma_addr = pci_map_single(c->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + SCpnt->sc_data_direction); if(dma_addr == 0) BUG(); /* How to handle ?? */ SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr; @@ -883,7 +888,7 @@ * Locks: no locks are held or needed */ -int i2o_scsi_abort(Scsi_Cmnd * SCpnt) +static int i2o_scsi_abort(struct scsi_cmnd * SCpnt) { struct i2o_controller *c; struct Scsi_Host *host; @@ -929,14 +934,14 @@ * Locks: called with no lock held, requires no locks. */ -static int i2o_scsi_bus_reset(Scsi_Cmnd * SCpnt) +static int i2o_scsi_bus_reset(struct scsi_cmnd * SCpnt) { int tid; struct i2o_controller *c; struct Scsi_Host *host; struct i2o_scsi_host *hostdata; u32 m; - unsigned long msg; + void *msg; unsigned long timeout; @@ -974,7 +979,7 @@ while(time_before(jiffies, timeout)); - msg = c->mem_offset + m; + msg = c->msg_virt + m; i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg); i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4); i2o_raw_writel(scsi_context|0x80000000, msg+8); @@ -992,32 +997,6 @@ } /** - * i2o_scsi_host_reset - host reset callback - * @SCpnt: command causing the reset - * - * An I2O controller can be many things at once. While we can - * reset a controller the potential mess from doing so is vast, and - * it's better to simply hold on and pray - */ - -static int i2o_scsi_host_reset(Scsi_Cmnd * SCpnt) -{ - return FAILED; -} - -/** - * i2o_scsi_device_reset - device reset callback - * @SCpnt: command causing the reset - * - * I2O does not (AFAIK) support doing a device reset - */ - -static int i2o_scsi_device_reset(Scsi_Cmnd * SCpnt) -{ - return FAILED; -} - -/** * i2o_scsi_bios_param - Invent disk geometry * @sdev: scsi device * @dev: block layer device @@ -1048,7 +1027,7 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = { +static struct scsi_host_template driver_template = { .proc_name = "i2o_scsi", .name = "I2O SCSI Layer", .detect = i2o_scsi_detect, @@ -1057,8 +1036,6 @@ .queuecommand = i2o_scsi_queuecommand, .eh_abort_handler = i2o_scsi_abort, .eh_bus_reset_handler = i2o_scsi_bus_reset, - .eh_device_reset_handler= i2o_scsi_device_reset, - .eh_host_reset_handler = i2o_scsi_host_reset, .bios_param = i2o_scsi_bios_param, .can_queue = I2O_SCSI_CAN_QUEUE, .this_id = 15, diff -Nru a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c --- a/drivers/misc/ibmasm/ibmasmfs.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/misc/ibmasm/ibmasmfs.c 2004-06-20 13:00:25 -07:00 @@ -224,12 +224,12 @@ return dentry; } -int ibmasmfs_register() +int ibmasmfs_register(void) { return register_filesystem(&ibmasmfs_type); } -void ibmasmfs_unregister() +void ibmasmfs_unregister(void) { unregister_filesystem(&ibmasmfs_type); } @@ -287,7 +287,7 @@ return 0; } -static ssize_t command_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +static ssize_t command_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { struct ibmasmfs_command_data *command_data = file->private_data; struct command *cmd; @@ -324,7 +324,7 @@ return len; } -static ssize_t command_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset) +static ssize_t command_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) { struct ibmasmfs_command_data *command_data = file->private_data; struct command *cmd; @@ -345,7 +345,7 @@ if (!cmd) return -ENOMEM; - if (copy_from_user((void *)cmd->buffer, (void *)ubuff, count)) { + if (copy_from_user(cmd->buffer, ubuff, count)) { command_put(cmd); return -EFAULT; } @@ -395,7 +395,7 @@ return 0; } -static ssize_t event_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +static ssize_t event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { struct ibmasmfs_event_data *event_data = file->private_data; struct event_reader *reader = &event_data->reader; @@ -421,7 +421,7 @@ return reader->data_size; } -static ssize_t event_file_write(struct file *file, const char *buf, size_t count, loff_t *offset) +static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { struct ibmasmfs_event_data *event_data = file->private_data; @@ -462,7 +462,7 @@ return 0; } -static ssize_t r_heartbeat_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +static ssize_t r_heartbeat_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; unsigned long flags; @@ -490,7 +490,7 @@ return result; } -static ssize_t r_heartbeat_file_write(struct file *file, const char *buf, size_t count, loff_t *offset) +static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; @@ -518,7 +518,7 @@ return 0; } -static ssize_t remote_settings_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { unsigned long address = (unsigned long)file->private_data; unsigned char *page; @@ -552,7 +552,7 @@ return retval; } -static ssize_t remote_settings_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset) +static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) { unsigned long address = (unsigned long)file->private_data; char *buff; @@ -571,7 +571,7 @@ memset(buff, 0x0, count + 1); - if (copy_from_user((void *)buff, (void *)ubuff, count)) { + if (copy_from_user(buff, ubuff, count)) { kfree(buff); return -EFAULT; } @@ -618,7 +618,7 @@ return 0; } -static ssize_t remote_event_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { struct service_processor *sp = file->private_data; struct remote_queue *q = &sp->remote_queue; @@ -663,7 +663,7 @@ .open = event_file_open, .release = event_file_close, .read = event_file_read, - .write event_file_write, + .write = event_file_write, }; static struct file_operations r_heartbeat_fops = { diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/mtd/mtdblock.c 2004-06-20 13:00:24 -07:00 @@ -275,7 +275,7 @@ /* OK, it's not open. Create cache info for it */ mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); - if (!mtdblks) + if (!mtdblk) return -ENOMEM; memset(mtdblk, 0, sizeof(*mtdblk)); diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c --- a/drivers/net/3c501.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/3c501.c 2004-06-20 13:00:23 -07:00 @@ -225,7 +225,7 @@ * Reserve I/O resource for exclusive use by this driver */ - if (!request_region(ioaddr, EL1_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, EL1_IO_EXTENT, DRV_NAME)) return -ENODEV; /* diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c --- a/drivers/net/3c503.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/3c503.c 2004-06-20 13:00:25 -07:00 @@ -147,6 +147,7 @@ release_region(dev->base_addr, EL2_IO_EXTENT); } +#ifndef MODULE struct net_device * __init el2_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -171,6 +172,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* Probe for the Etherlink II card at I/O port base IOADDR, returning non-zero on success. If found, set the station @@ -182,10 +184,10 @@ static unsigned version_printed; unsigned long vendor_id; - if (!request_region(ioaddr, EL2_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME)) return -EBUSY; - if (!request_region(ioaddr + 0x400, 8, dev->name)) { + if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) { retval = -EBUSY; goto out; } diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c --- a/drivers/net/3c505.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/3c505.c 2004-06-20 13:00:26 -07:00 @@ -1614,6 +1614,7 @@ return err; } +#ifndef MODULE struct net_device * __init elplus_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(elp_device)); @@ -1632,7 +1633,7 @@ return dev; } -#ifdef MODULE +#else static struct net_device *dev_3c505[ELP_MAX_CARDS]; static int io[ELP_MAX_CARDS]; static int irq[ELP_MAX_CARDS]; diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c --- a/drivers/net/3c507.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/3c507.c 2004-06-20 13:00:25 -07:00 @@ -373,7 +373,7 @@ init_ID_done = 1; } - if (!request_region(ioaddr, EL16_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, EL16_IO_EXTENT, DRV_NAME)) return -ENODEV; if ((inb(ioaddr) != '*') || (inb(ioaddr + 1) != '3') || @@ -392,7 +392,7 @@ irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - irqval = request_irq(irq, &el16_interrupt, 0, dev->name, dev); + irqval = request_irq(irq, &el16_interrupt, 0, DRV_NAME, dev); if (irqval) { printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval); retval = -EAGAIN; diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c --- a/drivers/net/3c509.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/3c509.c 2004-06-20 13:00:23 -07:00 @@ -56,10 +56,6 @@ v1.19b 08Nov2002 Marc Zyngier - Introduce driver model for EISA cards. */ -/* - FIXES for PC-9800: - Shu Iwanaga: 3c569B(PC-9801 C-bus) support -*/ #define DRV_NAME "3c509" #define DRV_VERSION "1.19b" @@ -265,7 +261,7 @@ }; #endif /* CONFIG_MCA */ -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) static struct isapnp_device_id el3_isapnp_adapters[] __initdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), @@ -362,7 +358,7 @@ if (lp->pmdev) pm_unregister(lp->pmdev); #endif -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) if (lp->type == EL3_PNP) pnp_device_detach(to_pnp_dev(lp->dev)); #endif @@ -381,7 +377,7 @@ u16 phys_addr[3]; static int current_tag; int err = -ENODEV; -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) static int pnp_cards; struct pnp_dev *idev = NULL; @@ -436,9 +432,6 @@ no_pnp: #endif /* __ISAPNP__ */ -#ifdef CONFIG_X86_PC9800 - id_port = 0x71d0; -#else /* Select an open I/O location at 0x1*0 to do contention select. */ for ( ; id_port < 0x200; id_port += 0x10) { if (!request_region(id_port, 1, "3c509")) @@ -456,7 +449,7 @@ printk(" WARNING: No I/O port available for 3c509 activation.\n"); return -ENODEV; } -#endif /* CONFIG_X86_PC9800 */ + /* Next check for all ISA bus boards by sending the ID sequence to the ID_PORT. We find cards past the first by setting the 'current_tag' on cards as they are found. Cards with their tag set will not @@ -487,7 +480,7 @@ phys_addr[i] = htons(id_read_eeprom(i)); } -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) if (nopnp == 0) { /* The ISA PnP 3c509 cards respond to the ID sequence. This check is needed in order not to register them twice. */ @@ -512,19 +505,9 @@ { unsigned int iobase = id_read_eeprom(8); if_port = iobase >> 14; -#ifdef CONFIG_X86_PC9800 - ioaddr = 0x40d0 + ((iobase & 0x1f) << 8); -#else ioaddr = 0x200 + ((iobase & 0x1f) << 4); -#endif } irq = id_read_eeprom(9) >> 12; -#ifdef CONFIG_X86_PC9800 - if (irq == 7) - irq = 6; - else if (irq == 15) - irq = 13; -#endif dev = alloc_etherdev(sizeof (struct el3_private)); if (!dev) @@ -555,11 +538,7 @@ outb(0xd0 + ++current_tag, id_port); /* Activate the adaptor at the EEPROM location. */ -#ifdef CONFIG_X86_PC9800 - outb((ioaddr >> 8) | 0xe0, id_port); -#else outb((ioaddr >> 4) | 0xe0, id_port); -#endif EL3WINDOW(0); if (inw(ioaddr) != 0x6d50) @@ -568,7 +547,7 @@ /* Free the interrupt so that some other card can use it. */ outw(0x0f00, ioaddr + WN0_IRQ); -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) found: /* PNP jumps here... */ #endif /* __ISAPNP__ */ @@ -577,7 +556,7 @@ dev->irq = irq; dev->if_port = if_port; lp = netdev_priv(dev); -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) lp->dev = &idev->dev; #endif err = el3_common_init(dev); @@ -601,7 +580,7 @@ return 0; out1: -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) if (idev) pnp_device_detach(idev); #endif @@ -1461,12 +1440,6 @@ outw(0x0001, ioaddr + 4); /* Set the IRQ line. */ -#ifdef CONFIG_X86_PC9800 - if (dev->irq == 6) - dev->irq = 7; - else if (dev->irq == 13) - dev->irq = 15; -#endif outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ); /* Set the station address in window 2 each time opened. */ @@ -1629,7 +1602,7 @@ MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)"); MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt"); -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) MODULE_PARM(nopnp, "i"); MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)"); MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters); diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c --- a/drivers/net/3c523.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/3c523.c 2004-06-20 13:00:24 -07:00 @@ -445,7 +445,7 @@ slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); continue; } - if (!request_region(dev->base_addr, ELMC_IO_EXTENT, dev->name)) { + if (!request_region(dev->base_addr, ELMC_IO_EXTENT, DRV_NAME)) { slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); continue; } @@ -585,6 +585,7 @@ release_region(dev->base_addr, ELMC_IO_EXTENT); } +#ifndef MODULE struct net_device * __init elmc_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct priv)); @@ -609,6 +610,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /********************************************** * init the chip (elmc-interrupt should be disabled?!) diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c --- a/drivers/net/3c527.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/3c527.c 2004-06-20 13:00:24 -07:00 @@ -435,10 +435,10 @@ * Grab the IRQ */ - err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, DRV_NAME, dev); if (err) { release_region(dev->base_addr, MC32_IO_EXTENT); - printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq); goto err_exit_ports; } diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c --- a/drivers/net/3c59x.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/3c59x.c 2004-06-20 13:00:23 -07:00 @@ -446,6 +446,7 @@ CH_3C905B_2, CH_3C905B_FX, CH_3C905C, + CH_3C9202, CH_3C980, CH_3C9805, @@ -520,12 +521,14 @@ {"3c905B-FX Cyclone 100baseFx", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, {"3c905C Tornado", - PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, + {"3c920B-EMB-WNM (ATI Radeon 9100 IGP)", + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_MII|HAS_HWCKSM, 128, }, {"3c980 Cyclone", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, }, + {"3c980C Python-T", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, - {"3cSOHO100-TX Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, {"3c555 Laptop Hurricane", @@ -536,9 +539,9 @@ {"3c556B Laptop Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR| WNO_XCVR_PWR|HAS_HWCKSM, 128, }, + {"3c575 [Megahertz] 10/100 LAN CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, - {"3c575 Boomerang CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, {"3CCFE575BT Cyclone CardBus", @@ -550,10 +553,10 @@ {"3CCFE656 Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| INVERT_LED_PWR|HAS_HWCKSM, 128, }, + {"3CCFEM656B Cyclone+Winmodem CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| INVERT_LED_PWR|HAS_HWCKSM, 128, }, - {"3CXFEM656C Tornado+Winmodem CardBus", /* From pcmcia-cs-3.1.5 */ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR| MAX_COLLISION_RESET|HAS_HWCKSM, 128, }, @@ -563,9 +566,9 @@ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, }, {"3c982 Hydra Dual Port A", PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, }, + {"3c982 Hydra Dual Port B", PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, }, - {"3c905B-T4", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, {"3c920B-EMB-WNM Tornado", @@ -597,6 +600,7 @@ { 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 }, { 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX }, { 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C }, + { 0x10B7, 0x9202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9202 }, { 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 }, { 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 }, @@ -884,7 +888,7 @@ static int vortex_probe1(struct device *gendev, long ioaddr, int irq, int chip_idx, int card_idx); static void vortex_up(struct net_device *dev); -static void vortex_down(struct net_device *dev); +static void vortex_down(struct net_device *dev, int final); static int vortex_open(struct net_device *dev); static void mdio_sync(long ioaddr, int bits); static int mdio_read(struct net_device *dev, int phy_id, int location); @@ -948,7 +952,7 @@ if (dev && dev->priv) { if (netif_running(dev)) { netif_device_detach(dev); - vortex_down(dev); + vortex_down(dev, 1); } } return 0; @@ -2059,7 +2063,8 @@ printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status); /* In this case, blow the card away */ - vortex_down(dev); + /* Must not enter D3 or we can't legally issue the reset! */ + vortex_down(dev, 0); issue_and_wait(dev, TotalReset | 0xff); vortex_up(dev); /* AKPM: bug. vortex_up() assumes that the rx ring is full. It may not be. */ } else if (fifo_diag & 0x0400) @@ -2656,7 +2661,7 @@ } static void -vortex_down(struct net_device *dev) +vortex_down(struct net_device *dev, int final_down) { struct vortex_private *vp = netdev_priv(dev); long ioaddr = dev->base_addr; @@ -2685,7 +2690,7 @@ if (vp->full_bus_master_tx) outl(0, ioaddr + DownListPtr); - if (VORTEX_PCI(vp) && vp->enable_wol) { + if (final_down && VORTEX_PCI(vp) && vp->enable_wol) { pci_save_state(VORTEX_PCI(vp), vp->power_state); acpi_set_WOL(dev); } @@ -2699,7 +2704,7 @@ int i; if (netif_device_present(dev)) - vortex_down(dev); + vortex_down(dev, 1); if (vortex_debug > 1) { printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n", @@ -2869,7 +2874,7 @@ .get_drvinfo = vortex_get_drvinfo, }; -static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct vortex_private *vp = netdev_priv(dev); long ioaddr = dev->base_addr; @@ -2904,6 +2909,30 @@ return retval; } +/* + * Must power the device up to do MDIO operations + */ +static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + int err; + struct vortex_private *vp = netdev_priv(dev); + int state = 0; + + if(VORTEX_PCI(vp)) + state = VORTEX_PCI(vp)->current_state; + + /* The kernel core really should have pci_get_power_state() */ + + if(state != 0) + pci_set_power_state(VORTEX_PCI(vp), 0); + err = vortex_do_ioctl(dev, rq, cmd); + if(state != 0) + pci_set_power_state(VORTEX_PCI(vp), state); + + return err; +} + + /* Pre-Cyclone chips have no documented multicast filter, so the only multicast setting is to receive all multicast frames. At least the chip has a very clean way to set the mode, unlike many others. */ @@ -3059,14 +3088,14 @@ * here */ unregister_netdev(dev); - /* Should really use issue_and_wait() here */ - outw(TotalReset|0x14, dev->base_addr + EL3_CMD); if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ if (vp->pm_state_valid) pci_restore_state(VORTEX_PCI(vp), vp->power_state); } + /* Should really use issue_and_wait() here */ + outw(TotalReset|0x14, dev->base_addr + EL3_CMD); pci_free_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c 2004-06-20 13:00:22 -07:00 +++ b/drivers/net/8139too.c 2004-06-20 13:00:22 -07:00 @@ -87,8 +87,6 @@ "rtl8139-diag -mmmaaavvveefN" output enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log - See 8139too.txt for more details. - */ #define DRV_NAME "8139too" diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c --- a/drivers/net/82596.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/82596.c 2004-06-20 13:00:25 -07:00 @@ -58,11 +58,12 @@ #include #include #include -#include static char version[] __initdata = "82596.c $Revision: 1.5 $\n"; +#define DRV_NAME "82596" + /* DEBUG flags */ @@ -1191,7 +1192,7 @@ /* this is easy the ethernet interface can only be at 0x300 */ /* first check nothing is already registered here */ - if (!request_region(ioaddr, I596_TOTAL_SIZE, dev->name)) { + if (!request_region(ioaddr, I596_TOTAL_SIZE, DRV_NAME)) { printk(KERN_ERR "82596: IO address 0x%04x in use\n", ioaddr); err = -EBUSY; goto out; diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/Kconfig 2004-06-20 13:00:25 -07:00 @@ -922,7 +922,7 @@ config NET_ISA bool "Other ISA cards" - depends on NET_ETHERNET && ISA && !X86_PC9800 + depends on NET_ETHERNET && ISA ---help--- If your network (Ethernet) card hasn't been mentioned yet and its bus system (that's the way the cards talks to the other components @@ -1105,56 +1105,6 @@ the Ethernet-HOWTO, available from . -config NET_CBUS - bool "NEC PC-9800 C-bus cards" - depends on NET_ETHERNET && ISA && X86_PC9800 - ---help--- - If your network (Ethernet) card hasn't been mentioned yet and its - bus system (that's the way the cards talks to the other components - of your computer) is NEC PC-9800 C-Bus, say Y. - -config NE2K_CBUS - tristate "Most NE2000-based Ethernet support" - depends on NET_CBUS - select CRC32 - -config NE2K_CBUS_EGY98 - bool "Melco EGY-98 support" - depends on NE2K_CBUS - -config NE2K_CBUS_LGY98 - bool "Melco LGY-98 support" - depends on NE2K_CBUS - -config NE2K_CBUS_ICM - bool "ICM IF-27xxET support" - depends on NE2K_CBUS - -config NE2K_CBUS_IOLA98 - bool "I-O DATA LA-98 support" - depends on NE2K_CBUS - -config NE2K_CBUS_CNET98EL - bool "Contec C-NET(98)E/L support" - depends on NE2K_CBUS - -config NE2K_CBUS_CNET98EL_IO_BASE - hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)" - depends on NE2K_CBUS_CNET98EL - default "0xaaed" - -config NE2K_CBUS_ATLA98 - bool "Allied Telesis LA-98 Support" - depends on NE2K_CBUS - -config NE2K_CBUS_BDN - bool "ELECOM Laneed LD-BDN[123]A Support" - depends on NE2K_CBUS - -config NE2K_CBUS_NEC108 - bool "NEC PC-9801-108 Support" - depends on NE2K_CBUS - config SKMC tristate "SKnet MCA support" depends on NET_ETHERNET && MCA && BROKEN @@ -1287,6 +1237,19 @@ config AMD8111E_NAPI bool "Enable NAPI support" depends on AMD8111_ETH + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config ADAPTEC_STARFIRE tristate "Adaptec Starfire/DuraLAN support" @@ -1314,6 +1277,11 @@ deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. + See for more + information. + + If in doubt, say N. + config AC3200 tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)" depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL @@ -1501,6 +1469,19 @@ config E100_NAPI bool "Use Rx Polling (NAPI)" depends on E100 + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config LNE390 tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)" @@ -1605,9 +1586,7 @@ ---help--- This is a driver for the Fast Ethernet PCI network cards based on the RTL8139 chips. If you have one of those, say Y and read - as well as the - Ethernet-HOWTO, available from - . + the Ethernet-HOWTO . To compile this driver as a module, choose M here: the module will be called 8139too. This is recommended. @@ -1745,6 +1724,17 @@ If unsure, say Y. +config VIA_VELOCITY + tristate "VIA Velocity support" + depends on NET_PCI && PCI + select CRC32 + select MII + help + If you have a VIA "Velocity" based network card say Y here. + + To compile this driver as a module, choose M here. The module + will be called via-rhine. + config LAN_SAA9730 bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" depends on NET_PCI && EXPERIMENTAL && MIPS @@ -1963,6 +1953,19 @@ config E1000_NAPI bool "Use Rx Polling (NAPI)" depends on E1000 + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config MYRI_SBUS tristate "MyriCOM Gigabit Ethernet support" @@ -2148,6 +2151,19 @@ config IXGB_NAPI bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" depends on IXGB && EXPERIMENTAL + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config S2IO tristate "S2IO 10Gbe XFrame NIC" @@ -2160,6 +2176,19 @@ config S2IO_NAPI bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" depends on S2IO && EXPERIMENTAL + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. endmenu diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile --- a/drivers/net/Makefile 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/Makefile 2004-06-20 13:00:23 -07:00 @@ -52,6 +52,7 @@ obj-$(CONFIG_SK98LIN) += sk98lin/ obj-$(CONFIG_SKFP) += skfp/ obj-$(CONFIG_VIA_RHINE) += via-rhine.o +obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o # @@ -79,7 +80,6 @@ obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390.o -obj-$(CONFIG_NE2K_CBUS) += ne2k_cbus.o 8390.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o obj-$(CONFIG_HPLAN) += hp.o 8390.o obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c --- a/drivers/net/Space.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/Space.c 2004-06-20 13:00:23 -07:00 @@ -191,8 +191,8 @@ #ifdef CONFIG_E2100 /* Cabletron E21xx series. */ {e2100_probe, 0}, #endif -#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) || \ - defined(CONFIG_NE_H8300) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */ +#if defined(CONFIG_NE2000) || \ + defined(CONFIG_NE_H8300) /* ISA (use ne2k-pci for PCI cards) */ {ne_probe, 0}, #endif #ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */ diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c --- a/drivers/net/ac3200.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/ac3200.c 2004-06-20 13:00:25 -07:00 @@ -39,6 +39,8 @@ #include "8390.h" +#define DRV_NAME "ac3200" + /* Offsets from the base address. */ #define AC_NIC_BASE 0x00 #define AC_SA_PROM 0x16 /* The station address PROM. */ @@ -130,6 +132,7 @@ iounmap((void *)dev->mem_start); } +#ifndef MODULE struct net_device * __init ac3200_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -154,12 +157,13 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ac_probe1(int ioaddr, struct net_device *dev) { int i, retval; - if (!request_region(ioaddr, AC_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME)) return -EBUSY; if (inb_p(ioaddr + AC_ID_PORT) == 0xff) { @@ -203,7 +207,7 @@ printk(", assigning"); } - retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (retval) { printk (" nothing! Unable to get IRQ %d.\n", dev->irq); goto out1; diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c --- a/drivers/net/acenic.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/acenic.c 2004-06-20 13:00:24 -07:00 @@ -85,6 +85,8 @@ #include +#define DRV_NAME "acenic" + #undef INDEX_DEBUG #ifdef CONFIG_ACENIC_OMIT_TIGON_I @@ -443,6 +445,16 @@ "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; +static int ace_get_settings(struct net_device *, struct ethtool_cmd *); +static int ace_set_settings(struct net_device *, struct ethtool_cmd *); +static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); + +static struct ethtool_ops ace_ethtool_ops = { + .get_settings = ace_get_settings, + .set_settings = ace_set_settings, + .get_drvinfo = ace_get_drvinfo, +}; + static int __devinit acenic_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -480,7 +492,7 @@ dev->hard_start_xmit = &ace_start_xmit; dev->get_stats = &ace_get_stats; dev->set_multicast_list = &ace_set_multicast_list; - dev->do_ioctl = &ace_ioctl; + SET_ETHTOOL_OPS(dev, &ace_ethtool_ops); dev->set_mac_address = &ace_set_mac_addr; dev->change_mtu = &ace_change_mtu; @@ -1195,10 +1207,10 @@ } ecode = request_irq(pdev->irq, ace_interrupt, SA_SHIRQ, - dev->name, dev); + DRV_NAME, dev); if (ecode) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", - dev->name, pdev->irq); + DRV_NAME, pdev->irq); goto init_error; } else dev->irq = pdev->irq; @@ -2688,146 +2700,136 @@ return 0; } - -static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct ace_private *ap = dev->priv; struct ace_regs *regs = ap->regs; -#ifdef SIOCETHTOOL - struct ethtool_cmd ecmd; - u32 link, speed; + u32 link; - if (cmd != SIOCETHTOOL) - return -EOPNOTSUPP; - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd))) - return -EFAULT; - switch (ecmd.cmd) { - case ETHTOOL_GSET: - ecmd.supported = - (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_FIBRE); - - ecmd.port = PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = 0; - - link = readl(®s->GigLnkState); - if (link & LNK_1000MB) - ecmd.speed = SPEED_1000; - else { - link = readl(®s->FastLnkState); - if (link & LNK_100MB) - ecmd.speed = SPEED_100; - else if (link & LNK_100MB) - ecmd.speed = SPEED_10; - else - ecmd.speed = 0; - } - if (link & LNK_FULL_DUPLEX) - ecmd.duplex = DUPLEX_FULL; + memset(ecmd, 0, sizeof(struct ethtool_cmd)); + ecmd->supported = + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_FIBRE); + + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_INTERNAL; + + link = readl(®s->GigLnkState); + if (link & LNK_1000MB) + ecmd->speed = SPEED_1000; + else { + link = readl(®s->FastLnkState); + if (link & LNK_100MB) + ecmd->speed = SPEED_100; + else if (link & LNK_10MB) + ecmd->speed = SPEED_10; else - ecmd.duplex = DUPLEX_HALF; + ecmd->speed = 0; + } + if (link & LNK_FULL_DUPLEX) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; - if (link & LNK_NEGOTIATE) - ecmd.autoneg = AUTONEG_ENABLE; - else - ecmd.autoneg = AUTONEG_DISABLE; + if (link & LNK_NEGOTIATE) + ecmd->autoneg = AUTONEG_ENABLE; + else + ecmd->autoneg = AUTONEG_DISABLE; #if 0 - /* - * Current struct ethtool_cmd is insufficient - */ - ecmd.trace = readl(®s->TuneTrace); + /* + * Current struct ethtool_cmd is insufficient + */ + ecmd->trace = readl(®s->TuneTrace); - ecmd.txcoal = readl(®s->TuneTxCoalTicks); - ecmd.rxcoal = readl(®s->TuneRxCoalTicks); + ecmd->txcoal = readl(®s->TuneTxCoalTicks); + ecmd->rxcoal = readl(®s->TuneRxCoalTicks); #endif - ecmd.maxtxpkt = readl(®s->TuneMaxTxDesc); - ecmd.maxrxpkt = readl(®s->TuneMaxRxDesc); + ecmd->maxtxpkt = readl(®s->TuneMaxTxDesc); + ecmd->maxrxpkt = readl(®s->TuneMaxRxDesc); - if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - - case ETHTOOL_SSET: - link = readl(®s->GigLnkState); - if (link & LNK_1000MB) - speed = SPEED_1000; - else { - link = readl(®s->FastLnkState); - if (link & LNK_100MB) - speed = SPEED_100; - else if (link & LNK_100MB) - speed = SPEED_10; - else - speed = SPEED_100; - } + return 0; +} - link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB | - LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL; - if (!ACE_IS_TIGON_I(ap)) - link |= LNK_TX_FLOW_CTL_Y; - if (ecmd.autoneg == AUTONEG_ENABLE) - link |= LNK_NEGOTIATE; - if (ecmd.speed != speed) { - link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB); - switch (speed) { - case SPEED_1000: - link |= LNK_1000MB; - break; - case SPEED_100: - link |= LNK_100MB; - break; - case SPEED_10: - link |= LNK_10MB; - break; - } +static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct ace_private *ap = dev->priv; + struct ace_regs *regs = ap->regs; + u32 link, speed; + + link = readl(®s->GigLnkState); + if (link & LNK_1000MB) + speed = SPEED_1000; + else { + link = readl(®s->FastLnkState); + if (link & LNK_100MB) + speed = SPEED_100; + else if (link & LNK_10MB) + speed = SPEED_10; + else + speed = SPEED_100; + } + + link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB | + LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL; + if (!ACE_IS_TIGON_I(ap)) + link |= LNK_TX_FLOW_CTL_Y; + if (ecmd->autoneg == AUTONEG_ENABLE) + link |= LNK_NEGOTIATE; + if (ecmd->speed != speed) { + link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB); + switch (speed) { + case SPEED_1000: + link |= LNK_1000MB; + break; + case SPEED_100: + link |= LNK_100MB; + break; + case SPEED_10: + link |= LNK_10MB; + break; } - if (ecmd.duplex == DUPLEX_FULL) - link |= LNK_FULL_DUPLEX; + } - if (link != ap->link) { - struct cmd cmd; - printk(KERN_INFO "%s: Renegotiating link state\n", - dev->name); + if (ecmd->duplex == DUPLEX_FULL) + link |= LNK_FULL_DUPLEX; - ap->link = link; - writel(link, ®s->TuneLink); - if (!ACE_IS_TIGON_I(ap)) - writel(link, ®s->TuneFastLink); - wmb(); + if (link != ap->link) { + struct cmd cmd; + printk(KERN_INFO "%s: Renegotiating link state\n", + dev->name); - cmd.evt = C_LNK_NEGOTIATION; - cmd.code = 0; - cmd.idx = 0; - ace_issue_cmd(regs, &cmd); - } - return 0; + ap->link = link; + writel(link, ®s->TuneLink); + if (!ACE_IS_TIGON_I(ap)) + writel(link, ®s->TuneFastLink); + wmb(); - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strncpy(info.driver, "acenic", sizeof(info.driver) - 1); - sprintf(info.fw_version, "%i.%i.%i", - tigonFwReleaseMajor, tigonFwReleaseMinor, - tigonFwReleaseFix); - strncpy(info.version, version, sizeof(info.version) - 1); - if (ap && ap->pdev) - strcpy(info.bus_info, pci_name(ap->pdev)); - if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) - return -EFAULT; - return 0; - } - default: - break; + cmd.evt = C_LNK_NEGOTIATION; + cmd.code = 0; + cmd.idx = 0; + ace_issue_cmd(regs, &cmd); } - -#endif - - return -EOPNOTSUPP; + return 0; } +static void ace_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct ace_private *ap = dev->priv; + + strlcpy(info->driver, "acenic", sizeof(info->driver)); + snprintf(info->version, sizeof(info->version), "%i.%i.%i", + tigonFwReleaseMajor, tigonFwReleaseMinor, + tigonFwReleaseFix); + + if (ap->pdev) + strlcpy(info->bus_info, pci_name(ap->pdev), + sizeof(info->bus_info)); + +} /* * Set the hardware MAC address. diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h --- a/drivers/net/acenic.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/acenic.h 2004-06-20 13:00:24 -07:00 @@ -790,7 +790,6 @@ static void ace_dump_trace(struct ace_private *ap); static void ace_set_multicast_list(struct net_device *dev); static int ace_change_mtu(struct net_device *dev, int new_mtu); -static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int ace_set_mac_addr(struct net_device *dev, void *p); static void ace_set_rxtx_parms(struct net_device *dev, int jumbo); static int ace_allocate_descriptors(struct net_device *dev); diff -Nru a/drivers/net/apne.c b/drivers/net/apne.c --- a/drivers/net/apne.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/apne.c 2004-06-20 13:00:26 -07:00 @@ -49,6 +49,8 @@ /* ---- No user-serviceable parts below ---- */ +#define DRV_NAME "apne" + #define NE_BASE (dev->base_addr) #define NE_CMD 0x00 #define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ @@ -168,7 +170,7 @@ return ERR_PTR(-ENODEV); } - if (!request_region(IOBASE, 0x20, dev->name)) { + if (!request_region(IOBASE, 0x20, DRV_NAME)) { free_netdev(dev); return ERR_PTR(-EBUSY); } @@ -310,7 +312,7 @@ dev->base_addr = ioaddr; /* Install the Interrupt handler */ - i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, dev->name, dev); + i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, DRV_NAME, dev); if (i) return i; for(i = 0; i < ETHER_ADDR_LEN; i++) { diff -Nru a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig --- a/drivers/net/arm/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/arm/Kconfig 2004-06-20 13:00:25 -07:00 @@ -45,3 +45,20 @@ number (MTD support is required for this). Otherwise you will need to set a suitable hw address using ifconfig. +config SMC91X + tristate "SMC 91C9x/91C1xxx support" + select CRC32 + select MII + depends on ARM + help + This is a driver for SMC's 91x series of Ethernet chipsets, + including the SMC91C94 and the SMC91C111. Say Y if you want it + compiled into the kernel, and read the file + and the Ethernet-HOWTO, + available from . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called smc91x. If you want to compile it as a + module, say M here and read as well + as . diff -Nru a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile --- a/drivers/net/arm/Makefile 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/arm/Makefile 2004-06-20 13:00:25 -07:00 @@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_ETHERH) += etherh.o obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER1) += ether1.o +obj-$(CONFIG_SMC91X) += smc91x.o diff -Nru a/drivers/net/arm/smc91x.c b/drivers/net/arm/smc91x.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/arm/smc91x.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,2171 @@ +/* + * smc91x.c + * This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices. + * + * Copyright (C) 1996 by Erik Stahlman + * Copyright (C) 2001 Standard Microsystems Corporation + * Developed by Simple Network Magic Corporation + * Copyright (C) 2003 Monta Vista Software, Inc. + * Unified SMC91x driver by Nicolas Pitre + * + * 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 + * + * Arguments: + * io = for the base address + * irq = for the IRQ + * nowait = 0 for normal wait states, 1 eliminates additional wait states + * + * original author: + * Erik Stahlman + * + * hardware multicast code: + * Peter Cammaert + * + * contributors: + * Daris A Nevil + * Nicolas Pitre + * Russell King + * + * History: + * 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet + * 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ" + * 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111 + * 08/22/01 Scott Anderson merge changes from smc9194 to smc91111 + * 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111 + * 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support + * 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races, + * more bus abstraction, big cleanup, etc. + * 29/09/03 Russell King - add driver model support + * - ethtool support + * - convert to use generic MII interface + * - add link up/down notification + * - don't try to handle full negotiation in + * smc_phy_configure + * - clean up (and fix stack overrun) in PHY + * MII read/write functions + */ +static const char version[] = + "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre \n"; + +/* Debugging level */ +#ifndef SMC_DEBUG +#define SMC_DEBUG 0 +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "smc91x.h" + +#ifdef CONFIG_ISA +/* + * the LAN91C111 can be at any of the following port addresses. To change, + * for a slightly different card, you can add it to the array. Keep in + * mind that the array must end in zero. + */ +static unsigned int smc_portlist[] __initdata = { + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, + 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0 +}; + +#ifndef SMC_IOADDR +# define SMC_IOADDR -1 +#endif +static unsigned long io = SMC_IOADDR; +module_param(io, ulong, 0400); +MODULE_PARM_DESC(io, "I/O base address"); + +#ifndef SMC_IRQ +# define SMC_IRQ -1 +#endif +static int irq = SMC_IRQ; +module_param(irq, int, 0400); +MODULE_PARM_DESC(irq, "IRQ number"); + +#endif /* CONFIG_ISA */ + +#ifndef SMC_NOWAIT +# define SMC_NOWAIT 0 +#endif +static int nowait = SMC_NOWAIT; +module_param(nowait, int, 0400); +MODULE_PARM_DESC(nowait, "set to 1 for no wait state"); + +/* + * Transmit timeout, default 5 seconds. + */ +static int watchdog = 5000; +module_param(watchdog, int, 0400); +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); + +MODULE_LICENSE("GPL"); + +/* + * The internal workings of the driver. If you are changing anything + * here with the SMC stuff, you should have the datasheet and know + * what you are doing. + */ +#define CARDNAME "smc91x" + +/* + * Use power-down feature of the chip + */ +#define POWER_DOWN 1 + +/* + * Wait time for memory to be free. This probably shouldn't be + * tuned that much, as waiting for this means nothing else happens + * in the system + */ +#define MEMORY_WAIT_TIME 16 + +/* + * This selects whether TX packets are sent one by one to the SMC91x internal + * memory and throttled until transmission completes. This may prevent + * RX overruns a litle by keeping much of the memory free for RX packets + * but to the expense of reduced TX throughput and increased IRQ overhead. + * Note this is not a cure for a too slow data bus or too high IRQ latency. + */ +#define THROTTLE_TX_PKTS 0 + +/* + * The MII clock high/low times. 2x this number gives the MII clock period + * in microseconds. (was 50, but this gives 6.4ms for each MII transaction!) + */ +#define MII_DELAY 1 + +/* store this information for the driver.. */ +struct smc_local { + /* + * If I have to wait until memory is available to send a + * packet, I will store the skbuff here, until I get the + * desired memory. Then, I'll send it out and free it. + */ + struct sk_buff *saved_skb; + + /* + * these are things that the kernel wants me to keep, so users + * can find out semi-useless statistics of how well the card is + * performing + */ + struct net_device_stats stats; + + /* version/revision of the SMC91x chip */ + int version; + + /* Contains the current active transmission mode */ + int tcr_cur_mode; + + /* Contains the current active receive mode */ + int rcr_cur_mode; + + /* Contains the current active receive/phy mode */ + int rpc_cur_mode; + int ctl_rfduplx; + int ctl_rspeed; + + u32 msg_enable; + u32 phy_type; + struct mii_if_info mii; + spinlock_t lock; + +#ifdef SMC_USE_PXA_DMA + /* DMA needs the physical address of the chip */ + u_long physaddr; +#endif +}; + +#if SMC_DEBUG > 0 +#define DBG(n, args...) \ + do { \ + if (SMC_DEBUG >= (n)) \ + printk(KERN_DEBUG args); \ + } while (0) + +#define PRINTK(args...) printk(args) +#else +#define DBG(n, args...) do { } while(0) +#define PRINTK(args...) printk(KERN_DEBUG args) +#endif + +#if SMC_DEBUG > 3 +static void PRINT_PKT(u_char *buf, int length) +{ + int i; + int remainder; + int lines; + + lines = length / 16; + remainder = length % 16; + + for (i = 0; i < lines ; i ++) { + int cur; + for (cur = 0; cur < 8; cur++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); + } + for (i = 0; i < remainder/2 ; i++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); +} +#else +#define PRINT_PKT(x...) do { } while(0) +#endif + + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) do { \ + unsigned long flags; \ + unsigned char mask; \ + spin_lock_irqsave(&lp->lock, flags); \ + mask = SMC_GET_INT_MASK(); \ + mask |= (x); \ + SMC_SET_INT_MASK(mask); \ + spin_unlock_irqrestore(&lp->lock, flags); \ +} while (0) + +/* this disables an interrupt from the interrupt mask register */ +#define SMC_DISABLE_INT(x) do { \ + unsigned long flags; \ + unsigned char mask; \ + spin_lock_irqsave(&lp->lock, flags); \ + mask = SMC_GET_INT_MASK(); \ + mask &= ~(x); \ + SMC_SET_INT_MASK(mask); \ + spin_unlock_irqrestore(&lp->lock, flags); \ +} while (0) + +/* + * Wait while MMU is busy. This is usually in the order of a few nanosecs + * if at all, but let's avoid deadlocking the system if the hardware + * decides to go south. + */ +#define SMC_WAIT_MMU_BUSY() do { \ + if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) { \ + unsigned long timeout = jiffies + 2; \ + while (SMC_GET_MMU_CMD() & MC_BUSY) { \ + if (time_after(jiffies, timeout)) { \ + printk("%s: timeout %s line %d\n", \ + dev->name, __FILE__, __LINE__); \ + break; \ + } \ + cpu_relax(); \ + } \ + } \ +} while (0) + + +/* + * this does a soft reset on the device + */ +static void smc_reset(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int ctl, cfg; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + /* + * This resets the registers mostly to defaults, but doesn't + * affect EEPROM. That seems unnecessary + */ + SMC_SELECT_BANK(0); + SMC_SET_RCR(RCR_SOFTRST); + + /* + * Setup the Configuration Register + * This is necessary because the CONFIG_REG is not affected + * by a soft reset + */ + SMC_SELECT_BANK(1); + + cfg = CONFIG_DEFAULT; + + /* + * Setup for fast accesses if requested. If the card/system + * can't handle it then there will be no recovery except for + * a hard reset or power cycle + */ + if (nowait) + cfg |= CONFIG_NO_WAIT; + + /* + * Release from possible power-down state + * Configuration register is not affected by Soft Reset + */ + cfg |= CONFIG_EPH_POWER_EN; + + SMC_SET_CONFIG(cfg); + + /* this should pause enough for the chip to be happy */ + /* + * elaborate? What does the chip _need_? --jgarzik + * + * This seems to be undocumented, but something the original + * driver(s) have always done. Suspect undocumented timing + * info/determined empirically. --rmk + */ + udelay(1); + + /* Disable transmit and receive functionality */ + SMC_SELECT_BANK(0); + SMC_SET_RCR(RCR_CLEAR); + SMC_SET_TCR(TCR_CLEAR); + + SMC_SELECT_BANK(1); + ctl = SMC_GET_CTL() | CTL_LE_ENABLE; + + /* + * Set the control register to automatically release successfully + * transmitted packets, to make the best use out of our limited + * memory + */ +#if ! THROTTLE_TX_PKTS + ctl |= CTL_AUTO_RELEASE; +#else + ctl &= ~CTL_AUTO_RELEASE; +#endif + SMC_SET_CTL(ctl); + + /* Disable all interrupts */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(0); + + /* Reset the MMU */ + SMC_SET_MMU_CMD(MC_RESET); + SMC_WAIT_MMU_BUSY(); +} + +/* + * Enable Interrupts, Receive, and Transmit + */ +static void smc_enable(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + int mask; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + /* see the header file for options in TCR/RCR DEFAULT */ + SMC_SELECT_BANK(0); + SMC_SET_TCR(lp->tcr_cur_mode); + SMC_SET_RCR(lp->rcr_cur_mode); + + /* now, enable interrupts */ + mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT; + if (lp->version >= (CHIP_91100 << 4)) + mask |= IM_MDINT; + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(mask); +} + +/* + * this puts the device in an inactive state + */ +static void smc_shutdown(unsigned long ioaddr) +{ + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + + /* no more interrupts for me */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(0); + + /* and tell the card to stay away from that nasty outside world */ + SMC_SELECT_BANK(0); + SMC_SET_RCR(RCR_CLEAR); + SMC_SET_TCR(TCR_CLEAR); + +#ifdef POWER_DOWN + /* finally, shut the chip down */ + SMC_SELECT_BANK(1); + SMC_SET_CONFIG(SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN); +#endif +} + +/* + * This is the procedure to handle the receipt of a packet. + */ +static inline void smc_rcv(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int packet_number, status, packet_len; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + packet_number = SMC_GET_RXFIFO(); + if (unlikely(packet_number & RXFIFO_REMPTY)) { + PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name); + return; + } + + /* read from start of packet */ + SMC_SET_PTR(PTR_READ | PTR_RCV | PTR_AUTOINC); + + /* First two words are status and packet length */ + SMC_GET_PKT_HDR(status, packet_len); + packet_len &= 0x07ff; /* mask off top bits */ + DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n", + dev->name, packet_number, status, + packet_len, packet_len); + + if (unlikely(status & RS_ERRORS)) { + lp->stats.rx_errors++; + if (status & RS_ALGNERR) + lp->stats.rx_frame_errors++; + if (status & (RS_TOOSHORT | RS_TOOLONG)) + lp->stats.rx_length_errors++; + if (status & RS_BADCRC) + lp->stats.rx_crc_errors++; + } else { + struct sk_buff *skb; + unsigned char *data; + unsigned int data_len; + + /* set multicast stats */ + if (status & RS_MULTICAST) + lp->stats.multicast++; + + /* + * Actual payload is packet_len - 4 (or 3 if odd byte). + * We want skb_reserve(2) and the final ctrl word + * (2 bytes, possibly containing the payload odd byte). + * Ence packet_len - 4 + 2 + 2. + */ + skb = dev_alloc_skb(packet_len); + if (unlikely(skb == NULL)) { + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", + dev->name); + lp->stats.rx_dropped++; + goto done; + } + + /* Align IP header to 32 bits */ + skb_reserve(skb, 2); + + /* BUG: the LAN91C111 rev A never sets this bit. Force it. */ + if (lp->version == 0x90) + status |= RS_ODDFRAME; + + /* + * If odd length: packet_len - 3, + * otherwise packet_len - 4. + */ + data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4); + data = skb_put(skb, data_len); + SMC_PULL_DATA(data, packet_len - 2); + + PRINT_PKT(data, packet_len - 2); + + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += data_len; + } + +done: + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD(MC_RELEASE); +} + +/* + * This is called to actually send a packet to the chip. + * Returns non-zero when successful. + */ +static void smc_hardware_send_packet(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + struct sk_buff *skb = lp->saved_skb; + unsigned int packet_no, len; + unsigned char *buf; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + packet_no = SMC_GET_AR(); + if (unlikely(packet_no & AR_FAILED)) { + printk("%s: Memory allocation failed.\n", dev->name); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_fifo_errors++; + dev_kfree_skb_any(skb); + return; + } + + /* point to the beginning of the packet */ + SMC_SET_PN(packet_no); + SMC_SET_PTR(PTR_AUTOINC); + + buf = skb->data; + len = skb->len; + DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n", + dev->name, packet_no, len, len, buf); + PRINT_PKT(buf, len); + + /* + * Send the packet length (+6 for status words, length, and ctl. + * The card will pad to 64 bytes with zeroes if packet is too small. + */ + SMC_PUT_PKT_HDR(0, len + 6); + + /* send the actual data */ + SMC_PUSH_DATA(buf, len & ~1); + + /* Send final ctl word with the last byte if there is one */ + SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG); + + /* and let the chipset deal with it */ + SMC_SET_MMU_CMD(MC_ENQUEUE); + SMC_ACK_INT(IM_TX_EMPTY_INT); + + dev->trans_start = jiffies; + dev_kfree_skb_any(skb); + lp->saved_skb = NULL; + lp->stats.tx_packets++; + lp->stats.tx_bytes += len; +} + +/* + * Since I am not sure if I will have enough room in the chip's ram + * to store the packet, I call this routine which either sends it + * now, or set the card to generates an interrupt when ready + * for the packet. + */ +static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int numPages, poll_count, status, saved_bank; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + BUG_ON(lp->saved_skb != NULL); + lp->saved_skb = skb; + + /* + * The MMU wants the number of pages to be the number of 256 bytes + * 'pages', minus 1 (since a packet can't ever have 0 pages :)) + * + * The 91C111 ignores the size bits, but earlier models don't. + * + * Pkt size for allocating is data length +6 (for additional status + * words, length and ctl) + * + * If odd size then last byte is included in ctl word. + */ + numPages = ((skb->len & ~1) + (6 - 1)) >> 8; + if (unlikely(numPages > 7)) { + printk("%s: Far too big packet error.\n", dev->name); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + /* now, try to allocate the memory */ + saved_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(2); + SMC_SET_MMU_CMD(MC_ALLOC | numPages); + + /* + * Poll the chip for a short amount of time in case the + * allocation succeeds quickly. + */ + poll_count = MEMORY_WAIT_TIME; + do { + status = SMC_GET_INT(); + if (status & IM_ALLOC_INT) { + SMC_ACK_INT(IM_ALLOC_INT); + break; + } + } while (--poll_count); + + if (!poll_count) { + /* oh well, wait until the chip finds memory later */ + netif_stop_queue(dev); + DBG(2, "%s: TX memory allocation deferred.\n", dev->name); + SMC_ENABLE_INT(IM_ALLOC_INT); + } else { + /* + * Allocation succeeded: push packet to the chip's own memory + * immediately. + * + * If THROTTLE_TX_PKTS is selected that means we don't want + * more than a single TX packet taking up space in the chip's + * internal memory at all time, in which case we stop the + * queue right here until we're notified of TX completion. + * + * Otherwise we're quite happy to feed more TX packets right + * away for better TX throughput, in which case the queue is + * left active. + */ +#if THROTTLE_TX_PKTS + netif_stop_queue(dev); +#endif + smc_hardware_send_packet(dev); + SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT); + } + + SMC_SELECT_BANK(saved_bank); + return 0; +} + +/* + * This handles a TX interrupt, which is only called when: + * - a TX error occurred, or + * - CTL_AUTO_RELEASE is not set and TX of a packet completed. + */ +static void smc_tx(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + unsigned int saved_packet, packet_no, tx_status, pkt_len; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + /* If the TX FIFO is empty then nothing to do */ + packet_no = SMC_GET_TXFIFO(); + if (unlikely(packet_no & TXFIFO_TEMPTY)) { + PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name); + return; + } + + /* select packet to read from */ + saved_packet = SMC_GET_PN(); + SMC_SET_PN(packet_no); + + /* read the first word (status word) from this packet */ + SMC_SET_PTR(PTR_AUTOINC | PTR_READ); + SMC_GET_PKT_HDR(tx_status, pkt_len); + DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n", + dev->name, tx_status, packet_no); + + if (!(tx_status & TS_SUCCESS)) + lp->stats.tx_errors++; + if (tx_status & TS_LOSTCAR) + lp->stats.tx_carrier_errors++; + + SMC_WAIT_MMU_BUSY(); + + if (tx_status & TS_LATCOL) { + PRINTK("%s: late collision occurred on last xmit\n", dev->name); + lp->stats.tx_window_errors++; + /* It's really cheap to requeue the pkt here */ + SMC_SET_MMU_CMD( MC_ENQUEUE ); + } else { + /* kill the packet */ + SMC_SET_MMU_CMD(MC_FREEPKT); + } + + /* Don't restore Packet Number Reg until busy bit is cleared */ + SMC_WAIT_MMU_BUSY(); + SMC_SET_PN(saved_packet); + + /* re-enable transmit */ + SMC_SELECT_BANK(0); + SMC_SET_TCR(lp->tcr_cur_mode); + SMC_SELECT_BANK(2); +} + + +/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ + +static void smc_mii_out(struct net_device *dev, unsigned int val, int bits) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int mii_reg, mask; + + mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO); + mii_reg |= MII_MDOE; + + for (mask = 1 << (bits - 1); mask; mask >>= 1) { + if (val & mask) + mii_reg |= MII_MDO; + else + mii_reg &= ~MII_MDO; + + SMC_SET_MII(mii_reg); + udelay(MII_DELAY); + SMC_SET_MII(mii_reg | MII_MCLK); + udelay(MII_DELAY); + } +} + +static unsigned int smc_mii_in(struct net_device *dev, int bits) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int mii_reg, mask, val; + + mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO); + SMC_SET_MII(mii_reg); + + for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) { + if (SMC_GET_MII() & MII_MDI) + val |= mask; + + SMC_SET_MII(mii_reg); + udelay(MII_DELAY); + SMC_SET_MII(mii_reg | MII_MCLK); + udelay(MII_DELAY); + } + + return val; +} + +/* + * Reads a register from the MII Management serial interface + */ +static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int phydata, old_bank; + + /* Save the current bank, and select bank 3 */ + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(3); + + /* Idle - 32 ones */ + smc_mii_out(dev, 0xffffffff, 32); + + /* Start code (01) + read (10) + phyaddr + phyreg */ + smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14); + + /* Turnaround (2bits) + phydata */ + phydata = smc_mii_in(dev, 18); + + /* Return to idle state */ + SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO)); + + /* And select original bank */ + SMC_SELECT_BANK(old_bank); + + DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + + return phydata; +} + +/* + * Writes a register to the MII Management serial interface + */ +static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, + int phydata) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int old_bank; + + /* Save the current bank, and select bank 3 */ + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(3); + + /* Idle - 32 ones */ + smc_mii_out(dev, 0xffffffff, 32); + + /* Start code (01) + write (01) + phyaddr + phyreg + turnaround + phydata */ + smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32); + + /* Return to idle state */ + SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO)); + + /* And select original bank */ + SMC_SELECT_BANK(old_bank); + + DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); +} + +/* + * Finds and reports the PHY address + */ +static void smc_detect_phy(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + int phyaddr; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + lp->phy_type = 0; + + /* + * Scan all 32 PHY addresses if necessary, starting at + * PHY#1 to PHY#31, and then PHY#0 last. + */ + for (phyaddr = 1; phyaddr < 33; ++phyaddr) { + unsigned int id1, id2; + + /* Read the PHY identifiers */ + id1 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID1); + id2 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID2); + + DBG(3, "%s: phy_id1=0x%x, phy_id2=0x%x\n", + dev->name, id1, id2); + + /* Make sure it is a valid identifier */ + if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 && + id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) { + /* Save the PHY's address */ + lp->mii.phy_id = phyaddr & 31; + lp->phy_type = id1 << 16 | id2; + break; + } + } +} + +/* + * Sets the PHY to a configuration as determined by the user + */ +static int smc_phy_fixed(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int bmcr, cfg1; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + /* Enter Link Disable state */ + cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG); + cfg1 |= PHY_CFG1_LNKDIS; + smc_phy_write(dev, phyaddr, PHY_CFG1_REG, cfg1); + + /* + * Set our fixed capabilities + * Disable auto-negotiation + */ + bmcr = 0; + + if (lp->ctl_rfduplx) + bmcr |= BMCR_FULLDPLX; + + if (lp->ctl_rspeed == 100) + bmcr |= BMCR_SPEED100; + + /* Write our capabilities to the phy control register */ + smc_phy_write(dev, phyaddr, MII_BMCR, bmcr); + + /* Re-Configure the Receive/Phy Control register */ + SMC_SET_RPC(lp->rpc_cur_mode); + + return 1; +} + +/* + * smc_phy_reset - reset the phy + * @dev: net device + * @phy: phy address + * + * Issue a software reset for the specified PHY and + * wait up to 100ms for the reset to complete. We should + * not access the PHY for 50ms after issuing the reset. + * + * The time to wait appears to be dependent on the PHY. + * + * Must be called with lp->lock locked. + */ +static int smc_phy_reset(struct net_device *dev, int phy) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned int bmcr; + int timeout; + + smc_phy_write(dev, phy, MII_BMCR, BMCR_RESET); + + for (timeout = 2; timeout; timeout--) { + spin_unlock_irq(&lp->lock); + msleep(50); + spin_lock_irq(&lp->lock); + + bmcr = smc_phy_read(dev, phy, MII_BMCR); + if (!(bmcr & BMCR_RESET)) + break; + } + + return bmcr & BMCR_RESET; +} + +/* + * smc_phy_powerdown - powerdown phy + * @dev: net device + * @phy: phy address + * + * Power down the specified PHY + */ +static void smc_phy_powerdown(struct net_device *dev, int phy) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned int bmcr; + + spin_lock_irq(&lp->lock); + bmcr = smc_phy_read(dev, phy, MII_BMCR); + smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); + spin_unlock_irq(&lp->lock); +} + +/* + * smc_phy_check_media - check the media status and adjust TCR + * @dev: net device + * @init: set true for initialisation + * + * Select duplex mode depending on negotiation state. This + * also updates our carrier state. + */ +static void smc_phy_check_media(struct net_device *dev, int init) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + + if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { + unsigned int old_bank; + + /* duplex state has changed */ + if (lp->mii.full_duplex) { + lp->tcr_cur_mode |= TCR_SWFDUP; + } else { + lp->tcr_cur_mode &= ~TCR_SWFDUP; + } + + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(0); + SMC_SET_TCR(lp->tcr_cur_mode); + SMC_SELECT_BANK(old_bank); + } +} + +/* + * Configures the specified PHY through the MII management interface + * using Autonegotiation. + * Calls smc_phy_fixed() if the user has requested a certain config. + * If RPC ANEG bit is set, the media selection is dependent purely on + * the selection by the MII (either in the MII BMCR reg or the result + * of autonegotiation.) If the RPC ANEG bit is cleared, the selection + * is controlled by the RPC SPEED and RPC DPLX bits. + */ +static void smc_phy_configure(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int my_phy_caps; /* My PHY capabilities */ + int my_ad_caps; /* My Advertised capabilities */ + int status; + + DBG(3, "%s:smc_program_phy()\n", dev->name); + + spin_lock_irq(&lp->lock); + + /* + * We should not be called if phy_type is zero. + */ + if (lp->phy_type == 0) + goto smc_phy_configure_exit; + + if (smc_phy_reset(dev, phyaddr)) { + printk("%s: PHY reset timed out\n", dev->name); + goto smc_phy_configure_exit; + } + + /* + * Enable PHY Interrupts (for register 18) + * Interrupts listed here are disabled + */ + smc_phy_write(dev, phyaddr, PHY_MASK_REG, + PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | + PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | + PHY_INT_SPDDET | PHY_INT_DPLXDET); + + /* Configure the Receive/Phy Control register */ + SMC_SELECT_BANK(0); + SMC_SET_RPC(lp->rpc_cur_mode); + + /* If the user requested no auto neg, then go set his request */ + if (lp->mii.force_media) { + smc_phy_fixed(dev); + goto smc_phy_configure_exit; + } + + /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ + my_phy_caps = smc_phy_read(dev, phyaddr, MII_BMSR); + + if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { + printk(KERN_INFO "Auto negotiation NOT supported\n"); + smc_phy_fixed(dev); + goto smc_phy_configure_exit; + } + + my_ad_caps = ADVERTISE_CSMA; /* I am CSMA capable */ + + if (my_phy_caps & BMSR_100BASE4) + my_ad_caps |= ADVERTISE_100BASE4; + if (my_phy_caps & BMSR_100FULL) + my_ad_caps |= ADVERTISE_100FULL; + if (my_phy_caps & BMSR_100HALF) + my_ad_caps |= ADVERTISE_100HALF; + if (my_phy_caps & BMSR_10FULL) + my_ad_caps |= ADVERTISE_10FULL; + if (my_phy_caps & BMSR_10HALF) + my_ad_caps |= ADVERTISE_10HALF; + + /* Disable capabilities not selected by our user */ + if (lp->ctl_rspeed != 100) + my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF); + + if (!lp->ctl_rfduplx) + my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); + + /* Update our Auto-Neg Advertisement Register */ + smc_phy_write(dev, phyaddr, MII_ADVERTISE, my_ad_caps); + lp->mii.advertising = my_ad_caps; + + /* + * Read the register back. Without this, it appears that when + * auto-negotiation is restarted, sometimes it isn't ready and + * the link does not come up. + */ + status = smc_phy_read(dev, phyaddr, MII_ADVERTISE); + + DBG(2, "%s: phy caps=%x\n", dev->name, my_phy_caps); + DBG(2, "%s: phy advertised caps=%x\n", dev->name, my_ad_caps); + + /* Restart auto-negotiation process in order to advertise my caps */ + smc_phy_write(dev, phyaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); + + smc_phy_check_media(dev, 1); + +smc_phy_configure_exit: + spin_unlock_irq(&lp->lock); +} + +/* + * smc_phy_interrupt + * + * Purpose: Handle interrupts relating to PHY register 18. This is + * called from the "hard" interrupt handler under our private spinlock. + */ +static void smc_phy_interrupt(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + int phyaddr = lp->mii.phy_id; + int phy18; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + if (lp->phy_type == 0) + return; + + for(;;) { + smc_phy_check_media(dev, 0); + + /* Read PHY Register 18, Status Output */ + phy18 = smc_phy_read(dev, phyaddr, PHY_INT_REG); + if ((phy18 & PHY_INT_INT) == 0) + break; + } +} + +/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/ + +static void smc_10bt_check_media(struct net_device *dev, int init) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int old_carrier, new_carrier, old_bank; + + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(0); + old_carrier = netif_carrier_ok(dev) ? 1 : 0; + new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0; + + if (init || (old_carrier != new_carrier)) { + if (!new_carrier) { + netif_carrier_off(dev); + } else { + netif_carrier_on(dev); + } + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: link %s\n", dev->name, + new_carrier ? "up" : "down"); + } + SMC_SELECT_BANK(old_bank); +} + +static void smc_eph_interrupt(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int old_bank, ctl; + + smc_10bt_check_media(dev, 0); + + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(1); + + ctl = SMC_GET_CTL(); + SMC_SET_CTL(ctl & ~CTL_LE_ENABLE); + SMC_SET_CTL(ctl); + + SMC_SELECT_BANK(old_bank); +} + +/* + * This is the main routine of the driver, to handle the device when + * it needs some attention. + */ +static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + int status, mask, timeout, card_stats; + int saved_bank, saved_pointer; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + saved_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(2); + saved_pointer = SMC_GET_PTR(); + mask = SMC_GET_INT_MASK(); + SMC_SET_INT_MASK(0); + + /* set a timeout value, so I don't stay here forever */ + timeout = 8; + + do { + status = SMC_GET_INT(); + + DBG(2, "%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", + dev->name, status, mask, + ({ int meminfo; SMC_SELECT_BANK(0); + meminfo = SMC_GET_MIR(); + SMC_SELECT_BANK(2); meminfo; }), + SMC_GET_FIFO()); + + status &= mask; + if (!status) + break; + + spin_lock(&lp->lock); + + if (status & IM_RCV_INT) { + DBG(3, "%s: RX irq\n", dev->name); + smc_rcv(dev); + } else if (status & IM_TX_INT) { + DBG(3, "%s: TX int\n", dev->name); + smc_tx(dev); + SMC_ACK_INT(IM_TX_INT); +#if THROTTLE_TX_PKTS + netif_wake_queue(dev); +#endif + } else if (status & IM_ALLOC_INT) { + DBG(3, "%s: Allocation irq\n", dev->name); + smc_hardware_send_packet(dev); + mask |= (IM_TX_INT | IM_TX_EMPTY_INT); + mask &= ~IM_ALLOC_INT; +#if ! THROTTLE_TX_PKTS + netif_wake_queue(dev); +#endif + } else if (status & IM_TX_EMPTY_INT) { + DBG(3, "%s: TX empty\n", dev->name); + mask &= ~IM_TX_EMPTY_INT; + + /* update stats */ + SMC_SELECT_BANK(0); + card_stats = SMC_GET_COUNTER(); + SMC_SELECT_BANK(2); + + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + } else if (status & IM_RX_OVRN_INT) { + DBG(1, "%s: RX overrun\n", dev->name); + SMC_ACK_INT(IM_RX_OVRN_INT); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } else if (status & IM_EPH_INT) { + smc_eph_interrupt(dev); + } else if (status & IM_MDINT) { + SMC_ACK_INT(IM_MDINT); + smc_phy_interrupt(dev); + } else if (status & IM_ERCV_INT) { + SMC_ACK_INT(IM_ERCV_INT); + PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name); + } + + spin_unlock(&lp->lock); + } while (--timeout); + + /* restore register states */ + SMC_SET_INT_MASK(mask); + SMC_SET_PTR(saved_pointer); + SMC_SELECT_BANK(saved_bank); + + DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); + + /* + * We return IRQ_HANDLED unconditionally here even if there was + * nothing to do. There is a possibility that a packet might + * get enqueued into the chip right after TX_EMPTY_INT is raised + * but just before the CPU acknowledges the IRQ. + * Better take an unneeded IRQ in some occasions than complexifying + * the code for all cases. + */ + return IRQ_HANDLED; +} + +/* Our watchdog timed out. Called by the networking layer */ +static void smc_timeout(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + smc_reset(dev); + smc_enable(dev); + +#if 0 + /* + * Reconfiguring the PHY doesn't seem like a bad idea here, but + * it introduced a problem. Now that this is a timeout routine, + * we are getting called from within an interrupt context. + * smc_phy_configure() calls msleep() which calls + * schedule_timeout() which calls schedule(). When schedule() + * is called from an interrupt context, it prints out + * "Scheduling in interrupt" and then calls BUG(). This is + * obviously not desirable. This was worked around by removing + * the call to smc_phy_configure() here because it didn't seem + * absolutely necessary. Ultimately, if msleep() is + * supposed to be usable from an interrupt context (which it + * looks like it thinks it should handle), it should be fixed. + */ + if (lp->phy_type != 0) + smc_phy_configure(dev); +#endif + + /* clear anything saved */ + if (lp->saved_skb != NULL) { + dev_kfree_skb (lp->saved_skb); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + +/* + * This sets the internal hardware table to filter out unwanted multicast + * packets before they take up memory. + * + * The SMC chip uses a hash table where the high 6 bits of the CRC of + * address are the offset into the table. If that bit is 1, then the + * multicast packet is accepted. Otherwise, it's dropped silently. + * + * To use the 6 bits as an offset into the table, the high 3 bits are the + * number of the 8 bit register, while the low 3 bits are the bit within + * that register. + * + * This routine is based very heavily on the one provided by Peter Cammaert. + */ +static void +smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs) +{ + int i; + unsigned char multicast_table[8]; + struct dev_mc_list *cur_addr; + + /* table for flipping the order of 3 bits */ + static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + /* start with a table of all zeros: reject all */ + memset(multicast_table, 0, sizeof(multicast_table)); + + cur_addr = addrs; + for (i = 0; i < count; i++, cur_addr = cur_addr->next) { + int position; + + /* do we have a pointer here? */ + if (!cur_addr) + break; + /* make sure this is a multicast address - shouldn't this + be a given if we have it here ? */ + if (!(*cur_addr->dmi_addr & 1)) + continue; + + /* only use the low order bits */ + position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert3[position&7]] |= + (1<>3)&7]); + + } + /* now, the table can be loaded into the chipset */ + SMC_SELECT_BANK(3); + SMC_SET_MCAST(multicast_table); +} + +/* + * This routine will, depending on the values passed to it, + * either make it accept multicast packets, go into + * promiscuous mode (for TCPDUMP and cousins) or accept + * a select set of multicast packets + */ +static void smc_set_multicast_list(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + SMC_SELECT_BANK(0); + if (dev->flags & IFF_PROMISC) { + DBG(2, "%s: RCR_PRMS\n", dev->name); + lp->rcr_cur_mode |= RCR_PRMS; + SMC_SET_RCR(lp->rcr_cur_mode); + } + +/* BUG? I never disable promiscuous mode if multicasting was turned on. + Now, I turn off promiscuous mode, but I don't do anything to multicasting + when promiscuous mode is turned on. +*/ + + /* + * Here, I am setting this to accept all multicast packets. + * I don't need to zero the multicast table, because the flag is + * checked before the table is + */ + else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + lp->rcr_cur_mode |= RCR_ALMUL; + SMC_SET_RCR(lp->rcr_cur_mode); + DBG(2, "%s: RCR_ALMUL\n", dev->name); + } + + /* + * We just get all multicast packets even if we only want them + * from one source. This will be changed at some future point. + */ + else if (dev->mc_count) { + /* support hardware multicasting */ + + /* be sure I get rid of flags I might have set */ + lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); + SMC_SET_RCR(lp->rcr_cur_mode); + /* + * NOTE: this has to set the bank, so make sure it is the + * last thing called. The bank is set to zero at the top + */ + smc_setmulticast(ioaddr, dev->mc_count, dev->mc_list); + } else { + DBG(2, "%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name); + lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); + SMC_SET_RCR(lp->rcr_cur_mode); + + /* + * since I'm disabling all multicast entirely, I need to + * clear the multicast list + */ + SMC_SELECT_BANK(3); + SMC_CLEAR_MCAST(); + } +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc.. + */ +static int +smc_open(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + /* + * Check that the address is valid. If its not, refuse + * to bring the device up. The user must specify an + * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n")); + return -EINVAL; + } + + /* clear out all the junk that was put here before... */ + lp->saved_skb = NULL; + + /* Setup the default Register Modes */ + lp->tcr_cur_mode = TCR_DEFAULT; + lp->rcr_cur_mode = RCR_DEFAULT; + lp->rpc_cur_mode = RPC_DEFAULT; + + /* + * If we are not using a MII interface, we need to + * monitor our own carrier signal to detect faults. + */ + if (lp->phy_type == 0) + lp->tcr_cur_mode |= TCR_MON_CSN; + + /* reset the hardware */ + smc_reset(dev); + smc_enable(dev); + + SMC_SELECT_BANK(1); + SMC_SET_MAC_ADDR(dev->dev_addr); + + /* Configure the PHY */ + if (lp->phy_type != 0) + smc_phy_configure(dev); + else { + spin_lock_irq(&lp->lock); + smc_10bt_check_media(dev, 1); + spin_unlock_irq(&lp->lock); + } + + /* + * make sure to initialize the link state with netif_carrier_off() + * somewhere, too --jgarzik + * + * smc_phy_configure() and smc_10bt_check_media() does that. --rmk + */ + netif_start_queue(dev); + return 0; +} + +/* + * smc_close + * + * this makes the board clean up everything that it can + * and not talk to the outside world. Caused by + * an 'ifconfig ethX down' + */ +static int smc_close(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + netif_stop_queue(dev); + netif_carrier_off(dev); + + /* clear everything */ + smc_shutdown(dev->base_addr); + + if (lp->phy_type != 0) + smc_phy_powerdown(dev, lp->mii.phy_id); + + return 0; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct net_device_stats *smc_query_statistics(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + return &lp->stats; +} + +/* + * Ethtool support + */ +static int +smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc_local *lp = netdev_priv(dev); + int ret; + + cmd->maxtxpkt = 1; + cmd->maxrxpkt = 1; + + if (lp->phy_type != 0) { + spin_lock_irq(&lp->lock); + ret = mii_ethtool_gset(&lp->mii, cmd); + spin_unlock_irq(&lp->lock); + } else { + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_TP | SUPPORTED_AUI; + + if (lp->ctl_rspeed == 10) + cmd->speed = SPEED_10; + else if (lp->ctl_rspeed == 100) + cmd->speed = SPEED_100; + + cmd->autoneg = AUTONEG_DISABLE; + cmd->transceiver = XCVR_INTERNAL; + cmd->port = 0; + cmd->duplex = lp->tcr_cur_mode & TCR_SWFDUP ? DUPLEX_FULL : DUPLEX_HALF; + + ret = 0; + } + + return ret; +} + +static int +smc_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc_local *lp = netdev_priv(dev); + int ret; + + if (lp->phy_type != 0) { + spin_lock_irq(&lp->lock); + ret = mii_ethtool_sset(&lp->mii, cmd); + spin_unlock_irq(&lp->lock); + } else { + if (cmd->autoneg != AUTONEG_DISABLE || + cmd->speed != SPEED_10 || + (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) || + (cmd->port != PORT_TP && cmd->port != PORT_AUI)) + return -EINVAL; + +// lp->port = cmd->port; + lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL; + +// if (netif_running(dev)) +// smc_set_port(dev); + + ret = 0; + } + + return ret; +} + +static void +smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strncpy(info->driver, CARDNAME, sizeof(info->driver)); + strncpy(info->version, version, sizeof(info->version)); + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); +} + +static int smc_ethtool_nwayreset(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + int ret = -EINVAL; + + if (lp->phy_type != 0) { + spin_lock_irq(&lp->lock); + ret = mii_nway_restart(&lp->mii); + spin_unlock_irq(&lp->lock); + } + + return ret; +} + +static u32 smc_ethtool_getmsglevel(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + return lp->msg_enable; +} + +static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level) +{ + struct smc_local *lp = netdev_priv(dev); + lp->msg_enable = level; +} + +static struct ethtool_ops smc_ethtool_ops = { + .get_settings = smc_ethtool_getsettings, + .set_settings = smc_ethtool_setsettings, + .get_drvinfo = smc_ethtool_getdrvinfo, + + .get_msglevel = smc_ethtool_getmsglevel, + .set_msglevel = smc_ethtool_setmsglevel, + .nway_reset = smc_ethtool_nwayreset, + .get_link = ethtool_op_get_link, +// .get_eeprom = smc_ethtool_geteeprom, +// .set_eeprom = smc_ethtool_seteeprom, +}; + +/* + * smc_findirq + * + * This routine has a simple purpose -- make the SMC chip generate an + * interrupt, so an auto-detect routine can detect it, and find the IRQ, + */ +/* + * does this still work? + * + * I just deleted auto_irq.c, since it was never built... + * --jgarzik + */ +static int __init smc_findirq(unsigned long ioaddr) +{ + int timeout = 20; + unsigned long cookie; + + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + + cookie = probe_irq_on(); + + /* + * What I try to do here is trigger an ALLOC_INT. This is done + * by allocating a small chunk of memory, which will give an interrupt + * when done. + */ + /* enable ALLOCation interrupts ONLY */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(IM_ALLOC_INT); + + /* + * Allocate 512 bytes of memory. Note that the chip was just + * reset so all the memory is available + */ + SMC_SET_MMU_CMD(MC_ALLOC | 1); + + /* + * Wait until positive that the interrupt has been generated + */ + do { + int int_status; + udelay(10); + int_status = SMC_GET_INT(); + if (int_status & IM_ALLOC_INT) + break; /* got the interrupt */ + } while (--timeout); + + /* + * there is really nothing that I can do here if timeout fails, + * as autoirq_report will return a 0 anyway, which is what I + * want in this case. Plus, the clean up is needed in both + * cases. + */ + + /* and disable all interrupts again */ + SMC_SET_INT_MASK(0); + + /* and return what I found */ + return probe_irq_off(cookie); +} + +/* + * Function: smc_probe(unsigned long ioaddr) + * + * Purpose: + * Tests to see if a given ioaddr points to an SMC91x chip. + * Returns a 0 on success + * + * Algorithm: + * (1) see if the high byte of BANK_SELECT is 0x33 + * (2) compare the ioaddr with the base register's address + * (3) see if I recognize the chip ID in the appropriate register + * + * Here I do typical initialization tasks. + * + * o Initialize the structure if needed + * o print out my vanity message if not done so already + * o print out what type of hardware is detected + * o print out the ethernet address + * o find the IRQ + * o set up my private data + * o configure the dev structure with my subroutines + * o actually GRAB the irq. + * o GRAB the region + */ +static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) +{ + struct smc_local *lp = netdev_priv(dev); + static int version_printed = 0; + int i, retval; + unsigned int val, revision_register; + const char *version_string; + + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + + /* First, see if the high byte is 0x33 */ + val = SMC_CURRENT_BANK(); + DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val); + if ((val & 0xFF00) != 0x3300) { + if ((val & 0xFF) == 0x33) { + printk(KERN_WARNING + "%s: Detected possible byte-swapped interface" + " at IOADDR 0x%lx\n", CARDNAME, ioaddr); + } + retval = -ENODEV; + goto err_out; + } + + /* + * The above MIGHT indicate a device, but I need to write to + * further test this. + */ + SMC_SELECT_BANK(0); + val = SMC_CURRENT_BANK(); + if ((val & 0xFF00) != 0x3300) { + retval = -ENODEV; + goto err_out; + } + + /* + * well, we've already written once, so hopefully another + * time won't hurt. This time, I need to switch the bank + * register to bank 1, so I can access the base address + * register + */ + SMC_SELECT_BANK(1); + val = SMC_GET_BASE(); + val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT; + if ((ioaddr & ((PAGE_SIZE-1)<> 4) & 0xF]; + if (!version_string || (revision_register & 0xff00) != 0x3300) { + /* I don't recognize this chip, so... */ + printk("%s: IO 0x%lx: Unrecognized revision register 0x%04x" + ", Contact author.\n", CARDNAME, + ioaddr, revision_register); + + retval = -ENODEV; + goto err_out; + } + + /* At this point I'll assume that the chip is an SMC91x. */ + if (version_printed++ == 0) + printk("%s", version); + + /* fill in some of the fields */ + dev->base_addr = ioaddr; + lp->version = revision_register & 0xff; + + /* Get the MAC address */ + SMC_SELECT_BANK(1); + SMC_GET_MAC_ADDR(dev->dev_addr); + + /* now, reset the chip, and put it into a known state */ + smc_reset(dev); + + /* + * If dev->irq is 0, then the device has to be banged on to see + * what the IRQ is. + * + * This banging doesn't always detect the IRQ, for unknown reasons. + * a workaround is to reset the chip and try again. + * + * Interestingly, the DOS packet driver *SETS* the IRQ on the card to + * be what is requested on the command line. I don't do that, mostly + * because the card that I have uses a non-standard method of accessing + * the IRQs, and because this _should_ work in most configurations. + * + * Specifying an IRQ is done with the assumption that the user knows + * what (s)he is doing. No checking is done!!!! + */ + if (dev->irq < 1) { + int trials; + + trials = 3; + while (trials--) { + dev->irq = smc_findirq(ioaddr); + if (dev->irq) + break; + /* kick the card and try again */ + smc_reset(dev); + } + } + if (dev->irq == 0) { + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n", + dev->name); + retval = -ENODEV; + goto err_out; + } + dev->irq = irq_canonicalize(dev->irq); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + dev->open = smc_open; + dev->stop = smc_close; + dev->hard_start_xmit = smc_hard_start_xmit; + dev->tx_timeout = smc_timeout; + dev->watchdog_timeo = msecs_to_jiffies(watchdog); + dev->get_stats = smc_query_statistics; + dev->set_multicast_list = smc_set_multicast_list; + dev->ethtool_ops = &smc_ethtool_ops; + + spin_lock_init(&lp->lock); + lp->mii.phy_id_mask = 0x1f; + lp->mii.reg_num_mask = 0x1f; + lp->mii.force_media = 0; + lp->mii.full_duplex = 0; + lp->mii.dev = dev; + lp->mii.mdio_read = smc_phy_read; + lp->mii.mdio_write = smc_phy_write; + + /* + * Locate the phy, if any. + */ + if (lp->version >= (CHIP_91100 << 4)) + smc_detect_phy(dev); + + /* Set default parameters */ + lp->msg_enable = NETIF_MSG_LINK; + lp->ctl_rfduplx = 0; + lp->ctl_rspeed = 10; + + if (lp->version >= (CHIP_91100 << 4)) { + lp->ctl_rfduplx = 1; + lp->ctl_rspeed = 100; + } + + /* Grab the IRQ */ + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + if (retval) + goto err_out; + + set_irq_type(dev->irq, IRQT_RISING); +#ifdef SMC_USE_PXA_DMA + { + int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, + smc_pxa_dma_irq, NULL); + if (dma >= 0) + dev->dma = dma; + } +#endif + + retval = register_netdev(dev); + if (retval == 0) { + /* now, print out the card info, in a short format.. */ + printk("%s: %s (rev %d) at %#lx IRQ %d", + dev->name, version_string, revision_register & 0x0f, + dev->base_addr, dev->irq); + + if (dev->dma != (unsigned char)-1) + printk(" DMA %d", dev->dma); + + printk("%s%s\n", nowait ? " [nowait]" : "", + THROTTLE_TX_PKTS ? " [throttle_tx]" : ""); + + if (!is_valid_ether_addr(dev->dev_addr)) { + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", dev->name); + } else { + /* Print the Ethernet address */ + printk("%s: Ethernet addr: ", dev->name); + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x\n", dev->dev_addr[5]); + } + + if (lp->phy_type == 0) { + PRINTK("%s: No PHY found\n", dev->name); + } else if ((lp->phy_type & 0xfffffff0) == 0x0016f840) { + PRINTK("%s: PHY LAN83C183 (LAN91C111 Internal)\n", dev->name); + } else if ((lp->phy_type & 0xfffffff0) == 0x02821c50) { + PRINTK("%s: PHY LAN83C180\n", dev->name); + } + } + +err_out: +#ifdef SMC_USE_PXA_DMA + if (retval && dev->dma != (unsigned char)-1) + pxa_free_dma(dev->dma); +#endif + return retval; +} + +static int smc_enable_device(unsigned long attrib_phys) +{ + unsigned long flags; + unsigned char ecor, ecsr; + void *addr; + + /* + * Map the attribute space. This is overkill, but clean. + */ + addr = ioremap(attrib_phys, ATTRIB_SIZE); + if (!addr) + return -ENOMEM; + + /* + * Reset the device. We must disable IRQs around this + * since a reset causes the IRQ line become active. + */ + local_irq_save(flags); + ecor = readb(addr + (ECOR << SMC_IO_SHIFT)) & ~ECOR_RESET; + writeb(ecor | ECOR_RESET, addr + (ECOR << SMC_IO_SHIFT)); + readb(addr + (ECOR << SMC_IO_SHIFT)); + + /* + * Wait 100us for the chip to reset. + */ + udelay(100); + + /* + * The device will ignore all writes to the enable bit while + * reset is asserted, even if the reset bit is cleared in the + * same write. Must clear reset first, then enable the device. + */ + writeb(ecor, addr + (ECOR << SMC_IO_SHIFT)); + writeb(ecor | ECOR_ENABLE, addr + (ECOR << SMC_IO_SHIFT)); + + /* + * Set the appropriate byte/word mode. + */ + ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8; +#ifndef SMC_CAN_USE_16BIT + ecsr |= ECSR_IOIS8; +#endif + writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT)); + local_irq_restore(flags); + + iounmap(addr); + + /* + * Wait for the chip to wake up. We could poll the control + * register in the main register space, but that isn't mapped + * yet. We know this is going to take 750us. + */ + msleep(1); + + return 0; +} + +/* + * smc_init(void) + * Input parameters: + * dev->base_addr == 0, try to find all possible locations + * dev->base_addr > 0x1ff, this is the address to check + * dev->base_addr == , return failure code + * + * Output: + * 0 --> there is a device + * anything else, error + */ +static int smc_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev; + struct resource *res, *ext = NULL; + unsigned int *addr; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto out; + } + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) { + ret = -EBUSY; + goto out; + } + + ndev = alloc_etherdev(sizeof(struct smc_local)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto release_1; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, dev); + + ndev->dma = (unsigned char)-1; + ndev->irq = platform_get_irq(pdev, 0); + + ext = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (ext) { + if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) { + ret = -EBUSY; + goto release_1; + } + +#if defined(CONFIG_SA1100_ASSABET) + NCR_0 |= NCR_ENET_OSC_EN; +#endif + + ret = smc_enable_device(ext->start); + if (ret) + goto release_both; + } + + addr = ioremap(res->start, SMC_IO_EXTENT); + if (!addr) { + ret = -ENOMEM; + goto release_both; + } + + dev_set_drvdata(dev, ndev); + ret = smc_probe(ndev, (unsigned long)addr); + if (ret != 0) { + dev_set_drvdata(dev, NULL); + iounmap(addr); + release_both: + if (ext) + release_mem_region(ext->start, ATTRIB_SIZE); + free_netdev(ndev); + release_1: + release_mem_region(res->start, SMC_IO_EXTENT); + out: + printk("%s: not found (%d).\n", CARDNAME, ret); + } +#ifdef SMC_USE_PXA_DMA + else { + struct smc_local *lp = netdev_priv(ndev); + lp->physaddr = res->start; + } +#endif + + return ret; +} + +static int smc_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev = dev_get_drvdata(dev); + struct resource *res; + + dev_set_drvdata(dev, NULL); + + unregister_netdev(ndev); + + free_irq(ndev->irq, ndev); + +#ifdef SMC_USE_PXA_DMA + if (ndev->dma != (unsigned char)-1) + pxa_free_dma(ndev->dma); +#endif + iounmap((void *)ndev->base_addr); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) + release_mem_region(res->start, ATTRIB_SIZE); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, SMC_IO_EXTENT); + + free_netdev(ndev); + + return 0; +} + +static int smc_drv_suspend(struct device *dev, u32 state, u32 level) +{ + struct net_device *ndev = dev_get_drvdata(dev); + + if (ndev && level == SUSPEND_DISABLE) { + if (netif_running(ndev)) { + netif_device_detach(ndev); + smc_shutdown(ndev->base_addr); + } + } + return 0; +} + +static int smc_drv_resume(struct device *dev, u32 level) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev = dev_get_drvdata(dev); + + if (ndev && level == RESUME_ENABLE) { + struct smc_local *lp = netdev_priv(ndev); + unsigned long ioaddr = ndev->base_addr; + + if (pdev->num_resources == 3) + smc_enable_device(pdev->resource[2].start); + if (netif_running(ndev)) { + smc_reset(ndev); + smc_enable(ndev); + SMC_SELECT_BANK(1); + SMC_SET_MAC_ADDR(ndev->dev_addr); + if (lp->phy_type != 0) + smc_phy_configure(ndev); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct device_driver smc_driver = { + .name = CARDNAME, + .bus = &platform_bus_type, + .probe = smc_drv_probe, + .remove = smc_drv_remove, + .suspend = smc_drv_suspend, + .resume = smc_drv_resume, +}; + +static int __init smc_init(void) +{ +#ifdef MODULE + if (io == -1) + printk(KERN_WARNING + "%s: You shouldn't use auto-probing with insmod!\n", + CARDNAME); +#endif + + return driver_register(&smc_driver); +} + +static void __exit smc_cleanup(void) +{ + driver_unregister(&smc_driver); +} + +module_init(smc_init); +module_exit(smc_cleanup); diff -Nru a/drivers/net/arm/smc91x.h b/drivers/net/arm/smc91x.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/arm/smc91x.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,829 @@ +/*------------------------------------------------------------------------ + . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device. + . + . Copyright (C) 1996 by Erik Stahlman + . Copyright (C) 2001 Standard Microsystems Corporation + . Developed by Simple Network Magic Corporation + . Copyright (C) 2003 Monta Vista Software, Inc. + . Unified SMC91x driver by Nicolas Pitre + . + . 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 + . + . Information contained in this file was obtained from the LAN91C111 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . Authors + . Erik Stahlman + . Daris A Nevil + . Nicolas Pitre + . + ---------------------------------------------------------------------------*/ +#ifndef _SMC91X_H_ +#define _SMC91X_H_ + + +/* + * Define your architecture specific bus configuration parameters here. + */ + +#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \ + defined(CONFIG_SA1100_PFS168) || \ + defined(CONFIG_SA1100_FLEXANET) || \ + defined(CONFIG_SA1100_GRAPHICSMASTER) || \ + defined(CONFIG_ARCH_LUBBOCK) + +/* We can only do 16-bit reads and writes in the static memory space. */ +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +/* The first two address lines aren't connected... */ +#define SMC_IO_SHIFT 2 + +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) + +#elif defined(CONFIG_SA1100_ASSABET) + +#include + +/* We can only do 8-bit reads and writes in the static memory space. */ +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 0 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +/* The first two address lines aren't connected... */ +#define SMC_IO_SHIFT 2 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l)) +#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) + +#elif defined(CONFIG_ARCH_INNOKOM) || \ + defined(CONFIG_MACH_MAINSTONE) || \ + defined(CONFIG_ARCH_PXA_IDP) || \ + defined(CONFIG_ARCH_RAMSES) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +/* We actually can't write halfwords properly if not word aligned */ +static inline void +SMC_outw(u16 val, unsigned long ioaddr, int reg) +{ + if (reg & 2) { + unsigned int v = val << 16; + v |= readl(ioaddr + (reg & ~2)) & 0xffff; + writel(v, ioaddr + (reg & ~2)); + } else { + writew(val, ioaddr + reg); + } +} + +#elif defined(CONFIG_ISA) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 + +#define SMC_inb(a, r) inb((a) + (r)) +#define SMC_inw(a, r) inw((a) + (r)) +#define SMC_outb(v, a, r) outb(v, (a) + (r)) +#define SMC_outw(v, a, r) outw(v, (a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) + +#else + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define RPC_LSA_DEFAULT RPC_LED_100_10 +#define RPC_LSB_DEFAULT RPC_LED_TX_RX + +#endif + + +#ifdef SMC_USE_PXA_DMA +/* + * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is + * always happening in irq context so no need to worry about races. TX is + * different and probably not worth it for that reason, and not as critical + * as RX which can overrun memory and lose packets. + */ +#include +#include + +#ifdef SMC_insl +#undef SMC_insl +#define SMC_insl(a, r, p, l) \ + smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l) +static inline void +smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma, + u_char *buf, int len) +{ + dma_addr_t dmabuf; + + /* fallback if no DMA available */ + if (dma == (unsigned char)-1) { + readsl(ioaddr + reg, buf, len); + return; + } + + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + *((u32 *)buf)++ = SMC_inl(ioaddr, reg); + len--; + } + + len *= 4; + dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH4 | (DCMD_LENGTH & len)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; + while (!(DCSR(dma) & DCSR_STOPSTATE)); + DCSR(dma) = 0; + dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE); +} +#endif + +#ifdef SMC_insw +#undef SMC_insw +#define SMC_insw(a, r, p, l) \ + smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l) +static inline void +smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma, + u_char *buf, int len) +{ + dma_addr_t dmabuf; + + /* fallback if no DMA available */ + if (dma == (unsigned char)-1) { + readsw(ioaddr + reg, buf, len); + return; + } + + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + *((u16 *)buf)++ = SMC_inw(ioaddr, reg); + len--; + } + + len *= 2; + dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH2 | (DCMD_LENGTH & len)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; + while (!(DCSR(dma) & DCSR_STOPSTATE)); + DCSR(dma) = 0; + dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE); +} +#endif + +static void +smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs) +{ + DCSR(dma) = 0; +} +#endif /* SMC_USE_PXA_DMA */ + + +/* Because of bank switching, the LAN91x uses only 16 I/O ports */ +#ifndef SMC_IO_SHIFT +#define SMC_IO_SHIFT 0 +#endif +#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT) + + +/* + . Bank Select Register: + . + . yyyy yyyy 0000 00xx + . xx = bank number + . yyyy yyyy = 0x33, for identification purposes. +*/ +#define BANK_SELECT (14 << SMC_IO_SHIFT) + + +// Transmit Control Register +/* BANK 0 */ +#define TCR_REG SMC_REG(0x0000, 0) +#define TCR_ENABLE 0x0001 // When 1 we can transmit +#define TCR_LOOP 0x0002 // Controls output pin LBK +#define TCR_FORCOL 0x0004 // When 1 will force a collision +#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0 +#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames +#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier +#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation +#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error +#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback +#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode + +#define TCR_CLEAR 0 /* do NOTHING */ +/* the default settings for the TCR register : */ +#define TCR_DEFAULT (TCR_ENABLE | TCR_PAD_EN) + + +// EPH Status Register +/* BANK 0 */ +#define EPH_STATUS_REG SMC_REG(0x0002, 0) +#define ES_TX_SUC 0x0001 // Last TX was successful +#define ES_SNGL_COL 0x0002 // Single collision detected for last tx +#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx +#define ES_LTX_MULT 0x0008 // Last tx was a multicast +#define ES_16COL 0x0010 // 16 Collisions Reached +#define ES_SQET 0x0020 // Signal Quality Error Test +#define ES_LTXBRD 0x0040 // Last tx was a broadcast +#define ES_TXDEFR 0x0080 // Transmit Deferred +#define ES_LATCOL 0x0200 // Late collision detected on last tx +#define ES_LOSTCARR 0x0400 // Lost Carrier Sense +#define ES_EXC_DEF 0x0800 // Excessive Deferral +#define ES_CTR_ROL 0x1000 // Counter Roll Over indication +#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin +#define ES_TXUNRN 0x8000 // Tx Underrun + + +// Receive Control Register +/* BANK 0 */ +#define RCR_REG SMC_REG(0x0004, 0) +#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted +#define RCR_PRMS 0x0002 // Enable promiscuous mode +#define RCR_ALMUL 0x0004 // When set accepts all multicast frames +#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets +#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets +#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision +#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier +#define RCR_SOFTRST 0x8000 // resets the chip + +/* the normal settings for the RCR register : */ +#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) +#define RCR_CLEAR 0x0 // set it to a base state + + +// Counter Register +/* BANK 0 */ +#define COUNTER_REG SMC_REG(0x0006, 0) + + +// Memory Information Register +/* BANK 0 */ +#define MIR_REG SMC_REG(0x0008, 0) + + +// Receive/Phy Control Register +/* BANK 0 */ +#define RPC_REG SMC_REG(0x000A, 0) +#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode. +#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode +#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode +#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb +#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb +#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect +#define RPC_LED_RES (0x01) // LED = Reserved +#define RPC_LED_10 (0x02) // LED = 10Mbps link detect +#define RPC_LED_FD (0x03) // LED = Full Duplex Mode +#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred +#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect +#define RPC_LED_TX (0x06) // LED = TX packet occurred +#define RPC_LED_RX (0x07) // LED = RX packet occurred + +#ifndef RPC_LSA_DEFAULT +#define RPC_LSA_DEFAULT RPC_LED_100 +#endif +#ifndef RPC_LSB_DEFAULT +#define RPC_LSB_DEFAULT RPC_LED_FD +#endif + +#define RPC_DEFAULT (RPC_ANEG | (RPC_LSA_DEFAULT << RPC_LSXA_SHFT) | (RPC_LSB_DEFAULT << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) + + +/* Bank 0 0x0C is reserved */ + +// Bank Select Register +/* All Banks */ +#define BSR_REG 0x000E + + +// Configuration Reg +/* BANK 1 */ +#define CONFIG_REG SMC_REG(0x0000, 1) +#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy +#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL +#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus +#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode. + +// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low +#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) + + +// Base Address Register +/* BANK 1 */ +#define BASE_REG SMC_REG(0x0002, 1) + + +// Individual Address Registers +/* BANK 1 */ +#define ADDR0_REG SMC_REG(0x0004, 1) +#define ADDR1_REG SMC_REG(0x0006, 1) +#define ADDR2_REG SMC_REG(0x0008, 1) + + +// General Purpose Register +/* BANK 1 */ +#define GP_REG SMC_REG(0x000A, 1) + + +// Control Register +/* BANK 1 */ +#define CTL_REG SMC_REG(0x000C, 1) +#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received +#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically +#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt +#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt +#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt +#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store +#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers +#define CTL_STORE 0x0001 // When set stores registers into EEPROM + + +// MMU Command Register +/* BANK 2 */ +#define MMU_CMD_REG SMC_REG(0x0000, 2) +#define MC_BUSY 1 // When 1 the last release has not completed +#define MC_NOP (0<<5) // No Op +#define MC_ALLOC (1<<5) // OR with number of 256 byte packets +#define MC_RESET (2<<5) // Reset MMU to initial state +#define MC_REMOVE (3<<5) // Remove the current rx packet +#define MC_RELEASE (4<<5) // Remove and release the current rx packet +#define MC_FREEPKT (5<<5) // Release packet in PNR register +#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit +#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs + + +// Packet Number Register +/* BANK 2 */ +#define PN_REG SMC_REG(0x0002, 2) + + +// Allocation Result Register +/* BANK 2 */ +#define AR_REG SMC_REG(0x0003, 2) +#define AR_FAILED 0x80 // Alocation Failed + + +// TX FIFO Ports Register +/* BANK 2 */ +#define TXFIFO_REG SMC_REG(0x0004, 2) +#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty + +// RX FIFO Ports Register +/* BANK 2 */ +#define RXFIFO_REG SMC_REG(0x0005, 2) +#define RXFIFO_REMPTY 0x80 // RX FIFO Empty + +#define FIFO_REG SMC_REG(0x0004, 2) + +// Pointer Register +/* BANK 2 */ +#define PTR_REG SMC_REG(0x0006, 2) +#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area +#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access +#define PTR_READ 0x2000 // When 1 the operation is a read + + +// Data Register +/* BANK 2 */ +#define DATA_REG SMC_REG(0x0008, 2) + + +// Interrupt Status/Acknowledge Register +/* BANK 2 */ +#define INT_REG SMC_REG(0x000C, 2) + + +// Interrupt Mask Register +/* BANK 2 */ +#define IM_REG SMC_REG(0x000D, 2) +#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt +#define IM_ERCV_INT 0x40 // Early Receive Interrupt +#define IM_EPH_INT 0x20 // Set by Ethernet Protocol Handler section +#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns +#define IM_ALLOC_INT 0x08 // Set when allocation request is completed +#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty +#define IM_TX_INT 0x02 // Transmit Interrupt +#define IM_RCV_INT 0x01 // Receive Interrupt + + +// Multicast Table Registers +/* BANK 3 */ +#define MCAST_REG1 SMC_REG(0x0000, 3) +#define MCAST_REG2 SMC_REG(0x0002, 3) +#define MCAST_REG3 SMC_REG(0x0004, 3) +#define MCAST_REG4 SMC_REG(0x0006, 3) + + +// Management Interface Register (MII) +/* BANK 3 */ +#define MII_REG SMC_REG(0x0008, 3) +#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup +#define MII_MDOE 0x0008 // MII Output Enable +#define MII_MCLK 0x0004 // MII Clock, pin MDCLK +#define MII_MDI 0x0002 // MII Input, pin MDI +#define MII_MDO 0x0001 // MII Output, pin MDO + + +// Revision Register +/* BANK 3 */ +/* ( hi: chip id low: rev # ) */ +#define REV_REG SMC_REG(0x000A, 3) + + +// Early RCV Register +/* BANK 3 */ +/* this is NOT on SMC9192 */ +#define ERCV_REG SMC_REG(0x000C, 3) +#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received +#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask + + +// External Register +/* BANK 7 */ +#define EXT_REG SMC_REG(0x0000, 7) + + +#define CHIP_9192 3 +#define CHIP_9194 4 +#define CHIP_9195 5 +#define CHIP_9196 6 +#define CHIP_91100 7 +#define CHIP_91100FD 8 +#define CHIP_91111FD 9 + +static const char * chip_ids[ 16 ] = { + NULL, NULL, NULL, + /* 3 */ "SMC91C90/91C92", + /* 4 */ "SMC91C94", + /* 5 */ "SMC91C95", + /* 6 */ "SMC91C96", + /* 7 */ "SMC91C100", + /* 8 */ "SMC91C100FD", + /* 9 */ "SMC91C11xFD", + NULL, NULL, NULL, + NULL, NULL, NULL}; + + +/* + . Transmit status bits +*/ +#define TS_SUCCESS 0x0001 +#define TS_LOSTCAR 0x0400 +#define TS_LATCOL 0x0200 +#define TS_16COL 0x0010 + +/* + . Receive status bits +*/ +#define RS_ALGNERR 0x8000 +#define RS_BRODCAST 0x4000 +#define RS_BADCRC 0x2000 +#define RS_ODDFRAME 0x1000 +#define RS_TOOLONG 0x0800 +#define RS_TOOSHORT 0x0400 +#define RS_MULTICAST 0x0001 +#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) + + +/* + * PHY IDs + * LAN83C183 == LAN91C111 Internal PHY + */ +#define PHY_LAN83C183 0x0016f840 +#define PHY_LAN83C180 0x02821c50 + +/* + * PHY Register Addresses (LAN91C111 Internal PHY) + * + * Generic PHY registers can be found in + * + * These phy registers are specific to our on-board phy. + */ + +// PHY Configuration Register 1 +#define PHY_CFG1_REG 0x10 +#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled +#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled +#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down +#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler +#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable +#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled +#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm) +#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db +#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust +#define PHY_CFG1_TLVL_MASK 0x003C +#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time + + +// PHY Configuration Register 2 +#define PHY_CFG2_REG 0x11 +#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled +#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled +#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt) +#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo + +// PHY Status Output (and Interrupt status) Register +#define PHY_INT_REG 0x12 // Status Output (Interrupt Status) +#define PHY_INT_INT 0x8000 // 1=bits have changed since last read +#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected +#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync +#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx +#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx +#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx +#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected +#define PHY_INT_JAB 0x0100 // 1=Jabber detected +#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode +#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex + +// PHY Interrupt/Status Mask Register +#define PHY_MASK_REG 0x13 // Interrupt Mask +// Uses the same bit definitions as PHY_INT_REG + + +/* + * SMC91C96 ethernet config and status registers. + * These are in the "attribute" space. + */ +#define ECOR 0x8000 +#define ECOR_RESET 0x80 +#define ECOR_LEVEL_IRQ 0x40 +#define ECOR_WR_ATTRIB 0x04 +#define ECOR_ENABLE 0x01 + +#define ECSR 0x8002 +#define ECSR_IOIS8 0x20 +#define ECSR_PWRDWN 0x04 +#define ECSR_INT 0x02 + +#define ATTRIB_SIZE ((64*1024) << SMC_IO_SHIFT) + + +/* + * Macros to abstract register access according to the data bus + * capabilities. Please use those and not the in/out primitives. + * Note: the following macros do *not* select the bank -- this must + * be done separately as needed in the main code. The SMC_REG() macro + * only uses the bank argument for debugging purposes (when enabled). + */ + +#if SMC_DEBUG > 0 +#define SMC_REG(reg, bank) \ + ({ \ + int __b = SMC_CURRENT_BANK(); \ + if (unlikely((__b & ~0xf0) != (0x3300 | bank))) { \ + printk( "%s: bank reg screwed (0x%04x)\n", \ + CARDNAME, __b ); \ + BUG(); \ + } \ + reg<> 8) +#define SMC_GET_TXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF) +#define SMC_GET_RXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) >> 8) +#define SMC_GET_INT() (SMC_inw( ioaddr, INT_REG ) & 0xFF) +#define SMC_ACK_INT(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \ + SMC_outw( __mask | (x), ioaddr, INT_REG ); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_GET_INT_MASK() (SMC_inw( ioaddr, INT_REG ) >> 8) +#define SMC_SET_INT_MASK(x) SMC_outw( (x) << 8, ioaddr, INT_REG ) +#endif + +#define SMC_CURRENT_BANK() SMC_inw( ioaddr, BANK_SELECT ) +#define SMC_SELECT_BANK(x) SMC_outw( x, ioaddr, BANK_SELECT ) +#define SMC_GET_BASE() SMC_inw( ioaddr, BASE_REG ) +#define SMC_SET_BASE(x) SMC_outw( x, ioaddr, BASE_REG ) +#define SMC_GET_CONFIG() SMC_inw( ioaddr, CONFIG_REG ) +#define SMC_SET_CONFIG(x) SMC_outw( x, ioaddr, CONFIG_REG ) +#define SMC_GET_COUNTER() SMC_inw( ioaddr, COUNTER_REG ) +#define SMC_GET_CTL() SMC_inw( ioaddr, CTL_REG ) +#define SMC_SET_CTL(x) SMC_outw( x, ioaddr, CTL_REG ) +#define SMC_GET_MII() SMC_inw( ioaddr, MII_REG ) +#define SMC_SET_MII(x) SMC_outw( x, ioaddr, MII_REG ) +#define SMC_GET_MIR() SMC_inw( ioaddr, MIR_REG ) +#define SMC_SET_MIR(x) SMC_outw( x, ioaddr, MIR_REG ) +#define SMC_GET_MMU_CMD() SMC_inw( ioaddr, MMU_CMD_REG ) +#define SMC_SET_MMU_CMD(x) SMC_outw( x, ioaddr, MMU_CMD_REG ) +#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG ) +#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG ) +#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG ) +#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG ) +#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG ) +#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG ) +#define SMC_GET_RPC() SMC_inw( ioaddr, RPC_REG ) +#define SMC_SET_RPC(x) SMC_outw( x, ioaddr, RPC_REG ) +#define SMC_GET_TCR() SMC_inw( ioaddr, TCR_REG ) +#define SMC_SET_TCR(x) SMC_outw( x, ioaddr, TCR_REG ) + +#ifndef SMC_GET_MAC_ADDR +#define SMC_GET_MAC_ADDR(addr) \ + do { \ + unsigned int __v; \ + __v = SMC_inw( ioaddr, ADDR0_REG ); \ + addr[0] = __v; addr[1] = __v >> 8; \ + __v = SMC_inw( ioaddr, ADDR1_REG ); \ + addr[2] = __v; addr[3] = __v >> 8; \ + __v = SMC_inw( ioaddr, ADDR2_REG ); \ + addr[4] = __v; addr[5] = __v >> 8; \ + } while (0) +#endif + +#define SMC_SET_MAC_ADDR(addr) \ + do { \ + SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG ); \ + SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG ); \ + SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \ + } while (0) + +#define SMC_CLEAR_MCAST() \ + do { \ + SMC_outw( 0, ioaddr, MCAST_REG1 ); \ + SMC_outw( 0, ioaddr, MCAST_REG2 ); \ + SMC_outw( 0, ioaddr, MCAST_REG3 ); \ + SMC_outw( 0, ioaddr, MCAST_REG4 ); \ + } while (0) +#define SMC_SET_MCAST(x) \ + do { \ + unsigned char *mt = (x); \ + SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \ + SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \ + SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \ + SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \ + } while (0) + +#if SMC_CAN_USE_32BIT +/* + * Some setups just can't write 8 or 16 bits reliably when not aligned + * to a 32 bit boundary. I tell you that exists! + * We re-do the ones here that can be easily worked around if they can have + * their low parts written to 0 without adverse effects. + */ +#undef SMC_SELECT_BANK +#define SMC_SELECT_BANK(x) SMC_outl( (x)<<16, ioaddr, 12<> 16; \ + } while (0) +#else +#define SMC_PUT_PKT_HDR(status, length) \ + do { \ + SMC_outw( status, ioaddr, DATA_REG ); \ + SMC_outw( length, ioaddr, DATA_REG ); \ + } while (0) +#define SMC_GET_PKT_HDR(status, length) \ + do { \ + (status) = SMC_inw( ioaddr, DATA_REG ); \ + (length) = SMC_inw( ioaddr, DATA_REG ); \ + } while (0) +#endif + +#if SMC_CAN_USE_32BIT +#define SMC_PUSH_DATA(p, l) \ + do { \ + char *__ptr = (p); \ + int __len = (l); \ + if (__len >= 2 && (long)__ptr & 2) { \ + __len -= 2; \ + SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\ + } \ + SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \ + if (__len & 2) { \ + __ptr += (__len & ~3); \ + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ + } \ + } while (0) +#define SMC_PULL_DATA(p, l) \ + do { \ + char *__ptr = (p); \ + int __len = (l); \ + if ((long)__ptr & 2) { \ + /* \ + * We want 32bit alignment here. \ + * Since some buses perform a full 32bit \ + * fetch even for 16bit data we can't use \ + * SMC_inw() here. Back both source (on chip \ + * and destination) pointers of 2 bytes. \ + */ \ + (long)__ptr &= ~2; \ + __len += 2; \ + SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \ + } \ + __len += 2; \ + SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \ + } while (0) +#elif SMC_CAN_USE_16BIT +#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 ) +#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 ) +#elif SMC_CAN_USE_8BIT +#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l ) +#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l ) +#endif + +#if ! SMC_CAN_USE_16BIT +#define SMC_outw(x, ioaddr, reg) \ + do { \ + unsigned int __val16 = (x); \ + SMC_outb( __val16, ioaddr, reg ); \ + SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\ + } while (0) +#define SMC_inw(ioaddr, reg) \ + ({ \ + unsigned int __val16; \ + __val16 = SMC_inb( ioaddr, reg ); \ + __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \ + __val16; \ + }) +#endif + + +#endif /* _SMC91X_H_ */ diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c --- a/drivers/net/at1700.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/at1700.c 2004-06-20 13:00:24 -07:00 @@ -65,6 +65,8 @@ static char version[] __initdata = "at1700.c:v1.15 4/7/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +#define DRV_NAME "at1700" + /* Tunable parameters. */ /* When to switch from the 64-entry multicast filter to Rx-all-multicast. */ @@ -80,17 +82,10 @@ * ISA */ -#ifndef CONFIG_X86_PC9800 static unsigned at1700_probe_list[] __initdata = { 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 }; -#else /* CONFIG_X86_PC9800 */ -static unsigned at1700_probe_list[] __initdata = { - 0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0 -}; - -#endif /* CONFIG_X86_PC9800 */ /* * MCA */ @@ -133,7 +128,6 @@ /* Offsets from the base address. */ -#ifndef CONFIG_X86_PC9800 #define STATUS 0 #define TX_STATUS 0 #define RX_STATUS 1 @@ -161,34 +155,6 @@ #define RESET 31 /* Write to reset some parts of the chip. */ #define AT1700_IO_EXTENT 32 #define PORT_OFFSET(o) (o) -#else /* CONFIG_X86_PC9800 */ -#define STATUS (0x0000) -#define TX_STATUS (0x0000) -#define RX_STATUS (0x0001) -#define TX_INTR (0x0200)/* Bit-mapped interrupt enable registers. */ -#define RX_INTR (0x0201) -#define TX_MODE (0x0400) -#define RX_MODE (0x0401) -#define CONFIG_0 (0x0600)/* Misc. configuration settings. */ -#define CONFIG_1 (0x0601) -/* Run-time register bank 2 definitions. */ -#define DATAPORT (0x0800)/* Word-wide DMA or programmed-I/O dataport. */ -#define TX_START (0x0a00) -#define COL16CNTL (0x0a01)/* Controll Reg for 16 collisions */ -#define MODE13 (0x0c01) -#define RX_CTRL (0x0e00) -/* Configuration registers only on the '865A/B chips. */ -#define EEPROM_Ctrl (0x1000) -#define EEPROM_Data (0x1200) -#define CARDSTATUS 16 /* FMV-18x Card Status */ -#define CARDSTATUS1 17 /* FMV-18x Card Status */ -#define IOCONFIG (0x1400)/* Either read the jumper, or move the I/O. */ -#define IOCONFIG1 (0x1600) -#define SAPROM 20 /* The station address PROM, if no EEPROM. */ -#define MODE24 (0x1800)/* The station address PROM, if no EEPROM. */ -#define RESET (0x1e01)/* Write to reset some parts of the chip. */ -#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); }) -#endif /* CONFIG_X86_PC9800 */ #define TX_TIMEOUT 10 @@ -230,11 +196,7 @@ (detachable devices only). */ -#ifndef CONFIG_X86_PC9800 static int io = 0x260; -#else -static int io = 0xd0; -#endif static int irq; @@ -246,15 +208,7 @@ mca_mark_as_unused(lp->mca_slot); #endif free_irq(dev->irq, NULL); -#ifndef CONFIG_X86_PC9800 release_region(dev->base_addr, AT1700_IO_EXTENT); -#else - { - int i; - for (i = 0; i < 0x2000; i += 0x200) - release_region(dev->base_addr + i, 2); - } -#endif } struct net_device * __init at1700_probe(int unit) @@ -321,20 +275,8 @@ int slot, ret = -ENODEV; struct net_local *lp = netdev_priv(dev); -#ifndef CONFIG_X86_PC9800 - if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME)) return -EBUSY; -#else - for (i = 0; i < 0x2000; i += 0x0200) { - if (!request_region(ioaddr + i, 2, dev->name)) { - while (i > 0) { - i -= 0x0200; - release_region(ioaddr + i, 2); - } - return -EBUSY; - } - } -#endif /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe @@ -425,15 +367,8 @@ outb(0, ioaddr + RESET); if (is_at1700) { -#ifndef CONFIG_X86_PC9800 irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04) | (read_eeprom(ioaddr, 0)>>14)]; -#else - { - char re1000plus_irqmap[4] = {3, 5, 6, 12}; - irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6]; - } -#endif } else { /* Check PnP mode for FMV-183/184/183A/184A. */ /* This PnP routine is very poor. IO and IRQ should be known. */ @@ -517,11 +452,7 @@ /* Switch to bank 2 */ /* Lock our I/O address, and set manual processing mode for 16 collisions. */ outb(0x08, ioaddr + CONFIG_1); -#ifndef CONFIG_X86_PC9800 outb(dev->if_port, ioaddr + MODE13); -#else - outb(0, ioaddr + MODE13); -#endif outb(0x00, ioaddr + COL16CNTL); if (net_debug) @@ -542,7 +473,7 @@ lp->jumpered = is_fmv18x; lp->mca_slot = slot; /* Snarf the interrupt vector now. */ - ret = request_irq(irq, &net_interrupt, 0, dev->name, dev); + ret = request_irq(irq, &net_interrupt, 0, DRV_NAME, dev); if (ret) { printk (" AT1700 at %#3x is unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); @@ -557,12 +488,7 @@ mca_mark_as_unused(slot); #endif err_out: -#ifndef CONFIG_X86_PC9800 release_region(ioaddr, AT1700_IO_EXTENT); -#else - for (i = 0; i < 0x2000; i += 0x0200) - release_region(ioaddr + i, 2); -#endif return ret; } @@ -573,13 +499,6 @@ #define EE_DATA_WRITE 0x80 /* EEPROM chip data in, in reg. 17. */ #define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ -/* Delay between EEPROM clock transitions. */ -#ifndef CONFIG_X86_PC9800 -#define eeprom_delay() do { } while (0) -#else -#define eeprom_delay() __asm__ ("out%B0 %%al,%0" :: "N"(0x5f)) -#endif - /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5 << 6) #define EE_READ_CMD (6 << 6) @@ -598,22 +517,17 @@ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; outb(EE_CS, ee_addr); outb(dataval, ee_daddr); - eeprom_delay(); outb(EE_CS | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ - eeprom_delay(); } outb(EE_DATA_WRITE, ee_daddr); for (i = 16; i > 0; i--) { outb(EE_CS, ee_addr); - eeprom_delay(); outb(EE_CS | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0); } /* Terminate the EEPROM access. */ outb(EE_CS, ee_addr); - eeprom_delay(); outb(EE_SHIFT_CLK, ee_addr); outb(0, ee_addr); return retval; diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c --- a/drivers/net/cs89x0.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/cs89x0.c 2004-06-20 13:00:25 -07:00 @@ -141,6 +141,8 @@ static char version[] __initdata = "cs89x0.c: v2.4.3-pre1 Russell Nelson , Andrew Morton \n"; +#define DRV_NAME "cs89x0" + /* First, a few definitions that the brave might change. A zero-terminated list of I/O addresses to be probed. Some special flags.. Addr & 1 = Read back the address port, look for signature and reset @@ -261,7 +263,6 @@ } __setup("cs89x0_media=", media_fn); -#endif /* Check for a network adaptor of this type, and return '0' iff one exists. @@ -318,6 +319,7 @@ printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); return ERR_PTR(err); } +#endif static int readreg(struct net_device *dev, int portno) @@ -425,9 +427,9 @@ /* Grab the region so we can find another board if autoIRQ fails. */ /* WTF is going on here? */ - if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n", - dev->name, ioaddr, NETCARD_IO_EXTENT); + DRV_NAME, ioaddr, NETCARD_IO_EXTENT); retval = -EBUSY; goto out1; } diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c --- a/drivers/net/defxx.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/defxx.c 2004-06-20 13:00:23 -07:00 @@ -219,6 +219,8 @@ static char version[] __devinitdata = "defxx.c:v1.06 2003/08/04 Lawrence V. Stefani and others\n"; +#define DRV_NAME "defxx" + #define DYNAMIC_BUFFERS 1 #define SKBUFF_RX_COPYBREAK 200 @@ -435,9 +437,9 @@ bp = dev->priv; - if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, dev->name)) { + if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) { printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n", - dev->name, PFI_K_CSR_IO_LEN, ioaddr); + DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr); err = -EBUSY; goto err_out; } diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/e1000/e1000.h 2004-06-20 13:00:23 -07:00 @@ -196,6 +196,7 @@ uint32_t part_num; uint32_t wol; uint32_t smartspeed; + uint32_t en_mng_pt; uint16_t link_speed; uint16_t link_duplex; spinlock_t stats_lock; diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c --- a/drivers/net/e1000/e1000_ethtool.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/e1000/e1000_ethtool.c 2004-06-20 13:00:24 -07:00 @@ -1004,11 +1004,12 @@ struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); struct sk_buff *skb; - if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) { + if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, + GFP_KERNEL))) { ret_val = 6; goto err_nomem; } - skb_reserve(skb, 2); + skb_reserve(skb, NET_IP_ALIGN); rxdr->buffer_info[i].skb = skb; rxdr->buffer_info[i].length = E1000_RXBUFFER_2048; rxdr->buffer_info[i].dma = diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c --- a/drivers/net/e1000/e1000_hw.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/e1000/e1000_hw.c 2004-06-20 13:00:26 -07:00 @@ -265,6 +265,17 @@ return -E1000_ERR_MAC_TYPE; } + switch(hw->mac_type) { + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + hw->asf_firmware_present = TRUE; + break; + default: + break; + } + return E1000_SUCCESS; } @@ -5189,3 +5200,27 @@ return E1000_SUCCESS; } +/****************************************************************************** + * 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; + + 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 ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) + return TRUE; + } + return FALSE; +} diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h --- a/drivers/net/e1000/e1000_hw.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/e1000/e1000_hw.h 2004-06-20 13:00:25 -07:00 @@ -307,6 +307,7 @@ /* 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); @@ -983,6 +984,7 @@ e1000_ms_type master_slave; e1000_ms_type original_master_slave; e1000_ffe_config ffe_config_state; + uint32_t asf_firmware_present; unsigned long io_base; uint32_t phy_id; uint32_t phy_revision; diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/e1000/e1000_main.c 2004-06-20 13:00:24 -07:00 @@ -299,7 +299,7 @@ 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. */ @@ -341,6 +341,12 @@ 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); + } } /** @@ -483,6 +489,8 @@ if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + 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 */ @@ -2367,7 +2375,6 @@ struct e1000_rx_desc *rx_desc; struct e1000_buffer *buffer_info; struct sk_buff *skb; - int reserve_len = 2; unsigned int i; i = rx_ring->next_to_use; @@ -2376,7 +2383,7 @@ while(!buffer_info->skb) { rx_desc = E1000_RX_DESC(*rx_ring, i); - skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); + skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); if(!skb) { /* Better luck next round */ @@ -2387,7 +2394,7 @@ * this will result in a 16 byte aligned IP header after * the 14 byte MAC header is removed */ - skb_reserve(skb, reserve_len); + skb_reserve(skb, NET_IP_ALIGN); skb->dev = netdev; diff -Nru a/drivers/net/e2100.c b/drivers/net/e2100.c --- a/drivers/net/e2100.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/e2100.c 2004-06-20 13:00:25 -07:00 @@ -51,6 +51,8 @@ #include "8390.h" +#define DRV_NAME "e2100" + static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0}; /* Offsets from the base_addr. @@ -144,6 +146,7 @@ release_region(dev->base_addr, E21_IO_EXTENT); } +#ifndef MODULE struct net_device * __init e2100_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -168,6 +171,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init e21_probe1(struct net_device *dev, int ioaddr) { @@ -175,7 +179,7 @@ unsigned char *station_addr = dev->dev_addr; static unsigned version_printed; - if (!request_region(ioaddr, E21_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME)) return -EBUSY; /* First check the station address for the Ctron prefix. */ diff -Nru a/drivers/net/eepro.c b/drivers/net/eepro.c --- a/drivers/net/eepro.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/eepro.c 2004-06-20 13:00:25 -07:00 @@ -151,6 +151,8 @@ #include #include +#define DRV_NAME "eepro" + #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) ) /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */ #define SLOW_DOWN inb(0x80) @@ -577,6 +579,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init eepro_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local)); @@ -603,6 +606,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static void __init printEEPROMInfo(short ioaddr, struct net_device *dev) { @@ -745,7 +749,7 @@ int ioaddr = dev->base_addr; /* Grab the region so we can find another board if autoIRQ fails. */ - if (!request_region(ioaddr, EEPRO_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { if (!autoprobe) printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n", ioaddr); diff -Nru a/drivers/net/eexpress.c b/drivers/net/eexpress.c --- a/drivers/net/eexpress.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/eexpress.c 2004-06-20 13:00:23 -07:00 @@ -423,6 +423,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init express_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); @@ -443,6 +444,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* * open and initialize the adapter, ready for use diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c --- a/drivers/net/epic100.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/epic100.c 2004-06-20 13:00:24 -07:00 @@ -1218,13 +1218,8 @@ ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); -#if 1 /* HAS_IP_COPYSUM */ eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), ep->rx_skbuff[entry]->tail, - pkt_len); -#endif pci_dma_sync_single_for_device(ep->pci_dev, ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, diff -Nru a/drivers/net/eql.c b/drivers/net/eql.c --- a/drivers/net/eql.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/eql.c 2004-06-20 13:00:25 -07:00 @@ -495,8 +495,12 @@ return -EFAULT; slave_dev = dev_get_by_name(sc.slave_name); + if (!slave_dev) + return -ENODEV; ret = -EINVAL; + if (!slave_dev) + return ret; spin_lock_bh(&eql->queue.lock); if (eql_is_slave(slave_dev)) { @@ -527,11 +531,15 @@ if (copy_from_user(&sc, scp, sizeof (slave_config_t))) return -EFAULT; - eql = dev->priv; slave_dev = dev_get_by_name(sc.slave_name); + if (!slave_dev) + return -ENODEV; ret = -EINVAL; + if (!slave_dev) + return ret; + eql = dev->priv; spin_lock_bh(&eql->queue.lock); if (eql_is_slave(slave_dev)) { slave = __eql_find_slave_dev(&eql->queue, slave_dev); diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c --- a/drivers/net/es3210.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/es3210.c 2004-06-20 13:00:25 -07:00 @@ -161,6 +161,7 @@ release_region(dev->base_addr, ES_IO_EXTENT); } +#ifndef MODULE struct net_device * __init es_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -185,6 +186,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init es_probe1(struct net_device *dev, int ioaddr) { diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/eth16i.c 2004-06-20 13:00:25 -07:00 @@ -458,6 +458,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init eth16i_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local)); @@ -483,6 +484,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init eth16i_probe1(struct net_device *dev, int ioaddr) { @@ -491,7 +493,7 @@ int retval; /* Let's grab the region */ - if (!request_region(ioaddr, ETH16I_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname)) return -EBUSY; /* @@ -538,9 +540,9 @@ /* Try to obtain interrupt vector */ - if ((retval = request_irq(dev->irq, (void *)ð16i_interrupt, 0, dev->name, dev))) { - printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n", - dev->name, cardname, ioaddr, dev->irq); + if ((retval = request_irq(dev->irq, (void *)ð16i_interrupt, 0, cardname, dev))) { + printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n", + cardname, ioaddr, dev->irq); goto out; } diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c --- a/drivers/net/ewrk3.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/ewrk3.c 2004-06-20 13:00:26 -07:00 @@ -341,6 +341,7 @@ mdelay(1);\ } +#ifndef MODULE struct net_device * __init ewrk3_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct ewrk3_private)); @@ -364,6 +365,7 @@ return ERR_PTR(err); } +#endif static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq) { @@ -1269,7 +1271,7 @@ for (; (i < maxSlots) && (dev != NULL); iobase += EWRK3_IOP_INC, i++) { - if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name)) { + if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME)) { if (DevicePresent(iobase) == 0) { int irq = dev->irq; ret = ewrk3_hw_init(dev, iobase); @@ -1310,7 +1312,7 @@ for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { if (EISA_signature(name, EISA_ID) == 0) { - if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name) && + if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME) && DevicePresent(iobase) == 0) { int irq = dev->irq; ret = ewrk3_hw_init(dev, iobase); diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c --- a/drivers/net/fealnx.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/fealnx.c 2004-06-20 13:00:25 -07:00 @@ -858,11 +858,16 @@ { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; + int i; writel(0x00000001, ioaddr + BCR); /* Reset */ if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) return -EAGAIN; + + for (i = 0; i < 3; i++) + writew(((unsigned short*)dev->dev_addr)[i], + ioaddr + PAR0 + i*2); init_ring(dev); diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c --- a/drivers/net/fmv18x.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/fmv18x.c 2004-06-20 13:00:23 -07:00 @@ -57,6 +57,8 @@ #include #include +#define DRV_NAME "fmv18x" + static unsigned fmv18x_probe_list[] __initdata = { 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0 }; @@ -192,7 +194,7 @@ That means we have to be careful with the register values we probe for. */ - if (!request_region(ioaddr, FMV18X_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME)) return -EBUSY; dev->irq = irq; @@ -224,7 +226,7 @@ } /* Snarf the interrupt vector now. */ - retval = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev); if (retval) { printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" "IRQ %d.\n", ioaddr, dev->irq); diff -Nru a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c --- a/drivers/net/forcedeth.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/forcedeth.c 2004-06-20 13:00:23 -07:00 @@ -81,6 +81,7 @@ * superfluous timer interrupts from the nic. */ #define FORCEDETH_VERSION "0.25" +#define DRV_NAME "forcedeth" #include #include @@ -1424,7 +1425,7 @@ pci_set_master(pci_dev); - err = pci_request_regions(pci_dev, dev->name); + err = pci_request_regions(pci_dev, DRV_NAME); if (err < 0) goto out_disable; diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c --- a/drivers/net/hamachi.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/hamachi.c 2004-06-20 13:00:26 -07:00 @@ -207,10 +207,8 @@ /* Condensed bus+endian portability operations. */ #if ADDRLEN == 64 #define cpu_to_leXX(addr) cpu_to_le64(addr) -#define desc_to_virt(addr) bus_to_virt(le64_to_cpu(addr)) #else #define cpu_to_leXX(addr) cpu_to_le32(addr) -#define desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) #endif @@ -1502,7 +1500,7 @@ desc->addr, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); - buf_addr = desc_to_virt(desc->addr); + buf_addr = (u8 *) hmp->rx_skbuff[entry]->tail; frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12]))); if (hamachi_debug > 4) printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", diff -Nru a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c --- a/drivers/net/hamradio/hdlcdrv.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/hamradio/hdlcdrv.c 2004-06-20 13:00:25 -07:00 @@ -588,6 +588,8 @@ return -EINVAL; s = (struct hdlcdrv_state *)dev->priv; + netif_stop_queue(dev); + if (s->ops && s->ops->close) i = s->ops->close(dev); if (s->skb) diff -Nru a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c --- a/drivers/net/hp-plus.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/hp-plus.c 2004-06-20 13:00:23 -07:00 @@ -37,6 +37,8 @@ #include "8390.h" +#define DRV_NAME "hp-plus" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int hpplus_portlist[] __initdata = {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; @@ -142,6 +144,7 @@ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } +#ifndef MODULE struct net_device * __init hp_plus_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -166,6 +169,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* Do the interesting part of the probe at a single address. */ static int __init hpp_probe1(struct net_device *dev, int ioaddr) @@ -176,7 +180,7 @@ int mem_start; static unsigned version_printed; - if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME)) return -EBUSY; /* Check for the HP+ signature, 50 48 0x 53. */ diff -Nru a/drivers/net/hp.c b/drivers/net/hp.c --- a/drivers/net/hp.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/hp.c 2004-06-20 13:00:23 -07:00 @@ -37,6 +37,8 @@ #include "8390.h" +#define DRV_NAME "hp" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int hppclan_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0}; @@ -106,6 +108,7 @@ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } +#ifndef MODULE struct net_device * __init hp_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -130,6 +133,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init hp_probe1(struct net_device *dev, int ioaddr) { @@ -137,7 +141,7 @@ const char *name; static unsigned version_printed; - if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME)) return -EBUSY; /* Check for the HP physical address, 08 00 09 xx xx xx. */ @@ -182,7 +186,7 @@ outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE); outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE); if (irq == probe_irq_off(cookie) /* It's a good IRQ line! */ - && request_irq (irq, ei_interrupt, 0, dev->name, dev) == 0) { + && request_irq (irq, ei_interrupt, 0, DRV_NAME, dev) == 0) { printk(" selecting IRQ %d.\n", irq); dev->irq = *irqp; break; @@ -197,7 +201,7 @@ } else { if (dev->irq == 2) dev->irq = 9; - if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + if ((retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) { printk (" unable to get IRQ %d.\n", dev->irq); goto out; } diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/hp100.c 2004-06-20 13:00:24 -07:00 @@ -386,6 +386,7 @@ } +#ifndef MODULE struct net_device * __init hp100_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); @@ -420,6 +421,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init hp100_probe1(struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev) diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c --- a/drivers/net/ibmlana.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/ibmlana.c 2004-06-20 13:00:23 -07:00 @@ -98,6 +98,8 @@ #undef DEBUG +#define DRV_NAME "ibmlana" + /* ------------------------------------------------------------------------ * global static data - not more since we can handle multiple boards and * have to pack all state info into the device struct! @@ -952,8 +954,8 @@ printk(KERN_INFO "%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1); /* try to obtain I/O range */ - if (!request_region(iobase, IBM_LANA_IORANGE, dev->name)) { - printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", dev->name, iobase); + if (!request_region(iobase, IBM_LANA_IORANGE, DRV_NAME)) { + printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", DRV_NAME, iobase); startslot = slot + 1; return -EBUSY; } diff -Nru a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c --- a/drivers/net/irda/ali-ircc.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/irda/ali-ircc.c 2004-06-20 13:00:24 -07:00 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -304,16 +305,18 @@ self->tx_buff.truesize = 14384; /* Allocate memory if needed */ - self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, - GFP_KERNEL |GFP_DMA); + self->rx_buff.head = + dma_alloc_coherent(NULL, self->rx_buff.truesize, + &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { err = -ENOMEM; goto err_out2; } memset(self->rx_buff.head, 0, self->rx_buff.truesize); - self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->tx_buff.head = + dma_alloc_coherent(NULL, self->tx_buff.truesize, + &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { err = -ENOMEM; goto err_out3; @@ -362,9 +365,11 @@ return 0; err_out4: - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); err_out3: - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); err_out2: release_region(self->io.fir_base, self->io.fir_ext); err_out1: @@ -398,10 +403,12 @@ release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); if (self->rx_buff.head) - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); dev_self[self->index] = NULL; free_netdev(self->netdev); @@ -1572,7 +1579,8 @@ self->io.direction = IO_XMIT; irda_setup_dma(self->io.dma, - self->tx_fifo.queue[self->tx_fifo.ptr].start, + ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - + self->tx_buff.head) + self->tx_buff_dma, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); @@ -1724,8 +1732,8 @@ self->st_fifo.len = self->st_fifo.pending_bytes = 0; self->st_fifo.tail = self->st_fifo.head = 0; - irda_setup_dma(self->io.dma, self->rx_buff.data, - self->rx_buff.truesize, DMA_RX_MODE); + irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, + DMA_RX_MODE); /* Set Receive Mode,Brick Wall */ //switch_bank(iobase, BANK0); diff -Nru a/drivers/net/irda/ali-ircc.h b/drivers/net/irda/ali-ircc.h --- a/drivers/net/irda/ali-ircc.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/irda/ali-ircc.h 2004-06-20 13:00:24 -07:00 @@ -26,6 +26,7 @@ #include #include +#include #include /* SIR Register */ @@ -198,6 +199,8 @@ chipio_t io; /* IrDA controller information */ iobuff_t tx_buff; /* Transmit buffer */ iobuff_t rx_buff; /* Receive buffer */ + dma_addr_t tx_buff_dma; + dma_addr_t rx_buff_dma; __u8 ier; /* Interrupt enable register */ diff -Nru a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c --- a/drivers/net/irda/irtty-sir.c 2004-06-20 13:00:22 -07:00 +++ b/drivers/net/irda/irtty-sir.c 2004-06-20 13:00:22 -07:00 @@ -438,7 +438,6 @@ struct irtty_info { char name[6]; } info; struct sir_dev *dev; struct sirtty_cb *priv = tty->disc_data; - int size = _IOC_SIZE(cmd); int err = 0; ASSERT(priv != NULL, return -ENODEV;); @@ -449,13 +448,6 @@ dev = priv->dev; ASSERT(dev != NULL, return -1;); - if (_IOC_DIR(cmd) & _IOC_READ) - err = verify_area(VERIFY_WRITE, (void *) arg, size); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - err = verify_area(VERIFY_READ, (void *) arg, size); - if (err) - return err; - switch (cmd) { case TCGETS: case TCGETA: @@ -473,7 +465,7 @@ memset(&info, 0, sizeof(info)); strncpy(info.name, dev->netdev->name, sizeof(info.name)-1); - if (copy_to_user((void *)arg, &info, sizeof(info))) + if (copy_to_user((void __user *)arg, &info, sizeof(info))) err = -EFAULT; break; default: diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c --- a/drivers/net/irda/nsc-ircc.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/irda/nsc-ircc.c 2004-06-20 13:00:23 -07:00 @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -307,8 +308,9 @@ self->tx_buff.truesize = 14384; /* Allocate memory if needed */ - self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->rx_buff.head = + dma_alloc_coherent(NULL, self->rx_buff.truesize, + &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { err = -ENOMEM; goto out2; @@ -316,8 +318,9 @@ } memset(self->rx_buff.head, 0, self->rx_buff.truesize); - self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->tx_buff.head = + dma_alloc_coherent(NULL, self->tx_buff.truesize, + &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { err = -ENOMEM; goto out3; @@ -368,9 +371,11 @@ return 0; out4: - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); out3: - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); out2: release_region(self->io.fir_base, self->io.fir_ext); out1: @@ -404,10 +409,12 @@ release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); if (self->rx_buff.head) - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); dev_self[self->index] = NULL; free_netdev(self->netdev); @@ -1409,7 +1416,8 @@ outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); irda_setup_dma(self->io.dma, - self->tx_fifo.queue[self->tx_fifo.ptr].start, + ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - + self->tx_buff.head) + self->tx_buff_dma, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); @@ -1566,8 +1574,8 @@ self->st_fifo.len = self->st_fifo.pending_bytes = 0; self->st_fifo.tail = self->st_fifo.head = 0; - irda_setup_dma(self->io.dma, self->rx_buff.data, - self->rx_buff.truesize, DMA_RX_MODE); + irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, + DMA_RX_MODE); /* Enable DMA */ switch_bank(iobase, BANK0); diff -Nru a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h --- a/drivers/net/irda/nsc-ircc.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/irda/nsc-ircc.h 2004-06-20 13:00:24 -07:00 @@ -32,6 +32,7 @@ #include #include +#include #include /* DMA modes needed */ @@ -255,6 +256,8 @@ chipio_t io; /* IrDA controller information */ iobuff_t tx_buff; /* Transmit buffer */ iobuff_t rx_buff; /* Receive buffer */ + dma_addr_t tx_buff_dma; + dma_addr_t rx_buff_dma; __u8 ier; /* Interrupt enable register */ diff -Nru a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c --- a/drivers/net/irda/smsc-ircc2.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/irda/smsc-ircc2.c 2004-06-20 13:00:25 -07:00 @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -112,6 +113,8 @@ chipio_t io; /* IrDA controller information */ iobuff_t tx_buff; /* Transmit buffer */ iobuff_t rx_buff; /* Receive buffer */ + dma_addr_t tx_buff_dma; + dma_addr_t rx_buff_dma; struct qos_info qos; /* QoS capabilities for this device */ @@ -413,16 +416,18 @@ self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE; - self->rx_buff.head = (u8 *) kmalloc(self->rx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->rx_buff.head = + dma_alloc_coherent(NULL, self->rx_buff.truesize, + &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { ERROR("%s, Can't allocate memory for receive buffer!\n", driver_name); goto err_out2; } - self->tx_buff.head = (u8 *) kmalloc(self->tx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->tx_buff.head = + dma_alloc_coherent(NULL, self->tx_buff.truesize, + &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { ERROR("%s, Can't allocate memory for transmit buffer!\n", driver_name); @@ -464,9 +469,11 @@ return 0; err_out4: - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); err_out3: - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); err_out2: free_netdev(self->netdev); dev_self[--dev_count] = NULL; @@ -1159,7 +1166,7 @@ IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB); /* Setup DMA controller (must be done after enabling chip DMA) */ - irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, + irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, DMA_TX_MODE); /* Enable interrupt */ @@ -1249,8 +1256,8 @@ outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO); /* Setup DMA controller */ - irda_setup_dma(self->io.dma, self->rx_buff.data, - self->rx_buff.truesize, DMA_RX_MODE); + irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, + DMA_RX_MODE); /* Enable burst mode chip Rx DMA */ register_bank(iobase, 1); @@ -1717,10 +1724,12 @@ release_region(self->io.sir_base, self->io.sir_ext); if (self->tx_buff.head) - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); if (self->rx_buff.head) - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); free_netdev(self->netdev); diff -Nru a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c --- a/drivers/net/irda/via-ircc.c 2004-06-20 13:00:22 -07:00 +++ b/drivers/net/irda/via-ircc.c 2004-06-20 13:00:23 -07:00 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -383,7 +384,8 @@ /* Allocate memory if needed */ self->rx_buff.head = - (__u8 *) kmalloc(self->rx_buff.truesize, GFP_KERNEL | GFP_DMA); + dma_alloc_coherent(NULL, self->rx_buff.truesize, + &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { err = -ENOMEM; goto err_out2; @@ -391,7 +393,8 @@ memset(self->rx_buff.head, 0, self->rx_buff.truesize); self->tx_buff.head = - (__u8 *) kmalloc(self->tx_buff.truesize, GFP_KERNEL | GFP_DMA); + dma_alloc_coherent(NULL, self->tx_buff.truesize, + &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { err = -ENOMEM; goto err_out3; @@ -432,9 +435,11 @@ return 0; err_out4: - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); err_out3: - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); err_out2: release_region(self->io.fir_base, self->io.fir_ext); err_out1: @@ -468,9 +473,11 @@ __FUNCTION__, self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); if (self->rx_buff.head) - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); dev_self[self->index] = NULL; free_netdev(self->netdev); @@ -816,7 +823,7 @@ EnTXDMA(iobase, ON); EnRXDMA(iobase, OFF); - irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, + irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, DMA_TX_MODE); SetSendByte(iobase, self->tx_buff.len); @@ -897,7 +904,8 @@ EnTXDMA(iobase, ON); EnRXDMA(iobase, OFF); irda_setup_dma(self->io.dma, - self->tx_fifo.queue[self->tx_fifo.ptr].start, + ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - + self->tx_buff.head) + self->tx_buff_dma, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); #ifdef DBGMSG DBG(printk @@ -1022,8 +1030,8 @@ EnAllInt(iobase, ON); EnTXDMA(iobase, OFF); EnRXDMA(iobase, ON); - irda_setup_dma(self->io.dma2, self->rx_buff.data, - self->rx_buff.truesize, DMA_RX_MODE); + irda_setup_dma(self->io.dma2, self->rx_buff_dma, + self->rx_buff.truesize, DMA_RX_MODE); TXStart(iobase, OFF); RXStart(iobase, ON); diff -Nru a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h --- a/drivers/net/irda/via-ircc.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/irda/via-ircc.h 2004-06-20 13:00:25 -07:00 @@ -33,6 +33,7 @@ #include #include #include +#include #include #define MAX_TX_WINDOW 7 @@ -102,6 +103,8 @@ chipio_t io; /* IrDA controller information */ iobuff_t tx_buff; /* Transmit buffer */ iobuff_t rx_buff; /* Receive buffer */ + dma_addr_t tx_buff_dma; + dma_addr_t rx_buff_dma; __u8 ier; /* Interrupt enable register */ diff -Nru a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c --- a/drivers/net/irda/w83977af_ir.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/irda/w83977af_ir.c 2004-06-20 13:00:24 -07:00 @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -207,8 +208,9 @@ self->tx_buff.truesize = 4000; /* Allocate memory if needed */ - self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->rx_buff.head = + dma_alloc_coherent(NULL, self->rx_buff.truesize, + &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { err = -ENOMEM; goto err_out1; @@ -216,8 +218,9 @@ memset(self->rx_buff.head, 0, self->rx_buff.truesize); - self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, - GFP_KERNEL|GFP_DMA); + self->tx_buff.head = + dma_alloc_coherent(NULL, self->tx_buff.truesize, + &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { err = -ENOMEM; goto err_out2; @@ -252,9 +255,11 @@ return 0; err_out3: - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); err_out2: - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); err_out1: free_netdev(dev); err_out: @@ -297,10 +302,12 @@ release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) - kfree(self->tx_buff.head); + dma_free_coherent(NULL, self->tx_buff.truesize, + self->tx_buff.head, self->tx_buff_dma); if (self->rx_buff.head) - kfree(self->rx_buff.head); + dma_free_coherent(NULL, self->rx_buff.truesize, + self->rx_buff.head, self->rx_buff_dma); free_netdev(self->netdev); @@ -606,10 +613,10 @@ disable_dma(self->io.dma); clear_dma_ff(self->io.dma); set_dma_mode(self->io.dma, DMA_MODE_READ); - set_dma_addr(self->io.dma, isa_virt_to_bus(self->tx_buff.data)); + set_dma_addr(self->io.dma, self->tx_buff_dma); set_dma_count(self->io.dma, self->tx_buff.len); #else - irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, + irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, DMA_MODE_WRITE); #endif self->io.direction = IO_XMIT; @@ -763,10 +770,10 @@ disable_dma(self->io.dma); clear_dma_ff(self->io.dma); set_dma_mode(self->io.dma, DMA_MODE_READ); - set_dma_addr(self->io.dma, isa_virt_to_bus(self->rx_buff.data)); + set_dma_addr(self->io.dma, self->rx_buff_dma); set_dma_count(self->io.dma, self->rx_buff.truesize); #else - irda_setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, + irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, DMA_MODE_READ); #endif /* diff -Nru a/drivers/net/irda/w83977af_ir.h b/drivers/net/irda/w83977af_ir.h --- a/drivers/net/irda/w83977af_ir.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/irda/w83977af_ir.h 2004-06-20 13:00:23 -07:00 @@ -26,6 +26,7 @@ #define W83977AF_IR_H #include +#include /* Flags for configuration register CRF0 */ #define ENBNKSEL 0x01 @@ -179,6 +180,8 @@ chipio_t io; /* IrDA controller information */ iobuff_t tx_buff; /* Transmit buffer */ iobuff_t rx_buff; /* Receive buffer */ + dma_addr_t tx_buff_dma; + dma_addr_t rx_buff_dma; /* Note : currently locking is *very* incomplete, but this * will get you started. Check in nsc-ircc.c for a proper diff -Nru a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c --- a/drivers/net/isa-skeleton.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/isa-skeleton.c 2004-06-20 13:00:26 -07:00 @@ -161,6 +161,7 @@ release_region(dev->base_addr, NETCARD_IO_EXTENT); } +#ifndef MODULE struct net_device * __init netcard_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); @@ -185,6 +186,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* * This is the real probe routine. Linux has a history of friendly device diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c --- a/drivers/net/ixgb/ixgb_main.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/ixgb/ixgb_main.c 2004-06-20 13:00:23 -07:00 @@ -1876,7 +1876,6 @@ struct ixgb_rx_desc *rx_desc; struct ixgb_buffer *buffer_info; struct sk_buff *skb; - int reserve_len = 2; unsigned int i; int num_group_tail_writes; long cleancount; @@ -1895,7 +1894,7 @@ while (--cleancount > 0) { rx_desc = IXGB_RX_DESC(*rx_ring, i); - skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); + skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); if (unlikely(!skb)) { /* Better luck next round */ @@ -1906,7 +1905,7 @@ * this will result in a 16 byte aligned IP header after * the 14 byte MAC header is removed */ - skb_reserve(skb, reserve_len); + skb_reserve(skb, NET_IP_ALIGN); skb->dev = netdev; diff -Nru a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c --- a/drivers/net/jazzsonic.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/jazzsonic.c 2004-06-20 13:00:24 -07:00 @@ -37,6 +37,8 @@ #include #include +#define DRV_NAME "jazzsonic" + #define SREGS_PAD(n) u16 n; #include "sonic.h" @@ -151,7 +153,7 @@ int err = -ENODEV; int i; - if (!request_region(base_addr, 0x100, dev->name)) + if (!request_region(base_addr, 0x100, DRV_NAME)) return -EBUSY; /* * get the Silicon Revision ID. If this is one of the known diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c --- a/drivers/net/lance.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/lance.c 2004-06-20 13:00:23 -07:00 @@ -432,6 +432,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init lance_probe(int unit) { struct net_device *dev = alloc_etherdev(0); @@ -456,6 +457,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options) { diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c --- a/drivers/net/lasi_82596.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/lasi_82596.c 2004-06-20 13:00:23 -07:00 @@ -87,7 +87,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c --- a/drivers/net/lne390.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/lne390.c 2004-06-20 13:00:25 -07:00 @@ -49,6 +49,8 @@ #include "8390.h" +#define DRV_NAME "lne390" + static int lne390_probe1(struct net_device *dev, int ioaddr); static int lne390_open(struct net_device *dev); @@ -112,7 +114,7 @@ SET_MODULE_OWNER(dev); if (ioaddr > 0x1ff) { /* Check a single specified location. */ - if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME)) return -EBUSY; ret = lne390_probe1(dev, ioaddr); if (ret) @@ -131,7 +133,7 @@ /* EISA spec allows for up to 16 slots, but 8 is typical. */ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME)) continue; if (lne390_probe1(dev, ioaddr) == 0) return 0; @@ -151,6 +153,7 @@ iounmap((void *)dev->mem_start); } +#ifndef MODULE struct net_device * __init lne390_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -175,6 +178,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init lne390_probe1(struct net_device *dev, int ioaddr) { @@ -228,7 +232,7 @@ } printk(" IRQ %d,", dev->irq); - if ((ret = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + if ((ret = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) { printk (" unable to get IRQ %d.\n", dev->irq); return ret; } diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c --- a/drivers/net/lp486e.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/lp486e.c 2004-06-20 13:00:23 -07:00 @@ -75,6 +75,8 @@ #include #include +#define DRV_NAME "lp486e" + /* debug print flags */ #define LOG_SRCDST 0x80000000 #define LOG_STATINT 0x40000000 @@ -970,7 +972,7 @@ return -ENODEV; probed++; - if (!request_region(IOADDR, LP486E_TOTAL_SIZE, dev->name)) { + if (!request_region(IOADDR, LP486E_TOTAL_SIZE, DRV_NAME)) { printk(KERN_ERR "lp486e: IO address 0x%x in use\n", IOADDR); return -EBUSY; } diff -Nru a/drivers/net/macsonic.c b/drivers/net/macsonic.c --- a/drivers/net/macsonic.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/macsonic.c 2004-06-20 13:00:23 -07:00 @@ -53,7 +53,6 @@ #include #include #include -#include #define SREGS_PAD(n) u16 n; @@ -613,7 +612,6 @@ MODULE_PARM(sonic_debug, "i"); MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); -MODULE_LICENSE("GPL"); int init_module(void) diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c --- a/drivers/net/natsemi.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/natsemi.c 2004-06-20 13:00:23 -07:00 @@ -766,7 +766,7 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - i = pci_request_regions(pdev, dev->name); + i = pci_request_regions(pdev, DRV_NAME); if (i) goto err_pci_request_regions; @@ -1798,14 +1798,9 @@ np->rx_dma[entry], buflen, PCI_DMA_FROMDEVICE); -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - np->rx_skbuff[entry]->tail, pkt_len); -#endif pci_dma_sync_single_for_device(np->pci_dev, np->rx_dma[entry], buflen, diff -Nru a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c --- a/drivers/net/ne-h8300.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/ne-h8300.c 2004-06-20 13:00:24 -07:00 @@ -34,6 +34,8 @@ #include "8390.h" +#define DRV_NAME "ne-h8300" + /* Some defines that people can play with if so inclined. */ /* Do we perform extra sanity checks on stuff ? */ @@ -156,6 +158,7 @@ release_region(dev->base_addr, NE_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ne_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -187,6 +190,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ne_probe1(struct net_device *dev, int ioaddr) { @@ -200,7 +204,7 @@ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); unsigned char bus_width; - if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; reg0 = inb_p(ioaddr); diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c --- a/drivers/net/ne.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/ne.c 2004-06-20 13:00:24 -07:00 @@ -55,6 +55,8 @@ #include "8390.h" +#define DRV_NAME "ne" + /* Some defines that people can play with if so inclined. */ /* Do we support clones that don't adhere to 14,15 of the SAprom ? */ @@ -203,6 +205,7 @@ release_region(dev->base_addr, NE_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ne_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -227,6 +230,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ne_probe_isapnp(struct net_device *dev) { @@ -284,7 +288,7 @@ int reg0, ret; static unsigned version_printed; - if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; reg0 = inb_p(ioaddr); diff -Nru a/drivers/net/ne2.c b/drivers/net/ne2.c --- a/drivers/net/ne2.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/ne2.c 2004-06-20 13:00:26 -07:00 @@ -82,6 +82,8 @@ #include "8390.h" +#define DRV_NAME "ne2" + /* Some defines that people can play with if so inclined. */ /* Do we perform extra sanity checks on stuff ? */ @@ -284,6 +286,7 @@ release_region(dev->base_addr, NE_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ne2_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -308,6 +311,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int ne2_procinfo(char *buf, int slot, struct net_device *dev) { @@ -368,7 +372,7 @@ irq = irqs[(POS & 0x60)>>5]; } - if (!request_region(base_addr, NE_IO_EXTENT, dev->name)) + if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; #ifdef DEBUG @@ -470,7 +474,7 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (retval) { printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, retval); diff -Nru a/drivers/net/ne2k_cbus.c b/drivers/net/ne2k_cbus.c --- a/drivers/net/ne2k_cbus.c 2004-06-20 13:00:24 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,887 +0,0 @@ -/* - - ne2k_cbus.c: A driver for the NE2000 like ethernet on NEC PC-9800. - - This is a copy of the 2.5.66 Linux ISA NE2000 driver "ne.c" - (Donald Becker/Paul Gortmaker) with the NEC PC-9800 specific - changes added by Osamu Tomita. - -From ne.c: ------------ - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. ------------ - -*/ - -/* Routines for the NatSemi-based designs (NE[12]000). */ - -static const char version[] = -"ne2k_cbus.c:v1.0 3/24/03 Osamu Tomita\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "8390.h" - -/* Some defines that people can play with if so inclined. */ - -/* Do we support clones that don't adhere to 14,15 of the SAprom ? */ -#define SUPPORT_NE_BAD_CLONES - -/* Do we perform extra sanity checks on stuff ? */ -/* #define NE_SANITY_CHECK */ - -/* Do we implement the read before write bugfix ? */ -/* #define NE_RW_BUGFIX */ - -/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ -/* #define PACKETBUF_MEMSIZE 0x40 */ - -#ifdef SUPPORT_NE_BAD_CLONES -/* A list of bad clones that we none-the-less recognize. */ -static struct { const char *name8, *name16; unsigned char SAprefix[4];} -bad_clone_list[] __initdata = { - {"LA/T-98?", "LA/T-98", {0x00, 0xa0, 0xb0}}, /* I/O Data */ - {"EGY-98?", "EGY-98", {0x00, 0x40, 0x26}}, /* Melco EGY98 */ - {"ICM?", "ICM-27xx-ET", {0x00, 0x80, 0xc8}}, /* ICM IF-27xx-ET */ - {"CNET-98/EL?", "CNET(98)E/L", {0x00, 0x80, 0x4C}}, /* Contec CNET-98/EL */ - {0,} -}; -#endif - -/* ---- No user-serviceable parts below ---- */ - -#define NE_BASE (dev->base_addr) -#define NE_CMD EI_SHIFT(0x00) -#define NE_DATAPORT EI_SHIFT(0x10) /* NatSemi-defined port window offset. */ -#define NE_RESET EI_SHIFT(0x1f) /* Issue a read to reset, a write to clear. */ -#define NE_IO_EXTENT 0x20 - -#define NE1SM_START_PG 0x20 /* First page of TX buffer */ -#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ -#define NESM_START_PG 0x40 /* First page of TX buffer */ -#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ - -#include "ne2k_cbus.h" - -static int ne_probe1(struct net_device *dev, int ioaddr); -static int ne_open(struct net_device *dev); -static int ne_close(struct net_device *dev); - -static void ne_reset_8390(struct net_device *dev); -static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void ne_block_input(struct net_device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void ne_block_output(struct net_device *dev, const int count, - const unsigned char *buf, const int start_page); - - -/* Probe for various non-shared-memory ethercards. - - NEx000-clone boards have a Station Address PROM (SAPROM) in the packet - buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of - the SAPROM, while other supposed NE2000 clones must be detected by their - SA prefix. - - Reading the SAPROM from a word-wide card with the 8390 set in byte-wide - mode results in doubled values, which can be detected and compensated for. - - The probe is also responsible for initializing the card and filling - in the 'dev' and 'ei_status' structures. - - We use the minimum memory size for some ethercard product lines, iff we can't - distinguish models. You can increase the packet buffer size by setting - PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are: - E1010 starts at 0x100 and ends at 0x2000. - E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") - E2010 starts at 0x100 and ends at 0x4000. - E2010-x starts at 0x100 and ends at 0xffff. */ - -static int __init do_ne_probe(struct net_device *dev) -{ - unsigned int base_addr = dev->base_addr; - int irq = dev->irq; - - SET_MODULE_OWNER(dev); - - if (ei_debug > 2) - printk(KERN_DEBUG "ne_probe(): entered.\n"); - - /* If CONFIG_NET_CBUS, - we need dev->priv->reg_offset BEFORE to probe */ - if (ne2k_cbus_init(dev) != 0) - return -ENOMEM; - - /* First check any supplied i/o locations. User knows best. */ - if (base_addr > 0) { - int result; - const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); - - if (ei_debug > 2) - printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr); - - result = ne_probe_cbus(dev, hw, base_addr, irq); - if (result != 0) - ne2k_cbus_destroy(dev); - - return result; - } - - if (ei_debug > 2) - printk(KERN_DEBUG "ne_probe(): base_addr is not specified.\n"); - -#ifndef MODULE - /* Last resort. The semi-risky C-Bus auto-probe. */ - if (ei_debug > 2) - printk(KERN_DEBUG "ne_probe(): auto-probe start.\n"); - - { - const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); - - if (hw && hw->hwtype) { - const unsigned short *plist; - for (plist = hw->portlist; *plist; plist++) - if (ne_probe_cbus(dev, hw, *plist, irq) == 0) - return 0; - } else { - for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { - const unsigned short *plist; - for (plist = hw->portlist; *plist; plist++) - if (ne_probe_cbus(dev, hw, *plist, irq) == 0) - return 0; - } - } - } -#endif - - ne2k_cbus_destroy(dev); - - return -ENODEV; -} - -static void cleanup_card(struct net_device *dev) -{ - const struct ne2k_cbus_region *rlist; - const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); - - free_irq(dev->irq, dev); - for (rlist = hw->regionlist; rlist->range; rlist++) { - release_region(dev->base_addr + rlist->start, - rlist->range); - } - ne2k_cbus_destroy(dev); -} - -struct net_device * __init ne_probe(int unit) -{ - struct net_device *dev = alloc_ei_netdev(); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_ne_probe(dev); - if (err) - goto out; - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - cleanup_card(dev); -out: - free_netdev(dev); - return ERR_PTR(err); -} - -static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq) -{ - if (ei_debug > 2) - printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n", - __builtin_return_address(0)); - - if (hw && hw->hwtype) { - ne2k_cbus_set_hwtype(dev, hw, ioaddr); - dev->irq = irq; - return ne_probe1(dev, ioaddr); - } else { - /* auto detect */ - - printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n"); - for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { - ne2k_cbus_set_hwtype(dev, hw, ioaddr); - dev->irq = irq; - if (ne_probe1(dev, ioaddr) == 0) - return 0; - } - } - return -ENODEV; -} - -static int __init ne_probe1(struct net_device *dev, int ioaddr) -{ - int i; - unsigned char SA_prom[32]; - int wordlength = 2; - const char *name = NULL; - int start_page, stop_page; - int neX000, bad_card; - int reg0, ret; - static unsigned version_printed; - const struct ne2k_cbus_region *rlist; - const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - -#ifdef CONFIG_NE2K_CBUS_CNET98EL - if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) { - outb_p(0, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE); - /* udelay(5000); */ - outb_p(1, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE); - /* udelay(5000); */ - outb_p((ioaddr & 0xf000) >> 8 | 0x08 | 0x01, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE + 2); - /* udelay(5000); */ - } -#endif - - for (rlist = hw->regionlist; rlist->range; rlist++) - if (!request_region(ioaddr + rlist->start, - rlist->range, dev->name)) { - ret = -EBUSY; - goto err_out; - } - - reg0 = inb_p(ioaddr + EI_SHIFT(0)); - if (reg0 == 0xFF) { - ret = -ENODEV; - goto err_out; - } - - /* Do a preliminary verification that we have a 8390. */ -#ifdef CONFIG_NE2K_CBUS_CNET98EL - if (hw->hwtype != NE2K_CBUS_HARDWARE_TYPE_CNET98EL) -#endif - { - int regd; - outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); - regd = inb_p(ioaddr + EI_SHIFT(0x0d)); - outb_p(0xff, ioaddr + EI_SHIFT(0x0d)); - outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); - inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ - if (inb_p(ioaddr + EN0_COUNTER0) != 0) { - outb_p(reg0, ioaddr); - outb_p(regd, ioaddr + EI_SHIFT(0x0d)); /* Restore the old values. */ - ret = -ENODEV; - goto err_out; - } - } - - if (ei_debug && version_printed++ == 0) - printk(KERN_INFO "%s", version); - - printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr); - - /* A user with a poor card that fails to ack the reset, or that - does not have a valid 0x57,0x57 signature can still use this - without having to recompile. Specifying an i/o address along - with an otherwise unused dev->mem_end value of "0xBAD" will - cause the driver to skip these parts of the probe. */ - - bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad)); - - /* Reset card. Who knows what dain-bramaged state it was left in. */ - - { - unsigned long reset_start_time = jiffies; - - /* derived from CNET98EL-patch for bad clones */ - outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); - - /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ - outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); - - while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - if (bad_card) { - printk(" (warning: no reset ack)"); - break; - } else { - printk(" not found (no reset ack).\n"); - ret = -ENODEV; - goto err_out; - } - } - - outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ - } - -#ifdef CONFIG_NE2K_CBUS_CNET98EL - if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) { - static const char pat[32] ="AbcdeFghijKlmnoPqrstUvwxyZ789012"; - char buf[32]; - int maxwait = 200; - - if (ei_debug > 2) - printk(" [CNET98EL-specific initialize..."); - outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); /* 0x20|0x1 */ - ret = -ENODEV; - i = inb(ioaddr); - if ((i & ~0x2) != (0x20 | 0x01)) - goto err_out; - if ((inb(ioaddr + 0x7) & 0x80) != 0x80) - goto err_out; - outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* out(ioaddr+0xc, 0x20) */ - /* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */ - outb_p(ENDCFG_WTS | 0x48, ioaddr + EN0_DCFG); /* 0x49 */ - outb_p(CNET98EL_START_PG, ioaddr + EN0_STARTPG); - outb_p(CNET98EL_STOP_PG, ioaddr + EN0_STOPPG); - if (ei_debug > 2) - printk("memory check"); - for (i = 0; i < 65536; i += 1024) { - if (ei_debug > 2) - printk(" %04x", i); - ne2k_cbus_writemem(dev, ioaddr, i, pat, 32); - while (((inb(ioaddr + EN0_ISR) & ENISR_RDC) != ENISR_RDC) && --maxwait) - ; - ne2k_cbus_readmem(dev, ioaddr, i, buf, 32); - if (memcmp(pat, buf, 32)) { - if (ei_debug > 2) - printk(" failed."); - break; - } - } - if (i != 16384) { - if (ei_debug > 2) - printk("] "); - printk("memory failure at %x\n", i); - goto err_out; - } - if (ei_debug > 2) - printk(" good..."); - if (!dev->irq) { - if (ei_debug > 2) - printk("] "); - printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n"); - goto err_out; - } - outb((dev->irq > 5) ? (dev->irq & 4):(dev->irq >> 1), ioaddr + (0x2 | 0x400)); - outb(0x7e, ioaddr + (0x4 | 0x400)); - ne2k_cbus_readmem(dev, ioaddr, 16384, SA_prom, 32); - outb(0xff, ioaddr + EN0_ISR); - if (ei_debug > 2) - printk("done]"); - } else -#endif /* CONFIG_NE2K_CBUS_CNET98EL */ - /* Read the 16 bytes of station address PROM. - We must first initialize registers, similar to NS8390_init(eifdev, 0). - We can't reliably read the SAPROM address without this. - (I learned the hard way!). */ - { - struct {unsigned char value; unsigned short offset;} program_seq[] = - { - {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ - /* NEC PC-9800: some board can only handle word-wide access? */ - {0x48 | ENDCFG_WTS, EN0_DCFG}, /* Set word-wide (0x48) access. */ - {16384 / 256, EN0_STARTPG}, - {32768 / 256, EN0_STOPPG}, - {0x00, EN0_RCNTLO}, /* Clear the count regs. */ - {0x00, EN0_RCNTHI}, - {0x00, EN0_IMR}, /* Mask completion irq. */ - {0xFF, EN0_ISR}, - {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ - {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ - {32, EN0_RCNTLO}, - {0x00, EN0_RCNTHI}, - {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ - {0x00, EN0_RSARHI}, - {E8390_RREAD+E8390_START, E8390_CMD}, - }; - - for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) - outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); - insw(ioaddr + NE_DATAPORT, SA_prom, 32 >> 1); - - } - - if (wordlength == 2) - { - for (i = 0; i < 16; i++) - SA_prom[i] = SA_prom[i+i]; - start_page = NESM_START_PG; - stop_page = NESM_STOP_PG; -#ifdef CONFIG_NE2K_CBUS_CNET98EL - if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) { - start_page = CNET98EL_START_PG; - stop_page = CNET98EL_STOP_PG; - } -#endif - } else { - start_page = NE1SM_START_PG; - stop_page = NE1SM_STOP_PG; - } - - neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); - if (neX000) { - name = "C-Bus-NE2K-compat"; - } - else - { -#ifdef SUPPORT_NE_BAD_CLONES - /* Ack! Well, there might be a *bad* NE*000 clone there. - Check for total bogus addresses. */ - for (i = 0; bad_clone_list[i].name8; i++) - { - if (SA_prom[0] == bad_clone_list[i].SAprefix[0] && - SA_prom[1] == bad_clone_list[i].SAprefix[1] && - SA_prom[2] == bad_clone_list[i].SAprefix[2]) - { - if (wordlength == 2) - { - name = bad_clone_list[i].name16; - } else { - name = bad_clone_list[i].name8; - } - break; - } - } - if (bad_clone_list[i].name8 == NULL) - { - printk(" not found (invalid signature %2.2x %2.2x).\n", - SA_prom[14], SA_prom[15]); - ret = -ENXIO; - goto err_out; - } -#else - printk(" not found.\n"); - ret = -ENXIO; - goto err_out; -#endif - } - - if (dev->irq < 2) - { - unsigned long cookie = probe_irq_on(); - outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */ - outb_p(0x00, ioaddr + EN0_RCNTLO); - outb_p(0x00, ioaddr + EN0_RCNTHI); - outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */ - mdelay(10); /* wait 10ms for interrupt to propagate */ - outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ - dev->irq = probe_irq_off(cookie); - if (ei_debug > 2) - printk(" autoirq is %d\n", dev->irq); - } else if (dev->irq == 7) - /* Fixup for users that don't know that IRQ 7 is really IRQ 11, - or don't know which one to set. */ - dev->irq = 11; - - if (! dev->irq) { - printk(" failed to detect IRQ line.\n"); - ret = -EAGAIN; - goto err_out; - } - - /* Snarf the interrupt now. There's no point in waiting since we cannot - share and the board will usually be enabled. */ - ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); - if (ret) { - printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); - goto err_out_kfree; - } - - dev->base_addr = ioaddr; - - for(i = 0; i < ETHER_ADDR_LEN; i++) { - printk(" %2.2x", SA_prom[i]); - dev->dev_addr[i] = SA_prom[i]; - } - - printk("\n%s: %s found at %#x, hardware type %d(%s), using IRQ %d.\n", - dev->name, name, ioaddr, hw->hwtype, hw->hwident, dev->irq); - - ei_status.name = name; - ei_status.tx_start_page = start_page; - ei_status.stop_page = stop_page; - ei_status.word16 = (wordlength == 2); - - ei_status.rx_start_page = start_page + TX_PAGES; -#ifdef PACKETBUF_MEMSIZE - /* Allow the packet buffer size to be overridden by know-it-alls. */ - ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; -#endif - - ei_status.reset_8390 = &ne_reset_8390; - ei_status.block_input = &ne_block_input; - ei_status.block_output = &ne_block_output; - ei_status.get_8390_hdr = &ne_get_8390_hdr; - ei_status.priv = 0; - dev->open = &ne_open; - dev->stop = &ne_close; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; -#endif - NS8390_init(dev, 0); - return 0; - -err_out_kfree: - ne2k_cbus_destroy(dev); -err_out: - while (rlist > hw->regionlist) { - rlist --; - release_region(ioaddr + rlist->start, rlist->range); - } - return ret; -} - -static int ne_open(struct net_device *dev) -{ - ei_open(dev); - return 0; -} - -static int ne_close(struct net_device *dev) -{ - if (ei_debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); - return 0; -} - -/* Hard reset the card. This used to pause for the same period that a - 8390 reset command required, but that shouldn't be necessary. */ - -static void ne_reset_8390(struct net_device *dev) -{ - unsigned long reset_start_time = jiffies; - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - - if (ei_debug > 1) - printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); - - /* derived from CNET98EL-patch for bad clones... */ - outb_p(E8390_NODMA | E8390_STOP, NE_BASE + E8390_CMD); /* 0x20 | 0x1 */ - - /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ - outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); - - ei_status.txing = 0; - ei_status.dmaing = 0; - - /* This check _should_not_ be necessary, omit eventually. */ - while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); - break; - } - outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ -} - -/* Grab the 8390 specific header. Similar to the block_input routine, but - we don't need to be concerned with ring wrap as the header will be at - the start of a page, so we optimize accordingly. */ - -static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - int nic_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - - if (ei_status.dmaing) - { - printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); - return; - } - - ei_status.dmaing |= 0x01; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); - outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); - outb_p(0, nic_base + EN0_RCNTHI); - outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ - outb_p(ring_page, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - - if (ei_status.word16) - insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); - else - insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); - - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; - - le16_to_cpus(&hdr->count); -} - -/* Block input and output, similar to the Crynwr packet driver. If you - are porting to a new ethercard, look at the packet driver source for hints. - The NEx000 doesn't share the on-board packet memory -- you have to put - the packet out through the "remote DMA" dataport using outb. */ - -static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) -{ -#ifdef NE_SANITY_CHECK - int xfer_count = count; -#endif - int nic_base = dev->base_addr; - char *buf = skb->data; - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) - { - printk(KERN_EMERG "%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); - return; - } - ei_status.dmaing |= 0x01; - - /* round up count to a word (derived from ICM-patch) */ - count = (count + 1) & ~1; - - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); - outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) - { - insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) - { - buf[count-1] = inb(NE_BASE + NE_DATAPORT); -#ifdef NE_SANITY_CHECK - xfer_count++; -#endif - } - } else { - insb(NE_BASE + NE_DATAPORT, buf, count); - } - -#ifdef NE_SANITY_CHECK - /* This was for the ALPHA version only, but enough people have - been encountering problems so it is still here. If you see - this message you either 1) have a slightly incompatible clone - or 2) have noise/speed problems with your bus. */ - - if (ei_debug > 1) - { - /* DMA termination address check... */ - int addr, tries = 20; - do { - /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here - -- it's broken for Rx on some cards! */ - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - addr = (high << 8) + low; - if (((ring_offset + xfer_count) & 0xff) == low) - break; - } while (--tries > 0); - if (tries <= 0) - printk(KERN_WARNING "%s: RX transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, ring_offset + xfer_count, addr); - } -#endif - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; -} - -static void ne_block_output(struct net_device *dev, int count, - const unsigned char *buf, const int start_page) -{ - int nic_base = NE_BASE; - unsigned long dma_start; -#ifdef NE_SANITY_CHECK - int retries = 0; -#endif - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - - /* Round the count up for word writes. Do we need to do this? - What effect will an odd byte count have on the 8390? - I should check someday. */ - - if (ei_status.word16 && (count & 0x01)) - count++; - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) - { - printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); - return; - } - ei_status.dmaing |= 0x01; - /* We should already be in page 0, but to be safe... */ - outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); - -#ifdef NE_SANITY_CHECK -retry: -#endif - -#ifdef NE8390_RW_BUGFIX - /* Handle the read-before-write bug the same way as the - Crynwr packet driver -- the NatSemi method doesn't work. - Actually this doesn't always work either, but if you have - problems with your NEx000 this is better than nothing! */ - - outb_p(0x42, nic_base + EN0_RCNTLO); - outb_p(0x00, nic_base + EN0_RCNTHI); - outb_p(0x42, nic_base + EN0_RSARLO); - outb_p(0x00, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - /* Make certain that the dummy read has occurred. */ - udelay(6); -#endif - - outb_p(ENISR_RDC, nic_base + EN0_ISR); - - /* Now the normal output. */ - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(0x00, nic_base + EN0_RSARLO); - outb_p(start_page, nic_base + EN0_RSARHI); - - outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) { - outsw(NE_BASE + NE_DATAPORT, buf, count>>1); - } else { - outsb(NE_BASE + NE_DATAPORT, buf, count); - } - - dma_start = jiffies; - -#ifdef NE_SANITY_CHECK - /* This was for the ALPHA version only, but enough people have - been encountering problems so it is still here. */ - - if (ei_debug > 1) - { - /* DMA termination address check... */ - int addr, tries = 20; - do { - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - addr = (high << 8) + low; - if ((start_page << 8) + count == addr) - break; - } while (--tries > 0); - - if (tries <= 0) - { - printk(KERN_WARNING "%s: Tx packet transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, (start_page << 8) + count, addr); - if (retries++ == 0) - goto retry; - } - } -#endif - - while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ - printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); - ne_reset_8390(dev); - NS8390_init(dev,1); - break; - } - - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; - return; -} - - -#ifdef MODULE -#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ -static struct net_device *dev_ne[MAX_NE_CARDS]; -static int io[MAX_NE_CARDS]; -static int irq[MAX_NE_CARDS]; -static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */ -static int hwtype[MAX_NE_CARDS] = { 0, }; /* board type */ - -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(hwtype, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM_DESC(io, "I/O base address(es),required"); -MODULE_PARM_DESC(irq, "IRQ number(s)"); -MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures"); -MODULE_PARM_DESC(hwtype, "Board type of PC-9800 C-Bus NIC"); -MODULE_DESCRIPTION("NE1000/NE2000 PC-9800 C-bus Ethernet driver"); -MODULE_LICENSE("GPL"); - -/* This is set up so that no ISA autoprobe takes place. We can't guarantee -that the ne2k probe is the last 8390 based probe to take place (as it -is at boot) and so the probe will get confused by any other 8390 cards. -ISA device autoprobes on a running machine are not recommended anyway. */ - -int init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = alloc_ei_netdev(); - if (!dev) - break; - dev->irq = irq[this_dev]; - dev->mem_end = bad[this_dev]; - dev->base_addr = io[this_dev]; - dev->mem_start = hwtype[this_dev]; - if (do_ne_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ne[found++] = dev; - continue; - } - cleanup_card(dev); - } - free_netdev(dev); - if (found) - break; - if (io[this_dev] != 0) - printk(KERN_WARNING "ne2k_cbus: No NE*000 card found at i/o = %#x\n", io[this_dev]); - else - printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); - return -ENXIO; - } - if (found) - return 0; - return -ENODEV; -} - -void cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = dev_ne[this_dev]; - if (dev) { - unregister_netdev(dev); - cleanup_card(dev); - free_netdev(dev); - } - } -} -#endif /* MODULE */ - diff -Nru a/drivers/net/ne2k_cbus.h b/drivers/net/ne2k_cbus.h --- a/drivers/net/ne2k_cbus.h 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,481 +0,0 @@ -/* ne2k_cbus.h: - vender-specific information definition for NEC PC-9800 - C-bus Ethernet Cards - Used in ne.c - - (C)1998,1999 KITAGWA Takurou & Linux/98 project -*/ - -#include - -#undef NE_RESET -#define NE_RESET EI_SHIFT(0x11) /* Issue a read to reset, a write to clear. */ - -#ifdef CONFIG_NE2K_CBUS_CNET98EL -#ifndef CONFIG_NE2K_CBUS_CNET98EL_IO_BASE -#warning CONFIG_NE2K_CBUS_CNET98EL_IO_BASE is not defined(config error?) -#warning use 0xaaed as default -#define CONFIG_NE2K_CBUS_CNET98EL_IO_BASE 0xaaed /* or 0x55ed */ -#endif -#define CNET98EL_START_PG 0x00 -#define CNET98EL_STOP_PG 0x40 -#endif - -/* Hardware type definition (derived from *BSD) */ -#define NE2K_CBUS_HARDWARE_TYPE_MASK 0xff - -/* 0: reserved for auto-detect */ -/* 1: (not tested) - Allied Telesis CentreCom LA-98-T */ -#define NE2K_CBUS_HARDWARE_TYPE_ATLA98 1 -/* 2: (not tested) - ELECOM Laneed - LD-BDN[123]A - PLANET SMART COM 98 EN-2298-C - MACNICA ME98 */ -#define NE2K_CBUS_HARDWARE_TYPE_BDN 2 -/* 3: - Melco EGY-98 - Contec C-NET(98)E*A/L*A,C-NET(98)P */ -#define NE2K_CBUS_HARDWARE_TYPE_EGY98 3 -/* 4: - Melco LGY-98,IND-SP,IND-SS - MACNICA NE2098 */ -#define NE2K_CBUS_HARDWARE_TYPE_LGY98 4 -/* 5: - ICM DT-ET-25,DT-ET-T5,IF-2766ET,IF-2771ET - PLANET SMART COM 98 EN-2298-T,EN-2298P-T - D-Link DE-298PT,DE-298PCAT - ELECOM Laneed LD-98P */ -#define NE2K_CBUS_HARDWARE_TYPE_ICM 5 -/* 6: (reserved for SIC-98, which is not supported in this driver.) */ -/* 7: (unused in *BSD?) - - -*/ -#define NE2K_CBUS_HARDWARE_TYPE_NE2K 7 -/* 8: - NEC PC-9801-108 */ -#define NE2K_CBUS_HARDWARE_TYPE_NEC108 8 -/* 9: - I-O DATA LA-98,LA/T-98 */ -#define NE2K_CBUS_HARDWARE_TYPE_IOLA98 9 -/* 10: (reserved for C-NET(98), which is not supported in this driver.) */ -/* 11: - Contec C-NET(98)E,L */ -#define NE2K_CBUS_HARDWARE_TYPE_CNET98EL 11 - -#define NE2K_CBUS_HARDWARE_TYPE_MAX 11 - -/* HARDWARE TYPE ID 12-31: reserved */ - -struct ne2k_cbus_offsetinfo { - unsigned short skip; - unsigned short offset8; /* +0x8 - +0xf */ - unsigned short offset10; /* +0x10 */ - unsigned short offset1f; /* +0x1f */ -}; - -struct ne2k_cbus_region { - unsigned short start; - short range; -}; - -struct ne2k_cbus_hwinfo { - const unsigned short hwtype; - const unsigned char *hwident; -#ifndef MODULE - const unsigned short *portlist; -#endif - const struct ne2k_cbus_offsetinfo *offsetinfo; - const struct ne2k_cbus_region *regionlist; -}; - -#ifdef CONFIG_NE2K_CBUS_ATLA98 -#ifndef MODULE -static unsigned short atla98_portlist[] __initdata = { - 0xd0, - 0 -}; -#endif -#define atla98_offsetinfo ne2k_offsetinfo -#define atla98_regionlist ne2k_regionlist -#endif /* CONFIG_NE2K_CBUS_ATLA98 */ - -#ifdef CONFIG_NE2K_CBUS_BDN -#ifndef MODULE -static unsigned short bdn_portlist[] __initdata = { - 0xd0, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo bdn_offsetinfo __initdata = { -#if 0 - /* comes from FreeBSD(98) ed98.h */ - 0x1000, 0x8000, 0x100, 0xc200 /* ??? */ -#else - /* comes from NetBSD/pc98 if_ne_isa.c */ - 0x1000, 0x8000, 0x100, 0x7f00 /* ??? */ -#endif -}; -static struct ne2k_cbus_region bdn_regionlist[] __initdata = { - {0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000,1}, - {0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1}, - {0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1}, - {0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1}, - {0x100, 1}, {0x7f00, 1}, - {0x0, 0} -}; -#endif /* CONFIG_NE2K_CBUS_BDN */ - -#ifdef CONFIG_NE2K_CBUS_EGY98 -#ifndef MODULE -static unsigned short egy98_portlist[] __initdata = { - 0xd0, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo egy98_offsetinfo __initdata = { - 0x02, 0x100, 0x200, 0x300 -}; -static struct ne2k_cbus_region egy98_regionlist[] __initdata = { - {0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1}, - {0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1}, - {0x100, 1}, {0x102, 1}, {0x104, 1}, {0x106, 1}, - {0x108, 1}, {0x10a, 1}, {0x10c, 1}, {0x10e, 1}, - {0x200, 1}, {0x300, 1}, - {0x0, 0} -}; -#endif /* CONFIG_NE2K_CBUS_EGY98 */ - -#ifdef CONFIG_NE2K_CBUS_LGY98 -#ifndef MODULE -static unsigned short lgy98_portlist[] __initdata = { - 0xd0, 0x10d0, 0x20d0, 0x30d0, 0x40d0, 0x50d0, 0x60d0, 0x70d0, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo lgy98_offsetinfo __initdata = { - 0x01, 0x08, 0x200, 0x300 -}; -static struct ne2k_cbus_region lgy98_regionlist[] __initdata = { - {0x0, 16}, {0x200, 1}, {0x300, 1}, - {0x0, 0} -}; -#endif /* CONFIG_NE2K_CBUS_LGY98 */ - -#ifdef CONFIG_NE2K_CBUS_ICM -#ifndef MODULE -static unsigned short icm_portlist[] __initdata = { - /* ICM */ - 0x56d0, - /* LD-98PT */ - 0x46d0, 0x66d0, 0x76d0, 0x86d0, 0x96d0, 0xa6d0, 0xb6d0, 0xc6d0, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo icm_offsetinfo __initdata = { - 0x01, 0x08, 0x100, 0x10f -}; -static struct ne2k_cbus_region icm_regionlist[] __initdata = { - {0x0, 16}, {0x100, 16}, - {0x0, 0} -}; -#endif /* CONFIG_NE2K_CBUS_ICM */ - -#if defined(CONFIG_NE2K_CBUS_NE2K) && !defined(MODULE) -static unsigned short ne2k_portlist[] __initdata = { - 0xd0, 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, - 0 -}; -#endif -#if defined(CONFIG_NE2K_CBUS_NE2K) || defined(CONFIG_NE2K_CBUS_ATLA98) -static struct ne2k_cbus_offsetinfo ne2k_offsetinfo __initdata = { - 0x01, 0x08, 0x10, 0x1f -}; -static struct ne2k_cbus_region ne2k_regionlist[] __initdata = { - {0x0, 32}, - {0x0, 0} -}; -#endif - -#ifdef CONFIG_NE2K_CBUS_NEC108 -#ifndef MODULE -static unsigned short nec108_portlist[] __initdata = { - 0x770, 0x2770, 0x4770, 0x6770, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo nec108_offsetinfo __initdata = { - 0x02, 0x1000, 0x888, 0x88a -}; -static struct ne2k_cbus_region nec108_regionlist[] __initdata = { - {0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1}, - {0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1}, - {0x1000, 1}, {0x1002, 1}, {0x1004, 1}, {0x1006, 1}, - {0x1008, 1}, {0x100a, 1}, {0x100c, 1}, {0x100e, 1}, - {0x888, 1}, {0x88a, 1}, {0x88c, 1}, {0x88e, 1}, - {0x0, 0} -}; -#endif - -#ifdef CONFIG_NE2K_CBUS_IOLA98 -#ifndef MODULE -static unsigned short iola98_portlist[] __initdata = { - 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo iola98_offsetinfo __initdata = { - 0x1000, 0x8000, 0x100, 0xf100 -}; -static struct ne2k_cbus_region iola98_regionlist[] __initdata = { - {0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000, 1}, - {0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1}, - {0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1}, - {0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1}, - {0x100, 1}, {0xf100, 1}, - {0x0,0} -}; -#endif /* CONFIG_NE2K_CBUS_IOLA98 */ - -#ifdef CONFIG_NE2K_CBUS_CNET98EL -#ifndef MODULE -static unsigned short cnet98el_portlist[] __initdata = { - 0x3d0, 0x13d0, 0x23d0, 0x33d0, 0x43d0, 0x53d0, 0x60d0, 0x70d0, - 0 -}; -#endif -static struct ne2k_cbus_offsetinfo cnet98el_offsetinfo __initdata = { - 0x01, 0x08, 0x40e, 0x400 -}; -static struct ne2k_cbus_region cnet98el_regionlist[] __initdata = { - {0x0, 16}, {0x400, 16}, - {0x0, 0} -}; -#endif - - -/* port information table (for ne.c initialize/probe process) */ - -static struct ne2k_cbus_hwinfo ne2k_cbus_hwinfo_list[] __initdata = { -#ifdef CONFIG_NE2K_CBUS_ATLA98 -/* NOT TESTED */ - { - NE2K_CBUS_HARDWARE_TYPE_ATLA98, - "LA-98-T", -#ifndef MODULE - atla98_portlist, -#endif - &atla98_offsetinfo, atla98_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_BDN -/* NOT TESTED */ - { - NE2K_CBUS_HARDWARE_TYPE_BDN, - "LD-BDN[123]A", -#ifndef MODULE - bdn_portlist, -#endif - &bdn_offsetinfo, bdn_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_ICM - { - NE2K_CBUS_HARDWARE_TYPE_ICM, - "IF-27xxET", -#ifndef MODULE - icm_portlist, -#endif - &icm_offsetinfo, icm_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_NE2K - { - NE2K_CBUS_HARDWARE_TYPE_NE2K, - "NE2000 compat.", -#ifndef MODULE - ne2k_portlist, -#endif - &ne2k_offsetinfo, ne2k_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_NEC108 - { - NE2K_CBUS_HARDWARE_TYPE_NEC108, - "PC-9801-108", -#ifndef MODULE - nec108_portlist, -#endif - &nec108_offsetinfo, nec108_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_IOLA98 - { - NE2K_CBUS_HARDWARE_TYPE_IOLA98, - "LA-98", -#ifndef MODULE - iola98_portlist, -#endif - &iola98_offsetinfo, iola98_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_CNET98EL - { - NE2K_CBUS_HARDWARE_TYPE_CNET98EL, - "C-NET(98)E/L", -#ifndef MODULE - cnet98el_portlist, -#endif - &cnet98el_offsetinfo, cnet98el_regionlist - }, -#endif -/* NOTE: LGY98 must be probed before EGY98, or system stalled!? */ -#ifdef CONFIG_NE2K_CBUS_LGY98 - { - NE2K_CBUS_HARDWARE_TYPE_LGY98, - "LGY-98", -#ifndef MODULE - lgy98_portlist, -#endif - &lgy98_offsetinfo, lgy98_regionlist - }, -#endif -#ifdef CONFIG_NE2K_CBUS_EGY98 - { - NE2K_CBUS_HARDWARE_TYPE_EGY98, - "EGY-98", -#ifndef MODULE - egy98_portlist, -#endif - &egy98_offsetinfo, egy98_regionlist - }, -#endif - { - 0, - "unsupported hardware", -#ifndef MODULE - NULL, -#endif - NULL, NULL - } -}; - -static int __init ne2k_cbus_init(struct net_device *dev) -{ - struct ei_device *ei_local; - if (dev->priv == NULL) { - ei_local = kmalloc(sizeof(struct ei_device), GFP_KERNEL); - if (ei_local == NULL) - return -ENOMEM; - memset(ei_local, 0, sizeof(struct ei_device)); - ei_local->reg_offset = kmalloc(sizeof(typeof(*ei_local->reg_offset))*18, GFP_KERNEL); - if (ei_local->reg_offset == NULL) { - kfree(ei_local); - return -ENOMEM; - } - spin_lock_init(&ei_local->page_lock); - dev->priv = ei_local; - } - return 0; -} - -static void ne2k_cbus_destroy(struct net_device *dev) -{ - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - if (ei_local != NULL) { - if (ei_local->reg_offset) - kfree(ei_local->reg_offset); - kfree(dev->priv); - dev->priv = NULL; - } -} - -static const struct ne2k_cbus_hwinfo * __init ne2k_cbus_get_hwinfo(int hwtype) -{ - const struct ne2k_cbus_hwinfo *hw; - - for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { - if (hw->hwtype == hwtype) break; - } - return hw; -} - -static void __init ne2k_cbus_set_hwtype(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr) -{ - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - int i; - int hwtype_old = dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK; - - if (!ei_local) - panic("Gieee! ei_local == NULL!! (from %p)", - __builtin_return_address(0)); - - dev->mem_start &= ~NE2K_CBUS_HARDWARE_TYPE_MASK; - dev->mem_start |= hw->hwtype & NE2K_CBUS_HARDWARE_TYPE_MASK; - - if (ei_debug > 2) { - printk(KERN_DEBUG "hwtype changed: %d -> %d\n",hwtype_old,(int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); - } - - if (hw->offsetinfo) { - for (i = 0; i < 8; i++) { - ei_local->reg_offset[i] = hw->offsetinfo->skip * i; - } - for (i = 8; i < 16; i++) { - ei_local->reg_offset[i] = - hw->offsetinfo->skip*(i-8) + hw->offsetinfo->offset8; - } -#ifdef CONFIG_NE2K_CBUS_NEC108 - if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_NEC108) { - int adj = (ioaddr & 0xf000) /2; - ei_local->reg_offset[16] = - (hw->offsetinfo->offset10 | adj) - ioaddr; - ei_local->reg_offset[17] = - (hw->offsetinfo->offset1f | adj) - ioaddr; - } else { -#endif /* CONFIG_NE2K_CBUS_NEC108 */ - ei_local->reg_offset[16] = hw->offsetinfo->offset10; - ei_local->reg_offset[17] = hw->offsetinfo->offset1f; -#ifdef CONFIG_NE2K_CBUS_NEC108 - } -#endif - } else { - /* make dummmy offset list */ - for (i = 0; i < 16; i++) { - ei_local->reg_offset[i] = i; - } - ei_local->reg_offset[16] = 0x10; - ei_local->reg_offset[17] = 0x1f; - } -} - -#if defined(CONFIG_NE2K_CBUS_ICM) || defined(CONFIG_NE2K_CBUS_CNET98EL) -static void __init ne2k_cbus_readmem(struct net_device *dev, int ioaddr, unsigned short memaddr, char *buf, unsigned short len) -{ - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD); - outb_p(len & 0xff, ioaddr+EN0_RCNTLO); - outb_p(len >> 8, ioaddr+EN0_RCNTHI); - outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO); - outb_p(memaddr >> 8, ioaddr+EN0_RSARHI); - outb_p(E8390_RREAD | E8390_START, ioaddr+E8390_CMD); - insw(ioaddr+NE_DATAPORT, buf, len >> 1); -} -static void __init ne2k_cbus_writemem(struct net_device *dev, int ioaddr, unsigned short memaddr, const char *buf, unsigned short len) -{ - struct ei_device *ei_local = (struct ei_device *)(dev->priv); - outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD); - outb_p(ENISR_RDC, ioaddr+EN0_ISR); - outb_p(len & 0xff, ioaddr+EN0_RCNTLO); - outb_p(len >> 8, ioaddr+EN0_RCNTHI); - outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO); - outb_p(memaddr >> 8, ioaddr+EN0_RSARHI); - outb_p(E8390_RWRITE | E8390_START, ioaddr+E8390_CMD); - outsw(ioaddr+NE_DATAPORT, buf, len >> 1); -} -#endif - -static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq); -/* End of ne2k_cbus.h */ diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c --- a/drivers/net/ne3210.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/ne3210.c 2004-06-20 13:00:24 -07:00 @@ -45,6 +45,8 @@ #include "8390.h" +#define DRV_NAME "ne3210" + static int ne3210_open(struct net_device *dev); static int ne3210_close(struct net_device *dev); @@ -111,13 +113,13 @@ device->driver_data = dev; ioaddr = edev->base_addr; - if (!request_region(ioaddr, NE3210_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) { retval = -EBUSY; goto out; } if (!request_region(ioaddr + NE3210_CFG1, - NE3210_CFG_EXTENT, dev->name)) { + NE3210_CFG_EXTENT, DRV_NAME)) { retval = -EBUSY; goto out1; } @@ -140,7 +142,7 @@ dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07]; printk(".\nne3210.c: using IRQ %d, ", dev->irq); - retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (retval) { printk (" unable to get IRQ %d.\n", dev->irq); goto out2; @@ -163,7 +165,7 @@ } } - if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, dev->name)) { + if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, DRV_NAME)) { printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n", phys_mem); goto out3; diff -Nru a/drivers/net/ni52.c b/drivers/net/ni52.c --- a/drivers/net/ni52.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/ni52.c 2004-06-20 13:00:25 -07:00 @@ -124,6 +124,8 @@ #include "ni52.h" +#define DRV_NAME "ni52" + #define DEBUG /* debug on */ #define SYSBUSVAL 1 /* 8 Bit */ @@ -424,7 +426,7 @@ dev->mem_start = memstart; dev->mem_end = memend; - if (!request_region(ioaddr, NI52_TOTAL_SIZE, dev->name)) + if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME)) return -EBUSY; if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c --- a/drivers/net/ns83820.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/ns83820.c 2004-06-20 13:00:26 -07:00 @@ -113,6 +113,8 @@ #include #include +#define DRV_NAME "ns83820" + /* Global parameters. See MODULE_PARM near the bottom. */ static int ihr = 2; static int reset_phy = 0; @@ -1851,7 +1853,7 @@ 0); err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, - ndev->name, ndev); + DRV_NAME, ndev); if (err) { printk(KERN_INFO "ns83820: unable to register irq %d\n", pci_dev->irq); diff -Nru a/drivers/net/oaknet.c b/drivers/net/oaknet.c --- a/drivers/net/oaknet.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/oaknet.c 2004-06-20 13:00:25 -07:00 @@ -164,7 +164,7 @@ ret = -EAGAIN; if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) { printk("%s: unable to request interrupt %d.\n", - dev->name, dev->irq); + name, dev->irq); goto out_region; } diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c --- a/drivers/net/pcnet32.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/pcnet32.c 2004-06-20 13:00:23 -07:00 @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.30c" -#define DRV_RELDATE "05.25.2004" +#define DRV_VERSION "1.30f" +#define DRV_RELDATE "06.16.2004" #define PFX DRV_NAME ": " static const char *version = @@ -245,6 +245,11 @@ * v1.30b 24 May 2004 Don Fry fix bogus tx carrier errors with 79c973, * assisted by Bruce Penrod . * v1.30c 25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart. + * v1.30d 01 Jun 2004 Don Fry discard oversize rx packets. + * v1.30e 11 Jun 2004 Don Fry recover after fifo error and rx hang. + * v1.30f 16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI, + * expanding on suggestions from Ralf Baechle , + * and Brian Murphy . */ @@ -360,7 +365,7 @@ static void pcnet32_probe_vlbus(void); static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); -static int pcnet32_probe1(unsigned long, unsigned int, int, struct pci_dev *); +static int pcnet32_probe1(unsigned long, int, struct pci_dev *); static int pcnet32_open(struct net_device *); static int pcnet32_init_ring(struct net_device *); static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); @@ -958,7 +963,7 @@ if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) { /* check if there is really a pcnet chip on that ioaddr */ if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) { - pcnet32_probe1(ioaddr, 0, 0, NULL); + pcnet32_probe1(ioaddr, 0, NULL); } else { release_region(ioaddr, PCNET32_TOTAL_SIZE); } @@ -999,7 +1004,7 @@ return -EBUSY; } - return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev); + return pcnet32_probe1(ioaddr, 1, pdev); } @@ -1008,8 +1013,7 @@ * pdev will be NULL when called from pcnet32_probe_vlbus. */ static int __devinit -pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, - struct pci_dev *pdev) +pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) { struct pcnet32_private *lp; dma_addr_t lp_dma_addr; @@ -1270,11 +1274,8 @@ a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); - if (irq_line) { - dev->irq = irq_line; - } - - if (dev->irq >= 2) { + if (pdev) { /* use the IRQ provided by PCI */ + dev->irq = pdev->irq; if (pcnet32_debug & NETIF_MSG_PROBE) printk(" assigned IRQ %d.\n", dev->irq); } else { @@ -1362,8 +1363,7 @@ int rc; unsigned long flags; - if (dev->irq == 0 || - request_irq(dev->irq, &pcnet32_interrupt, + if (request_irq(dev->irq, &pcnet32_interrupt, lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) { return -EAGAIN; } @@ -1531,13 +1531,15 @@ int i; for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ if (lp->tx_skbuff[i]) { pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(lp->tx_skbuff[i]); - lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; } + lp->tx_skbuff[i] = NULL; + lp->tx_dma_addr[i] = 0; } } @@ -1566,21 +1568,23 @@ skb_reserve (rx_skbuff, 2); } + rmb(); if (lp->rx_dma_addr[i] == 0) lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); + wmb(); /* Make sure owner changes after all others are visible */ lp->rx_ring[i].status = le16_to_cpu(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear * the upper ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].status = 0; /* CPU owns buffer */ + wmb(); /* Make sure adapter sees owner change */ lp->tx_ring[i].base = 0; - lp->tx_ring[i].status = 0; lp->tx_dma_addr[i] = 0; } - wmb(); /* Make sure all changes are visible */ lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); for (i = 0; i < 6; i++) @@ -1589,9 +1593,14 @@ offsetof(struct pcnet32_private, rx_ring)); lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)); + wmb(); /* Make sure all changes are visible */ return 0; } +/* the pcnet32 has been issued a stop or reset. Wait for the stop bit + * then flush the pending transmit operations, re-initialize the ring, + * and tell the chip to initialize. + */ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) { @@ -1599,6 +1608,15 @@ unsigned long ioaddr = dev->base_addr; int i; + /* wait for stop */ + for (i=0; i<100; i++) + if (lp->a.read_csr(ioaddr, 0) & 0x0004) + break; + + if (i >= 100 && netif_msg_drv(lp)) + printk(KERN_ERR "%s: pcnet32_restart timed out waiting for stop.\n", + dev->name); + pcnet32_purge_tx_ring(dev); if (pcnet32_init_ring(dev)) return; @@ -1857,15 +1875,16 @@ } if (must_restart) { - /* stop the chip to clear the error condition, then restart */ - lp->a.write_csr (ioaddr, 0, 0x0004); + /* reset the chip to clear the error condition, then restart */ + lp->a.reset(ioaddr); + lp->a.write_csr(ioaddr, 4, 0x0915); pcnet32_restart(dev, 0x0002); netif_wake_queue(dev); } } - /* Clear any other interrupt, and set interrupt enable. */ - lp->a.write_csr (ioaddr, 0, 0x7940); + /* Set interrupt enable. */ + lp->a.write_csr (ioaddr, 0, 0x0040); lp->a.write_rap (ioaddr,rap); if (netif_msg_intr(lp)) @@ -1907,7 +1926,13 @@ short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; struct sk_buff *skb; - if (pkt_len < 60) { + /* Discard oversize frames. */ + if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { + if (netif_msg_drv(lp)) + printk(KERN_ERR "%s: Impossible packet size %d!\n", + dev->name, pkt_len); + lp->stats.rx_errors++; + } else if (pkt_len < 60) { if (netif_msg_rx_err(lp)) printk(KERN_ERR "%s: Runt packet!\n", dev->name); lp->stats.rx_errors++; diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/r8169.c 2004-06-20 13:00:24 -07:00 @@ -716,7 +716,7 @@ goto err_out_disable; } - rc = pci_request_regions(pdev, dev->name); + rc = pci_request_regions(pdev, MODULENAME); if (rc) { printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); goto err_out_disable; diff -Nru a/drivers/net/s2io.c b/drivers/net/s2io.c --- a/drivers/net/s2io.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/s2io.c 2004-06-20 13:00:25 -07:00 @@ -1425,13 +1425,13 @@ goto end; } - skb = dev_alloc_skb(size + HEADER_ALIGN_LAYER_3); + skb = dev_alloc_skb(size + NET_IP_ALIGN); if (!skb) { DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); return -ENOMEM; } - skb_reserve(skb, HEADER_ALIGN_LAYER_3); + skb_reserve(skb, NET_IP_ALIGN); memset(rxdp, 0, sizeof(RxD_t)); rxdp->Buffer0_ptr = pci_map_single (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE); diff -Nru a/drivers/net/s2io.h b/drivers/net/s2io.h --- a/drivers/net/s2io.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/s2io.h 2004-06-20 13:00:24 -07:00 @@ -411,7 +411,6 @@ #define HEADER_802_2_SIZE 3 #define HEADER_SNAP_SIZE 5 #define HEADER_VLAN_SIZE 4 -#define HEADER_ALIGN_LAYER_3 2 #define MIN_MTU 46 #define MAX_PYLD 1500 diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c --- a/drivers/net/sb1250-mac.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/sb1250-mac.c 2004-06-20 13:00:25 -07:00 @@ -2900,15 +2900,15 @@ sbmac_cleanup_module(void) { struct net_device *dev; - sbmac_port_t port; int idx; for (idx = 0; idx < MAX_UNITS; idx++) { + struct sbmac_softc *sc; dev = dev_sbmac[idx]; if (!dev) continue; - struct sbmac_softc *sc = netdev_priv(dev); + sc = netdev_priv(dev); unregister_netdev(dev); sbmac_uninitctx(sc); free_netdev(dev); diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c --- a/drivers/net/sgiseeq.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/sgiseeq.c 2004-06-20 13:00:25 -07:00 @@ -64,13 +64,13 @@ #define DEBUG struct sgiseeq_rx_desc { - struct hpc_dma_desc rdma; - signed int buf_vaddr; + volatile struct hpc_dma_desc rdma; + volatile signed int buf_vaddr; }; struct sgiseeq_tx_desc { - struct hpc_dma_desc tdma; - signed int buf_vaddr; + volatile struct hpc_dma_desc tdma; + volatile signed int buf_vaddr; }; /* @@ -79,17 +79,17 @@ * some care. */ struct sgiseeq_init_block { /* Note the name ;-) */ - /* Ptrs to the descriptors in KSEG1 uncached space. */ - struct sgiseeq_rx_desc *rx_desc; - struct sgiseeq_tx_desc *tx_desc; - unsigned int _padding[30]; /* Pad out to largest cache line size. */ - struct sgiseeq_rx_desc rxvector[SEEQ_RX_BUFFERS]; struct sgiseeq_tx_desc txvector[SEEQ_TX_BUFFERS]; }; struct sgiseeq_private { - volatile struct sgiseeq_init_block srings; + struct sgiseeq_init_block *srings; + + /* Ptrs to the descriptors in uncached space. */ + struct sgiseeq_rx_desc *rx_desc; + struct sgiseeq_tx_desc *tx_desc; + char *name; struct hpc3_ethregs *hregs; struct sgiseeq_regs *sregs; @@ -152,8 +152,7 @@ static int seeq_init_ring(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; - volatile struct sgiseeq_init_block *ib = &sp->srings; + struct sgiseeq_private *sp = netdev_priv(dev); int i; netif_stop_queue(dev); @@ -170,32 +169,32 @@ /* Setup tx ring. */ for(i = 0; i < SEEQ_TX_BUFFERS; i++) { - if (!ib->tx_desc[i].tdma.pbuf) { + if (!sp->tx_desc[i].tdma.pbuf) { unsigned long buffer; buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); if (!buffer) return -ENOMEM; - ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); - ib->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer); + sp->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); + sp->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer); } - ib->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT; + sp->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT; } /* And now the rx ring. */ for (i = 0; i < SEEQ_RX_BUFFERS; i++) { - if (!ib->rx_desc[i].rdma.pbuf) { + if (!sp->rx_desc[i].rdma.pbuf) { unsigned long buffer; buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL); if (!buffer) return -ENOMEM; - ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); - ib->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer); + sp->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); + sp->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer); } - ib->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT; + sp->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT; } - ib->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR; + sp->rx_desc[i - 1].rdma.cntinfo |= HPCDMA_EOR; return 0; } @@ -206,8 +205,8 @@ void sgiseeq_dump_rings(void) { static int once; - struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc; - struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc; + struct sgiseeq_rx_desc *r = gpriv->rx_desc; + struct sgiseeq_tx_desc *t = gpriv->tx_desc; struct hpc3_ethregs *hregs = gpriv->hregs; int i; @@ -268,8 +267,8 @@ hregs->rx_dconfig |= RDMACFG_INIT; - hregs->rx_ndptr = CPHYSADDR(sp->srings.rx_desc); - hregs->tx_ndptr = CPHYSADDR(sp->srings.tx_desc); + hregs->rx_ndptr = CPHYSADDR(sp->rx_desc); + hregs->tx_ndptr = CPHYSADDR(sp->tx_desc); seeq_go(sp, hregs, sregs); return 0; @@ -294,14 +293,14 @@ struct sgiseeq_regs *sregs) { if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) { - hregs->rx_ndptr = CPHYSADDR(sp->srings.rx_desc + sp->rx_new); + hregs->rx_ndptr = CPHYSADDR(sp->rx_desc + sp->rx_new); seeq_go(sp, hregs, sregs); } } -#define for_each_rx(rd, sp) for((rd) = &(sp)->srings.rx_desc[(sp)->rx_new]; \ +#define for_each_rx(rd, sp) for((rd) = &(sp)->rx_desc[(sp)->rx_new]; \ !((rd)->rdma.cntinfo & HPCDMA_OWN); \ - (rd) = &(sp)->srings.rx_desc[(sp)->rx_new]) + (rd) = &(sp)->rx_desc[(sp)->rx_new]) static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp, struct hpc3_ethregs *hregs, @@ -349,8 +348,8 @@ rd->rdma.cntinfo = RCNTINFO_INIT; sp->rx_new = NEXT_RX(sp->rx_new); } - sp->srings.rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR); - sp->srings.rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR; + sp->rx_desc[orig_end].rdma.cntinfo &= ~(HPCDMA_EOR); + sp->rx_desc[PREV_RX(sp->rx_new)].rdma.cntinfo |= HPCDMA_EOR; rx_maybe_restart(sp, hregs, sregs); } @@ -403,7 +402,7 @@ /* Ack 'em... */ for (j = sp->tx_old; j != sp->tx_new; j = NEXT_TX(j)) { - td = &sp->srings.tx_desc[j]; + td = &sp->tx_desc[j]; if (!(td->tdma.cntinfo & (HPCDMA_XIU))) break; @@ -424,7 +423,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct hpc3_ethregs *hregs = sp->hregs; struct sgiseeq_regs *sregs = sp->sregs; @@ -450,21 +449,33 @@ static int sgiseeq_open(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct sgiseeq_regs *sregs = sp->sregs; + unsigned int irq = dev->irq; + int err; - int err = init_seeq(dev, sp, sregs); + if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { + printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); + err = -EAGAIN; + } + + err = init_seeq(dev, sp, sregs); if (err) - return err; + goto out_free_irq; netif_start_queue(dev); return 0; + +out_free_irq: + free_irq(irq, dev); + + return err; } static int sgiseeq_close(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct sgiseeq_regs *sregs = sp->sregs; netif_stop_queue(dev); @@ -477,7 +488,7 @@ static inline int sgiseeq_reset(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct sgiseeq_regs *sregs = sp->sregs; int err; @@ -499,7 +510,7 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); struct hpc3_ethregs *hregs = sp->hregs; unsigned long flags; struct sgiseeq_tx_desc *td; @@ -512,7 +523,7 @@ len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; sp->stats.tx_bytes += len; entry = sp->tx_new; - td = &sp->srings.tx_desc[entry]; + td = &sp->tx_desc[entry]; /* Create entry. There are so many races with adding a new * descriptor to the chain: @@ -535,14 +546,14 @@ if (sp->tx_old != sp->tx_new) { struct sgiseeq_tx_desc *backend; - backend = &sp->srings.tx_desc[PREV_TX(sp->tx_new)]; + backend = &sp->tx_desc[PREV_TX(sp->tx_new)]; backend->tdma.cntinfo &= ~HPCDMA_EOX; } sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */ /* Maybe kick the HPC back into motion. */ if (!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) - kick_tx(&sp->srings.tx_desc[sp->tx_old], hregs); + kick_tx(&sp->tx_desc[sp->tx_old], hregs); dev->trans_start = jiffies; dev_kfree_skb(skb); @@ -565,7 +576,7 @@ static struct net_device_stats *sgiseeq_get_stats(struct net_device *dev) { - struct sgiseeq_private *sp = dev->priv; + struct sgiseeq_private *sp = netdev_priv(dev); return &sp->stats; } @@ -601,31 +612,29 @@ #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) -int sgiseeq_init(struct hpc3_regs* regs, int irq) +static int sgiseeq_init(struct hpc3_regs* regs, int irq) { - struct net_device *dev; + struct sgiseeq_init_block *sr; struct sgiseeq_private *sp; + struct net_device *dev; int err, i; - dev = alloc_etherdev(0); + dev = alloc_etherdev(sizeof (struct sgiseeq_private)); if (!dev) { printk(KERN_ERR "Sgiseeq: Etherdev alloc failed, aborting.\n"); err = -ENOMEM; goto err_out; } + sp = netdev_priv(dev); + /* Make private data page aligned */ - sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL); - if (!sp) { + sr = (struct sgiseeq_init_block *) get_zeroed_page(GFP_KERNEL); + if (!sr) { printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n"); err = -ENOMEM; goto err_out_free_dev; } - - if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { - printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); - err = -EAGAIN; - goto err_out_free_page; - } + sp->srings = sr; #define EADDR_NVOFS 250 for (i = 0; i < 3; i++) { @@ -643,18 +652,18 @@ sp->hregs = &hpc3c0->ethregs; sp->name = sgiseeqstr; - sp->srings.rx_desc = (struct sgiseeq_rx_desc *) - KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0])); - dma_cache_wback_inv((unsigned long)&sp->srings.rxvector, - sizeof(sp->srings.rxvector)); - sp->srings.tx_desc = (struct sgiseeq_tx_desc *) - KSEG1ADDR(ALIGNED(&sp->srings.txvector[0])); - dma_cache_wback_inv((unsigned long)&sp->srings.txvector, - sizeof(sp->srings.txvector)); + sp->rx_desc = (struct sgiseeq_rx_desc *) + KSEG1ADDR(ALIGNED(&sp->srings->rxvector[0])); + dma_cache_wback_inv((unsigned long)&sp->srings->rxvector, + sizeof(sp->srings->rxvector)); + sp->tx_desc = (struct sgiseeq_tx_desc *) + KSEG1ADDR(ALIGNED(&sp->srings->txvector[0])); + dma_cache_wback_inv((unsigned long)&sp->srings->txvector, + sizeof(sp->srings->txvector)); /* A couple calculations now, saves many cycles later. */ - setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS); - setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS); + setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS); + setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS); /* Reset the chip. */ hpc3_eth_reset(sp->hregs); @@ -673,14 +682,12 @@ dev->get_stats = sgiseeq_get_stats; dev->set_multicast_list = sgiseeq_set_multicast; dev->irq = irq; - dev->dma = 0; - dev->priv = sp; if (register_netdev(dev)) { printk(KERN_ERR "Sgiseeq: Cannot register net device, " "aborting.\n"); err = -ENODEV; - goto err_out_free_irq; + goto err_out_free_page; } printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name); @@ -692,8 +699,6 @@ return 0; -err_out_free_irq: - free_irq(irq, dev); err_out_free_page: free_page((unsigned long) sp); err_out_free_dev: @@ -718,12 +723,12 @@ int irq; for (dev = root_sgiseeq_dev; dev; dev = next) { - sp = (struct sgiseeq_private *) dev->priv; + sp = (struct sgiseeq_private *) netdev_priv(dev); next = sp->next_module; irq = dev->irq; unregister_netdev(dev); free_irq(irq, dev); - free_page((unsigned long) dev->priv); + free_page((unsigned long) sp); free_netdev(dev); } } diff -Nru a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h --- a/drivers/net/sk98lin/h/skdrv2nd.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/sk98lin/h/skdrv2nd.h 2004-06-20 13:00:26 -07:00 @@ -58,7 +58,8 @@ /* 3Com (0x10b7) */ \ if (pdev->vendor == 0x10b7) { \ /* Gigabit Ethernet Adapter (0x1700) */ \ - if ((pdev->device == 0x1700)) { \ + if ((pdev->device == 0x1700) || \ + (pdev->device == 0x80eb)) { \ result = SK_TRUE; \ } \ /* SysKonnect (0x1148) */ \ diff -Nru a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c --- a/drivers/net/skfp/cfm.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/skfp/cfm.c 2004-06-20 13:00:24 -07:00 @@ -96,14 +96,13 @@ /* * function declarations */ -static void cfm_fsm() ; +static void cfm_fsm(struct s_smc *smc, int cmd); /* init CFM state machine clear all CFM vars and flags */ -void cfm_init(smc) -struct s_smc *smc ; +void cfm_init(struct s_smc *smc) { smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ; smc->r.rm_join = 0 ; @@ -118,9 +117,7 @@ #define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \ smc->y[PB].pc_mode != PM_TREE) /* Selection criteria for the ports */ -static void selection_criteria (smc,phy) -struct s_smc *smc ; -struct s_phy *phy ; +static void selection_criteria (struct s_smc *smc, struct s_phy *phy) { switch (phy->mib->fddiPORTMy_Type) { @@ -146,8 +143,7 @@ } -void all_selection_criteria (smc) -struct s_smc *smc ; +void all_selection_criteria(struct s_smc *smc) { struct s_phy *phy ; int p ; @@ -158,9 +154,7 @@ } } -static void cem_priv_state (smc, event) -struct s_smc *smc ; -int event ; +static void cem_priv_state(struct s_smc *smc, int event) /* State machine for private PORT states: used to optimize dual homing */ { int np; /* Number of the port */ @@ -216,9 +210,7 @@ process event until SM is stable */ -void cfm(smc,event) -struct s_smc *smc ; -int event ; +void cfm(struct s_smc *smc, int event) { int state ; /* remember last state */ int cond ; @@ -290,9 +282,7 @@ process CFM event */ /*ARGSUSED1*/ -static void cfm_fsm(smc,cmd) -struct s_smc *smc ; -int cmd ; +static void cfm_fsm(struct s_smc *smc, int cmd) { switch(smc->mib.fddiSMTCF_State) { case ACTIONS(SC0_ISOLATED) : @@ -550,8 +540,7 @@ * return : * PA or PB */ -int cfm_get_mac_input(smc) -struct s_smc *smc ; +int cfm_get_mac_input(struct s_smc *smc) { return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ; @@ -562,8 +551,7 @@ * return : * PA or PB */ -int cfm_get_mac_output(smc) -struct s_smc *smc ; +int cfm_get_mac_output(struct s_smc *smc) { return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ; @@ -603,10 +591,7 @@ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO, } ; -int cem_build_path(smc,to,path_index) -struct s_smc *smc ; -char *to ; -int path_index ; +int cem_build_path(struct s_smc *smc, char *to, int path_index) { char *path ; int len ; diff -Nru a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c --- a/drivers/net/skfp/drvfbi.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/drvfbi.c 2004-06-20 13:00:23 -07:00 @@ -100,14 +100,13 @@ #endif /* MULT_OEM */ /* Prototypes of external functions */ -extern void hwt_restart() ; #ifdef AIX extern int AIX_vpdReadByte() ; #endif /* Prototypes of local functions. */ -void smt_stop_watchdog() ; +void smt_stop_watchdog(struct s_smc *smc); #ifdef MCA static int read_card_id() ; @@ -129,8 +128,7 @@ /* * FDDI card reset */ -static void card_start(smc) -struct s_smc *smc ; +static void card_start(struct s_smc *smc) { int i ; #ifdef PCI @@ -250,8 +248,7 @@ GET_PAGE(0) ; /* necessary for BOOT */ } -void card_stop(smc) -struct s_smc *smc ; +void card_stop(struct s_smc *smc) { smt_stop_watchdog(smc) ; smc->hw.mac_ring_is_up = 0 ; /* ring down */ @@ -282,14 +279,11 @@ } /*--------------------------- ISR handling ----------------------------------*/ -#ifndef PCI -void mac1_irq(smc,stu, stl) -struct s_smc *smc ; -u_short stu; -u_short stl; +void mac1_irq(struct s_smc *smc, u_short stu, u_short stl) { int restart_tx = 0 ; again: +#ifndef PCI #ifndef ISA /* * FORMAC+ bug modified the queue pointer if many read/write accesses happens!? @@ -344,14 +338,6 @@ } #else /* PCI */ -void mac1_irq(smc,stu, stl) -struct s_smc *smc ; -u_short stu; -u_short stl; -{ - int restart_tx = 0 ; -again: - /* * parity error: note encoding error is not possible in tag mode */ @@ -396,8 +382,7 @@ * interrupt source= plc1 * this function is called in nwfbisr.asm */ -void plc1_irq(smc) -struct s_smc *smc ; +void plc1_irq(struct s_smc *smc) { u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ; @@ -412,8 +397,7 @@ * interrupt source= plc2 * this function is called in nwfbisr.asm */ -void plc2_irq(smc) -struct s_smc *smc ; +void plc2_irq(struct s_smc *smc) { u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ; @@ -428,8 +412,7 @@ /* * interrupt source= timer */ -void timer_irq(smc) -struct s_smc *smc ; +void timer_irq(struct s_smc *smc) { hwt_restart(smc); smc->hw.t_stop = smc->hw.t_start; @@ -439,8 +422,7 @@ /* * return S-port (PA or PB) */ -int pcm_get_s_port(smc) -struct s_smc *smc ; +int pcm_get_s_port(struct s_smc *smc) { SK_UNUSED(smc) ; return(PS) ; @@ -457,9 +439,7 @@ #define STATION_LABEL_PMD_OFFSET 6 #define STATION_LABEL_PORT_OFFSET 7 -void read_address(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; +void read_address(struct s_smc *smc, u_char *mac_addr) { char ConnectorType ; char PmdType ; @@ -528,9 +508,7 @@ /* * FDDI card soft reset */ -void init_board(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; +void init_board(struct s_smc *smc, u_char *mac_addr) { card_start(smc) ; read_address(smc,mac_addr) ; @@ -559,9 +537,7 @@ /* * insert or deinsert optical bypass (called by ECM) */ -void sm_pm_bypass_req(smc,mode) -struct s_smc *smc ; -int mode; +void sm_pm_bypass_req(struct s_smc *smc, int mode) { #if (defined(ISA) || defined(EISA)) int csra_v ; @@ -614,8 +590,7 @@ /* * check if bypass connected */ -int sm_pm_bypass_present(smc) -struct s_smc *smc ; +int sm_pm_bypass_present(struct s_smc *smc) { #ifndef PCI return( (inpw(CSR_A) & CS_BYSTAT) ? FALSE : TRUE ) ; @@ -624,9 +599,7 @@ #endif } -void plc_clear_irq(smc,p) -struct s_smc *smc ; -int p ; +void plc_clear_irq(struct s_smc *smc, int p) { SK_UNUSED(p) ; @@ -658,9 +631,7 @@ * LED_Y_OFF just switch yellow LED off * LED_Y_ON just switch yello LED on */ -void led_indication(smc,led_event) -struct s_smc *smc ; -int led_event; +void led_indication(struct s_smc *smc, int led_event) { /* use smc->hw.mac_ring_is_up == TRUE * as indication for Ring Operational @@ -754,10 +725,7 @@ } -void pcm_state_change(smc,plc,p_state) -struct s_smc *smc; -int plc; -int p_state; +void pcm_state_change(struct s_smc *smc, int plc, int p_state) { /* * the current implementation of pcm_state_change() in the driver @@ -770,9 +738,7 @@ } -void rmt_indication(smc,i) -struct s_smc *smc ; -int i; +void rmt_indication(struct s_smc *smc, int i) { /* Call a driver special function if defined */ DRV_RMT_INDICATION(smc,i) ; @@ -784,8 +750,7 @@ /* * llc_recover_tx called by init_tx (fplus.c) */ -void llc_recover_tx(smc) -struct s_smc *smc ; +void llc_recover_tx(struct s_smc *smc) { #ifdef LOAD_GEN extern int load_gen_flag ; @@ -805,9 +770,7 @@ /* * init DMA */ -void init_dma(smc,dma) -struct s_smc *smc; -int dma; +void init_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; @@ -828,9 +791,7 @@ /* * disable DMA */ -void dis_dma(smc,dma) -struct s_smc *smc ; -int dma; +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; @@ -854,9 +815,7 @@ static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ; static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ; -void init_dma(smc,dma) -struct s_smc *smc ; -int dma; +void init_dma(struct s_smc *smc, int dma) { /* * extended mode register @@ -885,9 +844,7 @@ } -void dis_dma(smc,dma) -struct s_smc *smc ; -int dma; +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; @@ -896,16 +853,13 @@ #endif /* EISA */ #ifdef MCA -void init_dma(smc,dma) -struct s_smc *smc; -int dma; +void init_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; } -void dis_dma(smc,dma) -struct s_smc *smc; -int dma; + +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; @@ -913,16 +867,13 @@ #endif #ifdef PCI -void init_dma(smc,dma) -struct s_smc *smc; -int dma; +void init_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; } -void dis_dma(smc,dma) -struct s_smc *smc; -int dma; + +void dis_dma(struct s_smc *smc, int dma) { SK_UNUSED(smc) ; SK_UNUSED(dma) ; @@ -930,10 +881,7 @@ #endif #ifdef MULT_OEM -static int is_equal_num(comp1,comp2,num) -char comp1[] ; -char comp2[] ; -int num ; +static int is_equal_num(char comp1[], char comp2[], int num) { int i ; @@ -954,8 +902,7 @@ * 2 data base empty * 3 no active entry */ -int set_oi_id_def(smc) -struct s_smc *smc ; +int set_oi_id_def(struct s_smc *smc) { int sel_id ; int i ; @@ -1029,9 +976,7 @@ * ************************/ #define LONG_CARD_ID(lo, hi) ((((hi) & 0xff) << 8) | ((lo) & 0xff)) -int exist_board(smc,slot) -struct s_smc *smc ; -int slot ; +int exist_board(struct s_smc *smc, int slot) { #ifdef MULT_OEM SK_LOC_DECL(u_char,id[2]) ; @@ -1081,9 +1026,8 @@ * number is specified, the function returns zero. * ************************/ -static int read_card_id(smc,slot) -struct s_smc *smc ; /* Do not use. */ -int slot ; +static int read_card_id(struct s_smc *smc, int slot) +/* struct s_smc *smc ; Do not use. */ { int card_id ; @@ -1126,9 +1070,7 @@ * END_MANUAL_ENTRY() * ************************/ -int get_board_para(smc,slot) -struct s_smc *smc ; -int slot ; +int get_board_para(struct s_smc *smc, int slot) { int val ; int i ; @@ -1175,9 +1117,7 @@ } /* Enable access to specified MCA slot. */ -static void EnableSlotAccess(smc,slot) -struct s_smc *smc ; -int slot ; +static void EnableSlotAccess(struct s_smc *smc, int slot) { SK_UNUSED(slot) ; @@ -1195,8 +1135,7 @@ } /* Disable access to MCA slot formerly enabled via EnableSlotAccess(). */ -static void DisableSlotAccess(smc) -struct s_smc *smc ; +static void DisableSlotAccess(struct s_smc *smc) { #ifndef AIX SK_UNUSED(smc) ; @@ -1245,9 +1184,7 @@ * The smc pointer must be valid now. * ************************/ -int exist_board(smc,slot) -struct s_smc *smc ; -int slot ; +int exist_board(struct s_smc *smc, int slot) { int i ; #ifdef MULT_OEM @@ -1284,9 +1221,7 @@ } -int get_board_para(smc,slot) -struct s_smc *smc ; -int slot ; +int get_board_para(struct s_smc *smc, int slot) { int i ; @@ -1327,9 +1262,7 @@ #endif /* MULT_OEM */ -int exist_board(smc,port) -struct s_smc *smc ; -HW_PTR port ; +int exist_board(struct s_smc *smc, HW_PTR port) { int i ; #ifdef MULT_OEM @@ -1400,9 +1333,7 @@ #endif /* MULT_OEM */ } -int get_board_para(smc,slot) -struct s_smc *smc ; -int slot ; +int get_board_para(struct s_smc *smc, int slot) { SK_UNUSED(smc) ; SK_UNUSED(slot) ; @@ -1412,9 +1343,7 @@ #ifdef PCI #ifdef USE_BIOS_FUN -int exist_board(smc,slot) -struct s_smc *smc ; -int slot ; +int exist_board(struct s_smc *smc, int slot) { u_short dev_id ; u_short ven_id ; @@ -1452,9 +1381,7 @@ #endif /* PCI */ #endif /* USE_BIOS_FUNC */ -void driver_get_bia(smc, bia_addr) -struct s_smc *smc ; -struct fddi_addr *bia_addr ; +void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr) { int i ; @@ -1465,8 +1392,7 @@ } } -void smt_start_watchdog(smc) -struct s_smc *smc ; +void smt_start_watchdog(struct s_smc *smc) { SK_UNUSED(smc) ; /* Make LINT happy. */ @@ -1481,8 +1407,7 @@ #endif /* DEBUG */ } -void smt_stop_watchdog(smc) -struct s_smc *smc ; +void smt_stop_watchdog(struct s_smc *smc) { SK_UNUSED(smc) ; /* Make LINT happy. */ #ifndef DEBUG @@ -1497,9 +1422,7 @@ } #ifdef PCI -static char get_rom_byte(smc,addr) -struct s_smc *smc ; -u_short addr ; +static char get_rom_byte(struct s_smc *smc, u_short addr) { GET_PAGE(addr) ; return (READ_PROM(ADDR(B2_FDP))) ; @@ -1544,11 +1467,7 @@ * * END_MANUAL_ENTRY */ -int mac_drv_vpd_read(smc,buf,size,image) -struct s_smc *smc ; -char *buf ; -int size ; -char image ; +int mac_drv_vpd_read(struct s_smc *smc, char *buf, int size, char image) { u_short ibase ; u_short pci_base ; @@ -1597,16 +1516,14 @@ return(len) ; } -void mac_drv_pci_fix(smc,fix_value) -struct s_smc *smc ; -u_long fix_value ; +void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value) { smc->hw.pci_fix_value = fix_value ; } -void mac_do_pci_fix(smc) -struct s_smc *smc ; +void mac_do_pci_fix(struct s_smc *smc) { SK_UNUSED(smc) ; } #endif /* PCI */ + diff -Nru a/drivers/net/skfp/ecm.c b/drivers/net/skfp/ecm.c --- a/drivers/net/skfp/ecm.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/ecm.c 2004-06-20 13:00:23 -07:00 @@ -94,17 +94,16 @@ * function declarations */ -static void ecm_fsm() ; -static void start_ecm_timer() ; -static void stop_ecm_timer() ; -static void prop_actions() ; +static void ecm_fsm(struct s_smc *smc, int cmd); +static void start_ecm_timer(struct s_smc *smc, u_long value, int event); +static void stop_ecm_timer(struct s_smc *smc); +static void prop_actions(struct s_smc *smc); /* init ECM state machine clear all ECM vars and flags */ -void ecm_init(smc) -struct s_smc *smc ; +void ecm_init(struct s_smc *smc) { smc->e.path_test = PT_PASSED ; smc->e.trace_prop = 0 ; @@ -122,9 +121,7 @@ process event until SM is stable */ -void ecm(smc,event) -struct s_smc *smc ; -int event ; +void ecm(struct s_smc *smc, int event) { int state ; @@ -143,9 +140,7 @@ /* process ECM event */ -static void ecm_fsm(smc,cmd) -struct s_smc *smc ; -int cmd ; +static void ecm_fsm(struct s_smc *smc, int cmd) { int ls_a ; /* current line state PHY A */ int ls_b ; /* current line state PHY B */ @@ -429,8 +424,7 @@ /* * trace propagation actions for SAS & DAS */ -static void prop_actions(smc) -struct s_smc *smc ; +static void prop_actions(struct s_smc *smc) { int port_in = 0 ; int port_out = 0 ; @@ -480,8 +474,7 @@ /* * trace propagation actions for Concentrator */ -static void prop_actions(smc) -struct s_smc *smc ; +static void prop_actions(struct s_smc *smc) { int initiator ; int upstream ; @@ -527,10 +520,7 @@ * SMT timer interface * start ECM timer */ -static void start_ecm_timer(smc,value,event) -struct s_smc *smc ; -u_long value; -int event ; +static void start_ecm_timer(struct s_smc *smc, u_long value, int event) { smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event)); } @@ -539,8 +529,7 @@ * SMT timer interface * stop ECM timer */ -static void stop_ecm_timer(smc) -struct s_smc *smc ; +static void stop_ecm_timer(struct s_smc *smc) { if (smc->e.ecm_timer.tm_active) smt_timer_stop(smc,&smc->e.ecm_timer) ; diff -Nru a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c --- a/drivers/net/skfp/ess.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/ess.c 2004-06-20 13:00:23 -07:00 @@ -80,8 +80,11 @@ ------------------------------------------------------------- */ -static void ess_send_response(), ess_config_fifo(), - ess_send_alc_req(), ess_send_frame() ; +static void ess_send_response(struct s_smc *smc, struct smt_header *sm, + int sba_cmd); +static void ess_config_fifo(struct s_smc *smc); +static void ess_send_alc_req(struct s_smc *smc); +static void ess_send_frame(struct s_smc *smc, SMbuf *mb); /* ------------------------------------------------------------- @@ -89,26 +92,17 @@ ------------------------------------------------------------- */ -extern void *sm_to_para() ; - -extern void smt_send_frame(), smt_free_mbuf(), - set_formac_tsync(), formac_reinit_tx() ; - -extern int smt_check_para() ; - -extern SMbuf *smt_get_mbuf(), *smt_build_frame() ; - -extern u_long smt_get_tid() ; - /* ------------------------------------------------------------- PUBLIC FUNCTIONS: ------------------------------------------------------------- */ - void ess_timer_poll(), ess_para_change() ; - - int ess_raf_received_pack(), process_bw_alloc() ; +void ess_timer_poll(struct s_smc *smc); +void ess_para_change(struct s_smc *smc); +int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, + int fs); +int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead); /* @@ -120,11 +114,8 @@ /* * evaluate the RAF frame */ -int ess_raf_received_pack(smc,mb,sm,fs) -struct s_smc *smc ; -SMbuf *mb ; -struct smt_header *sm ; -int fs ; +int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, + int fs) { void *p ; /* universal pointer */ struct smt_p_0016 *cmd ; /* para: command for the ESS */ @@ -384,10 +375,7 @@ * determines the synchronous bandwidth, set the TSYNC register and the * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG. */ -int process_bw_alloc(smc,payload,overhead) -struct s_smc *smc ; -long payload ; -long overhead ; +int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead) { /* * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG, @@ -483,10 +471,8 @@ return(TRUE) ; } -static void ess_send_response(smc,sm,sba_cmd) -struct s_smc *smc ; -struct smt_header *sm ; -int sba_cmd ; +static void ess_send_response(struct s_smc *smc, struct smt_header *sm, + int sba_cmd) { struct smt_sba_chg *chg ; SMbuf *mb ; @@ -550,9 +536,7 @@ ess_send_frame(smc,mb) ; } - -void ess_timer_poll(smc) -struct s_smc *smc ; +void ess_timer_poll(struct s_smc *smc) { if (!smc->ess.raf_act_timer_poll) return ; @@ -566,8 +550,7 @@ } } -static void ess_send_alc_req(smc) -struct s_smc *smc ; +static void ess_send_alc_req(struct s_smc *smc) { struct smt_sba_alc_req *req ; SMbuf *mb ; @@ -675,9 +658,7 @@ ess_send_frame(smc,mb) ; } -static void ess_send_frame(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void ess_send_frame(struct s_smc *smc, SMbuf *mb) { /* * check if the frame must be send to the own ESS @@ -703,15 +684,13 @@ } } -void ess_para_change(smc) -struct s_smc *smc ; +void ess_para_change(struct s_smc *smc) { (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload, (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ; } -static void ess_config_fifo(smc) -struct s_smc *smc ; +static void ess_config_fifo(struct s_smc *smc) { /* * if nothing to do exit @@ -738,3 +717,4 @@ #endif /* ESS */ #endif /* no SLIM_SMT */ + diff -Nru a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c --- a/drivers/net/skfp/fplustm.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/skfp/fplustm.c 2004-06-20 13:00:24 -07:00 @@ -43,10 +43,10 @@ /* * prototypes for static function */ -static void build_claim_beacon() ; -static int init_mac() ; -static void rtm_init() ; -static void smt_split_up_fifo() ; +static void build_claim_beacon(struct s_smc *smc, u_long t_request); +static int init_mac(struct s_smc *smc, int all); +static void rtm_init(struct s_smc *smc); +static void smt_split_up_fifo(struct s_smc *smc); #if (!defined(NO_SMT_PANIC) || defined(DEBUG)) static char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n"; @@ -107,8 +107,7 @@ FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ; -static u_long mac_get_tneg(smc) -struct s_smc *smc ; +static u_long mac_get_tneg(struct s_smc *smc) { u_long tneg ; @@ -117,8 +116,7 @@ 0xffe00000L)) ; } -void mac_update_counter(smc) -struct s_smc *smc ; +void mac_update_counter(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACFrame_Ct = (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L) @@ -143,9 +141,7 @@ /* * write long value into buffer memory over memory data register (MDR), */ -void write_mdr(smc,val) -struct s_smc *smc ; -u_long val; +void write_mdr(struct s_smc *smc, u_long val) { CHECK_NPP() ; MDRW(val) ; @@ -154,9 +150,7 @@ /* * read long value from buffer memory over memory data register (MDR), */ -u_long read_mdr(smc,addr) -struct s_smc *smc ; -unsigned int addr; +u_long read_mdr(struct s_smc *smc, unsigned int addr) { long p ; CHECK_NPP() ; @@ -173,8 +167,7 @@ /* * clear buffer memory */ -static void init_ram(smc) -struct s_smc *smc ; +static void init_ram(struct s_smc *smc) { u_short i ; @@ -193,8 +186,7 @@ /* * set receive FIFO pointer */ -static void set_recvptr(smc) -struct s_smc *smc ; +static void set_recvptr(struct s_smc *smc) { /* * initialize the pointer for receive queue 1 @@ -224,8 +216,7 @@ /* * set transmit FIFO pointer */ -static void set_txptr(smc) -struct s_smc *smc ; +static void set_txptr(struct s_smc *smc) { outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ; /* reset transmit queues */ @@ -257,8 +248,7 @@ /* * init memory buffer management registers */ -static void init_rbc(smc) -struct s_smc *smc ; +static void init_rbc(struct s_smc *smc) { u_short rbc_ram_addr ; @@ -279,8 +269,7 @@ /* * init rx pointer */ -static void init_rx(smc) -struct s_smc *smc ; +static void init_rx(struct s_smc *smc) { struct s_smt_rx_queue *queue ; @@ -302,9 +291,7 @@ /* * set the TSYNC register of the FORMAC to regulate synchronous transmission */ -void set_formac_tsync(smc,sync_bw) -struct s_smc *smc ; -long sync_bw ; +void set_formac_tsync(struct s_smc *smc, long sync_bw) { outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ; } @@ -312,8 +299,7 @@ /* * init all tx data structures */ -static void init_tx(smc) -struct s_smc *smc ; +static void init_tx(struct s_smc *smc) { struct s_smt_tx_queue *queue ; @@ -339,8 +325,7 @@ llc_recover_tx(smc) ; } -static void mac_counter_init(smc) -struct s_smc *smc ; +static void mac_counter_init(struct s_smc *smc) { int i ; u_long *ec ; @@ -363,8 +348,7 @@ /* * set FORMAC address, and t_request */ -static void set_formac_addr(smc) -struct s_smc *smc ; +static void set_formac_addr(struct s_smc *smc) { long t_requ = smc->mib.m[MAC0].fddiMACT_Req ; @@ -390,9 +374,7 @@ outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ; } -static void set_int(p,l) -char *p; -int l; +static void set_int(char *p, int l) { p[0] = (char)(l >> 24) ; p[1] = (char)(l >> 16) ; @@ -408,12 +390,12 @@ * else * append 'end of chain' pointer */ -static void copy_tx_mac(smc,td,mac,off,len) -struct s_smc *smc ; -u_long td; /* transmit descriptor */ -struct fddi_mac *mac; /* mac frame pointer */ -unsigned off; /* start address within buffer memory */ -int len ; /* lenght of the frame including the FC */ +static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac, + unsigned off, int len) +/* u_long td; transmit descriptor */ +/* struct fddi_mac *mac; mac frame pointer */ +/* unsigned off; start address within buffer memory */ +/* int len ; lenght of the frame including the FC */ { int i ; u_int *p ; @@ -457,8 +439,7 @@ END_MANUAL_ENTRY */ -static void directed_beacon(smc) -struct s_smc *smc ; +static void directed_beacon(struct s_smc *smc) { SK_LOC_DECL(u_int,a[2]) ; @@ -487,9 +468,7 @@ special frame packets end with a pointer to their own descriptor, and the MORE bit is set in the descriptor */ -static void build_claim_beacon(smc,t_request) -struct s_smc *smc ; -u_long t_request; +static void build_claim_beacon(struct s_smc *smc, u_long t_request) { u_int td ; int len ; @@ -550,8 +529,7 @@ outpw(FM_A(FM_RPXSF),0) ; } -void formac_rcv_restart(smc) -struct s_smc *smc ; +void formac_rcv_restart(struct s_smc *smc) { /* enable receive function */ SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ; @@ -559,15 +537,13 @@ outpw(FM_A(FM_CMDREG1),FM_ICLLR) ; /* clear receive lock */ } -void formac_tx_restart(smc) -struct s_smc *smc ; +void formac_tx_restart(struct s_smc *smc) { outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */ outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */ } -static void enable_formac(smc) -struct s_smc *smc ; +static void enable_formac(struct s_smc *smc) { /* set formac IMSK : 0 enables irq */ outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ; @@ -607,9 +583,8 @@ END_MANUAL_ENTRY */ -void enable_tx_irq(smc, queue) -struct s_smc *smc ; -u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */ +void enable_tx_irq(struct s_smc *smc, u_short queue) +/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */ { u_short imask ; @@ -643,9 +618,8 @@ END_MANUAL_ENTRY */ -void disable_tx_irq(smc, queue) -struct s_smc *smc ; -u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */ +void disable_tx_irq(struct s_smc *smc, u_short queue) +/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */ { u_short imask ; @@ -660,8 +634,7 @@ } #endif -static void disable_formac(smc) -struct s_smc *smc ; +static void disable_formac(struct s_smc *smc) { /* clear formac IMSK : 1 disables irq */ outpw(FM_A(FM_IMSK1U),MW) ; @@ -673,9 +646,7 @@ } -static void mac_ring_up(smc,up) -struct s_smc *smc ; -int up; +static void mac_ring_up(struct s_smc *smc, int up) { if (up) { formac_rcv_restart(smc) ; /* enable receive function */ @@ -702,10 +673,7 @@ * mac2_irq: status bits for the receive queue 1, and ring status * ring status indication bits */ -void mac2_irq(smc,code_s2u,code_s2l) -struct s_smc *smc ; -u_short code_s2u ; -u_short code_s2l ; +void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l) { u_short change_s2l ; u_short change_s2u ; @@ -831,10 +799,7 @@ /* * mac3_irq: receive queue 2 bits and address detection bits */ -void mac3_irq(smc,code_s3u,code_s3l) -struct s_smc *smc ; -u_short code_s3u ; -u_short code_s3l ; +void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l) { UNUSED(code_s3l) ; @@ -857,8 +822,7 @@ /* * take formac offline */ -static void formac_offline(smc) -struct s_smc *smc ; +static void formac_offline(struct s_smc *smc) { outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */ @@ -876,8 +840,7 @@ /* * bring formac online */ -static void formac_online(smc) -struct s_smc *smc ; +static void formac_online(struct s_smc *smc) { enable_formac(smc) ; SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT | @@ -887,8 +850,7 @@ /* * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon) */ -int init_fplus(smc) -struct s_smc *smc ; +int init_fplus(struct s_smc *smc) { smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ; smc->hw.fp.rx_mode = FM_MDAMA ; @@ -926,9 +888,7 @@ /* enable_formac(smc) ; */ } -static int init_mac(smc,all) -struct s_smc *smc ; -int all ; +static int init_mac(struct s_smc *smc, int all) { u_short t_max,x ; u_long time=0 ; @@ -1033,9 +993,7 @@ /* * called by CFM */ -void config_mux(smc,mux) -struct s_smc *smc ; -int mux; +void config_mux(struct s_smc *smc, int mux) { plc_config_mux(smc,mux) ; @@ -1049,8 +1007,7 @@ * the interrupt must not be permanently enabled * RMT calls this function periodically (timer driven polling) */ -void sm_mac_check_beacon_claim(smc) -struct s_smc *smc ; +void sm_mac_check_beacon_claim(struct s_smc *smc) { /* set formac IMSK : 0 enables irq */ outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ; @@ -1063,9 +1020,7 @@ /* * control ODL output */ -void sm_pm_control(smc,mode) -struct s_smc *smc ; -int mode; +void sm_pm_control(struct s_smc *smc, int mode) { SK_UNUSED(smc) ; @@ -1084,9 +1039,7 @@ /* * control MAC layer (called by RMT) */ -void sm_ma_control(smc,mode) -struct s_smc *smc ; -int mode; +void sm_ma_control(struct s_smc *smc, int mode) { switch(mode) { case MA_OFFLINE : @@ -1110,8 +1063,7 @@ } } -int sm_mac_get_tx_state(smc) -struct s_smc *smc ; +int sm_mac_get_tx_state(struct s_smc *smc) { return((inpw(FM_A(FM_STMCHN))>>4)&7) ; } @@ -1120,12 +1072,10 @@ * multicast functions */ -static struct s_fpmc *mac_get_mc_table(smc,user,own,del,can) -struct s_smc *smc ; -struct fddi_addr *user ; -struct fddi_addr *own ; -int del ; -int can ; +static struct s_fpmc* mac_get_mc_table(struct s_smc *smc, + struct fddi_addr *user, + struct fddi_addr *own, + int del, int can) { struct s_fpmc *tb ; struct s_fpmc *slot ; @@ -1166,8 +1116,7 @@ END_MANUAL_ENTRY() */ -void mac_clear_multicast(smc) -struct s_smc *smc ; +void mac_clear_multicast(struct s_smc *smc) { struct s_fpmc *tb ; int i ; @@ -1198,9 +1147,7 @@ END_MANUAL_ENTRY() */ -int mac_set_func_addr(smc,f_addr) -struct s_smc *smc ; -u_long f_addr ; +int mac_set_func_addr(struct s_smc *smc, u_long f_addr) { smc->hw.fp.func_addr = f_addr ; return(0) ; @@ -1235,10 +1182,7 @@ END_MANUAL_ENTRY() */ -int mac_add_multicast(smc,addr,can) -struct s_smc *smc ; -struct fddi_addr *addr ; -int can ; +int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) { SK_LOC_DECL(struct fddi_addr,own) ; struct s_fpmc *tb ; @@ -1292,10 +1236,7 @@ END_MANUAL_ENTRY() */ -void mac_del_multicast(smc,addr,can) -struct s_smc *smc ; -struct fddi_addr *addr ; -int can ; +void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can) { SK_LOC_DECL(struct fddi_addr,own) ; struct s_fpmc *tb ; @@ -1341,8 +1282,7 @@ END_MANUAL_ENTRY() */ -void mac_update_multicast(smc) -struct s_smc *smc ; +void mac_update_multicast(struct s_smc *smc) { struct s_fpmc *tb ; u_char *fu ; @@ -1418,9 +1358,7 @@ END_MANUAL_ENTRY */ -void mac_set_rx_mode(smc,mode) -struct s_smc *smc ; -int mode ; +void mac_set_rx_mode(struct s_smc *smc, int mode) { switch (mode) { case RX_ENABLE_ALLMULTI : @@ -1476,8 +1414,7 @@ END_MANUAL_ENTRY */ -void rtm_irq(smc) -struct s_smc *smc ; +void rtm_irq(struct s_smc *smc) { outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ; /* clear IRQ */ if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) { @@ -1490,15 +1427,13 @@ outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable RTM monitoring */ } -static void rtm_init(smc) -struct s_smc *smc ; +static void rtm_init(struct s_smc *smc) { outpd(ADDR(B2_RTM_INI),0) ; /* timer = 0 */ outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable IRQ */ } -void rtm_set_timer(smc) -struct s_smc *smc ; +void rtm_set_timer(struct s_smc *smc) { /* * MIB timer and hardware timer have the same resolution of 80nS @@ -1508,8 +1443,7 @@ outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ; } -static void smt_split_up_fifo(smc) -struct s_smc *smc ; +static void smt_split_up_fifo(struct s_smc *smc) { /* @@ -1629,8 +1563,7 @@ smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ; } -void formac_reinit_tx(smc) -struct s_smc *smc ; +void formac_reinit_tx(struct s_smc *smc) { /* * Split up the FIFO and reinitialize the MAC if synchronous @@ -1641,5 +1574,4 @@ (void)init_mac(smc,0) ; } } - diff -Nru a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h --- a/drivers/net/skfp/h/cmtdef.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/h/cmtdef.h 2004-06-20 13:00:23 -07:00 @@ -418,7 +418,6 @@ void *pc_p ; } ; - /* * link error monitor */ @@ -444,7 +443,6 @@ #define NUMBITS 10 - #ifdef AMDPLC /* @@ -480,216 +478,184 @@ * function prototypes */ #include "h/mbuf.h" /* Type definitions for MBUFs */ -void hwt_restart( /* hwt.c */ -#ifdef ANSIC - struct s_smc *smc -#endif - ) ; - -SMbuf *smt_build_frame( /* smt.c */ -#ifdef ANSIC - struct s_smc *smc, - int class, - int type, - int length -#endif - ) ; - -SMbuf *smt_get_mbuf( /* drvsr.c */ -#ifdef ANSIC - struct s_smc *smc -#endif - ) ; - -void *sm_to_para( /* smt.c */ -#ifdef ANSIC - struct s_smc *smc, - struct smt_header *sm, - int para -#endif - ) ; +#include "h/smtstate.h" /* struct smt_state */ + +void hwt_restart(struct s_smc *smc); /* hwt.c */ +SMbuf *smt_build_frame(struct s_smc *smc, int class, int type, + int length); /* smt.c */ +SMbuf *smt_get_mbuf(struct s_smc *smc); /* drvsr.c */ +void *sm_to_para(struct s_smc *smc, struct smt_header *sm, + int para); /* smt.c */ #ifndef SK_UNUSED #define SK_UNUSED(var) (void)(var) #endif -void queue_event() ; -void ecm() ; -void ecm_init() ; -void rmt() ; -void rmt_init() ; -void pcm() ; -void pcm_init() ; -void cfm() ; -void cfm_init() ; -void smt_timer_start() ; -void smt_timer_stop() ; -void pcm_status_state() ; -void plc_config_mux() ; -void sm_lem_evaluate() ; -void smt_clear_una_dna() ; -void mac_status_para() ; -void mac_update_counter() ; -void sm_pm_ls_latch() ; -void sm_ma_control() ; -void sm_mac_check_beacon_claim() ; -void config_mux() ; -void smt_agent_init() ; -void smt_timer_init() ; -void smt_received_pack() ; -void smt_add_para() ; -void smt_swap_para() ; -void ev_init() ; -void hwt_init() ; -u_long hwt_read() ; -void hwt_stop() ; -void hwt_start() ; -void smt_send_mbuf() ; -void smt_free_mbuf() ; -void sm_pm_bypass_req() ; -void rmt_indication() ; -void cfm_state_change() ; -void rx_indication() ; -void tx_indication() ; -#ifndef NO_SMT_PANIC -void smt_panic() ; -#else -#ifdef DEBUG -void smt_panic() ; +void queue_event(struct s_smc *smc, int class, int event); +void ecm(struct s_smc *smc, int event); +void ecm_init(struct s_smc *smc); +void rmt(struct s_smc *smc, int event); +void rmt_init(struct s_smc *smc); +void pcm(struct s_smc *smc, const int np, int event); +void pcm_init(struct s_smc *smc); +void cfm(struct s_smc *smc, int event); +void cfm_init(struct s_smc *smc); +void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time, + u_long token); +void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer); +void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, + int *remote, int *mac); +void plc_config_mux(struct s_smc *smc, int mux); +void sm_lem_evaluate(struct s_smc *smc); +void smt_clear_una_dna(struct s_smc *smc); +void mac_update_counter(struct s_smc *smc); +void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off); +void sm_ma_control(struct s_smc *smc, int mode); +void sm_mac_check_beacon_claim(struct s_smc *smc); +void config_mux(struct s_smc *smc, int mux); +void smt_agent_init(struct s_smc *smc); +void smt_timer_init(struct s_smc *smc); +void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs); +void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, + int index, int local); +void smt_swap_para(struct smt_header *sm, int len, int direction); +void ev_init(struct s_smc *smc); +void hwt_init(struct s_smc *smc); +u_long hwt_read(struct s_smc *smc); +void hwt_stop(struct s_smc *smc); +void hwt_start(struct s_smc *smc, u_long time); +void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc); +void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); +void sm_pm_bypass_req(struct s_smc *smc, int mode); +void rmt_indication(struct s_smc *smc, int i); +void cfm_state_change(struct s_smc *smc, int c_state); + +#if defined(DEBUG) || !defined(NO_SMT_PANIC) +void smt_panic(struct s_smc *smc, char *text); #else #define smt_panic(smc,text) -#endif /* DEBUG */ -#endif /* NO_SMT_PANIC */ -void smt_stat_counter() ; -void smt_timer_poll() ; -u_long smt_get_time() ; -u_long smt_get_tid() ; -void smt_timer_done() ; -void smt_set_defaults() ; -void smt_fixup_mib() ; -void smt_reset_defaults() ; -void smt_agent_task() ; -void smt_please_reconnect() ; -int smt_check_para() ; -void driver_get_bia() ; -#ifdef SUPERNET_3 -void drv_reset_indication() ; +#endif /* DEBUG || !NO_SMT_PANIC */ + +void smt_stat_counter(struct s_smc *smc, int stat); +void smt_timer_poll(struct s_smc *smc); +u_long smt_get_time(void); +u_long smt_get_tid(struct s_smc *smc); +void smt_timer_done(struct s_smc *smc); +void smt_set_defaults(struct s_smc *smc); +void smt_fixup_mib(struct s_smc *smc); +void smt_reset_defaults(struct s_smc *smc, int level); +void smt_agent_task(struct s_smc *smc); +void smt_please_reconnect(struct s_smc *smc, int reconn_time); +int smt_check_para(struct s_smc *smc, struct smt_header *sm, + const u_short list[]); +void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr); + +#ifdef SUPERNET_3 +void drv_reset_indication(struct s_smc *smc); #endif /* SUPERNET_3 */ -void smt_start_watchdog() ; -void smt_event() ; -void pcm_event() ; -void rmt_event() ; -void cfm_event() ; -void timer_event() ; -void ev_dispatcher() ; - -void smt_get_state() ; -void ecm_get_state() ; -void pcm_get_state() ; -void rmt_get_state() ; - -void ecm_state_change() ; -int sm_pm_bypass_present() ; -void pcm_state_change() ; -void rmt_state_change() ; -int sm_pm_get_ls() ; -int pcm_get_s_port() ; -int pcm_rooted_station() ; -int cfm_get_mac_input() ; -int cfm_get_mac_output() ; -int port_to_mib() ; -int cem_build_path() ; -int sm_mac_get_tx_state() ; -int is_individual() ; -int is_my_addr() ; -int is_broadcast() ; -int is_equal() ; -char *get_pcmstate() ; - -int smt_action() ; -u_short smt_online() ; -void smt_force_irq() ; -void smt_pmf_received_pack() ; -void smt_send_frame() ; -void smt_set_timestamp() ; -void mac_set_rx_mode() ; -int mac_add_multicast() ; -int mac_set_func_addr() ; -void mac_del_multicast() ; -void mac_update_multicast() ; -void mac_clear_multicast() ; -void mac_rx_directed_beacon() ; -void set_formac_tsync() ; -void formac_reinit_tx() ; -void formac_tx_restart() ; -void process_receive() ; -void init_driver_fplus() ; - -void rtm_irq() ; -void rtm_set_timer() ; -void ring_status_indication() ; -void llc_recover_tx() ; -void llc_restart_tx() ; -void plc_clear_irq() ; -void plc_irq() ; -int smt_set_mac_opvalues() ; -#ifdef TAG_MODE -void mac_drv_pci_fix() ; -void mac_do_pci_fix() ; -void mac_drv_clear_tx_queue() ; -void mac_drv_repair_descr() ; -u_long hwt_quick_read() ; -void hwt_wait_time() ; +void smt_start_watchdog(struct s_smc *smc); +void smt_event(struct s_smc *smc, int event); +void timer_event(struct s_smc *smc, u_long token); +void ev_dispatcher(struct s_smc *smc); +void pcm_get_state(struct s_smc *smc, struct smt_state *state); +void ecm_state_change(struct s_smc *smc, int e_state); +int sm_pm_bypass_present(struct s_smc *smc); +void pcm_state_change(struct s_smc *smc, int plc, int p_state); +void rmt_state_change(struct s_smc *smc, int r_state); +int sm_pm_get_ls(struct s_smc *smc, int phy); +int pcm_get_s_port(struct s_smc *smc); +int pcm_rooted_station(struct s_smc *smc); +int cfm_get_mac_input(struct s_smc *smc); +int cfm_get_mac_output(struct s_smc *smc); +int port_to_mib(struct s_smc *smc, int p); +int cem_build_path(struct s_smc *smc, char *to, int path_index); +int sm_mac_get_tx_state(struct s_smc *smc); +int is_individual(struct fddi_addr *addr); +int is_my_addr(struct s_smc *smc, struct fddi_addr *addr); +int is_broadcast(struct fddi_addr *addr); +int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2); +char *get_pcmstate(struct s_smc *smc, int np); +int smt_action(struct s_smc *smc, int class, int code, int index); +u_short smt_online(struct s_smc *smc, int on); +void smt_force_irq(struct s_smc *smc); +void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local); +void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local); +void smt_set_timestamp(struct s_smc *smc, u_char *p); +void mac_set_rx_mode(struct s_smc *smc, int mode); +int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); +int mac_set_func_addr(struct s_smc *smc, u_long f_addr); +void mac_del_multicast(struct s_smc *smc, struct fddi_addr *addr, int can); +void mac_update_multicast(struct s_smc *smc); +void mac_clear_multicast(struct s_smc *smc); +void set_formac_tsync(struct s_smc *smc, long sync_bw); +void formac_reinit_tx(struct s_smc *smc); +void formac_tx_restart(struct s_smc *smc); +void process_receive(struct s_smc *smc); +void init_driver_fplus(struct s_smc *smc); +void rtm_irq(struct s_smc *smc); +void rtm_set_timer(struct s_smc *smc); +void ring_status_indication(struct s_smc *smc, u_long status); +void llc_recover_tx(struct s_smc *smc); +void llc_restart_tx(struct s_smc *smc); +void plc_clear_irq(struct s_smc *smc, int p); +void plc_irq(struct s_smc *smc, int np, unsigned int cmd); +int smt_set_mac_opvalues(struct s_smc *smc); + +#ifdef TAG_MODE +void mac_drv_pci_fix(struct s_smc *smc, u_long fix_value); +void mac_do_pci_fix(struct s_smc *smc); +void mac_drv_clear_tx_queue(struct s_smc *smc); +void mac_drv_repair_descr(struct s_smc *smc); +u_long hwt_quick_read(struct s_smc *smc); +void hwt_wait_time(struct s_smc *smc, u_long start, long duration); #endif #ifdef SMT_PNMI -#ifdef ANSIC -int pnmi_init (struct s_smc* smc); -int pnmi_process_ndis_id (struct s_smc* smc, u_long ndis_oid, void* buf, - int len, int* BytesAccessed, int* BytesNeeded, u_char action); -#else -int pnmi_init (); -int pnmi_process_ndis_id (); -#endif +int pnmi_init(struct s_smc* smc); +int pnmi_process_ndis_id(struct s_smc *smc, u_long ndis_oid, void *buf, int len, + int *BytesAccessed, int *BytesNeeded, u_char action); #endif #ifdef SBA #ifndef _H2INC -void sba() ; +void sba(); #endif -void sba_raf_received_pack() ; -void sba_timer_poll() ; -void smt_init_sba() ; +void sba_raf_received_pack(); +void sba_timer_poll(); +void smt_init_sba(); #endif + #ifdef ESS -int ess_raf_received_pack() ; -void ess_timer_poll() ; -void ess_para_change() ; +int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm, + int fs); +void ess_timer_poll(struct s_smc *smc); +void ess_para_change(struct s_smc *smc); #endif -#ifdef BOOT -#define smt_srf_event(a,b,c,d) -#define smt_init_evc(a) +#ifndef BOOT +void smt_init_evc(struct s_smc *smc); +void smt_srf_event(struct s_smc *smc, int code, int index, int cond); #else -void smt_init_evc() ; -void smt_srf_event() ; +#define smt_init_evc(smc) +#define smt_srf_event(smc,code,index,cond) #endif #ifndef SMT_REAL_TOKEN_CT -void smt_emulate_token_ct(); +void smt_emulate_token_ct(struct s_smc *smc, int mac_index); #endif #if defined(DEBUG) && !defined(BOOT) -void dump_smt() ; +void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text); #else #define dump_smt(smc,sm,text) #endif #ifdef DEBUG -char *addr_to_string() ; -void dump_hex() ; +char* addr_to_string(struct fddi_addr *addr); +void dump_hex(char *p, int len); #endif + #endif /* PROTOTYP_INC */ /* PNMI default defines */ diff -Nru a/drivers/net/skfp/h/smtstate.h b/drivers/net/skfp/h/smtstate.h --- a/drivers/net/skfp/h/smtstate.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/skfp/h/smtstate.h 2004-06-20 13:00:25 -07:00 @@ -12,6 +12,9 @@ * ******************************************************************************/ +#ifndef _SKFP_H_SMTSTATE_H_ +#define _SKFP_H_SMTSTATE_H_ + /* * SMT state definitions */ @@ -98,3 +101,6 @@ struct smt_state { struct pcm_state pcm_state[NUMPHYS] ; /* port A & port B */ } ; + +#endif + diff -Nru a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c --- a/drivers/net/skfp/hwmtm.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/skfp/hwmtm.c 2004-06-20 13:00:24 -07:00 @@ -75,15 +75,17 @@ ------------------------------------------------------------- */ -static void queue_llc_rx(), smt_to_llc(), - init_txd_ring(), init_rxd_ring(), - queue_txd_mb() ; - -static u_long init_descr_ring(), repair_txd_ring(), - repair_rxd_ring() ; - -static SMbuf *get_llc_rx(), *get_txd_mb() ; - +static void queue_llc_rx(struct s_smc *smc, SMbuf *mb); +static void smt_to_llc(struct s_smc *smc, SMbuf *mb); +static void init_txd_ring(struct s_smc *smc); +static void init_rxd_ring(struct s_smc *smc); +static void queue_txd_mb(struct s_smc *smc, SMbuf *mb); +static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start, + int count); +static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue); +static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue); +static SMbuf* get_llc_rx(struct s_smc *smc); +static SMbuf* get_txd_mb(struct s_smc *smc); /* ------------------------------------------------------------- @@ -92,55 +94,81 @@ */ /* The external SMT functions are listed in cmtdef.h */ -extern void *mac_drv_get_space(), *mac_drv_get_desc_mem(), - init_board(), mac_drv_fill_rxd(), - plc1_irq(), mac_drv_tx_complete(), - plc2_irq(), mac1_irq(), - mac2_irq(), mac3_irq(), - timer_irq(), mac_drv_rx_complete(), - mac_drv_requeue_rxd(), init_plc(), - mac_drv_clear_rxd(), llc_restart_tx(), - ev_dispatcher(), smt_force_irq() ; +extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size); +extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size); +extern void init_board(struct s_smc *smc, u_char *mac_addr); +extern void mac_drv_fill_rxd(struct s_smc *smc); +extern void plc1_irq(struct s_smc *smc); +extern void mac_drv_tx_complete(struct s_smc *smc, + volatile struct s_smt_fp_txd *txd); +extern void plc2_irq(struct s_smc *smc); +extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl); +extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l); +extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l); +extern void timer_irq(struct s_smc *smc); +extern void mac_drv_rx_complete(struct s_smc *smc, + volatile struct s_smt_fp_rxd *rxd, + int frag_count, int len); +extern void mac_drv_requeue_rxd(struct s_smc *smc, + volatile struct s_smt_fp_rxd *rxd, + int frag_count); +extern void init_plc(struct s_smc *smc); +extern void mac_drv_clear_rxd(struct s_smc *smc, + volatile struct s_smt_fp_rxd *rxd, int frag_count); #ifdef USE_OS_CPY -extern void hwm_cpy_rxd2mb(), hwm_cpy_txd2mb() ; +extern void hwm_cpy_rxd2mb(void); +extern void hwm_cpy_txd2mb(void); #endif + #ifdef ALL_RX_COMPLETE -extern void mac_drv_all_receives_complete() ; +extern void mac_drv_all_receives_complete(void); #endif -extern u_long mac_drv_virt2phys(), dma_master() ; +extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt); +extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag); #ifdef NDIS_OS2 -extern void post_proc() ; +extern void post_proc(void); #else -extern void dma_complete() ; +extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, + int flag); #endif -extern int init_fplus(), mac_drv_rx_init() ; +extern int init_fplus(struct s_smc *smc); +extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, + int la_len); /* ------------------------------------------------------------- PUBLIC FUNCTIONS: ------------------------------------------------------------- */ - void process_receive(), smt_send_mbuf(), - fddi_isr(), mac_drv_clear_txd(), - smt_free_mbuf(), init_driver_fplus(), - mac_drv_rx_mode(), init_fddi_driver(), - mac_drv_clear_tx_queue(), - mac_drv_clear_rx_queue(), - hwm_tx_frag(), hwm_rx_frag() ; - - int mac_drv_rx_frag(), mac_drv_init(), - hwm_tx_init() ; +void process_receive(struct s_smc *smc); +void fddi_isr(struct s_smc *smc); +void mac_drv_clear_txd(struct s_smc *smc); +void smt_free_mbuf(struct s_smc *smc, SMbuf *mb); +void init_driver_fplus(struct s_smc *smc); +void mac_drv_rx_mode(struct s_smc *smc, int mode); +void init_fddi_driver(struct s_smc *smc, u_char *mac_addr); +void mac_drv_clear_tx_queue(struct s_smc *smc); +void mac_drv_clear_rx_queue(struct s_smc *smc); +void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status); +void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status); + +int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len); +int mac_drv_init(struct s_smc *smc); +int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, + int frame_status); - u_int mac_drv_check_space() ; +u_int mac_drv_check_space(void); - SMbuf *smt_get_mbuf() ; +SMbuf* smt_get_mbuf(struct s_smc *smc); #ifdef DEBUG - void mac_drv_debug_lev() ; + void mac_drv_debug_lev(void); #endif /* @@ -208,7 +236,7 @@ * * END_MANUAL_ENTRY */ -u_int mac_drv_check_space() +u_int mac_drv_check_space(void) { #ifdef MB_OUTSIDE_SMC #ifdef COMMON_MB_POOL @@ -238,8 +266,7 @@ * mac_drv_init once, after the adatper is detected. * END_MANUAL_ENTRY */ -int mac_drv_init(smc) -struct s_smc *smc ; +int mac_drv_init(struct s_smc *smc) { if (sizeof(struct s_smt_fp_rxd) % 16) { SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ; @@ -289,8 +316,7 @@ * least significant byte etc.) * END_MANUAL_ENTRY */ -void init_driver_fplus(smc) -struct s_smc *smc ; +void init_driver_fplus(struct s_smc *smc) { smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ; @@ -305,10 +331,9 @@ #endif } -static u_long init_descr_ring(smc,start,count) -struct s_smc *smc ; -union s_fp_descr volatile *start; -int count ; +static u_long init_descr_ring(struct s_smc *smc, + union s_fp_descr volatile *start, + int count) { int i ; union s_fp_descr volatile *d1 ; @@ -337,8 +362,7 @@ return(phys) ; } -static void init_txd_ring(smc) -struct s_smc *smc ; +static void init_txd_ring(struct s_smc *smc) { struct s_smt_fp_txd volatile *ds ; struct s_smt_tx_queue *queue ; @@ -375,8 +399,7 @@ outpd(ADDR(B5_XS_DA),phys) ; } -static void init_rxd_ring(smc) -struct s_smc *smc ; +static void init_rxd_ring(struct s_smc *smc) { struct s_smt_fp_rxd volatile *ds ; struct s_smt_rx_queue *queue ; @@ -406,9 +429,7 @@ * * END_MANUAL_ENTRY */ -void init_fddi_driver(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; /* canonical address */ +void init_fddi_driver(struct s_smc *smc, u_char *mac_addr) { SMbuf *mb ; int i ; @@ -472,8 +493,7 @@ } -SMbuf *smt_get_mbuf(smc) -struct s_smc *smc ; +SMbuf *smt_get_mbuf(struct s_smc *smc) { register SMbuf *mb ; @@ -495,9 +515,7 @@ return (mb) ; /* May be NULL */ } -void smt_free_mbuf(smc, mb) -struct s_smc *smc ; -SMbuf *mb; +void smt_free_mbuf(struct s_smc *smc, SMbuf *mb) { if (mb) { @@ -543,8 +561,7 @@ * * END_MANUAL_ENTRY */ -void mac_drv_repair_descr(smc) -struct s_smc *smc ; +void mac_drv_repair_descr(struct s_smc *smc) { u_long phys ; @@ -576,9 +593,7 @@ outpd(ADDR(B0_R1_CSR),CSR_START) ; } -static u_long repair_txd_ring(smc,queue) -struct s_smc *smc ; -struct s_smt_tx_queue *queue ; +static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue) { int i ; int tx_used ; @@ -630,9 +645,7 @@ * RxDs with an OWN bit set but with a reset STF bit should be * skipped and owned by the driver (OWN = 0). */ -static u_long repair_rxd_ring(smc,queue) -struct s_smc *smc ; -struct s_smt_rx_queue *queue ; +static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue) { int i ; int rx_used ; @@ -703,8 +716,7 @@ * * END_MANUAL_ENTRY */ -void fddi_isr(smc) -struct s_smc *smc ; +void fddi_isr(struct s_smc *smc) { u_long is ; /* ISR source */ u_short stu, stl ; @@ -987,9 +999,7 @@ * * END_MANUAL_ENTRY */ -void mac_drv_rx_mode(smc,mode) -struct s_smc *smc ; -int mode ; +void mac_drv_rx_mode(struct s_smc *smc, int mode) { switch(mode) { case RX_ENABLE_PASS_SMT: @@ -1038,8 +1048,7 @@ /* * process receive queue */ -void process_receive(smc) -struct s_smc *smc ; +void process_receive(struct s_smc *smc) { int i ; int n ; @@ -1379,9 +1388,7 @@ return ; /* lint bug: needs return detect end of function */ } -static void smt_to_llc(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void smt_to_llc(struct s_smc *smc, SMbuf *mb) { u_char fc ; @@ -1416,12 +1423,8 @@ * * END_MANUAL_ENTRY */ -void hwm_rx_frag(smc,virt,phys,len,frame_status) -struct s_smc *smc ; -char far *virt ; -u_long phys ; -int len ; -int frame_status ; +void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status) { struct s_smt_fp_rxd volatile *r ; u_int rbctrl ; @@ -1460,10 +1463,7 @@ * * END_MANUAL_ENTRY */ -int mac_drv_rx_frag(smc,virt,len) -struct s_smc *smc ; -void far *virt ; -int len ; +int mac_drv_rx_frag(struct s_smc *smc, void far *virt, int len) { NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ; @@ -1500,8 +1500,7 @@ * * END_MANUAL_ENTRY */ -void mac_drv_clear_rx_queue(smc) -struct s_smc *smc ; +void mac_drv_clear_rx_queue(struct s_smc *smc) { struct s_smt_fp_rxd volatile *r ; struct s_smt_fp_rxd volatile *next_rxd ; @@ -1588,12 +1587,8 @@ * * END_MANUAL_ENTRY */ -int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status) -struct s_smc *smc ; -u_char fc ; -int frag_count ; -int frame_len ; -int frame_status ; +int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len, + int frame_status) { NDD_TRACE("THiB",fc,frag_count,frame_len) ; smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ; @@ -1670,12 +1665,8 @@ * * END_MANUAL_ENTRY */ -void hwm_tx_frag(smc,virt,phys,len,frame_status) -struct s_smc *smc ; -char far *virt ; -u_long phys ; -int len ; -int frame_status ; +void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len, + int frame_status) { struct s_smt_fp_txd volatile *t ; struct s_smt_tx_queue *queue ; @@ -1780,9 +1771,7 @@ /* * queues a receive for later send */ -static void queue_llc_rx(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void queue_llc_rx(struct s_smc *smc, SMbuf *mb) { DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ; smc->os.hwm.queued_rx_frames++ ; @@ -1806,8 +1795,7 @@ /* * get a SMbuf from the llc_rx_queue */ -static SMbuf *get_llc_rx(smc) -struct s_smc *smc ; +static SMbuf *get_llc_rx(struct s_smc *smc) { SMbuf *mb ; @@ -1823,9 +1811,7 @@ * queues a transmit SMT MBuf during the time were the MBuf is * queued the TxD ring */ -static void queue_txd_mb(smc,mb) -struct s_smc *smc ; -SMbuf *mb ; +static void queue_txd_mb(struct s_smc *smc, SMbuf *mb) { DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ; smc->os.hwm.queued_txd_mb++ ; @@ -1842,8 +1828,7 @@ /* * get a SMbuf from the txd_tx_queue */ -static SMbuf *get_txd_mb(smc) -struct s_smc *smc ; +static SMbuf *get_txd_mb(struct s_smc *smc) { SMbuf *mb ; @@ -1858,10 +1843,7 @@ /* * SMT Send function */ -void smt_send_mbuf(smc,mb,fc) -struct s_smc *smc; -SMbuf *mb; -int fc; +void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) { char far *data ; int len ; @@ -1995,8 +1977,7 @@ * * END_MANUAL_ENTRY */ -void mac_drv_clear_txd(smc) -struct s_smc *smc ; +void mac_drv_clear_txd(struct s_smc *smc) { struct s_smt_tx_queue *queue ; struct s_smt_fp_txd volatile *t1 ; @@ -2087,8 +2068,7 @@ * * END_MANUAL_ENTRY */ -void mac_drv_clear_tx_queue(smc) -struct s_smc *smc ; +void mac_drv_clear_tx_queue(struct s_smc *smc) { struct s_smt_fp_txd volatile *t ; struct s_smt_tx_queue *queue ; @@ -2180,10 +2160,7 @@ * * END_MANUAL_ENTRY */ -void mac_drv_debug_lev(smc,flag,lev) -struct s_smc *smc ; -int flag ; -int lev ; +void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev) { switch(flag) { case (int)NULL: diff -Nru a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c --- a/drivers/net/skfp/hwt.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/hwt.c 2004-06-20 13:00:23 -07:00 @@ -39,7 +39,7 @@ * Prototypes of local functions. */ /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */ -/*static*/ void hwt_restart() ; +/*static void hwt_restart() ; */ /************************ * @@ -60,9 +60,7 @@ ************************/ #define HWT_MAX (65000) -void hwt_start(smc, time) -struct s_smc *smc ; -u_long time ; +void hwt_start(struct s_smc *smc, u_long time) { u_short cnt ; @@ -115,8 +113,7 @@ * Nothing. * ************************/ -void hwt_stop(smc) -struct s_smc *smc ; +void hwt_stop(struct s_smc *smc) { #ifndef PCI /* stop counter 0 by switching to mode 0 */ @@ -145,8 +142,7 @@ * Nothing. * ************************/ -void hwt_init(smc) -struct s_smc *smc ; +void hwt_init(struct s_smc *smc) { smc->hw.t_start = 0 ; smc->hw.t_stop = 0 ; @@ -169,8 +165,7 @@ * Nothing. * ************************/ -void hwt_restart(smc) -struct s_smc *smc ; +void hwt_restart(struct s_smc *smc) { hwt_stop(smc) ; #ifndef PCI @@ -193,8 +188,7 @@ * The elapsed time since last start in units of 16us. * ************************/ -u_long hwt_read(smc) -struct s_smc *smc ; +u_long hwt_read(struct s_smc *smc) { u_short tr ; #ifndef PCI @@ -238,8 +232,7 @@ * current timer value in units of 80ns. * ************************/ -u_long hwt_quick_read(smc) -struct s_smc *smc ; +u_long hwt_quick_read(struct s_smc *smc) { u_long interval ; u_long time ; @@ -267,10 +260,7 @@ * NOTE: The fuction will return immediately, if the timer is not * started ************************/ -void hwt_wait_time(smc,start,duration) -struct s_smc *smc ; -u_long start ; -long duration ; +void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) { long diff ; long interval ; @@ -312,3 +302,4 @@ } } #endif + diff -Nru a/drivers/net/skfp/lnkstat.c b/drivers/net/skfp/lnkstat.c --- a/drivers/net/skfp/lnkstat.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/skfp/lnkstat.c 2004-06-20 13:00:24 -07:00 @@ -52,8 +52,7 @@ END_MANUAL_ENTRY() */ -u_long smt_get_error_word(smc) -struct s_smc *smc ; +u_long smt_get_error_word(struct s_smc *smc) { u_long st; @@ -92,8 +91,7 @@ END_MANUAL_ENTRY() */ -u_long smt_get_event_word(smc) -struct s_smc *smc ; +u_long smt_get_event_word(struct s_smc *smc) { return (u_long) 0; } @@ -111,8 +109,7 @@ END_MANUAL_ENTRY() */ -u_long smt_get_port_event_word(smc) -struct s_smc *smc ; +u_long smt_get_port_event_word(struct s_smc *smc) { return (u_long) 0; } @@ -135,10 +132,7 @@ END_MANUAL_ENTRY() */ -int smt_read_errorlog(smc,p,len) -struct s_smc *smc ; -char _far *p ; -int len ; +int smt_read_errorlog(struct s_smc *smc, char _far *p, int len) { int i ; int st ; @@ -207,3 +201,4 @@ er->ucode_version_level = 0x0101 ; return(len) ; } + diff -Nru a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c --- a/drivers/net/skfp/pcmplc.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/pcmplc.c 2004-06-20 13:00:23 -07:00 @@ -199,28 +199,25 @@ PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR; /* external functions */ -void all_selection_criteria (); +void all_selection_criteria(struct s_smc *smc); /* internal functions */ -static void pcm_fsm() ; -static void pc_rcode_actions() ; -static void pc_tcode_actions() ; -static void reset_lem_struct() ; -static void plc_init() ; -static void sm_ph_lem_start() ; -static void sm_ph_lem_stop() ; -static void sm_ph_linestate() ; -static void real_init_plc() ; +static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd); +static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy); +static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy); +static void reset_lem_struct(struct s_phy *phy); +static void plc_init(struct s_smc *smc, int p); +static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold); +static void sm_ph_lem_stop(struct s_smc *smc, int np); +static void sm_ph_linestate(struct s_smc *smc, int phy, int ls); +static void real_init_plc(struct s_smc *smc); /* * SMT timer interface * start PCM timer 0 */ -static void start_pcm_timer0(smc,value,event,phy) -struct s_smc *smc ; -u_long value; -int event; -struct s_phy *phy; +static void start_pcm_timer0(struct s_smc *smc, u_long value, int event, + struct s_phy *phy) { phy->timer0_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&phy->pcm_timer0,value, @@ -230,9 +227,7 @@ * SMT timer interface * stop PCM timer 0 */ -static void stop_pcm_timer0(smc,phy) -struct s_smc *smc ; -struct s_phy *phy; +static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy) { if (phy->pcm_timer0.tm_active) smt_timer_stop(smc,&phy->pcm_timer0) ; @@ -242,8 +237,7 @@ init PCM state machine (called by driver) clear all PCM vars and flags */ -void pcm_init(smc) -struct s_smc *smc ; +void pcm_init(struct s_smc *smc) { int i ; int np ; @@ -407,8 +401,7 @@ real_init_plc(smc) ; } -void init_plc(smc) -struct s_smc *smc ; +void init_plc(struct s_smc *smc) { SK_UNUSED(smc) ; @@ -421,8 +414,7 @@ */ } -static void real_init_plc(smc) -struct s_smc *smc ; +static void real_init_plc(struct s_smc *smc) { int p ; @@ -430,9 +422,7 @@ plc_init(smc,p) ; } -static void plc_init(smc,p) -struct s_smc *smc ; -int p; +static void plc_init(struct s_smc *smc, int p) { int i ; #ifndef MOT_ELM @@ -495,10 +485,7 @@ /* * control PCM state machine */ -static void plc_go_state(smc,p,state) -struct s_smc *smc ; -int p; -int state; +static void plc_go_state(struct s_smc *smc, int p, int state) { HW_PTR port ; int val ; @@ -514,9 +501,7 @@ /* * read current line state (called by ECM & PCM) */ -int sm_pm_get_ls(smc,phy) -struct s_smc *smc ; -int phy; +int sm_pm_get_ls(struct s_smc *smc, int phy) { int state ; @@ -549,10 +534,7 @@ return(state) ; } -static int plc_send_bits(smc,phy,len) -struct s_smc *smc ; -struct s_phy *phy; -int len; +static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len) { int np = phy->np ; /* PHY index */ int n ; @@ -589,9 +571,7 @@ /* * config plc muxes */ -void plc_config_mux(smc,mux) -struct s_smc *smc ; -int mux ; +void plc_config_mux(struct s_smc *smc, int mux) { if (smc->s.sas != SMT_DAS) return ; @@ -615,10 +595,7 @@ process event until SM is stable */ -void pcm(smc,np,event) -struct s_smc *smc ; -const int np; -int event; +void pcm(struct s_smc *smc, const int np, int event) { int state ; int oldstate ; @@ -697,10 +674,7 @@ /* * PCM state machine */ -static void pcm_fsm(smc,phy,cmd) -struct s_smc *smc ; -struct s_phy *phy; -int cmd; +static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd) { int i ; int np = phy->np ; /* PHY index */ @@ -1063,10 +1037,7 @@ /* * force line state on a PHY output (only in MAINT state) */ -static void sm_ph_linestate(smc,phy,ls) -struct s_smc *smc ; -int phy; -int ls; +static void sm_ph_linestate(struct s_smc *smc, int phy, int ls) { int cntrl ; @@ -1095,9 +1066,7 @@ outpw(PLC(phy,PL_CNTRL_B),cntrl) ; } - -static void reset_lem_struct(phy) -struct s_phy *phy; +static void reset_lem_struct(struct s_phy *phy) { struct lem_counter *lem = &phy->lem ; @@ -1108,9 +1077,7 @@ /* * link error monitor */ -static void lem_evaluate(smc,phy) -struct s_smc *smc ; -struct s_phy *phy; +static void lem_evaluate(struct s_smc *smc, struct s_phy *phy) { int ber ; u_long errors ; @@ -1210,8 +1177,7 @@ /* * called by SMT to calculate LEM bit error rate */ -void sm_lem_evaluate(smc) -struct s_smc *smc ; +void sm_lem_evaluate(struct s_smc *smc) { int np ; @@ -1219,9 +1185,7 @@ lem_evaluate(smc,&smc->y[np]) ; } -static void lem_check_lct(smc,phy) -struct s_smc *smc ; -struct s_phy *phy ; +static void lem_check_lct(struct s_smc *smc, struct s_phy *phy) { struct lem_counter *lem = &phy->lem ; struct fddi_mib_p *mib ; @@ -1265,10 +1229,7 @@ /* * LEM functions */ -static void sm_ph_lem_start(smc,np,threshold) -struct s_smc *smc ; -int np; -int threshold; +static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold) { struct lem_counter *lem = &smc->y[np].lem ; @@ -1286,9 +1247,7 @@ SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ; } -static void sm_ph_lem_stop(smc,np) -struct s_smc *smc ; -int np; +static void sm_ph_lem_stop(struct s_smc *smc, int np) { struct lem_counter *lem = &smc->y[np].lem ; @@ -1297,10 +1256,8 @@ } /* ARGSUSED */ -void sm_pm_ls_latch(smc,phy,on_off) -struct s_smc *smc ; -int phy; -int on_off; /* en- or disable ident. ls */ +void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off) +/* int on_off; en- or disable ident. ls */ { SK_UNUSED(smc) ; @@ -1317,10 +1274,7 @@ /* * PCM pseudo code 5.1 .. 6.1 */ -static void pc_rcode_actions(smc,bit,phy) -struct s_smc *smc ; -int bit; -struct s_phy *phy; +static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy) { struct fddi_mib_p *mib ; @@ -1456,10 +1410,7 @@ /* * PCM pseudo code 5.1 .. 6.1 */ -static void pc_tcode_actions(smc,bit,phy) -struct s_smc *smc ; -const int bit; -struct s_phy *phy; +static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy) { int np = phy->np ; struct fddi_mib_p *mib ; @@ -1638,8 +1589,7 @@ /* * return status twisted (called by SMT) */ -int pcm_status_twisted(smc) -struct s_smc *smc ; +int pcm_status_twisted(struct s_smc *smc) { int twist = 0 ; if (smc->s.sas != SMT_DAS) @@ -1658,13 +1608,8 @@ * remote phy type * remote mac yes/no */ -void pcm_status_state(smc,np,type,state,remote,mac) -struct s_smc *smc ; -int np; -int *type; -int *state; -int *remote; -int *mac; +void pcm_status_state(struct s_smc *smc, int np, int *type, int *state, + int *remote, int *mac) { struct s_phy *phy = &smc->y[np] ; struct fddi_mib_p *mib ; @@ -1687,8 +1632,7 @@ /* * return rooted station status (called by SMT) */ -int pcm_rooted_station(smc) -struct s_smc *smc ; +int pcm_rooted_station(struct s_smc *smc) { int n ; @@ -1703,10 +1647,8 @@ /* * Interrupt actions for PLC & PCM events */ -void plc_irq(smc,np,cmd) -struct s_smc *smc ; -int np; /* PHY index */ -unsigned int cmd; +void plc_irq(struct s_smc *smc, int np, unsigned int cmd) +/* int np; PHY index */ { struct s_phy *phy = &smc->y[np] ; struct s_plc *plc = &phy->plc ; @@ -1919,9 +1861,7 @@ #endif } -void pcm_set_lct_short(smc,n) -struct s_smc *smc ; -int n ; +void pcm_set_lct_short(struct s_smc *smc, int n) { if (n <= 0 || n > 1000) return ; @@ -1932,9 +1872,7 @@ /* * fill state struct */ -void pcm_get_state(smc,state) -struct s_smc *smc ; -struct smt_state *state ; +void pcm_get_state(struct s_smc *smc, struct smt_state *state) { struct s_phy *phy ; struct pcm_state *pcs ; @@ -1968,9 +1906,7 @@ } } -int get_pcm_state(smc,np) -struct s_smc *smc ; -int np; +int get_pcm_state(struct s_smc *smc, int np) { int pcs ; @@ -1992,9 +1928,7 @@ return(pcs) ; } -char *get_linestate(smc,np) -struct s_smc *smc ; -int np; +char *get_linestate(struct s_smc *smc, int np) { char *ls = "" ; @@ -2016,9 +1950,7 @@ return(ls) ; } -char *get_pcmstate(smc,np) -struct s_smc *smc ; -int np; +char *get_pcmstate(struct s_smc *smc, int np) { char *pcs ; @@ -2040,8 +1972,7 @@ return(pcs) ; } -void list_phy(smc) -struct s_smc *smc ; +void list_phy(struct s_smc *smc) { struct s_plc *plc ; int np ; @@ -2069,8 +2000,7 @@ #ifdef CONCENTRATOR -void pcm_lem_dump(smc) -struct s_smc *smc ; +void pcm_lem_dump(struct s_smc *smc) { int i ; struct s_phy *phy ; diff -Nru a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c --- a/drivers/net/skfp/pmf.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/skfp/pmf.c 2004-06-20 13:00:26 -07:00 @@ -32,12 +32,16 @@ static const char ID_sccs[] = "@(#)pmf.c 1.37 97/08/04 (C) SK " ; #endif -static int smt_authorize() ; -static int smt_check_set_count() ; -static const struct s_p_tab *smt_get_ptab() ; -static int smt_mib_phys() ; -int smt_set_para() ; -void smt_add_para() ; +static int smt_authorize(struct s_smc *smc, struct smt_header *sm); +static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm); +static const struct s_p_tab* smt_get_ptab(u_short para); +static int smt_mib_phys(struct s_smc *smc); +int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, + int set); +void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, + int index, int local); +static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, + int set, int local); #define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e)) #define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e)) @@ -280,13 +284,7 @@ { 0 } } ; - -static SMbuf *smt_build_pmf_response() ; - -void smt_pmf_received_pack(smc,mb,local) -struct s_smc *smc ; -SMbuf *mb ; -int local ; +void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local) { struct smt_header *sm ; SMbuf *reply ; @@ -316,13 +314,8 @@ } } -extern SMbuf *smt_get_mbuf() ; - -static SMbuf *smt_build_pmf_response(smc,req,set,local) -struct s_smc *smc ; -struct smt_header *req ; -int set ; -int local ; +static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req, + int set, int local) { SMbuf *mb ; struct smt_header *smt ; @@ -509,11 +502,7 @@ return(mb) ; } -extern void *sm_to_para() ; - -static int smt_authorize(smc,sm) -struct s_smc *smc ; -struct smt_header *sm ; +static int smt_authorize(struct s_smc *smc, struct smt_header *sm) { struct smt_para *pa ; int i ; @@ -548,9 +537,7 @@ return(0) ; } -static int smt_check_set_count(smc,sm) -struct s_smc *smc ; -struct smt_header *sm ; +static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm) { struct smt_para *pa ; struct smt_p_setcount *sc ; @@ -566,12 +553,8 @@ return(0) ; } -void smt_add_para(smc,pcon,para,index,local) -struct s_smc *smc ; -struct s_pcon *pcon ; -u_short para ; -int index ; -int local ; +void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, + int index, int local) { struct smt_para *pa ; const struct s_p_tab *pt ; @@ -1095,12 +1078,8 @@ /* * set parameter */ -int smt_set_para(smc,pa,index,local,set) -struct s_smc *smc ; -struct smt_para *pa ; -int index ; -int local ; -int set ; +int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index, int local, + int set) { #define IFSET(x) if (set) (x) @@ -1549,8 +1528,7 @@ #endif } -static const struct s_p_tab *smt_get_ptab(para) -u_short para ; +static const struct s_p_tab *smt_get_ptab(u_short para) { const struct s_p_tab *pt ; for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++) @@ -1558,8 +1536,7 @@ return(pt->p_num ? pt : 0) ; } -static int smt_mib_phys(smc) -struct s_smc *smc ; +static int smt_mib_phys(struct s_smc *smc) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; @@ -1572,9 +1549,7 @@ #endif } -int port_to_mib(smc,p) -struct s_smc *smc ; -int p ; +int port_to_mib(struct s_smc *smc, int p) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; @@ -1590,10 +1565,7 @@ #ifdef DEBUG #ifndef BOOT -void dump_smt(smc,sm,text) -struct s_smc *smc ; -struct smt_header *sm ; -char *text ; +void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text) { int len ; struct smt_para *pa ; @@ -1680,9 +1652,7 @@ printf("-------------------------------------------------\n\n") ; } -void dump_hex(p,len) -char *p ; -int len ; +void dump_hex(char *p, int len) { int n = 0 ; while (len--) { diff -Nru a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c --- a/drivers/net/skfp/queue.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/skfp/queue.c 2004-06-20 13:00:25 -07:00 @@ -31,8 +31,7 @@ /* * init event queue management */ -void ev_init(smc) -struct s_smc *smc ; +void ev_init(struct s_smc *smc) { smc->q.ev_put = smc->q.ev_get = smc->q.ev_queue ; } @@ -40,10 +39,7 @@ /* * add event to queue */ -void queue_event(smc,class,event) -struct s_smc *smc ; -int class ; -int event ; +void queue_event(struct s_smc *smc, int class, int event) { PRINTF("queue class %d event %d\n",class,event) ; smc->q.ev_put->class = class ; @@ -59,9 +55,7 @@ /* * timer_event is called from HW timer package. */ -void timer_event(smc,token) -struct s_smc *smc ; -u_long token ; +void timer_event(struct s_smc *smc, u_long token) { PRINTF("timer event class %d token %d\n", EV_T_CLASS(token), @@ -76,8 +70,7 @@ * send command to state machine * end */ -void ev_dispatcher(smc) -struct s_smc *smc ; +void ev_dispatcher(struct s_smc *smc) { struct event_queue *ev ; /* pointer into queue */ int class ; @@ -131,9 +124,7 @@ * on 0 disconnect * on 1 connect */ -u_short smt_online(smc,on) -struct s_smc *smc ; -int on ; +u_short smt_online(struct s_smc *smc, int on) { queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ; ev_dispatcher(smc) ; @@ -147,10 +138,7 @@ * dump current flag setting */ #ifdef CONCENTRATOR -void do_smt_flag(smc,flag,value) -struct s_smc *smc ; -char *flag ; -int value ; +void do_smt_flag(struct s_smc *smc, char *flag, int value) { #ifdef DEBUG struct smt_debug *deb; diff -Nru a/drivers/net/skfp/rmt.c b/drivers/net/skfp/rmt.c --- a/drivers/net/skfp/rmt.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/skfp/rmt.c 2004-06-20 13:00:26 -07:00 @@ -102,17 +102,17 @@ /* * function declarations */ -static void rmt_fsm() ; -static void start_rmt_timer0() ; -static void start_rmt_timer1() ; -static void start_rmt_timer2() ; -static void stop_rmt_timer0() ; -static void stop_rmt_timer1() ; -static void stop_rmt_timer2() ; -static void rmt_dup_actions() ; -static void rmt_reinsert_actions() ; -static void rmt_leave_actions() ; -static void rmt_new_dup_actions() ; +static void rmt_fsm(struct s_smc *smc, int cmd); +static void start_rmt_timer0(struct s_smc *smc, u_long value, int event); +static void start_rmt_timer1(struct s_smc *smc, u_long value, int event); +static void start_rmt_timer2(struct s_smc *smc, u_long value, int event); +static void stop_rmt_timer0(struct s_smc *smc); +static void stop_rmt_timer1(struct s_smc *smc); +static void stop_rmt_timer2(struct s_smc *smc); +static void rmt_dup_actions(struct s_smc *smc); +static void rmt_reinsert_actions(struct s_smc *smc); +static void rmt_leave_actions(struct s_smc *smc); +static void rmt_new_dup_actions(struct s_smc *smc); #ifndef SUPERNET_3 extern void restart_trt_for_dbcn() ; @@ -122,8 +122,7 @@ init RMT state machine clear all RMT vars and flags */ -void rmt_init(smc) -struct s_smc *smc ; +void rmt_init(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ; smc->r.dup_addr_test = DA_NONE ; @@ -145,9 +144,7 @@ process event until SM is stable */ -void rmt(smc,event) -struct s_smc *smc ; -int event ; +void rmt(struct s_smc *smc, int event) { int state ; @@ -166,9 +163,7 @@ /* process RMT event */ -static void rmt_fsm(smc,cmd) -struct s_smc *smc ; -int cmd ; +static void rmt_fsm(struct s_smc *smc, int cmd) { /* * RM00-RM70 : from all states @@ -535,8 +530,7 @@ * (jd) RMT duplicate address actions * leave the ring or reinsert just as configured */ -static void rmt_dup_actions(smc) -struct s_smc *smc ; +static void rmt_dup_actions(struct s_smc *smc) { if (smc->r.jm_flag) { } @@ -555,8 +549,7 @@ /* * Reconnect to the Ring */ -static void rmt_reinsert_actions(smc) -struct s_smc *smc ; +static void rmt_reinsert_actions(struct s_smc *smc) { queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; queue_event(smc,EVENT_ECM,EC_CONNECT) ; @@ -565,8 +558,7 @@ /* * duplicate address detected */ -static void rmt_new_dup_actions(smc) -struct s_smc *smc ; +static void rmt_new_dup_actions(struct s_smc *smc) { smc->r.da_flag = TRUE ; smc->r.bn_flag = FALSE ; @@ -591,8 +583,7 @@ /* * leave the ring */ -static void rmt_leave_actions(smc) -struct s_smc *smc ; +static void rmt_leave_actions(struct s_smc *smc) { queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; /* @@ -605,10 +596,7 @@ * SMT timer interface * start RMT timer 0 */ -static void start_rmt_timer0(smc,value,event) -struct s_smc *smc ; -u_long value ; -int event ; +static void start_rmt_timer0(struct s_smc *smc, u_long value, int event) { smc->r.timer0_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event)); @@ -618,10 +606,7 @@ * SMT timer interface * start RMT timer 1 */ -static void start_rmt_timer1(smc,value,event) -struct s_smc *smc ; -u_long value ; -int event ; +static void start_rmt_timer1(struct s_smc *smc, u_long value, int event) { smc->r.timer1_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event)); @@ -631,10 +616,7 @@ * SMT timer interface * start RMT timer 2 */ -static void start_rmt_timer2(smc,value,event) -struct s_smc *smc ; -u_long value ; -int event ; +static void start_rmt_timer2(struct s_smc *smc, u_long value, int event) { smc->r.timer2_exp = FALSE ; /* clear timer event flag */ smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event)); @@ -644,8 +626,7 @@ * SMT timer interface * stop RMT timer 0 */ -static void stop_rmt_timer0(smc) -struct s_smc *smc ; +static void stop_rmt_timer0(struct s_smc *smc) { if (smc->r.rmt_timer0.tm_active) smt_timer_stop(smc,&smc->r.rmt_timer0) ; @@ -655,8 +636,7 @@ * SMT timer interface * stop RMT timer 1 */ -static void stop_rmt_timer1(smc) -struct s_smc *smc ; +static void stop_rmt_timer1(struct s_smc *smc) { if (smc->r.rmt_timer1.tm_active) smt_timer_stop(smc,&smc->r.rmt_timer1) ; @@ -666,9 +646,9 @@ * SMT timer interface * stop RMT timer 2 */ -static void stop_rmt_timer2(smc) -struct s_smc *smc ; +static void stop_rmt_timer2(struct s_smc *smc) { if (smc->r.rmt_timer2.tm_active) smt_timer_stop(smc,&smc->r.rmt_timer2) ; } + diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c --- a/drivers/net/skfp/skfddi.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/skfddi.c 2004-06-20 13:00:23 -07:00 @@ -131,20 +131,10 @@ int frag_count); int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, int la_len); -void smt_timer_poll(struct s_smc *smc); -void ring_status_indication(struct s_smc *smc, u_long status); -unsigned long smt_get_time(void); -void smt_stat_counter(struct s_smc *smc, int stat); -void cfm_state_change(struct s_smc *smc, int c_state); -void ecm_state_change(struct s_smc *smc, int e_state); -void pcm_state_change(struct s_smc *smc, int plc, int p_state); -void rmt_state_change(struct s_smc *smc, int r_state); -void drv_reset_indication(struct s_smc *smc); void dump_data(unsigned char *Data, int length); - // External functions from the hardware module -extern u_int mac_drv_check_space(); +extern u_int mac_drv_check_space(void); extern void read_address(struct s_smc *smc, u_char * mac_addr); extern void card_stop(struct s_smc *smc); extern int mac_drv_init(struct s_smc *smc); @@ -157,9 +147,7 @@ extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys, int len, int frame_status); extern void mac_drv_rx_mode(struct s_smc *smc, int mode); -extern void mac_drv_clear_tx_queue(struct s_smc *smc); extern void mac_drv_clear_rx_queue(struct s_smc *smc); -extern void mac_clear_multicast(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); extern void mac_drv_clear_txd(struct s_smc *smc); @@ -921,8 +909,7 @@ dmi = dev->mc_list; for (i = 0; i < dev->mc_count; i++) { - mac_add_multicast(smc, - dmi->dmi_addr, 1); + mac_add_multicast(smc, dmi->dmi_addr, 1); PRINTK(KERN_INFO "ENABLE MC ADDRESS:"); PRINTK(" %02x %02x %02x ", dmi->dmi_addr[0], diff -Nru a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c --- a/drivers/net/skfp/smt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/skfp/smt.c 2004-06-20 13:00:25 -07:00 @@ -62,68 +62,63 @@ /* * external functions */ -int pcm_status_twisted() ; -void pcm_status_state() ; -int pcm_status_type() ; +int pcm_status_twisted(struct s_smc *smc); -extern SMbuf *smt_get_mbuf() ; - -#define EXPORT_PMF /* * function prototypes */ -u_long smt_get_tid() ; -EXPORT_PMF SMbuf *smt_build_frame() ; -EXPORT_PMF void *sm_to_para() ; #ifdef LITTLE_ENDIAN -static int smt_swap_short() ; +static int smt_swap_short(u_short s); #endif -static int mac_index() ; -static int phy_index() ; -static int mac_con_resource_index() ; -static int phy_con_resource_index() ; -EXPORT_PMF void smt_send_frame() ; -EXPORT_PMF void smt_set_timestamp() ; -static void smt_send_rdf() ; -static void smt_send_nif() ; -static void smt_send_ecf() ; -static void smt_echo_test() ; -static void smt_send_sif_config() ; -static void smt_send_sif_operation() ; -EXPORT_PMF void smt_swap_para() ; +static int mac_index(struct s_smc *smc, int mac); +static int phy_index(struct s_smc *smc, int phy); +static int mac_con_resource_index(struct s_smc *smc, int mac); +static int phy_con_resource_index(struct s_smc *smc, int phy); +static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, + int local); +static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int local); +static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int len); +static void smt_echo_test(struct s_smc *smc, int dna); +static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local); +static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local); #ifdef LITTLE_ENDIAN -static void smt_string_swap() ; +static void smt_string_swap(void); #endif -static void smt_add_frame_len() ; -static void smt_fill_una() ; -static void smt_fill_sde() ; -static void smt_fill_state() ; -static void smt_fill_timestamp() ; -static void smt_fill_policy() ; -static void smt_fill_latency() ; -static void smt_fill_neighbor() ; -static int smt_fill_path() ; -static void smt_fill_mac_status() ; -static void smt_fill_lem() ; -static void smt_fill_version() ; -static void smt_fill_fsc() ; -static void smt_fill_mac_counter() ; -static void smt_fill_mac_fnc() ; -static void smt_fill_manufacturer() ; -static void smt_fill_user() ; -static void smt_fill_setcount() ; -static void smt_fill_echo() ; -int smt_check_para() ; +static void smt_add_frame_len(SMbuf *mb, int len); +static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una); +static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde); +static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state); +static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts); +static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy); +static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency); +static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor); +static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path); +static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st); +static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy); +static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers); +static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc); +static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc); +static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc); +static void smt_fill_manufacturer(struct s_smc *smc, + struct smp_p_manufacturer *man); +static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user); +static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount); +static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, + int len); -void smt_clear_una_dna() ; -static void smt_clear_old_una_dna() ; +void smt_clear_una_dna(struct s_smc *smc); +static void smt_clear_old_una_dna(struct s_smc *smc); #ifdef CONCENTRATOR -static int entity_to_index() ; +static int entity_to_index(void); #endif -static void update_dac() ; -static int div_ratio() ; +static void update_dac(struct s_smc *smc, int report); +static int div_ratio(u_long upper, u_long lower); #ifdef USE_CAN_ADDR -void hwm_conv_can() ; +void hwm_conv_can(struct s_smc *smc, char *data, int len); #else #define hwm_conv_can(smc,data,len) #endif @@ -136,8 +131,7 @@ /* * init SMT agent */ -void smt_agent_init(smc) -struct s_smc *smc ; +void smt_agent_init(struct s_smc *smc) { int i ; @@ -183,17 +177,16 @@ * check tvu & tvd * end */ -void smt_agent_task(smc) -struct s_smc *smc ; +void smt_agent_task(struct s_smc *smc) { smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, EV_TOKEN(EVENT_SMT,SM_TIMER)) ; DB_SMT("SMT agent task\n",0,0) ; } -void smt_please_reconnect(smc,reconn_time) -struct s_smc *smc ; /* Pointer to SMT context */ -int reconn_time ; /* Wait for reconnect time in seconds */ +void smt_please_reconnect(struct s_smc *smc, int reconn_time) +/* struct s_smc *smc; Pointer to SMT context */ +/* int reconn_time; Wait for reconnect time in seconds */ { /* * The please reconnect variable is used as a timer. @@ -210,9 +203,7 @@ } #ifndef SMT_REAL_TOKEN_CT -void smt_emulate_token_ct(smc, mac_index) -struct s_smc *smc; -int mac_index; +void smt_emulate_token_ct(struct s_smc *smc, int mac_index) { u_long count; u_long time; @@ -239,9 +230,7 @@ #endif /*ARGSUSED1*/ -void smt_event(smc,event) -struct s_smc *smc ; -int event ; +void smt_event(struct s_smc *smc, int event) { u_long time ; #ifndef SMT_REAL_TOKEN_CT @@ -457,9 +446,7 @@ EV_TOKEN(EVENT_SMT,SM_TIMER)) ; } -static int div_ratio(upper,lower) -u_long upper ; -u_long lower ; +static int div_ratio(u_long upper, u_long lower) { if ((upper<<16L) < upper) upper = 0xffff0000L ; @@ -475,10 +462,8 @@ /* * receive packet handler */ -void smt_received_pack(smc,mb,fs) -struct s_smc *smc ; -SMbuf *mb ; -int fs ; /* frame status */ +void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs) +/* int fs; frame status */ { struct smt_header *sm ; int local ; @@ -823,9 +808,7 @@ smt_free_mbuf(smc,mb) ; } -static void update_dac(smc,report) -struct s_smc *smc ; -int report ; +static void update_dac(struct s_smc *smc, int report) { int cond ; @@ -843,11 +826,9 @@ * set station ID * send frame */ -EXPORT_PMF void smt_send_frame(smc,mb,fc,local) -struct s_smc *smc ; -SMbuf *mb ; /* buffer to send */ -int fc ; /* FC value */ -int local ; +void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local) +/* SMbuf *mb; buffer to send */ +/* int fc; FC value */ { struct smt_header *sm ; @@ -868,12 +849,11 @@ /* * generate and send RDF */ -static void smt_send_rdf(smc,rej,fc,reason,local) -struct s_smc *smc ; -SMbuf *rej ; /* mbuf of offending frame */ -int fc ; /* FC of denied frame */ -int reason ; /* reason code */ -int local ; +static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, + int local) +/* SMbuf *rej; mbuf of offending frame */ +/* int fc; FC of denied frame */ +/* int reason; reason code */ { SMbuf *mb ; struct smt_header *sm ; /* header of offending frame */ @@ -946,13 +926,12 @@ /* * generate and send NIF */ -static void smt_send_nif(smc,dest,fc,tid,type,local) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -int fc ; /* frame control */ -u_long tid ; /* transaction id */ -int type ; /* frame type */ -int local ; +static void smt_send_nif(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int local) +/* struct fddi_addr *dest; dest address */ +/* int fc; frame control */ +/* u_long tid; transaction id */ +/* int type; frame type */ { struct smt_nif *nif ; SMbuf *mb ; @@ -976,9 +955,7 @@ /* * send NIF request (test purpose) */ -static void smt_send_nif_request(smc,dest) -struct s_smc *smc ; -struct fddi_addr *dest ; +static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest) { smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ; smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST], @@ -988,10 +965,8 @@ /* * send ECF request (test purpose) */ -static void smt_send_ecf_request(smc,dest,len) -struct s_smc *smc ; -struct fddi_addr *dest ; -int len ; +static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest, + int len) { smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ; smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF], @@ -1002,9 +977,7 @@ /* * echo test */ -static void smt_echo_test(smc,dna) -struct s_smc *smc ; -int dna ; +static void smt_echo_test(struct s_smc *smc, int dna) { u_long tid ; @@ -1019,13 +992,13 @@ /* * generate and send ECF */ -static void smt_send_ecf(smc,dest,fc,tid,type,len) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -int fc ; /* frame control */ -u_long tid ; /* transaction id */ -int type ; /* frame type */ -int len ; /* frame length */ +static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, + u_long tid, int type, int len) +/* struct fddi_addr *dest; dest address */ +/* int fc; frame control */ +/* u_long tid; transaction id */ +/* int type; frame type */ +/* int len; frame length */ { struct smt_ecf *ecf ; SMbuf *mb ; @@ -1045,11 +1018,10 @@ * generate and send SIF config response */ -static void smt_send_sif_config(smc,dest,tid,local) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -u_long tid ; /* transaction id */ -int local ; +static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local) +/* struct fddi_addr *dest; dest address */ +/* u_long tid; transaction id */ { struct smt_sif_config *sif ; SMbuf *mb ; @@ -1079,11 +1051,10 @@ * generate and send SIF operation response */ -static void smt_send_sif_operation(smc,dest,tid,local) -struct s_smc *smc ; -struct fddi_addr *dest ; /* dest address */ -u_long tid ; /* transaction id */ -int local ; +static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, + u_long tid, int local) +/* struct fddi_addr *dest; dest address */ +/* u_long tid; transaction id */ { struct smt_sif_operation *sif ; SMbuf *mb ; @@ -1128,11 +1099,8 @@ /* * get and initialize SMT frame */ -EXPORT_PMF SMbuf *smt_build_frame(smc,class,type,length) -struct s_smc *smc ; -int class ; -int type ; -int length ; +SMbuf *smt_build_frame(struct s_smc *smc, int class, int type, + int length) { SMbuf *mb ; struct smt_header *smt ; @@ -1167,9 +1135,7 @@ return(mb) ; } -static void smt_add_frame_len(mb,len) -SMbuf *mb ; -int len ; +static void smt_add_frame_len(SMbuf *mb, int len) { struct smt_header *smt ; @@ -1183,9 +1149,7 @@ /* * fill values in UNA parameter */ -static void smt_fill_una(smc,una) -struct s_smc *smc ; -struct smt_p_una *una ; +static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una) { SMTSETPARA(una,SMT_P_UNA) ; una->una_pad = 0 ; @@ -1195,9 +1159,7 @@ /* * fill values in SDE parameter */ -static void smt_fill_sde(smc,sde) -struct s_smc *smc ; -struct smt_p_sde *sde ; +static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde) { SMTSETPARA(sde,SMT_P_SDE) ; sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ; @@ -1213,9 +1175,7 @@ /* * fill in values in station state parameter */ -static void smt_fill_state(smc,state) -struct s_smc *smc ; -struct smt_p_state *state ; +static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state) { int top ; int twist ; @@ -1255,18 +1215,14 @@ /* * fill values in timestamp parameter */ -static void smt_fill_timestamp(smc,ts) -struct s_smc *smc ; -struct smt_p_timestamp *ts ; +static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts) { SMTSETPARA(ts,SMT_P_TIMESTAMP) ; smt_set_timestamp(smc,ts->ts_time) ; } -EXPORT_PMF void smt_set_timestamp(smc,p) -struct s_smc *smc ; -u_char *p ; +void smt_set_timestamp(struct s_smc *smc, u_char *p) { u_long time ; u_long utime ; @@ -1300,9 +1256,7 @@ /* * fill values in station policy parameter */ -static void smt_fill_policy(smc,policy) -struct s_smc *smc ; -struct smt_p_policy *policy ; +static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy) { int i ; u_char *map ; @@ -1333,9 +1287,7 @@ /* * fill values in latency equivalent parameter */ -static void smt_fill_latency(smc,latency) -struct s_smc *smc ; -struct smt_p_latency *latency ; +static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency) { SMTSETPARA(latency,SMT_P_LATENCY) ; @@ -1358,9 +1310,7 @@ /* * fill values in MAC neighbors parameter */ -static void smt_fill_neighbor(smc,neighbor) -struct s_smc *smc ; -struct smt_p_neighbor *neighbor ; +static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor) { SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ; @@ -1379,9 +1329,7 @@ #define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2) #endif -static int smt_fill_path(smc,path) -struct s_smc *smc ; -struct smt_p_path *path ; +static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path) { SK_LOC_DECL(int,type) ; SK_LOC_DECL(int,state) ; @@ -1429,9 +1377,7 @@ /* * fill values in mac status */ -static void smt_fill_mac_status(smc,st) -struct s_smc *smc ; -struct smt_p_mac_status *st ; +static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st) { SMTSETPARA(st,SMT_P_MAC_STATUS) ; @@ -1458,11 +1404,7 @@ /* * fill values in LEM status */ - -static void smt_fill_lem(smc,lem,phy) -struct s_smc *smc ; -struct smt_p_lem *lem ; -int phy ; +static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy) { struct fddi_mib_p *mib ; @@ -1484,9 +1426,7 @@ /* * fill version parameter */ -static void smt_fill_version(smc,vers) -struct s_smc *smc ; -struct smt_p_version *vers ; +static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers) { SK_UNUSED(smc) ; SMTSETPARA(vers,SMT_P_VERSION) ; @@ -1505,9 +1445,7 @@ * note: this para 200B is NOT in swap table, because it's also set in * PMF add_para */ -static void smt_fill_fsc(smc,fsc) -struct s_smc *smc ; -struct smt_p_fsc *fsc ; +static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc) { SK_UNUSED(smc) ; SMTSETPARA(fsc,SMT_P_FSC) ; @@ -1527,9 +1465,7 @@ /* * fill mac counter field */ -static void smt_fill_mac_counter(smc,mc) -struct s_smc *smc ; -struct smt_p_mac_counter *mc ; +static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc) { SMTSETPARA(mc,SMT_P_MAC_COUNTER) ; mc->mc_mib_index = INDEX_MAC ; @@ -1541,9 +1477,7 @@ /* * fill mac frame not copied counter */ -static void smt_fill_mac_fnc(smc,fnc) -struct s_smc *smc ; -struct smt_p_mac_fnc *fnc ; +static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc) { SMTSETPARA(fnc,SMT_P_MAC_FNC) ; fnc->nc_mib_index = INDEX_MAC ; @@ -1555,9 +1489,8 @@ /* * fill manufacturer field */ -static void smt_fill_manufacturer(smc,man) -struct s_smc *smc ; -struct smp_p_manufacturer *man ; +static void smt_fill_manufacturer(struct s_smc *smc, + struct smp_p_manufacturer *man) { SMTSETPARA(man,SMT_P_MANUFACTURER) ; memcpy((char *) man->mf_data, @@ -1568,9 +1501,7 @@ /* * fill user field */ -static void smt_fill_user(smc,user) -struct s_smc *smc ; -struct smp_p_user *user ; +static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user) { SMTSETPARA(user,SMT_P_USER) ; memcpy((char *) user->us_data, @@ -1578,14 +1509,10 @@ sizeof(user->us_data)) ; } - - /* * fill set count */ -static void smt_fill_setcount(smc,setcount) -struct s_smc *smc ; -struct smt_p_setcount *setcount ; +static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount) { SK_UNUSED(smc) ; SMTSETPARA(setcount,SMT_P_SETCOUNT) ; @@ -1597,13 +1524,9 @@ /* * fill echo data */ -static void smt_fill_echo(smc,echo,seed,len) -struct s_smc *smc ; -struct smt_p_echo *echo ; -u_long seed ; -int len ; +static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, + int len) { - u_char *p ; SK_UNUSED(smc) ; @@ -1619,22 +1542,19 @@ * clear DNA and UNA * called from CFM if configuration changes */ -void smt_clear_una_dna(smc) -struct s_smc *smc ; +void smt_clear_una_dna(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; } -static void smt_clear_old_una_dna(smc) -struct s_smc *smc ; +static void smt_clear_old_una_dna(struct s_smc *smc) { smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ; smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ; } -u_long smt_get_tid(smc) -struct s_smc *smc ; +u_long smt_get_tid(struct s_smc *smc) { u_long tid ; while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0) @@ -1723,10 +1643,8 @@ #define N_SMT_PLEN (sizeof(smt_pdef)/sizeof(smt_pdef[0])) -int smt_check_para(smc,sm,list) -struct s_smc *smc ; -struct smt_header *sm ; -const u_short list[] ; +int smt_check_para(struct s_smc *smc, struct smt_header *sm, + const u_short list[]) { const u_short *p = list ; while (*p) { @@ -1739,10 +1657,7 @@ return(0) ; } -EXPORT_PMF void *sm_to_para(smc,sm,para) -struct s_smc *smc ; -struct smt_header *sm ; -int para ; +void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para) { char *p ; int len ; @@ -1773,9 +1688,7 @@ return(0) ; } -int is_my_addr(smc,addr) -struct s_smc *smc ; -struct fddi_addr *addr ; +int is_my_addr(struct s_smc *smc, struct fddi_addr *addr) { return(*(short *)(&addr->a[0]) == *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0]) @@ -1785,31 +1698,26 @@ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ; } -int is_zero(addr) -struct fddi_addr *addr ; +int is_zero(struct fddi_addr *addr) { return(*(short *)(&addr->a[0]) == 0 && *(short *)(&addr->a[2]) == 0 && *(short *)(&addr->a[4]) == 0 ) ; } -int is_broadcast(addr) -struct fddi_addr *addr ; +int is_broadcast(struct fddi_addr *addr) { return(*(u_short *)(&addr->a[0]) == 0xffff && *(u_short *)(&addr->a[2]) == 0xffff && *(u_short *)(&addr->a[4]) == 0xffff ) ; } -int is_individual(addr) -struct fddi_addr *addr ; +int is_individual(struct fddi_addr *addr) { return(!(addr->a[0] & GROUP_ADDR)) ; } -int is_equal(addr1,addr2) -struct fddi_addr *addr1 ; -struct fddi_addr *addr2 ; +int is_equal(struct fddi_addr *addr1, struct fddi_addr *addr2) { return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) && *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) && @@ -1821,9 +1729,7 @@ /* * send ANTC data test frame */ -void fddi_send_antc(smc,dest) -struct s_smc *smc ; -struct fddi_addr *dest ; +void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest) { SK_UNUSED(smc) ; SK_UNUSED(dest) ; @@ -1850,8 +1756,7 @@ #ifdef DEBUG #define hextoasc(x) "0123456789abcdef"[x] -char *addr_to_string(addr) -struct fddi_addr *addr ; +char *addr_to_string(struct fddi_addr *addr) { int i ; static char string[6*3] = "****" ; @@ -1867,9 +1772,7 @@ #endif #ifdef AM29K -smt_ifconfig(argc,argv) -int argc ; -char *argv[] ; +smt_ifconfig(int argc, char *argv[]) { if (argc >= 2 && !strcmp(argv[0],"opt_bypass") && !strcmp(argv[1],"yes")) { @@ -1883,9 +1786,7 @@ /* * return static mac index */ -static int mac_index(smc,mac) -struct s_smc *smc ; -int mac ; +static int mac_index(struct s_smc *smc, int mac) { SK_UNUSED(mac) ; #ifdef CONCENTRATOR @@ -1899,9 +1800,7 @@ /* * return static phy index */ -static int phy_index(smc,phy) -struct s_smc *smc ; -int phy ; +static int phy_index(struct s_smc *smc, int phy) { SK_UNUSED(smc) ; return(phy+1); @@ -1910,9 +1809,7 @@ /* * return dynamic mac connection resource index */ -static int mac_con_resource_index(smc,mac) -struct s_smc *smc ; -int mac ; +static int mac_con_resource_index(struct s_smc *smc, int mac) { #ifdef CONCENTRATOR SK_UNUSED(smc) ; @@ -1936,9 +1833,7 @@ /* * return dynamic phy connection resource index */ -static int phy_con_resource_index(smc,phy) -struct s_smc *smc ; -int phy ; +static int phy_con_resource_index(struct s_smc *smc, int phy) { #ifdef CONCENTRATOR return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_PHY(phy)))) ; @@ -1960,9 +1855,7 @@ } #ifdef CONCENTRATOR -static int entity_to_index(smc,e) -struct s_smc *smc ; -int e ; +static int entity_to_index(struct s_smc *smc, int e) { if (e == ENTITY_MAC) return(mac_index(smc,1)) ; @@ -1972,16 +1865,13 @@ #endif #ifdef LITTLE_ENDIAN -static int smt_swap_short(s) -u_short s ; +static int smt_swap_short(u_short s) { return(((s>>8)&0xff)|((s&0xff)<<8)) ; } -void smt_swap_para(sm,len,direction) -struct smt_header *sm ; -int len ; -int direction ; /* 0 encode 1 decode */ +void smt_swap_para(struct smt_header *sm, int len, int direction) +/* int direction; 0 encode 1 decode */ { struct smt_para *pa ; const struct smt_pdef *pd ; @@ -2027,10 +1917,7 @@ } } -static void smt_string_swap(data,format,len) -char *data ; -const char *format ; -int len ; +static void smt_string_swap(char *data, const char *format, int len) { const char *open_paren = 0 ; int x ; @@ -2081,10 +1968,8 @@ } } #else -void smt_swap_para(sm,len,direction) -struct smt_header *sm ; -int len ; -int direction ; /* 0 encode 1 decode */ +void smt_swap_para(struct smt_header *sm, int len, int direction) +/* int direction; 0 encode 1 decode */ { SK_UNUSED(sm) ; SK_UNUSED(len) ; @@ -2095,11 +1980,7 @@ /* * PMF actions */ -int smt_action(smc,class,code,index) -struct s_smc *smc ; -int class ; -int code ; -int index ; +int smt_action(struct s_smc *smc, int class, int code, int index) { int event ; int port ; @@ -2190,9 +2071,7 @@ * set reconnect * end */ -void smt_change_t_neg(smc,tneg) -struct s_smc *smc ; -u_long tneg ; +void smt_change_t_neg(struct s_smc *smc, u_long tneg) { smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ; @@ -2207,10 +2086,7 @@ * canonical conversion of bytes beginning form *data */ #ifdef USE_CAN_ADDR -void hwm_conv_can(smc,data,len) -struct s_smc *smc ; -char *data ; -int len ; +void hwm_conv_can(struct s_smc *smc, char *data, int len) { int i ; @@ -2223,3 +2099,4 @@ #endif #endif /* no SLIM_SMT */ + diff -Nru a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c --- a/drivers/net/skfp/smtdef.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/smtdef.c 2004-06-20 13:00:23 -07:00 @@ -72,13 +72,11 @@ #define DEFAULT_LCT_EXTEND 50 /* Forward declarations */ -extern void smt_reset_defaults (); -static void smt_init_mib (); +void smt_reset_defaults(struct s_smc *smc, int level); +static void smt_init_mib(struct s_smc *smc, int level); +static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper); -static int set_min_max() ; - -void smt_set_defaults(smc) -struct s_smc *smc ; +void smt_set_defaults(struct s_smc *smc) { smt_reset_defaults(smc,0) ; } @@ -86,9 +84,7 @@ #define MS2BCLK(x) ((x)*12500L) #define US2BCLK(x) ((x)*1250L) -void smt_reset_defaults(smc,level) -struct s_smc *smc ; -int level ; +void smt_reset_defaults(struct s_smc *smc, int level) { struct smt_config *smt ; int i ; @@ -170,9 +166,7 @@ /* 01234567890123456789012345678901 */ "xxxSK-NET FDDI SMT 7.3 - V2.8.8" ; -static void smt_init_mib(smc,level) -struct s_smc *smc ; -int level ; +static void smt_init_mib(struct s_smc *smc, int level) { struct fddi_mib *mib ; struct fddi_mib_p *pm ; @@ -292,8 +286,7 @@ (void) smt_set_mac_opvalues(smc) ; } -int smt_set_mac_opvalues(smc) -struct s_smc *smc ; +int smt_set_mac_opvalues(struct s_smc *smc) { int st ; int st2 ; @@ -318,8 +311,7 @@ return(st) ; } -void smt_fixup_mib(smc) -struct s_smc *smc ; +void smt_fixup_mib(struct s_smc *smc) { #ifdef CONCENTRATOR switch (smc->s.sas) { @@ -355,11 +347,7 @@ * use mib * NOTE : numbers are negative, negate comparison ! */ -static int set_min_max(maxflag,mib,limit,oper) -int maxflag ; -u_long mib ; -u_long limit ; -u_long *oper ; +static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper) { u_long old ; old = *oper ; @@ -369,3 +357,4 @@ *oper = mib ; return(old != *oper) ; } + diff -Nru a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c --- a/drivers/net/skfp/smtinit.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/skfp/smtinit.c 2004-06-20 13:00:25 -07:00 @@ -27,7 +27,7 @@ static const char ID_sccs[] = "@(#)smtinit.c 1.15 97/05/06 (C) SK " ; #endif -extern void init_fddi_driver() ; +void init_fddi_driver(struct s_smc *smc, u_char *mac_addr); /* define global debug variable */ #if defined(DEBUG) && !defined(DEBUG_BRD) @@ -48,8 +48,7 @@ * Can not be called in smt_reset_defaults, because it is not sure that * the OEM ID is already defined. */ -static void set_oem_spec_val(smc) -struct s_smc *smc ; +static void set_oem_spec_val(struct s_smc *smc) { struct fddi_mib *mib ; @@ -66,9 +65,8 @@ /* * Init SMT */ -int init_smt(smc,mac_addr) -struct s_smc *smc ; -u_char *mac_addr ; /* canonical address or NULL */ +int init_smt(struct s_smc *smc, u_char *mac_addr) +/* u_char *mac_addr; canonical address or NULL */ { int p ; @@ -124,3 +122,4 @@ return(0) ; } + diff -Nru a/drivers/net/skfp/smtparse.c b/drivers/net/skfp/smtparse.c --- a/drivers/net/skfp/smtparse.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/skfp/smtparse.c 2004-06-20 13:00:25 -07:00 @@ -82,8 +82,9 @@ /* * local function declarations */ -static u_long parse_num() ; -static int parse_word() ; +static u_long parse_num(int type, char _far *value, char *v, u_long mn, + u_long mx, int scale); +static int parse_word(char *buf, char _far *text); #ifdef SIM #define DB_MAIN(a,b,c) printf(a,b,c) @@ -117,11 +118,8 @@ * * END_MANUAL_ENTRY() */ -int smt_parse_arg(smc,keyword,type,value) -struct s_smc *smc ; -char _far *keyword ; -int type ; -char _far *value ; +int smt_parse_arg(struct s_smc *smc, char _far *keyword, int type, + char _far *value) { char keybuf[MAX_VAL+1]; char valbuf[MAX_VAL+1]; @@ -287,9 +285,7 @@ return(0) ; } -static int parse_word(buf,text) -char *buf ; -char _far *text ; +static int parse_word(char *buf, char _far *text) { char c ; char *p ; @@ -364,13 +360,8 @@ return(0) ; } -static u_long parse_num(type,value,v,mn,mx,scale) -int type ; -char _far *value ; -char *v ; -u_long mn ; -u_long mx ; -int scale ; +static u_long parse_num(int type, char _far *value, char *v, u_long mn, + u_long mx, int scale) { u_long x = 0 ; char c ; @@ -473,3 +464,4 @@ exit(0) ; } #endif + diff -Nru a/drivers/net/skfp/smttimer.c b/drivers/net/skfp/smttimer.c --- a/drivers/net/skfp/smttimer.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/skfp/smttimer.c 2004-06-20 13:00:23 -07:00 @@ -26,18 +26,9 @@ static const char ID_sccs[] = "@(#)smttimer.c 2.4 97/08/04 (C) SK " ; #endif -/* - * external function declarations - */ -extern u_long hwt_read() ; -extern void hwt_stop() ; -extern void hwt_start() ; +static void timer_done(struct s_smc *smc, int restart); -static void timer_done() ; - - -void smt_timer_init(smc) -struct s_smc *smc ; +void smt_timer_init(struct s_smc *smc) { smc->t.st_queue = 0 ; smc->t.st_fast.tm_active = FALSE ; @@ -45,9 +36,7 @@ hwt_init(smc) ; } -void smt_timer_stop(smc,timer) -struct s_smc *smc ; -struct smt_timer *timer ; +void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer) { struct smt_timer **prev ; struct smt_timer *tm ; @@ -70,11 +59,8 @@ } } -void smt_timer_start(smc,timer,time,token) -struct s_smc *smc ; -struct smt_timer *timer ; -u_long time ; -u_long token ; +void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time, + u_long token) { struct smt_timer **prev ; struct smt_timer *tm ; @@ -121,21 +107,17 @@ hwt_start(smc,smc->t.st_queue->tm_delta) ; } -void smt_force_irq(smc) -struct s_smc *smc ; +void smt_force_irq(struct s_smc *smc) { smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); } -void smt_timer_done(smc) -struct s_smc *smc ; +void smt_timer_done(struct s_smc *smc) { timer_done(smc,1) ; } -static void timer_done(smc,restart) -struct s_smc *smc ; -int restart ; +static void timer_done(struct s_smc *smc, int restart) { u_long delta ; struct smt_timer *tm ; @@ -171,3 +153,4 @@ if (restart && smc->t.st_queue) hwt_start(smc,smc->t.st_queue->tm_delta) ; } + diff -Nru a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c --- a/drivers/net/skfp/srf.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/skfp/srf.c 2004-06-20 13:00:24 -07:00 @@ -38,10 +38,10 @@ /* * function declarations */ -static void clear_all_rep() ; -static void clear_reported() ; -static void smt_send_srf() ; -static struct s_srf_evc *smt_get_evc() ; +static void clear_all_rep(struct s_smc *smc); +static void clear_reported(struct s_smc *smc); +static void smt_send_srf(struct s_smc *smc); +static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index); #define MAX_EVCS (sizeof(smc->evcs)/sizeof(smc->evcs[0])) @@ -69,8 +69,7 @@ #define MAX_INIT_EVC (sizeof(evc_inits)/sizeof(evc_inits[0])) -void smt_init_evc(smc) -struct s_smc *smc ; +void smt_init_evc(struct s_smc *smc) { struct s_srf_evc *evc ; const struct evc_init *init ; @@ -159,10 +158,7 @@ smc->srf.sr_state = SR0_WAIT ; } -static struct s_srf_evc *smt_get_evc(smc,code,index) -struct s_smc *smc ; -int code ; -int index ; +static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index) { int i ; struct s_srf_evc *evc ; @@ -188,11 +184,7 @@ } ; #endif -void smt_srf_event(smc,code,index,cond) -struct s_smc *smc ; -int code ; -int index ; -int cond ; +void smt_srf_event(struct s_smc *smc, int code, int index, int cond) { struct s_srf_evc *evc ; int cond_asserted = 0 ; @@ -340,8 +332,7 @@ } } -static void clear_all_rep(smc) -struct s_smc *smc ; +static void clear_all_rep(struct s_smc *smc) { struct s_srf_evc *evc ; int i ; @@ -354,8 +345,7 @@ smc->srf.any_report = FALSE ; } -static void clear_reported(smc) -struct s_smc *smc ; +static void clear_reported(struct s_smc *smc) { struct s_srf_evc *evc ; int i ; @@ -375,13 +365,10 @@ } } -extern SMbuf *smt_build_frame() ; - /* * build and send SMT SRF frame */ -static void smt_send_srf(smc) -struct s_smc *smc ; +static void smt_send_srf(struct s_smc *smc) { struct smt_header *smt ; @@ -439,3 +426,4 @@ #endif /* no BOOT */ #endif /* no SLIM_SMT */ + diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c --- a/drivers/net/smc-mca.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/smc-mca.c 2004-06-20 13:00:23 -07:00 @@ -51,6 +51,8 @@ #include "8390.h" #include "smc-mca.h" +#define DRV_NAME "smc-mca" + static int ultramca_open(struct net_device *dev); static void ultramca_reset_8390(struct net_device *dev); static void ultramca_get_8390_hdr(struct net_device *dev, @@ -265,7 +267,7 @@ goto err_unclaim; } - if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) { rc = -ENODEV; goto err_unclaim; } diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c --- a/drivers/net/smc-ultra.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/smc-ultra.c 2004-06-20 13:00:23 -07:00 @@ -72,6 +72,8 @@ #include "8390.h" +#define DRV_NAME "smc-ultra" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int ultra_portlist[] __initdata = {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0}; @@ -178,6 +180,7 @@ release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ultra_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -202,6 +205,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ultra_probe1(struct net_device *dev, int ioaddr) { @@ -215,7 +219,7 @@ unsigned char idreg = inb(ioaddr + 7); unsigned char reg4 = inb(ioaddr + 4) & 0x7f; - if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) return -EBUSY; /* Check the ID nibble. */ diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c --- a/drivers/net/smc-ultra32.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/smc-ultra32.c 2004-06-20 13:00:25 -07:00 @@ -61,6 +61,8 @@ #include "8390.h" +#define DRV_NAME "smc-ultra32" + static int ultra32_probe1(struct net_device *dev, int ioaddr); static int ultra32_open(struct net_device *dev); static void ultra32_reset_8390(struct net_device *dev); @@ -163,7 +165,7 @@ unsigned char reg4; const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; - if (!request_region(ioaddr, ULTRA32_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME)) return -EBUSY; if (inb(ioaddr + ULTRA32_IDPORT) == 0xff || diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c --- a/drivers/net/smc9194.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/smc9194.c 2004-06-20 13:00:25 -07:00 @@ -78,6 +78,8 @@ #include "smc9194.h" +#define DRV_NAME "smc9194" + /*------------------------------------------------------------------------ . . Configuration options, for the experienced user to change. @@ -94,16 +96,51 @@ #define USE_32_BIT 1 #endif +#if defined(__H8300H__) || defined(__H8300S__) +#define NO_AUTOPROBE +#undef insl +#undef outsl +#define insl(a,b,l) io_insl_noswap(a,b,l) +#define outsl(a,b,l) io_outsl_noswap(a,b,l) +#endif + /* .the SMC9194 can be at any of the following port addresses. To change, .for a slightly different card, you can add it to the array. Keep in .mind that the array must end in zero. */ -static unsigned int smc_portlist[] __initdata = { - 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, - 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0 + +struct devlist { + unsigned int port; + unsigned int irq; }; +#if defined(CONFIG_H8S_EDOSK2674) +static struct devlist smc_devlist[] __initdata = { + {.port = 0xf80000, .irq = 16}, + {.port = 0, .irq = 0 }, +}; +#else +static struct devlist smc_devlist[] __initdata = { + {.port = 0x200, .irq = 0}, + {.port = 0x220, .irq = 0}, + {.port = 0x240, .irq = 0}, + {.port = 0x260, .irq = 0}, + {.port = 0x280, .irq = 0}, + {.port = 0x2A0, .irq = 0}, + {.port = 0x2C0, .irq = 0}, + {.port = 0x2E0, .irq = 0}, + {.port = 0x300, .irq = 0}, + {.port = 0x320, .irq = 0}, + {.port = 0x340, .irq = 0}, + {.port = 0x360, .irq = 0}, + {.port = 0x380, .irq = 0}, + {.port = 0x3A0, .irq = 0}, + {.port = 0x3C0, .irq = 0}, + {.port = 0x3E0, .irq = 0}, + {.port = 0, .irq = 0}, +}; +#endif /* . Wait time for memory to be free. This probably shouldn't be . tuned that much, as waiting for this means nothing else happens @@ -466,7 +503,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev ) { struct smc_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; + unsigned int ioaddr = dev->base_addr; word length; unsigned short numPages; word time_out; @@ -580,7 +617,7 @@ byte packet_no; struct sk_buff * skb = lp->saved_skb; word length; - unsigned short ioaddr; + unsigned int ioaddr; byte * buf; ioaddr = dev->base_addr; @@ -635,7 +672,11 @@ #ifdef USE_32_BIT if ( length & 0x2 ) { outsl(ioaddr + DATA_1, buf, length >> 2 ); +#if !defined(__H8300H__) && !defined(__H8300S__) outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); +#else + ctrl_outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); +#endif } else outsl(ioaddr + DATA_1, buf, length >> 2 ); @@ -691,9 +732,12 @@ struct net_device * __init smc_init(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct smc_local)); - unsigned *port; + static struct devlist *smcdev = smc_devlist; int err = 0; +#ifndef NO_AUTOPROBE + smcdev = smc_devlist; +#endif if (!dev) return ERR_PTR(-ENODEV); @@ -711,11 +755,11 @@ } else if (io != 0) { /* Don't probe at all. */ err = -ENXIO; } else { - for (port = smc_portlist; *port; port++) { - if (smc_probe(dev, *port) == 0) + for (;smcdev->port; smcdev++) { + if (smc_probe(dev, smcdev->port) == 0) break; } - if (!*port) + if (!smcdev->port) err = -ENODEV; } if (err) @@ -741,6 +785,7 @@ */ int __init smc_findirq( int ioaddr ) { +#ifndef NO_AUTOPROBE int timeout = 20; unsigned long cookie; @@ -795,6 +840,14 @@ /* and return what I found */ return probe_irq_off(cookie); +#else /* NO_AUTOPROBE */ + struct devlist *smcdev; + for (smcdev = smc_devlist; smcdev->port; smcdev++) { + if (smcdev->port == ioaddr) + return smcdev->irq; + } + return 0; +#endif } /*---------------------------------------------------------------------- @@ -843,7 +896,7 @@ word memory_cfg_register; /* Grab the region so that no one else tries to probe our ioports. */ - if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, SMC_IO_EXTENT, DRV_NAME)) return -EBUSY; dev->irq = irq; @@ -863,6 +916,7 @@ retval = -ENODEV; goto err_out; } +#if !defined(CONFIG_H8S_EDOSK2674) /* well, we've already written once, so hopefully another time won't hurt. This time, I need to switch the bank register to bank 1, so I can access the base address register */ @@ -877,6 +931,10 @@ retval = -ENODEV; goto err_out; } +#else + (void)base_address_register; /* Warning suppression */ +#endif + /* check if the revision register is something that I recognize. These might need to be added to later, as future revisions @@ -1001,9 +1059,9 @@ memset(dev->priv, 0, sizeof(struct smc_local)); /* Grab the IRQ */ - retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, &smc_interrupt, 0, DRV_NAME, dev); if (retval) { - printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, + printk("%s: unable to get IRQ %d (irqval=%d).\n", DRV_NAME, dev->irq, retval); goto err_out; } diff -Nru a/drivers/net/starfire.c b/drivers/net/starfire.c --- a/drivers/net/starfire.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/starfire.c 2004-06-20 13:00:26 -07:00 @@ -880,7 +880,7 @@ irq = pdev->irq; - if (pci_request_regions (pdev, dev->name)) { + if (pci_request_regions (pdev, DRV_NAME)) { printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx); goto err_out_free_netdev; } diff -Nru a/drivers/net/stnic.c b/drivers/net/stnic.c --- a/drivers/net/stnic.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/stnic.c 2004-06-20 13:00:25 -07:00 @@ -28,6 +28,8 @@ #include "8390.h" +#define DRV_NAME "stnic" + #define byte unsigned char #define half unsigned short #define word unsigned int @@ -130,7 +132,7 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - err = request_irq (dev->irq, ei_interrupt, 0, dev->name, dev); + err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (err) { printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq); free_netdev(dev); diff -Nru a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c --- a/drivers/net/sun3_82586.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/sun3_82586.c 2004-06-20 13:00:24 -07:00 @@ -53,6 +53,8 @@ #include "sun3_82586.h" +#define DRV_NAME "sun3_82586" + #define DEBUG /* debug on */ #define SYSBUSVAL 0 /* 16 Bit */ #define SUN3_82586_TOTAL_SIZE PAGE_SIZE @@ -336,7 +338,7 @@ { int i, size, retval; - if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, dev->name)) + if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, DRV_NAME)) return -EBUSY; /* copy in the ethernet address from the prom */ diff -Nru a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c --- a/drivers/net/sun3lance.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/sun3lance.c 2004-06-20 13:00:25 -07:00 @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/sungem.c 2004-06-20 13:00:26 -07:00 @@ -2717,7 +2717,7 @@ gp = dev->priv; - err = pci_request_regions(pdev, dev->name); + err = pci_request_regions(pdev, DRV_NAME); if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources, " "aborting.\n"); diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c --- a/drivers/net/sunhme.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/sunhme.c 2004-06-20 13:00:24 -07:00 @@ -68,6 +68,8 @@ #include "sunhme.h" +#define DRV_NAME "sunhme" + static int macaddr[6]; /* accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */ @@ -2920,7 +2922,8 @@ struct list_head *tmp; int n_hmes; - if (busdev->vendor != PCI_VENDOR_ID_DEC || + if (busdev == NULL || + busdev->vendor != PCI_VENDOR_ID_DEC || busdev->device != PCI_DEVICE_ID_DEC_21153) return 0; @@ -3085,7 +3088,7 @@ printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n"); goto err_out_clear_quattro; } - if (pci_request_regions(pdev, dev->name)) { + if (pci_request_regions(pdev, DRV_NAME)) { printk(KERN_ERR "happymeal(PCI): Cannot obtain PCI resources, " "aborting.\n"); goto err_out_clear_quattro; diff -Nru a/drivers/net/tc35815.c b/drivers/net/tc35815.c --- a/drivers/net/tc35815.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/tc35815.c 2004-06-20 13:00:23 -07:00 @@ -1717,7 +1717,7 @@ } static struct pci_driver tc35815_driver = { - .name =TC35815_MODULE_NAME, + .name = TC35815_MODULE_NAME, .probe = tc35815_probe, .remove = NULL, .id_table = tc35815_pci_tbl, diff -Nru a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig --- a/drivers/net/tulip/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/tulip/Kconfig 2004-06-20 13:00:25 -07:00 @@ -71,10 +71,17 @@ config TULIP_NAPI bool "Use NAPI RX polling " depends on TULIP - ---help--- - This is of useful for servers and routers dealing with high network loads. - - See . + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. If in doubt, say N. diff -Nru a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c --- a/drivers/net/tulip/winbond-840.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/tulip/winbond-840.c 2004-06-20 13:00:23 -07:00 @@ -1292,14 +1292,8 @@ pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); - /* Call copy + cksum if available. */ -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail, - pkt_len); -#endif pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c --- a/drivers/net/via-rhine.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/via-rhine.c 2004-06-20 13:00:26 -07:00 @@ -354,59 +354,46 @@ second only the 1234 card. */ -enum pci_flags_bit { - PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, - PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +enum rhine_revs { + VT86C100A = 0x00, + VT6102 = 0x40, + VT8231 = 0x50, /* Integrated MAC */ + VT8233 = 0x60, /* Integrated MAC */ + VT8235 = 0x74, /* Integrated MAC */ + VT8237 = 0x78, /* Integrated MAC */ + VTunknown0 = 0x7C, + VT6105 = 0x80, + VT6105_B0 = 0x83, + VT6105L = 0x8A, + VT6107 = 0x8C, + VTunknown1 = 0x8E, + VT6105M = 0x90, }; -enum rhine_chips { - VT86C100A = 0, - VT6102, - VT6105, - VT6105M -}; - -struct rhine_chip_info { - const char *name; - u16 pci_flags; - int io_size; - int drv_flags; -}; - - -enum chip_capability_flags { - CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4, - ReqTxAlign=0x10, HasWOL=0x20, +enum rhine_quirks { + rqWOL = 0x0001, /* Wake-On-LAN support */ + rqForceReset = 0x0002, + rqDavicomPhy = 0x0020, + rq6patterns = 0x0040, /* 6 instead of 4 patterns for WOL */ + rqStatusWBRace = 0x0080, /* Tx Status Writeback Error possible */ + rqRhineI = 0x0100, /* See comment below */ }; +/* + * rqRhineI: VT86C100A (aka Rhine-I) uses different bits to enable + * MMIO as well as for the collision counter and the Tx FIFO underflow + * indicator. In addition, Tx and Rx buffers need to 4 byte aligned. + */ -#ifdef USE_MMIO -#define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR1) -#else -#define RHINE_IOTYPE (PCI_USES_IO | PCI_USES_MASTER | PCI_ADDR0) -#endif /* Beware of PCI posted writes */ #define IOSYNC do { readb(dev->base_addr + StationAddr); } while (0) -/* directly indexed by enum rhine_chips, above */ -static struct rhine_chip_info rhine_chip_info[] __devinitdata = -{ - { "VIA VT86C100A Rhine", RHINE_IOTYPE, 128, - CanHaveMII | ReqTxAlign | HasDavicomPhy }, - { "VIA VT6102 Rhine-II", RHINE_IOTYPE, 256, - CanHaveMII | HasWOL }, - { "VIA VT6105 Rhine-III", RHINE_IOTYPE, 256, - CanHaveMII | HasWOL }, - { "VIA VT6105M Rhine-III", RHINE_IOTYPE, 256, - CanHaveMII | HasWOL }, -}; - static struct pci_device_id rhine_pci_tbl[] = { - {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A}, - {0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6102}, - {0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105}, /* 6105{,L,LOM} */ - {0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105M}, - {0,} /* terminate list */ + {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */ + {0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */ + {0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */ + {0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */ + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, rhine_pci_tbl); @@ -421,8 +408,10 @@ MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74, ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B, RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81, - StickyHW=0x83, IntrStatus2=0x84, WOLcrClr=0xA4, WOLcgClr=0xA7, - PwrcsrClr=0xAC, + StickyHW=0x83, IntrStatus2=0x84, + WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6, + WOLcgClr=0xA7, + PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD, }; /* Bits in ConfigD */ @@ -514,7 +503,7 @@ spinlock_t lock; /* Frequently used values: keep some adjacent for cache effect. */ - int chip_id, drv_flags; + u32 quirks; struct rx_desc *rx_head_desc; unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; @@ -522,7 +511,6 @@ u16 chip_cmd; /* Current setting for ChipCmd */ /* These values are keep track of the transceiver/media in use. */ - unsigned int default_port:4; /* Last dev->if_port value. */ u8 tx_thresh, rx_thresh; /* MII transceiver section. */ @@ -557,12 +545,41 @@ intr_status = readw(ioaddr + IntrStatus); /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ - if (rp->chip_id == VT6102) + if (rp->quirks & rqStatusWBRace) intr_status |= readb(ioaddr + IntrStatus2) << 16; return intr_status; } -static void wait_for_reset(struct net_device *dev, int chip_id, char *name) +/* + * Get power related registers into sane state. + * Returns content of power-event (WOL) registers. + */ +static void rhine_power_init(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + struct rhine_private *rp = netdev_priv(dev); + + if (rp->quirks & rqWOL) { + /* Make sure chip is in power state D0 */ + writeb(readb(ioaddr + StickyHW) & 0xFC, ioaddr + StickyHW); + + /* Disable "force PME-enable" */ + writeb(0x80, ioaddr + WOLcgClr); + + /* Clear power-event config bits (WOL) */ + writeb(0xFF, ioaddr + WOLcrClr); + /* More recent cards can manage two additional patterns */ + if (rp->quirks & rq6patterns) + writeb(0x03, ioaddr + WOLcrClr1); + + /* Clear power-event status bits */ + writeb(0xFF, ioaddr + PwrcsrClr); + if (rp->quirks & rq6patterns) + writeb(0x03, ioaddr + PwrcsrClr1); + } +} + +static void wait_for_reset(struct net_device *dev, u32 quirks, char *name) { long ioaddr = dev->base_addr; int boguscnt = 20; @@ -574,7 +591,7 @@ "Trying harder.\n", name); /* Rhine-II needs to be forced sometimes */ - if (chip_id == VT6102) + if (quirks & rqForceReset) writeb(0x40, ioaddr + MiscCmd); /* VT86C100A may need long delay after reset (dlink) */ @@ -590,10 +607,10 @@ } #ifdef USE_MMIO -static void __devinit enable_mmio(long ioaddr, int chip_id) +static void __devinit enable_mmio(long ioaddr, u32 quirks) { int n; - if (chip_id == VT86C100A) { + if (quirks & rqRhineI) { /* More recent docs say that this bit is reserved ... */ n = inb(ioaddr + ConfigA) | 0x20; outb(n, ioaddr + ConfigA); @@ -628,16 +645,18 @@ { struct net_device *dev; struct rhine_private *rp; - int i, option; - int chip_id = (int) ent->driver_data; + int i, option, rc; + u8 pci_rev; + u32 quirks; static int card_idx = -1; long ioaddr; long memaddr; int io_size; - int pci_flags; + int phy, phy_idx = 0; #ifdef USE_MMIO long ioaddr0; #endif + const char *name; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -648,14 +667,34 @@ card_idx++; option = card_idx < MAX_UNITS ? options[card_idx] : 0; - io_size = rhine_chip_info[chip_id].io_size; - pci_flags = rhine_chip_info[chip_id].pci_flags; + pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); + + io_size = 256; + if (pci_rev < VT6102) { + quirks = rqRhineI | rqDavicomPhy; + io_size = 128; + name = "VT86C100A Rhine"; + } + else { + quirks = rqWOL | rqForceReset; + if (pci_rev < VT6105) { + name = "Rhine II"; + quirks |= rqStatusWBRace; /* Rhine-II exclusive */ + } + else { + name = "Rhine III"; + if (pci_rev >= VT6105_B0) + quirks |= rq6patterns; + } + } - if (pci_enable_device(pdev)) + rc = pci_enable_device(pdev); + if (rc) goto err_out; /* this should always be supported */ - if (pci_set_dma_mask(pdev, 0xffffffff)) { + rc = pci_set_dma_mask(pdev, 0xffffffff); + if (rc) { printk(KERN_ERR "32-bit PCI DMA addresses not supported by " "the card!?\n"); goto err_out; @@ -664,6 +703,7 @@ /* sanity check */ if ((pci_resource_len(pdev, 0) < io_size) || (pci_resource_len(pdev, 1) < io_size)) { + rc = -EIO; printk(KERN_ERR "Insufficient PCI resources, aborting\n"); goto err_out; } @@ -671,11 +711,11 @@ ioaddr = pci_resource_start(pdev, 0); memaddr = pci_resource_start(pdev, 1); - if (pci_flags & PCI_USES_MASTER) - pci_set_master(pdev); + pci_set_master(pdev); dev = alloc_etherdev(sizeof(*rp)); if (dev == NULL) { + rc = -ENOMEM; printk(KERN_ERR "init_ethernet failed for card #%d\n", card_idx); goto err_out; @@ -683,15 +723,17 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, shortname)) + rc = pci_request_regions(pdev, shortname); + if (rc) goto err_out_free_netdev; #ifdef USE_MMIO ioaddr0 = ioaddr; - enable_mmio(ioaddr0, chip_id); + enable_mmio(ioaddr0, quirks); ioaddr = (long) ioremap(memaddr, io_size); if (!ioaddr) { + rc = -EIO; printk(KERN_ERR "ioremap failed for device %s, region 0x%X " "@ 0x%lX\n", pci_name(pdev), io_size, memaddr); goto err_out_free_res; @@ -704,36 +746,21 @@ unsigned char a = inb(ioaddr0+reg); unsigned char b = readb(ioaddr+reg); if (a != b) { + rc = -EIO; printk(KERN_ERR "MMIO do not match PIO [%02x] " "(%02x != %02x)\n", reg, a, b); goto err_out_unmap; } } #endif /* USE_MMIO */ + dev->base_addr = ioaddr; - /* D-Link provided reset code (with comment additions) */ - if (rhine_chip_info[chip_id].drv_flags & HasWOL) { - unsigned char byOrgValue; - - /* clear sticky bit before reset & read ethernet address */ - byOrgValue = readb(ioaddr + StickyHW); - byOrgValue = byOrgValue & 0xFC; - writeb(byOrgValue, ioaddr + StickyHW); - - /* (bits written are cleared?) */ - /* disable force PME-enable */ - writeb(0x80, ioaddr + WOLcgClr); - /* disable power-event config bit */ - writeb(0xFF, ioaddr + WOLcrClr); - /* clear power status (undocumented in vt6102 docs?) */ - writeb(0xFF, ioaddr + PwrcsrClr); - } + rhine_power_init(dev); /* Reset the chip to erase previous misconfiguration. */ writew(CmdReset, ioaddr + ChipCmd); - dev->base_addr = ioaddr; - wait_for_reset(dev, chip_id, shortname); + wait_for_reset(dev, quirks, shortname); /* Reload the station address from the EEPROM. */ #ifdef USE_MMIO @@ -741,7 +768,7 @@ /* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO. If reload_eeprom() was done first this could be avoided, but it is not known if that still works with the "win98-reboot" problem. */ - enable_mmio(ioaddr0, chip_id); + enable_mmio(ioaddr0, quirks); #else reload_eeprom(ioaddr); #endif @@ -750,11 +777,12 @@ dev->dev_addr[i] = readb(ioaddr + StationAddr + i); if (!is_valid_ether_addr(dev->dev_addr)) { + rc = -EIO; printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx); goto err_out_unmap; } - if (chip_id == VT6102) { + if (quirks & rqWOL) { /* * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA * turned on. it makes MAC receive magic packet @@ -772,9 +800,8 @@ rp = netdev_priv(dev); spin_lock_init(&rp->lock); - rp->chip_id = chip_id; - rp->drv_flags = rhine_chip_info[chip_id].drv_flags; rp->pdev = pdev; + rp->quirks = quirks; rp->mii_if.dev = dev; rp->mii_if.mdio_read = mdio_read; rp->mii_if.mdio_write = mdio_write; @@ -797,19 +824,18 @@ #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = rhine_poll; #endif - if (rp->drv_flags & ReqTxAlign) + if (rp->quirks & rqRhineI) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; /* dev->name not defined before register_netdev()! */ - i = register_netdev(dev); - if (i) + rc = register_netdev(dev); + if (rc) goto err_out_unmap; /* The lower four bits are the media type. */ if (option > 0) { if (option & 0x220) rp->mii_if.full_duplex = 1; - rp->default_port = option & 15; } if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) rp->mii_if.full_duplex = 1; @@ -820,9 +846,14 @@ rp->mii_if.force_media = 1; } - printk(KERN_INFO "%s: %s at 0x%lx, ", - dev->name, rhine_chip_info[chip_id].name, - (pci_flags & PCI_USES_IO) ? ioaddr : memaddr); + printk(KERN_INFO "%s: VIA %s at 0x%lx, ", + dev->name, name, +#ifdef USE_MMIO + memaddr +#else + ioaddr +#endif + ); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); @@ -830,41 +861,35 @@ pci_set_drvdata(pdev, dev); - if (rp->drv_flags & CanHaveMII) { - int phy, phy_idx = 0; - rp->phys[0] = 1; /* Standard for this chip. */ - for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - rp->phys[phy_idx++] = phy; - rp->mii_if.advertising = mdio_read(dev, phy, 4); - printk(KERN_INFO "%s: MII PHY found at address " - "%d, status 0x%4.4x advertising %4.4x " - "Link %4.4x.\n", dev->name, phy, - mii_status, rp->mii_if.advertising, - mdio_read(dev, phy, 5)); - - /* set IFF_RUNNING */ - if (mii_status & BMSR_LSTATUS) - netif_carrier_on(dev); - else - netif_carrier_off(dev); + rp->phys[0] = 1; /* Standard for this chip. */ + for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) { + int mii_status = mdio_read(dev, phy, 1); + if (mii_status != 0xffff && mii_status != 0x0000) { + rp->phys[phy_idx++] = phy; + rp->mii_if.advertising = mdio_read(dev, phy, 4); + printk(KERN_INFO "%s: MII PHY found at address " + "%d, status 0x%4.4x advertising %4.4x " + "Link %4.4x.\n", dev->name, phy, + mii_status, rp->mii_if.advertising, + mdio_read(dev, phy, 5)); + + /* set IFF_RUNNING */ + if (mii_status & BMSR_LSTATUS) + netif_carrier_on(dev); + else + netif_carrier_off(dev); - break; - } + break; } - rp->mii_cnt = phy_idx; - rp->mii_if.phy_id = rp->phys[0]; } + rp->mii_cnt = phy_idx; + rp->mii_if.phy_id = rp->phys[0]; /* Allow forcing the media type. */ if (option > 0) { if (option & 0x220) rp->mii_if.full_duplex = 1; - rp->default_port = option & 0x3ff; if (option & 0x330) { - /* FIXME: shouldn't someone check this variable? */ - /* rp->medialock = 1; */ printk(KERN_INFO " Forcing %dMbs %s-duplex " "operation.\n", (option & 0x300 ? 100 : 10), @@ -887,7 +912,7 @@ err_out_free_netdev: free_netdev(dev); err_out: - return -ENODEV; + return rc; } static int alloc_ring(struct net_device* dev) @@ -904,7 +929,7 @@ printk(KERN_ERR "Could not allocate DMA memory.\n"); return -ENOMEM; } - if (rp->drv_flags & ReqTxAlign) { + if (rp->quirks & rqRhineI) { rp->tx_bufs = pci_alloc_consistent(rp->pdev, PKT_BUF_SZ * TX_RING_SIZE, &rp->tx_bufs_dma); @@ -1063,9 +1088,6 @@ rp->rx_thresh = 0x60; /* Written in rhine_set_rx_mode(). */ rp->mii_if.full_duplex = 0; - if (dev->if_port == 0) - dev->if_port = rp->default_port; - writel(rp->rx_ring_dma, ioaddr + RxRingPtr); writel(rp->tx_ring_dma, ioaddr + TxRingPtr); @@ -1087,9 +1109,8 @@ /* The LED outputs of various MII xcvrs should be configured. */ /* For NS or Mison phys, turn on bit 1 in register 0x17 */ - /* For ESI phys, turn on bit 7 in register 0x17. */ mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) | - (rp->drv_flags & HasESIPhy) ? 0x0080 : 0x0001); + 0x0001); } /* Read and write over the MII Management Data I/O (MDIO) interface. */ @@ -1166,7 +1187,7 @@ return i; alloc_rbufs(dev); alloc_tbufs(dev); - wait_for_reset(dev, rp->chip_id, dev->name); + wait_for_reset(dev, rp->quirks, dev->name); init_registers(dev); if (debug > 2) printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x " @@ -1257,8 +1278,6 @@ dev->name, readw(ioaddr + IntrStatus), mdio_read(dev, rp->phys[0], MII_BMSR)); - dev->if_port = 0; - /* protect against concurrent rx interrupts */ disable_irq(rp->pdev->irq); @@ -1274,7 +1293,7 @@ alloc_rbufs(dev); /* Reinitialize the hardware. */ - wait_for_reset(dev, rp->chip_id, dev->name); + wait_for_reset(dev, rp->quirks, dev->name); init_registers(dev); spin_unlock(&rp->lock); @@ -1305,7 +1324,7 @@ rp->tx_skbuff[entry] = skb; - if ((rp->drv_flags & ReqTxAlign) && + if ((rp->quirks & rqRhineI) && (((long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) { /* Must use alignment buffer. */ if (skb->len > PKT_BUF_SZ) { @@ -1454,7 +1473,7 @@ if (txstatus & 0x0200) rp->stats.tx_window_errors++; if (txstatus & 0x0100) rp->stats.tx_aborted_errors++; if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++; - if (((rp->chip_id == VT86C100A) && txstatus & 0x0002) || + if (((rp->quirks & rqRhineI) && txstatus & 0x0002) || (txstatus & 0x0800) || (txstatus & 0x1000)) { rp->stats.tx_fifo_errors++; rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); @@ -1462,7 +1481,7 @@ } /* Transmitter restarted in 'abnormal' handler. */ } else { - if (rp->chip_id == VT86C100A) + if (rp->quirks & rqRhineI) rp->stats.collisions += (txstatus >> 3) & 0x0F; else rp->stats.collisions += txstatus & 0x0F; @@ -1563,15 +1582,10 @@ eth_copy_and_sum is memcpy for all archs so this is kind of pointless right now ... or? */ -#if HAS_IP_COPYSUM /* Call copy + cksum if available. */ eth_copy_and_sum(skb, rp->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - rp->rx_skbuff[entry]->tail, pkt_len); -#endif pci_dma_sync_single_for_device(rp->pdev, rp->rx_skbuff_dma[entry], rp->rx_buf_sz, @@ -1679,7 +1693,7 @@ if (intr_status & (IntrLinkChange)) { if (readb(ioaddr + MIIStatus) & 0x02) { /* Link failed, restart autonegotiation. */ - if (rp->drv_flags & HasDavicomPhy) + if (rp->quirks & rqRhineI) mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300); } else rhine_check_duplex(dev); @@ -1805,9 +1819,6 @@ struct rhine_private *rp = netdev_priv(dev); int rc; - if (!(rp->drv_flags & CanHaveMII)) - return -EINVAL; - spin_lock_irq(&rp->lock); rc = mii_ethtool_gset(&rp->mii_if, cmd); spin_unlock_irq(&rp->lock); @@ -1820,9 +1831,6 @@ struct rhine_private *rp = netdev_priv(dev); int rc; - if (!(rp->drv_flags & CanHaveMII)) - return -EINVAL; - spin_lock_irq(&rp->lock); rc = mii_ethtool_sset(&rp->mii_if, cmd); spin_unlock_irq(&rp->lock); @@ -1834,18 +1842,12 @@ { struct rhine_private *rp = netdev_priv(dev); - if (!(rp->drv_flags & CanHaveMII)) - return -EINVAL; - return mii_nway_restart(&rp->mii_if); } static u32 netdev_get_link(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); - - if (!(rp->drv_flags & CanHaveMII)) - return 0; /* -EINVAL */ return mii_link_ok(&rp->mii_if); } diff -Nru a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/via-velocity.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,3277 @@ +/* + * This code is derived from the VIA reference driver (copyright message + * below) provided to Red Hat by VIA Networking Technologies, Inc. for + * addition to the Linux kernel. + * + * The code has been merged into one source file, cleaned up to follow + * Linux coding style, ported to the Linux 2.6 kernel tree and cleaned + * for 64bit hardware platforms. + * + * TODO + * Big-endian support + * rx_copybreak/alignment + * Scatter gather + * More testing + * + * The changes are (c) Copyright 2004, Red Hat Inc. + * Additional fixes and clean up: Francois Romieu + * + * This source has not been verified for use in safety critical systems. + * + * Please direct queries about the revamped driver to the linux-kernel + * list not VIA. + * + * Original code: + * + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + * + * MODULE_LICENSE("GPL"); + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "via-velocity.h" + + +static int velocity_nics = 0; +static int msglevel = MSG_LEVEL_INFO; + + +static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static struct ethtool_ops velocity_ethtool_ops; + +/* + Define module options +*/ + +MODULE_AUTHOR("VIA Networking Technologies, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"); + +#define VELOCITY_PARAM(N,D) \ + static const int N[MAX_UNITS]=OPTION_DEFAULT;\ + MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\ + MODULE_PARM_DESC(N, D); + +#define RX_DESC_MIN 64 +#define RX_DESC_MAX 255 +#define RX_DESC_DEF 64 +VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors"); + +#define TX_DESC_MIN 16 +#define TX_DESC_MAX 256 +#define TX_DESC_DEF 64 +VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors"); + +#define VLAN_ID_MIN 0 +#define VLAN_ID_MAX 4095 +#define VLAN_ID_DEF 0 +/* VID_setting[] is used for setting the VID of NIC. + 0: default VID. + 1-4094: other VIDs. +*/ +VELOCITY_PARAM(VID_setting, "802.1Q VLAN ID"); + +#define RX_THRESH_MIN 0 +#define RX_THRESH_MAX 3 +#define RX_THRESH_DEF 0 +/* rx_thresh[] is used for controlling the receive fifo threshold. + 0: indicate the rxfifo threshold is 128 bytes. + 1: indicate the rxfifo threshold is 512 bytes. + 2: indicate the rxfifo threshold is 1024 bytes. + 3: indicate the rxfifo threshold is store & forward. +*/ +VELOCITY_PARAM(rx_thresh, "Receive fifo threshold"); + +#define DMA_LENGTH_MIN 0 +#define DMA_LENGTH_MAX 7 +#define DMA_LENGTH_DEF 0 + +/* DMA_length[] is used for controlling the DMA length + 0: 8 DWORDs + 1: 16 DWORDs + 2: 32 DWORDs + 3: 64 DWORDs + 4: 128 DWORDs + 5: 256 DWORDs + 6: SF(flush till emply) + 7: SF(flush till emply) +*/ +VELOCITY_PARAM(DMA_length, "DMA length"); + +#define TAGGING_DEF 0 +/* enable_tagging[] is used for enabling 802.1Q VID tagging. + 0: disable VID seeting(default). + 1: enable VID setting. +*/ +VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging"); + +#define IP_ALIG_DEF 0 +/* IP_byte_align[] is used for IP header DWORD byte aligned + 0: indicate the IP header won't be DWORD byte aligned.(Default) . + 1: indicate the IP header will be DWORD byte aligned. + In some enviroment, the IP header should be DWORD byte aligned, + or the packet will be droped when we receive it. (eg: IPVS) +*/ +VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned"); + +#define TX_CSUM_DEF 1 +/* txcsum_offload[] is used for setting the checksum offload ability of NIC. + (We only support RX checksum offload now) + 0: disable csum_offload[checksum offload + 1: enable checksum offload. (Default) +*/ +VELOCITY_PARAM(txcsum_offload, "Enable transmit packet checksum offload"); + +#define FLOW_CNTL_DEF 1 +#define FLOW_CNTL_MIN 1 +#define FLOW_CNTL_MAX 5 + +/* flow_control[] is used for setting the flow control ability of NIC. + 1: hardware deafult - AUTO (default). Use Hardware default value in ANAR. + 2: enable TX flow control. + 3: enable RX flow control. + 4: enable RX/TX flow control. + 5: disable +*/ +VELOCITY_PARAM(flow_control, "Enable flow control ability"); + +#define MED_LNK_DEF 0 +#define MED_LNK_MIN 0 +#define MED_LNK_MAX 4 +/* speed_duplex[] is used for setting the speed and duplex mode of NIC. + 0: indicate autonegotiation for both speed and duplex mode + 1: indicate 100Mbps half duplex mode + 2: indicate 100Mbps full duplex mode + 3: indicate 10Mbps half duplex mode + 4: indicate 10Mbps full duplex mode + + Note: + if EEPROM have been set to the force mode, this option is ignored + by driver. +*/ +VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode"); + +#define VAL_PKT_LEN_DEF 0 +/* ValPktLen[] is used for setting the checksum offload ability of NIC. + 0: Receive frame with invalid layer 2 length (Default) + 1: Drop frame with invalid layer 2 length +*/ +VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame"); + +#define WOL_OPT_DEF 0 +#define WOL_OPT_MIN 0 +#define WOL_OPT_MAX 7 +/* wol_opts[] is used for controlling wake on lan behavior. + 0: Wake up if recevied a magic packet. (Default) + 1: Wake up if link status is on/off. + 2: Wake up if recevied an arp packet. + 4: Wake up if recevied any unicast packet. + Those value can be sumed up to support more than one option. +*/ +VELOCITY_PARAM(wol_opts, "Wake On Lan options"); + +#define INT_WORKS_DEF 20 +#define INT_WORKS_MIN 10 +#define INT_WORKS_MAX 64 + +VELOCITY_PARAM(int_works, "Number of packets per interrupt services"); + +static int velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent); +static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info); +static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev); +static void velocity_print_info(struct velocity_info *vptr); +static int velocity_open(struct net_device *dev); +static int velocity_change_mtu(struct net_device *dev, int mtu); +static int velocity_xmit(struct sk_buff *skb, struct net_device *dev); +static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs); +static void velocity_set_multi(struct net_device *dev); +static struct net_device_stats *velocity_get_stats(struct net_device *dev); +static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int velocity_close(struct net_device *dev); +static int velocity_rx_srv(struct velocity_info *vptr, int status); +static int velocity_receive_frame(struct velocity_info *, int idx); +static int velocity_alloc_rx_buf(struct velocity_info *, int idx); +static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type); +static void velocity_free_rd_ring(struct velocity_info *vptr); +static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *); +static int velocity_soft_reset(struct velocity_info *vptr); +static void mii_init(struct velocity_info *vptr, u32 mii_status); +static u32 velocity_get_opt_media_mode(struct velocity_info *vptr); +static void velocity_print_link_status(struct velocity_info *vptr); +static void safe_disable_mii_autopoll(struct mac_regs * regs); +static void velocity_shutdown(struct velocity_info *vptr); +static void enable_flow_control_ability(struct velocity_info *vptr); +static void enable_mii_autopoll(struct mac_regs * regs); +static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata); +static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data); +static int velocity_set_wol(struct velocity_info *vptr); +static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context); +static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context); +static u32 mii_check_media_mode(struct mac_regs * regs); +static u32 check_connection_type(struct mac_regs * regs); +static void velocity_init_cam_filter(struct velocity_info *vptr); +static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status); + +#ifdef CONFIG_PM +static int velocity_suspend(struct pci_dev *pdev, u32 state); +static int velocity_resume(struct pci_dev *pdev); + +static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr); + +static struct notifier_block velocity_inetaddr_notifier = { + notifier_call:velocity_netdev_event, +}; + +#endif /* CONFIG_PM */ + +/* + * Internal board variants. At the moment we have only one + */ + +static struct velocity_info_tbl chip_info_table[] = { + {CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1, 0x00FFFFFFUL}, + {0, NULL} +}; + +/* + * Describe the PCI device identifiers that we support in this + * device driver. Used for hotplug autoloading. + */ + +static struct pci_device_id velocity_id_table[] __devinitdata = { + {0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &chip_info_table[0]}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, velocity_id_table); + +/** + * get_chip_name - identifier to name + * @id: chip identifier + * + * Given a chip identifier return a suitable description. Returns + * a pointer a static string valid while the driver is loaded. + */ + +static char __devinit *get_chip_name(enum chip_type chip_id) +{ + int i; + for (i = 0; chip_info_table[i].name != NULL; i++) + if (chip_info_table[i].chip_id == chip_id) + break; + return chip_info_table[i].name; +} + +/** + * velocity_remove1 - device unplug + * @pdev: PCI device being removed + * + * Device unload callback. Called on an unplug or on module + * unload for each active device that is present. Disconnects + * the device from the network layer and frees all the resources + */ + +static void __devexit velocity_remove1(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct velocity_info *vptr = dev->priv; + + unregister_netdev(dev); + iounmap(vptr->mac_regs); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + free_netdev(dev); +} + +/** + * velocity_set_int_opt - parser for integer options + * @opt: pointer to option value + * @val: value the user requested (or -1 for default) + * @min: lowest value allowed + * @max: highest value allowed + * @def: default value + * @name: property name + * @dev: device name + * + * Set an integer property in the module options. This function does + * all the verification and checking as well as reporting so that + * we don't duplicate code for each option. + */ + +static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, char *devname) +{ + if (val == -1) + *opt = def; + else if (val < min || val > max) { + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n", + devname, name, min, max); + *opt = def; + } else { + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n", + devname, name, val); + *opt = val; + } +} + +/** + * velocity_set_bool_opt - parser for boolean options + * @opt: pointer to option value + * @val: value the user requested (or -1 for default) + * @def: default value (yes/no) + * @flag: numeric value to set for true. + * @name: property name + * @dev: device name + * + * Set a boolean property in the module options. This function does + * all the verification and checking as well as reporting so that + * we don't duplicate code for each option. + */ + +static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, char *name, char *devname) +{ + (*opt) &= (~flag); + if (val == -1) + *opt |= (def ? flag : 0); + else if (val < 0 || val > 1) { + printk(KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (0-1)\n", + devname, name); + *opt |= (def ? flag : 0); + } else { + printk(KERN_INFO "%s: set parameter %s to %s\n", + devname, name, val ? "TRUE" : "FALSE"); + *opt |= (val ? flag : 0); + } +} + +/** + * velocity_get_options - set options on device + * @opts: option structure for the device + * @index: index of option to use in module options array + * @devname: device name + * + * Turn the module and command options into a single structure + * for the current device + */ + +static void __devinit velocity_get_options(struct velocity_opt *opts, int index, char *devname) +{ + + velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname); + velocity_set_int_opt(&opts->DMA_length, DMA_length[index], DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF, "DMA_length", devname); + velocity_set_int_opt(&opts->numrx, RxDescriptors[index], RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors", devname); + velocity_set_int_opt(&opts->numtx, TxDescriptors[index], TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors", devname); + velocity_set_int_opt(&opts->vid, VID_setting[index], VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_DEF, "VID_setting", devname); + velocity_set_bool_opt(&opts->flags, enable_tagging[index], TAGGING_DEF, VELOCITY_FLAGS_TAGGING, "enable_tagging", devname); + velocity_set_bool_opt(&opts->flags, txcsum_offload[index], TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM, "txcsum_offload", devname); + velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname); + velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname); + velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname); + velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname); + velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname); + velocity_set_int_opt((int *) &opts->int_works, int_works[index], INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF, "Interrupt service works", devname); + opts->numrx = (opts->numrx & ~3); +} + +/** + * velocity_init_cam_filter - initialise CAM + * @vptr: velocity to program + * + * Initialize the content addressable memory used for filters. Load + * appropriately according to the presence of VLAN + */ + +static void velocity_init_cam_filter(struct velocity_info *vptr) +{ + struct mac_regs * regs = vptr->mac_regs; + + /* T urn on MCFG_PQEN, turn off MCFG_RTGOPT */ + WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); + WORD_REG_BITS_ON(MCFG_VIDFR, ®s->MCFG); + + /* Disable all CAMs */ + memset(vptr->vCAMmask, 0, sizeof(u8) * 8); + memset(vptr->mCAMmask, 0, sizeof(u8) * 8); + mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); + mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM); + + /* Enable first VCAM */ + if (vptr->flags & VELOCITY_FLAGS_TAGGING) { + /* If Tagging option is enabled and VLAN ID is not zero, then + turn on MCFG_RTGOPT also */ + if (vptr->options.vid != 0) + WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); + + mac_set_cam(regs, 0, (u8 *) & (vptr->options.vid), VELOCITY_VLAN_ID_CAM); + vptr->vCAMmask[0] |= 1; + mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); + } else { + u16 temp = 0; + mac_set_cam(regs, 0, (u8 *) &temp, VELOCITY_VLAN_ID_CAM); + temp = 1; + mac_set_cam_mask(regs, (u8 *) &temp, VELOCITY_VLAN_ID_CAM); + } +} + +/** + * velocity_rx_reset - handle a receive reset + * @vptr: velocity we are resetting + * + * Reset the ownership and status for the receive ring side. + * Hand all the receive queue to the NIC. + */ + +static void velocity_rx_reset(struct velocity_info *vptr) +{ + + struct mac_regs * regs = vptr->mac_regs; + int i; + + vptr->rd_used = vptr->rd_curr = 0; + + /* + * Init state, all RD entries belong to the NIC + */ + for (i = 0; i < vptr->options.numrx; ++i) + vptr->rd_ring[i].rdesc0.owner = cpu_to_le32(OWNED_BY_NIC); + + writew(vptr->options.numrx, ®s->RBRDU); + writel(vptr->rd_pool_dma, ®s->RDBaseLo); + writew(0, ®s->RDIdx); + writew(vptr->options.numrx - 1, ®s->RDCSize); +} + +/** + * velocity_init_registers - initialise MAC registers + * @vptr: velocity to init + * @type: type of initialisation (hot or cold) + * + * Initialise the MAC on a reset or on first set up on the + * hardware. + */ + +static void velocity_init_registers(struct velocity_info *vptr, + enum velocity_init_type type) +{ + struct mac_regs * regs = vptr->mac_regs; + int i, mii_status; + + mac_wol_reset(regs); + + switch (type) { + case VELOCITY_INIT_RESET: + case VELOCITY_INIT_WOL: + + netif_stop_queue(vptr->dev); + + /* + * Reset RX to prevent RX pointer not on the 4X location + */ + velocity_rx_reset(vptr); + mac_rx_queue_run(regs); + mac_rx_queue_wake(regs); + + mii_status = velocity_get_opt_media_mode(vptr); + if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) { + velocity_print_link_status(vptr); + if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) + netif_wake_queue(vptr->dev); + } + + enable_flow_control_ability(vptr); + + mac_clear_isr(regs); + writel(CR0_STOP, ®s->CR0Clr); + writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), + ®s->CR0Set); + + break; + + case VELOCITY_INIT_COLD: + default: + /* + * Do reset + */ + velocity_soft_reset(vptr); + mdelay(5); + + mac_eeprom_reload(regs); + for (i = 0; i < 6; i++) { + writeb(vptr->dev->dev_addr[i], &(regs->PAR[i])); + } + /* + * clear Pre_ACPI bit. + */ + BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA)); + mac_set_rx_thresh(regs, vptr->options.rx_thresh); + mac_set_dma_length(regs, vptr->options.DMA_length); + + writeb(WOLCFG_SAM | WOLCFG_SAB, ®s->WOLCFGSet); + /* + * Bback off algorithm use original IEEE standard + */ + BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), ®s->CFGB); + + /* + * Set packet filter: Receive directed and broadcast address + */ + velocity_set_multi(vptr->dev); + + /* + * Enable MII auto-polling + */ + enable_mii_autopoll(regs); + + vptr->int_mask = INT_MASK_DEF; + + writel(cpu_to_le32(vptr->rd_pool_dma), ®s->RDBaseLo); + writew(vptr->options.numrx - 1, ®s->RDCSize); + mac_rx_queue_run(regs); + mac_rx_queue_wake(regs); + + writew(vptr->options.numtx - 1, ®s->TDCSize); + + for (i = 0; i < vptr->num_txq; i++) { + writel(cpu_to_le32(vptr->td_pool_dma[i]), &(regs->TDBaseLo[i])); + mac_tx_queue_run(regs, i); + } + + velocity_init_cam_filter(vptr); + + init_flow_control_register(vptr); + + writel(CR0_STOP, ®s->CR0Clr); + writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), ®s->CR0Set); + + mii_status = velocity_get_opt_media_mode(vptr); + netif_stop_queue(vptr->dev); + mac_clear_isr(regs); + + mii_init(vptr, mii_status); + + if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) { + velocity_print_link_status(vptr); + if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) + netif_wake_queue(vptr->dev); + } + + enable_flow_control_ability(vptr); + mac_hw_mibs_init(regs); + mac_write_int_mask(vptr->int_mask, regs); + mac_clear_isr(regs); + + } +} + +/** + * velocity_soft_reset - soft reset + * @vptr: velocity to reset + * + * Kick off a soft reset of the velocity adapter and then poll + * until the reset sequence has completed before returning. + */ + +static int velocity_soft_reset(struct velocity_info *vptr) +{ + struct mac_regs * regs = vptr->mac_regs; + int i = 0; + + writel(CR0_SFRST, ®s->CR0Set); + + for (i = 0; i < W_MAX_TIMEOUT; i++) { + udelay(5); + if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, ®s->CR0Set)) + break; + } + + if (i == W_MAX_TIMEOUT) { + writel(CR0_FORSRST, ®s->CR0Set); + /* FIXME: PCI POSTING */ + /* delay 2ms */ + mdelay(2); + } + return 0; +} + +/** + * velocity_found1 - set up discovered velocity card + * @pdev: PCI device + * @ent: PCI device table entry that matched + * + * Configure a discovered adapter from scratch. Return a negative + * errno error code on failure paths. + */ + +static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int first = 1; + struct net_device *dev; + int i; + struct velocity_info_tbl *info = (struct velocity_info_tbl *) ent->driver_data; + struct velocity_info *vptr; + struct mac_regs * regs; + int ret = -ENOMEM; + + if (velocity_nics++ >= MAX_UNITS) { + printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", + velocity_nics); + return -ENODEV; + } + + dev = alloc_etherdev(sizeof(struct velocity_info)); + + if (dev == NULL) { + printk(KERN_ERR VELOCITY_NAME ": allocate net device failed.\n"); + goto out; + } + + /* Chain it all together */ + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + vptr = dev->priv; + + + if (first) { + printk(KERN_INFO "%s Ver. %s\n", + VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION); + printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n"); + printk(KERN_INFO "Copyright (c) 2004 Red Hat Inc.\n"); + first = 0; + } + + velocity_init_info(pdev, vptr, info); + + vptr->dev = dev; + + dev->priv = vptr; + dev->irq = pdev->irq; + + ret = pci_enable_device(pdev); + if (ret < 0) + goto err_free_dev; + + ret = velocity_get_pci_info(vptr, pdev); + if (ret < 0) { + printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n"); + goto err_disable; + } + + ret = pci_request_regions(pdev, VELOCITY_NAME); + if (ret < 0) { + printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n"); + goto err_disable; + } + + regs = ioremap(vptr->memaddr, vptr->io_size); + if (regs == NULL) { + ret = -EIO; + goto err_release_res; + } + + vptr->mac_regs = regs; + + mac_wol_reset(regs); + + dev->base_addr = vptr->ioaddr; + + for (i = 0; i < 6; i++) + dev->dev_addr[i] = readb(®s->PAR[i]); + + + velocity_get_options(&vptr->options, velocity_nics - 1, dev->name); + + /* + * Mask out the options cannot be set to the chip + */ + + vptr->options.flags &= info->flags; + + /* + * Enable the chip specified capbilities + */ + + vptr->flags = vptr->options.flags | (info->flags & 0xFF000000UL); + + vptr->wol_opts = vptr->options.wol_opts; + vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED; + + vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs); + + dev->irq = pdev->irq; + dev->open = velocity_open; + dev->hard_start_xmit = velocity_xmit; + dev->stop = velocity_close; + dev->get_stats = velocity_get_stats; + dev->set_multicast_list = velocity_set_multi; + dev->do_ioctl = velocity_ioctl; + dev->ethtool_ops = &velocity_ethtool_ops; + dev->change_mtu = velocity_change_mtu; +#ifdef VELOCITY_ZERO_COPY_SUPPORT + dev->features |= NETIF_F_SG; +#endif + + if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { + dev->features |= NETIF_F_HW_CSUM; + } + + ret = register_netdev(dev); + if (ret < 0) + goto err_iounmap; + + velocity_print_info(vptr); + pci_set_drvdata(pdev, dev); + + /* and leave the chip powered down */ + + pci_set_power_state(pdev, 3); +out: + return ret; + +err_iounmap: + iounmap(regs); +err_release_res: + pci_release_regions(pdev); +err_disable: + pci_disable_device(pdev); +err_free_dev: + free_netdev(dev); + goto out; +} + +/** + * velocity_print_info - per driver data + * @vptr: velocity + * + * Print per driver data as the kernel driver finds Velocity + * hardware + */ + +static void __devinit velocity_print_info(struct velocity_info *vptr) +{ + struct net_device *dev = vptr->dev; + + printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id)); + printk(KERN_INFO "%s: Ethernet Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + dev->name, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); +} + +/** + * velocity_init_info - init private data + * @pdev: PCI device + * @vptr: Velocity info + * @info: Board type + * + * Set up the initial velocity_info struct for the device that has been + * discovered. + */ + +static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info) +{ + memset(vptr, 0, sizeof(struct velocity_info)); + + vptr->pdev = pdev; + vptr->chip_id = info->chip_id; + vptr->io_size = info->io_size; + vptr->num_txq = info->txqueue; + vptr->multicast_limit = MCAM_SIZE; + + spin_lock_init(&vptr->lock); + spin_lock_init(&vptr->xmit_lock); +} + +/** + * velocity_get_pci_info - retrieve PCI info for device + * @vptr: velocity device + * @pdev: PCI device it matches + * + * Retrieve the PCI configuration space data that interests us from + * the kernel PCI layer + */ + +static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev) +{ + + if(pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0) + return -EIO; + + pci_set_master(pdev); + + vptr->ioaddr = pci_resource_start(pdev, 0); + vptr->memaddr = pci_resource_start(pdev, 1); + + if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) + { + printk(KERN_ERR "%s: region #0 is not an I/O resource, aborting.\n", + pci_name(pdev)); + return -EINVAL; + } + + if((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) + { + printk(KERN_ERR "%s: region #1 is an I/O resource, aborting.\n", + pci_name(pdev)); + return -EINVAL; + } + + if(pci_resource_len(pdev, 1) < 256) + { + printk(KERN_ERR "%s: region #1 is too small.\n", + pci_name(pdev)); + return -EINVAL; + } + vptr->pdev = pdev; + + return 0; +} + +/** + * velocity_init_rings - set up DMA rings + * @vptr: Velocity to set up + * + * Allocate PCI mapped DMA rings for the receive and transmit layer + * to use. + */ + +static int velocity_init_rings(struct velocity_info *vptr) +{ + int i; + unsigned int psize; + unsigned int tsize; + dma_addr_t pool_dma; + u8 *pool; + + /* + * Allocate all RD/TD rings a single pool + */ + + psize = vptr->options.numrx * sizeof(struct rx_desc) + + vptr->options.numtx * sizeof(struct tx_desc) * vptr->num_txq; + + /* + * pci_alloc_consistent() fulfills the requirement for 64 bytes + * alignment + */ + pool = pci_alloc_consistent(vptr->pdev, psize, &pool_dma); + + if (pool == NULL) { + printk(KERN_ERR "%s : DMA memory allocation failed.\n", + vptr->dev->name); + return -ENOMEM; + } + + memset(pool, 0, psize); + + vptr->rd_ring = (struct rx_desc *) pool; + + vptr->rd_pool_dma = pool_dma; + + tsize = vptr->options.numtx * PKT_BUF_SZ * vptr->num_txq; + vptr->tx_bufs = pci_alloc_consistent(vptr->pdev, tsize, + &vptr->tx_bufs_dma); + + if (vptr->tx_bufs == NULL) { + printk(KERN_ERR "%s: DMA memory allocation failed.\n", + vptr->dev->name); + pci_free_consistent(vptr->pdev, psize, pool, pool_dma); + return -ENOMEM; + } + + memset(vptr->tx_bufs, 0, vptr->options.numtx * PKT_BUF_SZ * vptr->num_txq); + + i = vptr->options.numrx * sizeof(struct rx_desc); + pool += i; + pool_dma += i; + for (i = 0; i < vptr->num_txq; i++) { + int offset = vptr->options.numtx * sizeof(struct tx_desc); + + vptr->td_pool_dma[i] = pool_dma; + vptr->td_rings[i] = (struct tx_desc *) pool; + pool += offset; + pool_dma += offset; + } + return 0; +} + +/** + * velocity_free_rings - free PCI ring pointers + * @vptr: Velocity to free from + * + * Clean up the PCI ring buffers allocated to this velocity. + */ + +static void velocity_free_rings(struct velocity_info *vptr) +{ + int size; + + size = vptr->options.numrx * sizeof(struct rx_desc) + + vptr->options.numtx * sizeof(struct tx_desc) * vptr->num_txq; + + pci_free_consistent(vptr->pdev, size, vptr->rd_ring, vptr->rd_pool_dma); + + size = vptr->options.numtx * PKT_BUF_SZ * vptr->num_txq; + + pci_free_consistent(vptr->pdev, size, vptr->tx_bufs, vptr->tx_bufs_dma); +} + +/** + * velocity_init_rd_ring - set up receive ring + * @vptr: velocity to configure + * + * Allocate and set up the receive buffers for each ring slot and + * assign them to the network adapter. + */ + +static int velocity_init_rd_ring(struct velocity_info *vptr) +{ + int i, ret = -ENOMEM; + struct rx_desc *rd; + struct velocity_rd_info *rd_info; + unsigned int rsize = sizeof(struct velocity_rd_info) * + vptr->options.numrx; + + vptr->rd_info = kmalloc(rsize, GFP_KERNEL); + if(vptr->rd_info == NULL) + goto out; + memset(vptr->rd_info, 0, rsize); + + /* Init the RD ring entries */ + for (i = 0; i < vptr->options.numrx; i++) { + rd = &(vptr->rd_ring[i]); + rd_info = &(vptr->rd_info[i]); + + ret = velocity_alloc_rx_buf(vptr, i); + if (ret < 0) { + VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: failed to allocate RX buffer.\n", + vptr->dev->name); + velocity_free_rd_ring(vptr); + goto out; + } + rd->rdesc0.owner = OWNED_BY_NIC; + } + vptr->rd_used = vptr->rd_curr = 0; +out: + return ret; +} + +/** + * velocity_free_rd_ring - set up receive ring + * @vptr: velocity to clean up + * + * Free the receive buffers for each ring slot and any + * attached socket buffers that need to go away. + */ + +static void velocity_free_rd_ring(struct velocity_info *vptr) +{ + int i; + + if (vptr->rd_info == NULL) + return; + + for (i = 0; i < vptr->options.numrx; i++) { + struct velocity_rd_info *rd_info = &(vptr->rd_info[i]); + + if (!rd_info->skb_dma) + continue; + pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, + PCI_DMA_FROMDEVICE); + rd_info->skb_dma = (dma_addr_t) NULL; + + dev_kfree_skb(rd_info->skb); + rd_info->skb = NULL; + } + + kfree(vptr->rd_info); + vptr->rd_info = NULL; +} + +/** + * velocity_init_td_ring - set up transmit ring + * @vptr: velocity + * + * Set up the transmit ring and chain the ring pointers together. + * Returns zero on success or a negative posix errno code for + * failure. + */ + +static int velocity_init_td_ring(struct velocity_info *vptr) +{ + int i, j; + dma_addr_t curr; + struct tx_desc *td; + struct velocity_td_info *td_info; + unsigned int tsize = sizeof(struct velocity_td_info) * + vptr->options.numtx; + + /* Init the TD ring entries */ + for (j = 0; j < vptr->num_txq; j++) { + curr = vptr->td_pool_dma[j]; + + vptr->td_infos[j] = kmalloc(tsize, GFP_KERNEL); + if(vptr->td_infos[j] == NULL) + { + while(--j >= 0) + kfree(vptr->td_infos[j]); + return -ENOMEM; + } + memset(vptr->td_infos[j], 0, tsize); + + for (i = 0; i < vptr->options.numtx; i++, curr += sizeof(struct tx_desc)) { + td = &(vptr->td_rings[j][i]); + td_info = &(vptr->td_infos[j][i]); + td_info->buf = vptr->tx_bufs + (i + j) * PKT_BUF_SZ; + td_info->buf_dma = vptr->tx_bufs_dma + (i + j) * PKT_BUF_SZ; + } + vptr->td_tail[j] = vptr->td_curr[j] = vptr->td_used[j] = 0; + } + return 0; +} + +/* + * FIXME: could we merge this with velocity_free_tx_buf ? + */ + +static void velocity_free_td_ring_entry(struct velocity_info *vptr, + int q, int n) +{ + struct velocity_td_info * td_info = &(vptr->td_infos[q][n]); + int i; + + if (td_info == NULL) + return; + + if (td_info->skb) { + for (i = 0; i < td_info->nskb_dma; i++) + { + if (td_info->skb_dma[i]) { + pci_unmap_single(vptr->pdev, td_info->skb_dma[i], + td_info->skb->len, PCI_DMA_TODEVICE); + td_info->skb_dma[i] = (dma_addr_t) NULL; + } + } + dev_kfree_skb(td_info->skb); + td_info->skb = NULL; + } +} + +/** + * velocity_free_td_ring - free td ring + * @vptr: velocity + * + * Free up the transmit ring for this particular velocity adapter. + * We free the ring contents but not the ring itself. + */ + +static void velocity_free_td_ring(struct velocity_info *vptr) +{ + int i, j; + + for (j = 0; j < vptr->num_txq; j++) { + if (vptr->td_infos[j] == NULL) + continue; + for (i = 0; i < vptr->options.numtx; i++) { + velocity_free_td_ring_entry(vptr, j, i); + + } + if (vptr->td_infos[j]) { + kfree(vptr->td_infos[j]); + vptr->td_infos[j] = NULL; + } + } +} + +/** + * velocity_rx_srv - service RX interrupt + * @vptr: velocity + * @status: adapter status (unused) + * + * Walk the receive ring of the velocity adapter and remove + * any received packets from the receive queue. Hand the ring + * slots back to the adapter for reuse. + */ + +static int velocity_rx_srv(struct velocity_info *vptr, int status) +{ + struct rx_desc *rd; + struct net_device_stats *stats = &vptr->stats; + struct mac_regs * regs = vptr->mac_regs; + int rd_curr = vptr->rd_curr; + int works = 0; + + while (1) { + + rd = &(vptr->rd_ring[rd_curr]); + + if ((vptr->rd_info[rd_curr]).skb == NULL) { + if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) + break; + } + + if (works++ > 15) + break; + + if (rd->rdesc0.owner == OWNED_BY_NIC) + break; + + /* + * Don't drop CE or RL error frame although RXOK is off + * FIXME: need to handle copybreak + */ + if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) { + if (velocity_receive_frame(vptr, rd_curr) == 0) { + if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) { + VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not allocate rx buf\n", vptr->dev->name); + break; + } + } else { + stats->rx_dropped++; + } + } else { + if (rd->rdesc0.RSR & RSR_CRC) + stats->rx_crc_errors++; + if (rd->rdesc0.RSR & RSR_FAE) + stats->rx_frame_errors++; + + stats->rx_dropped++; + } + + rd->inten = 1; + + if (++vptr->rd_used >= 4) { + int i, rd_prev = rd_curr; + for (i = 0; i < 4; i++) { + if (--rd_prev < 0) + rd_prev = vptr->options.numrx - 1; + + rd = &(vptr->rd_ring[rd_prev]); + rd->rdesc0.owner = OWNED_BY_NIC; + } + writew(4, &(regs->RBRDU)); + vptr->rd_used -= 4; + } + + vptr->dev->last_rx = jiffies; + + rd_curr++; + if (rd_curr >= vptr->options.numrx) + rd_curr = 0; + } + vptr->rd_curr = rd_curr; + VAR_USED(stats); + return works; +} + +/** + * velocity_rx_csum - checksum process + * @rd: receive packet descriptor + * @skb: network layer packet buffer + * + * Process the status bits for the received packet and determine + * if the checksum was computed and verified by the hardware + */ + +static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb) +{ + skb->ip_summed = CHECKSUM_NONE; + + if (rd->rdesc1.CSM & CSM_IPKT) { + if (rd->rdesc1.CSM & CSM_IPOK) { + if ((rd->rdesc1.CSM & CSM_TCPKT) || + (rd->rdesc1.CSM & CSM_UDPKT)) { + if (!(rd->rdesc1.CSM & CSM_TUPOK)) { + return; + } + } + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + } +} + +/** + * velocity_receive_frame - received packet processor + * @vptr: velocity we are handling + * @idx: ring index + * + * A packet has arrived. We process the packet and if appropriate + * pass the frame up the network stack + */ + +static int velocity_receive_frame(struct velocity_info *vptr, int idx) +{ + struct net_device_stats *stats = &vptr->stats; + struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]); + struct rx_desc *rd = &(vptr->rd_ring[idx]); + struct sk_buff *skb; + + if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) { + VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->dev->name); + stats->rx_length_errors++; + return -EINVAL; + } + + if (rd->rdesc0.RSR & RSR_MAR) + vptr->stats.multicast++; + + skb = rd_info->skb; + skb->dev = vptr->dev; + + pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, + PCI_DMA_FROMDEVICE); + rd_info->skb_dma = (dma_addr_t) NULL; + rd_info->skb = NULL; + + /* FIXME - memmove ? */ + if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) { + int i; + for (i = rd->rdesc0.len + 4; i >= 0; i--) + *(skb->data + i + 2) = *(skb->data + i); + skb->data += 2; + skb->tail += 2; + } + + skb_put(skb, (rd->rdesc0.len - 4)); + skb->protocol = eth_type_trans(skb, skb->dev); + + /* + * Drop frame not meeting IEEE 802.3 + */ + + if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) { + if (rd->rdesc0.RSR & RSR_RL) { + stats->rx_length_errors++; + return -EINVAL; + } + } + + velocity_rx_csum(rd, skb); + + /* + * FIXME: need rx_copybreak handling + */ + + stats->rx_bytes += skb->len; + netif_rx(skb); + + return 0; +} + +/** + * velocity_alloc_rx_buf - allocate aligned receive buffer + * @vptr: velocity + * @idx: ring index + * + * Allocate a new full sized buffer for the reception of a frame and + * map it into PCI space for the hardware to use. The hardware + * requires *64* byte alignment of the buffer which makes life + * less fun than would be ideal. + */ + +static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx) +{ + struct rx_desc *rd = &(vptr->rd_ring[idx]); + struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]); + + rd_info->skb = dev_alloc_skb(vptr->rx_buf_sz + 64); + if (rd_info->skb == NULL) + return -ENOMEM; + + /* + * Do the gymnastics to get the buffer head for data at + * 64byte alignment. + */ + skb_reserve(rd_info->skb, (unsigned long) rd_info->skb->tail & 63); + rd_info->skb->dev = vptr->dev; + rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->tail, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE); + + /* + * Fill in the descriptor to match + */ + + *((u32 *) & (rd->rdesc0)) = 0; + rd->len = cpu_to_le32(vptr->rx_buf_sz); + rd->inten = 1; + rd->pa_low = cpu_to_le32(rd_info->skb_dma); + rd->pa_high = 0; + return 0; +} + +/** + * tx_srv - transmit interrupt service + * @vptr; Velocity + * @status: + * + * Scan the queues looking for transmitted packets that + * we can complete and clean up. Update any statistics as + * neccessary/ + */ + +static int velocity_tx_srv(struct velocity_info *vptr, u32 status) +{ + struct tx_desc *td; + int qnum; + int full = 0; + int idx; + int works = 0; + struct velocity_td_info *tdinfo; + struct net_device_stats *stats = &vptr->stats; + + for (qnum = 0; qnum < vptr->num_txq; qnum++) { + for (idx = vptr->td_tail[qnum]; vptr->td_used[qnum] > 0; + idx = (idx + 1) % vptr->options.numtx) { + + /* + * Get Tx Descriptor + */ + td = &(vptr->td_rings[qnum][idx]); + tdinfo = &(vptr->td_infos[qnum][idx]); + + if (td->tdesc0.owner == OWNED_BY_NIC) + break; + + if ((works++ > 15)) + break; + + if (td->tdesc0.TSR & TSR0_TERR) { + stats->tx_errors++; + stats->tx_dropped++; + if (td->tdesc0.TSR & TSR0_CDH) + stats->tx_heartbeat_errors++; + if (td->tdesc0.TSR & TSR0_CRS) + stats->tx_carrier_errors++; + if (td->tdesc0.TSR & TSR0_ABT) + stats->tx_aborted_errors++; + if (td->tdesc0.TSR & TSR0_OWC) + stats->tx_window_errors++; + } else { + stats->tx_packets++; + stats->tx_bytes += tdinfo->skb->len; + } + velocity_free_tx_buf(vptr, tdinfo); + vptr->td_used[qnum]--; + } + vptr->td_tail[qnum] = idx; + + if (AVAIL_TD(vptr, qnum) < 1) { + full = 1; + } + } + /* + * Look to see if we should kick the transmit network + * layer for more work. + */ + if (netif_queue_stopped(vptr->dev) && (full == 0) + && (!(vptr->mii_status & VELOCITY_LINK_FAIL))) { + netif_wake_queue(vptr->dev); + } + return works; +} + +/** + * velocity_print_link_status - link status reporting + * @vptr: velocity to report on + * + * Turn the link status of the velocity card into a kernel log + * description of the new link state, detailing speed and duplex + * status + */ + +static void velocity_print_link_status(struct velocity_info *vptr) +{ + + if (vptr->mii_status & VELOCITY_LINK_FAIL) { + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name); + } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) { + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name); + + if (vptr->mii_status & VELOCITY_SPEED_1000) + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps"); + else if (vptr->mii_status & VELOCITY_SPEED_100) + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps"); + else + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps"); + + if (vptr->mii_status & VELOCITY_DUPLEX_FULL) + VELOCITY_PRT(MSG_LEVEL_INFO, " full duplex\n"); + else + VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n"); + } else { + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name); + switch (vptr->options.spd_dpx) { + case SPD_DPX_100_HALF: + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n"); + break; + case SPD_DPX_100_FULL: + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps full duplex\n"); + break; + case SPD_DPX_10_HALF: + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps half duplex\n"); + break; + case SPD_DPX_10_FULL: + VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps full duplex\n"); + break; + default: + break; + } + } +} + +/** + * velocity_error - handle error from controller + * @vptr: velocity + * @status: card status + * + * Process an error report from the hardware and attempt to recover + * the card itself. At the moment we cannot recover from some + * theoretically impossible errors but this could be fixed using + * the pci_device_failed logic to bounce the hardware + * + */ + +static void velocity_error(struct velocity_info *vptr, int status) +{ + + if (status & ISR_TXSTLI) { + struct mac_regs * regs = vptr->mac_regs; + + printk(KERN_ERR "TD structure errror TDindex=%hx\n", readw(®s->TDIdx[0])); + BYTE_REG_BITS_ON(TXESR_TDSTR, ®s->TXESR); + writew(TRDCSR_RUN, ®s->TDCSRClr); + netif_stop_queue(vptr->dev); + + /* FIXME: port over the pci_device_failed code and use it + here */ + } + + if (status & ISR_SRCI) { + struct mac_regs * regs = vptr->mac_regs; + int linked; + + if (vptr->options.spd_dpx == SPD_DPX_AUTO) { + vptr->mii_status = check_connection_type(regs); + + /* + * If it is a 3119, disable frame bursting in + * halfduplex mode and enable it in fullduplex + * mode + */ + if (vptr->rev_id < REV_ID_VT3216_A0) { + if (vptr->mii_status | VELOCITY_DUPLEX_FULL) + BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); + else + BYTE_REG_BITS_OFF(TCR_TB2BDIS, ®s->TCR); + } + /* + * Only enable CD heart beat counter in 10HD mode + */ + if (!(vptr->mii_status & VELOCITY_DUPLEX_FULL) && (vptr->mii_status & VELOCITY_SPEED_10)) { + BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG); + } else { + BYTE_REG_BITS_ON(TESTCFG_HBDIS, ®s->TESTCFG); + } + } + /* + * Get link status from PHYSR0 + */ + linked = readb(®s->PHYSR0) & PHYSR0_LINKGD; + + if (linked) { + vptr->mii_status &= ~VELOCITY_LINK_FAIL; + } else { + vptr->mii_status |= VELOCITY_LINK_FAIL; + } + + velocity_print_link_status(vptr); + enable_flow_control_ability(vptr); + + /* + * Re-enable auto-polling because SRCI will disable + * auto-polling + */ + + enable_mii_autopoll(regs); + + if (vptr->mii_status & VELOCITY_LINK_FAIL) + netif_stop_queue(vptr->dev); + else + netif_wake_queue(vptr->dev); + + }; + if (status & ISR_MIBFI) + velocity_update_hw_mibs(vptr); + if (status & ISR_LSTEI) + mac_rx_queue_wake(vptr->mac_regs); +} + +/** + * velocity_free_tx_buf - free transmit buffer + * @vptr: velocity + * @tdinfo: buffer + * + * Release an transmit buffer. If the buffer was preallocated then + * recycle it, if not then unmap the buffer. + */ + +static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *tdinfo) +{ + struct sk_buff *skb = tdinfo->skb; + int i; + + /* + * Don't unmap the pre-allocated tx_bufs + */ + if (tdinfo->skb_dma && (tdinfo->skb_dma[0] != tdinfo->buf_dma)) { + + for (i = 0; i < tdinfo->nskb_dma; i++) { +#ifdef VELOCITY_ZERO_COPY_SUPPORT + pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], td->tdesc1.len, PCI_DMA_TODEVICE); +#else + pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE); +#endif + tdinfo->skb_dma[i] = 0; + } + } + dev_kfree_skb_irq(skb); + tdinfo->skb = NULL; +} + +/** + * velocity_open - interface activation callback + * @dev: network layer device to open + * + * Called when the network layer brings the interface up. Returns + * a negative posix error code on failure, or zero on success. + * + * All the ring allocation and set up is done on open for this + * adapter to minimise memory usage when inactive + */ + +static int velocity_open(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + int ret; + + vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32); + + ret = velocity_init_rings(vptr); + if (ret < 0) + goto out; + + ret = velocity_init_rd_ring(vptr); + if (ret < 0) + goto err_free_desc_rings; + + ret = velocity_init_td_ring(vptr); + if (ret < 0) + goto err_free_rd_ring; + + /* Ensure chip is running */ + pci_set_power_state(vptr->pdev, 0); + + velocity_init_registers(vptr, VELOCITY_INIT_COLD); + + ret = request_irq(vptr->pdev->irq, &velocity_intr, SA_SHIRQ, + dev->name, dev); + if (ret < 0) { + /* Power down the chip */ + pci_set_power_state(vptr->pdev, 3); + goto err_free_td_ring; + } + + mac_enable_int(vptr->mac_regs); + netif_start_queue(dev); + vptr->flags |= VELOCITY_FLAGS_OPENED; +out: + return ret; + +err_free_td_ring: + velocity_free_td_ring(vptr); +err_free_rd_ring: + velocity_free_rd_ring(vptr); +err_free_desc_rings: + velocity_free_rings(vptr); + goto out; +} + +/** + * velocity_change_mtu - MTU change callback + * @dev: network device + * @new_mtu: desired MTU + * + * Handle requests from the networking layer for MTU change on + * this interface. It gets called on a change by the network layer. + * Return zero for success or negative posix error code. + */ + +static int velocity_change_mtu(struct net_device *dev, int new_mtu) +{ + struct velocity_info *vptr = dev->priv; + unsigned long flags; + int oldmtu = dev->mtu; + int ret = 0; + + if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) { + VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", + vptr->dev->name); + return -EINVAL; + } + + if (new_mtu != oldmtu) { + spin_lock_irqsave(&vptr->lock, flags); + + netif_stop_queue(dev); + velocity_shutdown(vptr); + + velocity_free_td_ring(vptr); + velocity_free_rd_ring(vptr); + + dev->mtu = new_mtu; + if (new_mtu > 8192) + vptr->rx_buf_sz = 9 * 1024; + else if (new_mtu > 4096) + vptr->rx_buf_sz = 8192; + else + vptr->rx_buf_sz = 4 * 1024; + + ret = velocity_init_rd_ring(vptr); + if (ret < 0) + goto out_unlock; + + ret = velocity_init_td_ring(vptr); + if (ret < 0) + goto out_unlock; + + velocity_init_registers(vptr, VELOCITY_INIT_COLD); + + mac_enable_int(vptr->mac_regs); + netif_start_queue(dev); +out_unlock: + spin_unlock_irqrestore(&vptr->lock, flags); + } + + return ret; +} + +/** + * velocity_shutdown - shut down the chip + * @vptr: velocity to deactivate + * + * Shuts down the internal operations of the velocity and + * disables interrupts, autopolling, transmit and receive + */ + +static void velocity_shutdown(struct velocity_info *vptr) +{ + struct mac_regs * regs = vptr->mac_regs; + mac_disable_int(regs); + writel(CR0_STOP, ®s->CR0Set); + writew(0xFFFF, ®s->TDCSRClr); + writeb(0xFF, ®s->RDCSRClr); + safe_disable_mii_autopoll(regs); + mac_clear_isr(regs); +} + +/** + * velocity_close - close adapter callback + * @dev: network device + * + * Callback from the network layer when the velocity is being + * deactivated by the network layer + */ + +static int velocity_close(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + + netif_stop_queue(dev); + velocity_shutdown(vptr); + + if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) + velocity_get_ip(vptr); + if (dev->irq != 0) + free_irq(dev->irq, dev); + + /* Power down the chip */ + pci_set_power_state(vptr->pdev, 3); + + /* Free the resources */ + velocity_free_td_ring(vptr); + velocity_free_rd_ring(vptr); + velocity_free_rings(vptr); + + vptr->flags &= (~VELOCITY_FLAGS_OPENED); + return 0; +} + +/** + * velocity_xmit - transmit packet callback + * @skb: buffer to transmit + * @dev: network device + * + * Called by the networ layer to request a packet is queued to + * the velocity. Returns zero on success. + */ + +static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + int qnum = 0; + struct tx_desc *td_ptr; + struct velocity_td_info *tdinfo; + unsigned long flags; + int index; + + int pktlen = skb->len; + + spin_lock_irqsave(&vptr->lock, flags); + + index = vptr->td_curr[qnum]; + td_ptr = &(vptr->td_rings[qnum][index]); + tdinfo = &(vptr->td_infos[qnum][index]); + + td_ptr->tdesc1.TCPLS = TCPLS_NORMAL; + td_ptr->tdesc1.TCR = TCR0_TIC; + td_ptr->td_buf[0].queue = 0; + + /* + * Pad short frames. + */ + if (pktlen < ETH_ZLEN) { + /* Cannot occur until ZC support */ + if(skb_linearize(skb, GFP_ATOMIC)) + return 0; + pktlen = ETH_ZLEN; + memcpy(tdinfo->buf, skb->data, skb->len); + memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len); + tdinfo->skb = skb; + tdinfo->skb_dma[0] = tdinfo->buf_dma; + td_ptr->tdesc0.pktsize = pktlen; + td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]); + td_ptr->td_buf[0].pa_high = 0; + td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize; + tdinfo->nskb_dma = 1; + td_ptr->tdesc1.CMDZ = 2; + } else +#ifdef VELOCITY_ZERO_COPY_SUPPORT + if (skb_shinfo(skb)->nr_frags > 0) { + int nfrags = skb_shinfo(skb)->nr_frags; + tdinfo->skb = skb; + if (nfrags > 6) { + skb_linearize(skb, GFP_ATOMIC); + memcpy(tdinfo->buf, skb->data, skb->len); + tdinfo->skb_dma[0] = tdinfo->buf_dma; + td_ptr->tdesc0.pktsize = + td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]); + td_ptr->td_buf[0].pa_high = 0; + td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize; + tdinfo->nskb_dma = 1; + td_ptr->tdesc1.CMDZ = 2; + } else { + int i = 0; + tdinfo->nskb_dma = 0; + tdinfo->skb_dma[i] = pci_map_single(vptr->pdev, skb->data, skb->len - skb->data_len, PCI_DMA_TODEVICE); + + td_ptr->tdesc0.pktsize = pktlen; + + /* FIXME: support 48bit DMA later */ + td_ptr->td_buf[i].pa_low = cpu_to_le32(tdinfo->skb_dma); + td_ptr->td_buf[i].pa_high = 0; + td_ptr->td_buf[i].bufsize = skb->len->skb->data_len; + + for (i = 0; i < nfrags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + void *addr = ((void *) page_address(frag->page + frag->page_offset)); + + tdinfo->skb_dma[i + 1] = pci_map_single(vptr->pdev, addr, frag->size, PCI_DMA_TODEVICE); + + td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]); + td_ptr->td_buf[i + 1].pa_high = 0; + td_ptr->td_buf[i + 1].bufsize = frag->size; + } + tdinfo->nskb_dma = i - 1; + td_ptr->tdesc1.CMDZ = i; + } + + } else +#endif + { + /* + * Map the linear network buffer into PCI space and + * add it to the transmit ring. + */ + tdinfo->skb = skb; + tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE); + td_ptr->tdesc0.pktsize = pktlen; + td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]); + td_ptr->td_buf[0].pa_high = 0; + td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize; + tdinfo->nskb_dma = 1; + td_ptr->tdesc1.CMDZ = 2; + } + + if (vptr->flags & VELOCITY_FLAGS_TAGGING) { + td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff); + td_ptr->tdesc1.pqinf.priority = 0; + td_ptr->tdesc1.pqinf.CFI = 0; + td_ptr->tdesc1.TCR |= TCR0_VETAG; + } + + /* + * Handle hardware checksum + */ + if ((vptr->flags & VELOCITY_FLAGS_TX_CSUM) + && (skb->ip_summed == CHECKSUM_HW)) { + struct iphdr *ip = skb->nh.iph; + if (ip->protocol == IPPROTO_TCP) + td_ptr->tdesc1.TCR |= TCR0_TCPCK; + else if (ip->protocol == IPPROTO_UDP) + td_ptr->tdesc1.TCR |= (TCR0_UDPCK); + td_ptr->tdesc1.TCR |= TCR0_IPCK; + } + { + + int prev = index - 1; + + if (prev < 0) + prev = vptr->options.numtx - 1; + td_ptr->tdesc0.owner = OWNED_BY_NIC; + vptr->td_used[qnum]++; + vptr->td_curr[qnum] = (index + 1) % vptr->options.numtx; + + if (AVAIL_TD(vptr, qnum) < 1) + netif_stop_queue(dev); + + td_ptr = &(vptr->td_rings[qnum][prev]); + td_ptr->td_buf[0].queue = 1; + mac_tx_queue_wake(vptr->mac_regs, qnum); + } + dev->trans_start = jiffies; + spin_unlock_irqrestore(&vptr->lock, flags); + return 0; +} + +/** + * velocity_intr - interrupt callback + * @irq: interrupt number + * @dev_instance: interrupting device + * @pt_regs: CPU register state at interrupt + * + * Called whenever an interrupt is generated by the velocity + * adapter IRQ line. We may not be the source of the interrupt + * and need to identify initially if we are, and if not exit as + * efficiently as possible. + */ + +static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *dev = dev_instance; + struct velocity_info *vptr = dev->priv; + u32 isr_status; + int max_count = 0; + + + spin_lock(&vptr->lock); + isr_status = mac_read_isr(vptr->mac_regs); + + /* Not us ? */ + if (isr_status == 0) { + spin_unlock(&vptr->lock); + return IRQ_NONE; + } + + mac_disable_int(vptr->mac_regs); + + /* + * Keep processing the ISR until we have completed + * processing and the isr_status becomes zero + */ + + while (isr_status != 0) { + mac_write_isr(vptr->mac_regs, isr_status); + if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI))) + velocity_error(vptr, isr_status); + if (isr_status & (ISR_PRXI | ISR_PPRXI)) + max_count += velocity_rx_srv(vptr, isr_status); + if (isr_status & (ISR_PTXI | ISR_PPTXI)) + max_count += velocity_tx_srv(vptr, isr_status); + isr_status = mac_read_isr(vptr->mac_regs); + if (max_count > vptr->options.int_works) + { + printk(KERN_WARNING "%s: excessive work at interrupt.\n", + dev->name); + max_count = 0; + } + } + spin_unlock(&vptr->lock); + mac_enable_int(vptr->mac_regs); + return IRQ_HANDLED; + +} + + +/** + * ether_crc - ethernet CRC function + * + * Compute an ethernet CRC hash of the data block provided. This + * is not performance optimised but is not needed in performance + * critical code paths. + * + * FIXME: could we use shared code here ? + */ + +static inline u32 ether_crc(int length, unsigned char *data) +{ + static unsigned const ethernet_polynomial = 0x04c11db7U; + + int crc = -1; + + while (--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) { + crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + } + return crc; +} + +/** + * velocity_set_multi - filter list change callback + * @dev: network device + * + * Called by the network layer when the filter lists need to change + * for a velocity adapter. Reload the CAMs with the new address + * filter ruleset. + */ + +static void velocity_set_multi(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + struct mac_regs * regs = vptr->mac_regs; + u8 rx_mode; + int i; + struct dev_mc_list *mclist; + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + /* Unconditionally log net taps. */ + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + writel(0xffffffff, ®s->MARCAM[0]); + writel(0xffffffff, ®s->MARCAM[4]); + rx_mode = (RCR_AM | RCR_AB | RCR_PROM); + } else if ((dev->mc_count > vptr->multicast_limit) + || (dev->flags & IFF_ALLMULTI)) { + writel(0xffffffff, ®s->MARCAM[0]); + writel(0xffffffff, ®s->MARCAM[4]); + rx_mode = (RCR_AM | RCR_AB); + } else { + int offset = MCAM_SIZE - vptr->multicast_limit; + mac_get_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM); + + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { + mac_set_cam(regs, i + offset, mclist->dmi_addr, VELOCITY_MULTICAST_CAM); + vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7); + } + + mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM); + rx_mode = (RCR_AM | RCR_AB); + } + if (dev->mtu > 1500) + rx_mode |= RCR_AL; + + BYTE_REG_BITS_ON(rx_mode, ®s->RCR); + +} + +/** + * velocity_get_status - statistics callback + * @dev: network device + * + * Callback from the network layer to allow driver statistics + * to be resynchronized with hardware collected state. In the + * case of the velocity we need to pull the MIB counters from + * the hardware into the counters before letting the network + * layer display them. + */ + +static struct net_device_stats *velocity_get_stats(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + + /* If the hardware is down, don't touch MII */ + if(!netif_running(dev)) + return &vptr->stats; + + spin_lock_irq(&vptr->lock); + velocity_update_hw_mibs(vptr); + spin_unlock_irq(&vptr->lock); + + vptr->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts]; + vptr->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts]; + vptr->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors]; + +// unsigned long rx_dropped; /* no space in linux buffers */ + vptr->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions]; + /* detailed rx_errors: */ +// unsigned long rx_length_errors; +// unsigned long rx_over_errors; /* receiver ring buff overflow */ + vptr->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE]; +// unsigned long rx_frame_errors; /* recv'd frame alignment error */ +// unsigned long rx_fifo_errors; /* recv'r fifo overrun */ +// unsigned long rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ +// unsigned long tx_fifo_errors; + + return &vptr->stats; +} + + +/** + * velocity_ioctl - ioctl entry point + * @dev: network device + * @rq: interface request ioctl + * @cmd: command code + * + * Called when the user issues an ioctl request to the network + * device in question. The velocity interface supports MII. + */ + +static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct velocity_info *vptr = dev->priv; + int ret; + + /* If we are asked for information and the device is power + saving then we need to bring the device back up to talk to it */ + + if(!netif_running(dev)) + pci_set_power_state(vptr->pdev, 0); + + switch (cmd) { + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCSMIIREG: /* Write to MII PHY register. */ + ret = velocity_mii_ioctl(dev, rq, cmd); + break; + + default: + ret = -EOPNOTSUPP; + } + if(!netif_running(dev)) + pci_set_power_state(vptr->pdev, 3); + + + return ret; +} + +/* + * Definition for our device driver. The PCI layer interface + * uses this to handle all our card discover and plugging + */ + +static struct pci_driver velocity_driver = { + name:VELOCITY_NAME, + id_table:velocity_id_table, + probe:velocity_found1, + remove:velocity_remove1, +#ifdef CONFIG_PM + suspend:velocity_suspend, + resume:velocity_resume, +#endif +}; + +/** + * velocity_init_module - load time function + * + * Called when the velocity module is loaded. The PCI driver + * is registered with the PCI layer, and in turn will call + * the probe functions for each velocity adapter installed + * in the system. + */ + +static int __init velocity_init_module(void) +{ + int ret; + ret = pci_module_init(&velocity_driver); + +#ifdef CONFIG_PM + register_inetaddr_notifier(&velocity_inetaddr_notifier); +#endif + return ret; +} + +/** + * velocity_cleanup - module unload + * + * When the velocity hardware is unloaded this function is called. + * It will clean up the notifiers and the unregister the PCI + * driver interface for this hardware. This in turn cleans up + * all discovered interfaces before returning from the function + */ + +static void __exit velocity_cleanup_module(void) +{ +#ifdef CONFIG_PM + unregister_inetaddr_notifier(&velocity_inetaddr_notifier); +#endif + pci_unregister_driver(&velocity_driver); +} + +module_init(velocity_init_module); +module_exit(velocity_cleanup_module); + + +/* + * MII access , media link mode setting functions + */ + + +/** + * mii_init - set up MII + * @vptr: velocity adapter + * @mii_status: links tatus + * + * Set up the PHY for the current link state. + */ + +static void mii_init(struct velocity_info *vptr, u32 mii_status) +{ + u16 BMCR; + + switch (PHYID_GET_PHY_ID(vptr->phy_id)) { + case PHYID_CICADA_CS8201: + /* + * Reset to hardware default + */ + MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs); + /* + * Turn on ECHODIS bit in NWay-forced full mode and turn it + * off it in NWay-forced half mode for NWay-forced v.s. + * legacy-forced issue. + */ + if (vptr->mii_status & VELOCITY_DUPLEX_FULL) + MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs); + else + MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs); + /* + * Turn on Link/Activity LED enable bit for CIS8201 + */ + MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs); + break; + case PHYID_VT3216_32BIT: + case PHYID_VT3216_64BIT: + /* + * Reset to hardware default + */ + MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs); + /* + * Turn on ECHODIS bit in NWay-forced full mode and turn it + * off it in NWay-forced half mode for NWay-forced v.s. + * legacy-forced issue + */ + if (vptr->mii_status & VELOCITY_DUPLEX_FULL) + MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs); + else + MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR, vptr->mac_regs); + break; + + case PHYID_MARVELL_1000: + case PHYID_MARVELL_1000S: + /* + * Assert CRS on Transmit + */ + MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs); + /* + * Reset to hardware default + */ + MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR, vptr->mac_regs); + break; + default: + ; + } + velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR); + if (BMCR & BMCR_ISO) { + BMCR &= ~BMCR_ISO; + velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR); + } +} + +/** + * safe_disable_mii_autopoll - autopoll off + * @regs: velocity registers + * + * Turn off the autopoll and wait for it to disable on the chip + */ + +static void safe_disable_mii_autopoll(struct mac_regs * regs) +{ + u16 ww; + + /* turn off MAUTO */ + writeb(0, ®s->MIICR); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(1); + if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, ®s->MIISR)) + break; + } +} + +/** + * enable_mii_autopoll - turn on autopolling + * @regs: velocity registers + * + * Enable the MII link status autopoll feature on the Velocity + * hardware. Wait for it to enable. + */ + +static void enable_mii_autopoll(struct mac_regs * regs) +{ + int ii; + + writeb(0, &(regs->MIICR)); + writeb(MIIADR_SWMPL, ®s->MIIADR); + + for (ii = 0; ii < W_MAX_TIMEOUT; ii++) { + udelay(1); + if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, ®s->MIISR)) + break; + } + + writeb(MIICR_MAUTO, ®s->MIICR); + + for (ii = 0; ii < W_MAX_TIMEOUT; ii++) { + udelay(1); + if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, ®s->MIISR)) + break; + } + +} + +/** + * velocity_mii_read - read MII data + * @regs: velocity registers + * @index: MII register index + * @data: buffer for received data + * + * Perform a single read of an MII 16bit register. Returns zero + * on success or -ETIMEDOUT if the PHY did not respond. + */ + +static int velocity_mii_read(struct mac_regs * regs, u8 index, u16 *data) +{ + u16 ww; + + /* + * Disable MIICR_MAUTO, so that mii addr can be set normally + */ + safe_disable_mii_autopoll(regs); + + writeb(index, ®s->MIIADR); + + BYTE_REG_BITS_ON(MIICR_RCMD, ®s->MIICR); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(readb(®s->MIICR) & MIICR_RCMD)) + break; + } + + *data = readw(®s->MIIDATA); + + enable_mii_autopoll(regs); + if (ww == W_MAX_TIMEOUT) + return -ETIMEDOUT; + return 0; +} + +/** + * velocity_mii_write - write MII data + * @regs: velocity registers + * @index: MII register index + * @data: 16bit data for the MII register + * + * Perform a single write to an MII 16bit register. Returns zero + * on success or -ETIMEDOUT if the PHY did not respond. + */ + +static int velocity_mii_write(struct mac_regs * regs, u8 mii_addr, u16 data) +{ + u16 ww; + + /* + * Disable MIICR_MAUTO, so that mii addr can be set normally + */ + safe_disable_mii_autopoll(regs); + + /* MII reg offset */ + writeb(mii_addr, ®s->MIIADR); + /* set MII data */ + writew(data, ®s->MIIDATA); + + /* turn on MIICR_WCMD */ + BYTE_REG_BITS_ON(MIICR_WCMD, ®s->MIICR); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + udelay(5); + if (!(readb(®s->MIICR) & MIICR_WCMD)) + break; + } + enable_mii_autopoll(regs); + + if (ww == W_MAX_TIMEOUT) + return -ETIMEDOUT; + return 0; +} + +/** + * velocity_get_opt_media_mode - get media selection + * @vptr: velocity adapter + * + * Get the media mode stored in EEPROM or module options and load + * mii_status accordingly. The requested link state information + * is also returned. + */ + +static u32 velocity_get_opt_media_mode(struct velocity_info *vptr) +{ + u32 status = 0; + + switch (vptr->options.spd_dpx) { + case SPD_DPX_AUTO: + status = VELOCITY_AUTONEG_ENABLE; + break; + case SPD_DPX_100_FULL: + status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL; + break; + case SPD_DPX_10_FULL: + status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL; + break; + case SPD_DPX_100_HALF: + status = VELOCITY_SPEED_100; + break; + case SPD_DPX_10_HALF: + status = VELOCITY_SPEED_10; + break; + } + vptr->mii_status = status; + return status; +} + +/** + * mii_set_auto_on - autonegotiate on + * @vptr: velocity + * + * Enable autonegotation on this interface + */ + +static void mii_set_auto_on(struct velocity_info *vptr) +{ + if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs)) + MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs); + else + MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); +} + + +/* +static void mii_set_auto_off(struct velocity_info * vptr) +{ + MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); +} +*/ + +/** + * set_mii_flow_control - flow control setup + * @vptr: velocity interface + * + * Set up the flow control on this interface according to + * the supplied user/eeprom options. + */ + +static void set_mii_flow_control(struct velocity_info *vptr) +{ + /*Enable or Disable PAUSE in ANAR */ + switch (vptr->options.flow_cntl) { + case FLOW_CNTL_TX: + MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); + MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); + break; + + case FLOW_CNTL_RX: + MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); + MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); + break; + + case FLOW_CNTL_TX_RX: + MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); + MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); + break; + + case FLOW_CNTL_DISABLE: + MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs); + MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs); + break; + default: + break; + } +} + +/** + * velocity_set_media_mode - set media mode + * @mii_status: old MII link state + * + * Check the media link state and configure the flow control + * PHY and also velocity hardware setup accordingly. In particular + * we need to set up CD polling and frame bursting. + */ + +static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) +{ + u32 curr_status; + struct mac_regs * regs = vptr->mac_regs; + + vptr->mii_status = mii_check_media_mode(vptr->mac_regs); + curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL); + + /* Set mii link status */ + set_mii_flow_control(vptr); + + /* + Check if new status is consisent with current status + if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE) + || (mii_status==curr_status)) { + vptr->mii_status=mii_check_media_mode(vptr->mac_regs); + vptr->mii_status=check_connection_type(vptr->mac_regs); + VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity link no change\n"); + return 0; + } + */ + + if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) { + MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs); + } + + /* + * If connection type is AUTO + */ + if (mii_status & VELOCITY_AUTONEG_ENABLE) { + VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity is AUTO mode\n"); + /* clear force MAC mode bit */ + BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, ®s->CHIPGCR); + /* set duplex mode of MAC according to duplex mode of MII */ + MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10, MII_REG_ANAR, vptr->mac_regs); + MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs); + MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); + + /* enable AUTO-NEGO mode */ + mii_set_auto_on(vptr); + } else { + u16 ANAR; + u8 CHIPGCR; + + /* + * 1. if it's 3119, disable frame bursting in halfduplex mode + * and enable it in fullduplex mode + * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR + * 3. only enable CD heart beat counter in 10HD mode + */ + + /* set force MAC mode bit */ + BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR); + + CHIPGCR = readb(®s->CHIPGCR); + CHIPGCR &= ~CHIPGCR_FCGMII; + + if (mii_status & VELOCITY_DUPLEX_FULL) { + CHIPGCR |= CHIPGCR_FCFDX; + writeb(CHIPGCR, ®s->CHIPGCR); + VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced full mode\n"); + if (vptr->rev_id < REV_ID_VT3216_A0) + BYTE_REG_BITS_OFF(TCR_TB2BDIS, ®s->TCR); + } else { + CHIPGCR &= ~CHIPGCR_FCFDX; + VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced half mode\n"); + writeb(CHIPGCR, ®s->CHIPGCR); + if (vptr->rev_id < REV_ID_VT3216_A0) + BYTE_REG_BITS_ON(TCR_TB2BDIS, ®s->TCR); + } + + MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs); + + if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10)) { + BYTE_REG_BITS_OFF(TESTCFG_HBDIS, ®s->TESTCFG); + } else { + BYTE_REG_BITS_ON(TESTCFG_HBDIS, ®s->TESTCFG); + } + /* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */ + velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR); + ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)); + if (mii_status & VELOCITY_SPEED_100) { + if (mii_status & VELOCITY_DUPLEX_FULL) + ANAR |= ANAR_TXFD; + else + ANAR |= ANAR_TX; + } else { + if (mii_status & VELOCITY_DUPLEX_FULL) + ANAR |= ANAR_10FD; + else + ANAR |= ANAR_10; + } + velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR); + /* enable AUTO-NEGO mode */ + mii_set_auto_on(vptr); + /* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */ + } + /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */ + /* vptr->mii_status=check_connection_type(vptr->mac_regs); */ + return VELOCITY_LINK_CHANGE; +} + +/** + * mii_check_media_mode - check media state + * @regs: velocity registers + * + * Check the current MII status and determine the link status + * accordingly + */ + +static u32 mii_check_media_mode(struct mac_regs * regs) +{ + u32 status = 0; + u16 ANAR; + + if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs)) + status |= VELOCITY_LINK_FAIL; + + if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs)) + status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL; + else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs)) + status |= (VELOCITY_SPEED_1000); + else { + velocity_mii_read(regs, MII_REG_ANAR, &ANAR); + if (ANAR & ANAR_TXFD) + status |= (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL); + else if (ANAR & ANAR_TX) + status |= VELOCITY_SPEED_100; + else if (ANAR & ANAR_10FD) + status |= (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL); + else + status |= (VELOCITY_SPEED_10); + } + + if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) { + velocity_mii_read(regs, MII_REG_ANAR, &ANAR); + if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) + == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) { + if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs)) + status |= VELOCITY_AUTONEG_ENABLE; + } + } + + return status; +} + +static u32 check_connection_type(struct mac_regs * regs) +{ + u32 status = 0; + u8 PHYSR0; + u16 ANAR; + PHYSR0 = readb(®s->PHYSR0); + + /* + if (!(PHYSR0 & PHYSR0_LINKGD)) + status|=VELOCITY_LINK_FAIL; + */ + + if (PHYSR0 & PHYSR0_FDPX) + status |= VELOCITY_DUPLEX_FULL; + + if (PHYSR0 & PHYSR0_SPDG) + status |= VELOCITY_SPEED_1000; + if (PHYSR0 & PHYSR0_SPD10) + status |= VELOCITY_SPEED_10; + else + status |= VELOCITY_SPEED_100; + + if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) { + velocity_mii_read(regs, MII_REG_ANAR, &ANAR); + if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) + == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) { + if (MII_REG_BITS_IS_ON(G1000CR_1000 | G1000CR_1000FD, MII_REG_G1000CR, regs)) + status |= VELOCITY_AUTONEG_ENABLE; + } + } + + return status; +} + +/** + * enable_flow_control_ability - flow control + * @vptr: veloity to configure + * + * Set up flow control according to the flow control options + * determined by the eeprom/configuration. + */ + +static void enable_flow_control_ability(struct velocity_info *vptr) +{ + + struct mac_regs * regs = vptr->mac_regs; + + switch (vptr->options.flow_cntl) { + + case FLOW_CNTL_DEFAULT: + if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, ®s->PHYSR0)) + writel(CR0_FDXRFCEN, ®s->CR0Set); + else + writel(CR0_FDXRFCEN, ®s->CR0Clr); + + if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, ®s->PHYSR0)) + writel(CR0_FDXTFCEN, ®s->CR0Set); + else + writel(CR0_FDXTFCEN, ®s->CR0Clr); + break; + + case FLOW_CNTL_TX: + writel(CR0_FDXTFCEN, ®s->CR0Set); + writel(CR0_FDXRFCEN, ®s->CR0Clr); + break; + + case FLOW_CNTL_RX: + writel(CR0_FDXRFCEN, ®s->CR0Set); + writel(CR0_FDXTFCEN, ®s->CR0Clr); + break; + + case FLOW_CNTL_TX_RX: + writel(CR0_FDXTFCEN, ®s->CR0Set); + writel(CR0_FDXRFCEN, ®s->CR0Set); + break; + + case FLOW_CNTL_DISABLE: + writel(CR0_FDXRFCEN, ®s->CR0Clr); + writel(CR0_FDXTFCEN, ®s->CR0Clr); + break; + + default: + break; + } + +} + + +/** + * velocity_ethtool_up - pre hook for ethtool + * @dev: network device + * + * Called before an ethtool operation. We need to make sure the + * chip is out of D3 state before we poke at it. + */ + +static int velocity_ethtool_up(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + if(!netif_running(dev)) + pci_set_power_state(vptr->pdev, 0); + return 0; +} + +/** + * velocity_ethtool_down - post hook for ethtool + * @dev: network device + * + * Called after an ethtool operation. Restore the chip back to D3 + * state if it isn't running. + */ + +static void velocity_ethtool_down(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + if(!netif_running(dev)) + pci_set_power_state(vptr->pdev, 3); +} + +static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct velocity_info *vptr = dev->priv; + struct mac_regs * regs = vptr->mac_regs; + u32 status; + status = check_connection_type(vptr->mac_regs); + + cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; + if (status & VELOCITY_SPEED_100) + cmd->speed = SPEED_100; + else + cmd->speed = SPEED_10; + cmd->autoneg = (status & VELOCITY_AUTONEG_ENABLE) ? AUTONEG_ENABLE : AUTONEG_DISABLE; + cmd->port = PORT_TP; + cmd->transceiver = XCVR_INTERNAL; + cmd->phy_address = readb(®s->MIIADR) & 0x1F; + + if (status & VELOCITY_DUPLEX_FULL) + cmd->duplex = DUPLEX_FULL; + else + cmd->duplex = DUPLEX_HALF; + + return 0; +} + +static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct velocity_info *vptr = dev->priv; + u32 curr_status; + u32 new_status = 0; + int ret = 0; + + curr_status = check_connection_type(vptr->mac_regs); + curr_status &= (~VELOCITY_LINK_FAIL); + + new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); + new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0); + new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0); + new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); + + if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) + ret = -EINVAL; + else + velocity_set_media_mode(vptr, new_status); + + return ret; +} + +static u32 velocity_get_link(struct net_device *dev) +{ + struct velocity_info *vptr = dev->priv; + struct mac_regs * regs = vptr->mac_regs; + return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 0 : 1; +} + +static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct velocity_info *vptr = dev->priv; + strcpy(info->driver, VELOCITY_NAME); + strcpy(info->version, VELOCITY_VERSION); + strcpy(info->bus_info, vptr->pdev->slot_name); +} + +static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct velocity_info *vptr = dev->priv; + wol->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP; + wol->wolopts |= WAKE_MAGIC; + /* + if (vptr->wol_opts & VELOCITY_WOL_PHY) + wol.wolopts|=WAKE_PHY; + */ + if (vptr->wol_opts & VELOCITY_WOL_UCAST) + wol->wolopts |= WAKE_UCAST; + if (vptr->wol_opts & VELOCITY_WOL_ARP) + wol->wolopts |= WAKE_ARP; + memcpy(&wol->sopass, vptr->wol_passwd, 6); +} + +static int velocity_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct velocity_info *vptr = dev->priv; + + if (!(wol->wolopts & (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP))) + return -EFAULT; + vptr->wol_opts = VELOCITY_WOL_MAGIC; + + /* + if (wol.wolopts & WAKE_PHY) { + vptr->wol_opts|=VELOCITY_WOL_PHY; + vptr->flags |=VELOCITY_FLAGS_WOL_ENABLED; + } + */ + + if (wol->wolopts & WAKE_MAGIC) { + vptr->wol_opts |= VELOCITY_WOL_MAGIC; + vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED; + } + if (wol->wolopts & WAKE_UCAST) { + vptr->wol_opts |= VELOCITY_WOL_UCAST; + vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED; + } + if (wol->wolopts & WAKE_ARP) { + vptr->wol_opts |= VELOCITY_WOL_ARP; + vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED; + } + memcpy(vptr->wol_passwd, wol->sopass, 6); + return 0; +} + +static u32 velocity_get_msglevel(struct net_device *dev) +{ + return msglevel; +} + +static void velocity_set_msglevel(struct net_device *dev, u32 value) +{ + msglevel = value; +} + +static struct ethtool_ops velocity_ethtool_ops = { + .get_settings = velocity_get_settings, + .set_settings = velocity_set_settings, + .get_drvinfo = velocity_get_drvinfo, + .get_wol = velocity_ethtool_get_wol, + .set_wol = velocity_ethtool_set_wol, + .get_msglevel = velocity_get_msglevel, + .set_msglevel = velocity_set_msglevel, + .get_link = velocity_get_link, + .begin = velocity_ethtool_up, + .complete = velocity_ethtool_down +}; + +/** + * velocity_mii_ioctl - MII ioctl handler + * @dev: network device + * @ifr: the ifreq block for the ioctl + * @cmd: the command + * + * Process MII requests made via ioctl from the network layer. These + * are used by tools like kudzu to interrogate the link state of the + * hardware + */ + +static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct velocity_info *vptr = dev->priv; + struct mac_regs * regs = vptr->mac_regs; + unsigned long flags; + struct mii_ioctl_data *miidata = (struct mii_ioctl_data *) &(ifr->ifr_data); + int err; + + switch (cmd) { + case SIOCGMIIPHY: + miidata->phy_id = readb(®s->MIIADR) & 0x1f; + break; + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if(velocity_mii_read(vptr->mac_regs, miidata->reg_num & 0x1f, &(miidata->val_out)) < 0) + return -ETIMEDOUT; + break; + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + spin_lock_irqsave(&vptr->lock, flags); + err = velocity_mii_write(vptr->mac_regs, miidata->reg_num & 0x1f, miidata->val_in); + spin_unlock_irqrestore(&vptr->lock, flags); + check_connection_type(vptr->mac_regs); + if(err) + return err; + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +#ifdef CONFIG_PM + +/** + * velocity_save_context - save registers + * @vptr: velocity + * @context: buffer for stored context + * + * Retrieve the current configuration from the velocity hardware + * and stash it in the context structure, for use by the context + * restore functions. This allows us to save things we need across + * power down states + */ + +static void velocity_save_context(struct velocity_info *vptr, struct velocity_context * context) +{ + struct mac_regs * regs = vptr->mac_regs; + u16 i; + u8 *ptr = (u8 *)regs; + + for (i = MAC_REG_PAR; i < MAC_REG_CR0_CLR; i += 4) + *((u32 *) (context->mac_reg + i)) = readl(ptr + i); + + for (i = MAC_REG_MAR; i < MAC_REG_TDCSR_CLR; i += 4) + *((u32 *) (context->mac_reg + i)) = readl(ptr + i); + + for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4) + *((u32 *) (context->mac_reg + i)) = readl(ptr + i); + +} + +/** + * velocity_restore_context - restore registers + * @vptr: velocity + * @context: buffer for stored context + * + * Reload the register configuration from the velocity context + * created by velocity_save_context. + */ + +static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context) +{ + struct mac_regs * regs = vptr->mac_regs; + int i; + u8 *ptr = (u8 *)regs; + + for (i = MAC_REG_PAR; i < MAC_REG_CR0_SET; i += 4) { + writel(*((u32 *) (context->mac_reg + i)), ptr + i); + } + + /* Just skip cr0 */ + for (i = MAC_REG_CR1_SET; i < MAC_REG_CR0_CLR; i++) { + /* Clear */ + writeb(~(*((u8 *) (context->mac_reg + i))), ptr + i + 4); + /* Set */ + writeb(*((u8 *) (context->mac_reg + i)), ptr + i); + } + + for (i = MAC_REG_MAR; i < MAC_REG_IMR; i += 4) { + writel(*((u32 *) (context->mac_reg + i)), ptr + i); + } + + for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4) { + writel(*((u32 *) (context->mac_reg + i)), ptr + i); + } + + for (i = MAC_REG_TDCSR_SET; i <= MAC_REG_RDCSR_SET; i++) { + writeb(*((u8 *) (context->mac_reg + i)), ptr + i); + } + +} + +static int velocity_suspend(struct pci_dev *pdev, u32 state) +{ + struct velocity_info *vptr = pci_get_drvdata(pdev); + unsigned long flags; + + if(!netif_running(vptr->dev)) + return 0; + + netif_device_detach(vptr->dev); + + spin_lock_irqsave(&vptr->lock, flags); + pci_save_state(pdev, vptr->pci_state); +#ifdef ETHTOOL_GWOL + if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) { + velocity_get_ip(vptr); + velocity_save_context(vptr, &vptr->context); + velocity_shutdown(vptr); + velocity_set_wol(vptr); + pci_enable_wake(pdev, 3, 1); + pci_set_power_state(pdev, 3); + } else { + velocity_save_context(vptr, &vptr->context); + velocity_shutdown(vptr); + pci_disable_device(pdev); + pci_set_power_state(pdev, state); + } +#else + pci_set_power_state(pdev, state); +#endif + spin_unlock_irqrestore(&vptr->lock, flags); + return 0; +} + +static int velocity_resume(struct pci_dev *pdev) +{ + struct velocity_info *vptr = pci_get_drvdata(pdev); + unsigned long flags; + int i; + + if(!netif_running(vptr->dev)) + return 0; + + pci_set_power_state(pdev, 0); + pci_enable_wake(pdev, 0, 0); + pci_restore_state(pdev, vptr->pci_state); + + mac_wol_reset(vptr->mac_regs); + + spin_lock_irqsave(&vptr->lock, flags); + velocity_restore_context(vptr, &vptr->context); + velocity_init_registers(vptr, VELOCITY_INIT_WOL); + mac_disable_int(vptr->mac_regs); + + velocity_tx_srv(vptr, 0); + + for (i = 0; i < vptr->num_txq; i++) { + if (vptr->td_used[i]) { + mac_tx_queue_wake(vptr->mac_regs, i); + } + } + + mac_enable_int(vptr->mac_regs); + spin_unlock_irqrestore(&vptr->lock, flags); + netif_device_attach(vptr->dev); + + return 0; +} + +static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; + struct net_device *dev; + struct velocity_info *vptr; + + if (ifa) { + dev = ifa->ifa_dev->dev; + vptr = dev->priv; + velocity_get_ip(vptr); + } + return NOTIFY_DONE; +} +#endif + +/* + * Purpose: Functions to set WOL. + */ + +const static unsigned short crc16_tab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + + +static u32 mask_pattern[2][4] = { + {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */ + {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} /* Magic Packet */ +}; + +/** + * ether_crc16 - compute ethernet CRC + * @len: buffer length + * @cp: buffer + * @crc16: initial CRC + * + * Compute a CRC value for a block of data. + * FIXME: can we use generic functions ? + */ + +static u16 ether_crc16(int len, u8 * cp, u16 crc16) +{ + while (len--) + crc16 = (crc16 >> 8) ^ crc16_tab[(crc16 ^ *cp++) & 0xff]; + return (crc16); +} + +/** + * bit_reverse - 16bit reverse + * @data: 16bit data t reverse + * + * Reverse the order of a 16bit value and return the reversed bits + */ + +static u16 bit_reverse(u16 data) +{ + u32 new = 0x00000000; + int ii; + + + for (ii = 0; ii < 16; ii++) { + new |= ((u32) (data & 1) << (31 - ii)); + data >>= 1; + } + + return (u16) (new >> 16); +} + +/** + * wol_calc_crc - WOL CRC + * @pattern: data pattern + * @mask_pattern: mask + * + * Compute the wake on lan crc hashes for the packet header + * we are interested in. + */ + +u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern) +{ + u16 crc = 0xFFFF; + u8 mask; + int i, j; + + for (i = 0; i < size; i++) { + mask = mask_pattern[i]; + + /* Skip this loop if the mask equals to zero */ + if (mask == 0x00) + continue; + + for (j = 0; j < 8; j++) { + if ((mask & 0x01) == 0) { + mask >>= 1; + continue; + } + mask >>= 1; + crc = ether_crc16(1, &(pattern[i * 8 + j]), crc); + } + } + /* Finally, invert the result once to get the correct data */ + crc = ~crc; + return bit_reverse(crc); +} + +/** + * velocity_set_wol - set up for wake on lan + * @vptr: velocity to set WOL status on + * + * Set a card up for wake on lan either by unicast or by + * ARP packet. + * + * FIXME: check static buffer is safe here + */ + +static int velocity_set_wol(struct velocity_info *vptr) +{ + struct mac_regs * regs = vptr->mac_regs; + static u8 buf[256]; + int i; + + writew(0xFFFF, ®s->WOLCRClr); + writeb(WOLCFG_SAB | WOLCFG_SAM, ®s->WOLCFGSet); + writew(WOLCR_MAGIC_EN, ®s->WOLCRSet); + + /* + if (vptr->wol_opts & VELOCITY_WOL_PHY) + writew((WOLCR_LINKON_EN|WOLCR_LINKOFF_EN), ®s->WOLCRSet); + */ + + if (vptr->wol_opts & VELOCITY_WOL_UCAST) { + writew(WOLCR_UNICAST_EN, ®s->WOLCRSet); + } + + if (vptr->wol_opts & VELOCITY_WOL_ARP) { + struct arp_packet *arp = (struct arp_packet *) buf; + u16 crc; + memset(buf, 0, sizeof(struct arp_packet) + 7); + + for (i = 0; i < 4; i++) + writel(mask_pattern[0][i], ®s->ByteMask[0][i]); + + arp->type = htons(ETH_P_ARP); + arp->ar_op = htons(1); + + memcpy(arp->ar_tip, vptr->ip_addr, 4); + + crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, (u8 *) & mask_pattern[0][0]); + + writew(crc, ®s->PatternCRC[0]); + writew(WOLCR_ARP_EN, ®s->WOLCRSet); + } + + BYTE_REG_BITS_ON(PWCFG_WOLTYPE, ®s->PWCFGSet); + BYTE_REG_BITS_ON(PWCFG_LEGACY_WOLEN, ®s->PWCFGSet); + + writew(0x0FFF, ®s->WOLSRClr); + + if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) { + if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) + MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR, vptr->mac_regs); + + MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000, MII_REG_G1000CR, vptr->mac_regs); + } + + if (vptr->mii_status & VELOCITY_SPEED_1000) + MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs); + + BYTE_REG_BITS_ON(CHIPGCR_FCMODE, ®s->CHIPGCR); + + { + u8 GCR; + GCR = readb(®s->CHIPGCR); + GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX; + writeb(GCR, ®s->CHIPGCR); + } + + BYTE_REG_BITS_OFF(ISR_PWEI, ®s->ISR); + /* Turn on SWPTAG just before entering power mode */ + BYTE_REG_BITS_ON(STICKHW_SWPTAG, ®s->STICKHW); + /* Go to bed ..... */ + BYTE_REG_BITS_ON((STICKHW_DS1 | STICKHW_DS0), ®s->STICKHW); + + return 0; +} + diff -Nru a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/via-velocity.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,1885 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This software may be redistributed and/or modified under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or + * 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. + * + * File: via-velocity.h + * + * Purpose: Header file to define driver's private structures. + * + * Author: Chuang Liang-Shing, AJ Jiang + * + * Date: Jan 24, 2003 + */ + + +#ifndef VELOCITY_H +#define VELOCITY_H + +#define VELOCITY_TX_CSUM_SUPPORT + +#define VELOCITY_NAME "via-velocity" +#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver" +#define VELOCITY_VERSION "1.13" + +#define PKT_BUF_SZ 1540 + +#define MAX_UNITS 8 +#define OPTION_DEFAULT { [0 ... MAX_UNITS-1] = -1} + +#define REV_ID_VT6110 (0) +#define DEVICE_ID (0x3119) + +#define BYTE_REG_BITS_ON(x,p) do { writeb(readb((p))|(x),(p));} while (0) +#define WORD_REG_BITS_ON(x,p) do { writew(readw((p))|(x),(p));} while (0) +#define DWORD_REG_BITS_ON(x,p) do { writel(readl((p))|(x),(p));} while (0) + +#define BYTE_REG_BITS_IS_ON(x,p) (readb((p)) & (x)) +#define WORD_REG_BITS_IS_ON(x,p) (readw((p)) & (x)) +#define DWORD_REG_BITS_IS_ON(x,p) (readl((p)) & (x)) + +#define BYTE_REG_BITS_OFF(x,p) do { writeb(readb((p)) & (~(x)),(p));} while (0) +#define WORD_REG_BITS_OFF(x,p) do { writew(readw((p)) & (~(x)),(p));} while (0) +#define DWORD_REG_BITS_OFF(x,p) do { writel(readl((p)) & (~(x)),(p));} while (0) + +#define BYTE_REG_BITS_SET(x,m,p) do { writeb( (readb((p)) & (~(m))) |(x),(p));} while (0) +#define WORD_REG_BITS_SET(x,m,p) do { writew( (readw((p)) & (~(m))) |(x),(p));} while (0) +#define DWORD_REG_BITS_SET(x,m,p) do { writel( (readl((p)) & (~(m)))|(x),(p));} while (0) + +#define VAR_USED(p) do {(p)=(p);} while (0) + +/* + * Purpose: Structures for MAX RX/TX descriptors. + */ + + +#define B_OWNED_BY_CHIP 1 +#define B_OWNED_BY_HOST 0 + +/* + * Bits in the RSR0 register + */ + +#define RSR_DETAG 0x0080 +#define RSR_SNTAG 0x0040 +#define RSR_RXER 0x0020 +#define RSR_RL 0x0010 +#define RSR_CE 0x0008 +#define RSR_FAE 0x0004 +#define RSR_CRC 0x0002 +#define RSR_VIDM 0x0001 + +/* + * Bits in the RSR1 register + */ + +#define RSR_RXOK 0x8000 // rx OK +#define RSR_PFT 0x4000 // Perfect filtering address match +#define RSR_MAR 0x2000 // MAC accept multicast address packet +#define RSR_BAR 0x1000 // MAC accept broadcast address packet +#define RSR_PHY 0x0800 // MAC accept physical address packet +#define RSR_VTAG 0x0400 // 802.1p/1q tagging packet indicator +#define RSR_STP 0x0200 // start of packet +#define RSR_EDP 0x0100 // end of packet + +/* + * Bits in the RSR1 register + */ + +#define RSR1_RXOK 0x80 // rx OK +#define RSR1_PFT 0x40 // Perfect filtering address match +#define RSR1_MAR 0x20 // MAC accept multicast address packet +#define RSR1_BAR 0x10 // MAC accept broadcast address packet +#define RSR1_PHY 0x08 // MAC accept physical address packet +#define RSR1_VTAG 0x04 // 802.1p/1q tagging packet indicator +#define RSR1_STP 0x02 // start of packet +#define RSR1_EDP 0x01 // end of packet + +/* + * Bits in the CSM register + */ + +#define CSM_IPOK 0x40 //IP Checkusm validatiaon ok +#define CSM_TUPOK 0x20 //TCP/UDP Checkusm validatiaon ok +#define CSM_FRAG 0x10 //Fragment IP datagram +#define CSM_IPKT 0x04 //Received an IP packet +#define CSM_TCPKT 0x02 //Received a TCP packet +#define CSM_UDPKT 0x01 //Received a UDP packet + +/* + * Bits in the TSR0 register + */ + +#define TSR0_ABT 0x0080 // Tx abort because of excessive collision +#define TSR0_OWT 0x0040 // Jumbo frame Tx abort +#define TSR0_OWC 0x0020 // Out of window collision +#define TSR0_COLS 0x0010 // experience collision in this transmit event +#define TSR0_NCR3 0x0008 // collision retry counter[3] +#define TSR0_NCR2 0x0004 // collision retry counter[2] +#define TSR0_NCR1 0x0002 // collision retry counter[1] +#define TSR0_NCR0 0x0001 // collision retry counter[0] +#define TSR0_TERR 0x8000 // +#define TSR0_FDX 0x4000 // current transaction is serviced by full duplex mode +#define TSR0_GMII 0x2000 // current transaction is serviced by GMII mode +#define TSR0_LNKFL 0x1000 // packet serviced during link down +#define TSR0_SHDN 0x0400 // shutdown case +#define TSR0_CRS 0x0200 // carrier sense lost +#define TSR0_CDH 0x0100 // AQE test fail (CD heartbeat) + +/* + * Bits in the TSR1 register + */ + +#define TSR1_TERR 0x80 // +#define TSR1_FDX 0x40 // current transaction is serviced by full duplex mode +#define TSR1_GMII 0x20 // current transaction is serviced by GMII mode +#define TSR1_LNKFL 0x10 // packet serviced during link down +#define TSR1_SHDN 0x04 // shutdown case +#define TSR1_CRS 0x02 // carrier sense lost +#define TSR1_CDH 0x01 // AQE test fail (CD heartbeat) + +// +// Bits in the TCR0 register +// +#define TCR0_TIC 0x80 // assert interrupt immediately while descriptor has been send complete +#define TCR0_PIC 0x40 // priority interrupt request, INA# is issued over adaptive interrupt scheme +#define TCR0_VETAG 0x20 // enable VLAN tag +#define TCR0_IPCK 0x10 // request IP checksum calculation. +#define TCR0_UDPCK 0x08 // request UDP checksum calculation. +#define TCR0_TCPCK 0x04 // request TCP checksum calculation. +#define TCR0_JMBO 0x02 // indicate a jumbo packet in GMAC side +#define TCR0_CRC 0x01 // disable CRC generation + +#define TCPLS_NORMAL 3 +#define TCPLS_START 2 +#define TCPLS_END 1 +#define TCPLS_MED 0 + + +// max transmit or receive buffer size +#define CB_RX_BUF_SIZE 2048UL // max buffer size + // NOTE: must be multiple of 4 + +#define CB_MAX_RD_NUM 512 // MAX # of RD +#define CB_MAX_TD_NUM 256 // MAX # of TD + +#define CB_INIT_RD_NUM_3119 128 // init # of RD, for setup VT3119 +#define CB_INIT_TD_NUM_3119 64 // init # of TD, for setup VT3119 + +#define CB_INIT_RD_NUM 128 // init # of RD, for setup default +#define CB_INIT_TD_NUM 64 // init # of TD, for setup default + +// for 3119 +#define CB_TD_RING_NUM 4 // # of TD rings. +#define CB_MAX_SEG_PER_PKT 7 // max data seg per packet (Tx) + + +/* + * If collisions excess 15 times , tx will abort, and + * if tx fifo underflow, tx will fail + * we should try to resend it + */ + +#define CB_MAX_TX_ABORT_RETRY 3 + +/* + * Receive descriptor + */ + +struct rdesc0 { + u16 RSR; /* Receive status */ + u16 len:14; /* Received packet length */ + u16 reserved:1; + u16 owner:1; /* Who owns this buffer ? */ +}; + +struct rdesc1 { + u16 PQTAG; + u8 CSM; + u8 IPKT; +}; + +struct rx_desc { + struct rdesc0 rdesc0; + struct rdesc1 rdesc1; + u32 pa_low; /* Low 32 bit PCI address */ + u16 pa_high; /* Next 16 bit PCI address (48 total) */ + u16 len:15; /* Frame size */ + u16 inten:1; /* Enable interrupt */ +} __attribute__ ((__packed__)); + +/* + * Transmit descriptor + */ + +struct tdesc0 { + u16 TSR; /* Transmit status register */ + u16 pktsize:14; /* Size of frame */ + u16 reserved:1; + u16 owner:1; /* Who owns the buffer */ +}; + +struct pqinf { /* Priority queue info */ + u16 VID:12; + u16 CFI:1; + u16 priority:3; +} __attribute__ ((__packed__)); + +struct tdesc1 { + struct pqinf pqinf; + u8 TCR; + u8 TCPLS:2; + u8 reserved:2; + u8 CMDZ:4; +} __attribute__ ((__packed__)); + +struct td_buf { + u32 pa_low; + u16 pa_high; + u16 bufsize:14; + u16 reserved:1; + u16 queue:1; +} __attribute__ ((__packed__)); + +struct tx_desc { + struct tdesc0 tdesc0; + struct tdesc1 tdesc1; + struct td_buf td_buf[7]; +}; + +struct velocity_rd_info { + struct sk_buff *skb; + dma_addr_t skb_dma; +}; + +/** + * alloc_rd_info - allocate an rd info block + * + * Alocate and initialize a receive info structure used for keeping + * track of kernel side information related to each receive + * descriptor we are using + */ + +static inline struct velocity_rd_info *alloc_rd_info(void) +{ + struct velocity_rd_info *ptr; + if ((ptr = kmalloc(sizeof(struct velocity_rd_info), GFP_ATOMIC)) == NULL) + return NULL; + else { + memset(ptr, 0, sizeof(struct velocity_rd_info)); + return ptr; + } +} + +/* + * Used to track transmit side buffers. + */ + +struct velocity_td_info { + struct sk_buff *skb; + u8 *buf; + int nskb_dma; + dma_addr_t skb_dma[7]; + dma_addr_t buf_dma; +}; + +enum { + OWNED_BY_HOST = 0, + OWNED_BY_NIC = 1 +} velocity_owner; + + +/* + * MAC registers and macros. + */ + + +#define MCAM_SIZE 64 +#define VCAM_SIZE 64 +#define TX_QUEUE_NO 4 + +#define MAX_HW_MIB_COUNTER 32 +#define VELOCITY_MIN_MTU (1514-14) +#define VELOCITY_MAX_MTU (9000) + +/* + * Registers in the MAC + */ + +#define MAC_REG_PAR 0x00 // physical address +#define MAC_REG_RCR 0x06 +#define MAC_REG_TCR 0x07 +#define MAC_REG_CR0_SET 0x08 +#define MAC_REG_CR1_SET 0x09 +#define MAC_REG_CR2_SET 0x0A +#define MAC_REG_CR3_SET 0x0B +#define MAC_REG_CR0_CLR 0x0C +#define MAC_REG_CR1_CLR 0x0D +#define MAC_REG_CR2_CLR 0x0E +#define MAC_REG_CR3_CLR 0x0F +#define MAC_REG_MAR 0x10 +#define MAC_REG_CAM 0x10 +#define MAC_REG_DEC_BASE_HI 0x18 +#define MAC_REG_DBF_BASE_HI 0x1C +#define MAC_REG_ISR_CTL 0x20 +#define MAC_REG_ISR_HOTMR 0x20 +#define MAC_REG_ISR_TSUPTHR 0x20 +#define MAC_REG_ISR_RSUPTHR 0x20 +#define MAC_REG_ISR_CTL1 0x21 +#define MAC_REG_TXE_SR 0x22 +#define MAC_REG_RXE_SR 0x23 +#define MAC_REG_ISR 0x24 +#define MAC_REG_ISR0 0x24 +#define MAC_REG_ISR1 0x25 +#define MAC_REG_ISR2 0x26 +#define MAC_REG_ISR3 0x27 +#define MAC_REG_IMR 0x28 +#define MAC_REG_IMR0 0x28 +#define MAC_REG_IMR1 0x29 +#define MAC_REG_IMR2 0x2A +#define MAC_REG_IMR3 0x2B +#define MAC_REG_TDCSR_SET 0x30 +#define MAC_REG_RDCSR_SET 0x32 +#define MAC_REG_TDCSR_CLR 0x34 +#define MAC_REG_RDCSR_CLR 0x36 +#define MAC_REG_RDBASE_LO 0x38 +#define MAC_REG_RDINDX 0x3C +#define MAC_REG_TDBASE_LO 0x40 +#define MAC_REG_RDCSIZE 0x50 +#define MAC_REG_TDCSIZE 0x52 +#define MAC_REG_TDINDX 0x54 +#define MAC_REG_TDIDX0 0x54 +#define MAC_REG_TDIDX1 0x56 +#define MAC_REG_TDIDX2 0x58 +#define MAC_REG_TDIDX3 0x5A +#define MAC_REG_PAUSE_TIMER 0x5C +#define MAC_REG_RBRDU 0x5E +#define MAC_REG_FIFO_TEST0 0x60 +#define MAC_REG_FIFO_TEST1 0x64 +#define MAC_REG_CAMADDR 0x68 +#define MAC_REG_CAMCR 0x69 +#define MAC_REG_GFTEST 0x6A +#define MAC_REG_FTSTCMD 0x6B +#define MAC_REG_MIICFG 0x6C +#define MAC_REG_MIISR 0x6D +#define MAC_REG_PHYSR0 0x6E +#define MAC_REG_PHYSR1 0x6F +#define MAC_REG_MIICR 0x70 +#define MAC_REG_MIIADR 0x71 +#define MAC_REG_MIIDATA 0x72 +#define MAC_REG_SOFT_TIMER0 0x74 +#define MAC_REG_SOFT_TIMER1 0x76 +#define MAC_REG_CFGA 0x78 +#define MAC_REG_CFGB 0x79 +#define MAC_REG_CFGC 0x7A +#define MAC_REG_CFGD 0x7B +#define MAC_REG_DCFG0 0x7C +#define MAC_REG_DCFG1 0x7D +#define MAC_REG_MCFG0 0x7E +#define MAC_REG_MCFG1 0x7F + +#define MAC_REG_TBIST 0x80 +#define MAC_REG_RBIST 0x81 +#define MAC_REG_PMCC 0x82 +#define MAC_REG_STICKHW 0x83 +#define MAC_REG_MIBCR 0x84 +#define MAC_REG_EERSV 0x85 +#define MAC_REG_REVID 0x86 +#define MAC_REG_MIBREAD 0x88 +#define MAC_REG_BPMA 0x8C +#define MAC_REG_EEWR_DATA 0x8C +#define MAC_REG_BPMD_WR 0x8F +#define MAC_REG_BPCMD 0x90 +#define MAC_REG_BPMD_RD 0x91 +#define MAC_REG_EECHKSUM 0x92 +#define MAC_REG_EECSR 0x93 +#define MAC_REG_EERD_DATA 0x94 +#define MAC_REG_EADDR 0x96 +#define MAC_REG_EMBCMD 0x97 +#define MAC_REG_JMPSR0 0x98 +#define MAC_REG_JMPSR1 0x99 +#define MAC_REG_JMPSR2 0x9A +#define MAC_REG_JMPSR3 0x9B +#define MAC_REG_CHIPGSR 0x9C +#define MAC_REG_TESTCFG 0x9D +#define MAC_REG_DEBUG 0x9E +#define MAC_REG_CHIPGCR 0x9F +#define MAC_REG_WOLCR0_SET 0xA0 +#define MAC_REG_WOLCR1_SET 0xA1 +#define MAC_REG_PWCFG_SET 0xA2 +#define MAC_REG_WOLCFG_SET 0xA3 +#define MAC_REG_WOLCR0_CLR 0xA4 +#define MAC_REG_WOLCR1_CLR 0xA5 +#define MAC_REG_PWCFG_CLR 0xA6 +#define MAC_REG_WOLCFG_CLR 0xA7 +#define MAC_REG_WOLSR0_SET 0xA8 +#define MAC_REG_WOLSR1_SET 0xA9 +#define MAC_REG_WOLSR0_CLR 0xAC +#define MAC_REG_WOLSR1_CLR 0xAD +#define MAC_REG_PATRN_CRC0 0xB0 +#define MAC_REG_PATRN_CRC1 0xB2 +#define MAC_REG_PATRN_CRC2 0xB4 +#define MAC_REG_PATRN_CRC3 0xB6 +#define MAC_REG_PATRN_CRC4 0xB8 +#define MAC_REG_PATRN_CRC5 0xBA +#define MAC_REG_PATRN_CRC6 0xBC +#define MAC_REG_PATRN_CRC7 0xBE +#define MAC_REG_BYTEMSK0_0 0xC0 +#define MAC_REG_BYTEMSK0_1 0xC4 +#define MAC_REG_BYTEMSK0_2 0xC8 +#define MAC_REG_BYTEMSK0_3 0xCC +#define MAC_REG_BYTEMSK1_0 0xD0 +#define MAC_REG_BYTEMSK1_1 0xD4 +#define MAC_REG_BYTEMSK1_2 0xD8 +#define MAC_REG_BYTEMSK1_3 0xDC +#define MAC_REG_BYTEMSK2_0 0xE0 +#define MAC_REG_BYTEMSK2_1 0xE4 +#define MAC_REG_BYTEMSK2_2 0xE8 +#define MAC_REG_BYTEMSK2_3 0xEC +#define MAC_REG_BYTEMSK3_0 0xF0 +#define MAC_REG_BYTEMSK3_1 0xF4 +#define MAC_REG_BYTEMSK3_2 0xF8 +#define MAC_REG_BYTEMSK3_3 0xFC + +/* + * Bits in the RCR register + */ + +#define RCR_AS 0x80 +#define RCR_AP 0x40 +#define RCR_AL 0x20 +#define RCR_PROM 0x10 +#define RCR_AB 0x08 +#define RCR_AM 0x04 +#define RCR_AR 0x02 +#define RCR_SEP 0x01 + +/* + * Bits in the TCR register + */ + +#define TCR_TB2BDIS 0x80 +#define TCR_COLTMC1 0x08 +#define TCR_COLTMC0 0x04 +#define TCR_LB1 0x02 /* loopback[1] */ +#define TCR_LB0 0x01 /* loopback[0] */ + +/* + * Bits in the CR0 register + */ + +#define CR0_TXON 0x00000008UL +#define CR0_RXON 0x00000004UL +#define CR0_STOP 0x00000002UL /* stop MAC, default = 1 */ +#define CR0_STRT 0x00000001UL /* start MAC */ +#define CR0_SFRST 0x00008000UL /* software reset */ +#define CR0_TM1EN 0x00004000UL +#define CR0_TM0EN 0x00002000UL +#define CR0_DPOLL 0x00000800UL /* disable rx/tx auto polling */ +#define CR0_DISAU 0x00000100UL +#define CR0_XONEN 0x00800000UL +#define CR0_FDXTFCEN 0x00400000UL /* full-duplex TX flow control enable */ +#define CR0_FDXRFCEN 0x00200000UL /* full-duplex RX flow control enable */ +#define CR0_HDXFCEN 0x00100000UL /* half-duplex flow control enable */ +#define CR0_XHITH1 0x00080000UL /* TX XON high threshold 1 */ +#define CR0_XHITH0 0x00040000UL /* TX XON high threshold 0 */ +#define CR0_XLTH1 0x00020000UL /* TX pause frame low threshold 1 */ +#define CR0_XLTH0 0x00010000UL /* TX pause frame low threshold 0 */ +#define CR0_GSPRST 0x80000000UL +#define CR0_FORSRST 0x40000000UL +#define CR0_FPHYRST 0x20000000UL +#define CR0_DIAG 0x10000000UL +#define CR0_INTPCTL 0x04000000UL +#define CR0_GINTMSK1 0x02000000UL +#define CR0_GINTMSK0 0x01000000UL + +/* + * Bits in the CR1 register + */ + +#define CR1_SFRST 0x80 /* software reset */ +#define CR1_TM1EN 0x40 +#define CR1_TM0EN 0x20 +#define CR1_DPOLL 0x08 /* disable rx/tx auto polling */ +#define CR1_DISAU 0x01 + +/* + * Bits in the CR2 register + */ + +#define CR2_XONEN 0x80 +#define CR2_FDXTFCEN 0x40 /* full-duplex TX flow control enable */ +#define CR2_FDXRFCEN 0x20 /* full-duplex RX flow control enable */ +#define CR2_HDXFCEN 0x10 /* half-duplex flow control enable */ +#define CR2_XHITH1 0x08 /* TX XON high threshold 1 */ +#define CR2_XHITH0 0x04 /* TX XON high threshold 0 */ +#define CR2_XLTH1 0x02 /* TX pause frame low threshold 1 */ +#define CR2_XLTH0 0x01 /* TX pause frame low threshold 0 */ + +/* + * Bits in the CR3 register + */ + +#define CR3_GSPRST 0x80 +#define CR3_FORSRST 0x40 +#define CR3_FPHYRST 0x20 +#define CR3_DIAG 0x10 +#define CR3_INTPCTL 0x04 +#define CR3_GINTMSK1 0x02 +#define CR3_GINTMSK0 0x01 + +#define ISRCTL_UDPINT 0x8000 +#define ISRCTL_TSUPDIS 0x4000 +#define ISRCTL_RSUPDIS 0x2000 +#define ISRCTL_PMSK1 0x1000 +#define ISRCTL_PMSK0 0x0800 +#define ISRCTL_INTPD 0x0400 +#define ISRCTL_HCRLD 0x0200 +#define ISRCTL_SCRLD 0x0100 + +/* + * Bits in the ISR_CTL1 register + */ + +#define ISRCTL1_UDPINT 0x80 +#define ISRCTL1_TSUPDIS 0x40 +#define ISRCTL1_RSUPDIS 0x20 +#define ISRCTL1_PMSK1 0x10 +#define ISRCTL1_PMSK0 0x08 +#define ISRCTL1_INTPD 0x04 +#define ISRCTL1_HCRLD 0x02 +#define ISRCTL1_SCRLD 0x01 + +/* + * Bits in the TXE_SR register + */ + +#define TXESR_TFDBS 0x08 +#define TXESR_TDWBS 0x04 +#define TXESR_TDRBS 0x02 +#define TXESR_TDSTR 0x01 + +/* + * Bits in the RXE_SR register + */ + +#define RXESR_RFDBS 0x08 +#define RXESR_RDWBS 0x04 +#define RXESR_RDRBS 0x02 +#define RXESR_RDSTR 0x01 + +/* + * Bits in the ISR register + */ + +#define ISR_ISR3 0x80000000UL +#define ISR_ISR2 0x40000000UL +#define ISR_ISR1 0x20000000UL +#define ISR_ISR0 0x10000000UL +#define ISR_TXSTLI 0x02000000UL +#define ISR_RXSTLI 0x01000000UL +#define ISR_HFLD 0x00800000UL +#define ISR_UDPI 0x00400000UL +#define ISR_MIBFI 0x00200000UL +#define ISR_SHDNI 0x00100000UL +#define ISR_PHYI 0x00080000UL +#define ISR_PWEI 0x00040000UL +#define ISR_TMR1I 0x00020000UL +#define ISR_TMR0I 0x00010000UL +#define ISR_SRCI 0x00008000UL +#define ISR_LSTPEI 0x00004000UL +#define ISR_LSTEI 0x00002000UL +#define ISR_OVFI 0x00001000UL +#define ISR_FLONI 0x00000800UL +#define ISR_RACEI 0x00000400UL +#define ISR_TXWB1I 0x00000200UL +#define ISR_TXWB0I 0x00000100UL +#define ISR_PTX3I 0x00000080UL +#define ISR_PTX2I 0x00000040UL +#define ISR_PTX1I 0x00000020UL +#define ISR_PTX0I 0x00000010UL +#define ISR_PTXI 0x00000008UL +#define ISR_PRXI 0x00000004UL +#define ISR_PPTXI 0x00000002UL +#define ISR_PPRXI 0x00000001UL + +/* + * Bits in the IMR register + */ + +#define IMR_TXSTLM 0x02000000UL +#define IMR_UDPIM 0x00400000UL +#define IMR_MIBFIM 0x00200000UL +#define IMR_SHDNIM 0x00100000UL +#define IMR_PHYIM 0x00080000UL +#define IMR_PWEIM 0x00040000UL +#define IMR_TMR1IM 0x00020000UL +#define IMR_TMR0IM 0x00010000UL + +#define IMR_SRCIM 0x00008000UL +#define IMR_LSTPEIM 0x00004000UL +#define IMR_LSTEIM 0x00002000UL +#define IMR_OVFIM 0x00001000UL +#define IMR_FLONIM 0x00000800UL +#define IMR_RACEIM 0x00000400UL +#define IMR_TXWB1IM 0x00000200UL +#define IMR_TXWB0IM 0x00000100UL + +#define IMR_PTX3IM 0x00000080UL +#define IMR_PTX2IM 0x00000040UL +#define IMR_PTX1IM 0x00000020UL +#define IMR_PTX0IM 0x00000010UL +#define IMR_PTXIM 0x00000008UL +#define IMR_PRXIM 0x00000004UL +#define IMR_PPTXIM 0x00000002UL +#define IMR_PPRXIM 0x00000001UL + +/* 0x0013FB0FUL = initial value of IMR */ + +#define INT_MASK_DEF (IMR_PPTXIM|IMR_PPRXIM|IMR_PTXIM|IMR_PRXIM|\ + IMR_PWEIM|IMR_TXWB0IM|IMR_TXWB1IM|IMR_FLONIM|\ + IMR_OVFIM|IMR_LSTEIM|IMR_LSTPEIM|IMR_SRCIM|IMR_MIBFIM|\ + IMR_SHDNIM|IMR_TMR1IM|IMR_TMR0IM|IMR_TXSTLM) + +/* + * Bits in the TDCSR0/1, RDCSR0 register + */ + +#define TRDCSR_DEAD 0x0008 +#define TRDCSR_WAK 0x0004 +#define TRDCSR_ACT 0x0002 +#define TRDCSR_RUN 0x0001 + +/* + * Bits in the CAMADDR register + */ + +#define CAMADDR_CAMEN 0x80 +#define CAMADDR_VCAMSL 0x40 + +/* + * Bits in the CAMCR register + */ + +#define CAMCR_PS1 0x80 +#define CAMCR_PS0 0x40 +#define CAMCR_AITRPKT 0x20 +#define CAMCR_AITR16 0x10 +#define CAMCR_CAMRD 0x08 +#define CAMCR_CAMWR 0x04 +#define CAMCR_PS_CAM_MASK 0x40 +#define CAMCR_PS_CAM_DATA 0x80 +#define CAMCR_PS_MAR 0x00 + +/* + * Bits in the MIICFG register + */ + +#define MIICFG_MPO1 0x80 +#define MIICFG_MPO0 0x40 +#define MIICFG_MFDC 0x20 + +/* + * Bits in the MIISR register + */ + +#define MIISR_MIDLE 0x80 + +/* + * Bits in the PHYSR0 register + */ + +#define PHYSR0_PHYRST 0x80 +#define PHYSR0_LINKGD 0x40 +#define PHYSR0_FDPX 0x10 +#define PHYSR0_SPDG 0x08 +#define PHYSR0_SPD10 0x04 +#define PHYSR0_RXFLC 0x02 +#define PHYSR0_TXFLC 0x01 + +/* + * Bits in the PHYSR1 register + */ + +#define PHYSR1_PHYTBI 0x01 + +/* + * Bits in the MIICR register + */ + +#define MIICR_MAUTO 0x80 +#define MIICR_RCMD 0x40 +#define MIICR_WCMD 0x20 +#define MIICR_MDPM 0x10 +#define MIICR_MOUT 0x08 +#define MIICR_MDO 0x04 +#define MIICR_MDI 0x02 +#define MIICR_MDC 0x01 + +/* + * Bits in the MIIADR register + */ + +#define MIIADR_SWMPL 0x80 + +/* + * Bits in the CFGA register + */ + +#define CFGA_PMHCTG 0x08 +#define CFGA_GPIO1PD 0x04 +#define CFGA_ABSHDN 0x02 +#define CFGA_PACPI 0x01 + +/* + * Bits in the CFGB register + */ + +#define CFGB_GTCKOPT 0x80 +#define CFGB_MIIOPT 0x40 +#define CFGB_CRSEOPT 0x20 +#define CFGB_OFSET 0x10 +#define CFGB_CRANDOM 0x08 +#define CFGB_CAP 0x04 +#define CFGB_MBA 0x02 +#define CFGB_BAKOPT 0x01 + +/* + * Bits in the CFGC register + */ + +#define CFGC_EELOAD 0x80 +#define CFGC_BROPT 0x40 +#define CFGC_DLYEN 0x20 +#define CFGC_DTSEL 0x10 +#define CFGC_BTSEL 0x08 +#define CFGC_BPS2 0x04 /* bootrom select[2] */ +#define CFGC_BPS1 0x02 /* bootrom select[1] */ +#define CFGC_BPS0 0x01 /* bootrom select[0] */ + +/* + * Bits in the CFGD register + */ + +#define CFGD_IODIS 0x80 +#define CFGD_MSLVDACEN 0x40 +#define CFGD_CFGDACEN 0x20 +#define CFGD_PCI64EN 0x10 +#define CFGD_HTMRL4 0x08 + +/* + * Bits in the DCFG1 register + */ + +#define DCFG_XMWI 0x8000 +#define DCFG_XMRM 0x4000 +#define DCFG_XMRL 0x2000 +#define DCFG_PERDIS 0x1000 +#define DCFG_MRWAIT 0x0400 +#define DCFG_MWWAIT 0x0200 +#define DCFG_LATMEN 0x0100 + +/* + * Bits in the MCFG0 register + */ + +#define MCFG_RXARB 0x0080 +#define MCFG_RFT1 0x0020 +#define MCFG_RFT0 0x0010 +#define MCFG_LOWTHOPT 0x0008 +#define MCFG_PQEN 0x0004 +#define MCFG_RTGOPT 0x0002 +#define MCFG_VIDFR 0x0001 + +/* + * Bits in the MCFG1 register + */ + +#define MCFG_TXARB 0x8000 +#define MCFG_TXQBK1 0x0800 +#define MCFG_TXQBK0 0x0400 +#define MCFG_TXQNOBK 0x0200 +#define MCFG_SNAPOPT 0x0100 + +/* + * Bits in the PMCC register + */ + +#define PMCC_DSI 0x80 +#define PMCC_D2_DIS 0x40 +#define PMCC_D1_DIS 0x20 +#define PMCC_D3C_EN 0x10 +#define PMCC_D3H_EN 0x08 +#define PMCC_D2_EN 0x04 +#define PMCC_D1_EN 0x02 +#define PMCC_D0_EN 0x01 + +/* + * Bits in STICKHW + */ + +#define STICKHW_SWPTAG 0x10 +#define STICKHW_WOLSR 0x08 +#define STICKHW_WOLEN 0x04 +#define STICKHW_DS1 0x02 /* R/W by software/cfg cycle */ +#define STICKHW_DS0 0x01 /* suspend well DS write port */ + +/* + * Bits in the MIBCR register + */ + +#define MIBCR_MIBISTOK 0x80 +#define MIBCR_MIBISTGO 0x40 +#define MIBCR_MIBINC 0x20 +#define MIBCR_MIBHI 0x10 +#define MIBCR_MIBFRZ 0x08 +#define MIBCR_MIBFLSH 0x04 +#define MIBCR_MPTRINI 0x02 +#define MIBCR_MIBCLR 0x01 + +/* + * Bits in the EERSV register + */ + +#define EERSV_BOOT_RPL ((u8) 0x01) /* Boot method selection for VT6110 */ + +#define EERSV_BOOT_MASK ((u8) 0x06) +#define EERSV_BOOT_INT19 ((u8) 0x00) +#define EERSV_BOOT_INT18 ((u8) 0x02) +#define EERSV_BOOT_LOCAL ((u8) 0x04) +#define EERSV_BOOT_BEV ((u8) 0x06) + + +/* + * Bits in BPCMD + */ + +#define BPCMD_BPDNE 0x80 +#define BPCMD_EBPWR 0x02 +#define BPCMD_EBPRD 0x01 + +/* + * Bits in the EECSR register + */ + +#define EECSR_EMBP 0x40 /* eeprom embeded programming */ +#define EECSR_RELOAD 0x20 /* eeprom content reload */ +#define EECSR_DPM 0x10 /* eeprom direct programming */ +#define EECSR_ECS 0x08 /* eeprom CS pin */ +#define EECSR_ECK 0x04 /* eeprom CK pin */ +#define EECSR_EDI 0x02 /* eeprom DI pin */ +#define EECSR_EDO 0x01 /* eeprom DO pin */ + +/* + * Bits in the EMBCMD register + */ + +#define EMBCMD_EDONE 0x80 +#define EMBCMD_EWDIS 0x08 +#define EMBCMD_EWEN 0x04 +#define EMBCMD_EWR 0x02 +#define EMBCMD_ERD 0x01 + +/* + * Bits in TESTCFG register + */ + +#define TESTCFG_HBDIS 0x80 + +/* + * Bits in CHIPGCR register + */ + +#define CHIPGCR_FCGMII 0x80 +#define CHIPGCR_FCFDX 0x40 +#define CHIPGCR_FCRESV 0x20 +#define CHIPGCR_FCMODE 0x10 +#define CHIPGCR_LPSOPT 0x08 +#define CHIPGCR_TM1US 0x04 +#define CHIPGCR_TM0US 0x02 +#define CHIPGCR_PHYINTEN 0x01 + +/* + * Bits in WOLCR0 + */ + +#define WOLCR_MSWOLEN7 0x0080 /* enable pattern match filtering */ +#define WOLCR_MSWOLEN6 0x0040 +#define WOLCR_MSWOLEN5 0x0020 +#define WOLCR_MSWOLEN4 0x0010 +#define WOLCR_MSWOLEN3 0x0008 +#define WOLCR_MSWOLEN2 0x0004 +#define WOLCR_MSWOLEN1 0x0002 +#define WOLCR_MSWOLEN0 0x0001 +#define WOLCR_ARP_EN 0x0001 + +/* + * Bits in WOLCR1 + */ + +#define WOLCR_LINKOFF_EN 0x0800 /* link off detected enable */ +#define WOLCR_LINKON_EN 0x0400 /* link on detected enable */ +#define WOLCR_MAGIC_EN 0x0200 /* magic packet filter enable */ +#define WOLCR_UNICAST_EN 0x0100 /* unicast filter enable */ + + +/* + * Bits in PWCFG + */ + +#define PWCFG_PHYPWOPT 0x80 /* internal MII I/F timing */ +#define PWCFG_PCISTICK 0x40 /* PCI sticky R/W enable */ +#define PWCFG_WOLTYPE 0x20 /* pulse(1) or button (0) */ +#define PWCFG_LEGCY_WOL 0x10 +#define PWCFG_PMCSR_PME_SR 0x08 +#define PWCFG_PMCSR_PME_EN 0x04 /* control by PCISTICK */ +#define PWCFG_LEGACY_WOLSR 0x02 /* Legacy WOL_SR shadow */ +#define PWCFG_LEGACY_WOLEN 0x01 /* Legacy WOL_EN shadow */ + +/* + * Bits in WOLCFG + */ + +#define WOLCFG_PMEOVR 0x80 /* for legacy use, force PMEEN always */ +#define WOLCFG_SAM 0x20 /* accept multicast case reset, default=0 */ +#define WOLCFG_SAB 0x10 /* accept broadcast case reset, default=0 */ +#define WOLCFG_SMIIACC 0x08 /* ?? */ +#define WOLCFG_SGENWH 0x02 +#define WOLCFG_PHYINTEN 0x01 /* 0:PHYINT trigger enable, 1:use internal MII + to report status change */ +/* + * Bits in WOLSR1 + */ + +#define WOLSR_LINKOFF_INT 0x0800 +#define WOLSR_LINKON_INT 0x0400 +#define WOLSR_MAGIC_INT 0x0200 +#define WOLSR_UNICAST_INT 0x0100 + +/* + * Ethernet address filter type + */ + +#define PKT_TYPE_NONE 0x0000 /* Turn off receiver */ +#define PKT_TYPE_DIRECTED 0x0001 /* obselete, directed address is always accepted */ +#define PKT_TYPE_MULTICAST 0x0002 +#define PKT_TYPE_ALL_MULTICAST 0x0004 +#define PKT_TYPE_BROADCAST 0x0008 +#define PKT_TYPE_PROMISCUOUS 0x0020 +#define PKT_TYPE_LONG 0x2000 /* NOTE.... the definition of LONG is >2048 bytes in our chip */ +#define PKT_TYPE_RUNT 0x4000 +#define PKT_TYPE_ERROR 0x8000 /* Accept error packets, e.g. CRC error */ + +/* + * Loopback mode + */ + +#define MAC_LB_NONE 0x00 +#define MAC_LB_INTERNAL 0x01 +#define MAC_LB_EXTERNAL 0x02 + +/* + * Enabled mask value of irq + */ + +#if defined(_SIM) +#define IMR_MASK_VALUE 0x0033FF0FUL /* initial value of IMR + set IMR0 to 0x0F according to spec */ + +#else +#define IMR_MASK_VALUE 0x0013FB0FUL /* initial value of IMR + ignore MIBFI,RACEI to + reduce intr. frequency + NOTE.... do not enable NoBuf int mask at driver driver + when (1) NoBuf -> RxThreshold = SF + (2) OK -> RxThreshold = original value + */ +#endif + +/* + * Revision id + */ + +#define REV_ID_VT3119_A0 0x00 +#define REV_ID_VT3119_A1 0x01 +#define REV_ID_VT3216_A0 0x10 + +/* + * Max time out delay time + */ + +#define W_MAX_TIMEOUT 0x0FFFU + + +/* + * MAC registers as a structure. Cannot be directly accessed this + * way but generates offsets for readl/writel() calls + */ + +struct mac_regs { + volatile u8 PAR[6]; /* 0x00 */ + volatile u8 RCR; + volatile u8 TCR; + + volatile u32 CR0Set; /* 0x08 */ + volatile u32 CR0Clr; /* 0x0C */ + + volatile u8 MARCAM[8]; /* 0x10 */ + + volatile u32 DecBaseHi; /* 0x18 */ + volatile u16 DbfBaseHi; /* 0x1C */ + volatile u16 reserved_1E; + + volatile u16 ISRCTL; /* 0x20 */ + volatile u8 TXESR; + volatile u8 RXESR; + + volatile u32 ISR; /* 0x24 */ + volatile u32 IMR; + + volatile u32 TDStatusPort; /* 0x2C */ + + volatile u16 TDCSRSet; /* 0x30 */ + volatile u8 RDCSRSet; + volatile u8 reserved_33; + volatile u16 TDCSRClr; + volatile u8 RDCSRClr; + volatile u8 reserved_37; + + volatile u32 RDBaseLo; /* 0x38 */ + volatile u16 RDIdx; /* 0x3C */ + volatile u16 reserved_3E; + + volatile u32 TDBaseLo[4]; /* 0x40 */ + + volatile u16 RDCSize; /* 0x50 */ + volatile u16 TDCSize; /* 0x52 */ + volatile u16 TDIdx[4]; /* 0x54 */ + volatile u16 tx_pause_timer; /* 0x5C */ + volatile u16 RBRDU; /* 0x5E */ + + volatile u32 FIFOTest0; /* 0x60 */ + volatile u32 FIFOTest1; /* 0x64 */ + + volatile u8 CAMADDR; /* 0x68 */ + volatile u8 CAMCR; /* 0x69 */ + volatile u8 GFTEST; /* 0x6A */ + volatile u8 FTSTCMD; /* 0x6B */ + + volatile u8 MIICFG; /* 0x6C */ + volatile u8 MIISR; + volatile u8 PHYSR0; + volatile u8 PHYSR1; + volatile u8 MIICR; + volatile u8 MIIADR; + volatile u16 MIIDATA; + + volatile u16 SoftTimer0; /* 0x74 */ + volatile u16 SoftTimer1; + + volatile u8 CFGA; /* 0x78 */ + volatile u8 CFGB; + volatile u8 CFGC; + volatile u8 CFGD; + + volatile u16 DCFG; /* 0x7C */ + volatile u16 MCFG; + + volatile u8 TBIST; /* 0x80 */ + volatile u8 RBIST; + volatile u8 PMCPORT; + volatile u8 STICKHW; + + volatile u8 MIBCR; /* 0x84 */ + volatile u8 reserved_85; + volatile u8 rev_id; + volatile u8 PORSTS; + + volatile u32 MIBData; /* 0x88 */ + + volatile u16 EEWrData; + + volatile u8 reserved_8E; + volatile u8 BPMDWr; + volatile u8 BPCMD; + volatile u8 BPMDRd; + + volatile u8 EECHKSUM; /* 0x92 */ + volatile u8 EECSR; + + volatile u16 EERdData; /* 0x94 */ + volatile u8 EADDR; + volatile u8 EMBCMD; + + + volatile u8 JMPSR0; /* 0x98 */ + volatile u8 JMPSR1; + volatile u8 JMPSR2; + volatile u8 JMPSR3; + volatile u8 CHIPGSR; /* 0x9C */ + volatile u8 TESTCFG; + volatile u8 DEBUG; + volatile u8 CHIPGCR; + + volatile u16 WOLCRSet; /* 0xA0 */ + volatile u8 PWCFGSet; + volatile u8 WOLCFGSet; + + volatile u16 WOLCRClr; /* 0xA4 */ + volatile u8 PWCFGCLR; + volatile u8 WOLCFGClr; + + volatile u16 WOLSRSet; /* 0xA8 */ + volatile u16 reserved_AA; + + volatile u16 WOLSRClr; /* 0xAC */ + volatile u16 reserved_AE; + + volatile u16 PatternCRC[8]; /* 0xB0 */ + volatile u32 ByteMask[4][4]; /* 0xC0 */ +} __attribute__ ((__packed__)); + + +enum hw_mib { + HW_MIB_ifRxAllPkts = 0, + HW_MIB_ifRxOkPkts, + HW_MIB_ifTxOkPkts, + HW_MIB_ifRxErrorPkts, + HW_MIB_ifRxRuntOkPkt, + HW_MIB_ifRxRuntErrPkt, + HW_MIB_ifRx64Pkts, + HW_MIB_ifTx64Pkts, + HW_MIB_ifRx65To127Pkts, + HW_MIB_ifTx65To127Pkts, + HW_MIB_ifRx128To255Pkts, + HW_MIB_ifTx128To255Pkts, + HW_MIB_ifRx256To511Pkts, + HW_MIB_ifTx256To511Pkts, + HW_MIB_ifRx512To1023Pkts, + HW_MIB_ifTx512To1023Pkts, + HW_MIB_ifRx1024To1518Pkts, + HW_MIB_ifTx1024To1518Pkts, + HW_MIB_ifTxEtherCollisions, + HW_MIB_ifRxPktCRCE, + HW_MIB_ifRxJumboPkts, + HW_MIB_ifTxJumboPkts, + HW_MIB_ifRxMacControlFrames, + HW_MIB_ifTxMacControlFrames, + HW_MIB_ifRxPktFAE, + HW_MIB_ifRxLongOkPkt, + HW_MIB_ifRxLongPktErrPkt, + HW_MIB_ifTXSQEErrors, + HW_MIB_ifRxNobuf, + HW_MIB_ifRxSymbolErrors, + HW_MIB_ifInRangeLengthErrors, + HW_MIB_ifLateCollisions, + HW_MIB_SIZE +}; + +enum chip_type { + CHIP_TYPE_VT6110 = 1, +}; + +struct velocity_info_tbl { + enum chip_type chip_id; + char *name; + int io_size; + int txqueue; + u32 flags; +}; + +#define mac_hw_mibs_init(regs) {\ + BYTE_REG_BITS_ON(MIBCR_MIBFRZ,&((regs)->MIBCR));\ + BYTE_REG_BITS_ON(MIBCR_MIBCLR,&((regs)->MIBCR));\ + do {}\ + while (BYTE_REG_BITS_IS_ON(MIBCR_MIBCLR,&((regs)->MIBCR)));\ + BYTE_REG_BITS_OFF(MIBCR_MIBFRZ,&((regs)->MIBCR));\ +} + +#define mac_read_isr(regs) readl(&((regs)->ISR)) +#define mac_write_isr(regs, x) writel((x),&((regs)->ISR)) +#define mac_clear_isr(regs) writel(0xffffffffL,&((regs)->ISR)) + +#define mac_write_int_mask(mask, regs) writel((mask),&((regs)->IMR)); +#define mac_disable_int(regs) writel(CR0_GINTMSK1,&((regs)->CR0Clr)) +#define mac_enable_int(regs) writel(CR0_GINTMSK1,&((regs)->CR0Set)) + +#define mac_hw_mibs_read(regs, MIBs) {\ + int i;\ + BYTE_REG_BITS_ON(MIBCR_MPTRINI,&((regs)->MIBCR));\ + for (i=0;iMIBData));\ + }\ +} + +#define mac_set_dma_length(regs, n) {\ + BYTE_REG_BITS_SET((n),0x07,&((regs)->DCFG));\ +} + +#define mac_set_rx_thresh(regs, n) {\ + BYTE_REG_BITS_SET((n),(MCFG_RFT0|MCFG_RFT1),&((regs)->MCFG));\ +} + +#define mac_rx_queue_run(regs) {\ + writeb(TRDCSR_RUN, &((regs)->RDCSRSet));\ +} + +#define mac_rx_queue_wake(regs) {\ + writeb(TRDCSR_WAK, &((regs)->RDCSRSet));\ +} + +#define mac_tx_queue_run(regs, n) {\ + writew(TRDCSR_RUN<<((n)*4),&((regs)->TDCSRSet));\ +} + +#define mac_tx_queue_wake(regs, n) {\ + writew(TRDCSR_WAK<<(n*4),&((regs)->TDCSRSet));\ +} + +#define mac_eeprom_reload(regs) {\ + int i=0;\ + BYTE_REG_BITS_ON(EECSR_RELOAD,&((regs)->EECSR));\ + do {\ + udelay(10);\ + if (i++>0x1000) {\ + break;\ + }\ + }while (BYTE_REG_BITS_IS_ON(EECSR_RELOAD,&((regs)->EECSR)));\ +} + +enum velocity_cam_type { + VELOCITY_VLAN_ID_CAM = 0, + VELOCITY_MULTICAST_CAM +}; + +/** + * mac_get_cam_mask - Read a CAM mask + * @regs: register block for this velocity + * @mask: buffer to store mask + * @cam_type: CAM to fetch + * + * Fetch the mask bits of the selected CAM and store them into the + * provided mask buffer. + */ + +static inline void mac_get_cam_mask(struct mac_regs * regs, u8 * mask, enum velocity_cam_type cam_type) +{ + int i; + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); + + if (cam_type == VELOCITY_VLAN_ID_CAM) + writeb(CAMADDR_VCAMSL, ®s->CAMADDR); + else + writeb(0, ®s->CAMADDR); + + /* read mask */ + for (i = 0; i < 8; i++) + *mask++ = readb(&(regs->MARCAM[i])); + + /* disable CAMEN */ + writeb(0, ®s->CAMADDR); + + /* Select mar */ + BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); + +} + +/** + * mac_set_cam_mask - Set a CAM mask + * @regs: register block for this velocity + * @mask: CAM mask to load + * @cam_type: CAM to store + * + * Store a new mask into a CAM + */ + +static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velocity_cam_type cam_type) +{ + int i; + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); + + if (cam_type == VELOCITY_VLAN_ID_CAM) + writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL, ®s->CAMADDR); + else + writeb(CAMADDR_CAMEN, ®s->CAMADDR); + + for (i = 0; i < 8; i++) { + writeb(*mask++, &(regs->MARCAM[i])); + } + /* disable CAMEN */ + writeb(0, ®s->CAMADDR); + + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); +} + +/** + * mac_set_cam - set CAM data + * @regs: register block of this velocity + * @idx: Cam index + * @addr: 2 or 6 bytes of CAM data + * @cam_type: CAM to load + * + * Load an address or vlan tag into a CAM + */ + +static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum velocity_cam_type cam_type) +{ + int i; + + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); + + idx &= (64 - 1); + + if (cam_type == VELOCITY_VLAN_ID_CAM) + writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, ®s->CAMADDR); + else + writeb(CAMADDR_CAMEN | idx, ®s->CAMADDR); + + if (cam_type == VELOCITY_VLAN_ID_CAM) + writew(*((u16 *) addr), ®s->MARCAM[0]); + else { + for (i = 0; i < 6; i++) { + writeb(*addr++, &(regs->MARCAM[i])); + } + } + BYTE_REG_BITS_ON(CAMCR_CAMWR, ®s->CAMCR); + + udelay(10); + + writeb(0, ®s->CAMADDR); + + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); +} + +/** + * mac_get_cam - fetch CAM data + * @regs: register block of this velocity + * @idx: Cam index + * @addr: buffer to hold up to 6 bytes of CAM data + * @cam_type: CAM to load + * + * Load an address or vlan tag from a CAM into the buffer provided by + * the caller. VLAN tags are 2 bytes the address cam entries are 6. + */ + +static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum velocity_cam_type cam_type) +{ + int i; + + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); + + idx &= (64 - 1); + + if (cam_type == VELOCITY_VLAN_ID_CAM) + writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, ®s->CAMADDR); + else + writeb(CAMADDR_CAMEN | idx, ®s->CAMADDR); + + BYTE_REG_BITS_ON(CAMCR_CAMRD, ®s->CAMCR); + + udelay(10); + + if (cam_type == VELOCITY_VLAN_ID_CAM) + *((u16 *) addr) = readw(&(regs->MARCAM[0])); + else + for (i = 0; i < 6; i++, addr++) + *((u8 *) addr) = readb(&(regs->MARCAM[i])); + + writeb(0, ®s->CAMADDR); + + /* Select CAM mask */ + BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); +} + +/** + * mac_wol_reset - reset WOL after exiting low power + * @regs: register block of this velocity + * + * Called after we drop out of wake on lan mode in order to + * reset the Wake on lan features. This function doesn't restore + * the rest of the logic from the result of sleep/wakeup + */ + +inline static void mac_wol_reset(struct mac_regs * regs) +{ + + /* Turn off SWPTAG right after leaving power mode */ + BYTE_REG_BITS_OFF(STICKHW_SWPTAG, ®s->STICKHW); + /* clear sticky bits */ + BYTE_REG_BITS_OFF((STICKHW_DS1 | STICKHW_DS0), ®s->STICKHW); + + BYTE_REG_BITS_OFF(CHIPGCR_FCGMII, ®s->CHIPGCR); + BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, ®s->CHIPGCR); + /* disable force PME-enable */ + writeb(WOLCFG_PMEOVR, ®s->WOLCFGClr); + /* disable power-event config bit */ + writew(0xFFFF, ®s->WOLCRClr); + /* clear power status */ + writew(0xFFFF, ®s->WOLSRClr); +} + + +/* + * Header for WOL definitions. Used to compute hashes + */ + +typedef u8 MCAM_ADDR[ETH_ALEN]; + +struct arp_packet { + u8 dest_mac[ETH_ALEN]; + u8 src_mac[ETH_ALEN]; + u16 type; + u16 ar_hrd; + u16 ar_pro; + u8 ar_hln; + u8 ar_pln; + u16 ar_op; + u8 ar_sha[ETH_ALEN]; + u8 ar_sip[4]; + u8 ar_tha[ETH_ALEN]; + u8 ar_tip[4]; +} __attribute__ ((__packed__)); + +struct _magic_packet { + u8 dest_mac[6]; + u8 src_mac[6]; + u16 type; + u8 MAC[16][6]; + u8 password[6]; +} __attribute__ ((__packed__)); + +/* + * Store for chip context when saving and restoring status. Not + * all fields are saved/restored currently. + */ + +struct velocity_context { + u8 mac_reg[256]; + MCAM_ADDR cam_addr[MCAM_SIZE]; + u16 vcam[VCAM_SIZE]; + u32 cammask[2]; + u32 patcrc[2]; + u32 pattern[8]; +}; + + +/* + * MII registers. + */ + + +/* + * Registers in the MII (offset unit is WORD) + */ + +#define MII_REG_BMCR 0x00 // physical address +#define MII_REG_BMSR 0x01 // +#define MII_REG_PHYID1 0x02 // OUI +#define MII_REG_PHYID2 0x03 // OUI + Module ID + REV ID +#define MII_REG_ANAR 0x04 // +#define MII_REG_ANLPAR 0x05 // +#define MII_REG_G1000CR 0x09 // +#define MII_REG_G1000SR 0x0A // +#define MII_REG_MODCFG 0x10 // +#define MII_REG_TCSR 0x16 // +#define MII_REG_PLED 0x1B // +// NS, MYSON only +#define MII_REG_PCR 0x17 // +// ESI only +#define MII_REG_PCSR 0x17 // +#define MII_REG_AUXCR 0x1C // + +// Marvell 88E1000/88E1000S +#define MII_REG_PSCR 0x10 // PHY specific control register + +// +// Bits in the BMCR register +// +#define BMCR_RESET 0x8000 // +#define BMCR_LBK 0x4000 // +#define BMCR_SPEED100 0x2000 // +#define BMCR_AUTO 0x1000 // +#define BMCR_PD 0x0800 // +#define BMCR_ISO 0x0400 // +#define BMCR_REAUTO 0x0200 // +#define BMCR_FDX 0x0100 // +#define BMCR_SPEED1G 0x0040 // +// +// Bits in the BMSR register +// +#define BMSR_AUTOCM 0x0020 // +#define BMSR_LNK 0x0004 // + +// +// Bits in the ANAR register +// +#define ANAR_ASMDIR 0x0800 // Asymmetric PAUSE support +#define ANAR_PAUSE 0x0400 // Symmetric PAUSE Support +#define ANAR_T4 0x0200 // +#define ANAR_TXFD 0x0100 // +#define ANAR_TX 0x0080 // +#define ANAR_10FD 0x0040 // +#define ANAR_10 0x0020 // +// +// Bits in the ANLPAR register +// +#define ANLPAR_ASMDIR 0x0800 // Asymmetric PAUSE support +#define ANLPAR_PAUSE 0x0400 // Symmetric PAUSE Support +#define ANLPAR_T4 0x0200 // +#define ANLPAR_TXFD 0x0100 // +#define ANLPAR_TX 0x0080 // +#define ANLPAR_10FD 0x0040 // +#define ANLPAR_10 0x0020 // + +// +// Bits in the G1000CR register +// +#define G1000CR_1000FD 0x0200 // PHY is 1000-T Full-duplex capable +#define G1000CR_1000 0x0100 // PHY is 1000-T Half-duplex capable + +// +// Bits in the G1000SR register +// +#define G1000SR_1000FD 0x0800 // LP PHY is 1000-T Full-duplex capable +#define G1000SR_1000 0x0400 // LP PHY is 1000-T Half-duplex capable + +#define TCSR_ECHODIS 0x2000 // +#define AUXCR_MDPPS 0x0004 // + +// Bits in the PLED register +#define PLED_LALBE 0x0004 // + +// Marvell 88E1000/88E1000S Bits in the PHY specific control register (10h) +#define PSCR_ACRSTX 0x0800 // Assert CRS on Transmit + +#define PHYID_CICADA_CS8201 0x000FC410UL +#define PHYID_VT3216_32BIT 0x000FC610UL +#define PHYID_VT3216_64BIT 0x000FC600UL +#define PHYID_MARVELL_1000 0x01410C50UL +#define PHYID_MARVELL_1000S 0x01410C40UL + +#define PHYID_REV_ID_MASK 0x0000000FUL + +#define PHYID_GET_PHY_REV_ID(i) ((i) & PHYID_REV_ID_MASK) +#define PHYID_GET_PHY_ID(i) ((i) & ~PHYID_REV_ID_MASK) + +#define MII_REG_BITS_ON(x,i,p) do {\ + u16 w;\ + velocity_mii_read((p),(i),&(w));\ + (w)|=(x);\ + velocity_mii_write((p),(i),(w));\ +} while (0) + +#define MII_REG_BITS_OFF(x,i,p) do {\ + u16 w;\ + velocity_mii_read((p),(i),&(w));\ + (w)&=(~(x));\ + velocity_mii_write((p),(i),(w));\ +} while (0) + +#define MII_REG_BITS_IS_ON(x,i,p) ({\ + u16 w;\ + velocity_mii_read((p),(i),&(w));\ + ((int) ((w) & (x)));}) + +#define MII_GET_PHY_ID(p) ({\ + u32 id;\ + velocity_mii_read((p),MII_REG_PHYID2,(u16 *) &id);\ + velocity_mii_read((p),MII_REG_PHYID1,((u16 *) &id)+1);\ + (id);}) + +/* + * Inline debug routine + */ + + +enum velocity_msg_level { + MSG_LEVEL_ERR = 0, //Errors that will cause abnormal operation. + MSG_LEVEL_NOTICE = 1, //Some errors need users to be notified. + MSG_LEVEL_INFO = 2, //Normal message. + MSG_LEVEL_VERBOSE = 3, //Will report all trival errors. + MSG_LEVEL_DEBUG = 4 //Only for debug purpose. +}; + +#ifdef VELOCITY_DEBUG +#define ASSERT(x) { \ + if (!(x)) { \ + printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x,\ + __FUNCTION__, __LINE__);\ + BUG(); \ + }\ +} +#define VELOCITY_DBG(p,args...) printk(p, ##args) +#else +#define ASSERT(x) +#define VELOCITY_DBG(x) +#endif + +#define VELOCITY_PRT(l, p, args...) do {if (l<=msglevel) printk( p ,##args);} while (0) + +#define VELOCITY_PRT_CAMMASK(p,t) {\ + int i;\ + if ((t)==VELOCITY_MULTICAST_CAM) {\ + for (i=0;i<(MCAM_SIZE/8);i++)\ + printk("%02X",(p)->mCAMmask[i]);\ + }\ + else {\ + for (i=0;i<(VCAM_SIZE/8);i++)\ + printk("%02X",(p)->vCAMmask[i]);\ + }\ + printk("\n");\ +} + + + +#define VELOCITY_WOL_MAGIC 0x00000000UL +#define VELOCITY_WOL_PHY 0x00000001UL +#define VELOCITY_WOL_ARP 0x00000002UL +#define VELOCITY_WOL_UCAST 0x00000004UL +#define VELOCITY_WOL_BCAST 0x00000010UL +#define VELOCITY_WOL_MCAST 0x00000020UL +#define VELOCITY_WOL_MAGIC_SEC 0x00000040UL + +/* + * Flags for options + */ + +#define VELOCITY_FLAGS_TAGGING 0x00000001UL +#define VELOCITY_FLAGS_TX_CSUM 0x00000002UL +#define VELOCITY_FLAGS_RX_CSUM 0x00000004UL +#define VELOCITY_FLAGS_IP_ALIGN 0x00000008UL +#define VELOCITY_FLAGS_VAL_PKT_LEN 0x00000010UL + +#define VELOCITY_FLAGS_FLOW_CTRL 0x01000000UL + +/* + * Flags for driver status + */ + +#define VELOCITY_FLAGS_OPENED 0x00010000UL +#define VELOCITY_FLAGS_VMNS_CONNECTED 0x00020000UL +#define VELOCITY_FLAGS_VMNS_COMMITTED 0x00040000UL +#define VELOCITY_FLAGS_WOL_ENABLED 0x00080000UL + +/* + * Flags for MII status + */ + +#define VELOCITY_LINK_FAIL 0x00000001UL +#define VELOCITY_SPEED_10 0x00000002UL +#define VELOCITY_SPEED_100 0x00000004UL +#define VELOCITY_SPEED_1000 0x00000008UL +#define VELOCITY_DUPLEX_FULL 0x00000010UL +#define VELOCITY_AUTONEG_ENABLE 0x00000020UL +#define VELOCITY_FORCED_BY_EEPROM 0x00000040UL + +/* + * For velocity_set_media_duplex + */ + +#define VELOCITY_LINK_CHANGE 0x00000001UL + +enum speed_opt { + SPD_DPX_AUTO = 0, + SPD_DPX_100_HALF = 1, + SPD_DPX_100_FULL = 2, + SPD_DPX_10_HALF = 3, + SPD_DPX_10_FULL = 4 +}; + +enum velocity_init_type { + VELOCITY_INIT_COLD = 0, + VELOCITY_INIT_RESET, + VELOCITY_INIT_WOL +}; + +enum velocity_flow_cntl_type { + FLOW_CNTL_DEFAULT = 1, + FLOW_CNTL_TX, + FLOW_CNTL_RX, + FLOW_CNTL_TX_RX, + FLOW_CNTL_DISABLE, +}; + +struct velocity_opt { + int numrx; /* Number of RX descriptors */ + int numtx; /* Number of TX descriptors */ + enum speed_opt spd_dpx; /* Media link mode */ + int vid; /* vlan id */ + int DMA_length; /* DMA length */ + int rx_thresh; /* RX_THRESH */ + int flow_cntl; + int wol_opts; /* Wake on lan options */ + int td_int_count; + int int_works; + int rx_bandwidth_hi; + int rx_bandwidth_lo; + int rx_bandwidth_en; + u32 flags; +}; + +struct velocity_info { + struct velocity_info *next; + struct velocity_info *prev; + + struct pci_dev *pdev; + struct net_device *dev; + struct net_device_stats stats; + +#if CONFIG_PM + u32 pci_state[16]; +#endif + + dma_addr_t rd_pool_dma; + dma_addr_t td_pool_dma[TX_QUEUE_NO]; + + dma_addr_t tx_bufs_dma; + u8 *tx_bufs; + + u8 ip_addr[4]; + enum chip_type chip_id; + + struct mac_regs * mac_regs; + unsigned long memaddr; + unsigned long ioaddr; + u32 io_size; + + u8 rev_id; + +#define AVAIL_TD(p,q) ((p)->options.numtx-((p)->td_used[(q)])) + + int num_txq; + + volatile int td_used[TX_QUEUE_NO]; + int td_curr[TX_QUEUE_NO]; + int td_tail[TX_QUEUE_NO]; + struct tx_desc *td_rings[TX_QUEUE_NO]; + struct velocity_td_info *td_infos[TX_QUEUE_NO]; + + int rd_curr; + int rd_used; + struct rx_desc *rd_ring; + struct velocity_rd_info *rd_info; /* It's an array */ + +#define GET_RD_BY_IDX(vptr, idx) (vptr->rd_ring[idx]) + u32 mib_counter[MAX_HW_MIB_COUNTER]; + struct velocity_opt options; + + u32 int_mask; + + u32 flags; + + int rx_buf_sz; + u32 mii_status; + u32 phy_id; + int multicast_limit; + + u8 vCAMmask[(VCAM_SIZE / 8)]; + u8 mCAMmask[(MCAM_SIZE / 8)]; + + spinlock_t lock; + spinlock_t xmit_lock; + + int wol_opts; + u8 wol_passwd[6]; + + struct velocity_context context; + + u32 ticks; + u32 rx_bytes; + +}; + +/** + * velocity_get_ip - find an IP address for the device + * @vptr: Velocity to query + * + * Dig out an IP address for this interface so that we can + * configure wakeup with WOL for ARP. If there are multiple IP + * addresses on this chain then we use the first - multi-IP WOL is not + * supported. + * + * CHECK ME: locking + */ + +inline static int velocity_get_ip(struct velocity_info *vptr) +{ + struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr; + struct in_ifaddr *ifa; + + if (in_dev != NULL) { + ifa = (struct in_ifaddr *) in_dev->ifa_list; + if (ifa != NULL) { + memcpy(vptr->ip_addr, &ifa->ifa_address, 4); + return 0; + } + } + return -ENOENT; +} + +/** + * velocity_update_hw_mibs - fetch MIB counters from chip + * @vptr: velocity to update + * + * The velocity hardware keeps certain counters in the hardware + * side. We need to read these when the user asks for statistics + * or when they overflow (causing an interrupt). The read of the + * statistic clears it, so we keep running master counters in user + * space. + */ + +static inline void velocity_update_hw_mibs(struct velocity_info *vptr) +{ + u32 tmp; + int i; + BYTE_REG_BITS_ON(MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR)); + + while (BYTE_REG_BITS_IS_ON(MIBCR_MIBFLSH, &(vptr->mac_regs->MIBCR))); + + BYTE_REG_BITS_ON(MIBCR_MPTRINI, &(vptr->mac_regs->MIBCR)); + for (i = 0; i < HW_MIB_SIZE; i++) { + tmp = readl(&(vptr->mac_regs->MIBData)) & 0x00FFFFFFUL; + vptr->mib_counter[i] += tmp; + } +} + +/** + * init_flow_control_register - set up flow control + * @vptr: velocity to configure + * + * Configure the flow control registers for this velocity device. + */ + +static inline void init_flow_control_register(struct velocity_info *vptr) +{ + struct mac_regs * regs = vptr->mac_regs; + + /* Set {XHITH1, XHITH0, XLTH1, XLTH0} in FlowCR1 to {1, 0, 1, 1} + depend on RD=64, and Turn on XNOEN in FlowCR1 */ + writel((CR0_XONEN | CR0_XHITH1 | CR0_XLTH1 | CR0_XLTH0), ®s->CR0Set); + writel((CR0_FDXTFCEN | CR0_FDXRFCEN | CR0_HDXFCEN | CR0_XHITH0), ®s->CR0Clr); + + /* Set TxPauseTimer to 0xFFFF */ + writew(0xFFFF, ®s->tx_pause_timer); + + /* Initialize RBRDU to Rx buffer count. */ + writew(vptr->options.numrx, ®s->RBRDU); +} + + +#endif diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c --- a/drivers/net/wd.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/wd.c 2004-06-20 13:00:23 -07:00 @@ -43,6 +43,8 @@ #include "8390.h" +#define DRV_NAME "wd" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int wd_portlist[] __initdata = {0x300, 0x280, 0x380, 0x240, 0}; @@ -131,6 +133,7 @@ release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT); } +#ifndef MODULE struct net_device * __init wd_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -155,6 +158,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init wd_probe1(struct net_device *dev, int ioaddr) { @@ -300,7 +304,7 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - i = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (i) { printk (" unable to get IRQ %d.\n", dev->irq); return i; diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c --- a/drivers/net/wireless/airo.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/wireless/airo.c 2004-06-20 13:00:23 -07:00 @@ -1209,6 +1209,7 @@ SsidRid *SSID; APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE + u32 pci_state[16]; }; static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, @@ -1963,7 +1964,7 @@ if ((skb = skb_dequeue(&ai->txq)) == 0) { printk (KERN_ERR - "airo_mpi: %s: Dequeue'd zero in send_packet()\n", + "airo: %s: Dequeue'd zero in send_packet()\n", __FUNCTION__); return 0; } @@ -2745,6 +2746,9 @@ SET_NETDEV_DEV(dev, &pci->dev); } + if (test_bit(FLAG_MPI,&ai->flags)) + reset_card (dev, 1); + rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev ); if (rc) { printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc ); @@ -4047,7 +4051,8 @@ Resp rsp; if (test_bit(FLAG_ENABLED, &ai->flags)) - printk(KERN_ERR "%s: MAC should be disabled (rid=%d)\n", + printk(KERN_ERR + "%s: MAC should be disabled (rid=%04x)\n", __FUNCTION__, rid); memset(&cmd, 0, sizeof(cmd)); memset(&rsp, 0, sizeof(rsp)); @@ -4527,6 +4532,8 @@ len = priv->maxwritelen - pos; if (copy_from_user(priv->wbuffer + pos, buffer, len)) return -EFAULT; + if ( pos + len > priv->writelen ) + priv->writelen = len + file->f_pos; *offset = pos + len; return len; } @@ -5470,9 +5477,6 @@ Cmd cmd; Resp rsp; - printk(KERN_DEBUG "%s: airo_mpi entering sleep mode (state=%d)\n", - dev->name, state); - if ((ai->APList == NULL) && (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL) return -ENOMEM; @@ -5490,7 +5494,10 @@ ai->power = state; cmd.cmd=HOSTSLEEP; issuecommand(ai, &cmd, &rsp); - return 0; + + pci_enable_wake(pdev, state, 1); + pci_save_state(pdev, ai->pci_state); + return pci_set_power_state(pdev, state); } static int airo_pci_resume(struct pci_dev *pdev) @@ -5499,12 +5506,12 @@ struct airo_info *ai = dev->priv; Resp rsp; - printk(KERN_DEBUG "%s: airo_mpi waking up\n", dev->name); - - if (!ai->power) - return 0; + pci_set_power_state(pdev, 0); + pci_restore_state(pdev, ai->pci_state); + pci_enable_wake(pdev, ai->power, 0); if (ai->power > 1) { + reset_card(dev, 0); mpi_init_descriptors(ai); setup_card(ai, dev->dev_addr, 0); clear_bit(FLAG_RADIO_OFF, &ai->flags); @@ -7166,6 +7173,7 @@ unsigned char *iobuf; int len; struct airo_info *ai = dev->priv; + Resp rsp; if (test_bit(FLAG_FLASHING, &ai->flags)) return -EIO; @@ -7173,8 +7181,11 @@ switch(comp->command) { case AIROGCAP: ridcode = RID_CAPABILITIES; break; - case AIROGCFG: writeConfigRid (ai, 1); - ridcode = RID_CONFIG; break; + case AIROGCFG: ridcode = RID_CONFIG; + disable_MAC (ai, 1); + writeConfigRid (ai, 1); + enable_MAC (ai, &rsp, 1); + break; case AIROGSLIST: ridcode = RID_SSID; break; case AIROGVLIST: ridcode = RID_APLIST; break; case AIROGDRVNAM: ridcode = RID_DRVNAME; break; @@ -7562,6 +7573,11 @@ set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (HZ); /* Added 12/7/00 */ clear_bit (FLAG_FLASHING, &ai->flags); + if (test_bit(FLAG_MPI, &ai->flags)) { + status = mpi_init_descriptors(ai); + if (status != SUCCESS) + return status; + } status = setup_card(ai, dev->dev_addr, 1); if (!test_bit(FLAG_MPI,&ai->flags)) diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c --- a/drivers/net/wireless/orinoco.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/wireless/orinoco.c 2004-06-20 13:00:26 -07:00 @@ -1519,7 +1519,8 @@ static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) { - printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); + if (net_ratelimit()) + printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); } static void print_linkstatus(struct net_device *dev, u16 status) diff -Nru a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c --- a/drivers/net/wireless/prism54/isl_38xx.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/wireless/prism54/isl_38xx.c 2004-06-20 13:00:24 -07:00 @@ -25,17 +25,11 @@ #include #include -#include "isl_38xx.h" -#include - #include #include -#include -#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) -#error No Firmware Loading configured in the kernel ! -#endif - +#include "prismcompat.h" +#include "isl_38xx.h" #include "islpci_dev.h" #include "islpci_mgt.h" @@ -233,130 +227,6 @@ ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP); isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); -} - -int -isl38xx_upload_firmware(char *fw_id, _REQ_FW_DEV_T dev, void *device_base, - dma_addr_t host_address) -{ - u32 reg, rc; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_ERROR_MESSAGES, "isl38xx_upload_firmware(0x%lx, 0x%lx)\n", - (long) device_base, (long) host_address); -#endif - - /* clear the RAMBoot and the Reset bit */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~ISL38XX_CTRL_STAT_RESET; - reg &= ~ISL38XX_CTRL_STAT_RAMBOOT; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the Reset bit without reading the register ! */ - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the Reset bit */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - - /* wait a while for the device to reboot */ - mdelay(50); - - { - const struct firmware *fw_entry = 0; - long fw_len; - const u32 *fw_ptr; - - rc = request_firmware(&fw_entry, fw_id, dev); - if (rc) { - printk(KERN_ERR - "%s: request_firmware() failed for '%s'\n", - "prism54", fw_id); - return rc; - } - /* prepare the Direct Memory Base register */ - reg = ISL38XX_DEV_FIRMWARE_ADDRES; - - fw_ptr = (u32 *) fw_entry->data; - fw_len = fw_entry->size; - - if (fw_len % 4) { - printk(KERN_ERR - "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", - "prism54", fw_id); - release_firmware(fw_entry); - return EILSEQ; /* Illegal byte sequence */; - } - - while (fw_len > 0) { - long _fw_len = - (fw_len > - ISL38XX_MEMORY_WINDOW_SIZE) ? - ISL38XX_MEMORY_WINDOW_SIZE : fw_len; - u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; - - /* set the cards base address for writting the data */ - isl38xx_w32_flush(device_base, reg, - ISL38XX_DIR_MEM_BASE_REG); - wmb(); /* be paranoid */ - - /* increment the write address for next iteration */ - reg += _fw_len; - fw_len -= _fw_len; - - /* write the data to the Direct Memory Window 32bit-wise */ - /* memcpy_toio() doesn't guarantee 32bit writes :-| */ - while (_fw_len > 0) { - /* use non-swapping writel() */ - __raw_writel(*fw_ptr, dev_fw_ptr); - fw_ptr++, dev_fw_ptr++; - _fw_len -= 4; - } - - /* flush PCI posting */ - (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH); - wmb(); /* be paranoid again */ - - BUG_ON(_fw_len != 0); - } - - BUG_ON(fw_len != 0); - - release_firmware(fw_entry); - } - - /* now reset the device - * clear the Reset & ClkRun bit, set the RAMBoot bit */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~ISL38XX_CTRL_STAT_CLKRUN; - reg &= ~ISL38XX_CTRL_STAT_RESET; - reg |= ISL38XX_CTRL_STAT_RAMBOOT; - isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the reset bit latches the host override and RAMBoot bits - * into the device for operation when the reset bit is reset */ - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - /* don't do flush PCI posting here! */ - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the reset bit should start the whole circus */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - /* don't do flush PCI posting here! */ - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - return 0; } int diff -Nru a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h --- a/drivers/net/wireless/prism54/isl_38xx.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/wireless/prism54/isl_38xx.h 2004-06-20 13:00:26 -07:00 @@ -22,14 +22,6 @@ #include #include - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75)) -#include -# define _REQ_FW_DEV_T struct device * -#else -# define _REQ_FW_DEV_T char * -#endif - #include #define ISL38XX_CB_RX_QSIZE 8 @@ -173,7 +165,5 @@ void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *); void isl38xx_trigger_device(int, void *); void isl38xx_interface_reset(void *, dma_addr_t); - -int isl38xx_upload_firmware(char *, _REQ_FW_DEV_T, void *, dma_addr_t); #endif /* _ISL_38XX_H */ diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c --- a/drivers/net/wireless/prism54/isl_ioctl.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/wireless/prism54/isl_ioctl.c 2004-06-20 13:00:24 -07:00 @@ -25,10 +25,10 @@ #include #include #include -#include #include +#include "prismcompat.h" #include "isl_ioctl.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ @@ -166,21 +166,13 @@ * for it save old values */ if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) { printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. " - "Using default mode\n", __FUNCTION__); + "Using default mode\n", __FUNCTION__); init_mode = CARD_DEFAULT_IW_MODE; } /* This sets all of the mode-dependent values */ prism54_mib_mode_helper(priv, init_mode); } -void -prism54_mib_init_work(islpci_private *priv) -{ - down_write(&priv->mib_sem); - mgt_commit(priv); - up_write(&priv->mib_sem); -} - /* this will be executed outside of atomic context thanks to * schedule_work(), thus we can as well use sleeping semaphore * locking */ @@ -195,16 +187,9 @@ if (down_interruptible(&priv->stats_sem)) return; -/* missing stats are : - * iwstatistics.qual.updated - * iwstatistics.discard.nwid - * iwstatistics.discard.fragment - * iwstatistics.discard.misc - * iwstatistics.miss.beacon */ - /* Noise floor. * I'm not sure if the unit is dBm. - * Note : If we are not connected, this value seems to be irrevelant. */ + * Note : If we are not connected, this value seems to be irrelevant. */ mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); priv->local_iwstatistics.qual.noise = r.u; @@ -216,8 +201,7 @@ data = r.ptr; /* copy this MAC to the bss */ - for (j = 0; j < 6; j++) - bss.address[j] = data[j]; + memcpy(bss.address, data, 6); kfree(data); /* now ask for the corresponding bss */ @@ -426,7 +410,6 @@ /* by default the card sets this to 20. */ sens = vwrq->disabled ? 20 : vwrq->value; - /* set the ed threshold. */ return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens); } @@ -505,7 +488,7 @@ return 0; /* Request the device for the supported frequencies - * not really revelant since some devices will report the 5 GHz band + * not really relevant since some devices will report the 5 GHz band * frequencies even if they don't support them. */ rvalue = @@ -515,21 +498,12 @@ range->num_channels = freq->nr; range->num_frequency = freq->nr; - /* Frequencies are not listed in the right order. The reordering is probably - * firmware dependant and thus should work for everyone. - */ m = min(IW_MAX_FREQUENCIES, (int) freq->nr); - for (i = 0; i < m - 12; i++) { - range->freq[i].m = freq->mhz[12 + i]; + for (i = 0; i < m; i++) { + range->freq[i].m = freq->mhz[i]; range->freq[i].e = 6; - range->freq[i].i = i + 1; + range->freq[i].i = channel_of_freq(freq->mhz[i]); } - for (i = m - 12; i < m; i++) { - range->freq[i].m = freq->mhz[i - m + 12]; - range->freq[i].e = 6; - range->freq[i].i = i + 23; - } - kfree(freq); rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); @@ -544,9 +518,7 @@ i++; data++; } - range->num_bitrates = i; - kfree(r.ptr); return rvalue; @@ -585,7 +557,6 @@ int rvalue; rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); - memcpy(awrq->sa_data, r.ptr, 6); awrq->sa_family = ARPHRD_ETHER; kfree(r.ptr); @@ -658,8 +629,8 @@ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = bss->channel; - iwe.u.freq.e = 6; + iwe.u.freq.m = channel_of_freq(bss->channel); + iwe.u.freq.e = 0; iwe.cmd = SIOCGIWFREQ; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -695,7 +666,6 @@ kfree(buf); } } - return current_ev; } @@ -722,7 +692,7 @@ /* Ask the device for a list of known bss. We can report at most * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of MAXBSS=24. Anyway 24 AP It is probably enough. + * if you change the value of IWMAX_BSS=24. */ rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; @@ -757,7 +727,7 @@ memcpy(essid.octets, extra, dwrq->length); } else essid.length = 0; - + if (priv->iw_mode != IW_MODE_MONITOR) return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid); @@ -843,21 +813,21 @@ char *data; int ret, i; union oid_res_t r; - + if (vwrq->value == -1) { /* auto mode. No limit. */ profile = 1; return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); } - + if ((ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r))) return ret; - + rate = (u32) (vwrq->value / 500000); data = r.ptr; i = 0; - + while (data[i]) { if (rate && (data[i] == rate)) { break; @@ -868,14 +838,14 @@ data[i] |= 0x80; i++; } - + if (!data[i]) { return -EINVAL; } - + data[i] |= 0x80; data[i + 1] = 0; - + /* Now, check if we want a fixed or auto value */ if (vwrq->fixed) { data[0] = data[i]; @@ -890,14 +860,14 @@ i++; } printk("0\n"); -*/ +*/ profile = -1; ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data); ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data); - + kfree(r.ptr); - + return ret; } @@ -923,7 +893,7 @@ data = r.ptr; vwrq->fixed = (data[0] != 0) && (data[1] == 0); kfree(r.ptr); - + return 0; } @@ -979,8 +949,6 @@ * small frame <=> smaller than the rts threshold * This is not really the behavior expected by the wireless tool but it seems * to be a common behavior in other drivers. - * - * It seems that playing with this tends to hang the card -> DISABLED */ static int @@ -1012,18 +980,16 @@ lifetime = vwrq->value / 1024; /* now set what is requested */ - - if (slimit != 0) + if (slimit) rvalue = mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit); - if (llimit != 0) + if (llimit) rvalue |= mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit); - if (lifetime != 0) + if (lifetime) rvalue |= mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0, &lifetime); - return rvalue; } @@ -1119,8 +1085,7 @@ } } } - - /* now read the flags */ + /* now read the flags */ if (dwrq->flags & IW_ENCODE_DISABLED) { /* Encoding disabled, * authen = DOT11_AUTH_OS; @@ -1269,13 +1234,8 @@ static int prism54_set_u32(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 * uwrq, char *extra) { - /* - u32 *i = (int *) extra; - int param = *i; - int u = *(i + 1); - */ u32 oid = uwrq[0], u = uwrq[1]; return mgt_set_request((islpci_private *) ndev->priv, oid, 0, &u); @@ -1846,9 +1806,7 @@ 0); break; - /* Note : the following should never happen since we don't run the card in - * extended mode. - * Note : "mlme" is actually a "struct obj_mlmeex *" here, but this + /* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this * is backward compatible layout-wise with "struct obj_mlme". */ @@ -1893,7 +1851,8 @@ struct net_device *ndev = frame->ndev; enum oid_num_t n = mgt_oidtonum(frame->header->oid); - prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); + if (n != OID_NUM_LAST) + prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); islpci_mgt_release(frame); } @@ -1966,65 +1925,11 @@ } int -prism54_set_maxframeburst(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 max_burst; - - max_burst = (*uwrq) ? *uwrq : CARD_DEFAULT_MAXFRAMEBURST; - mgt_set_request(priv, DOT11_OID_MAXFRAMEBURST, 0, &max_burst); - - return -EINPROGRESS; /* Call commit handler */ -} - -int -prism54_get_maxframeburst(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_MAXFRAMEBURST, 0, NULL, &r); - *uwrq = r.u; - - return rvalue; -} - -int -prism54_set_profile(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 profile; - - profile = (*uwrq) ? *uwrq : CARD_DEFAULT_PROFILE; - mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); - - return -EINPROGRESS; /* Call commit handler */ -} - -int -prism54_get_profile(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_PROFILES, 0, NULL, &r); - *uwrq = r.u; - - return rvalue; -} - -int prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - + priv->priv_oid = *uwrq; printk("%s: oid 0x%08X\n", ndev->name, *uwrq); @@ -2033,15 +1938,15 @@ int prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; int ret = -EIO, response_op = PIMFOR_OP_ERROR; - + printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); data->length = 0; - + if (islpci_get_state(priv) >= PRV_STATE_INIT) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, @@ -2065,21 +1970,21 @@ printk("%s: len: %i\n", ndev->name, data->length); } } - + return ret; } int prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; int ret = 0, response_op = PIMFOR_OP_ERROR; - + printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, data->length); - + if (islpci_get_state(priv) >= PRV_STATE_INIT) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, @@ -2094,11 +1999,11 @@ } if (ret || response_op == PIMFOR_OP_ERROR) { printk("%s: EIO\n", ndev->name); - ret = -EIO; + ret = -EIO; } } - - return ret; + + return (ret ? ret : -EINPROGRESS); } static int @@ -2196,7 +2101,7 @@ #define PRISM54_DBG_GET_OID SIOCIWFIRSTPRIV+15 #define PRISM54_DBG_SET_OID SIOCIWFIRSTPRIV+16 -#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 +#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 #define PRISM54_SET_OID_U32 SIOCIWFIRSTPRIV+18 #define PRISM54_SET_OID_STR SIOCIWFIRSTPRIV+20 #define PRISM54_SET_OID_ADDR SIOCIWFIRSTPRIV+22 @@ -2204,16 +2109,16 @@ #define PRISM54_GET_PRISMHDR SIOCIWFIRSTPRIV+23 #define PRISM54_SET_PRISMHDR SIOCIWFIRSTPRIV+24 -#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x } -#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x } -#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x } -#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "get_"x } +#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x } #define IWPRIV_U32(n,x) IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x) #define IWPRIV_SSID(n,x) IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x) #define IWPRIV_ADDR(n,x) IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x) -/* Note : limited to 128 private ioctls */ +/* Note : limited to 128 private ioctls (wireless tools 26) */ static const struct iw_priv_args prism54_private_args[] = { /*{ cmd, set_args, get_args, name } */ @@ -2241,7 +2146,7 @@ {PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dbg_oid"}, {PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"}, - {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_get_oid"}, + {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"}, /* --- sub-ioctls handlers --- */ {PRISM54_GET_OID, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""}, @@ -2268,7 +2173,7 @@ IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"), IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"), IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"), - + IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"), IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"), @@ -2351,5 +2256,6 @@ int prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { + return -EOPNOTSUPP; } diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h --- a/drivers/net/wireless/prism54/isl_ioctl.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/wireless/prism54/isl_ioctl.h 2004-06-20 13:00:24 -07:00 @@ -30,7 +30,6 @@ #define SUPPORTED_WIRELESS_EXT 16 void prism54_mib_init(islpci_private *); -void prism54_mib_init_work(islpci_private *); struct iw_statistics *prism54_get_wireless_stats(struct net_device *); void prism54_update_stats(islpci_private *); diff -Nru a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c --- a/drivers/net/wireless/prism54/islpci_dev.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/wireless/prism54/islpci_dev.c 2004-06-20 13:00:23 -07:00 @@ -30,6 +30,7 @@ #include +#include "prismcompat.h" #include "isl_38xx.h" #include "isl_ioctl.h" #include "islpci_dev.h" @@ -37,12 +38,6 @@ #include "islpci_eth.h" #include "oid_mgt.h" -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) -#define prism54_synchronize_irq(irq) synchronize_irq() -#else -#define prism54_synchronize_irq(irq) synchronize_irq(irq) -#endif - #define ISL3877_IMAGE_FILE "isl3877" #define ISL3890_IMAGE_FILE "isl3890" @@ -55,6 +50,125 @@ * ndev->set_mac_address. Jean II */ const unsigned char dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 }; +static int +isl_upload_firmware(islpci_private *priv) +{ + u32 reg, rc; + void *device_base = priv->device_base; + + /* clear the RAMBoot and the Reset bit */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~ISL38XX_CTRL_STAT_RESET; + reg &= ~ISL38XX_CTRL_STAT_RAMBOOT; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the Reset bit without reading the register ! */ + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the Reset bit */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + + /* wait a while for the device to reboot */ + mdelay(50); + + { + const struct firmware *fw_entry = 0; + long fw_len; + const u32 *fw_ptr; + + rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV); + if (rc) { + printk(KERN_ERR + "%s: request_firmware() failed for '%s'\n", + "prism54", priv->firmware); + return rc; + } + /* prepare the Direct Memory Base register */ + reg = ISL38XX_DEV_FIRMWARE_ADDRES; + + fw_ptr = (u32 *) fw_entry->data; + fw_len = fw_entry->size; + + if (fw_len % 4) { + printk(KERN_ERR + "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", + "prism54", priv->firmware); + release_firmware(fw_entry); + return EILSEQ; /* Illegal byte sequence */; + } + + while (fw_len > 0) { + long _fw_len = + (fw_len > + ISL38XX_MEMORY_WINDOW_SIZE) ? + ISL38XX_MEMORY_WINDOW_SIZE : fw_len; + u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; + + /* set the cards base address for writting the data */ + isl38xx_w32_flush(device_base, reg, + ISL38XX_DIR_MEM_BASE_REG); + wmb(); /* be paranoid */ + + /* increment the write address for next iteration */ + reg += _fw_len; + fw_len -= _fw_len; + + /* write the data to the Direct Memory Window 32bit-wise */ + /* memcpy_toio() doesn't guarantee 32bit writes :-| */ + while (_fw_len > 0) { + /* use non-swapping writel() */ + __raw_writel(*fw_ptr, dev_fw_ptr); + fw_ptr++, dev_fw_ptr++; + _fw_len -= 4; + } + + /* flush PCI posting */ + (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH); + wmb(); /* be paranoid again */ + + BUG_ON(_fw_len != 0); + } + + BUG_ON(fw_len != 0); + + release_firmware(fw_entry); + } + + /* now reset the device + * clear the Reset & ClkRun bit, set the RAMBoot bit */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~ISL38XX_CTRL_STAT_CLKRUN; + reg &= ~ISL38XX_CTRL_STAT_RESET; + reg |= ISL38XX_CTRL_STAT_RAMBOOT; + isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the reset bit latches the host override and RAMBoot bits + * into the device for operation when the reset bit is reset */ + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + /* don't do flush PCI posting here! */ + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the reset bit should start the whole circus */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + /* don't do flush PCI posting here! */ + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + return 0; +} + /****************************************************************************** Device Interrupt Handler ******************************************************************************/ @@ -74,7 +188,9 @@ if (reg & ISL38XX_CTRL_STAT_SLEEPMODE) /* device is in sleep mode, IRQ was generated by someone else */ { - printk(KERN_DEBUG "Assuming someone else called the IRQ\n"); +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); +#endif return IRQ_NONE; } @@ -324,14 +440,7 @@ printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name); - rc = isl38xx_upload_firmware(priv->firmware, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75)) - &priv->pdev->dev, -#else - pci_name(priv->pdev), -#endif - priv->device_base, - priv->device_host_address); + rc = isl_upload_firmware(priv); if (rc) { /* error uploading the firmware */ printk(KERN_ERR "%s: could not upload firmware ('%s')\n", @@ -357,15 +466,8 @@ int result = -ETIME; int count; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* This is 2.6 specific, nicer, shorter, but not in 2.4 yet */ DEFINE_WAIT(wait); prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE); -#else - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&priv->reset_done, &wait); -#endif /* now the last step is to reset the interface */ isl38xx_interface_reset(priv->device_base, priv->device_host_address); @@ -390,13 +492,7 @@ } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* 2.6 specific too */ finish_wait(&priv->reset_done, &wait); -#else - remove_wait_queue(&priv->reset_done, &wait); - set_current_state(TASK_RUNNING); -#endif if(result) return result; @@ -410,7 +506,9 @@ * the IRQ line until we know for sure the reset went through */ isl38xx_enable_common_interrupts(priv->device_base); - prism54_mib_init_work(priv); + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); islpci_set_state(priv, PRV_STATE_READY); @@ -448,9 +546,9 @@ /* reset the mgmt receive queue */ for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { isl38xx_fragment *frag = &cb->rx_data_mgmt[counter]; - frag->size = MGMT_FRAME_SIZE; + frag->size = cpu_to_le16(MGMT_FRAME_SIZE); frag->flags = 0; - frag->address = priv->mgmt_rx[counter].pci_addr; + frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr); } for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { @@ -580,6 +678,7 @@ skb = NULL; goto out_free; } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* add the new allocated sk_buff to the buffer array */ priv->data_low_rx[counter] = skb; diff -Nru a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h --- a/drivers/net/wireless/prism54/islpci_dev.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/wireless/prism54/islpci_dev.h 2004-06-20 13:00:24 -07:00 @@ -29,20 +29,6 @@ #include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -# include -#else -# include -# define work_struct tq_struct -# define INIT_WORK INIT_TQUEUE -# define schedule_work schedule_task -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) -#define free_netdev(x) kfree(x) -#define pci_name(x) x->slot_name -#endif - #include "isl_38xx.h" #include "isl_oid.h" #include "islpci_mgt.h" @@ -187,7 +173,7 @@ islpci_state_t state; int state_off; /* enumeration of off-state, if 0 then * we're not in any off-state */ - + /* WPA stuff */ int wpa; /* WPA mode enabled */ struct list_head bss_wpa_list; @@ -209,12 +195,6 @@ islpci_state_t islpci_set_state(islpci_private *priv, islpci_state_t new_state); #define ISLPCI_TX_TIMEOUT (2*HZ) - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,75)) -# define irqreturn_t void -# define IRQ_HANDLED -# define IRQ_NONE -#endif irqreturn_t islpci_interrupt(int, void *, struct pt_regs *); diff -Nru a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c --- a/drivers/net/wireless/prism54/islpci_eth.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/wireless/prism54/islpci_eth.c 2004-06-20 13:00:23 -07:00 @@ -26,6 +26,7 @@ #include #include +#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_eth.h" #include "islpci_mgt.h" @@ -104,7 +105,7 @@ /* check whether the destination queue has enough fragments for the frame */ curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]); - if (curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE) { + if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) { printk(KERN_ERR "%s: transmit device queue full when awake\n", ndev->name); netif_stop_queue(ndev); @@ -120,7 +121,7 @@ /* Check alignment and WDS frame formatting. The start of the packet should * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes * and add WDS address information */ - if (((long) skb->data & 0x03) | init_wds) { + if (unlikely(((long) skb->data & 0x03) | init_wds)) { /* get the number of bytes to add and re-allign */ offset = (4 - (long) skb->data) & 0x03; offset += init_wds ? 6 : 0; @@ -191,7 +192,7 @@ pci_map_address = pci_map_single(priv->pdev, (void *) skb->data, skb->len, PCI_DMA_TODEVICE); - if (pci_map_address == 0) { + if (unlikely(pci_map_address == 0)) { printk(KERN_WARNING "%s: cannot map buffer to PCI\n", ndev->name); @@ -207,7 +208,7 @@ priv->data_low_tx[index] = skb; /* set the proper fragment start address and size information */ fragment->size = cpu_to_le16(frame_size); - fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ + fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ fragment->address = cpu_to_le32(pci_map_address); curr_frag++; @@ -217,7 +218,7 @@ cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag); if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD - > ISL38XX_CB_TX_QSIZE) { + > ISL38XX_CB_TX_QSIZE) { /* stop sends from upper layers */ netif_stop_queue(ndev); @@ -238,7 +239,7 @@ return 0; - drop_free: + drop_free: /* free the skbuf structure before aborting */ dev_kfree_skb(skb); skb = NULL; @@ -261,9 +262,9 @@ if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) { struct avs_80211_1_header *avs; /* extract the relevant data from the header */ - u32 clock = hdr->clock; + u32 clock = le32_to_cpu(hdr->clock); u8 rate = hdr->rate; - u16 freq = be16_to_cpu(hdr->freq); + u16 freq = le16_to_cpu(hdr->freq); u8 rssi = hdr->rssi; skb_pull(*skb, sizeof (struct rfmon_header)); @@ -274,7 +275,7 @@ avs_80211_1_header), 0, GFP_ATOMIC); if (newskb) { - kfree_skb(*skb); + dev_kfree_skb_irq(*skb); *skb = newskb; } else return -1; @@ -286,21 +287,21 @@ (struct avs_80211_1_header *) skb_push(*skb, sizeof (struct avs_80211_1_header)); - - avs->version = htonl(P80211CAPTURE_VERSION); - avs->length = htonl(sizeof (struct avs_80211_1_header)); - avs->mactime = __cpu_to_be64(clock); - avs->hosttime = __cpu_to_be64(jiffies); - avs->phytype = htonl(6); /*OFDM: 6 for (g), 8 for (a) */ - avs->channel = htonl(channel_of_freq(freq)); - avs->datarate = htonl(rate * 5); - avs->antenna = htonl(0); /*unknown */ - avs->priority = htonl(0); /*unknown */ - avs->ssi_type = htonl(2); /*2: dBm, 3: raw RSSI */ - avs->ssi_signal = htonl(rssi); - avs->ssi_noise = htonl(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ - avs->preamble = htonl(0); /*unknown */ - avs->encoding = htonl(0); /*unknown */ + + avs->version = cpu_to_be32(P80211CAPTURE_VERSION); + avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); + avs->mactime = cpu_to_be64(le64_to_cpu(clock)); + avs->hosttime = cpu_to_be64(jiffies); + avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ + avs->channel = cpu_to_be32(channel_of_freq(freq)); + avs->datarate = cpu_to_be32(rate * 5); + avs->antenna = cpu_to_be32(0); /*unknown */ + avs->priority = cpu_to_be32(0); /*unknown */ + avs->ssi_type = cpu_to_be32(3); /*2: dBm, 3: raw RSSI */ + avs->ssi_signal = cpu_to_be32(rssi & 0x7f); + avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ + avs->preamble = cpu_to_be32(0); /*unknown */ + avs->encoding = cpu_to_be32(0); /*unknown */ } else skb_pull(*skb, sizeof (struct rfmon_header)); @@ -381,10 +382,10 @@ skb->dev = ndev; /* take care of monitor mode and spy monitoring. */ - if (priv->iw_mode == IW_MODE_MONITOR) + if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) discard = islpci_monitor_rx(priv, &skb); else { - if (skb->data[2 * ETH_ALEN] == 0) { + if (unlikely(skb->data[2 * ETH_ALEN] == 0)) { /* The packet has a rx_annex. Read it for spy monitoring, Then * remove it, while keeping the 2 leading MAC addr. */ @@ -417,8 +418,8 @@ skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5]); #endif - if (discard) { - dev_kfree_skb(skb); + if (unlikely(discard)) { + dev_kfree_skb_irq(skb); skb = NULL; } else netif_rx(skb); @@ -433,11 +434,13 @@ index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) { /* allocate an sk_buff for received data frames storage * include any required allignment operations */ - if (skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2), skb == NULL) { + skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); + if (unlikely(skb == NULL)) { /* error allocating an sk_buff structure elements */ DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); break; } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* store the new skb structure pointer */ index = index % ISL38XX_CB_RX_QSIZE; priv->data_low_rx[index] = skb; @@ -453,13 +456,13 @@ pci_map_single(priv->pdev, (void *) skb->data, MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - if (priv->pci_map_rx_address[index] == (dma_addr_t) NULL) { + if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) { /* error mapping the buffer to device accessable memory address */ DEBUG(SHOW_ERROR_MESSAGES, "Error mapping DMA address\n"); /* free the skbuf structure before aborting */ - dev_kfree_skb((struct sk_buff *) skb); + dev_kfree_skb_irq((struct sk_buff *) skb); skb = NULL; break; } @@ -484,10 +487,10 @@ void islpci_do_reset_and_wake(void *data) { - islpci_private *priv = (islpci_private *) data; - islpci_reset(priv, 1); - netif_wake_queue(priv->ndev); - priv->reset_task_pending = 0; + islpci_private *priv = (islpci_private *) data; + islpci_reset(priv, 1); + netif_wake_queue(priv->ndev); + priv->reset_task_pending = 0; } void diff -Nru a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c --- a/drivers/net/wireless/prism54/islpci_hotplug.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/wireless/prism54/islpci_hotplug.c 2004-06-20 13:00:24 -07:00 @@ -24,12 +24,13 @@ #include #include /* For __init, __exit */ +#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" /* for pc_debug */ #include "isl_oid.h" #define DRV_NAME "prism54" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team "); MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c --- a/drivers/net/wireless/prism54/islpci_mgt.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/wireless/prism54/islpci_mgt.c 2004-06-20 13:00:25 -07:00 @@ -22,12 +22,12 @@ #include #include #include -#include #include #include #include +#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ @@ -63,7 +63,6 @@ Queue handling for management frames ******************************************************************************/ - /* * Helper function to create a PIMFOR management frame header. */ @@ -86,8 +85,8 @@ { pimfor_header_t *h = data; - while ((void *) h < data + len) { - if(h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { + while ((void *) h < data + len) { + if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { le32_to_cpus(&h->oid); le32_to_cpus(&h->length); } else { @@ -108,8 +107,8 @@ islpci_mgmt_rx_fill(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); #if VERBOSE > SHOW_ERROR_MESSAGES @@ -124,7 +123,8 @@ if (buf->mem == NULL) { buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC); if (!buf->mem) { - printk(KERN_WARNING "Error allocating management frame.\n"); + printk(KERN_WARNING + "Error allocating management frame.\n"); return -ENOMEM; } buf->size = MGMT_FRAME_SIZE; @@ -133,24 +133,24 @@ buf->pci_addr = pci_map_single(priv->pdev, buf->mem, MGMT_FRAME_SIZE, PCI_DMA_FROMDEVICE); - if(!buf->pci_addr) { - printk(KERN_WARNING "Failed to make memory DMA'able\n."); + if (!buf->pci_addr) { + printk(KERN_WARNING + "Failed to make memory DMA'able\n."); return -ENOMEM; } } - /* be safe: always reset control block information */ + /* be safe: always reset control block information */ frag->size = cpu_to_le16(MGMT_FRAME_SIZE); frag->flags = 0; frag->address = cpu_to_le32(buf->pci_addr); curr++; - /* The fragment address in the control block must have - * been written before announcing the frame buffer to - * device */ + /* The fragment address in the control block must have + * been written before announcing the frame buffer to + * device */ wmb(); - cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = - cpu_to_le32(curr); + cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr); } return 0; } @@ -168,7 +168,7 @@ { islpci_private *priv = netdev_priv(ndev); isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; + (isl38xx_control_block *) priv->control_block; void *p; int err = -EINVAL; unsigned long flags; @@ -242,25 +242,25 @@ priv->mgmt_tx[index] = buf; frag = &cb->tx_data_mgmt[index]; frag->size = cpu_to_le16(frag_len); - frag->flags = 0; /* for any other than the last fragment, set to 1 */ + frag->flags = 0; /* for any other than the last fragment, set to 1 */ frag->address = cpu_to_le32(buf.pci_addr); /* The fragment address in the control block must have * been written before announcing the frame buffer to * device */ wmb(); - cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag+1); + cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1); spin_unlock_irqrestore(&priv->slock, flags); /* trigger the device */ islpci_trigger(priv); return 0; - error_unlock: + error_unlock: spin_unlock_irqrestore(&priv->slock, flags); - error_free: + error_free: kfree(buf.mem); - error: + error: return err; } @@ -274,50 +274,49 @@ { islpci_private *priv = netdev_priv(ndev); isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; + (isl38xx_control_block *) priv->control_block; u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); #endif - - /* Only once per interrupt, determine fragment range to - * process. This avoids an endless loop (i.e. lockup) if - * frames come in faster than we can process them. */ + /* Only once per interrupt, determine fragment range to + * process. This avoids an endless loop (i.e. lockup) if + * frames come in faster than we can process them. */ curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]); barrier(); - for ( ; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { + for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { pimfor_header_t *header; u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE; struct islpci_membuf *buf = &priv->mgmt_rx[index]; u16 frag_len; int size; struct islpci_mgmtframe *frame; - - /* I have no idea (and no documentation) if flags != 0 - * is possible. Drop the frame, reuse the buffer. */ - if(le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { - printk(KERN_WARNING "%s: unknown flags 0x%04x\n", - ndev->name, - le16_to_cpu(cb->rx_data_mgmt[index].flags)); - continue; - } + + /* I have no idea (and no documentation) if flags != 0 + * is possible. Drop the frame, reuse the buffer. */ + if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { + printk(KERN_WARNING "%s: unknown flags 0x%04x\n", + ndev->name, + le16_to_cpu(cb->rx_data_mgmt[index].flags)); + continue; + } /* The device only returns the size of the header(s) here. */ frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size); /* - * We appear to have no way to tell the device the - * size of a receive buffer. Thus, if this check - * triggers, we likely have kernel heap corruption. */ - if (frag_len > MGMT_FRAME_SIZE) { - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\ -n", - ndev->name, frag_len, frag_len); - frag_len = MGMT_FRAME_SIZE; - } + * We appear to have no way to tell the device the + * size of a receive buffer. Thus, if this check + * triggers, we likely have kernel heap corruption. */ + if (frag_len > MGMT_FRAME_SIZE) { + printk(KERN_WARNING + "%s: Bogus packet size of %d (%#x).\n", + ndev->name, frag_len, frag_len); + frag_len = MGMT_FRAME_SIZE; + } /* Ensure the results of device DMA are visible to the CPU. */ pci_dma_sync_single(priv->pdev, buf->pci_addr, @@ -339,30 +338,32 @@ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_PIMFOR_FRAMES, "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", - header->operation, header->oid, header->device_id, + header->operation, header->oid, header->device_id, header->flags, header->length); /* display the buffer contents for debugging */ display_buffer((char *) header, PIMFOR_HEADER_SIZE); - display_buffer((char *) header + PIMFOR_HEADER_SIZE, header->length); + display_buffer((char *) header + PIMFOR_HEADER_SIZE, + header->length); #endif /* nobody sends these */ if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) { - printk(KERN_DEBUG "%s: errant PIMFOR application frame\n", + printk(KERN_DEBUG + "%s: errant PIMFOR application frame\n", ndev->name); continue; } /* Determine frame size, skipping OID_INL_TUNNEL headers. */ size = PIMFOR_HEADER_SIZE + header->length; - frame = kmalloc(sizeof(struct islpci_mgmtframe) + size, + frame = kmalloc(sizeof (struct islpci_mgmtframe) + size, GFP_ATOMIC); if (!frame) { - printk(KERN_WARNING "%s: Out of memory, cannot handle oid 0x%08x\n", - + printk(KERN_WARNING + "%s: Out of memory, cannot handle oid 0x%08x\n", ndev->name, header->oid); - continue; + continue; } frame->ndev = ndev; memcpy(&frame->buf, header, size); @@ -382,7 +383,7 @@ header->oid, header->device_id, header->flags, header->length); #endif - + /* Create work to handle trap out of interrupt * context. */ INIT_WORK(&frame->ws, prism54_process_trap, frame); @@ -392,14 +393,13 @@ /* Signal the one waiting process that a response * has been received. */ if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) { - printk(KERN_WARNING "%s: mgmt response not collected\n", + printk(KERN_WARNING + "%s: mgmt response not collected\n", ndev->name); kfree(frame); } - #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "Wake up Mgmt Queue\n"); + DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n"); #endif wake_up(&priv->mgmt_wqueue); } @@ -416,22 +416,22 @@ islpci_mgt_cleanup_transmit(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); #endif /* Only once per cleanup, determine fragment range to * process. This avoids an endless loop (i.e. lockup) if * the device became confused, incrementing device_curr_frag * rapidly. */ - curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); + curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); barrier(); - for ( ; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { + for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE; struct islpci_membuf *buf = &priv->mgmt_tx[index]; pci_unmap_single(priv->pdev, buf->pci_addr, buf->size, @@ -456,23 +456,14 @@ const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000; long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies; int err; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) DEFINE_WAIT(wait); -#else - DECLARE_WAITQUEUE(wait, current); -#endif if (down_interruptible(&priv->mgmt_sem)) return -ERESTARTSYS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE); -#else - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&priv->mgmt_wqueue, &wait); -#endif err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen); - if(err) + if (err) goto out; err = -ETIMEDOUT; @@ -483,13 +474,24 @@ timeleft = schedule_timeout(wait_cycle_jiffies); frame = xchg(&priv->mgmt_received, NULL); if (frame) { - *recvframe = frame; - err = 0; - goto out; - } - if(timeleft == 0) { - printk(KERN_DEBUG "%s: timeout waiting for mgmt response %lu, trigging device\n", - ndev->name, timeout_left); + if (frame->header->oid == oid) { + *recvframe = frame; + err = 0; + goto out; + } else { + printk(KERN_DEBUG + "%s: expecting oid 0x%x, received 0x%x.\n", + ndev->name, (unsigned int) oid, + frame->header->oid); + kfree(frame); + frame = NULL; + } + } + if (timeleft == 0) { + printk(KERN_DEBUG + "%s: timeout waiting for mgmt response %lu, " + "triggering device\n", + ndev->name, timeout_left); islpci_trigger(priv); } timeout_left += timeleft - wait_cycle_jiffies; @@ -499,12 +501,7 @@ /* TODO: we should reset the device here */ out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) finish_wait(&priv->mgmt_wqueue, &wait); -#else - remove_wait_queue(&priv->mgmt_wqueue, &wait); - set_current_state(TASK_RUNNING); -#endif up(&priv->mgmt_sem); return err; } diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h --- a/drivers/net/wireless/prism54/islpci_mgt.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/net/wireless/prism54/islpci_mgt.h 2004-06-20 13:00:23 -07:00 @@ -24,15 +24,6 @@ #include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -# include -#else -# include -# define work_struct tq_struct -# define INIT_WORK INIT_TQUEUE -# define schedule_work schedule_task -#endif - /* * Function definitions */ @@ -43,7 +34,7 @@ #define TRACE(devname) K_DEBUG(SHOW_TRACING, VERBOSE, "%s: -> " __FUNCTION__ "()\n", devname) extern int pc_debug; -static const int init_wds = 0; /* help compiler optimize away dead code */ +#define init_wds 0 /* help compiler optimize away dead code */ /* General driver definitions */ diff -Nru a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c --- a/drivers/net/wireless/prism54/oid_mgt.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/wireless/prism54/oid_mgt.c 2004-06-20 13:00:26 -07:00 @@ -16,6 +16,7 @@ * */ +#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" #include "isl_oid.h" @@ -39,17 +40,13 @@ if ((f >= 2412) && (f <= 2484)) { while ((c < 14) && (f != frequency_list_bg[c])) c++; - if (c >= 14) - return 0; + return (c >= 14) ? 0 : ++c; } else if ((f >= (int) 5170) && (f <= (int) 5320)) { while ((c < 12) && (f != frequency_list_a[c])) c++; - if (c >= 12) - return 0; + return (c >= 12) ? 0 : (c + 37); } else return 0; - - return ++c; } #define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t} @@ -449,7 +446,7 @@ if (cache) down_write(&priv->mib_sem); - if (islpci_get_state(priv) >= PRV_STATE_INIT) { + if (islpci_get_state(priv) >= PRV_STATE_READY) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, _data, dlen, &response); if (!ret) { @@ -457,7 +454,7 @@ islpci_mgt_release(response); } if (ret || response_op == PIMFOR_OP_ERROR) - ret = -EIO; + ret = -EIO; } else if (!cache) ret = -EIO; @@ -482,7 +479,7 @@ int ret = -EIO; int reslen = 0; struct islpci_mgmtframe *response = NULL; - + int dlen; void *cache, *_res = NULL; u32 oid; @@ -503,11 +500,11 @@ if (cache) down_read(&priv->mib_sem); - if (islpci_get_state(priv) >= PRV_STATE_INIT) { + if (islpci_get_state(priv) >= PRV_STATE_READY) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, oid, data, dlen, &response); if (ret || !response || - response->header->operation == PIMFOR_OP_ERROR) { + response->header->operation == PIMFOR_OP_ERROR) { if (response) islpci_mgt_release(response); ret = -EIO; @@ -542,9 +539,9 @@ if (reslen > isl_oid[n].size) printk(KERN_DEBUG "mgt_get_request(0x%x): received data length was bigger " - "than expected (%d > %d). Memory is probably corrupted... ", + "than expected (%d > %d). Memory is probably corrupted...", oid, reslen, isl_oid[n].size); - + return ret; } @@ -564,11 +561,11 @@ while (j <= t->range) { response = NULL; ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, - oid, data, t->size, + oid, data, t->size, &response); if (response) { ret |= (response->header->operation == - PIMFOR_OP_ERROR); + PIMFOR_OP_ERROR); islpci_mgt_release(response); } j++; @@ -625,12 +622,32 @@ OID_INL_OUTPUTPOWER, }; +/* update the MAC addr. */ +static int +mgt_update_addr(islpci_private *priv) +{ + struct islpci_mgmtframe *res; + int ret; + + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + isl_oid[GEN_OID_MACADDRESS].oid, NULL, + isl_oid[GEN_OID_MACADDRESS].size, &res); + + if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) + memcpy(priv->ndev->dev_addr, res->data, 6); + else + ret = -EIO; + if (res) + islpci_mgt_release(res); + + return ret; +} + void mgt_commit(islpci_private *priv) { int rvalue; u32 u; - union oid_res_t r; if (islpci_get_state(priv) < PRV_STATE_INIT) return; @@ -646,21 +663,14 @@ u = OID_INL_MODE; rvalue |= mgt_commit_list(priv, &u, 1); + rvalue |= mgt_update_addr(priv); if (rvalue) { /* some request have failed. The device might be in an incoherent state. We should reset it ! */ printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the " - "device \n", priv->ndev->name); + "device \n", priv->ndev->name); } - - /* update the MAC addr. As it's not cached, no lock will be acquired by - * the mgt_get_request - */ - mgt_get_request(priv, GEN_OID_MACADDRESS, 0, NULL, &r); - memcpy(priv->ndev->dev_addr, r.ptr, 6); - kfree(r.ptr); - } /* This will tell you if you are allowed to answer a mlme(ex) request .*/ @@ -687,13 +697,13 @@ { int i; - for (i = 0; i < OID_NUM_LAST - 1; i++) + for (i = 0; i < OID_NUM_LAST; i++) if (isl_oid[i].oid == oid) return i; printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid); - return 0; + return OID_NUM_LAST; } int @@ -713,8 +723,11 @@ case OID_TYPE_BSS:{ struct obj_bss *bss = r->ptr; return snprintf(str, PRIV_STR_SIZE, - "age=%u\nchannel=%u\n\ - capinfo=0x%X\nrates=0x%X\nbasic_rates=0x%X\n", bss->age, bss->channel, bss->capinfo, bss->rates, bss->basic_rates); + "age=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", bss->age, + bss->channel, bss->capinfo, + bss->rates, bss->basic_rates); } break; case OID_TYPE_BSSLIST:{ @@ -723,7 +736,9 @@ k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); for (i = 0; i < list->nr; i++) k += snprintf(str + k, PRIV_STR_SIZE - k, - "bss[%u] : \nage=%u\nchannel=%u\ncapinfo=0x%X\nrates=0x%X\nbasic_rates=0x%X\n", + "bss[%u] : \nage=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", i, list->bsslist[i].age, list->bsslist[i].channel, list->bsslist[i].capinfo, @@ -745,16 +760,17 @@ break; case OID_TYPE_MLME:{ struct obj_mlme *mlme = r->ptr; - return snprintf(str, PRIV_STR_SIZE, "id=0x%X\nstate=0x%X\n\ - code=0x%X\n", mlme->id, mlme->state, - mlme->code); + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\ncode=0x%X\n", + mlme->id, mlme->state, mlme->code); } break; case OID_TYPE_MLMEEX:{ struct obj_mlmeex *mlme = r->ptr; - return snprintf(str, PRIV_STR_SIZE, "id=0x%X\nstate=0x%X\n\ - code=0x%X\nsize=0x%X\n", mlme->id, mlme->state, - mlme->code, mlme->size); + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\n" + "code=0x%X\nsize=0x%X\n", mlme->id, + mlme->state, mlme->code, mlme->size); } break; case OID_TYPE_SSID:{ diff -Nru a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h --- a/drivers/net/wireless/prism54/oid_mgt.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/net/wireless/prism54/oid_mgt.h 2004-06-20 13:00:26 -07:00 @@ -38,7 +38,7 @@ int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, - union oid_res_t *); + union oid_res_t *); int mgt_commit_list(islpci_private *, enum oid_num_t *, int); diff -Nru a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/wireless/prism54/prismcompat.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,46 @@ +/* + * (C) 2004 Margit Schubert-While + * + * 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 + * + * 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 + * + */ + +/* + * Compatibility header file to aid support of different kernel versions + */ + +#ifdef PRISM54_COMPAT24 +#include "prismcompat24.h" +#else /* PRISM54_COMPAT24 */ + +#ifndef _PRISM_COMPAT_H +#define _PRISM_COMPAT_H + +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) +#error Firmware Loading is not configured in the kernel ! +#endif + +#define prism54_synchronize_irq(irq) synchronize_irq(irq) + +#define PRISM_FW_PDEV &priv->pdev->dev + +#endif /* _PRISM_COMPAT_H */ +#endif /* PRISM54_COMPAT24 */ diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c --- a/drivers/net/yellowfin.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/net/yellowfin.c 2004-06-20 13:00:24 -07:00 @@ -448,7 +448,7 @@ np = dev->priv; - if (pci_request_regions(pdev, dev->name)) + if (pci_request_regions(pdev, DRV_NAME)) goto err_out_free_netdev; pci_set_master (pdev); @@ -1201,13 +1201,8 @@ break; skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - rx_skb->tail, pkt_len); -#endif pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, yp->rx_buf_sz, PCI_DMA_FROMDEVICE); diff -Nru a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c --- a/drivers/net/zorro8390.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/net/zorro8390.c 2004-06-20 13:00:25 -07:00 @@ -36,6 +36,8 @@ #include "8390.h" +#define DRV_NAME "zorro8390" + #define NE_BASE (dev->base_addr) #define NE_CMD (0x00*2) #define NE_DATAPORT (0x10*2) /* NatSemi-defined port window offset. */ @@ -115,7 +117,7 @@ if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); - if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) { + if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) { free_netdev(dev); return -EBUSY; } @@ -198,7 +200,7 @@ dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ - i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, dev->name, dev); + i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, DRV_NAME, dev); if (i) return i; for(i = 0; i < ETHER_ADDR_LEN; i++) { diff -Nru a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c --- a/drivers/parisc/ccio-dma.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/parisc/ccio-dma.c 2004-06-20 13:00:23 -07:00 @@ -44,7 +44,6 @@ #include #include /* for L1_CACHE_BYTES */ #include -#include #include #include #include diff -Nru a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c --- a/drivers/parisc/ccio-rm-dma.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/parisc/ccio-rm-dma.c 2004-06-20 13:00:23 -07:00 @@ -40,7 +40,6 @@ #include #include -#include #include #include diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/pcmcia/i82365.c 2004-06-20 13:00:25 -07:00 @@ -1372,8 +1372,15 @@ { int i, ret; - if (driver_register(&i82365_driver)) - return -1; + ret = driver_register(&i82365_driver); + if (ret) + return ret; + + ret = platform_device_register(&i82365_device); + if (ret) { + driver_unregister(&i82365_driver); + return ret; + } printk(KERN_INFO "Intel ISA PCIC probe: "); sockets = 0; @@ -1382,11 +1389,10 @@ if (sockets == 0) { printk("not found.\n"); + platform_device_unregister(&i82365_device); driver_unregister(&i82365_driver); return -ENODEV; } - - platform_device_register(&i82365_device); /* Set up interrupt handler(s) */ if (grab_irq != 0) diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/pnp/isapnp/core.c 2004-06-20 13:00:24 -07:00 @@ -68,13 +68,8 @@ MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode"); MODULE_LICENSE("GPL"); -#ifdef CONFIG_X86_PC9800 -#define _PIDXR 0x259 -#define _PNPWRP 0xa59 -#else #define _PIDXR 0x279 #define _PNPWRP 0xa79 -#endif /* short tags */ #define _STAG_PNPVERNO 0x01 diff -Nru a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/scsi/3w-9xxx.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,2153 @@ +/* + 3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux. + + Written By: Adam Radford + + Copyright (C) 2004 Applied Micro Circuits 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; version 2 of the License. + + 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. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + 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 + + Bugs/Comments/Suggestions should be mailed to: + linuxraid@amcc.com + + For more information, goto: + http://www.amcc.com + + Note: This version of the driver does not contain a bundled firmware + image. + + History + ------- + 2.26.02.000 - Driver cleanup for kernel submission. + 2.26.02.001 - Replace schedule_timeout() calls with msleep(). +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "3w-9xxx.h" + +/* Globals */ +static const char *twa_driver_version="2.26.02.001"; +static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; +static unsigned int twa_device_extension_count; +static int twa_major = -1; +extern struct timezone sys_tz; + +/* Module parameters */ +MODULE_AUTHOR ("AMCC"); +MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver"); +MODULE_LICENSE("GPL"); + +/* Function prototypes */ +static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header); +static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id); +static char *twa_aen_severity_lookup(unsigned char severity_code); +static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id); +static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int twa_chrdev_open(struct inode *inode, struct file *file); +static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host); +static void twa_free_request_id(TW_Device_Extension *tw_dev,int request_id); +static void twa_get_request_id(TW_Device_Extension *tw_dev, int *request_id); +static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, + u32 set_features, unsigned short current_fw_srl, + unsigned short current_fw_arch_id, + unsigned short current_fw_branch, + unsigned short current_fw_build, + unsigned short *fw_on_ctlr_srl, + unsigned short *fw_on_ctlr_arch_id, + unsigned short *fw_on_ctlr_branch, + unsigned short *fw_on_ctlr_build, + u32 *init_connect_result); +static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); +static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); +static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); +static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); +static int twa_reset_device_extension(TW_Device_Extension *tw_dev); +static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); +static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg); +static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); +static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); +static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id); + +/* Functions */ + +/* Show some statistics about the card */ +static ssize_t twa_show_stats(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(class_dev); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + unsigned long flags = 0; + ssize_t len; + + spin_lock_irqsave(tw_dev->host->host_lock, flags); + len = snprintf(buf, PAGE_SIZE, "Driver version: %s\n" + "Current commands posted: %4d\n" + "Max commands posted: %4d\n" + "Current pending commands: %4d\n" + "Max pending commands: %4d\n" + "Last sgl length: %4d\n" + "Max sgl length: %4d\n" + "Last sector count: %4d\n" + "Max sector count: %4d\n" + "SCSI Host Resets: %4d\n" + "SCSI Aborts/Timeouts: %4d\n" + "AEN's: %4d\n", + twa_driver_version, + tw_dev->posted_request_count, + tw_dev->max_posted_request_count, + tw_dev->pending_request_count, + tw_dev->max_pending_request_count, + tw_dev->sgl_entries, + tw_dev->max_sgl_entries, + tw_dev->sector_count, + tw_dev->max_sector_count, + tw_dev->num_resets, + tw_dev->num_aborts, + tw_dev->aen_count); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + return len; +} /* End twa_show_stats() */ + +/* This function will set a devices queue depth */ +static ssize_t twa_store_queue_depth(struct device *dev, const char *buf, size_t count) +{ + int queue_depth; + struct scsi_device *sdev = to_scsi_device(dev); + + queue_depth = simple_strtoul(buf, NULL, 0); + if (queue_depth > TW_Q_LENGTH-2) + return -EINVAL; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + + return count; +} /* End twa_store_queue_depth() */ + +/* Create sysfs 'queue_depth' entry */ +static struct device_attribute twa_queue_depth_attr = { + .attr = { + .name = "queue_depth", + .mode = S_IRUSR | S_IWUSR, + }, + .store = twa_store_queue_depth +}; + +/* Device attributes initializer */ +static struct device_attribute *twa_dev_attrs[] = { + &twa_queue_depth_attr, + NULL, +}; + +/* Create sysfs 'stats' entry */ +static struct class_device_attribute twa_host_stats_attr = { + .attr = { + .name = "stats", + .mode = S_IRUGO, + }, + .show = twa_show_stats +}; + +/* Host attributes initializer */ +static struct class_device_attribute *twa_host_attrs[] = { + &twa_host_stats_attr, + NULL, +}; + +/* File operations struct for character device */ +static struct file_operations twa_fops = { + .owner = THIS_MODULE, + .ioctl = twa_chrdev_ioctl, + .open = twa_chrdev_open, + .release = NULL +}; + +/* This function will complete an aen request from the isr */ +static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id) +{ + TW_Command_Full *full_command_packet; + TW_Command *command_packet; + TW_Command_Apache_Header *header; + unsigned short aen; + int retval = 1; + + header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; + tw_dev->posted_request_count--; + aen = header->status_block.error; + full_command_packet = tw_dev->command_packet_virt[request_id]; + command_packet = &full_command_packet->command.oldcommand; + + /* First check for internal completion of set param for time sync */ + if (TW_OP_OUT(command_packet->opcode__sgloffset) == TW_OP_SET_PARAM) { + /* Keep reading the queue in case there are more aen's */ + if (twa_aen_read_queue(tw_dev, request_id)) + goto out2; + else { + retval = 0; + goto out; + } + } + + switch (aen) { + case TW_AEN_QUEUE_EMPTY: + /* Quit reading the queue if this is the last one */ + break; + case TW_AEN_SYNC_TIME_WITH_HOST: + twa_aen_sync_time(tw_dev, request_id); + retval = 0; + goto out; + default: + twa_aen_queue_event(tw_dev, header); + + /* If there are more aen's, keep reading the queue */ + if (twa_aen_read_queue(tw_dev, request_id)) + goto out2; + else { + retval = 0; + goto out; + } + } + retval = 0; +out2: + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags); +out: + return retval; +} /* End twa_aen_complete() */ + +/* This function will drain aen queue */ +static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) +{ + int request_id = 0; + char cdb[TW_MAX_CDB_LEN]; + TW_SG_Apache sglist[1]; + int finished = 0, count = 0; + TW_Command_Full *full_command_packet; + TW_Command_Apache_Header *header; + unsigned short aen; + int first_reset = 0, queue = 0, retval = 1; + + if (no_check_reset) + first_reset = 0; + else + first_reset = 1; + + full_command_packet = tw_dev->command_packet_virt[request_id]; + memset(full_command_packet, 0, sizeof(TW_Command_Full)); + + /* Initialize cdb */ + memset(&cdb, 0, TW_MAX_CDB_LEN); + cdb[0] = REQUEST_SENSE; /* opcode */ + cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */ + + /* Initialize sglist */ + memset(&sglist, 0, sizeof(TW_SG_Apache)); + sglist[0].length = TW_SECTOR_SIZE; + sglist[0].address = tw_dev->generic_buffer_phys[request_id]; + + if (sglist[0].address & TW_ALIGNMENT_9000_SGL) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Found unaligned address during AEN drain"); + goto out; + } + + /* Mark internal command */ + tw_dev->srb[request_id] = NULL; + + do { + /* Send command to the board */ + if (twa_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2, "Error posting request sense"); + goto out; + } + + /* Now poll for completion */ + if (twa_poll_response(tw_dev, request_id, 30)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x3, "No valid response while draining AEN queue"); + tw_dev->posted_request_count--; + goto out; + } + + tw_dev->posted_request_count--; + header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id]; + aen = header->status_block.error; + queue = 0; + count++; + + switch (aen) { + case TW_AEN_QUEUE_EMPTY: + if (first_reset != 1) + goto out; + else + finished = 1; + break; + case TW_AEN_SOFT_RESET: + if (first_reset == 0) + first_reset = 1; + else + queue = 1; + break; + case TW_AEN_SYNC_TIME_WITH_HOST: + break; + default: + queue = 1; + } + + /* Now queue an event info */ + if (queue) + twa_aen_queue_event(tw_dev, header); + } while ((finished == 0) && (count < TW_MAX_AEN_DRAIN)); + + if (count == TW_MAX_AEN_DRAIN) + goto out; + + retval = 0; +out: + tw_dev->state[request_id] = TW_S_INITIAL; + return retval; +} /* End twa_aen_drain_queue() */ + +/* This function will queue an event */ +static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header) +{ + u32 local_time; + struct timeval time; + TW_Event *event; + unsigned short aen; + char host[16]; + + tw_dev->aen_count++; + + /* Fill out event info */ + event = tw_dev->event_queue[tw_dev->error_index]; + + /* Check for clobber */ + host[0] = '\0'; + if (tw_dev->host) { + sprintf(host, " scsi%d:", tw_dev->host->host_no); + if (event->retrieved == TW_AEN_NOT_RETRIEVED) + tw_dev->aen_clobber = 1; + } + + aen = header->status_block.error; + memset(event, 0, sizeof(TW_Event)); + + event->severity = TW_SEV_OUT(header->status_block.severity__reserved); + do_gettimeofday(&time); + local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60)); + event->time_stamp_sec = local_time; + event->aen_code = aen; + event->retrieved = TW_AEN_NOT_RETRIEVED; + event->sequence_id = tw_dev->error_sequence_id; + tw_dev->error_sequence_id++; + + header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0'; + event->parameter_len = strlen(header->err_specific_desc); + memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len); + if (event->severity != TW_AEN_SEVERITY_DEBUG) + printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n", + host, + twa_aen_severity_lookup(TW_SEV_OUT(header->status_block.severity__reserved)), + TW_MESSAGE_SOURCE_CONTROLLER_EVENT, aen, + twa_string_lookup(twa_aen_table, aen), + header->err_specific_desc); + else + tw_dev->aen_count--; + + if ((tw_dev->error_index + 1) == TW_Q_LENGTH) + tw_dev->event_queue_wrapped = 1; + tw_dev->error_index = (tw_dev->error_index + 1 ) % TW_Q_LENGTH; +} /* End twa_aen_queue_event() */ + +/* This function will read the aen queue from the isr */ +static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) +{ + char cdb[TW_MAX_CDB_LEN]; + TW_SG_Apache sglist[1]; + TW_Command_Full *full_command_packet; + int retval = 1; + + full_command_packet = tw_dev->command_packet_virt[request_id]; + memset(full_command_packet, 0, sizeof(TW_Command_Full)); + + /* Initialize cdb */ + memset(&cdb, 0, TW_MAX_CDB_LEN); + cdb[0] = REQUEST_SENSE; /* opcode */ + cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */ + + /* Initialize sglist */ + memset(&sglist, 0, sizeof(TW_SG_Apache)); + sglist[0].length = TW_SECTOR_SIZE; + sglist[0].address = tw_dev->generic_buffer_phys[request_id]; + + /* Mark internal command */ + tw_dev->srb[request_id] = NULL; + + /* Now post the command packet */ + if (twa_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x4, "Post failed while reading AEN queue"); + goto out; + } + retval = 0; +out: + return retval; +} /* End twa_aen_read_queue() */ + +/* This function will look up an AEN severity string */ +static char *twa_aen_severity_lookup(unsigned char severity_code) +{ + char *retval = NULL; + + if ((severity_code < (unsigned char) TW_AEN_SEVERITY_ERROR) || + (severity_code > (unsigned char) TW_AEN_SEVERITY_DEBUG)) + goto out; + + retval = twa_aen_severity_table[severity_code]; +out: + return retval; +} /* End twa_aen_severity_lookup() */ + +/* This function will sync firmware time with the host time */ +static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id) +{ + u32 schedulertime; + struct timeval utc; + TW_Command_Full *full_command_packet; + TW_Command *command_packet; + TW_Param_Apache *param; + u32 local_time; + + /* Fill out the command packet */ + full_command_packet = tw_dev->command_packet_virt[request_id]; + memset(full_command_packet, 0, sizeof(TW_Command_Full)); + command_packet = &full_command_packet->command.oldcommand; + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM); + command_packet->request_id = request_id; + command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id]; + command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; + command_packet->size = TW_COMMAND_SIZE; + command_packet->byte6_offset.parameter_count = 1; + + /* Setup the param */ + param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; + memset(param, 0, TW_SECTOR_SIZE); + param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */ + param->parameter_id = 0x3; /* SchedulerTime */ + param->parameter_size_bytes = 4; + + /* Convert system time in UTC to local time seconds since last + Sunday 12:00AM */ + do_gettimeofday(&utc); + local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60)); + schedulertime = local_time - (3 * 86400); + schedulertime = schedulertime % 604800; + + memcpy(param->data, &schedulertime, sizeof(u32)); + + /* Mark internal command */ + tw_dev->srb[request_id] = NULL; + + /* Now post the command */ + twa_post_command_packet(tw_dev, request_id, 1); +} /* End twa_aen_sync_time() */ + +/* This function will allocate memory and check if it is correctly aligned */ +static int twa_allocate_memory(TW_Device_Extension *tw_dev, int size, int which) +{ + int i; + dma_addr_t dma_handle; + unsigned long *cpu_addr; + int retval = 1; + + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle); + if (!cpu_addr) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed"); + goto out; + } + + if ((unsigned long)cpu_addr % (TW_ALIGNMENT_9000)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x6, "Failed to allocate correctly aligned memory"); + pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle); + goto out; + } + + memset(cpu_addr, 0, size*TW_Q_LENGTH); + + for (i = 0; i < TW_Q_LENGTH; i++) { + switch(which) { + case 0: + tw_dev->command_packet_phys[i] = dma_handle+(i*size); + tw_dev->command_packet_virt[i] = (TW_Command_Full *)((unsigned char *)cpu_addr + (i*size)); + break; + case 1: + tw_dev->generic_buffer_phys[i] = dma_handle+(i*size); + tw_dev->generic_buffer_virt[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); + break; + } + } + retval = 0; +out: + return retval; +} /* End twa_allocate_memory() */ + +/* This function will check the status register for unexpected bits */ +static int twa_check_bits(u32 status_reg_value) +{ + int retval = 1; + + if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) + goto out; + if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) + goto out; + + retval = 0; +out: + return retval; +} /* End twa_check_bits() */ + +/* This function will check the srl and decide if we are compatible */ +static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed) +{ + int retval = 1; + unsigned short fw_on_ctlr_srl = 0, fw_on_ctlr_arch_id = 0; + unsigned short fw_on_ctlr_branch = 0, fw_on_ctlr_build = 0; + u32 init_connect_result = 0; + + if (twa_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS, + TW_EXTENDED_INIT_CONNECT, TW_CURRENT_FW_SRL, + TW_9000_ARCH_ID, TW_CURRENT_FW_BRANCH, + TW_CURRENT_FW_BUILD, &fw_on_ctlr_srl, + &fw_on_ctlr_arch_id, &fw_on_ctlr_branch, + &fw_on_ctlr_build, &init_connect_result)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x7, "Initconnection failed while checking SRL"); + goto out; + } + + tw_dev->working_srl = TW_CURRENT_FW_SRL; + tw_dev->working_branch = TW_CURRENT_FW_BRANCH; + tw_dev->working_build = TW_CURRENT_FW_BUILD; + + /* Try base mode compatibility */ + if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) { + if (twa_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS, + TW_EXTENDED_INIT_CONNECT, + TW_BASE_FW_SRL, TW_9000_ARCH_ID, + TW_BASE_FW_BRANCH, TW_BASE_FW_BUILD, + &fw_on_ctlr_srl, &fw_on_ctlr_arch_id, + &fw_on_ctlr_branch, &fw_on_ctlr_build, + &init_connect_result)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xa, "Initconnection (base mode) failed while checking SRL"); + goto out; + } + if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) { + if (TW_CURRENT_FW_SRL > fw_on_ctlr_srl) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x32, "Firmware and driver incompatibility: please upgrade firmware"); + } else { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x33, "Firmware and driver incompatibility: please upgrade driver"); + } + goto out; + } + tw_dev->working_srl = TW_BASE_FW_SRL; + tw_dev->working_branch = TW_BASE_FW_BRANCH; + tw_dev->working_build = TW_BASE_FW_BUILD; + } + retval = 0; +out: + return retval; +} /* End twa_check_srl() */ + +/* This function handles ioctl for the character device */ +static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + long timeout; + unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0; + dma_addr_t dma_handle; + int request_id = 0; + unsigned int sequence_id = 0; + unsigned char event_index, start_index; + TW_Ioctl_Driver_Command driver_command; + TW_Ioctl_Buf_Apache *tw_ioctl; + TW_Lock *tw_lock; + TW_Command_Full *full_command_packet; + TW_Compatibility_Info *tw_compat_info; + TW_Event *event; + struct timeval current_time; + u32 current_time_ms; + TW_Device_Extension *tw_dev = twa_device_extension_list[iminor(inode)]; + int retval = TW_IOCTL_ERROR_OS_EFAULT; + + /* Only let one of these through at a time */ + if (down_interruptible(&tw_dev->ioctl_sem)) { + retval = TW_IOCTL_ERROR_OS_EINTR; + goto out; + } + + /* First copy down the driver command */ + if (copy_from_user(&driver_command, (void *)arg, sizeof(TW_Ioctl_Driver_Command))) + goto out2; + + /* Check data buffer size */ + if (driver_command.buffer_length > TW_MAX_SECTORS * 512) { + retval = TW_IOCTL_ERROR_OS_EINVAL; + goto out2; + } + + /* Hardware can only do multiple of 512 byte transfers */ + data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511; + + /* Now allocate ioctl buf memory */ + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle); + if (!cpu_addr) { + retval = TW_IOCTL_ERROR_OS_ENOMEM; + goto out2; + } + + tw_ioctl = (TW_Ioctl_Buf_Apache *)cpu_addr; + + /* Now copy down the entire ioctl */ + if (copy_from_user(tw_ioctl, (void *)arg, driver_command.buffer_length + sizeof(TW_Ioctl_Buf_Apache) - 1)) + goto out3; + + /* See which ioctl we are doing */ + switch (cmd) { + case TW_IOCTL_FIRMWARE_PASS_THROUGH: + spin_lock_irqsave(tw_dev->host->host_lock, flags); + twa_get_request_id(tw_dev, &request_id); + + /* Flag internal command */ + tw_dev->srb[request_id] = 0; + + /* Flag chrdev ioctl */ + tw_dev->chrdev_request_id = request_id; + + full_command_packet = &tw_ioctl->firmware_command; + + /* Load request id and sglist for both command types */ + twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); + + memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); + + /* Now post the command packet to the controller */ + twa_post_command_packet(tw_dev, request_id, 1); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + + timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ; + + /* Now wait for command to complete */ + timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); + + /* Check if we timed out, got a signal, or didn't get + an interrupt */ + if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) { + /* Now we need to reset the board */ + if (timeout == TW_IOCTL_ERROR_OS_ERESTARTSYS) { + retval = timeout; + } else { + printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", + tw_dev->host->host_no, TW_DRIVER, 0xc, + cmd); + retval = TW_IOCTL_ERROR_OS_EIO; + } + spin_lock_irqsave(tw_dev->host->host_lock, flags); + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; + twa_reset_device_extension(tw_dev); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + goto out3; + } + + /* Now copy in the command packet response */ + memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virt[request_id], sizeof(TW_Command_Full)); + + /* Now complete the io */ + spin_lock_irqsave(tw_dev->host->host_lock, flags); + tw_dev->posted_request_count--; + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + break; + case TW_IOCTL_GET_COMPATIBILITY_INFO: + tw_ioctl->driver_command.status = 0; + /* Copy compatiblity struct into ioctl data buffer */ + tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer; + strncpy(tw_compat_info->driver_version, twa_driver_version, strlen(twa_driver_version)); + tw_compat_info->working_srl = tw_dev->working_srl; + tw_compat_info->working_branch = tw_dev->working_branch; + tw_compat_info->working_build = tw_dev->working_build; + break; + case TW_IOCTL_GET_LAST_EVENT: + if (tw_dev->event_queue_wrapped) { + if (tw_dev->aen_clobber) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER; + tw_dev->aen_clobber = 0; + } else + tw_ioctl->driver_command.status = 0; + } else { + if (!tw_dev->error_index) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS; + break; + } + tw_ioctl->driver_command.status = 0; + } + event_index = (tw_dev->error_index - 1 + TW_Q_LENGTH) % TW_Q_LENGTH; + memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event)); + tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED; + break; + case TW_IOCTL_GET_FIRST_EVENT: + if (tw_dev->event_queue_wrapped) { + if (tw_dev->aen_clobber) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER; + tw_dev->aen_clobber = 0; + } else + tw_ioctl->driver_command.status = 0; + event_index = tw_dev->error_index; + } else { + if (!tw_dev->error_index) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS; + break; + } + tw_ioctl->driver_command.status = 0; + event_index = 0; + } + memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event)); + tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED; + break; + case TW_IOCTL_GET_NEXT_EVENT: + event = (TW_Event *)tw_ioctl->data_buffer; + sequence_id = event->sequence_id; + tw_ioctl->driver_command.status = 0; + + if (tw_dev->event_queue_wrapped) { + if (tw_dev->aen_clobber) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER; + tw_dev->aen_clobber = 0; + } + start_index = tw_dev->error_index; + } else { + if (!tw_dev->error_index) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS; + break; + } + start_index = 0; + } + event_index = (start_index + sequence_id - tw_dev->event_queue[start_index]->sequence_id + 1) % TW_Q_LENGTH; + + if (!(tw_dev->event_queue[event_index]->sequence_id > sequence_id)) { + if (tw_ioctl->driver_command.status == TW_IOCTL_ERROR_STATUS_AEN_CLOBBER) + tw_dev->aen_clobber = 1; + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS; + break; + } + memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event)); + tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED; + break; + case TW_IOCTL_GET_PREVIOUS_EVENT: + event = (TW_Event *)tw_ioctl->data_buffer; + sequence_id = event->sequence_id; + tw_ioctl->driver_command.status = 0; + + if (tw_dev->event_queue_wrapped) { + if (tw_dev->aen_clobber) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_AEN_CLOBBER; + tw_dev->aen_clobber = 0; + } + start_index = tw_dev->error_index; + } else { + if (!tw_dev->error_index) { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS; + break; + } + start_index = 0; + } + event_index = (start_index + sequence_id - tw_dev->event_queue[start_index]->sequence_id - 1) % TW_Q_LENGTH; + + if (!(tw_dev->event_queue[event_index]->sequence_id < sequence_id)) { + if (tw_ioctl->driver_command.status == TW_IOCTL_ERROR_STATUS_AEN_CLOBBER) + tw_dev->aen_clobber = 1; + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS; + break; + } + memcpy(tw_ioctl->data_buffer, tw_dev->event_queue[event_index], sizeof(TW_Event)); + tw_dev->event_queue[event_index]->retrieved = TW_AEN_RETRIEVED; + break; + case TW_IOCTL_GET_LOCK: + tw_lock = (TW_Lock *)tw_ioctl->data_buffer; + do_gettimeofday(¤t_time); + current_time_ms = (current_time.tv_sec * 1000) + (current_time.tv_usec / 1000); + + if ((tw_lock->force_flag == 1) || (tw_dev->ioctl_sem_lock == 0) || (current_time_ms >= tw_dev->ioctl_msec)) { + tw_dev->ioctl_sem_lock = 1; + tw_dev->ioctl_msec = current_time_ms + tw_lock->timeout_msec; + tw_ioctl->driver_command.status = 0; + tw_lock->time_remaining_msec = tw_lock->timeout_msec; + } else { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_LOCKED; + tw_lock->time_remaining_msec = tw_dev->ioctl_msec - current_time_ms; + } + break; + case TW_IOCTL_RELEASE_LOCK: + if (tw_dev->ioctl_sem_lock == 1) { + tw_dev->ioctl_sem_lock = 0; + tw_ioctl->driver_command.status = 0; + } else { + tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_NOT_LOCKED; + } + break; + default: + retval = TW_IOCTL_ERROR_OS_ENOTTY; + goto out3; + } + + /* Now copy the entire response to userspace */ + if (copy_to_user((void *)arg, tw_ioctl, sizeof(TW_Ioctl_Buf_Apache) + driver_command.buffer_length - 1) == 0) + retval = 0; +out3: + /* Now free ioctl buf memory */ + pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle); +out2: + up(&tw_dev->ioctl_sem); +out: + return retval; +} /* End twa_chrdev_ioctl() */ + +/* This function handles open for the character device */ +static int twa_chrdev_open(struct inode *inode, struct file *file) +{ + unsigned int minor_number; + int retval = TW_IOCTL_ERROR_OS_ENODEV; + + minor_number = iminor(inode); + if (minor_number >= twa_device_extension_count) + goto out; + retval = 0; +out: + return retval; +} /* End twa_chrdev_open() */ + +/* This function will print readable messages from status register errors */ +static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) +{ + int retval = 1; + + /* Check for various error conditions and handle them appropriately */ + if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xc, "PCI Parity Error: clearing"); + writel(TW_CONTROL_CLEAR_PARITY_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); + } + + if (status_reg_value & TW_STATUS_PCI_ABORT) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xd, "PCI Abort: clearing"); + writel(TW_CONTROL_CLEAR_PCI_ABORT, TW_CONTROL_REG_ADDR(tw_dev)); + pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT); + } + + if (status_reg_value & TW_STATUS_QUEUE_ERROR) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); + writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); + } + + if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "SBUF Write Error: clearing"); + writel(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); + } + + if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { + if (tw_dev->reset_print == 0) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing"); + tw_dev->reset_print = 1; + } + goto out; + } + retval = 0; +out: + return retval; +} /* End twa_decode_bits() */ + +/* This function will empty the response queue */ +static int twa_empty_response_queue(TW_Device_Extension *tw_dev) +{ + u32 status_reg_value, response_que_value; + int count = 0, retval = 1; + + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + + while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) { + response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + count++; + } + if (count == TW_MAX_RESPONSE_DRAIN) + goto out; + + retval = 0; +out: + return retval; +} /* End twa_empty_response_queue() */ + +/* This function passes sense keys from firmware to scsi layer */ +static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host) +{ + TW_Command_Full *full_command_packet; + unsigned short error; + int retval = 1; + + full_command_packet = tw_dev->command_packet_virt[request_id]; + /* Don't print error for Logical unit not supported during rollcall */ + error = full_command_packet->header.status_block.error; + if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) { + if (print_host) + printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n", + tw_dev->host->host_no, + TW_MESSAGE_SOURCE_CONTROLLER_ERROR, + full_command_packet->header.status_block.error, + twa_string_lookup(twa_error_table, + full_command_packet->header.status_block.error), + full_command_packet->header.err_specific_desc); + else + printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s:%s.\n", + TW_MESSAGE_SOURCE_CONTROLLER_ERROR, + full_command_packet->header.status_block.error, + twa_string_lookup(twa_error_table, + full_command_packet->header.status_block.error), + full_command_packet->header.err_specific_desc); + } + + if (copy_sense) { + memcpy(tw_dev->srb[request_id]->sense_buffer, full_command_packet->header.sense_data, TW_SENSE_DATA_LENGTH); + tw_dev->srb[request_id]->result = (full_command_packet->command.newcommand.status << 1); + retval = TW_ISR_DONT_RESULT; + goto out; + } + retval = 0; +out: + return retval; +} /* End twa_fill_sense() */ + +/* This function will free up device extension resources */ +static void twa_free_device_extension(TW_Device_Extension *tw_dev) +{ + if (tw_dev->command_packet_virt[0]) + pci_free_consistent(tw_dev->tw_pci_dev, + sizeof(TW_Command_Full)*TW_Q_LENGTH, + tw_dev->command_packet_virt[0], + tw_dev->command_packet_phys[0]); + + if (tw_dev->generic_buffer_virt[0]) + pci_free_consistent(tw_dev->tw_pci_dev, + TW_SECTOR_SIZE*TW_Q_LENGTH, + tw_dev->generic_buffer_virt[0], + tw_dev->generic_buffer_phys[0]); + + if (tw_dev->event_queue[0]) + kfree(tw_dev->event_queue[0]); +} /* End twa_free_device_extension() */ + +/* This function will free a request id */ +static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id) +{ + tw_dev->free_queue[tw_dev->free_tail] = request_id; + tw_dev->state[request_id] = TW_S_FINISHED; + tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH; +} /* End twa_free_request_id() */ + +/* This function will get parameter table entires from the firmware */ +static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes) +{ + TW_Command_Full *full_command_packet; + TW_Command *command_packet; + TW_Param_Apache *param; + unsigned long param_value; + void *retval = NULL; + + /* Setup the command packet */ + full_command_packet = tw_dev->command_packet_virt[request_id]; + memset(full_command_packet, 0, sizeof(TW_Command_Full)); + command_packet = &full_command_packet->command.oldcommand; + + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); + command_packet->size = TW_COMMAND_SIZE; + command_packet->request_id = request_id; + command_packet->byte6_offset.block_count = 1; + + /* Now setup the param */ + param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id]; + memset(param, 0, TW_SECTOR_SIZE); + param->table_id = table_id | 0x8000; + param->parameter_id = parameter_id; + param->parameter_size_bytes = parameter_size_bytes; + param_value = tw_dev->generic_buffer_phys[request_id]; + + command_packet->byte8_offset.param.sgl[0].address = param_value; + command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE; + + /* Post the command packet to the board */ + twa_post_command_packet(tw_dev, request_id, 1); + + /* Poll for completion */ + if (twa_poll_response(tw_dev, request_id, 30)) + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x13, "No valid response during get param") + else + retval = (void *)&(param->data[0]); + + tw_dev->posted_request_count--; + tw_dev->state[request_id] = TW_S_INITIAL; + + return retval; +} /* End twa_get_param() */ + +/* This function will assign an available request id */ +static void twa_get_request_id(TW_Device_Extension *tw_dev, int *request_id) +{ + *request_id = tw_dev->free_queue[tw_dev->free_head]; + tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH; + tw_dev->state[*request_id] = TW_S_STARTED; +} /* End twa_get_request_id() */ + +/* This function will send an initconnection command to controller */ +static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, + u32 set_features, unsigned short current_fw_srl, + unsigned short current_fw_arch_id, + unsigned short current_fw_branch, + unsigned short current_fw_build, + unsigned short *fw_on_ctlr_srl, + unsigned short *fw_on_ctlr_arch_id, + unsigned short *fw_on_ctlr_branch, + unsigned short *fw_on_ctlr_build, + u32 *init_connect_result) +{ + TW_Command_Full *full_command_packet; + TW_Initconnect *tw_initconnect; + int request_id = 0, retval = 1; + + /* Initialize InitConnection command packet */ + full_command_packet = tw_dev->command_packet_virt[request_id]; + memset(full_command_packet, 0, sizeof(TW_Command_Full)); + full_command_packet->header.header_desc.size_header = 128; + + tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand; + tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION); + tw_initconnect->request_id = request_id; + tw_initconnect->message_credits = message_credits; + tw_initconnect->features = set_features; +#if BITS_PER_LONG > 32 + /* Turn on 64-bit sgl support */ + tw_initconnect->features |= 1; +#endif + + if (set_features & TW_EXTENDED_INIT_CONNECT) { + tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED; + tw_initconnect->fw_srl = current_fw_srl; + tw_initconnect->fw_arch_id = current_fw_arch_id; + tw_initconnect->fw_branch = current_fw_branch; + tw_initconnect->fw_build = current_fw_build; + } else + tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE; + + /* Send command packet to the board */ + twa_post_command_packet(tw_dev, request_id, 1); + + /* Poll for completion */ + if (twa_poll_response(tw_dev, request_id, 30)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection"); + } else { + if (set_features & TW_EXTENDED_INIT_CONNECT) { + *fw_on_ctlr_srl = tw_initconnect->fw_srl; + *fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id; + *fw_on_ctlr_branch = tw_initconnect->fw_branch; + *fw_on_ctlr_build = tw_initconnect->fw_build; + *init_connect_result = tw_initconnect->result; + } + retval = 0; + } + + tw_dev->posted_request_count--; + tw_dev->state[request_id] = TW_S_INITIAL; + + return retval; +} /* End twa_initconnection() */ + +/* This function will initialize the fields of a device extension */ +static int twa_initialize_device_extension(TW_Device_Extension *tw_dev) +{ + int i, retval = 1; + + /* Initialize command packet buffers */ + if (twa_allocate_memory(tw_dev, sizeof(TW_Command_Full), 0)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x16, "Command packet memory allocation failed"); + goto out; + } + + /* Initialize generic buffer */ + if (twa_allocate_memory(tw_dev, TW_SECTOR_SIZE, 1)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x17, "Generic memory allocation failed"); + goto out; + } + + /* Allocate event info space */ + tw_dev->event_queue[0] = kmalloc(sizeof(TW_Event) * TW_Q_LENGTH, GFP_KERNEL); + if (!tw_dev->event_queue[0]) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x18, "Event info memory allocation failed"); + goto out; + } + + memset(tw_dev->event_queue[0], 0, sizeof(TW_Event) * TW_Q_LENGTH); + + for (i = 0; i < TW_Q_LENGTH; i++) { + tw_dev->event_queue[i] = (TW_Event *)((unsigned char *)tw_dev->event_queue[0] + (i * sizeof(TW_Event))); + tw_dev->free_queue[i] = i; + tw_dev->state[i] = TW_S_INITIAL; + } + + tw_dev->pending_head = TW_Q_START; + tw_dev->pending_tail = TW_Q_START; + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->error_sequence_id = 1; + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + + init_MUTEX(&tw_dev->ioctl_sem); + init_waitqueue_head(&tw_dev->ioctl_wqueue); + + retval = 0; +out: + return retval; +} /* End twa_initialize_device_extension() */ + +/* This function is the interrupt service routine */ +static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + int request_id, error = 0; + u32 status_reg_value; + TW_Response_Queue response_que; + TW_Command_Full *full_command_packet; + TW_Command *command_packet; + TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; + int handled = 0; + + /* Get the per adapter lock */ + spin_lock(tw_dev->host->host_lock); + + /* See if the interrupt matches this instance */ + if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) { + + handled = 1; + + /* Read the registers */ + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + + /* Check if this is our interrupt, otherwise bail */ + if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT)) + goto twa_interrupt_bail; + + /* Check controller for errors */ + if (twa_check_bits(status_reg_value)) { + if (twa_decode_bits(tw_dev, status_reg_value)) { + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + goto twa_interrupt_bail; + } + } + + /* Handle host interrupt */ + if (status_reg_value & TW_STATUS_HOST_INTERRUPT) + TW_CLEAR_HOST_INTERRUPT(tw_dev); + + /* Handle attention interrupt */ + if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) { + TW_CLEAR_ATTENTION_INTERRUPT(tw_dev); + if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) { + twa_get_request_id(tw_dev, &request_id); + + error = twa_aen_read_queue(tw_dev, request_id); + if (error) { + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags); + } + } + } + + /* Handle command interrupt */ + if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) { + TW_MASK_COMMAND_INTERRUPT(tw_dev); + /* Drain as many pending commands as we can */ + while (tw_dev->pending_request_count > 0) { + request_id = tw_dev->pending_queue[tw_dev->pending_head]; + if (tw_dev->state[request_id] != TW_S_PENDING) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x19, "Found request id that wasn't pending"); + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + goto twa_interrupt_bail; + } + if (twa_post_command_packet(tw_dev, request_id, 1)==0) { + tw_dev->pending_head = (tw_dev->pending_head + 1) % TW_Q_LENGTH; + tw_dev->pending_request_count--; + } else { + /* If we get here, we will continue re-posting on the next command interrupt */ + break; + } + } + } + + /* Handle response interrupt */ + if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) { + + /* Drain the response queue from the board */ + while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { + /* Complete the response */ + response_que.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + request_id = TW_RESID_OUT(response_que.response_id); + full_command_packet = tw_dev->command_packet_virt[request_id]; + error = 0; + command_packet = &full_command_packet->command.oldcommand; + /* Check for command packet errors */ + if (full_command_packet->command.newcommand.status != 0) { + if (tw_dev->srb[request_id] != 0) { + error = twa_fill_sense(tw_dev, request_id, 1, 1); + } else { + /* Skip ioctl error prints */ + if (request_id != tw_dev->chrdev_request_id) { + error = twa_fill_sense(tw_dev, request_id, 0, 1); + } + } + } + + /* Check for correct state */ + if (tw_dev->state[request_id] != TW_S_POSTED) { + if (tw_dev->srb[request_id] != 0) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted"); + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + goto twa_interrupt_bail; + } + } + + /* Check for internal command completion */ + if (tw_dev->srb[request_id] == 0) { + if (request_id != tw_dev->chrdev_request_id) { + if (twa_aen_complete(tw_dev, request_id)) + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt"); + } else { + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + wake_up(&tw_dev->ioctl_wqueue); + } + } else { + twa_scsiop_execute_scsi_complete(tw_dev, request_id); + /* If no error command was a success */ + if (error == 0) { + tw_dev->srb[request_id]->result = (DID_OK << 16); + } + + /* If error, command failed */ + if (error == 1) { + /* Ask for a host reset */ + tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + } + + /* Now complete the io */ + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; + tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + twa_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for valid status after each drain */ + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + if (twa_check_bits(status_reg_value)) { + if (twa_decode_bits(tw_dev, status_reg_value)) { + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + goto twa_interrupt_bail; + } + } + } + } + } +twa_interrupt_bail: + spin_unlock(tw_dev->host->host_lock); + return IRQ_RETVAL(handled); +} /* End twa_interrupt() */ + +/* This function will load the request id and various sgls for ioctls */ +static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) +{ + TW_Command *oldcommand; + TW_Command_Apache *newcommand; + TW_SG_Entry *sgl; + + if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { + newcommand = &full_command_packet->command.newcommand; + newcommand->request_id = request_id; + newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; + newcommand->sg_list[0].length = length; + } else { + oldcommand = &full_command_packet->command.oldcommand; + oldcommand->request_id = request_id; + + if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { + /* Load the sg list */ + sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); + sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1; + sgl->length = length; + } + } +} /* End twa_load_sgl() */ + +/* This function will perform a pci-dma mapping for a scatter gather list */ +static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +{ + int use_sg; + struct scsi_cmnd *cmd = tw_dev->srb[request_id]; + struct pci_dev *pdev = tw_dev->tw_pci_dev; + int retval = 0; + + if (cmd->use_sg == 0) + goto out; + + use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + + if (use_sg == 0) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); + goto out; + } + + cmd->SCp.phase = TW_PHASE_SGLIST; + cmd->SCp.have_data_in = use_sg; + retval = use_sg; +out: + return retval; +} /* End twa_map_scsi_sg_data() */ + +/* This function will perform a pci-dma map for a single buffer */ +static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id) +{ + dma_addr_t mapping; + struct scsi_cmnd *cmd = tw_dev->srb[request_id]; + struct pci_dev *pdev = tw_dev->tw_pci_dev; + int retval = 0; + + if (cmd->request_bufflen == 0) { + retval = 0; + goto out; + } + + mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL); + + if (mapping == 0) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page"); + goto out; + } + + cmd->SCp.phase = TW_PHASE_SINGLE; + cmd->SCp.have_data_in = mapping; + retval = mapping; +out: + return retval; +} /* End twa_map_scsi_single_data() */ + +/* This function will poll for a response interrupt of a request */ +static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) +{ + int retval = 1, found = 0, response_request_id; + TW_Response_Queue response_queue; + TW_Command_Full *full_command_packet = tw_dev->command_packet_virt[request_id]; + + if (twa_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, seconds) == 0) { + response_queue.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + response_request_id = TW_RESID_OUT(response_queue.response_id); + if (request_id != response_request_id) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1e, "Found unexpected request id while polling for response"); + goto out; + } + if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { + if (full_command_packet->command.newcommand.status != 0) { + /* bad response */ + twa_fill_sense(tw_dev, request_id, 0, 0); + goto out; + } + found = 1; + } else { + if (full_command_packet->command.oldcommand.status != 0) { + /* bad response */ + twa_fill_sense(tw_dev, request_id, 0, 0); + goto out; + } + found = 1; + } + } + + if (found) + retval = 0; +out: + return retval; +} /* End twa_poll_response() */ + +/* This function will poll the status register for a flag */ +static int twa_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds) +{ + u32 status_reg_value; + unsigned long before; + int retval = 1; + + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + before = jiffies; + + if (twa_check_bits(status_reg_value)) + twa_decode_bits(tw_dev, status_reg_value); + + while ((status_reg_value & flag) != flag) { + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + + if (twa_check_bits(status_reg_value)) + twa_decode_bits(tw_dev, status_reg_value); + + if (time_after(jiffies, before + HZ * seconds)) + goto out; + + msleep(50); + } + retval = 0; +out: + return retval; +} /* End twa_poll_status() */ + +/* This function will poll the status register for disappearance of a flag */ +static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds) +{ + u32 status_reg_value; + unsigned long before; + int retval = 1; + + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + before = jiffies; + + if (twa_check_bits(status_reg_value)) + twa_decode_bits(tw_dev, status_reg_value); + + while ((status_reg_value & flag) != 0) { + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + if (twa_check_bits(status_reg_value)) + twa_decode_bits(tw_dev, status_reg_value); + + if (time_after(jiffies, before + HZ * seconds)) + goto out; + + msleep(50); + } + retval = 0; +out: + return retval; +} /* End twa_poll_status_gone() */ + +/* This function will attempt to post a command packet to the board */ +static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal) +{ + u32 status_reg_value; + unsigned long command_que_value; + int retval = 1; + + command_que_value = tw_dev->command_packet_phys[request_id]; + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + + if (twa_check_bits(status_reg_value)) + twa_decode_bits(tw_dev, status_reg_value); + + if (((tw_dev->pending_request_count > 0) && (tw_dev->state[request_id] != TW_S_PENDING)) || (status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL)) { + + /* Only pend internal driver commands */ + if (!internal) { + retval = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + + /* Couldn't post the command packet, so we do it later */ + if (tw_dev->state[request_id] != TW_S_PENDING) { + tw_dev->state[request_id] = TW_S_PENDING; + tw_dev->pending_request_count++; + if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) { + tw_dev->max_pending_request_count = tw_dev->pending_request_count; + } + tw_dev->pending_queue[tw_dev->pending_tail] = request_id; + tw_dev->pending_tail = (tw_dev->pending_tail + 1) % TW_Q_LENGTH; + } + TW_UNMASK_COMMAND_INTERRUPT(tw_dev); + goto out; + } else { + /* We successfully posted the command packet */ +#if BITS_PER_LONG > 32 + writeq(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); +#else + writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); +#endif + tw_dev->state[request_id] = TW_S_POSTED; + tw_dev->posted_request_count++; + if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) { + tw_dev->max_posted_request_count = tw_dev->posted_request_count; + } + } + retval = 0; +out: + return retval; +} /* End twa_post_command_packet() */ + +/* This function will reset a device extension */ +static int twa_reset_device_extension(TW_Device_Extension *tw_dev) +{ + int i = 0; + int retval = 1; + + /* Abort all requests that are in progress */ + for (i = 0; i < TW_Q_LENGTH; i++) { + if ((tw_dev->state[i] != TW_S_FINISHED) && + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { + if (tw_dev->srb[i]) { + tw_dev->srb[i]->result = (DID_RESET << 16); + tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); + twa_unmap_scsi_data(tw_dev, i); + } + } + } + + /* Reset queues and counts */ + for (i = 0; i < TW_Q_LENGTH; i++) { + tw_dev->free_queue[i] = i; + tw_dev->state[i] = TW_S_INITIAL; + } + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->posted_request_count = 0; + tw_dev->pending_request_count = 0; + tw_dev->pending_head = TW_Q_START; + tw_dev->pending_tail = TW_Q_START; + tw_dev->reset_print = 0; + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + tw_dev->flags = 0; + + TW_DISABLE_INTERRUPTS(tw_dev); + + if (twa_reset_sequence(tw_dev, 1)) + goto out; + + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); + + retval = 0; +out: + return retval; +} /* End twa_reset_device_extension() */ + +/* This function will reset a controller */ +static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset) +{ + int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset; + + while (tries < TW_MAX_RESET_TRIES) { + if (do_soft_reset) + TW_SOFT_RESET(tw_dev); + + /* Make sure controller is in a good state */ + if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 30)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1f, "Microcontroller not ready during reset sequence"); + do_soft_reset = 1; + tries++; + continue; + } + + /* Empty response queue */ + if (twa_empty_response_queue(tw_dev)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x20, "Response queue empty failed during reset sequence"); + do_soft_reset = 1; + tries++; + continue; + } + + flashed = 0; + + /* Check for compatibility/flash */ + if (twa_check_srl(tw_dev, &flashed)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x21, "Compatibility check failed during reset sequence"); + do_soft_reset = 1; + tries++; + continue; + } else { + if (flashed) { + tries++; + continue; + } + } + + /* Drain the AEN queue */ + if (twa_aen_drain_queue(tw_dev, soft_reset)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x22, "AEN drain failed during reset sequence"); + do_soft_reset = 1; + tries++; + continue; + } + + /* If we got here, controller is in a good state */ + retval = 0; + goto out; + } +out: + return retval; +} /* End twa_reset_sequence() */ + +/* This funciton returns unit geometry in cylinders/heads/sectors */ +static int twa_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) +{ + int heads, sectors, cylinders; + TW_Device_Extension *tw_dev; + + tw_dev = (TW_Device_Extension *)sdev->host->hostdata; + + if (capacity >= 0x200000) { + heads = 255; + sectors = 63; + cylinders = sector_div(capacity, heads * sectors); + } else { + heads = 64; + sectors = 32; + cylinders = sector_div(capacity, heads * sectors); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return 0; +} /* End twa_scsi_biosparam() */ + +/* This is the new scsi eh abort function */ +static int twa_scsi_eh_abort(struct scsi_cmnd *SCpnt) +{ + int i; + TW_Device_Extension *tw_dev = NULL; + int retval = FAILED; + + tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; + + spin_unlock_irq(tw_dev->host->host_lock); + + tw_dev->num_aborts++; + + /* If we find any IO's in process, we have to reset the card */ + for (i = 0; i < TW_Q_LENGTH; i++) { + if ((tw_dev->state[i] != TW_S_FINISHED) && (tw_dev->state[i] != TW_S_INITIAL)) { + printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", + tw_dev->host->host_no, TW_DRIVER, 0x2c, + SCpnt->device->id, SCpnt->cmnd[0]); + if (twa_reset_device_extension(tw_dev)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2a, "Controller reset failed during scsi abort"); + goto out; + } + break; + } + } + retval = SUCCESS; +out: + spin_lock_irq(tw_dev->host->host_lock); + return retval; +} /* End twa_scsi_eh_abort() */ + +/* This is the new scsi eh reset function */ +static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) +{ + TW_Device_Extension *tw_dev = NULL; + int retval = FAILED; + + tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; + + spin_unlock_irq(tw_dev->host->host_lock); + + tw_dev->num_resets++; + + printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset started.\n", tw_dev->host->host_no); + + /* Now reset the card and some of the device extension data */ + if (twa_reset_device_extension(tw_dev)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); + goto out; + } + printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset succeeded.\n", tw_dev->host->host_no); + retval = SUCCESS; +out: + spin_lock_irq(tw_dev->host->host_lock); + return retval; +} /* End twa_scsi_eh_reset() */ + +/* This is the main scsi queue function to handle scsi opcodes */ +static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +{ + int request_id, retval; + TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; + + /* Save done function into scsi_cmnd struct */ + SCpnt->scsi_done = done; + + /* Get a free request id */ + twa_get_request_id(tw_dev, &request_id); + + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + + /* Initialize phase to zero */ + SCpnt->SCp.phase = TW_PHASE_INITIAL; + + retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + switch (retval) { + case SCSI_MLQUEUE_HOST_BUSY: + twa_free_request_id(tw_dev, request_id); + break; + case 1: + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + SCpnt->result = (DID_ERROR << 16); + done(SCpnt); + } + + return retval; +} /* End twa_scsi_queue() */ + +/* This function hands scsi cdb's to the firmware */ +static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg) +{ + TW_Command_Full *full_command_packet; + TW_Command_Apache *command_packet; + u32 num_sectors = 0x0; + int i, sg_count; + struct scsi_cmnd *srb = NULL; + struct scatterlist *sglist = NULL; + u32 buffaddr = 0x0; + int retval = 1; + + if (tw_dev->srb[request_id]) { + if (tw_dev->srb[request_id]->request_buffer) { + sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; + } + srb = tw_dev->srb[request_id]; + } + + /* Initialize command packet */ + full_command_packet = tw_dev->command_packet_virt[request_id]; + full_command_packet->header.header_desc.size_header = 128; + full_command_packet->header.status_block.error = 0; + full_command_packet->header.status_block.severity__reserved = 0; + + command_packet = &full_command_packet->command.newcommand; + command_packet->status = 0; + command_packet->opcode__reserved = TW_OPRES_IN(0, TW_OP_EXECUTE_SCSI); + + /* We forced 16 byte cdb use earlier */ + if (!cdb) + memcpy(command_packet->cdb, srb->cmnd, TW_MAX_CDB_LEN); + else + memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN); + + if (srb) + command_packet->unit = srb->device->id; + else + command_packet->unit = 0; + + command_packet->request_id = request_id; + command_packet->sgl_offset = 16; + + if (!sglistarg) { + /* Map sglist from scsi layer to cmd packet */ + if (tw_dev->srb[request_id]->use_sg == 0) { + if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { + command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; + command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; + } else { + buffaddr = twa_map_scsi_single_data(tw_dev, request_id); + if (buffaddr == 0) + goto out; + + command_packet->sg_list[0].address = buffaddr; + command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen; + } + command_packet->sgl_entries = 1; + + if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi"); + goto out; + } + } + + if (tw_dev->srb[request_id]->use_sg > 0) { + sg_count = twa_map_scsi_sg_data(tw_dev, request_id); + if (sg_count == 0) + goto out; + + for (i = 0; i < sg_count; i++) { + command_packet->sg_list[i].address = sg_dma_address(&sglist[i]); + command_packet->sg_list[i].length = sg_dma_len(&sglist[i]); + if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); + goto out; + } + } + command_packet->sgl_entries = tw_dev->srb[request_id]->use_sg; + } + } else { + /* Internal cdb post */ + for (i = 0; i < use_sg; i++) { + command_packet->sg_list[i].address = sglistarg[i].address; + command_packet->sg_list[i].length = sglistarg[i].length; + if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post"); + goto out; + } + } + command_packet->sgl_entries = use_sg; + } + + if (srb) { + if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) + num_sectors = (u32)srb->cmnd[4]; + + if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) + num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8); + } + + /* Update sector statistic */ + tw_dev->sector_count = num_sectors; + if (tw_dev->sector_count > tw_dev->max_sector_count) + tw_dev->max_sector_count = tw_dev->sector_count; + + /* Update SG statistics */ + if (srb) { + tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; + if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) + tw_dev->max_sgl_entries = tw_dev->sgl_entries; + } + + /* Now post the command to the board */ + if (srb) { + retval = twa_post_command_packet(tw_dev, request_id, 0); + } else { + twa_post_command_packet(tw_dev, request_id, 1); + retval = 0; + } +out: + return retval; +} /* End twa_scsiop_execute_scsi() */ + +/* This function completes an execute scsi operation */ +static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id) +{ + /* Copy the response if too small */ + if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) { + memcpy(tw_dev->srb[request_id]->request_buffer, + tw_dev->generic_buffer_virt[request_id], + tw_dev->srb[request_id]->request_bufflen); + } +} /* End twa_scsiop_execute_scsi_complete() */ + +/* This function tells the controller to shut down */ +static void __twa_shutdown(TW_Device_Extension *tw_dev) +{ + /* Disable interrupts */ + TW_DISABLE_INTERRUPTS(tw_dev); + + printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev->host->host_no); + + /* Tell the card we are shutting down */ + if (twa_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x31, "Connection shutdown failed"); + } else { + printk(KERN_WARNING "3w-9xxx: Shutdown complete.\n"); + } + + /* Clear all interrupts just before exit */ + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); +} /* End __twa_shutdown() */ + +/* Wrapper for __twa_shutdown */ +static void twa_shutdown(struct device *dev) +{ + struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev)); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + + __twa_shutdown(tw_dev); +} /* End twa_shutdown() */ + +/* This function will look up a string */ +static char *twa_string_lookup(twa_message_type *table, unsigned int code) +{ + int index; + + for (index = 0; ((code != table[index].code) && + (table[index].text != (char *)0)); index++); + return(table[index].text); +} /* End twa_string_lookup() */ + +/* This function will perform a pci-dma unmap */ +static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +{ + struct scsi_cmnd *cmd = tw_dev->srb[request_id]; + struct pci_dev *pdev = tw_dev->tw_pci_dev; + + switch(cmd->SCp.phase) { + case TW_PHASE_SINGLE: + pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL); + break; + case TW_PHASE_SGLIST: + pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + break; + } +} /* End twa_unmap_scsi_data() */ + +/* scsi_host_template initializer */ +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .name = "3ware 9000 Storage Controller", + .queuecommand = twa_scsi_queue, + .eh_abort_handler = twa_scsi_eh_abort, + .eh_host_reset_handler = twa_scsi_eh_reset, + .bios_param = twa_scsi_biosparam, + .can_queue = TW_Q_LENGTH-2, + .this_id = -1, + .sg_tablesize = TW_APACHE_MAX_SGL_LENGTH, + .max_sectors = TW_MAX_SECTORS, + .cmd_per_lun = TW_MAX_CMDS_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = twa_host_attrs, + .sdev_attrs = twa_dev_attrs, + .emulated = 1 +}; + +/* This function will probe and initialize a card */ +static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) +{ + struct Scsi_Host *host = NULL; + TW_Device_Extension *tw_dev; + u32 mem_addr; + int retval = -ENODEV; + + retval = pci_enable_device(pdev); + if (retval) { + TW_PRINTK(host, TW_DRIVER, 0x34, "Failed to enable pci device"); + goto out_disable_device; + } + + pci_set_master(pdev); + + retval = pci_set_dma_mask(pdev, TW_DMA_MASK); + if (retval) { + TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); + goto out_disable_device; + } + + host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); + if (!host) { + TW_PRINTK(host, TW_DRIVER, 0x24, "Failed to allocate memory for device extension"); + retval = -ENOMEM; + goto out_disable_device; + } + tw_dev = (TW_Device_Extension *)host->hostdata; + + memset(tw_dev, 0, sizeof(TW_Device_Extension)); + + /* Save values to device extension */ + tw_dev->host = host; + tw_dev->tw_pci_dev = pdev; + + if (twa_initialize_device_extension(tw_dev)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x25, "Failed to initialize device extension"); + goto out_free_device_extension; + } + + /* Request IO regions */ + retval = pci_request_regions(pdev, "3w-9xxx"); + if (retval) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x26, "Failed to get mem region"); + goto out_free_device_extension; + } + + mem_addr = pci_resource_start(pdev, 1); + + /* Save base address */ + tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE); + if (!tw_dev->base_addr) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap"); + goto out_release_mem_region; + } + + /* Disable interrupts on the card */ + TW_DISABLE_INTERRUPTS(tw_dev); + + /* Initialize the card */ + if (twa_reset_sequence(tw_dev, 0)) + goto out_release_mem_region; + + /* Set host specific parameters */ + host->max_id = TW_MAX_UNITS; + host->max_cmd_len = TW_MAX_CDB_LEN; + + /* Luns and channels aren't supported by adapter */ + host->max_lun = 0; + host->max_channel = 0; + + /* Register the card with the kernel SCSI layer */ + retval = scsi_add_host(host, &pdev->dev); + if (retval) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host failed"); + goto out_release_mem_region; + } + + pci_set_drvdata(pdev, host); + + printk(KERN_WARNING "3w-9xxx: scsi%d: Found a 3ware 9000 Storage Controller at 0x%x, IRQ: %d.\n", + host->host_no, mem_addr, pdev->irq); + printk(KERN_WARNING "3w-9xxx: scsi%d: Firmware %s, BIOS %s, Ports: %d.\n", + host->host_no, + (char *)twa_get_param(tw_dev, 0, TW_VERSION_TABLE, + TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH), + (char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE, + TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH), + *(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE, + TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)); + + /* Now setup the interrupt handler */ + retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev); + if (retval) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x30, "Error requesting IRQ"); + goto out_remove_host; + } + + twa_device_extension_list[twa_device_extension_count] = tw_dev; + twa_device_extension_count++; + + /* Re-enable interrupts on the card */ + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); + + /* Finally, scan the host */ + scsi_scan_host(host); + + if (twa_major == -1) { + if ((twa_major = register_chrdev (0, "twa", &twa_fops)) < 0) + TW_PRINTK(host, TW_DRIVER, 0x29, "Failed to register character device"); + } + return 0; + +out_remove_host: + scsi_remove_host(host); +out_release_mem_region: + pci_release_regions(pdev); +out_free_device_extension: + twa_free_device_extension(tw_dev); + scsi_host_put(host); +out_disable_device: + pci_disable_device(pdev); + + return retval; +} /* End twa_probe() */ + +/* This function is called to remove a device */ +static void twa_remove(struct pci_dev *pdev) +{ + struct Scsi_Host *host = pci_get_drvdata(pdev); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + + scsi_remove_host(tw_dev->host); + + __twa_shutdown(tw_dev); + + /* Free up the IRQ */ + free_irq(tw_dev->tw_pci_dev->irq, tw_dev); + + /* Free up the mem region */ + pci_release_regions(pdev); + + /* Free up device extension resources */ + twa_free_device_extension(tw_dev); + + /* Unregister character device */ + if (twa_major >= 0) { + unregister_chrdev(twa_major, "twa"); + twa_major = -1; + } + + scsi_host_put(tw_dev->host); + pci_disable_device(pdev); + twa_device_extension_count--; +} /* End twa_remove() */ + +/* PCI Devices supported by this driver */ +static struct pci_device_id twa_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; +MODULE_DEVICE_TABLE(pci, twa_pci_tbl); + +/* pci_driver initializer */ +static struct pci_driver twa_driver = { + .name = "3w-9xxx", + .id_table = twa_pci_tbl, + .probe = twa_probe, + .remove = twa_remove, + .driver = { + .shutdown = twa_shutdown + } +}; + +/* This function is called on driver initialization */ +static int __init twa_init(void) +{ + printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", twa_driver_version); + + return pci_module_init(&twa_driver); +} /* End twa_init() */ + +/* This function is called on driver exit */ +static void __exit twa_exit(void) +{ + pci_unregister_driver(&twa_driver); +} /* End twa_exit() */ + +module_init(twa_init); +module_exit(twa_exit); + diff -Nru a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/scsi/3w-9xxx.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,704 @@ +/* + 3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux. + + Written By: Adam Radford + + Copyright (C) 2004 Applied Micro Circuits 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; version 2 of the License. + + 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. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + 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 + + Bugs/Comments/Suggestions should be mailed to: + linuxraid@amcc.com + + For more information, goto: + http://www.amcc.com +*/ + +#ifndef _3W_9XXX_H +#define _3W_9XXX_H + +/* AEN string type */ +typedef struct TAG_twa_message_type { + unsigned int code; + char* text; +} twa_message_type; + +/* AEN strings */ +static twa_message_type twa_aen_table[] = { + {0x0000, "AEN queue empty"}, + {0x0001, "Controller reset occurred"}, + {0x0002, "Degraded unit detected"}, + {0x0003, "Controller error occured"}, + {0x0004, "Background rebuild failed"}, + {0x0005, "Background rebuild done"}, + {0x0006, "Incomplete unit detected"}, + {0x0007, "Background initialize done"}, + {0x0008, "Unclean shutdown detected"}, + {0x0009, "Drive timeout detected"}, + {0x000A, "Drive error detected"}, + {0x000B, "Rebuild started"}, + {0x000C, "Background initialize started"}, + {0x000D, "Entire logical unit was deleted"}, + {0x000E, "Background initialize failed"}, + {0x000F, "SMART attribute exceeded threshold"}, + {0x0010, "Power supply reported AC under range"}, + {0x0011, "Power supply reported DC out of range"}, + {0x0012, "Power supply reported a malfunction"}, + {0x0013, "Power supply predicted malfunction"}, + {0x0014, "Battery charge is below threshold"}, + {0x0015, "Fan speed is below threshold"}, + {0x0016, "Temperature sensor is above threshold"}, + {0x0017, "Power supply was removed"}, + {0x0018, "Power supply was inserted"}, + {0x0019, "Drive was removed from a bay"}, + {0x001A, "Drive was inserted into a bay"}, + {0x001B, "Drive bay cover door was opened"}, + {0x001C, "Drive bay cover door was closed"}, + {0x001D, "Product case was opened"}, + {0x0020, "Prepare for shutdown (power-off)"}, + {0x0021, "Downgrade UDMA mode to lower speed"}, + {0x0022, "Upgrade UDMA mode to higher speed"}, + {0x0023, "Sector repair completed"}, + {0x0024, "Sbuf memory test failed"}, + {0x0025, "Error flushing cached write data to array"}, + {0x0026, "Drive reported data ECC error"}, + {0x0027, "DCB has checksum error"}, + {0x0028, "DCB version is unsupported"}, + {0x0029, "Background verify started"}, + {0x002A, "Background verify failed"}, + {0x002B, "Background verify done"}, + {0x002C, "Bad sector overwritten during rebuild"}, + {0x002D, "Background rebuild error on source drive"}, + {0x002E, "Replace failed because replacement drive too small"}, + {0x002F, "Verify failed because array was never initialized"}, + {0x0030, "Unsupported ATA drive"}, + {0x0031, "Synchronize host/controller time"}, + {0x0032, "Spare capacity is inadequate for some units"}, + {0x0033, "Background migration started"}, + {0x0034, "Background migration failed"}, + {0x0035, "Background migration done"}, + {0x0036, "Verify detected and fixed data/parity mismatch"}, + {0x0037, "SO-DIMM incompatible"}, + {0x0038, "SO-DIMM not detected"}, + {0x0039, "Corrected Sbuf ECC error"}, + {0x003A, "Drive power on reset detected"}, + {0x003B, "Background rebuild paused"}, + {0x003C, "Background initialize paused"}, + {0x003D, "Background verify paused"}, + {0x003E, "Background migration paused"}, + {0x003F, "Corrupt flash file system detected"}, + {0x0040, "Flash file system repaired"}, + {0x0041, "Unit number assignments were lost"}, + {0x0042, "Error during read of primary DCB"}, + {0x0043, "Latent error found in backup DCB"}, + {0x00FC, "Recovered/finished array membership update"}, + {0x00FD, "Handler lockup"}, + {0x00FE, "Retrying PCI transfer"}, + {0x00FF, "AEN queue is full"}, + {0xFFFFFFFF, (char*) 0} +}; + +/* AEN severity table */ +static char *twa_aen_severity_table[] = +{ + "None", "ERROR", "WARNING", "INFO", "DEBUG", (char*) 0 +}; + +/* Error strings */ +static twa_message_type twa_error_table[] = { + {0x0100, "SGL entry contains zero data"}, + {0x0101, "Invalid command opcode"}, + {0x0102, "SGL entry has unaligned address"}, + {0x0103, "SGL size does not match command"}, + {0x0104, "SGL entry has illegal length"}, + {0x0105, "Command packet is not aligned"}, + {0x0106, "Invalid request ID"}, + {0x0107, "Duplicate request ID"}, + {0x0108, "ID not locked"}, + {0x0109, "LBA out of range"}, + {0x010A, "Logical unit not supported"}, + {0x010B, "Parameter table does not exist"}, + {0x010C, "Parameter index does not exist"}, + {0x010D, "Invalid field in CDB"}, + {0x010E, "Specified port has invalid drive"}, + {0x010F, "Parameter item size mismatch"}, + {0x0110, "Failed memory allocation"}, + {0x0111, "Memory request too large"}, + {0x0112, "Out of memory segments"}, + {0x0113, "Invalid address to deallocate"}, + {0x0114, "Out of memory"}, + {0x0115, "Out of heap"}, + {0x0120, "Double degrade"}, + {0x0121, "Drive not degraded"}, + {0x0122, "Reconstruct error"}, + {0x0123, "Replace not accepted"}, + {0x0124, "Replace drive capacity too small"}, + {0x0125, "Sector count not allowed"}, + {0x0126, "No spares left"}, + {0x0127, "Reconstruct error"}, + {0x0128, "Unit is offline"}, + {0x0129, "Cannot update status to DCB"}, + {0x0130, "Invalid stripe handle"}, + {0x0131, "Handle that was not locked"}, + {0x0132, "Handle that was not empty"}, + {0x0133, "Handle has different owner"}, + {0x0140, "IPR has parent"}, + {0x0150, "Illegal Pbuf address alignment"}, + {0x0151, "Illegal Pbuf transfer length"}, + {0x0152, "Illegal Sbuf address alignment"}, + {0x0153, "Illegal Sbuf transfer length"}, + {0x0160, "Command packet too large"}, + {0x0161, "SGL exceeds maximum length"}, + {0x0162, "SGL has too many entries"}, + {0x0170, "Insufficient resources for rebuilder"}, + {0x0171, "Verify error (data != parity)"}, + {0x0180, "Requested segment not in directory of this DCB"}, + {0x0181, "DCB segment has unsupported version"}, + {0x0182, "DCB segment has checksum error"}, + {0x0183, "DCB support (settings) segment invalid"}, + {0x0184, "DCB UDB (unit descriptor block) segment invalid"}, + {0x0185, "DCB GUID (globally unique identifier) segment invalid"}, + {0x01A0, "Could not clear Sbuf"}, + {0x01C0, "Flash identify failed"}, + {0x01C1, "Flash out of bounds"}, + {0x01C2, "Flash verify error"}, + {0x01C3, "Flash file object not found"}, + {0x01C4, "Flash file already present"}, + {0x01C5, "Flash file system full"}, + {0x01C6, "Flash file not present"}, + {0x01C7, "Flash file size error"}, + {0x01C8, "Bad flash file checksum"}, + {0x01CA, "Corrupt flash file system detected"}, + {0x01D0, "Invalid field in parameter list"}, + {0x01D1, "Parameter list length error"}, + {0x01D2, "Parameter item is not changeable"}, + {0x01D3, "Parameter item is not saveable"}, + {0x0200, "UDMA CRC error"}, + {0x0201, "Internal CRC error"}, + {0x0202, "Data ECC error"}, + {0x0203, "ADP level 1 error"}, + {0x0204, "Port timeout"}, + {0x0205, "Drive power on reset"}, + {0x0206, "ADP level 2 error"}, + {0x0207, "Soft reset failed"}, + {0x0208, "Drive not ready"}, + {0x0209, "Unclassified port error"}, + {0x020A, "Drive aborted command"}, + {0x0210, "Internal CRC error"}, + {0x0211, "PCI abort error"}, + {0x0212, "PCI parity error"}, + {0x0213, "Port handler error"}, + {0x0214, "Token interrupt count error"}, + {0x0215, "Timeout waiting for PCI transfer"}, + {0x0216, "Corrected buffer ECC"}, + {0x0217, "Uncorrected buffer ECC"}, + {0x0230, "Unsupported command during flash recovery"}, + {0x0231, "Next image buffer expected"}, + {0x0232, "Binary image architecture incompatible"}, + {0x0233, "Binary image has no signature"}, + {0x0234, "Binary image has bad checksum"}, + {0x0235, "Image downloaded overflowed buffer"}, + {0x0240, "I2C device not found"}, + {0x0241, "I2C transaction aborted"}, + {0x0242, "SO-DIMM parameter(s) incompatible using defaults"}, + {0x0243, "SO-DIMM unsupported"}, + {0x0248, "SPI transfer status error"}, + {0x0249, "SPI transfer timeout error"}, + {0x0250, "Invalid unit descriptor size in CreateUnit"}, + {0x0251, "Unit descriptor size exceeds data buffer in CreateUnit"}, + {0x0252, "Invalid value in CreateUnit descriptor"}, + {0x0253, "Inadequate disk space to support descriptor in CreateUnit"}, + {0x0254, "Unable to create data channel for this unit descriptor"}, + {0x0255, "CreateUnit descriptor specifies a drive already in use"}, + {0x0256, "Unable to write configuration to all disks during CreateUnit"}, + {0x0257, "CreateUnit does not support this descriptor version"}, + {0x0258, "Invalid subunit for RAID 0 or 5 in CreateUnit"}, + {0x0259, "Too many descriptors in CreateUnit"}, + {0x025A, "Invalid configuration specified in CreateUnit descriptor"}, + {0x025B, "Invalid LBA offset specified in CreateUnit descriptor"}, + {0x025C, "Invalid stripelet size specified in CreateUnit descriptor"}, + {0x0260, "SMART attribute exceeded threshold"}, + {0xFFFFFFFF, (char*) 0} +}; + +/* Control register bit definitions */ +#define TW_CONTROL_CLEAR_HOST_INTERRUPT 0x00080000 +#define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT 0x00040000 +#define TW_CONTROL_MASK_COMMAND_INTERRUPT 0x00020000 +#define TW_CONTROL_MASK_RESPONSE_INTERRUPT 0x00010000 +#define TW_CONTROL_UNMASK_COMMAND_INTERRUPT 0x00008000 +#define TW_CONTROL_UNMASK_RESPONSE_INTERRUPT 0x00004000 +#define TW_CONTROL_CLEAR_ERROR_STATUS 0x00000200 +#define TW_CONTROL_ISSUE_SOFT_RESET 0x00000100 +#define TW_CONTROL_ENABLE_INTERRUPTS 0x00000080 +#define TW_CONTROL_DISABLE_INTERRUPTS 0x00000040 +#define TW_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020 +#define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 +#define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000 +#define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000 +#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008 + +/* Status register bit definitions */ +#define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 +#define TW_STATUS_MINOR_VERSION_MASK 0x0F000000 +#define TW_STATUS_PCI_PARITY_ERROR 0x00800000 +#define TW_STATUS_QUEUE_ERROR 0x00400000 +#define TW_STATUS_MICROCONTROLLER_ERROR 0x00200000 +#define TW_STATUS_PCI_ABORT 0x00100000 +#define TW_STATUS_HOST_INTERRUPT 0x00080000 +#define TW_STATUS_ATTENTION_INTERRUPT 0x00040000 +#define TW_STATUS_COMMAND_INTERRUPT 0x00020000 +#define TW_STATUS_RESPONSE_INTERRUPT 0x00010000 +#define TW_STATUS_COMMAND_QUEUE_FULL 0x00008000 +#define TW_STATUS_RESPONSE_QUEUE_EMPTY 0x00004000 +#define TW_STATUS_MICROCONTROLLER_READY 0x00002000 +#define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000 +#define TW_STATUS_EXPECTED_BITS 0x00002000 +#define TW_STATUS_UNEXPECTED_BITS 0x00F00008 +#define TW_STATUS_SBUF_WRITE_ERROR 0x00000008 +#define TW_STATUS_VALID_INTERRUPT 0x00DF0008 + +/* RESPONSE QUEUE BIT DEFINITIONS */ +#define TW_RESPONSE_ID_MASK 0x00000FF0 + +/* PCI related defines */ +#define TW_DEVICE_NAME "3w-9xxx" +#define TW_NUMDEVICES 1 +#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100 +#define TW_PCI_CLEAR_PCI_ABORT 0x2000 + +/* Command packet opcodes used by the driver */ +#define TW_OP_INIT_CONNECTION 0x1 +#define TW_OP_GET_PARAM 0x12 +#define TW_OP_SET_PARAM 0x13 +#define TW_OP_EXECUTE_SCSI 0x10 +#define TW_OP_DOWNLOAD_FIRMWARE 0x16 +#define TW_OP_RESET 0x1C + +/* Asynchronous Event Notification (AEN) codes used by the driver */ +#define TW_AEN_QUEUE_EMPTY 0x0000 +#define TW_AEN_SOFT_RESET 0x0001 +#define TW_AEN_SYNC_TIME_WITH_HOST 0x031 +#define TW_AEN_SEVERITY_ERROR 0x1 +#define TW_AEN_SEVERITY_DEBUG 0x4 +#define TW_AEN_NOT_RETRIEVED 0x1 +#define TW_AEN_RETRIEVED 0x2 + +/* Command state defines */ +#define TW_S_INITIAL 0x1 /* Initial state */ +#define TW_S_STARTED 0x2 /* Id in use */ +#define TW_S_POSTED 0x4 /* Posted to the controller */ +#define TW_S_PENDING 0x8 /* Waiting to be posted in isr */ +#define TW_S_COMPLETED 0x10 /* Completed by isr */ +#define TW_S_FINISHED 0x20 /* I/O completely done */ + +/* Compatibility defines */ +#define TW_9000_ARCH_ID 0x5 +#define TW_CURRENT_FW_SRL 24 +#define TW_CURRENT_FW_BUILD 5 +#define TW_CURRENT_FW_BRANCH 1 + +/* Phase defines */ +#define TW_PHASE_INITIAL 0 +#define TW_PHASE_SINGLE 1 +#define TW_PHASE_SGLIST 2 + +/* Misc defines */ +#define TW_SECTOR_SIZE 512 +#define TW_ALIGNMENT_9000 4 /* 4 bytes */ +#define TW_ALIGNMENT_9000_SGL 0x3 +#define TW_MAX_UNITS 16 +#define TW_INIT_MESSAGE_CREDITS 0x100 +#define TW_INIT_COMMAND_PACKET_SIZE 0x3 +#define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED 0x6 +#define TW_EXTENDED_INIT_CONNECT 0x2 +#define TW_BUNDLED_FW_SAFE_TO_FLASH 0x4 +#define TW_CTLR_FW_RECOMMENDS_FLASH 0x8 +#define TW_CTLR_FW_COMPATIBLE 0x2 +#define TW_BASE_FW_SRL 0x17 +#define TW_BASE_FW_BRANCH 0 +#define TW_BASE_FW_BUILD 1 +#if BITS_PER_LONG > 32 +#define TW_APACHE_MAX_SGL_LENGTH 72 +#define TW_ESCALADE_MAX_SGL_LENGTH 41 +#define TW_APACHE_CMD_PKT_SIZE 5 +#else +#define TW_APACHE_MAX_SGL_LENGTH 109 +#define TW_ESCALADE_MAX_SGL_LENGTH 62 +#define TW_APACHE_CMD_PKT_SIZE 4 +#endif +#define TW_ATA_PASS_SGL_MAX 60 +#define TW_Q_LENGTH 256 +#define TW_Q_START 0 +#define TW_MAX_SLOT 32 +#define TW_MAX_RESET_TRIES 2 +#define TW_MAX_CMDS_PER_LUN 254 +#define TW_MAX_RESPONSE_DRAIN 256 +#define TW_MAX_AEN_DRAIN 40 +#define TW_IN_IOCTL 2 +#define TW_IN_CHRDEV_IOCTL 3 +#define TW_IN_ATTENTION_LOOP 4 +#define TW_MAX_SECTORS 256 +#define TW_AEN_WAIT_TIME 1000 +#define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */ +#define TW_MAX_CDB_LEN 16 +#define TW_ISR_DONT_COMPLETE 2 +#define TW_ISR_DONT_RESULT 3 +#define TW_IOCTL_CHRDEV_TIMEOUT 60 /* 60 seconds */ +#define TW_IOCTL_CHRDEV_FREE -1 +#define TW_COMMAND_OFFSET 128 /* 128 bytes */ +#define TW_VERSION_TABLE 0x0402 +#define TW_TIMEKEEP_TABLE 0x040A +#define TW_INFORMATION_TABLE 0x0403 +#define TW_PARAM_FWVER 3 +#define TW_PARAM_FWVER_LENGTH 16 +#define TW_PARAM_BIOSVER 4 +#define TW_PARAM_BIOSVER_LENGTH 16 +#define TW_PARAM_PORTCOUNT 3 +#define TW_PARAM_PORTCOUNT_LENGTH 1 +#define TW_MIN_SGL_LENGTH 0x200 /* 512 bytes */ +#define TW_MAX_SENSE_LENGTH 256 +#define TW_EVENT_SOURCE_AEN 0x1000 +#define TW_EVENT_SOURCE_COMMAND 0x1001 +#define TW_EVENT_SOURCE_PCHIP 0x1002 +#define TW_EVENT_SOURCE_DRIVER 0x1003 +#define TW_IOCTL_GET_COMPATIBILITY_INFO 0x101 +#define TW_IOCTL_GET_LAST_EVENT 0x102 +#define TW_IOCTL_GET_FIRST_EVENT 0x103 +#define TW_IOCTL_GET_NEXT_EVENT 0x104 +#define TW_IOCTL_GET_PREVIOUS_EVENT 0x105 +#define TW_IOCTL_GET_LOCK 0x106 +#define TW_IOCTL_RELEASE_LOCK 0x107 +#define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108 +#define TW_IOCTL_ERROR_STATUS_NOT_LOCKED 0x1001 // Not locked +#define TW_IOCTL_ERROR_STATUS_LOCKED 0x1002 // Already locked +#define TW_IOCTL_ERROR_STATUS_NO_MORE_EVENTS 0x1003 // No more events +#define TW_IOCTL_ERROR_STATUS_AEN_CLOBBER 0x1004 // AEN clobber occurred +#define TW_IOCTL_ERROR_OS_EFAULT -EFAULT // Bad address +#define TW_IOCTL_ERROR_OS_EINTR -EINTR // Interrupted system call +#define TW_IOCTL_ERROR_OS_EINVAL -EINVAL // Invalid argument +#define TW_IOCTL_ERROR_OS_ENOMEM -ENOMEM // Out of memory +#define TW_IOCTL_ERROR_OS_ERESTARTSYS -ERESTARTSYS // Restart system call +#define TW_IOCTL_ERROR_OS_EIO -EIO // I/O error +#define TW_IOCTL_ERROR_OS_ENOTTY -ENOTTY // Not a typewriter +#define TW_IOCTL_ERROR_OS_ENODEV -ENODEV // No such device +#define TW_ALLOCATION_LENGTH 128 +#define TW_SENSE_DATA_LENGTH 18 +#define TW_STATUS_CHECK_CONDITION 2 +#define TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED 0x10a +#define TW_ERROR_UNIT_OFFLINE 0x128 +#define TW_MESSAGE_SOURCE_CONTROLLER_ERROR 3 +#define TW_MESSAGE_SOURCE_CONTROLLER_EVENT 4 +#define TW_MESSAGE_SOURCE_LINUX_DRIVER 6 +#define TW_DRIVER TW_MESSAGE_SOURCE_LINUX_DRIVER +#define TW_MESSAGE_SOURCE_LINUX_OS 9 +#define TW_OS TW_MESSAGE_SOURCE_LINUX_OS +#if BITS_PER_LONG > 32 +#define TW_COMMAND_SIZE 5 +#define TW_DMA_MASK DMA_64BIT_MASK +#else +#define TW_COMMAND_SIZE 4 +#define TW_DMA_MASK DMA_32BIT_MASK +#endif +#ifndef PCI_DEVICE_ID_3WARE_9000 +#define PCI_DEVICE_ID_3WARE_9000 0x1002 +#endif + +/* Bitmask macros to eliminate bitfields */ + +/* opcode: 5, reserved: 3 */ +#define TW_OPRES_IN(x,y) ((x << 5) | (y & 0x1f)) +#define TW_OP_OUT(x) (x & 0x1f) + +/* opcode: 5, sgloffset: 3 */ +#define TW_OPSGL_IN(x,y) ((x << 5) | (y & 0x1f)) +#define TW_SGL_OUT(x) ((x >> 5) & 0x7) + +/* severity: 3, reserved: 5 */ +#define TW_SEV_OUT(x) (x & 0x7) + +/* reserved_1: 4, response_id: 8, reserved_2: 20 */ +#define TW_RESID_OUT(x) ((x >> 4) & 0xff) + +/* Macros */ +#define TW_CONTROL_REG_ADDR(x) (x->base_addr) +#define TW_STATUS_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x4) +#if BITS_PER_LONG > 32 +#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x20) +#else +#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x8) +#endif +#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0xC) +#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_DISABLE_INTERRUPTS(x) (writel(TW_CONTROL_DISABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x))) +#define TW_ENABLE_AND_CLEAR_INTERRUPTS(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | TW_CONTROL_UNMASK_RESPONSE_INTERRUPT | TW_CONTROL_ENABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x))) +#define TW_MASK_COMMAND_INTERRUPT(x) (writel(TW_CONTROL_MASK_COMMAND_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_UNMASK_COMMAND_INTERRUPT(x) (writel(TW_CONTROL_UNMASK_COMMAND_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_SOFT_RESET(x) (writel(TW_CONTROL_ISSUE_SOFT_RESET | \ + TW_CONTROL_CLEAR_HOST_INTERRUPT | \ + TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | \ + TW_CONTROL_MASK_COMMAND_INTERRUPT | \ + TW_CONTROL_MASK_RESPONSE_INTERRUPT | \ + TW_CONTROL_CLEAR_ERROR_STATUS | \ + TW_CONTROL_DISABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x))) +#define TW_PRINTK(h,a,b,c) { \ +if (h) \ +printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s.\n",h->host_no,a,b,c); \ +else \ +printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \ +} + +#pragma pack(1) + +/* Scatter Gather List Entry */ +typedef struct TAG_TW_SG_Entry { + unsigned long address; + u32 length; +} TW_SG_Entry; + +/* Command Packet */ +typedef struct TW_Command { + unsigned char opcode__sgloffset; + unsigned char size; + unsigned char request_id; + unsigned char unit__hostid; + /* Second DWORD */ + unsigned char status; + unsigned char flags; + union { + unsigned short block_count; + unsigned short parameter_count; + } byte6_offset; + union { + struct { + u32 lba; + TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH]; +#if BITS_PER_LONG > 32 + u32 padding[2]; /* pad to 512 bytes */ +#else + u32 padding; +#endif + } io; + struct { + TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH]; +#if BITS_PER_LONG > 32 + u32 padding[3]; +#else + u32 padding[2]; +#endif + } param; + } byte8_offset; +} TW_Command; + +/* Scatter gather element for 9000+ controllers */ +typedef struct TAG_TW_SG_Apache { + unsigned long address; + u32 length; +} TW_SG_Apache; + +/* Command Packet for 9000+ controllers */ +typedef struct TAG_TW_Command_Apache { + unsigned char opcode__reserved; + unsigned char unit; + unsigned short request_id; + unsigned char status; + unsigned char sgl_offset; + unsigned short sgl_entries; + unsigned char cdb[16]; + TW_SG_Apache sg_list[TW_APACHE_MAX_SGL_LENGTH]; +#if BITS_PER_LONG > 32 + unsigned char padding[8]; +#endif +} TW_Command_Apache; + +/* New command packet header */ +typedef struct TAG_TW_Command_Apache_Header { + unsigned char sense_data[TW_SENSE_DATA_LENGTH]; + struct { + char reserved[4]; + unsigned short error; + unsigned char padding; + unsigned char severity__reserved; + } status_block; + unsigned char err_specific_desc[98]; + struct { + unsigned char size_header; + unsigned short reserved; + unsigned char size_sense; + } header_desc; +} TW_Command_Apache_Header; + +/* This struct is a union of the 2 command packets */ +typedef struct TAG_TW_Command_Full { + TW_Command_Apache_Header header; + union { + TW_Command oldcommand; + TW_Command_Apache newcommand; + } command; +} TW_Command_Full; + +/* Initconnection structure */ +typedef struct TAG_TW_Initconnect { + unsigned char opcode__reserved; + unsigned char size; + unsigned char request_id; + unsigned char res2; + unsigned char status; + unsigned char flags; + unsigned short message_credits; + u32 features; + unsigned short fw_srl; + unsigned short fw_arch_id; + unsigned short fw_branch; + unsigned short fw_build; + u32 result; +} TW_Initconnect; + +/* Event info structure */ +typedef struct TAG_TW_Event +{ + unsigned int sequence_id; + unsigned int time_stamp_sec; + unsigned short aen_code; + unsigned char severity; + unsigned char retrieved; + unsigned char repeat_count; + unsigned char parameter_len; + unsigned char parameter_data[98]; +} TW_Event; + +typedef struct TAG_TW_Ioctl_Driver_Command { + unsigned int control_code; + unsigned int status; + unsigned int unique_id; + unsigned int sequence_id; + unsigned int os_specific; + unsigned int buffer_length; +} TW_Ioctl_Driver_Command; + +typedef struct TAG_TW_Ioctl_Apache { + TW_Ioctl_Driver_Command driver_command; + char padding[488]; + TW_Command_Full firmware_command; + char data_buffer[1]; +} TW_Ioctl_Buf_Apache; + +/* Lock structure for ioctl get/release lock */ +typedef struct TAG_TW_Lock { + unsigned long timeout_msec; + unsigned long time_remaining_msec; + unsigned long force_flag; +} TW_Lock; + +/* GetParam descriptor */ +typedef struct { + unsigned short table_id; + unsigned short parameter_id; + unsigned short parameter_size_bytes; + unsigned short actual_parameter_size_bytes; + unsigned char data[1]; +} TW_Param_Apache, *PTW_Param_Apache; + +/* Response queue */ +typedef union TAG_TW_Response_Queue { + u32 response_id; + u32 value; +} TW_Response_Queue; + +typedef struct TAG_TW_Info { + char *buffer; + int length; + int offset; + int position; +} TW_Info; + +/* Compatibility information structure */ +typedef struct TAG_TW_Compatibility_Info +{ + char driver_version[32]; + unsigned short working_srl; + unsigned short working_branch; + unsigned short working_build; +} TW_Compatibility_Info; + +typedef struct TAG_TW_Device_Extension { + u32 *base_addr; + unsigned long *generic_buffer_virt[TW_Q_LENGTH]; + unsigned long generic_buffer_phys[TW_Q_LENGTH]; + TW_Command_Full *command_packet_virt[TW_Q_LENGTH]; + unsigned long command_packet_phys[TW_Q_LENGTH]; + struct pci_dev *tw_pci_dev; + struct scsi_cmnd *srb[TW_Q_LENGTH]; + unsigned char free_queue[TW_Q_LENGTH]; + unsigned char free_head; + unsigned char free_tail; + unsigned char pending_queue[TW_Q_LENGTH]; + unsigned char pending_head; + unsigned char pending_tail; + int state[TW_Q_LENGTH]; + unsigned int posted_request_count; + unsigned int max_posted_request_count; + unsigned int pending_request_count; + unsigned int max_pending_request_count; + unsigned int max_sgl_entries; + unsigned int sgl_entries; + unsigned int num_aborts; + unsigned int num_resets; + unsigned int sector_count; + unsigned int max_sector_count; + unsigned int aen_count; + struct Scsi_Host *host; + long flags; + int reset_print; + TW_Event *event_queue[TW_Q_LENGTH]; + unsigned char error_index; + unsigned char event_queue_wrapped; + unsigned int error_sequence_id; + int ioctl_sem_lock; + u32 ioctl_msec; + int chrdev_request_id; + wait_queue_head_t ioctl_wqueue; + struct semaphore ioctl_sem; + char aen_clobber; + unsigned short working_srl; + unsigned short working_branch; + unsigned short working_build; +} TW_Device_Extension; + +#pragma pack() + +#endif /* _3W_9XXX_H */ + diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- a/drivers/scsi/3w-xxxx.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/3w-xxxx.c 2004-06-20 13:00:25 -07:00 @@ -220,7 +220,7 @@ #define __3W_C /* let 3w-xxxx.h know it is use */ #include "scsi.h" -#include "hosts.h" +#include #include "3w-xxxx.h" diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/53c700.c 2004-06-20 13:00:23 -07:00 @@ -125,18 +125,21 @@ #include #include #include +#include +#include +#include #include #include #include #include #include -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" +#include +#include +#include +#include +#include +#include #include #include @@ -164,15 +167,15 @@ #include "53c700_d.h" -STATIC int NCR_700_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -STATIC int NCR_700_abort(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); +STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt); +STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt); +STATIC int NCR_700_dev_reset(struct scsi_cmnd * SCpnt); +STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt); STATIC void NCR_700_chip_setup(struct Scsi_Host *host); STATIC void NCR_700_chip_reset(struct Scsi_Host *host); -STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt); -STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt); +STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); +STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); STATIC struct device_attribute *NCR_700_dev_attrs[]; @@ -279,7 +282,7 @@ } static inline __u8 -NCR_700_get_SXFER(Scsi_Device *SDp) +NCR_700_get_SXFER(struct scsi_device *SDp) { struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; @@ -289,7 +292,7 @@ } struct Scsi_Host * -NCR_700_detect(Scsi_Host_Template *tpnt, +NCR_700_detect(struct scsi_host_template *tpnt, struct NCR_700_Host_Parameters *hostdata) { dma_addr_t pScript, pSlots; @@ -561,7 +564,7 @@ the ITL and (if tagged) the ITLQ lists in _queuecommand */ STATIC void save_for_reselection(struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, __u32 dsp) + struct scsi_cmnd *SCp, __u32 dsp) { /* Its just possible that this gets executed twice */ if(SCp != NULL) { @@ -575,27 +578,25 @@ } STATIC inline void -NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp, +NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp, struct NCR_700_command_slot *slot) { - if(SCp->sc_data_direction != SCSI_DATA_NONE && - SCp->sc_data_direction != SCSI_DATA_UNKNOWN) { - enum dma_data_direction direction = SCp->sc_data_direction; + if(SCp->sc_data_direction != DMA_NONE && + SCp->sc_data_direction != DMA_BIDIRECTIONAL) { if(SCp->use_sg) { dma_unmap_sg(hostdata->dev, SCp->buffer, - SCp->use_sg, direction); + SCp->use_sg, SCp->sc_data_direction); } else { - dma_unmap_single(hostdata->dev, - slot->dma_handle, + dma_unmap_single(hostdata->dev, slot->dma_handle, SCp->request_bufflen, - direction); + SCp->sc_data_direction); } } } STATIC inline void NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, int result) + struct scsi_cmnd *SCp, int result) { hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; @@ -611,7 +612,7 @@ #ifdef NCR_700_DEBUG printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", SCp, SCp->cmnd[7], result); - print_sense("53c700", SCp); + scsi_print_sense("53c700", SCp); #endif /* restore the old result if the request sense was @@ -780,7 +781,7 @@ STATIC __u32 process_extended_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) + struct scsi_cmnd *SCp, __u32 dsp, __u32 dsps) { __u32 resume_offset = dsp, temp = dsp + 8; __u8 pun = 0xff, lun = 0xff; @@ -849,7 +850,7 @@ printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ", host->host_no, pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); - print_msg(hostdata->msgin); + scsi_print_msg(hostdata->msgin); printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; @@ -865,7 +866,7 @@ STATIC __u32 process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) + struct scsi_cmnd *SCp, __u32 dsp, __u32 dsps) { /* work out where to return to */ __u32 temp = dsp + 8, resume_offset = dsp; @@ -879,7 +880,7 @@ #ifdef NCR_700_DEBUG printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); - print_msg(hostdata->msgin); + scsi_print_msg(hostdata->msgin); printk("\n"); #endif @@ -927,7 +928,7 @@ host->host_no, pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); - print_msg(hostdata->msgin); + scsi_print_msg(hostdata->msgin); printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; @@ -946,7 +947,7 @@ } STATIC __u32 -process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, +process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata) { @@ -975,7 +976,7 @@ NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); } else { #ifdef NCR_DEBUG - print_command(SCp->cmnd); + scsi_print_command(SCp); printk(" cmd %p has status %d, requesting sense\n", SCp, hostdata->status[0]); #endif @@ -1004,7 +1005,7 @@ SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; SCp->cmnd[7] = hostdata->status[0]; SCp->use_sg = 0; - SCp->sc_data_direction = SCSI_DATA_READ; + SCp->sc_data_direction = DMA_FROM_DEVICE; dma_sync_single_for_device(hostdata->dev, slot->pCmd, SCp->cmd_len, DMA_TO_DEVICE); SCp->request_bufflen = sizeof(SCp->sense_buffer); @@ -1053,7 +1054,7 @@ NCR_700_phase[i], sbcl_to_string(NCR_700_readb(host, SBCL_REG))); printk(KERN_ERR " len = %d, cmd =", SCp->cmd_len); - print_command(SCp->cmnd); + scsi_print_command(SCp); NCR_700_internal_bus_reset(host); } else if((dsps & 0xfffff000) == A_FATAL) { @@ -1080,7 +1081,7 @@ __u8 lun; struct NCR_700_command_slot *slot; __u8 reselection_id = hostdata->reselection_id; - Scsi_Device *SDp; + struct scsi_device *SDp; lun = hostdata->msgin[0] & 0x1f; @@ -1095,7 +1096,7 @@ BUG(); } if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) { - Scsi_Cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]); + struct scsi_cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]); if(unlikely(SCp == NULL)) { printk(KERN_ERR "scsi%d: (%d:%d) no saved request for tag %d\n", host->host_no, reselection_id, lun, hostdata->msgin[2]); @@ -1107,7 +1108,7 @@ host->host_no, SDp->id, SDp->lun, hostdata->msgin[2], slot, slot->tag)); } else { - Scsi_Cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG); + struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG); if(unlikely(SCp == NULL)) { printk(KERN_ERR "scsi%d: (%d:%d) no saved request for untagged cmd\n", host->host_no, reselection_id, lun); @@ -1234,7 +1235,7 @@ host->host_no, pun, lun, NCR_700_condition[i], NCR_700_phase[j], dsp - hostdata->pScript); if(SCp != NULL) { - print_command(SCp->cmnd); + scsi_print_command(SCp); if(SCp->use_sg) { for(i = 0; i < SCp->use_sg + 1; i++) { @@ -1270,7 +1271,7 @@ __u32 resume_offset = 0; struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; - Scsi_Cmnd *SCp = hostdata->cmd; + struct scsi_cmnd *SCp = hostdata->cmd; __u8 sbcl; for(count = 0; count < 5; count++) { @@ -1373,7 +1374,7 @@ /* The queue lock with interrupts disabled must be held on entry to * this function */ STATIC int -NCR_700_start_command(Scsi_Cmnd *SCp) +NCR_700_start_command(struct scsi_cmnd *SCp) { struct NCR_700_command_slot *slot = (struct NCR_700_command_slot *)SCp->host_scribble; @@ -1481,7 +1482,7 @@ __u32 dsps; __u8 sstat0 = 0, dstat = 0; __u32 dsp; - Scsi_Cmnd *SCp = hostdata->cmd; + struct scsi_cmnd *SCp = hostdata->cmd; enum NCR_700_Host_State state; handled = 1; @@ -1514,7 +1515,7 @@ } if(sstat0 & SCSI_RESET_DETECTED) { - Scsi_Device *SDp; + struct scsi_device *SDp; int i; hostdata->state = NCR_700_HOST_BUSY; @@ -1530,7 +1531,7 @@ /* clear all the slots and their pending commands */ for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { - Scsi_Cmnd *SCp; + struct scsi_cmnd *SCp; struct NCR_700_command_slot *slot = &hostdata->slots[i]; @@ -1590,7 +1591,7 @@ printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x\n", host->host_no, pun, lun, SGcount, data_transfer); - print_command(SCp->cmnd); + scsi_print_command(SCp); if(residual) { printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x, residual %d\n", host->host_no, pun, lun, @@ -1731,7 +1732,7 @@ } STATIC int -NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) +NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) { struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0]; @@ -1781,7 +1782,7 @@ #ifdef NCR_700_DEBUG printk("53c700: scsi%d, command ", SCp->device->host->host_no); - print_command(SCp->cmnd); + scsi_print_command(SCp); #endif if(SCp->device->tagged_supported && !SCp->device->simple_tags && (hostdata->tag_negotiated &(1<device->id)) == 0 @@ -1827,13 +1828,13 @@ /* sanity check: some of the commands generated by the mid-layer * have an eccentric idea of their sc_data_direction */ if(!SCp->use_sg && !SCp->request_bufflen - && SCp->sc_data_direction != SCSI_DATA_NONE) { + && SCp->sc_data_direction != DMA_NONE) { #ifdef NCR_700_DEBUG printk("53c700: Command"); - print_command(SCp->cmnd); + scsi_print_command(SCp); printk("Has wrong data direction %d\n", SCp->sc_data_direction); #endif - SCp->sc_data_direction = SCSI_DATA_NONE; + SCp->sc_data_direction = DMA_NONE; } switch (SCp->cmnd[0]) { @@ -1844,20 +1845,20 @@ default: /* OK, get it from the command */ switch(SCp->sc_data_direction) { - case SCSI_DATA_UNKNOWN: + case DMA_BIDIRECTIONAL: default: printk(KERN_ERR "53c700: Unknown command for data direction "); - print_command(SCp->cmnd); + scsi_print_command(SCp); move_ins = 0; break; - case SCSI_DATA_NONE: + case DMA_NONE: move_ins = 0; break; - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: move_ins = SCRIPT_MOVE_DATA_IN; break; - case SCSI_DATA_WRITE: + case DMA_TO_DEVICE: move_ins = SCRIPT_MOVE_DATA_OUT; break; } @@ -1914,13 +1915,13 @@ } STATIC int -NCR_700_abort(Scsi_Cmnd * SCp) +NCR_700_abort(struct scsi_cmnd * SCp) { struct NCR_700_command_slot *slot; printk(KERN_INFO "scsi%d (%d:%d) New error handler wants to abort command\n\t", SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - print_command(SCp->cmnd); + scsi_print_command(SCp); slot = (struct NCR_700_command_slot *)SCp->host_scribble; @@ -1946,7 +1947,7 @@ } STATIC int -NCR_700_bus_reset(Scsi_Cmnd * SCp) +NCR_700_bus_reset(struct scsi_cmnd * SCp) { DECLARE_COMPLETION(complete); struct NCR_700_Host_Parameters *hostdata = @@ -1954,7 +1955,7 @@ printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t", SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp); - print_command(SCp->cmnd); + scsi_print_command(SCp); /* In theory, eh_complete should always be null because the * eh is single threaded, but just in case we're handling a * reset via sg or something */ @@ -1976,21 +1977,21 @@ } STATIC int -NCR_700_dev_reset(Scsi_Cmnd * SCp) +NCR_700_dev_reset(struct scsi_cmnd * SCp) { printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t", SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - print_command(SCp->cmnd); + scsi_print_command(SCp); return FAILED; } STATIC int -NCR_700_host_reset(Scsi_Cmnd * SCp) +NCR_700_host_reset(struct scsi_cmnd * SCp) { printk(KERN_INFO "scsi%d (%d:%d) New error handler wants HOST reset\n\t", SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - print_command(SCp->cmnd); + scsi_print_command(SCp); NCR_700_internal_bus_reset(SCp->device->host); NCR_700_chip_reset(SCp->device->host); @@ -2043,7 +2044,7 @@ STATIC int -NCR_700_slave_configure(Scsi_Device *SDp) +NCR_700_slave_configure(struct scsi_device *SDp) { struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; @@ -2066,7 +2067,7 @@ } STATIC void -NCR_700_slave_destroy(Scsi_Device *SDp) +NCR_700_slave_destroy(struct scsi_device *SDp) { /* to do here: deallocate memory */ } diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h --- a/drivers/scsi/53c700.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/53c700.h 2004-06-20 13:00:23 -07:00 @@ -9,9 +9,11 @@ #define _53C700_H #include - #include +#include + + #if defined(CONFIG_53C700_MEM_MAPPED) && defined(CONFIG_53C700_IO_MAPPED) #define CONFIG_53C700_BOTH_MAPPED #endif @@ -57,7 +59,8 @@ struct NCR_700_Host_Parameters; /* These are the externally used routines */ -struct Scsi_Host *NCR_700_detect(Scsi_Host_Template *, struct NCR_700_Host_Parameters *); +struct Scsi_Host *NCR_700_detect(struct scsi_host_template *, + struct NCR_700_Host_Parameters *); int NCR_700_release(struct Scsi_Host *host); irqreturn_t NCR_700_intr(int, void *, struct pt_regs *); @@ -102,7 +105,7 @@ #define NCR_700_DEV_PRINT_SYNC_NEGOTIATION (1<<19) static inline void -NCR_700_set_depth(Scsi_Device *SDp, __u8 depth) +NCR_700_set_depth(struct scsi_device *SDp, __u8 depth) { long l = (long)SDp->hostdata; @@ -111,27 +114,27 @@ SDp->hostdata = (void *)l; } static inline __u8 -NCR_700_get_depth(Scsi_Device *SDp) +NCR_700_get_depth(struct scsi_device *SDp) { return ((((unsigned long)SDp->hostdata) & 0xff00)>>8); } static inline int -NCR_700_is_flag_set(Scsi_Device *SDp, __u32 flag) +NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag) { return (((unsigned long)SDp->hostdata) & flag) == flag; } static inline int -NCR_700_is_flag_clear(Scsi_Device *SDp, __u32 flag) +NCR_700_is_flag_clear(struct scsi_device *SDp, __u32 flag) { return (((unsigned long)SDp->hostdata) & flag) == 0; } static inline void -NCR_700_set_flag(Scsi_Device *SDp, __u32 flag) +NCR_700_set_flag(struct scsi_device *SDp, __u32 flag) { SDp->hostdata = (void *)((long)SDp->hostdata | (flag & 0xffff0000)); } static inline void -NCR_700_clear_flag(Scsi_Device *SDp, __u32 flag) +NCR_700_clear_flag(struct scsi_device *SDp, __u32 flag) { SDp->hostdata = (void *)((long)SDp->hostdata & ~(flag & 0xffff0000)); } @@ -147,7 +150,7 @@ __u8 state; int tag; __u32 resume_offset; - Scsi_Cmnd *cmnd; + struct scsi_cmnd *cmnd; /* The pci_mapped address of the actual command in cmnd */ dma_addr_t pCmd; __u32 temp; @@ -185,7 +188,7 @@ __u32 pScript; /* physical mem addr of script */ enum NCR_700_Host_State state; /* protected by state lock */ - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; /* Note: pScript contains the single consistent block of * memory. All the msgin, msgout and status are allocated in * this memory too (at separate cache lines). TOTAL_MEM_SIZE diff -Nru a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c --- a/drivers/scsi/53c7xx.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/53c7xx.c 2004-06-20 13:00:26 -07:00 @@ -280,7 +280,7 @@ #endif #include "scsi.h" -#include "hosts.h" +#include #include "53c7xx.h" #include #include diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/BusLogic.c 2004-06-20 13:00:26 -07:00 @@ -48,7 +48,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "BusLogic.h" #include "FlashPoint.c" diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/Kconfig 2004-06-20 13:00:25 -07:00 @@ -227,7 +227,7 @@ depends on DECSTATION && SCSI config BLK_DEV_3W_XXXX_RAID - tristate "3ware Hardware ATA-RAID support" + tristate "3ware 5/6/7/8xxx ATA-RAID support" depends on PCI && SCSI help 3ware is the only hardware ATA-Raid product in Linux to date. @@ -239,6 +239,17 @@ Please read the comments at the top of . +config SCSI_3W_9XXX + tristate "3ware 9xxx SATA-RAID support" + depends on PCI && SCSI + help + This driver supports the 9000 series 3ware SATA-RAID cards. + + + + Please read the comments at the top of + . + config SCSI_7000FASST tristate "7000FASST SCSI support" depends on ISA && SCSI @@ -478,9 +489,7 @@ Adapters. Consult the SCSI-HOWTO, available from , and the files and - for more information. If this - driver does not work correctly without modification, please contact - the author, Leonard N. Zubkoff, by email to lnz@dandelion.com. + for more information. To compile this driver as a module, choose M here: the module will be called BusLogic. @@ -1715,18 +1724,6 @@ To compile this driver as a module, choose M here: the module will be called esp. - -config SCSI_PC980155 - tristate "NEC PC-9801-55 SCSI support" - depends on X86_PC9800 && SCSI - help - If you have the NEC PC-9801-55 SCSI interface card or compatibles - for NEC PC-9801/PC-9821, say Y. - -config WD33C93_PIO - bool - depends on SCSI_PC980155 - default y # bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile --- a/drivers/scsi/Makefile 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/Makefile 2004-06-20 13:00:25 -07:00 @@ -34,7 +34,6 @@ obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o -obj-$(CONFIG_SCSI_PC980155) += pc980155.o wd33c93.o obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o @@ -109,6 +108,7 @@ obj-$(CONFIG_SCSI_PLUTO) += pluto.o obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o +obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o @@ -142,7 +142,6 @@ scsi_devinfo.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o -scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o sd_mod-objs := sd.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/NCR53C9x.c 2004-06-20 13:00:23 -07:00 @@ -36,7 +36,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include @@ -3645,5 +3645,16 @@ esps_running = esps_in_use; } #endif + +EXPORT_SYMBOL(esp_abort); +EXPORT_SYMBOL(esp_allocate); +EXPORT_SYMBOL(esp_deallocate); +EXPORT_SYMBOL(esp_initialize); +EXPORT_SYMBOL(esp_intr); +EXPORT_SYMBOL(esp_queue); +EXPORT_SYMBOL(esp_reset); +EXPORT_SYMBOL(esp_slave_alloc); +EXPORT_SYMBOL(esp_slave_destroy); +EXPORT_SYMBOL(esps_in_use); MODULE_LICENSE("GPL"); diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c --- a/drivers/scsi/NCR53c406a.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/NCR53c406a.c 2004-06-20 13:00:24 -07:00 @@ -54,7 +54,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include /* ============================================================= */ diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c --- a/drivers/scsi/NCR_D700.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/NCR_D700.c 2004-06-20 13:00:23 -07:00 @@ -98,9 +98,7 @@ #include #include #include - -#include "scsi.h" -#include "hosts.h" +#include #include "53c700.h" #include "NCR_D700.h" @@ -156,7 +154,7 @@ /* Host template. The 53c700 routine NCR_700_detect will * fill in all of the missing routines */ -static Scsi_Host_Template NCR_D700_driver_template = { +static struct scsi_host_template NCR_D700_driver_template = { .module = THIS_MODULE, .name = "NCR Dual 700 MCA", .proc_name = "NCR_D700", diff -Nru a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c --- a/drivers/scsi/NCR_Q720.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/NCR_Q720.c 2004-06-20 13:00:23 -07:00 @@ -16,7 +16,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "ncr53c8xx.h" diff -Nru a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c --- a/drivers/scsi/a2091.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/a2091.c 2004-06-20 13:00:24 -07:00 @@ -16,7 +16,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "wd33c93.h" #include "a2091.h" diff -Nru a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c --- a/drivers/scsi/a3000.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/a3000.c 2004-06-20 13:00:25 -07:00 @@ -15,7 +15,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "wd33c93.h" #include "a3000.h" diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c --- a/drivers/scsi/advansys.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/advansys.c 2004-06-20 13:00:24 -07:00 @@ -756,27 +756,6 @@ */ - -/* - * --- Linux Version - */ - -#ifndef LINUX_VERSION_CODE -#include -#endif /* LINUX_VERSION_CODE */ - -/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ -#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) -#define ASC_LINUX_KERNEL22 (LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0)) -#define ASC_LINUX_KERNEL24 (LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,4,0)) - -/* Driver supported only in version 2.2 and version >= 2.4. */ -#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,2,0) || \ - (LINUX_VERSION_CODE > ASC_LINUX_VERSION(2,3,0) && \ - LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0)) -#error "AdvanSys driver supported only in 2.2 and 2.4 or greater kernels." -#endif - /* * --- Linux Include Files */ @@ -801,13 +780,14 @@ #include #include #include +#include #include #include #include #include "scsi.h" -#include "hosts.h" +#include #include "advansys.h" #ifdef CONFIG_PCI #include @@ -874,9 +854,6 @@ typedef unsigned char uchar; -#ifndef NULL -#define NULL (0) -#endif #ifndef TRUE #define TRUE (1) #endif @@ -986,49 +963,6 @@ #define ASC_MIN_SENSE_LEN 14 #define ASC_MAX_CDB_LEN 12 #define ASC_SCSI_RESET_HOLD_TIME_US 60 -#define SCSICMD_TestUnitReady 0x00 -#define SCSICMD_Rewind 0x01 -#define SCSICMD_Rezero 0x01 -#define SCSICMD_RequestSense 0x03 -#define SCSICMD_Format 0x04 -#define SCSICMD_FormatUnit 0x04 -#define SCSICMD_Read6 0x08 -#define SCSICMD_Write6 0x0A -#define SCSICMD_Seek6 0x0B -#define SCSICMD_Inquiry 0x12 -#define SCSICMD_Verify6 0x13 -#define SCSICMD_ModeSelect6 0x15 -#define SCSICMD_ModeSense6 0x1A -#define SCSICMD_StartStopUnit 0x1B -#define SCSICMD_LoadUnloadTape 0x1B -#define SCSICMD_ReadCapacity 0x25 -#define SCSICMD_Read10 0x28 -#define SCSICMD_Write10 0x2A -#define SCSICMD_Seek10 0x2B -#define SCSICMD_Erase10 0x2C -#define SCSICMD_WriteAndVerify10 0x2E -#define SCSICMD_Verify10 0x2F -#define SCSICMD_WriteBuffer 0x3B -#define SCSICMD_ReadBuffer 0x3C -#define SCSICMD_ReadLong 0x3E -#define SCSICMD_WriteLong 0x3F -#define SCSICMD_ReadTOC 0x43 -#define SCSICMD_ReadHeader 0x44 -#define SCSICMD_ModeSelect10 0x55 -#define SCSICMD_ModeSense10 0x5A - -/* Inquiry Data Peripheral Device Types */ -#define SCSI_TYPE_DASD 0x00 -#define SCSI_TYPE_SASD 0x01 -#define SCSI_TYPE_PRN 0x02 -#define SCSI_TYPE_PROC 0x03 -#define SCSI_TYPE_WORM 0x04 -#define SCSI_TYPE_CDROM 0x05 -#define SCSI_TYPE_SCANNER 0x06 -#define SCSI_TYPE_OPTMEM 0x07 -#define SCSI_TYPE_MED_CHG 0x08 -#define SCSI_TYPE_COMM 0x09 -#define SCSI_TYPE_UNKNOWN 0x1F #define ADV_INQ_CLOCKING_ST_ONLY 0x0 #define ADV_INQ_CLOCKING_DT_ONLY 0x1 @@ -1047,36 +981,11 @@ #define ASC_SCSIDIR_T2H 0x08 #define ASC_SCSIDIR_H2T 0x10 #define ASC_SCSIDIR_NODATA 0x18 -#define SCSI_SENKEY_NO_SENSE 0x00 -#define SCSI_SENKEY_UNDEFINED 0x01 -#define SCSI_SENKEY_NOT_READY 0x02 -#define SCSI_SENKEY_MEDIUM_ERR 0x03 -#define SCSI_SENKEY_HW_ERR 0x04 -#define SCSI_SENKEY_ILLEGAL 0x05 -#define SCSI_SENKEY_ATTENTION 0x06 -#define SCSI_SENKEY_PROTECTED 0x07 -#define SCSI_SENKEY_BLANK 0x08 -#define SCSI_SENKEY_V_UNIQUE 0x09 -#define SCSI_SENKEY_CPY_ABORT 0x0A -#define SCSI_SENKEY_ABORT 0x0B -#define SCSI_SENKEY_EQUAL 0x0C -#define SCSI_SENKEY_VOL_OVERFLOW 0x0D -#define SCSI_SENKEY_MISCOMP 0x0E -#define SCSI_SENKEY_RESERVED 0x0F #define SCSI_ASC_NOMEDIA 0x3A #define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4)) #define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F)) #define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13)) #define PUT_CDB1(x) ((uchar)((uint)(x) >> 8)) -#define SS_GOOD 0x00 -#define SS_CHK_CONDITION 0x02 -#define SS_CONDITION_MET 0x04 -#define SS_TARGET_BUSY 0x08 -#define SS_INTERMID 0x10 -#define SS_INTERMID_COND_MET 0x14 -#define SS_RSERV_CONFLICT 0x18 -#define SS_CMD_TERMINATED 0x22 -#define SS_QUEUE_FULL 0x28 #define MS_CMD_DONE 0x00 #define MS_EXTEND 0x01 #define MS_SDTR_LEN 0x03 @@ -1085,26 +994,6 @@ #define MS_WDTR_CODE 0x03 #define MS_MDP_LEN 0x05 #define MS_MDP_CODE 0x00 -#define M1_SAVE_DATA_PTR 0x02 -#define M1_RESTORE_PTRS 0x03 -#define M1_DISCONNECT 0x04 -#define M1_INIT_DETECTED_ERR 0x05 -#define M1_ABORT 0x06 -#define M1_MSG_REJECT 0x07 -#define M1_NO_OP 0x08 -#define M1_MSG_PARITY_ERR 0x09 -#define M1_LINK_CMD_DONE 0x0A -#define M1_LINK_CMD_DONE_WFLAG 0x0B -#define M1_BUS_DVC_RESET 0x0C -#define M1_ABORT_TAG 0x0D -#define M1_CLR_QUEUE 0x0E -#define M1_INIT_RECOVERY 0x0F -#define M1_RELEASE_RECOVERY 0x10 -#define M1_KILL_IO_PROC 0x11 -#define M2_QTAG_MSG_SIMPLE 0x20 -#define M2_QTAG_MSG_HEAD 0x21 -#define M2_QTAG_MSG_ORDERED 0x22 -#define M2_IGNORE_WIDE_RESIDUE 0x23 /* * Inquiry data structure and bitfield macros @@ -1576,7 +1465,7 @@ uchar sdtr_period_offset[ASC_MAX_TID + 1]; ushort pci_slot_info; uchar adapter_info[6]; - struct pci_dev *pci_dev; + struct device *dev; } ASC_DVC_CFG; #define ASC_DEF_DVC_CNTL 0xFFFF @@ -3082,7 +2971,7 @@ ushort serial1; /* EEPROM serial number word 1 */ ushort serial2; /* EEPROM serial number word 2 */ ushort serial3; /* EEPROM serial number word 3 */ - struct pci_dev *pci_dev; /* pointer to the pci dev structure for this board */ + struct device *dev; /* pointer to the pci dev structure for this board */ } ADV_DVC_CFG; struct adv_dvc_var; @@ -3581,19 +3470,6 @@ #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ -/* - * If the Linux kernel version supports freeing initialization code - * and data after loading, define macros for this purpose. These macros - * are not used when the driver is built as a module, cf. linux/init.h. - */ -#if ASC_LINUX_KERNEL24 -#define ASC_INITFUNC(type, func) type __init func -#elif ASC_LINUX_KERNEL22 -#define ASC_INITFUNC(type, func) __initfunc(type func) -#endif -#define ASC_INITDATA __initdata -#define ASC_INIT __init - #define ASC_INFO_SIZE 128 /* advansys_info() line size */ #ifdef CONFIG_PROC_FS @@ -3610,8 +3486,6 @@ } \ cp += len; \ } - -#define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif /* CONFIG_PROC_FS */ /* Asc Library return codes */ @@ -3685,53 +3559,6 @@ /* Return non-zero, if the queue is empty. */ #define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0) -/* PCI configuration declarations */ - -#define PCI_BASE_CLASS_PREDEFINED 0x00 -#define PCI_BASE_CLASS_MASS_STORAGE 0x01 -#define PCI_BASE_CLASS_NETWORK 0x02 -#define PCI_BASE_CLASS_DISPLAY 0x03 -#define PCI_BASE_CLASS_MULTIMEDIA 0x04 -#define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05 -#define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06 - -/* MASS STORAGE */ -#define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00 -#define PCI_SUB_CLASS_IDE_CONTROLLER 0x01 -#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02 -#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03 -#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80 - -/* NETWORK CONTROLLER */ -#define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00 -#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01 -#define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02 -#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80 - -/* DISPLAY CONTROLLER */ -#define PCI_SUB_CLASS_VGA_CONTROLLER 0x00 -#define PCI_SUB_CLASS_XGA_CONTROLLER 0x01 -#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80 - -/* MULTIMEDIA CONTROLLER */ -#define PCI_SUB_CLASS_VIDEO_DEVICE 0x00 -#define PCI_SUB_CLASS_AUDIO_DEVICE 0x01 -#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80 - -/* MEMORY CONTROLLER */ -#define PCI_SUB_CLASS_RAM_CONTROLLER 0x00 -#define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01 -#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80 - -/* BRIDGE CONTROLLER */ -#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00 -#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01 -#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02 -#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03 -#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04 -#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05 -#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80 - #define PCI_MAX_SLOT 0x1F #define PCI_MAX_BUS 0xFF #define PCI_IOADDRESS_MASK 0xFFFE @@ -3744,25 +3571,6 @@ #define ASC_PCI_DEVICE_ID_2500 0x2500 /* ASC-38C0800 */ #define ASC_PCI_DEVICE_ID_2700 0x2700 /* ASC-38C1600 */ -/* PCI IO Port Addresses to generate special cycle */ - -#define PCI_CONFIG_ADDRESS_MECH1 0x0CF8 -#define PCI_CONFIG_DATA_MECH1 0x0CFC - -#define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */ - -#define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000 -#define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00 -#define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8 - -#define PCI_DEVICE_FOUND 0x0000 -#define PCI_DEVICE_NOT_FOUND 0xffff - -#define SUBCLASS_OFFSET 0x0A -#define CLASSCODE_OFFSET 0x0B -#define VENDORID_OFFSET 0x00 -#define DEVICEID_OFFSET 0x02 - #ifndef ADVANSYS_STATS #define ASC_STATS(shp, counter) #define ASC_STATS_ADD(shp, counter, count) @@ -4145,19 +3953,6 @@ /* Note: All driver global data should be initialized. */ -#if ASC_LINUX_KERNEL22 -#ifdef CONFIG_PROC_FS -struct proc_dir_entry proc_scsi_advansys = -{ - PROC_SCSI_ADVANSYS, /* unsigned short low_ino */ - 8, /* unsigned short namelen */ - "advansys", /* const char *name */ - S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */ - 2 /* nlink_t nlink */ -}; -#endif /* CONFIG_PROC_FS */ -#endif /* ASC_LINUX_KERNEL22 */ - /* Number of boards detected in system. */ STATIC int asc_board_count = 0; STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 }; @@ -4172,7 +3967,7 @@ STATIC ASC_SG_HEAD asc_sg_head = { 0 }; /* List of supported bus types. */ -STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = { +STATIC ushort asc_bus[ASC_NUM_BUS] __initdata = { ASC_IS_ISA, ASC_IS_VL, ASC_IS_EISA, @@ -4210,11 +4005,11 @@ STATIC irqreturn_t advansys_interrupt(int, void *, struct pt_regs *); STATIC int advansys_slave_configure(Scsi_Device *); -STATIC void asc_scsi_done_list(Scsi_Cmnd *, int from_isr); +STATIC void asc_scsi_done_list(Scsi_Cmnd *); STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *); STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *); STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **); -STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *); +STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *, int); STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); STATIC void adv_async_callback(ADV_DVC_VAR *, uchar); @@ -4505,10 +4300,8 @@ * it must not call SCSI mid-level functions including scsi_malloc() * and scsi_free(). */ -ASC_INITFUNC( -int, +int __init advansys_detect(Scsi_Host_Template *tpnt) -) { static int detect_called = ASC_FALSE; int iop; @@ -4526,6 +4319,7 @@ struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED]; int pci_card_cnt_max = 0; int pci_card_cnt = 0; + struct device *dev = NULL; struct pci_dev *pci_devp = NULL; int pci_device_id_cnt = 0; unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { @@ -4550,12 +4344,6 @@ ASC_DBG(1, "advansys_detect: begin\n"); -#if ASC_LINUX_KERNEL24 - tpnt->proc_name = "advansys"; -#elif ASC_LINUX_KERNEL22 - tpnt->proc_dir = &proc_scsi_advansys; -#endif - asc_board_count = 0; /* @@ -4681,13 +4469,9 @@ NULL) { pci_device_id_cnt++; } else { -#if ASC_LINUX_KERNEL24 if (pci_enable_device(pci_devp) == 0) { pci_devicep[pci_card_cnt_max++] = pci_devp; } -#elif ASC_LINUX_KERNEL22 - pci_devicep[pci_card_cnt_max++] = pci_devp; -#endif } } @@ -4724,17 +4508,16 @@ ASC_DBG2(2, "advansys_detect: devfn %d, bus number %d\n", pci_devp->devfn, pci_devp->bus->number); -#if ASC_LINUX_KERNEL24 iop = pci_resource_start(pci_devp, 0); -#elif ASC_LINUX_KERNEL22 - iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK; -#endif ASC_DBG2(1, "advansys_detect: vendorID %X, deviceID %X\n", pci_devp->vendor, pci_devp->device); ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", iop, pci_devp->irq); } + if(pci_devp) + dev = &pci_devp->dev; + #endif /* CONFIG_PCI */ break; @@ -4765,7 +4548,7 @@ continue; } - scsi_set_device(shp, &pci_devp->dev); + scsi_set_device(shp, dev); /* Save a pointer to the Scsi_Host of each board found. */ asc_host[asc_board_count++] = shp; @@ -4849,11 +4632,7 @@ iolen = ADV_38C1600_IOLEN; } #ifdef CONFIG_PCI -#if ASC_LINUX_KERNEL24 pci_memory_address = pci_resource_start(pci_devp, 1); -#elif ASC_LINUX_KERNEL22 - pci_memory_address = pci_devp->base_address[1]; -#endif ASC_DBG1(1, "advansys_detect: pci_memory_address: 0x%lx\n", (ulong) pci_memory_address); if ((boardp->ioremap_addr = @@ -4904,7 +4683,8 @@ #endif /* CONFIG_PROC_FS */ if (ASC_NARROW_BOARD(boardp)) { - /* + asc_dvc_varp->cfg->dev = dev; + /* * Set the board bus type and PCI IRQ before * calling AscInitGetConfig(). */ @@ -4926,7 +4706,6 @@ #ifdef CONFIG_PCI case ASC_IS_PCI: shp->irq = asc_dvc_varp->irq_no = pci_devp->irq; - asc_dvc_varp->cfg->pci_dev = pci_devp; asc_dvc_varp->cfg->pci_slot_info = ASC_PCI_MKID(pci_devp->bus->number, PCI_SLOT(pci_devp->devfn), @@ -4944,13 +4723,13 @@ break; } } else { + adv_dvc_varp->cfg->dev = dev; /* * For Wide boards set PCI information before calling * AdvInitGetConfig(). */ #ifdef CONFIG_PCI shp->irq = adv_dvc_varp->irq_no = pci_devp->irq; - adv_dvc_varp->cfg->pci_dev = pci_devp; adv_dvc_varp->cfg->pci_slot_info = ASC_PCI_MKID(pci_devp->bus->number, PCI_SLOT(pci_devp->devfn), @@ -5321,11 +5100,7 @@ /* BIOS start address. */ if (ASC_NARROW_BOARD(boardp)) { -#if ASC_LINUX_KERNEL24 shp->base = -#elif ASC_LINUX_KERNEL22 - shp->base = (char *) -#endif ((ulong) AscGetChipBiosAddress( asc_dvc_varp->iop_base, asc_dvc_varp->bus_type)); @@ -5360,11 +5135,7 @@ * Convert x86 realmode code segment to a linear * address by shifting left 4. */ - shp->base = -#if ASC_LINUX_KERNEL22 - (char *) -#endif - ((ulong) boardp->bios_codeseg << 4); + shp->base = ((ulong) boardp->bios_codeseg << 4); } else { shp->base = 0; } @@ -5385,7 +5156,6 @@ ASC_DBG2(2, "advansys_detect: request_region port 0x%lx, len 0x%x\n", (ulong) shp->io_port, boardp->asc_n_io_port); -#if ASC_LINUX_KERNEL24 if (request_region(shp->io_port, boardp->asc_n_io_port, "advansys") == NULL) { ASC_PRINT3( @@ -5398,9 +5168,6 @@ asc_board_count--; continue; } -#elif ASC_LINUX_KERNEL22 - request_region(shp->io_port, boardp->asc_n_io_port, "advansys"); -#endif /* Register DMA Channel for Narrow boards. */ shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ @@ -5880,7 +5647,7 @@ default: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); /* Interrupts could be enabled here. */ - asc_scsi_done_list(done_scp, 0); + asc_scsi_done_list(done_scp); break; } spin_unlock_irqrestore(&boardp->lock, flags); @@ -6063,7 +5830,7 @@ * Complete all the 'done_scp' requests. */ if (done_scp != NULL) { - asc_scsi_done_list(done_scp, 0); + asc_scsi_done_list(done_scp); } ASC_DBG1(1, "advansys_reset: ret %d\n", ret); @@ -6149,10 +5916,8 @@ * ints[2] - second argument * ... */ -ASC_INITFUNC( -void, +void __init advansys_setup(char *str, int *ints) -) { int i; @@ -6328,7 +6093,7 @@ * Complete all requests on the done list. */ - asc_scsi_done_list(done_scp, 1); + asc_scsi_done_list(done_scp); ASC_DBG(1, "advansys_interrupt: end\n"); return IRQ_HANDLED; @@ -6374,23 +6139,38 @@ * Interrupts can be enabled on entry. */ STATIC void -asc_scsi_done_list(Scsi_Cmnd *scp, int from_isr) +asc_scsi_done_list(Scsi_Cmnd *scp) { Scsi_Cmnd *tscp; - ulong flags = 0; ASC_DBG(2, "asc_scsi_done_list: begin\n"); while (scp != NULL) { + asc_board_t *boardp; + struct device *dev; + ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp); tscp = REQPNEXT(scp); scp->host_scribble = NULL; + + boardp = ASC_BOARDP(scp->device->host); + + if (ASC_NARROW_BOARD(boardp)) + dev = boardp->dvc_cfg.asc_dvc_cfg.dev; + else + dev = boardp->dvc_cfg.adv_dvc_cfg.dev; + + if (scp->use_sg) + dma_unmap_sg(dev, (struct scatterlist *)scp->request_buffer, + scp->use_sg, scp->sc_data_direction); + else if (scp->request_bufflen) + dma_unmap_single(dev, scp->SCp.dma_handle, + scp->request_bufflen, scp->sc_data_direction); + ASC_STATS(scp->device->host, done); ASC_ASSERT(scp->scsi_done != NULL); - if (from_isr) - spin_lock_irqsave(scp->device->host->host_lock, flags); + scp->scsi_done(scp); - if (from_isr) - spin_unlock_irqrestore(scp->device->host->host_lock, flags); + scp = tscp; } ASC_DBG(2, "asc_scsi_done_list: done\n"); @@ -6619,6 +6399,8 @@ STATIC int asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp) { + struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev; + /* * Mutually exclusive access is required to 'asc_scsi_q' and * 'asc_sg_head' until after the request is started. @@ -6665,9 +6447,9 @@ */ if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && (boardp->reqcnt[scp->device->id] % 255) == 0) { - asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED; + asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; } else { - asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE; + asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; } /* @@ -6679,8 +6461,10 @@ * CDB request of single contiguous buffer. */ ASC_STATS(scp->device->host, cont_cnt); - asc_scsi_q.q1.data_addr = - cpu_to_le32(virt_to_bus(scp->request_buffer)); + scp->SCp.dma_handle = scp->request_bufflen ? + dma_map_single(dev, scp->request_buffer, + scp->request_bufflen, scp->sc_data_direction) : 0; + asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); ASC_STATS_ADD(scp->device->host, cont_xfer, ASC_CEILING(scp->request_bufflen, 512)); @@ -6691,12 +6475,17 @@ * CDB scatter-gather request list. */ int sgcnt; + int use_sg; struct scatterlist *slp; - if (scp->use_sg > scp->device->host->sg_tablesize) { + slp = (struct scatterlist *)scp->request_buffer; + use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); + + if (use_sg > scp->device->host->sg_tablesize) { ASC_PRINT3( "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", - boardp->id, scp->use_sg, scp->device->host->sg_tablesize); + boardp->id, use_sg, scp->device->host->sg_tablesize); + dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction); scp->result = HOST_BYTE(DID_ERROR); asc_enqueue(&boardp->done, scp, ASC_BACK); return ASC_ERROR; @@ -6715,19 +6504,16 @@ asc_scsi_q.q1.data_cnt = 0; asc_scsi_q.q1.data_addr = 0; /* This is a byte value, otherwise it would need to be swapped. */ - asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg; + asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; ASC_STATS_ADD(scp->device->host, sg_elem, asc_sg_head.entry_cnt); /* * Convert scatter-gather list into ASC_SG_HEAD list. */ - slp = (struct scatterlist *) scp->request_buffer; - for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) { - asc_sg_head.sg_list[sgcnt].addr = - cpu_to_le32(virt_to_bus( - (unsigned char *)page_address(slp->page) + slp->offset)); - asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(slp->length); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(slp->length, 512)); + for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { + asc_sg_head.sg_list[sgcnt].addr = cpu_to_le32(sg_dma_address(slp)); + asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); } } @@ -6755,6 +6541,7 @@ ADV_SCSI_REQ_Q *scsiqp; int i; int ret; + struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; /* * Allocate an adv_req_t structure from the board to execute @@ -6827,15 +6614,23 @@ * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather * buffer command. */ - scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - scsiqp->vdata_addr = scp->request_buffer; - scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); if (scp->use_sg == 0) { /* * CDB request of single contiguous buffer. */ reqp->sgblkp = NULL; + scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); + if (scp->request_bufflen) { + scsiqp->vdata_addr = scp->request_buffer; + scp->SCp.dma_handle = + dma_map_single(dev, scp->request_buffer, + scp->request_bufflen, scp->sc_data_direction); + } else { + scsiqp->vdata_addr = 0; + scp->SCp.dma_handle = 0; + } + scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); scsiqp->sg_list_ptr = NULL; scsiqp->sg_real_addr = 0; ASC_STATS(scp->device->host, cont_cnt); @@ -6845,10 +6640,21 @@ /* * CDB scatter-gather request list. */ - if (scp->use_sg > ADV_MAX_SG_LIST) { + struct scatterlist *slp; + int use_sg; + + scsiqp->data_cnt = 0; + scsiqp->vdata_addr = 0; + scsiqp->data_addr = 0; + + slp = (struct scatterlist *)scp->request_buffer; + use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); + + if (use_sg > ADV_MAX_SG_LIST) { ASC_PRINT3( "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", - boardp->id, scp->use_sg, scp->device->host->sg_tablesize); + boardp->id, use_sg, scp->device->host->sg_tablesize); + dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction); scp->result = HOST_BYTE(DID_ERROR); asc_enqueue(&boardp->done, scp, ASC_BACK); @@ -6862,7 +6668,7 @@ return ASC_ERROR; } - if ((ret = adv_get_sglist(boardp, reqp, scp)) != ADV_SUCCESS) { + if ((ret = adv_get_sglist(boardp, reqp, scp, use_sg)) != ADV_SUCCESS) { /* * Free the adv_req_t structure by adding it back to the * board free list. @@ -6874,7 +6680,7 @@ } ASC_STATS(scp->device->host, sg_cnt); - ASC_STATS_ADD(scp->device->host, sg_elem, scp->use_sg); + ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); } ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); @@ -6898,7 +6704,7 @@ * ADV_ERROR(-1) - SG List creation failed */ STATIC int -adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, Scsi_Cmnd *scp) +adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, Scsi_Cmnd *scp, int use_sg) { adv_sgblk_t *sgblkp; ADV_SCSI_REQ_Q *scsiqp; @@ -6910,7 +6716,7 @@ scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q); slp = (struct scatterlist *) scp->request_buffer; - sg_elem_cnt = scp->use_sg; + sg_elem_cnt = use_sg; prev_sg_block = NULL; reqp->sgblkp = NULL; @@ -6982,11 +6788,9 @@ for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { - sg_block->sg_list[i].sg_addr = - cpu_to_le32(virt_to_bus( - (unsigned char *)page_address(slp->page) + slp->offset)); - sg_block->sg_list[i].sg_count = cpu_to_le32(slp->length); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(slp->length, 512)); + sg_block->sg_list[i].sg_addr = cpu_to_le32(sg_dma_address(slp)); + sg_block->sg_list[i].sg_count = cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ @@ -7079,14 +6883,13 @@ * If an INQUIRY command completed successfully, then call * the AscInquiryHandling() function to set-up the device. */ - if (scp->cmnd[0] == SCSICMD_Inquiry && scp->device->lun == 0 && + if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 && (scp->request_bufflen - qdonep->remain_bytes) >= 8) { AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7, (ASC_SCSI_INQUIRY *) scp->request_buffer); } -#if ASC_LINUX_KERNEL24 /* * Check for an underrun condition. * @@ -7099,15 +6902,14 @@ (unsigned) qdonep->remain_bytes); scp->resid = qdonep->remain_bytes; } -#endif break; case QD_WITH_ERROR: ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); switch (qdonep->d3.host_stat) { case QHSTA_NO_ERROR: - if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) { - ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n"); + if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); ASC_DBG_PRT_SENSE(2, scp->sense_buffer, sizeof(scp->sense_buffer)); /* @@ -7185,9 +6987,7 @@ Scsi_Cmnd *scp; struct Scsi_Host *shp; int i; -#if ASC_LINUX_KERNEL24 ADV_DCNT resid_cnt; -#endif ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", @@ -7270,7 +7070,6 @@ ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); scp->result = 0; -#if ASC_LINUX_KERNEL24 /* * Check for an underrun condition. * @@ -7284,15 +7083,14 @@ (ulong) resid_cnt); scp->resid = resid_cnt; } -#endif break; case QD_WITH_ERROR: ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); switch (scsiqp->host_status) { case QHSTA_NO_ERROR: - if (scsiqp->scsi_status == SS_CHK_CONDITION) { - ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n"); + if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); ASC_DBG_PRT_SENSE(2, scp->sense_buffer, sizeof(scp->sense_buffer)); /* @@ -8858,7 +8656,7 @@ (unsigned) offset, (unsigned) advoffset, cplen); if (offset <= advoffset) { /* Read offset below current offset, copy everything. */ - cnt = ASC_MIN(cplen, leftlen); + cnt = min(cplen, leftlen); ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", (ulong) curbuf, (ulong) cp, cnt); memcpy(curbuf, cp, cnt); @@ -8866,7 +8664,7 @@ /* Read offset within current range, partial copy. */ cnt = (advoffset + cplen) - offset; cp = (cp + cplen) - cnt; - cnt = ASC_MIN(cnt, leftlen); + cnt = min(cnt, leftlen); ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", (ulong) curbuf, (ulong) cp, cnt); memcpy(curbuf, cp, cnt); @@ -8899,7 +8697,7 @@ (void) printk(s); ret = 0; } else { - ret = ASC_MIN(buflen, ret); + ret = min(buflen, ret); memcpy(buf, s, ret); } va_end(args); @@ -9002,16 +8800,14 @@ /* * Read a PCI configuration byte. */ -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init DvcReadPCIConfigByte( ASC_DVC_VAR *asc_dvc, ushort offset) -) { #ifdef CONFIG_PCI uchar byte_data; - pci_read_config_byte(asc_dvc->cfg->pci_dev, offset, &byte_data); + pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); return byte_data; #else /* !defined(CONFIG_PCI) */ return 0; @@ -9021,16 +8817,14 @@ /* * Write a PCI configuration byte. */ -ASC_INITFUNC( -STATIC void, +STATIC void __init DvcWritePCIConfigByte( ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) -) { #ifdef CONFIG_PCI - pci_write_config_byte(asc_dvc->cfg->pci_dev, offset, byte_data); + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); #endif /* CONFIG_PCI */ } @@ -9038,13 +8832,10 @@ * Return the BIOS address of the adapter at the specified * I/O port and with the specified bus type. */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscGetChipBiosAddress( PortAddr iop_base, - ushort bus_type -) -) + ushort bus_type) { ushort cfg_lsw; ushort bios_addr; @@ -9119,16 +8910,14 @@ /* * Read a PCI configuration byte. */ -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init DvcAdvReadPCIConfigByte( ADV_DVC_VAR *asc_dvc, ushort offset) -) { #ifdef CONFIG_PCI uchar byte_data; - pci_read_config_byte(asc_dvc->cfg->pci_dev, offset, &byte_data); + pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); return byte_data; #else /* CONFIG_PCI */ return 0; @@ -9138,16 +8927,14 @@ /* * Write a PCI configuration byte. */ -ASC_INITFUNC( -STATIC void, +STATIC void __init DvcAdvWritePCIConfigByte( ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) -) { #ifdef CONFIG_PCI - pci_write_config_byte(asc_dvc->cfg->pci_dev, offset, byte_data); + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); #else /* CONFIG_PCI */ return 0; #endif /* CONFIG_PCI */ @@ -9358,16 +9145,6 @@ s->host_busy, s->host_no, (unsigned) s->last_reset); -#if ASC_LINUX_KERNEL24 - printk( -" hostt 0x%lx\n", - (ulong) s->hostt); -#elif ASC_LINUX_KERNEL22 - printk( -" host_queue 0x%lx, hostt 0x%lx, block 0x%lx,\n", - (ulong) s->host_queue, (ulong) s->hostt, (ulong) s->block); -#endif - printk( " base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n", (ulong) s->base, (ulong) s->io_port, s->n_io_port, s->irq); @@ -9404,11 +9181,9 @@ asc_prt_hex(" CDB", s->cmnd, s->cmd_len); -#if ASC_LINUX_KERNEL24 printk ( "sc_data_direction %u, resid %d\n", s->sc_data_direction, s->resid); -#endif printk( " use_sg %u, sglist_len %u, abort_reason 0x%x\n", @@ -9423,15 +9198,9 @@ " timeout_per_command %d, timeout_total %d, timeout %d\n", s->timeout_per_command, s->timeout_total, s->timeout); -#if ASC_LINUX_KERNEL24 printk( " internal_timeout %u, flags %u\n", s->internal_timeout, s->flags); -#elif ASC_LINUX_KERNEL22 - printk( -" internal_timeout %u, flags %u, this_count %d\n", - s->internal_timeout, s->flags,s->this_count); -#endif printk( " scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", @@ -9507,7 +9276,8 @@ printk( " pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", - h->pci_dev->device, h->lib_serial_no, h->lib_version, h->mcode_date); + to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, + h->mcode_date); printk( " mcode_version %d, overrun_buf 0x%lx\n", @@ -9632,7 +9402,7 @@ printk( " mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", - h->mcode_version, h->pci_dev->device, h->lib_version); + h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); printk( " control_flag 0x%x, pci_slot_info 0x%x\n", @@ -9787,12 +9557,9 @@ * --- Asc Library Functions */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscGetEisaChipCfg( - PortAddr iop_base -) -) + PortAddr iop_base) { PortAddr eisa_cfg_iop; @@ -9801,13 +9568,11 @@ return (inpw(eisa_cfg_iop)); } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscSetChipScsiID( PortAddr iop_base, uchar new_host_id ) -) { ushort cfg_lsw; @@ -9821,12 +9586,9 @@ return (AscGetChipScsiID(iop_base)); } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscGetChipScsiCtrl( - PortAddr iop_base -) -) + PortAddr iop_base) { uchar sc; @@ -9836,13 +9598,11 @@ return (sc); } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscGetChipVersion( PortAddr iop_base, ushort bus_type ) -) { if ((bus_type & ASC_IS_EISA) != 0) { PortAddr eisa_iop; @@ -9855,12 +9615,9 @@ return (AscGetChipVerNo(iop_base)); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscGetChipBusType( - PortAddr iop_base -) -) + PortAddr iop_base) { ushort chip_ver; @@ -9940,22 +9697,19 @@ return (0); } -STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA = +STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = { 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 }; #ifdef CONFIG_ISA -STATIC uchar _isa_pnp_inited ASC_INITDATA = 0; +STATIC uchar _isa_pnp_inited __initdata = 0; -ASC_INITFUNC( -STATIC PortAddr, +STATIC PortAddr __init AscSearchIOPortAddr( PortAddr iop_beg, - ushort bus_type -) -) + ushort bus_type) { if (bus_type & ASC_IS_VL) { while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { @@ -9986,12 +9740,10 @@ return (0); } -ASC_INITFUNC( -STATIC PortAddr, +STATIC PortAddr __init AscSearchIOPortAddr11( PortAddr s_addr ) -) { int i; PortAddr iop_base; @@ -10017,11 +9769,8 @@ return (0); } -ASC_INITFUNC( -STATIC void, -AscSetISAPNPWaitForKey( - void) -) +STATIC void __init +AscSetISAPNPWaitForKey(void) { outp(ASC_ISA_PNP_PORT_ADDR, 0x02); outp(ASC_ISA_PNP_PORT_WRITE, 0x02); @@ -10029,25 +9778,20 @@ } #endif /* CONFIG_ISA */ -ASC_INITFUNC( -STATIC void, +STATIC void __init AscToggleIRQAct( PortAddr iop_base ) -) { AscSetChipStatus(iop_base, CIW_IRQ_ACT); AscSetChipStatus(iop_base, 0); return; } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscGetChipIRQ( PortAddr iop_base, - ushort bus_type -) -) + ushort bus_type) { ushort cfg_lsw; uchar chip_irq; @@ -10077,14 +9821,11 @@ return ((uchar) (chip_irq + ASC_MIN_IRQ_NO)); } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscSetChipIRQ( PortAddr iop_base, uchar irq_no, - ushort bus_type -) -) + ushort bus_type) { ushort cfg_lsw; @@ -10119,12 +9860,9 @@ } #ifdef CONFIG_ISA -ASC_INITFUNC( -STATIC void, +STATIC void __init AscEnableIsaDma( - uchar dma_channel -) -) + uchar dma_channel) { if (dma_channel < 4) { outp(0x000B, (ushort) (0xC0 | dma_channel)); @@ -10285,7 +10023,7 @@ return (0); } else { - ext_msg.msg_type = M1_MSG_REJECT; + ext_msg.msg_type = MESSAGE_REJECT; AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG, (uchar *) &ext_msg, @@ -10385,7 +10123,7 @@ (ushort) ASCV_SCSIBUSY_B, scsi_busy); asc_dvc->queue_full_or_busy |= target_id; - if (scsi_status == SS_QUEUE_FULL) { + if (scsi_status == SAM_STAT_TASK_SET_FULL) { if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { cur_dvc_qng -= 1; asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng; @@ -10732,7 +10470,7 @@ } else { if ((AscReadLramByte(iop_base, (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) == - SCSICMD_StartStopUnit)) { + START_STOP)) { asc_dvc->unit_not_ready &= ~target_id; if (scsiq->d3.done_stat != QD_NO_ERROR) { asc_dvc->start_motor &= ~target_id; @@ -11005,14 +10743,14 @@ #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { - SCSICMD_Inquiry, - SCSICMD_RequestSense, - SCSICMD_ReadCapacity, - SCSICMD_ReadTOC, - SCSICMD_ModeSelect6, - SCSICMD_ModeSense6, - SCSICMD_ModeSelect10, - SCSICMD_ModeSense10, + INQUIRY, + REQUEST_SENSE, + READ_CAPACITY, + READ_TOC, + MODE_SELECT, + MODE_SENSE, + MODE_SELECT_10, + MODE_SENSE_10, 0xFF, 0xFF, 0xFF, @@ -11065,7 +10803,7 @@ target_ix = scsiq->q2.target_ix; tid_no = ASC_TIX_TO_TID(target_ix); n_q_required = 1; - if (scsiq->cdbptr[0] == SCSICMD_RequestSense) { + if (scsiq->cdbptr[0] == REQUEST_SENSE) { if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { asc_dvc->sdtr_done &= ~scsiq->q1.target_id; sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); @@ -11134,7 +10872,7 @@ } } if (disable_syn_offset_one_fix) { - scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE; + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | ASC_TAG_FLAG_DISABLE_DISCONNECT); } else { @@ -11143,8 +10881,8 @@ if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { if (asc_dvc->bug_fix_cntl) { if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == SCSICMD_Read6) || - (scsi_cmd == SCSICMD_Read10)) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { addr = (ADV_PADDR) le32_to_cpu( sg_head->sg_list[sg_entry_cnt_minus_one].addr) + @@ -11193,8 +10931,8 @@ } else { if (asc_dvc->bug_fix_cntl) { if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == SCSICMD_Read6) || - (scsi_cmd == SCSICMD_Read10)) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { addr = le32_to_cpu(scsiq->q1.data_addr) + le32_to_cpu(scsiq->q1.data_cnt); extra_bytes = (uchar) ((ushort) addr & 0x0003); @@ -11365,7 +11103,7 @@ } q_addr = ASC_QNO_TO_QADDR(q_no); if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { - scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE; + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG ; } scsiq->q1.status = QS_FREE; AscMemWordCopyPtrToLram(iop_base, @@ -11862,12 +11600,9 @@ } #ifdef CONFIG_ISA -ASC_INITFUNC( -STATIC ASC_DCNT, +STATIC ASC_DCNT __init AscGetEisaProductID( - PortAddr iop_base -) -) + PortAddr iop_base) { PortAddr eisa_iop; ushort product_id_high, product_id_low; @@ -11881,12 +11616,9 @@ return (product_id); } -ASC_INITFUNC( -STATIC PortAddr, +STATIC PortAddr __init AscSearchIOPortAddrEISA( - PortAddr iop_base -) -) + PortAddr iop_base) { ASC_DCNT eisa_product_id; @@ -12080,12 +11812,9 @@ return (AscIsChipHalted(iop_base)); } -ASC_INITFUNC( -STATIC ASC_DCNT, +STATIC ASC_DCNT __init AscGetMaxDmaCount( - ushort bus_type -) -) + ushort bus_type) { if (bus_type & ASC_IS_ISA) return (ASC_MAX_ISA_DMA_COUNT); @@ -12095,12 +11824,9 @@ } #ifdef CONFIG_ISA -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscGetIsaDmaChannel( - PortAddr iop_base -) -) + PortAddr iop_base) { ushort channel; @@ -12112,13 +11838,10 @@ return (channel + 4); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscSetIsaDmaChannel( PortAddr iop_base, - ushort dma_channel -) -) + ushort dma_channel) { ushort cfg_lsw; uchar value; @@ -12136,13 +11859,10 @@ return (0); } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscSetIsaDmaSpeed( PortAddr iop_base, - uchar speed_value -) -) + uchar speed_value) { speed_value &= 0x07; AscSetBank(iop_base, 1); @@ -12151,12 +11871,10 @@ return (AscGetIsaDmaSpeed(iop_base)); } -ASC_INITFUNC( -STATIC uchar, +STATIC uchar __init AscGetIsaDmaSpeed( PortAddr iop_base ) -) { uchar speed_value; @@ -12168,12 +11886,10 @@ } #endif /* CONFIG_ISA */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscReadPCIConfigWord( ASC_DVC_VAR *asc_dvc, ushort pci_config_offset) -) { uchar lsb, msb; @@ -12182,12 +11898,10 @@ return ((ushort) ((msb << 8) | lsb)); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscInitGetConfig( ASC_DVC_VAR *asc_dvc ) -) { ushort warn_code; PortAddr iop_base; @@ -12267,12 +11981,10 @@ return(warn_code); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscInitSetConfig( ASC_DVC_VAR *asc_dvc ) -) { ushort warn_code = 0; @@ -12288,12 +12000,10 @@ return (warn_code); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscInitFromAscDvcVar( ASC_DVC_VAR *asc_dvc ) -) { PortAddr iop_base; ushort cfg_msw; @@ -12301,7 +12011,7 @@ ushort pci_device_id; iop_base = asc_dvc->iop_base; - pci_device_id = asc_dvc->cfg->pci_dev->device; + pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device; warn_code = 0; cfg_msw = AscGetChipCfgMsw(iop_base); if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { @@ -12393,12 +12103,9 @@ return (warn_code); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscInitAscDvcVar( - ASC_DVC_VAR *asc_dvc -) -) + ASC_DVC_VAR *asc_dvc) { int i; PortAddr iop_base; @@ -12508,12 +12215,8 @@ return (warn_code); } -ASC_INITFUNC( -STATIC ushort, -AscInitFromEEP( - ASC_DVC_VAR *asc_dvc -) -) +STATIC ushort __init +AscInitFromEEP(ASC_DVC_VAR *asc_dvc) { ASCEEP_CONFIG eep_config_buf; ASCEEP_CONFIG *eep_config; @@ -12729,12 +12432,9 @@ return (warn_code); } -ASC_INITFUNC( -STATIC int, +STATIC int __init AscTestExternalLram( - ASC_DVC_VAR *asc_dvc -) -) + ASC_DVC_VAR *asc_dvc) { PortAddr iop_base; ushort q_addr; @@ -12756,13 +12456,11 @@ return (sta); } -ASC_INITFUNC( -STATIC int, +STATIC int __init AscWriteEEPCmdReg( PortAddr iop_base, uchar cmd_reg ) -) { uchar read_back; int retry; @@ -12781,13 +12479,11 @@ } } -ASC_INITFUNC( -STATIC int, +STATIC int __init AscWriteEEPDataReg( PortAddr iop_base, ushort data_reg ) -) { ushort read_back; int retry; @@ -12806,35 +12502,24 @@ } } -ASC_INITFUNC( -STATIC void, -AscWaitEEPRead( - void -) -) +STATIC void __init +AscWaitEEPRead(void) { DvcSleepMilliSecond(1); return; } -ASC_INITFUNC( -STATIC void, -AscWaitEEPWrite( - void -) -) +STATIC void __init +AscWaitEEPWrite(void) { DvcSleepMilliSecond(20); return; } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscReadEEPWord( PortAddr iop_base, - uchar addr -) -) + uchar addr) { ushort read_wval; uchar cmd_reg; @@ -12849,14 +12534,11 @@ return (read_wval); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscWriteEEPWord( PortAddr iop_base, uchar addr, - ushort word_val -) -) + ushort word_val) { ushort read_wval; @@ -12876,13 +12558,10 @@ return (read_wval); } -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AscGetEEPConfig( PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type -) -) + ASCEEP_CONFIG * cfg_buf, ushort bus_type) { ushort wval; ushort sum; @@ -12928,13 +12607,10 @@ return (sum); } -ASC_INITFUNC( -STATIC int, +STATIC int __init AscSetEEPConfigOnce( PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type -) -) + ASCEEP_CONFIG * cfg_buf, ushort bus_type) { int n_error; ushort *wbuf; @@ -13026,13 +12702,11 @@ return (n_error); } -ASC_INITFUNC( -STATIC int, +STATIC int __init AscSetEEPConfig( PortAddr iop_base, ASCEEP_CONFIG * cfg_buf, ushort bus_type ) -) { int retry; int n_error; @@ -13066,17 +12740,17 @@ { if (!(asc_dvc->init_sdtr & tid_bits)) { - if ((dvc_type == SCSI_TYPE_CDROM) && + if ((dvc_type == TYPE_ROM) && (AscCompareString((uchar *) inq->vendor_id, (uchar *) "HP ", 3) == 0)) { asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; } asc_dvc->pci_fix_asyn_xfer |= tid_bits; - if ((dvc_type == SCSI_TYPE_PROC) || - (dvc_type == SCSI_TYPE_SCANNER) || - (dvc_type == SCSI_TYPE_CDROM) || - (dvc_type == SCSI_TYPE_SASD)) + if ((dvc_type == TYPE_PROCESSOR) || + (dvc_type == TYPE_SCANNER) || + (dvc_type == TYPE_ROM) || + (dvc_type == TYPE_TAPE)) { asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; } @@ -14470,7 +14144,7 @@ * unswapped on big-endian platforms. */ STATIC ADVEEP_3550_CONFIG -Default_3550_EEPROM_Config ASC_INITDATA = { +Default_3550_EEPROM_Config __initdata = { ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ 0x0000, /* cfg_msw */ 0xFFFF, /* disc_enable */ @@ -14508,7 +14182,7 @@ }; STATIC ADVEEP_3550_CONFIG -ADVEEP_3550_Config_Field_IsChar ASC_INITDATA = { +ADVEEP_3550_Config_Field_IsChar __initdata = { 0, /* cfg_lsw */ 0, /* cfg_msw */ 0, /* -disc_enable */ @@ -14546,7 +14220,7 @@ }; STATIC ADVEEP_38C0800_CONFIG -Default_38C0800_EEPROM_Config ASC_INITDATA = { +Default_38C0800_EEPROM_Config __initdata = { ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ 0x0000, /* 01 cfg_msw */ 0xFFFF, /* 02 disc_enable */ @@ -14611,7 +14285,7 @@ }; STATIC ADVEEP_38C0800_CONFIG -ADVEEP_38C0800_Config_Field_IsChar ASC_INITDATA = { +ADVEEP_38C0800_Config_Field_IsChar __initdata = { 0, /* 00 cfg_lsw */ 0, /* 01 cfg_msw */ 0, /* 02 disc_enable */ @@ -14676,7 +14350,7 @@ }; STATIC ADVEEP_38C1600_CONFIG -Default_38C1600_EEPROM_Config ASC_INITDATA = { +Default_38C1600_EEPROM_Config __initdata = { ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ 0x0000, /* 01 cfg_msw */ 0xFFFF, /* 02 disc_enable */ @@ -14741,7 +14415,7 @@ }; STATIC ADVEEP_38C1600_CONFIG -ADVEEP_38C1600_Config_Field_IsChar ASC_INITDATA = { +ADVEEP_38C1600_Config_Field_IsChar __initdata = { 0, /* 00 cfg_lsw */ 0, /* 01 cfg_msw */ 0, /* 02 disc_enable */ @@ -14813,10 +14487,8 @@ * For a non-fatal error return a warning code. If there are no warnings * then 0 is returned. */ -ASC_INITFUNC( -STATIC int, +STATIC int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) -) { ushort warn_code; AdvPortAddr iop_base; @@ -16800,10 +16472,8 @@ * * Note: Chip is stopped on entry. */ -ASC_INITFUNC( -STATIC int, +STATIC int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) -) { AdvPortAddr iop_base; ushort warn_code; @@ -16974,10 +16644,8 @@ * * Note: Chip is stopped on entry. */ -ASC_INITFUNC( -STATIC int, +STATIC int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) -) { AdvPortAddr iop_base; ushort warn_code; @@ -17209,10 +16877,8 @@ * * Note: Chip is stopped on entry. */ -ASC_INITFUNC( -STATIC int, +STATIC int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) -) { AdvPortAddr iop_base; ushort warn_code; @@ -17477,10 +17143,8 @@ * * Return a checksum based on the EEPROM configuration read. */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) -) { ushort wval, chksum; ushort *wbuf; @@ -17525,11 +17189,9 @@ * * Return a checksum based on the EEPROM configuration read. */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) -) { ushort wval, chksum; ushort *wbuf; @@ -17574,11 +17236,9 @@ * * Return a checksum based on the EEPROM configuration read. */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) -) { ushort wval, chksum; ushort *wbuf; @@ -17621,10 +17281,8 @@ /* * Read the EEPROM from specified location */ -ASC_INITFUNC( -STATIC ushort, +STATIC ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) -) { AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_READ | eep_word_addr); @@ -17635,10 +17293,8 @@ /* * Wait for EEPROM command to complete */ -ASC_INITFUNC( -STATIC void, +STATIC void __init AdvWaitEEPCmd(AdvPortAddr iop_base) -) { int eep_delay_ms; @@ -18290,7 +17946,7 @@ * the device, otherwise may erroneously set *_able bits. */ if (scsiq->done_status == QD_NO_ERROR && - scsiq->cdb[0] == SCSICMD_Inquiry && + scsiq->cdb[0] == INQUIRY && scsiq->target_lun == 0 && (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT) == ADV_INQ_RTN_STD_INQUIRY_DATA) diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/aha1542.c 2004-06-20 13:00:24 -07:00 @@ -47,7 +47,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "aha1542.h" #define SCSI_BUF_PA(address) isa_virt_to_bus(address) diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/aha1740.c 2004-06-20 13:00:26 -07:00 @@ -56,7 +56,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "aha1740.h" /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h --- a/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-06-20 13:00:25 -07:00 @@ -68,7 +68,7 @@ /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahd #include "scsi.h" -#include "hosts.h" +#include /* Name space conflict with BSD queue macros */ #ifdef LIST_HEAD diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-06-20 13:00:24 -07:00 @@ -85,7 +85,7 @@ /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahc #include "scsi.h" -#include "hosts.h" +#include /* Name space conflict with BSD queue macros */ #ifdef LIST_HEAD diff -Nru a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c --- a/drivers/scsi/aic7xxx/aiclib.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/aic7xxx/aiclib.c 2004-06-20 13:00:24 -07:00 @@ -36,7 +36,7 @@ /* Core SCSI definitions */ #include "scsi.h" -#include "hosts.h" +#include #include "aiclib.h" #include "cam.h" diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c --- a/drivers/scsi/aic7xxx_old.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/aic7xxx_old.c 2004-06-20 13:00:24 -07:00 @@ -239,7 +239,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "aic7xxx_old/aic7xxx.h" #include "aic7xxx_old/sequencer.h" diff -Nru a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c --- a/drivers/scsi/amiga7xx.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/amiga7xx.c 2004-06-20 13:00:24 -07:00 @@ -25,7 +25,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "53c7xx.h" #include "amiga7xx.h" diff -Nru a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c --- a/drivers/scsi/atari_scsi.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/atari_scsi.c 2004-06-20 13:00:26 -07:00 @@ -102,7 +102,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "atari_scsi.h" #include "NCR5380.h" #include diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c --- a/drivers/scsi/atp870u.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/atp870u.c 2004-06-20 13:00:24 -07:00 @@ -35,7 +35,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "atp870u.h" /* diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c --- a/drivers/scsi/blz1230.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/blz1230.c 2004-06-20 13:00:25 -07:00 @@ -28,7 +28,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c --- a/drivers/scsi/blz2060.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/blz2060.c 2004-06-20 13:00:24 -07:00 @@ -28,7 +28,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c --- a/drivers/scsi/bvme6000.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/bvme6000.c 2004-06-20 13:00:23 -07:00 @@ -17,7 +17,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "53c7xx.h" #include "bvme6000.h" diff -Nru a/drivers/scsi/constants.c b/drivers/scsi/constants.c --- a/drivers/scsi/constants.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/constants.c 2004-06-20 13:00:25 -07:00 @@ -12,7 +12,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #define CONST_COMMAND 0x01 #define CONST_STATUS 0x02 @@ -154,7 +154,7 @@ } #endif -void print_command (unsigned char *command) { +void __scsi_print_command (unsigned char *command) { int i,s; print_opcode(command[0]); for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) @@ -173,7 +173,7 @@ * (e.g. "0x2" for Check Condition). **/ void -print_status(unsigned char scsi_status) { +scsi_print_status(unsigned char scsi_status) { #if (CONSTANTS & CONST_STATUS) const char * ccp; @@ -1014,12 +1014,12 @@ #endif } -void print_sense(const char *devclass, struct scsi_cmnd *cmd) +void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd) { print_sense_internal(devclass, cmd->sense_buffer, cmd->request); } -void print_req_sense(const char *devclass, struct scsi_request *sreq) +void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq) { print_sense_internal(devclass, sreq->sr_sense_buffer, sreq->sr_request); } @@ -1051,7 +1051,7 @@ #define NO_EXTENDED_MSGS (sizeof(two_byte_msgs) / sizeof (const char *)) #endif /* (CONSTANTS & CONST_MSG) */ -int print_msg (const unsigned char *msg) { +int scsi_print_msg (const unsigned char *msg) { int len = 0, i; if (msg[0] == EXTENDED_MESSAGE) { len = 3 + msg[1]; @@ -1124,13 +1124,13 @@ return len; } -void print_Scsi_Cmnd(struct scsi_cmnd *cmd) { +void scsi_print_command(struct scsi_cmnd *cmd) { printk("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); printk(" command = "); - print_command(cmd->cmnd); + __scsi_print_command(cmd->cmnd); } #if (CONSTANTS & CONST_HOST) @@ -1139,7 +1139,7 @@ "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", NULL}; -void print_hostbyte(int scsiresult) +void scsi_print_hostbyte(int scsiresult) { static int maxcode=0; int i; @@ -1155,7 +1155,7 @@ printk("(%s) ",hostbyte_table[host_byte(scsiresult)]); } #else -void print_hostbyte(int scsiresult) +void scsi_print_hostbyte(int scsiresult) { printk("Hostbyte=0x%02x ",host_byte(scsiresult)); } #endif @@ -1170,7 +1170,7 @@ unknown,unknown,unknown, "SUGGEST_SENSE",NULL}; -void print_driverbyte(int scsiresult) +void scsi_print_driverbyte(int scsiresult) { static int driver_max=0,suggest_max=0; int i,dr=driver_byte(scsiresult)&DRIVER_MASK, su=(driver_byte(scsiresult)&SUGGEST_MASK)>>4; @@ -1187,7 +1187,7 @@ su #include "scsi.h" -#include "hosts.h" // Scsi_Host definition for INT handler +#include // Scsi_Host definition for INT handler #include "cpqfcTSchip.h" #include "cpqfcTSstructs.h" diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/cpqfcTSinit.c 2004-06-20 13:00:23 -07:00 @@ -51,7 +51,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include #include "cpqfcTSchip.h" #include "cpqfcTSstructs.h" @@ -1266,7 +1266,7 @@ -// The file "hosts.h" says not to call scsi_done from +// The file says not to call scsi_done from // inside _queuecommand, so we'll do it from the heartbeat timer // (clarification: Turns out it's ok to call scsi_done from queuecommand // for cases that don't go to the hardware like scsi cmds destined diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c --- a/drivers/scsi/cpqfcTSworker.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/cpqfcTSworker.c 2004-06-20 13:00:25 -07:00 @@ -39,7 +39,7 @@ #include #include "scsi.h" -#include "hosts.h" // struct Scsi_Host definition for T handler +#include // struct Scsi_Host definition for T handler #include "cpqfcTSchip.h" #include "cpqfcTSstructs.h" #include "cpqfcTStrigger.h" diff -Nru a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c --- a/drivers/scsi/cyberstorm.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/cyberstorm.c 2004-06-20 13:00:25 -07:00 @@ -31,7 +31,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c --- a/drivers/scsi/cyberstormII.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/cyberstormII.c 2004-06-20 13:00:25 -07:00 @@ -27,7 +27,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h --- a/drivers/scsi/dc390.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/dc390.h 2004-06-20 13:00:23 -07:00 @@ -14,12 +14,9 @@ #define DC390_H #include -#ifndef KERNEL_VERSION -# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif #define DC390_BANNER "Tekram DC390/AM53C974" -#define DC390_VERSION "2.1b 2004-04-13" +#define DC390_VERSION "2.1d 2004-05-27" /* We don't have eh_abort_handler, eh_device_reset_handler, * eh_bus_reset_handler, eh_host_reset_handler yet! @@ -32,14 +29,4 @@ # define NEW_EH use_new_eh_code: 1, # define USE_NEW_EH #endif - -static int DC390_detect(Scsi_Host_Template *psht); -static int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); -static int DC390_abort(Scsi_Cmnd *cmd); -static int DC390_reset(Scsi_Cmnd *cmd); -static int DC390_bios_param(struct scsi_device *sdev, struct block_device *dev, - sector_t capacity, int geom[]); - -static int DC390_release(struct Scsi_Host *); - #endif /* DC390_H */ diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c --- a/drivers/scsi/dc395x.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/dc395x.c 2004-06-20 13:00:23 -07:00 @@ -53,7 +53,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "dc395x.h" #include /* needed for scsicam_bios_param */ #include diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c --- a/drivers/scsi/dec_esp.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/dec_esp.c 2004-06-20 13:00:25 -07:00 @@ -29,7 +29,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c --- a/drivers/scsi/dmx3191d.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/dmx3191d.c 2004-06-20 13:00:24 -07:00 @@ -34,7 +34,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "dmx3191d.h" diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/dpt_i2o.c 2004-06-20 13:00:25 -07:00 @@ -68,8 +68,11 @@ #include #include /* for virt_to_bus, etc. */ -#include "scsi.h" -#include "hosts.h" +#include +#include +#include +#include +#include #include "dpt/dptsig.h" #include "dpti.h" @@ -86,9 +89,9 @@ #elif defined(__ia64__) PROC_INTEL, PROC_IA64, #elif defined(__sparc__) - PROC_ULTRASPARC, + PROC_ULTRASPARC, PROC_ULTRASPARC, #elif defined(__alpha__) - PROC_ALPHA , + PROC_ALPHA, PROC_ALPHA, #else (-1),(-1), #endif @@ -173,7 +176,7 @@ }; MODULE_DEVICE_TABLE(pci,dptids); -static int adpt_detect(Scsi_Host_Template* sht) +static int adpt_detect(struct scsi_host_template* sht) { struct pci_dev *pDev = NULL; adpt_hba* pHba; @@ -362,7 +365,7 @@ } -static int adpt_slave_configure(Scsi_Device * device) +static int adpt_slave_configure(struct scsi_device * device) { struct Scsi_Host *host = device->host; adpt_hba* pHba; @@ -378,7 +381,7 @@ return 0; } -static int adpt_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +static int adpt_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *)) { adpt_hba* pHba = NULL; struct adpt_device* pDev = NULL; /* dpt per device information */ @@ -643,7 +646,7 @@ *=========================================================================== */ -static int adpt_abort(Scsi_Cmnd * cmd) +static int adpt_abort(struct scsi_cmnd * cmd) { adpt_hba* pHba = NULL; /* host bus adapter structure */ struct adpt_device* dptdevice; /* dpt per device information */ @@ -683,7 +686,7 @@ // This is the same for BLK and SCSI devices // NOTE this is wrong in the i2o.h definitions // This is not currently supported by our adapter but we issue it anyway -static int adpt_device_reset(Scsi_Cmnd* cmd) +static int adpt_device_reset(struct scsi_cmnd* cmd) { adpt_hba* pHba; u32 msg[4]; @@ -723,7 +726,7 @@ #define I2O_HBA_BUS_RESET 0x87 // This version of bus reset is called by the eh_error handler -static int adpt_bus_reset(Scsi_Cmnd* cmd) +static int adpt_bus_reset(struct scsi_cmnd* cmd) { adpt_hba* pHba; u32 msg[4]; @@ -745,7 +748,7 @@ } // This version of reset is called by the eh_error_handler -static int adpt_reset(Scsi_Cmnd* cmd) +static int adpt_reset(struct scsi_cmnd* cmd) { adpt_hba* pHba; int rcode; @@ -860,7 +863,7 @@ #endif -static int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) +static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) { adpt_hba* pHba = NULL; @@ -1997,7 +2000,7 @@ static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs) { - Scsi_Cmnd* cmd; + struct scsi_cmnd* cmd; adpt_hba* pHba = dev_id; u32 m; ulong reply; @@ -2059,14 +2062,14 @@ status = I2O_POST_WAIT_OK; } if(!(context & 0x40000000)) { - cmd = (Scsi_Cmnd*) readl(reply+12); + cmd = (struct scsi_cmnd*) readl(reply+12); if(cmd != NULL) { printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); } } adpt_i2o_post_wait_complete(context, status); } else { // SCSI message - cmd = (Scsi_Cmnd*) readl(reply+12); + cmd = (struct scsi_cmnd*) readl(reply+12); if(cmd != NULL){ if(cmd->serial_number != 0) { // If not timedout adpt_i2o_to_scsi(reply, cmd); @@ -2083,7 +2086,7 @@ return IRQ_RETVAL(handled); } -static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d) +static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d) { int i; u32 msg[MAX_MESSAGE_SIZE]; @@ -2108,16 +2111,16 @@ * cmd->cmnd[0] is an unsigned char */ switch(cmd->sc_data_direction){ - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: scsidir =0x40000000; // DATA IN (iop<--dev) break; - case SCSI_DATA_WRITE: + case DMA_TO_DEVICE: direction=0x04000000; // SGL OUT scsidir =0x80000000; // DATA OUT (iop-->dev) break; - case SCSI_DATA_NONE: + case DMA_NONE: break; - case SCSI_DATA_UNKNOWN: + case DMA_BIDIRECTIONAL: scsidir =0x40000000; // DATA IN (iop<--dev) // Assume In - and continue; break; @@ -2156,7 +2159,7 @@ if(cmd->use_sg) { struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + cmd->sc_data_direction); len = 0; @@ -2184,7 +2187,7 @@ *mptr++ = pci_map_single(pHba->pDev, cmd->request_buffer, cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + cmd->sc_data_direction); } } @@ -2200,7 +2203,7 @@ } -static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht) +static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) { struct Scsi_Host *host = NULL; @@ -2231,7 +2234,7 @@ } -static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd) +static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd) { adpt_hba* pHba; u32 hba_status; @@ -2533,8 +2536,8 @@ static void adpt_fail_posted_scbs(adpt_hba* pHba) { - Scsi_Cmnd* cmd = NULL; - Scsi_Device* d = NULL; + struct scsi_cmnd* cmd = NULL; + struct scsi_device* d = NULL; shost_for_each_device(d, pHba->host) { unsigned long flags; @@ -3358,7 +3361,7 @@ #endif -static Scsi_Host_Template driver_template = { +static struct scsi_host_template driver_template = { .name = "dpt_i2o", .proc_name = "dpt_i2o", .proc_info = adpt_proc_info, diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h --- a/drivers/scsi/dpti.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/dpti.h 2004-06-20 13:00:23 -07:00 @@ -37,19 +37,19 @@ * SCSI interface function Prototypes */ -static int adpt_detect(Scsi_Host_Template * sht); -static int adpt_queue(Scsi_Cmnd * cmd, void (*cmdcomplete) (Scsi_Cmnd *)); -static int adpt_abort(Scsi_Cmnd * cmd); -static int adpt_reset(Scsi_Cmnd* cmd); +static int adpt_detect(struct scsi_host_template * sht); +static int adpt_queue(struct scsi_cmnd * cmd, void (*cmdcomplete) (struct scsi_cmnd *)); +static int adpt_abort(struct scsi_cmnd * cmd); +static int adpt_reset(struct scsi_cmnd* cmd); static int adpt_release(struct Scsi_Host *host); -static int adpt_slave_configure(Scsi_Device *); +static int adpt_slave_configure(struct scsi_device *); static const char *adpt_info(struct Scsi_Host *pSHost); static int adpt_bios_param(struct scsi_device * sdev, struct block_device *dev, sector_t, int geom[]); -static int adpt_bus_reset(Scsi_Cmnd* cmd); -static int adpt_device_reset(Scsi_Cmnd* cmd); +static int adpt_bus_reset(struct scsi_cmnd* cmd); +static int adpt_device_reset(struct scsi_cmnd* cmd); /* @@ -198,7 +198,7 @@ u8 state; u16 tid; struct i2o_device* pI2o_dev; - Scsi_Device *pScsi_dev; + struct scsi_device *pScsi_dev; }; struct adpt_channel { @@ -296,9 +296,9 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba); static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); static s32 adpt_i2o_hrt_get(adpt_hba* pHba); -static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* dptdevice); -static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd); -static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht); +static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); +static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd); +static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); static s32 adpt_rescan(adpt_hba* pHba); @@ -308,7 +308,7 @@ static void adpt_inquiry(adpt_hba* pHba); static void adpt_fail_posted_scbs(adpt_hba* pHba); static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun); -static int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) ; +static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); static void adpt_i2o_post_wait_complete(u32, int); static int adpt_i2o_systab_send(adpt_hba* pHba); diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c --- a/drivers/scsi/dtc.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/dtc.c 2004-06-20 13:00:25 -07:00 @@ -84,7 +84,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "dtc.h" #define AUTOPROBE_IRQ #include "NCR5380.h" diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c --- a/drivers/scsi/eata.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/eata.c 2004-06-20 13:00:25 -07:00 @@ -495,7 +495,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/eata_generic.h b/drivers/scsi/eata_generic.h --- a/drivers/scsi/eata_generic.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/eata_generic.h 2004-06-20 13:00:24 -07:00 @@ -317,7 +317,7 @@ __u8 rw_latency; __u8 retries; __u8 status; /* status of this queueslot */ - Scsi_Cmnd *cmd; /* address of cmd */ + struct scsi_cmnd *cmd; /* address of cmd */ struct eata_sg_list *sg_list; }; diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c --- a/drivers/scsi/eata_pio.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/eata_pio.c 2004-06-20 13:00:25 -07:00 @@ -46,6 +46,7 @@ * last change: 2002/11/02 OS: Linux 2.5.45 * ************************************************************/ +#include #include #include #include @@ -56,15 +57,14 @@ #include #include #include -#include -#include #include #include #include -#include "scsi.h" -#include "hosts.h" -#include +#include +#include +#include +#include #include "eata_generic.h" #include "eata_pio.h" @@ -91,6 +91,8 @@ static unsigned long int_counter; static unsigned long queue_counter; +static struct scsi_host_template driver_template; + /* * eata_proc_info * inout : decides on the direction of the dataflow and the meaning of the @@ -170,15 +172,15 @@ if (sh->io_port && sh->n_io_port) release_region(sh->io_port, sh->n_io_port); } - return (TRUE); + return 1; } -static void IncStat(Scsi_Pointer * SCp, uint Increment) +static void IncStat(struct scsi_pointer *SCp, uint Increment) { SCp->ptr += Increment; if ((SCp->this_residual -= Increment) == 0) { if ((--SCp->buffers_residual) == 0) - SCp->Status = FALSE; + SCp->Status = 0; else { SCp->buffer++; SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset; @@ -204,7 +206,7 @@ static void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs) { uint eata_stat = 0xfffff; - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; hostdata *hd; struct eata_ccb *cp; uint base; @@ -233,12 +235,12 @@ if (stat & HA_SDRQ) { if (cp->DataIn) { z = 256; - odd = FALSE; + odd = 0; while ((cmd->SCp.Status) && ((z > 0) || (odd))) { if (odd) { *(cmd->SCp.ptr) = zwickel >> 8; IncStat(&cmd->SCp, 1); - odd = FALSE; + odd = 0; } x = min_t(unsigned int, z, cmd->SCp.this_residual / 2); insw(base + HA_RDATA, cmd->SCp.ptr, x); @@ -249,7 +251,7 @@ *(cmd->SCp.ptr) = zwickel & 0xff; IncStat(&cmd->SCp, 1); z--; - odd = TRUE; + odd = 1; } } while (z > 0) { @@ -258,7 +260,7 @@ } } else { /* cp->DataOut */ - odd = FALSE; + odd = 0; z = 256; while ((cmd->SCp.Status) && ((z > 0) || (odd))) { if (odd) { @@ -266,7 +268,7 @@ IncStat(&cmd->SCp, 1); outw(zwickel, base + HA_RDATA); z--; - odd = FALSE; + odd = 0; } x = min_t(unsigned int, z, cmd->SCp.this_residual / 2); outsw(base + HA_RDATA, cmd->SCp.ptr, x); @@ -276,13 +278,13 @@ zwickel = *(cmd->SCp.ptr); zwickel &= 0xff; IncStat(&cmd->SCp, 1); - odd = TRUE; + odd = 1; } } while (z > 0 || odd) { outw(zwickel, base + HA_RDATA); z--; - odd = FALSE; + odd = 0; } } } @@ -331,7 +333,7 @@ while (inb(base + HA_RSTATUS) & HA_SBUSY) if (--loop == 0) - return (TRUE); + return 1; /* Enable interrupts for HBA. It is not the best way to do it at this * place, but I hope that it doesn't interfere with the IDE driver @@ -340,10 +342,11 @@ outb(HA_CTRL_8HEADS, base + HA_CTRLREG); outb(command, base + HA_WCOMMAND); - return (FALSE); + return 0; } -static int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +static int eata_pio_queue(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { uint x, y; uint base; @@ -383,21 +386,21 @@ cmd->scsi_done = (void *) done; - if(cmd->sc_data_direction == SCSI_DATA_WRITE) - cp->DataOut = TRUE; /* Output mode */ + if (cmd->sc_data_direction == DMA_TO_DEVICE) + cp->DataOut = 1; /* Output mode */ else - cp->DataIn = TRUE; /* Input mode */ + cp->DataIn = 0; /* Input mode */ cp->Interpret = (cmd->device->id == hd->hostid); cp->cp_datalen = htonl((unsigned long) cmd->request_bufflen); - cp->Auto_Req_Sen = FALSE; + cp->Auto_Req_Sen = 0; cp->cp_reqDMA = htonl(0); cp->reqlen = 0; cp->cp_id = cmd->device->id; cp->cp_lun = cmd->device->lun; - cp->cp_dispri = FALSE; - cp->cp_identify = TRUE; + cp->cp_dispri = 0; + cp->cp_identify = 1; memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); cp->cp_statDMA = htonl(0); @@ -440,7 +443,7 @@ return (0); } -static int eata_pio_abort(Scsi_Cmnd * cmd) +static int eata_pio_abort(struct scsi_cmnd *cmd) { uint loop = HZ; @@ -472,11 +475,11 @@ panic("eata_pio: abort: invalid slot status\n"); } -static int eata_pio_host_reset(Scsi_Cmnd * cmd) +static int eata_pio_host_reset(struct scsi_cmnd *cmd) { uint x, limit = 0; - unsigned char success = FALSE; - Scsi_Cmnd *sp; + unsigned char success = 0; + struct scsi_cmnd *sp; struct Scsi_Host *host = cmd->device->host; DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->device->id, cmd->device->lun, cmd->abort_reason)); @@ -530,7 +533,7 @@ sp->scsi_done(sp); } - HD(cmd)->state = FALSE; + HD(cmd)->state = 0; if (success) { /* hmmm... */ DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n")); @@ -550,8 +553,8 @@ memset(&cp, 0, sizeof(struct eata_ccb)); memset(buff, 0, sizeof(buff)); - cp.DataIn = TRUE; - cp.Interpret = TRUE; /* Interpret command */ + cp.DataIn = 1; + cp.Interpret = 1; /* Interpret command */ cp.cp_datalen = htonl(254); cp.cp_dataDMA = htonl(0); @@ -593,14 +596,14 @@ int z; unsigned short *p; - if (check_region(base, 9)) - return (FALSE); + if (!request_region(base, 9, "eata_pio")) + return 0; memset(buf, 0, sizeof(struct get_conf)); while (inb(base + HA_RSTATUS) & HA_SBUSY) if (--loop == 0) - return (FALSE); + goto fail; DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base)); eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); @@ -609,30 +612,40 @@ for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) { while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) if (--loop == 0) - return (FALSE); + goto fail; loop = HZ / 2; *p = inw(base + HA_RDATA); } - if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ - if (htonl(EATA_SIGNATURE) == buf->signature) { - DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " "at %#4x EATA Level: %x\n", base, (uint) (buf->version))); - - while (inb(base + HA_RSTATUS) & HA_SDRQ) - inw(base + HA_RDATA); - if (ALLOW_DMA_BOARDS == FALSE) { - for (z = 0; z < MAXISA; z++) - if (base == ISAbases[z]) { - buf->IRQ = ISAirqs[z]; - break; - } + if (inb(base + HA_RSTATUS) & HA_SERROR) { + DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during " + "transfer for HBA at %x\n", base)); + goto fail; + } + + if (htonl(EATA_SIGNATURE) != buf->signature) + goto fail; + + DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " + "at %#4x EATA Level: %x\n", + base, (uint) (buf->version))); + + while (inb(base + HA_RSTATUS) & HA_SDRQ) + inw(base + HA_RDATA); + + if (!ALLOW_DMA_BOARDS) { + for (z = 0; z < MAXISA; z++) + if (base == ISAbases[z]) { + buf->IRQ = ISAirqs[z]; + break; } - return (TRUE); - } - } else { - DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " "for HBA at %x\n", base)); } - return (FALSE); + + return 1; + + fail: + release_region(base, 9); + return 0; } static void print_pio_config(struct get_conf *gc) @@ -670,7 +683,7 @@ return (!(inb(base + HA_RSTATUS) & HA_SERROR)); } -static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt) +static int register_pio_HBA(long base, struct get_conf *gc) { unsigned long size = 0; char *buff; @@ -681,47 +694,41 @@ DBG(DBG_REGISTER, print_pio_config(gc)); - if (gc->DMA_support == TRUE) { + if (gc->DMA_support) { printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base); - if (ALLOW_DMA_BOARDS == FALSE) - return (FALSE); + if (!ALLOW_DMA_BOARDS) + return 0; } if ((buff = get_pio_board_data((uint) base, gc->IRQ, gc->scsi_id[3], cplen = (htonl(gc->cplen) + 1) / 2, cppadlen = (htons(gc->cppadlen) + 1) / 2)) == NULL) { printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (unsigned long) base); - return (FALSE); + return 0; } - if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) { + if (!print_selftest(base) && !ALLOW_DMA_BOARDS) { printk("HBA at %#lx failed while performing self test & setup.\n", (unsigned long) base); - return (FALSE); + return 0; } - request_region(base, 8, "eata_pio"); - size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); - sh = scsi_register(tpnt, size); - if (sh == NULL) { - release_region(base, 8); - return FALSE; - } + sh = scsi_register(&driver_template, size); + if (sh == NULL) + return 0; if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) { reg_IRQ[gc->IRQ]++; if (!gc->IRQ_TR) - reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ + reg_IRQL[gc->IRQ] = 1; /* IRQ is edge triggered */ } else { printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ); - release_region(base, 8); - return (FALSE); + return 0; } } else { /* More than one HBA on this IRQ */ - if (reg_IRQL[gc->IRQ] == TRUE) { + if (reg_IRQL[gc->IRQ]) { printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n"); - release_region(base, 8); - return (FALSE); + return 0; } else reg_IRQ[gc->IRQ]++; } @@ -757,9 +764,9 @@ } if (ntohl(gc->len) >= 0x22) { - if (gc->is_PCI == TRUE) + if (gc->is_PCI) hd->bustype = IS_PCI; - else if (gc->is_EISA == TRUE) + else if (gc->is_EISA) hd->bustype = IS_EISA; else hd->bustype = IS_ISA; @@ -780,7 +787,7 @@ sh->unique_id = base; sh->base = base; sh->io_port = base; - sh->n_io_port = 8; + sh->n_io_port = 9; sh->irq = gc->IRQ; sh->dma_channel = PIO; sh->this_id = gc->scsi_id[3]; @@ -794,11 +801,11 @@ sh->max_lun = 8; if (gc->SECOND) - hd->primary = FALSE; + hd->primary = 0; else - hd->primary = TRUE; + hd->primary = 1; - sh->unchecked_isa_dma = FALSE; /* We can only do PIO */ + sh->unchecked_isa_dma = 0; /* We can only do PIO */ hd->next = NULL; /* build a linked list of all HBAs */ hd->prev = last_HBA; @@ -811,22 +818,24 @@ return (1); } -static void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) +static void find_pio_ISA(struct get_conf *buf) { int i; for (i = 0; i < MAXISA; i++) { - if (ISAbases[i]) { - if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE) { - register_pio_HBA(ISAbases[i], buf, tpnt); - } + if (!ISAbases[i]) + continue; + if (!get_pio_conf_PIO(ISAbases[i], buf)) + continue; + if (!register_pio_HBA(ISAbases[i], buf)) + release_region(ISAbases[i], 9); + else ISAbases[i] = 0; - } } return; } -static void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) +static void find_pio_EISA(struct get_conf *buf) { u32 base; int i; @@ -836,7 +845,7 @@ #endif for (i = 0; i < MAXEISA; i++) { - if (EISAbases[i] == TRUE) { /* Still a possibility ? */ + if (EISAbases[i]) { /* Still a possibility ? */ base = 0x1c88 + (i * 0x1000); #if CHECKPAL @@ -847,12 +856,15 @@ if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) { DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3)); #endif - if (get_pio_conf_PIO(base, buf) == TRUE) { + if (get_pio_conf_PIO(base, buf)) { DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); if (buf->IRQ) { - register_pio_HBA(base, buf, tpnt); - } else + if (!register_pio_HBA(base, buf)) + release_region(base, 9); + } else { printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n"); + release_region(base, 9); + } } /* Nothing found here so we take it from the list */ EISAbases[i] = 0; @@ -864,7 +876,7 @@ return; } -static void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) +static void find_pio_PCI(struct get_conf *buf) { #ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); @@ -889,16 +901,21 @@ base += 0x10; /* Now, THIS is the real address */ if (base != 0x1f8) { /* We didn't find it in the primary search */ - if (get_pio_conf_PIO(base, buf) == TRUE) { - if (buf->FORCADR) /* If the address is forced */ + if (get_pio_conf_PIO(base, buf)) { + if (buf->FORCADR) { /* If the address is forced */ + release_region(base, 9); continue; /* we'll find it later */ + } /* OK. We made it till here, so we can go now * and register it. We only have to check and * eventually remove it from the EISA and ISA list */ - register_pio_HBA(base, buf, tpnt); + if (!register_pio_HBA(base, buf)) { + release_region(base, 9); + continue; + } if (base < 0x1000) { for (x = 0; x < MAXISA; ++x) { @@ -913,7 +930,7 @@ } } #if CHECK_BLINK - else if (check_blink_state(base) == TRUE) { + else if (check_blink_state(base)) { printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n"); } #endif @@ -922,20 +939,15 @@ #endif /* #ifndef CONFIG_PCI */ } - -static int eata_pio_detect(Scsi_Host_Template * tpnt) +static int eata_pio_detect(struct scsi_host_template *tpnt) { struct Scsi_Host *HBA_ptr; struct get_conf gc; int i; - tpnt->proc_name = "eata_pio"; - - find_pio_PCI(&gc, tpnt); - - find_pio_EISA(&gc, tpnt); - - find_pio_ISA(&gc, tpnt); + find_pio_PCI(&gc); + find_pio_EISA(&gc); + find_pio_ISA(&gc); for (i = 0; i <= MAXIRQ; i++) if (reg_IRQ[i]) @@ -955,16 +967,19 @@ HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P') ? "PCI " : (SD(HBA_ptr)->bustype == 'E') ? "EISA" : "ISA ", - (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE) ? 'Y' : 'N', HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun); + (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id, + SD(HBA_ptr)->primary ? 'Y' : 'N', HBA_ptr->can_queue, + HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun); HBA_ptr = SD(HBA_ptr)->next; } } return (registered_HBAs); } -static Scsi_Host_Template driver_template = { - .proc_info = eata_pio_proc_info, +static struct scsi_host_template driver_template = { + .proc_name = "eata_pio", .name = "EATA (Extended Attachment) PIO driver", + .proc_info = eata_pio_proc_info, .detect = eata_pio_detect, .release = eata_pio_release, .queuecommand = eata_pio_queue, diff -Nru a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c --- a/drivers/scsi/fastlane.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/fastlane.c 2004-06-20 13:00:24 -07:00 @@ -36,7 +36,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c --- a/drivers/scsi/fcal.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/fcal.c 2004-06-20 13:00:23 -07:00 @@ -21,7 +21,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "../fc4/fcp_impl.h" #include "fcal.h" diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/fd_mcs.c 2004-06-20 13:00:24 -07:00 @@ -87,13 +87,14 @@ #include #include #include +#include #include #include #include #include "scsi.h" -#include "hosts.h" +#include #include "fd_mcs.h" #define DRIVER_VERSION "v0.2 by ZP Gu" @@ -1337,23 +1338,14 @@ static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev, sector_t capacity, int *info_array) { - unsigned char buf[512 + sizeof(int) * 2]; + unsigned char *p = scsi_bios_ptable(bdev); int size = capacity; - int *sizes = (int *) buf; - unsigned char *data = (unsigned char *) (sizes + 2); - unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; - int retcode; /* BIOS >= 3.4 for MCA cards */ /* This algorithm was provided by Future Domain (much thanks!). */ - sizes[0] = 0; /* zero bytes out */ - sizes[1] = 512; /* one sector in */ - memcpy(data, do_read, sizeof(do_read)); - retcode = kernel_scsi_ioctl(disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf); - if (!retcode /* SCSI command ok */ - && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ - && data[0x1c2]) { /* Partition type */ + if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */ + && p[4]) { /* Partition type */ /* The partition table layout is as follows: Start: 0x1b3h @@ -1383,8 +1375,8 @@ Future Domain algorithm, but it seemed to be a reasonable thing to do, especially in the Linux and BSD worlds. */ - info_array[0] = data[0x1c3] + 1; /* heads */ - info_array[1] = data[0x1c4] & 0x3f; /* sectors */ + info_array[0] = p[5] + 1; /* heads */ + info_array[1] = p[6] & 0x3f; /* sectors */ } else { /* Note that this new method guarantees that there will always be less than 1024 cylinders on a platter. This is good for drives @@ -1403,6 +1395,7 @@ } /* For both methods, compute the cylinders */ info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]); + kfree(p); return 0; } diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/fdomain.c 2004-06-20 13:00:25 -07:00 @@ -279,12 +279,13 @@ #include #include #include +#include #include #include #include "scsi.h" -#include "hosts.h" +#include MODULE_AUTHOR("Rickard E. Faith"); MODULE_DESCRIPTION("Future domain SCSI driver"); @@ -1564,12 +1565,7 @@ sector_t capacity, int *info_array) { int drive; - unsigned char buf[512 + sizeof (Scsi_Ioctl_Command)]; - Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf; int size = capacity; - unsigned char *data = sic->data; - unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; - int retcode; unsigned long offset; struct drive_info { unsigned short cylinders; @@ -1657,16 +1653,10 @@ info_array[2] = i.cylinders; } else { /* 3.4 BIOS (and up?) */ /* This algorithm was provided by Future Domain (much thanks!). */ + unsigned char *p = scsi_bios_ptable(bdev); - sic->inlen = 0; /* zero bytes out */ - sic->outlen = 512; /* one sector in */ - memcpy( data, do_read, sizeof( do_read ) ); - retcode = kernel_scsi_ioctl( sdev, - SCSI_IOCTL_SEND_COMMAND, - sic ); - if (!retcode /* SCSI command ok */ - && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ - && data[0x1c2]) { /* Partition type */ + if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */ + && p[4]) { /* Partition type */ /* The partition table layout is as follows: @@ -1697,8 +1687,8 @@ Future Domain algorithm, but it seemed to be a reasonable thing to do, especially in the Linux and BSD worlds. */ - info_array[0] = data[0x1c3] + 1; /* heads */ - info_array[1] = data[0x1c4] & 0x3f; /* sectors */ + info_array[0] = p[5] + 1; /* heads */ + info_array[1] = p[6] & 0x3f; /* sectors */ } else { /* Note that this new method guarantees that there will always be @@ -1718,6 +1708,7 @@ } /* For both methods, compute the cylinders */ info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] ); + kfree(p); } return 0; diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/g_NCR5380.c 2004-06-20 13:00:23 -07:00 @@ -107,7 +107,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "g_NCR5380.h" #include "NCR5380.h" #include diff -Nru a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c --- a/drivers/scsi/gvp11.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/gvp11.c 2004-06-20 13:00:25 -07:00 @@ -16,7 +16,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "wd33c93.h" #include "gvp11.h" diff -Nru a/drivers/scsi/i60uscsi.c b/drivers/scsi/i60uscsi.c --- a/drivers/scsi/i60uscsi.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/i60uscsi.c 2004-06-20 13:00:23 -07:00 @@ -81,7 +81,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "inia100.h" #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ) diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/ibmmca.c 2004-06-20 13:00:23 -07:00 @@ -45,7 +45,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "ibmmca.h" /* current version of this driver-source: */ diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/ide-scsi.c 2004-06-20 13:00:25 -07:00 @@ -51,7 +51,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #define IDESCSI_DEBUG_LOG 0 diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h --- a/drivers/scsi/imm.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/imm.h 2004-06-20 13:00:23 -07:00 @@ -79,7 +79,7 @@ #include #include -#include "hosts.h" +#include /* batteries not included :-) */ /* diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c --- a/drivers/scsi/in2000.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/in2000.c 2004-06-20 13:00:25 -07:00 @@ -126,7 +126,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #define IN2000_VERSION "1.33-2.5" #define IN2000_DATE "2002/11/03" diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/ini9100u.c 2004-06-20 13:00:23 -07:00 @@ -136,7 +136,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "ini9100u.h" #ifdef DEBUG_i91u diff -Nru a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c --- a/drivers/scsi/ipr.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/ipr.c 2004-06-20 13:00:26 -07:00 @@ -2884,6 +2884,7 @@ (res->cfgte.res_addr.lun == sdev->lun)) { res->sdev = sdev; res->add_to_ml = 0; + res->in_erp = 0; sdev->hostdata = res; res->needs_sync_complete = 1; break; @@ -3435,8 +3436,10 @@ SCSI_SENSE_BUFFERSIZE); } - if (res) + if (res) { res->needs_sync_complete = 1; + res->in_erp = 0; + } ipr_unmap_sglist(ioa_cfg, ipr_cmd); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); scsi_cmd->scsi_done(scsi_cmd); @@ -3479,6 +3482,12 @@ static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd) { struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; + u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + + if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { + ipr_erp_done(ipr_cmd); + return; + } ipr_reinit_ipr_cmnd_for_erp(ipr_cmd); @@ -3756,6 +3765,7 @@ ipr_erp_cancel_all(ipr_cmd); return; } + res->needs_sync_complete = 1; break; case IPR_IOASC_NR_INIT_CMD_REQUIRED: break; @@ -4808,6 +4818,7 @@ ipr_cmd->timer.data = (unsigned long) ipr_cmd; ipr_cmd->timer.expires = jiffies + IPR_OPERATIONAL_TIMEOUT; ipr_cmd->timer.function = (void (*)(unsigned long))ipr_timeout; + ipr_cmd->done = ipr_reset_ioa_job; add_timer(&ipr_cmd->timer); list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q); diff -Nru a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h --- a/drivers/scsi/ipr.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/ipr.h 2004-06-20 13:00:23 -07:00 @@ -36,8 +36,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.0.7" -#define IPR_DRIVER_DATE "(May 21, 2004)" +#define IPR_DRIVER_VERSION "2.0.9" +#define IPR_DRIVER_DATE "(May 26, 2004)" /* * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/ips.c 2004-06-20 13:00:23 -07:00 @@ -176,7 +176,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "ips.h" #include diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c --- a/drivers/scsi/jazz_esp.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/jazz_esp.c 2004-06-20 13:00:23 -07:00 @@ -16,7 +16,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c --- a/drivers/scsi/lasi700.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/lasi700.c 2004-06-20 13:00:23 -07:00 @@ -49,8 +49,7 @@ #include #include -#include "scsi.h" -#include "hosts.h" +#include #include "lasi700.h" #include "53c700.h" @@ -65,7 +64,7 @@ { 0 } }; -static Scsi_Host_Template lasi700_template = { +static struct scsi_host_template lasi700_template = { .name = "LASI SCSI 53c700", .proc_name = "lasi700", .this_id = 7, diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c --- a/drivers/scsi/mac_esp.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/mac_esp.c 2004-06-20 13:00:24 -07:00 @@ -26,7 +26,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c --- a/drivers/scsi/mac_scsi.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/mac_scsi.c 2004-06-20 13:00:23 -07:00 @@ -52,7 +52,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "mac_scsi.h" #include "NCR5380.h" diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c --- a/drivers/scsi/mca_53c9x.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/mca_53c9x.c 2004-06-20 13:00:23 -07:00 @@ -43,7 +43,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/megaraid.c 2004-06-20 13:00:23 -07:00 @@ -49,7 +49,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "megaraid.h" @@ -3815,7 +3815,8 @@ umc = MBOX_P(uiocp); - upthru = (mega_passthru *)umc->xferaddr; + if (get_user(upthru, (mega_passthru **)&umc->xferaddr)) + return (-EFAULT); if( put_user(mc->status, (u8 *)&upthru->scsistatus) ) return (-EFAULT); @@ -3831,7 +3832,8 @@ umc = (megacmd_t *)uioc_mimd->mbox; - upthru = (mega_passthru *)umc->xferaddr; + if (get_user(upthru, (mega_passthru **)&umc->xferaddr)) + return (-EFAULT); if( put_user(mc->status, (u8 *)&upthru->scsistatus) ) return (-EFAULT); @@ -4068,7 +4070,6 @@ static int mega_del_logdrv(adapter_t *adapter, int logdrv) { - DECLARE_WAIT_QUEUE_HEAD(wq); unsigned long flags; scb_t *scb; int rval; @@ -4083,11 +4084,9 @@ * Wait till all the issued commands are complete and there are no * commands in the pending queue */ - while( atomic_read(&adapter->pend_cmds) > 0 || - !list_empty(&adapter->pending_list) ) { - - sleep_on_timeout( &wq, 1*HZ ); /* sleep for 1s */ - } + while (atomic_read(&adapter->pend_cmds) > 0 || + !list_empty(&adapter->pending_list)) + msleep(1000); /* sleep for 1s */ rval = mega_do_del_logdrv(adapter, logdrv); @@ -4610,6 +4609,26 @@ pci_bus = pdev->bus->number; pci_dev_func = pdev->devfn; + + /* + * The megaraid3 stuff reports the ID of the Intel part which is not + * remotely specific to the megaraid + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + u16 magic; + /* + * Don't fall over the Compaq management cards using the same + * PCI identifier + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ && + pdev->subsystem_device == 0xC000) + return -ENODEV; + /* Now check the magic signature byte */ + pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic); + if (magic != HBA_SIGNATURE_471 && magic != HBA_SIGNATURE) + return -ENODEV; + /* Ok it is probably a megaraid */ + } /* * For these vendor and device ids, signature offsets are not diff -Nru a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c --- a/drivers/scsi/mvme147.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/mvme147.c 2004-06-20 13:00:23 -07:00 @@ -11,7 +11,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "wd33c93.h" #include "mvme147.h" diff -Nru a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c --- a/drivers/scsi/mvme16x.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/mvme16x.c 2004-06-20 13:00:25 -07:00 @@ -15,7 +15,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "53c7xx.h" #include "mvme16x.h" diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/ncr53c8xx.c 2004-06-20 13:00:24 -07:00 @@ -138,7 +138,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "ncr53c8xx.h" diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/nsp32.c 2004-06-20 13:00:24 -07:00 @@ -44,7 +44,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c --- a/drivers/scsi/oktagon_esp.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/oktagon_esp.c 2004-06-20 13:00:23 -07:00 @@ -29,7 +29,7 @@ #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/osst.c 2004-06-20 13:00:24 -07:00 @@ -61,7 +61,7 @@ #define OSST_DEB_MSG KERN_NOTICE #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c --- a/drivers/scsi/pas16.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/pas16.c 2004-06-20 13:00:23 -07:00 @@ -125,7 +125,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "pas16.h" #define AUTOPROBE_IRQ #include "NCR5380.h" diff -Nru a/drivers/scsi/pc980155.c b/drivers/scsi/pc980155.c --- a/drivers/scsi/pc980155.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,299 +0,0 @@ -/* - * - * drivers/scsi/pc980155.c - * - * PC-9801-55 SCSI host adapter driver - * - * Copyright (C) 1997-2003 Kyoto University Microcomputer Club - * (Linux/98 project) - * Tomoharu Ugawa - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "scsi.h" -#include "hosts.h" -#include "wd33c93.h" -#include "pc980155.h" - -extern int pc98_bios_param(struct scsi_device *, struct block_device *, - sector_t, int *); -static int scsi_pc980155_detect(Scsi_Host_Template *); -static int scsi_pc980155_release(struct Scsi_Host *); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 16 -#endif - -#undef PC_9801_55_DEBUG -#undef PC_9801_55_DEBUG_VERBOSE - -#define NR_BASE_IOS 4 -static int nr_base_ios = NR_BASE_IOS; -static unsigned int base_ios[NR_BASE_IOS] = {0xcc0, 0xcd0, 0xce0, 0xcf0}; -static wd33c93_regs init_regs; -static int io; - -static struct Scsi_Host *pc980155_host = NULL; - -static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp); - -static inline void pc980155_dma_enable(unsigned int base_io) -{ - outb(0x01, REG_CWRITE); -} - -static inline void pc980155_dma_disable(unsigned int base_io) -{ - outb(0x02, REG_CWRITE); -} - - -static void pc980155_intr_handle(int irq, void *dev_id, struct pt_regs *regp) -{ - wd33c93_intr(pc980155_host); -} - -static int dma_setup(Scsi_Cmnd *sc, int dir_in) -{ - /* - * sc->SCp.this_residual : transfer count - * sc->SCp.ptr : distination address (virtual address) - * dir_in : data direction (DATA_OUT_DIR:0 or DATA_IN_DIR:1) - * - * if success return 0 - */ - - /* - * DMA WRITE MODE - * bit 7,6 01b single mode (this mode only) - * bit 5 inc/dec (default:0 = inc) - * bit 4 auto initialize (normaly:0 = off) - * bit 3,2 01b memory -> io - * 10b io -> memory - * 00b verify - * bit 1,0 channel - */ - disable_dma(sc->device->host->dma_channel); - set_dma_mode(sc->device->host->dma_channel, - 0x40 | (dir_in ? 0x04 : 0x08)); - clear_dma_ff(sc->device->host->dma_channel); - set_dma_addr(sc->device->host->dma_channel, virt_to_phys(sc->SCp.ptr)); - set_dma_count(sc->device->host->dma_channel, sc->SCp.this_residual); -#ifdef PC_9801_55_DEBUG - printk("D%d(%x)D", sc->device->host->dma_channel, - sc->SCp.this_residual); -#endif - enable_dma(sc->device->host->dma_channel); - pc980155_dma_enable(sc->device->host->io_port); - return 0; -} - -static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *sc, int status) -{ - /* - * instance: Hostadapter's instance - * sc: scsi command - * status: True if success - */ - pc980155_dma_disable(sc->device->host->io_port); - disable_dma(sc->device->host->dma_channel); -} - -/* return non-zero on detection */ -static inline int pc980155_test_port(wd33c93_regs regs) -{ - /* Quick and dirty test for presence of the card. */ - if (inb(regs.SASR) == 0xff) - return 0; - - return 1; -} - -static inline int pc980155_getconfig(unsigned int base_io, wd33c93_regs regs, - unsigned char* irq, unsigned char* dma, - unsigned char* scsi_id) -{ - static unsigned char irqs[] = {3, 5, 6, 9, 12, 13}; - unsigned char result; - - printk(KERN_DEBUG "PC-9801-55: base_io=%x SASR=%x SCMD=%x\n", - base_io, regs.SASR, regs.SCMD); - result = read_pc980155_resetint(regs); - printk(KERN_DEBUG "PC-9801-55: getting config (%x)\n", result); - *scsi_id = result & 0x07; - *irq = (result >> 3) & 0x07; - if (*irq > 5) { - printk(KERN_ERR "PC-9801-55 (base %#x): impossible IRQ (%d)" - " - other device here?\n", base_io, *irq); - return 0; - } - - *irq = irqs[*irq]; - result = inb(REG_STATRD); - *dma = result & 0x03; - if (*dma == 1) { - printk(KERN_ERR - "PC-9801-55 (base %#x): impossible DMA channl (%d)" - " - other device here?\n", base_io, *dma); - return 0; - } -#ifdef PC_9801_55_DEBUG - printk("PC-9801-55: end of getconfig\n"); -#endif - return 1; -} - -/* return non-zero on detection */ -static int scsi_pc980155_detect(Scsi_Host_Template* tpnt) -{ - unsigned int base_io; - unsigned char irq, dma, scsi_id; - int i; -#ifdef PC_9801_55_DEBUG - unsigned char debug; -#endif - - if (io) { - base_ios[0] = io; - nr_base_ios = 1; - } - - for (i = 0; i < nr_base_ios; i++) { - base_io = base_ios[i]; - init_regs.SASR = REG_ADDRST; - init_regs.SCMD = REG_CONTRL; -#ifdef PC_9801_55_DEBUG - printk("PC-9801-55: SASR(%x = %x)\n", SASR, REG_ADDRST); -#endif - if (!request_region(base_io, 6, "PC-9801-55")) - continue; - - if (pc980155_test_port(init_regs) && - pc980155_getconfig(base_io, init_regs, - &irq, &dma, &scsi_id)) - goto found; - - release_region(base_io, 6); - } - - printk("PC-9801-55: not found\n"); - return 0; - - found: -#ifdef PC_9801_55_DEBUG - printk("PC-9801-55: config: base io = %x, irq = %d, dma channel = %d, scsi id = %d\n", base_io, irq, dma, scsi_id); -#endif - if (request_irq(irq, pc980155_intr_handle, 0, "PC-9801-55", NULL)) { - printk(KERN_ERR "PC-9801-55: unable to allocate IRQ %d\n", irq); - goto err1; - } - - if (request_dma(dma, "PC-9801-55")) { - printk(KERN_ERR "PC-9801-55: unable to allocate DMA channel %d\n", dma); - goto err2; - } - - pc980155_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (pc980155_host) { - pc980155_host->this_id = scsi_id; - pc980155_host->io_port = base_io; - pc980155_host->n_io_port = 6; - pc980155_host->irq = irq; - pc980155_host->dma_channel = dma; - printk("PC-9801-55: scsi host found at %x irq = %d, use dma channel %d.\n", base_io, irq, dma); - pc980155_int_enable(init_regs); - wd33c93_init(pc980155_host, init_regs, dma_setup, dma_stop, - WD33C93_FS_12_15); - return 1; - } - - printk(KERN_ERR "PC-9801-55: failed to register device\n"); - -err2: - free_irq(irq, NULL); -err1: - release_region(base_io, 6); - return 0; -} - -static int scsi_pc980155_release(struct Scsi_Host *shost) -{ - struct WD33C93_hostdata *hostdata - = (struct WD33C93_hostdata *)shost->hostdata; - - pc980155_int_disable(hostdata->regs); - release_region(shost->io_port, shost->n_io_port); - free_irq(shost->irq, NULL); - free_dma(shost->dma_channel); - wd33c93_release(); - return 1; -} - -static int pc980155_bus_reset(Scsi_Cmnd *cmd) -{ - struct WD33C93_hostdata *hostdata - = (struct WD33C93_hostdata *)cmd->device->host->hostdata; - - pc980155_int_disable(hostdata->regs); - pc980155_assert_bus_reset(hostdata->regs); - udelay(50); - pc980155_negate_bus_reset(hostdata->regs); - (void) inb(hostdata->regs.SASR); - (void) read_pc980155(hostdata->regs, WD_SCSI_STATUS); - pc980155_int_enable(hostdata->regs); - wd33c93_host_reset(cmd); - return SUCCESS; -} - - -#ifndef MODULE -static int __init pc980155_setup(char *str) -{ - int ints[4]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] > 0) - io = ints[1]; - return 1; -} -__setup("pc980155_io=", pc980155_setup); -#endif - -MODULE_PARM(io, "i"); -MODULE_AUTHOR("Tomoharu Ugawa "); -MODULE_DESCRIPTION("PC-9801-55 SCSI host adapter driver"); -MODULE_LICENSE("GPL"); - -static Scsi_Host_Template driver_template = { - .proc_info = wd33c93_proc_info, - .name = "SCSI PC-9801-55", - .detect = scsi_pc980155_detect, - .release = scsi_pc980155_release, - .queuecommand = wd33c93_queuecommand, - .eh_abort_handler = wd33c93_abort, - .eh_bus_reset_handler = pc980155_bus_reset, - .eh_host_reset_handler = wd33c93_host_reset, - .bios_param = pc98_bios_param, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, /* dont use link command */ - .unchecked_isa_dma = 1, /* use dma **XXXX***/ - .use_clustering = ENABLE_CLUSTERING, - .proc_name = "PC_9801_55", -}; - -#include "scsi_module.c" diff -Nru a/drivers/scsi/pc980155.h b/drivers/scsi/pc980155.h --- a/drivers/scsi/pc980155.h 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,52 +0,0 @@ -/* - * - * drivers/scsi/pc980155.h - * - * PC-9801-55 SCSI host adapter driver - * - * Copyright (C) 1997-2003 Kyoto University Microcomputer Club - * (Linux/98 project) - * Tomoharu Ugawa - * - */ - -#ifndef __PC980155_H -#define __PC980155_H - -#include "wd33c93.h" - -#define REG_ADDRST (base_io) -#define REG_CONTRL (base_io + 2) -#define REG_CWRITE (base_io + 4) -#define REG_STATRD (base_io + 4) - -#define WD_MEMORYBANK 0x30 -#define WD_RESETINT 0x33 - -static inline uchar read_pc980155(const wd33c93_regs regs, uchar reg_num) -{ - outb(reg_num, regs.SASR); - return (uchar)inb(regs.SCMD); -} - -static inline void write_memorybank(const wd33c93_regs regs, uchar value) -{ - outb(WD_MEMORYBANK, regs.SASR); - outb(value, regs.SCMD); -} - -#define read_pc980155_resetint(regs) \ - read_pc980155((regs), WD_RESETINT) -#define pc980155_int_enable(regs) \ - write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x04) - -#define pc980155_int_disable(regs) \ - write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x04) - -#define pc980155_assert_bus_reset(regs) \ - write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) | 0x02) - -#define pc980155_negate_bus_reset(regs) \ - write_memorybank((regs), read_pc980155((regs), WD_MEMORYBANK) & ~0x02) - -#endif /* __PC980155_H */ diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c --- a/drivers/scsi/pci2000.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/pci2000.c 2004-06-20 13:00:25 -07:00 @@ -54,7 +54,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "pci2000.h" #include "psi_roy.h" diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c --- a/drivers/scsi/pci2220i.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/pci2220i.c 2004-06-20 13:00:23 -07:00 @@ -59,7 +59,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "pci2220i.h" #include "psi_dale.h" diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c --- a/drivers/scsi/pcmcia/aha152x_stub.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/pcmcia/aha152x_stub.c 2004-06-20 13:00:25 -07:00 @@ -47,7 +47,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "aha152x.h" #include diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c --- a/drivers/scsi/pcmcia/fdomain_stub.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/pcmcia/fdomain_stub.c 2004-06-20 13:00:25 -07:00 @@ -44,7 +44,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c --- a/drivers/scsi/pcmcia/nsp_cs.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/pcmcia/nsp_cs.c 2004-06-20 13:00:26 -07:00 @@ -1936,10 +1936,10 @@ nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host); for (dev = host->host_queue; dev != NULL; dev = dev->next) { - unsigned long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + - ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); + unsigned long id; + id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) + + ((dev->channel & 0x0f) << 8) + + ((dev->host->host_no & 0x0f) << 12); node = &info->node[info->ndev]; node->minor = 0; switch (dev->type) { diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/pcmcia/qlogic_stub.c 2004-06-20 13:00:24 -07:00 @@ -46,7 +46,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "../qlogicfas408.h" #include diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c --- a/drivers/scsi/pluto.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/pluto.c 2004-06-20 13:00:24 -07:00 @@ -21,7 +21,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "../fc4/fcp_impl.h" #include "pluto.h" diff -Nru a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h --- a/drivers/scsi/ppa.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/ppa.h 2004-06-20 13:00:25 -07:00 @@ -86,7 +86,7 @@ #include #include -#include "hosts.h" +#include /* batteries not included :-) */ /* diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c --- a/drivers/scsi/psi240i.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/psi240i.c 2004-06-20 13:00:25 -07:00 @@ -41,7 +41,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "psi240i.h" #include "psi_chip.h" diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/qla1280.c 2004-06-20 13:00:26 -07:00 @@ -357,7 +357,7 @@ #else #include #include "scsi.h" -#include "hosts.h" +#include #include "sd.h" #endif @@ -3119,6 +3119,7 @@ * Returns: * 0 = success, was able to issue command. */ +#ifdef QLA_64BIT_PTR static int qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { @@ -3381,9 +3382,8 @@ return status; } +#else /* !QLA_64BIT_PTR */ - -#ifndef QLA_64BIT_PTR /* * qla1280_32bit_start_scsi * The start SCSI is responsible for building request packets on diff -Nru a/drivers/scsi/qla2xxx/qla_os.h b/drivers/scsi/qla2xxx/qla_os.h --- a/drivers/scsi/qla2xxx/qla_os.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/qla2xxx/qla_os.h 2004-06-20 13:00:24 -07:00 @@ -59,7 +59,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/qlogicfas.c 2004-06-20 13:00:26 -07:00 @@ -32,7 +32,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "qlogicfas408.h" /* Set the following to 2 to use normal interrupt (active high/totempole- diff -Nru a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c --- a/drivers/scsi/qlogicfas408.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/qlogicfas408.c 2004-06-20 13:00:24 -07:00 @@ -56,7 +56,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "qlogicfas408.h" /*----------------------------------------------------------------*/ diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/qlogicfc.c 2004-06-20 13:00:25 -07:00 @@ -64,7 +64,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32))) #define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a))))) @@ -100,6 +100,7 @@ #define DEFAULT_LOOP_COUNT 1000000000 +#define ISP_TIMEOUT (2*HZ) /* End Configuration section ************************************************ */ #include @@ -1305,7 +1306,7 @@ cmd->control_flags = cpu_to_le16(CFLAG_READ); if (Cmnd->device->tagged_supported) { - if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * SCSI_TIMEOUT)) { + if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * ISP_TIMEOUT)) { cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG); hostdata->tag_ages[Cmnd->device->id] = jiffies; } else diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c --- a/drivers/scsi/qlogicisp.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/qlogicisp.c 2004-06-20 13:00:26 -07:00 @@ -36,7 +36,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "qlogicisp.h" /* Configuration section *****************************************************/ diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/scsi.h 2004-06-20 13:00:23 -07:00 @@ -11,6 +11,11 @@ * add scatter-gather, multiple outstanding request, and other * enhancements. */ +/* + * NOTE: this file only contains compatibility glue for old drivers. All + * these wrappers will be removed sooner or later. For new code please use + * the interfaces declared in the headers in include/scsi/ + */ #ifndef _SCSI_H #define _SCSI_H @@ -18,6 +23,7 @@ #include /* for CONFIG_SCSI_LOGGING */ #include +#include #include #include #include @@ -34,12 +40,6 @@ #define FALSE 0 #endif -#ifdef DEBUG -#define SCSI_TIMEOUT (5*HZ) -#else -#define SCSI_TIMEOUT (2*HZ) -#endif - struct Scsi_Host; struct scsi_cmnd; struct scsi_device; @@ -47,21 +47,6 @@ struct scatterlist; /* - * Prototypes for functions in constants.c - * Some of these used to live in constants.h - */ -extern void print_Scsi_Cmnd(struct scsi_cmnd *); -extern void print_command(unsigned char *); -extern void print_sense(const char *, struct scsi_cmnd *); -extern void print_req_sense(const char *, struct scsi_request *); -extern void print_driverbyte(int scsiresult); -extern void print_hostbyte(int scsiresult); -extern void print_status(unsigned char status); -extern int print_msg(const unsigned char *); -extern const char *scsi_sense_key_string(unsigned char); -extern const char *scsi_extd_sense_format(unsigned char, unsigned char); - -/* * Legacy dma direction interfaces. * * This assumes the pci/sbus dma mapping flags have the same numercial @@ -75,6 +60,42 @@ #define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir)) #define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir)) + +/* + * Old names for debug prettyprinting functions. + */ +static inline void print_Scsi_Cmnd(struct scsi_cmnd *cmd) +{ + return scsi_print_command(cmd); +} +static inline void print_command(unsigned char *cdb) +{ + return __scsi_print_command(cdb); +} +static inline void print_sense(const char *devclass, struct scsi_cmnd *cmd) +{ + return scsi_print_sense(devclass, cmd); +} +static inline void print_req_sense(const char *devclass, struct scsi_request *req) +{ + return scsi_print_req_sense(devclass, req); +} +static inline void print_driverbyte(int scsiresult) +{ + return scsi_print_driverbyte(scsiresult); +} +static inline void print_hostbyte(int scsiresult) +{ + return scsi_print_hostbyte(scsiresult); +} +static inline void print_status(unsigned char status) +{ + return scsi_print_status(status); +} +static inline int print_msg(const unsigned char *msg) +{ + return scsi_print_msg(msg); +} /* * This is the crap from the old error handling code. We have it in a special diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/scsi_debug.c 2004-06-20 13:00:25 -07:00 @@ -1,4 +1,4 @@ -/* +/* * linux/kernel/scsi_debug.c * vvvvvvvvvvvvvvvvvvvvvvv Original vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv * Copyright (C) 1992 Eric Youngdale @@ -7,9 +7,9 @@ * anything out of the ordinary is seen. * ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - * This version is more generic, simulating a variable number of disk - * (or disk like devices) sharing a common amount of RAM - * + * This version is more generic, simulating a variable number of disk + * (or disk like devices) sharing a common amount of RAM + * * * For documentation see http://www.torque.net/sg/sdebug25.html * @@ -43,7 +43,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include @@ -55,7 +55,8 @@ #include "scsi_logging.h" #include "scsi_debug.h" -static const char * scsi_debug_version_str = "Version: 1.71 (20031007)"; +#define SCSI_DEBUG_VERSION "1.73" +static const char * scsi_debug_version_date = "20040518"; /* Additional Sense Code (ASC) used */ #define NO_ADDED_SENSE 0x0 @@ -76,11 +77,13 @@ /* With these defaults, this driver will make 1 host with 1 target * (id 0) containing 1 logical unit (lun 0). That is 1 device. */ +#define DEF_DELAY 1 #define DEF_DEV_SIZE_MB 8 #define DEF_EVERY_NTH 0 -#define DEF_DELAY 1 -#define DEF_SCSI_LEVEL 3 +#define DEF_NUM_PARTS 0 #define DEF_OPTS 0 +#define DEF_SCSI_LEVEL 3 +#define DEF_PTYPE 0 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -101,19 +104,21 @@ * or "peripheral device" addressing (value 0) */ #define SAM2_LUN_ADDRESS_METHOD 0 +static int scsi_debug_add_host = DEF_NUM_HOST; +static int scsi_debug_delay = DEF_DELAY; static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; -static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */ -static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_every_nth = DEF_EVERY_NTH; -static int scsi_debug_cmnd_count = 0; -static int scsi_debug_delay = DEF_DELAY; static int scsi_debug_max_luns = DEF_MAX_LUNS; +static int scsi_debug_num_parts = DEF_NUM_PARTS; +static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */ +static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_scsi_level = DEF_SCSI_LEVEL; -static int scsi_debug_add_host = DEF_NUM_HOST; +static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ + +static int scsi_debug_cmnd_count = 0; #define DEV_READONLY(TGT) (0) #define DEV_REMOVEABLE(TGT) (0) -#define PERIPH_DEVICE_TYPE(TGT) (TYPE_DISK); static unsigned long sdebug_store_size; /* in bytes */ static sector_t sdebug_capacity; /* in sectors */ @@ -129,6 +134,8 @@ #define SECT_SIZE (1 << POW2_SECT_SIZE) #define SECT_SIZE_PER(TGT) SECT_SIZE +#define SDEBUG_MAX_PARTS 4 + #define SDEBUG_SENSE_LEN 32 struct sdebug_dev_info { @@ -215,7 +222,7 @@ .remove = sdebug_driver_remove, }; -static const int check_condition_result = +static const int check_condition_result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; /* function declarations */ @@ -224,7 +231,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, unsigned char * buff, int bufflen, struct sdebug_dev_info * devip); -static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, +static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, int num, struct sdebug_dev_info * devip); static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, int num, struct sdebug_dev_info * devip); @@ -232,14 +239,15 @@ int bufflen, struct sdebug_dev_info * devip); static void timer_intr_handler(unsigned long); static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev); -static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, +static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, int asc, int asq, int inbandLen); -static int check_reset(struct scsi_cmnd * SCpnt, +static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip); -static int schedule_resp(struct scsi_cmnd * cmnd, - struct sdebug_dev_info * devip, +static int schedule_resp(struct scsi_cmnd * cmnd, + struct sdebug_dev_info * devip, done_funct_t done, int scsi_result, int delta_jiff); -static void init_all_queued(void); +static void __init sdebug_build_parts(unsigned char * ramp); +static void __init init_all_queued(void); static void stop_all_queued(void); static int stop_queued_cmnd(struct scsi_cmnd * cmnd); static int inquiry_evpd_83(unsigned char * arr, int dev_id_num, @@ -249,6 +257,8 @@ static int sdebug_add_adapter(void); static void sdebug_remove_adapter(void); +static void sdebug_max_tgts_luns(void); + static struct device pseudo_primary; static struct bus_type pseudo_lld_bus; @@ -257,7 +267,7 @@ if (NULL == sclp) return NULL; else if (sclp->page) - return (unsigned char *)page_address(sclp->page) + + return (unsigned char *)page_address(sclp->page) + sclp->offset; else return NULL; @@ -288,7 +298,7 @@ bufflen = sgpnt[0].length; /* READ and WRITE process scatterlist themselves */ } - else + else buff = (unsigned char *) SCpnt->request_buffer; if (NULL == buff) { buff = spare_buff; /* assume cmd moves no data */ @@ -304,11 +314,11 @@ } if (SCpnt->device->lun >= scsi_debug_max_luns) - return schedule_resp(SCpnt, NULL, done, + return schedule_resp(SCpnt, NULL, done, DID_NO_CONNECT << 16, 0); devip = devInfoReg(SCpnt->device); if (NULL == devip) - return schedule_resp(SCpnt, NULL, done, + return schedule_resp(SCpnt, NULL, done, DID_NO_CONNECT << 16, 0); if ((scsi_debug_every_nth > 0) && @@ -331,7 +341,7 @@ * shouldn't need to call REQUEST_SENSE */ if (devip) { sbuff = devip->sense_buff; - memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? + memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? bufflen : SDEBUG_SENSE_LEN); mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0, 7); } else { @@ -392,29 +402,29 @@ break; upper_blk = 0; if ((*cmd) == READ_16) { - upper_blk = cmd[5] + (cmd[4] << 8) + + upper_blk = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - block = cmd[9] + (cmd[8] << 8) + + block = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); - num = cmd[13] + (cmd[12] << 8) + + num = cmd[13] + (cmd[12] << 8) + (cmd[11] << 16) + (cmd[10] << 24); } else if ((*cmd) == READ_12) { - block = cmd[5] + (cmd[4] << 8) + + block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - num = cmd[9] + (cmd[8] << 8) + + num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); } else if ((*cmd) == READ_10) { - block = cmd[5] + (cmd[4] << 8) + + block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); num = cmd[8] + (cmd[7] << 8); } else { - block = cmd[3] + (cmd[2] << 8) + + block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); num = cmd[4]; } errsts = resp_read(SCpnt, upper_blk, block, num, devip); if (inj_recovered && (0 == errsts)) { - mk_sense_buffer(devip, RECOVERED_ERROR, + mk_sense_buffer(devip, RECOVERED_ERROR, THRESHHOLD_EXCEEDED, 0, 18); errsts = check_condition_result; } @@ -430,29 +440,29 @@ break; upper_blk = 0; if ((*cmd) == WRITE_16) { - upper_blk = cmd[5] + (cmd[4] << 8) + + upper_blk = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - block = cmd[9] + (cmd[8] << 8) + + block = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); - num = cmd[13] + (cmd[12] << 8) + + num = cmd[13] + (cmd[12] << 8) + (cmd[11] << 16) + (cmd[10] << 24); } else if ((*cmd) == WRITE_12) { - block = cmd[5] + (cmd[4] << 8) + + block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); - num = cmd[9] + (cmd[8] << 8) + + num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); } else if ((*cmd) == WRITE_10) { - block = cmd[5] + (cmd[4] << 8) + + block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); num = cmd[8] + (cmd[7] << 8); } else { - block = cmd[3] + (cmd[2] << 8) + + block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16); num = cmd[4]; } errsts = resp_write(SCpnt, upper_blk, block, num, devip); if (inj_recovered && (0 == errsts)) { - mk_sense_buffer(devip, RECOVERED_ERROR, + mk_sense_buffer(devip, RECOVERED_ERROR, THRESHHOLD_EXCEEDED, 0, 18); errsts = check_condition_result; } @@ -500,7 +510,7 @@ static const char * product_id = "scsi_debug "; static const char * product_rev = "0004"; -static int inquiry_evpd_83(unsigned char * arr, int dev_id_num, +static int inquiry_evpd_83(unsigned char * arr, int dev_id_num, const char * dev_id_str, int dev_id_str_len) { int num; @@ -537,7 +547,7 @@ { unsigned char pq_pdt; unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ]; - int min_len = bufflen > SDEBUG_MAX_INQ_ARR_SZ ? + int min_len = bufflen > SDEBUG_MAX_INQ_ARR_SZ ? SDEBUG_MAX_INQ_ARR_SZ : bufflen; if (bufflen < cmd[4]) @@ -545,7 +555,7 @@ "< alloc_length=%d\n", bufflen, (int)cmd[4]); memset(buff, 0, bufflen); memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ); - pq_pdt = PERIPH_DEVICE_TYPE(target); + pq_pdt = (scsi_debug_ptype & 0x1f); arr[0] = pq_pdt; if (0x2 & cmd[1]) { /* CMDDT bit set */ mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, @@ -573,11 +583,11 @@ dev_id_str, len); } else { /* Illegal request, invalid field in cdb */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0, 18); return check_condition_result; } - memcpy(buff, arr, min_len); + memcpy(buff, arr, min_len); return 0; } /* drops through here for a standard inquiry */ @@ -592,11 +602,11 @@ return 0; } -/* <> */ +/* <> */ static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) { /* Read-Write Error Recovery page for mode_sense */ - unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0, + unsigned char err_recov_pg[] = {0x1, 0xa, 0xc0, 11, 240, 0, 0, 0, 5, 0, 0xff, 0xff}; memcpy(p, err_recov_pg, sizeof(err_recov_pg)); @@ -607,7 +617,7 @@ static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target) { /* Disconnect-Reconnect page for mode_sense */ - unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0, + unsigned char disconnect_pg[] = {0x2, 0xe, 128, 128, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; memcpy(p, disconnect_pg, sizeof(disconnect_pg)); @@ -636,7 +646,7 @@ static int resp_caching_pg(unsigned char * p, int pcontrol, int target) { /* Caching page for mode_sense */ - unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, + unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; memcpy(p, caching_pg, sizeof(caching_pg)); @@ -678,7 +688,7 @@ int alloc_len, msense_6, offset, len; unsigned char * ap; unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; - int min_len = bufflen > SDEBUG_MAX_MSENSE_SZ ? + int min_len = bufflen > SDEBUG_MAX_MSENSE_SZ ? SDEBUG_MAX_MSENSE_SZ : bufflen; SCSI_LOG_LLQUEUE(3, printk("Mode sense ...(%p %d)\n", buff, bufflen)); @@ -753,14 +763,14 @@ arr[0] = offset - 1; else { offset -= 2; - arr[0] = (offset >> 8) & 0xff; - arr[1] = offset & 0xff; + arr[0] = (offset >> 8) & 0xff; + arr[1] = offset & 0xff; } memcpy(buff, arr, min_len); return 0; } -static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, +static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, int num, struct sdebug_dev_info * devip) { unsigned char *buff = (unsigned char *) SCpnt->request_buffer; @@ -770,14 +780,14 @@ unsigned long iflags; if (upper_blk || (block + num > sdebug_capacity)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, + mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0, 18); return check_condition_result; } if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && - (block <= OPT_MEDIUM_ERR_ADDR) && + (block <= OPT_MEDIUM_ERR_ADDR) && ((block + num) > OPT_MEDIUM_ERR_ADDR)) { - mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, + mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0, 18); /* claim unrecoverable read error */ return check_condition_result; @@ -785,7 +795,7 @@ read_lock_irqsave(&atomic_rw, iflags); sgcount = 0; nbytes = bufflen; - /* printk(KERN_INFO "scsi_debug_read: block=%d, tot_bufflen=%d\n", + /* printk(KERN_INFO "scsi_debug_read: block=%d, tot_bufflen=%d\n", block, bufflen); */ if (SCpnt->use_sg) { sgcount = 0; @@ -857,7 +867,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff, int bufflen, struct sdebug_dev_info * devip) { - unsigned int alloc_len; + unsigned int alloc_len; int lun_cnt, i, upper; int select_report = (int)cmd[2]; struct scsi_lun *one_lun; @@ -868,19 +878,19 @@ 0, 18); return check_condition_result; } - if (bufflen > 8) { /* can produce response with up to 16k luns + if (bufflen > 8) { /* can produce response with up to 16k luns (lun 0 to lun 16383) */ memset(buff, 0, bufflen); lun_cnt = scsi_debug_max_luns; buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff; buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff; - lun_cnt = min((int)((bufflen - 8) / sizeof(struct scsi_lun)), + lun_cnt = min((int)((bufflen - 8) / sizeof(struct scsi_lun)), lun_cnt); one_lun = (struct scsi_lun *) &buff[8]; for (i = 0; i < lun_cnt; i++) { upper = (i >> 8) & 0x3f; if (upper) - one_lun[i].scsi_lun[0] = + one_lun[i].scsi_lun[0] = (upper | (SAM2_LUN_ADDRESS_METHOD << 6)); one_lun[i].scsi_lun[1] = i & 0xff; } @@ -926,7 +936,7 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp) { - struct sdebug_dev_info * devip; + struct sdebug_dev_info * devip; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", @@ -936,14 +946,14 @@ devip = devInfoReg(sdp); sdp->hostdata = devip; if (sdp->host->cmd_per_lun) - scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, + scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, sdp->host->cmd_per_lun); return 0; } static void scsi_debug_slave_destroy(struct scsi_device * sdp) { - struct sdebug_dev_info * devip = + struct sdebug_dev_info * devip = (struct sdebug_dev_info *)sdp->hostdata; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) @@ -980,6 +990,18 @@ open_devip = devip; } } + if (NULL == open_devip) { /* try and make a new one */ + open_devip = kmalloc(sizeof(*open_devip),GFP_KERNEL); + if (NULL == open_devip) { + printk(KERN_ERR "%s: out of memory at line %d\n", + __FUNCTION__, __LINE__); + return NULL; + } + memset(open_devip, 0, sizeof(*open_devip)); + open_devip->sdbg_host = sdbg_host; + list_add_tail(&open_devip->dev_list, + &sdbg_host->dev_info_list); + } if (open_devip) { open_devip->channel = sdev->channel; open_devip->target = sdev->id; @@ -994,7 +1016,7 @@ return NULL; } -static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, +static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, int asc, int asq, int inbandLen) { unsigned char * sbuff; @@ -1029,7 +1051,7 @@ printk(KERN_INFO "scsi_debug: biosparam\n"); buf = scsi_bios_ptable(bdev); if (buf) { - res = scsi_partsize(buf, capacity, + res = scsi_partsize(buf, capacity, &info[2], &info[0], &info[1]); kfree(buf); if (! res) @@ -1138,7 +1160,7 @@ } /* Initializes timers in queued array */ -static void init_all_queued(void) +static void __init init_all_queued(void) { unsigned long iflags; int k; @@ -1154,11 +1176,61 @@ spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static int schedule_resp(struct scsi_cmnd * cmnd, +static void __init sdebug_build_parts(unsigned char * ramp) +{ + struct partition * pp; + int starts[SDEBUG_MAX_PARTS + 2]; + int sectors_per_part, num_sectors, k; + int heads_by_sects, start_sec, end_sec; + + /* assume partition table already zeroed */ + if ((scsi_debug_num_parts < 1) || (sdebug_store_size < 1048576)) + return; + if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { + scsi_debug_num_parts = SDEBUG_MAX_PARTS; + printk(KERN_WARNING "scsi_debug:build_parts: reducing " + "partitions to %d\n", SDEBUG_MAX_PARTS); + } + num_sectors = (int)(sdebug_store_size / SECT_SIZE); + sectors_per_part = (num_sectors - sdebug_sectors_per) + / scsi_debug_num_parts; + heads_by_sects = sdebug_heads * sdebug_sectors_per; + starts[0] = sdebug_sectors_per; + for (k = 1; k < scsi_debug_num_parts; ++k) + starts[k] = ((k * sectors_per_part) / heads_by_sects) + * heads_by_sects; + starts[scsi_debug_num_parts] = num_sectors; + starts[scsi_debug_num_parts + 1] = 0; + + ramp[510] = 0x55; /* magic partition markings */ + ramp[511] = 0xAA; + pp = (struct partition *)(ramp + 0x1be); + for (k = 0; starts[k + 1]; ++k, ++pp) { + start_sec = starts[k]; + end_sec = starts[k + 1] - 1; + pp->boot_ind = 0; + + pp->cyl = start_sec / heads_by_sects; + pp->head = (start_sec - (pp->cyl * heads_by_sects)) + / sdebug_sectors_per; + pp->sector = (start_sec % sdebug_sectors_per) + 1; + + pp->end_cyl = end_sec / heads_by_sects; + pp->end_head = (end_sec - (pp->end_cyl * heads_by_sects)) + / sdebug_sectors_per; + pp->end_sector = (end_sec % sdebug_sectors_per) + 1; + + pp->start_sect = start_sec; + pp->nr_sects = end_sec - start_sec + 1; + pp->sys_ind = 0x83; /* plain Linux partition */ + } +} + +static int schedule_resp(struct scsi_cmnd * cmnd, struct sdebug_dev_info * devip, done_funct_t done, int scsi_result, int delta_jiff) { - int k, num; + int k, num; if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) { printk(KERN_INFO "scsi_debug: cmd "); @@ -1176,7 +1248,7 @@ if (cmnd && devip) { /* simulate autosense by this driver */ if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff)) - memcpy(cmnd->sense_buffer, devip->sense_buff, + memcpy(cmnd->sense_buffer, devip->sense_buff, (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ? SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE); } @@ -1219,38 +1291,43 @@ /* Set 'perm' (4th argument) to 0 to disable module_param's definition * of sysfs parameters (which module_param doesn't yet support). - * Sysfs parameters defined explicitly below. + * Sysfs parameters defined explicitly below. */ -module_param_named(num_tgts, scsi_debug_num_tgts, int, 0); -module_param_named(max_luns, scsi_debug_max_luns, int, 0); -module_param_named(scsi_level, scsi_debug_scsi_level, int, 0); +module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */ +module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */ module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0); -module_param_named(opts, scsi_debug_opts, int, 0); /* perm=0644 */ module_param_named(every_nth, scsi_debug_every_nth, int, 0); -module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */ -module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */ +module_param_named(max_luns, scsi_debug_max_luns, int, 0); +module_param_named(num_parts, scsi_debug_num_parts, int, 0); +module_param_named(num_tgts, scsi_debug_num_tgts, int, 0); +module_param_named(opts, scsi_debug_opts, int, 0); /* perm=0644 */ +module_param_named(ptype, scsi_debug_ptype, int, 0); +module_param_named(scsi_level, scsi_debug_scsi_level, int, 0); MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(SCSI_DEBUG_VERSION); -MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate"); -MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate"); -MODULE_PARM_DESC(scsi_level, "SCSI level to simulate"); +MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); +MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs"); -MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->..."); MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)"); -MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)"); -MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); +MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate"); +MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); +MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate"); +MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->..."); +MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); +MODULE_PARM_DESC(scsi_level, "SCSI level to simulate"); static char sdebug_info[256]; static const char * scsi_debug_info(struct Scsi_Host * shp) { - sprintf(sdebug_info, "scsi_debug, %s, num_tgts=%d, " - "dev_size_mb=%d, opts=0x%x", scsi_debug_version_str, - scsi_debug_num_tgts, scsi_debug_dev_size_mb, + sprintf(sdebug_info, "scsi_debug, version %s [%s], " + "dev_size_mb=%d, opts=0x%x", SCSI_DEBUG_VERSION, + scsi_debug_version_date, scsi_debug_dev_size_mb, scsi_debug_opts); return sdebug_info; } @@ -1282,14 +1359,15 @@ return length; } begin = 0; - pos = len = sprintf(buffer, "scsi_debug adapter driver, %s\n" + pos = len = sprintf(buffer, "scsi_debug adapter driver, version " + "%s [%s]\n" "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " "every_nth=%d(curr:%d)\n" "delay=%d, max_luns=%d, scsi_level=%d\n" "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" - "number of aborts=%d, device_reset=%d, bus_resets=%d, " + "number of aborts=%d, device_reset=%d, bus_resets=%d, " "host_resets=%d\n", - scsi_debug_version_str, scsi_debug_num_tgts, + SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_max_luns, scsi_debug_scsi_level, @@ -1306,12 +1384,12 @@ return len; } -static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); } -static ssize_t sdebug_delay_store(struct device_driver * ddp, +static ssize_t sdebug_delay_store(struct device_driver * ddp, const char * buf, size_t count) { int delay; @@ -1325,15 +1403,15 @@ } return -EINVAL; } -DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, +DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show, sdebug_delay_store) -static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); } -static ssize_t sdebug_opts_store(struct device_driver * ddp, +static ssize_t sdebug_opts_store(struct device_driver * ddp, const char * buf, size_t count) { int opts; @@ -1354,38 +1432,62 @@ scsi_debug_cmnd_count = 0; return count; } -DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, +DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show, sdebug_opts_store) -static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_ptype_show(struct device_driver * ddp, char * buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ptype); +} +static ssize_t sdebug_ptype_store(struct device_driver * ddp, + const char * buf, size_t count) +{ + int n; + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { + scsi_debug_ptype = n; + return count; + } + return -EINVAL; +} +DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store) + +static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); } -static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, +static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, const char * buf, size_t count) { int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { scsi_debug_num_tgts = n; + sdebug_max_tgts_luns(); return count; } return -EINVAL; } -DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show, - sdebug_num_tgts_store) +DRIVER_ATTR(num_tgts, S_IRUGO | S_IWUSR, sdebug_num_tgts_show, + sdebug_num_tgts_store) -static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); } -DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) +DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) + +static ssize_t sdebug_num_parts_show(struct device_driver * ddp, char * buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_parts); +} +DRIVER_ATTR(num_parts, S_IRUGO, sdebug_num_parts_show, NULL) -static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); } -static ssize_t sdebug_every_nth_store(struct device_driver * ddp, +static ssize_t sdebug_every_nth_store(struct device_driver * ddp, const char * buf, size_t count) { int nth; @@ -1398,38 +1500,39 @@ return -EINVAL; } DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show, - sdebug_every_nth_store) + sdebug_every_nth_store) -static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); } -static ssize_t sdebug_max_luns_store(struct device_driver * ddp, +static ssize_t sdebug_max_luns_store(struct device_driver * ddp, const char * buf, size_t count) { int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { scsi_debug_max_luns = n; + sdebug_max_tgts_luns(); return count; } return -EINVAL; } -DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show, - sdebug_max_luns_store) +DRIVER_ATTR(max_luns, S_IRUGO | S_IWUSR, sdebug_max_luns_show, + sdebug_max_luns_store) -static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); } -DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) +DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) -static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) +static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); } -static ssize_t sdebug_add_host_store(struct device_driver * ddp, +static ssize_t sdebug_add_host_store(struct device_driver * ddp, const char * buf, size_t count) { int delta_hosts; @@ -1463,26 +1566,30 @@ static void do_create_driverfs_files(void) { + driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host); driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth); driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns); + driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); + driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts); + driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype); + driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts); driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); - driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host); } static void do_remove_driverfs_files(void) { - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ptype); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_parts); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_max_luns); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_every_nth); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_num_tgts); - driver_remove_file(&sdebug_driverfs_driver, &driver_attr_opts); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_delay); + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host); } static int __init scsi_debug_init(void) @@ -1491,23 +1598,25 @@ int host_to_add; int k; + if (scsi_debug_dev_size_mb < 1) + scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ sdebug_store_size = (unsigned long)scsi_debug_dev_size_mb * 1048576; sdebug_capacity = sdebug_store_size / SECT_SIZE; /* play around with geometry, don't waste too much on track 0 */ sdebug_heads = 8; sdebug_sectors_per = 32; - if (scsi_debug_dev_size_mb >= 16) + if (scsi_debug_dev_size_mb >= 16) sdebug_heads = 32; else if (scsi_debug_dev_size_mb >= 256) sdebug_heads = 64; - sdebug_cylinders_per = (unsigned long)sdebug_capacity / + sdebug_cylinders_per = (unsigned long)sdebug_capacity / (sdebug_sectors_per * sdebug_heads); - if (sdebug_cylinders_per >= 1024) { + if (sdebug_cylinders_per >= 1024) { /* other LLDs do this; implies >= 1GB ram disk ... */ sdebug_heads = 255; sdebug_sectors_per = 63; - sdebug_cylinders_per = (unsigned long)sdebug_capacity / + sdebug_cylinders_per = (unsigned long)sdebug_capacity / (sdebug_sectors_per * sdebug_heads); } @@ -1518,6 +1627,8 @@ return -ENOMEM; } memset(fake_storep, 0, sz); + if (scsi_debug_num_parts > 0) + sdebug_build_parts(fake_storep); init_all_queued(); @@ -1575,7 +1686,7 @@ .release = pseudo_0_release, }; -static int pseudo_lld_bus_match(struct device *dev, +static int pseudo_lld_bus_match(struct device *dev, struct device_driver *dev_driver) { return 1; @@ -1736,4 +1847,22 @@ scsi_host_put(sdbg_host->shost); return 0; +} + +static void sdebug_max_tgts_luns(void) +{ + struct sdebug_host_info * sdbg_host; + struct Scsi_Host *hpnt; + + spin_lock(&sdebug_host_list_lock); + list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { + hpnt = sdbg_host->shost; + if ((hpnt->this_id >= 0) && + (scsi_debug_num_tgts > hpnt->this_id)) + hpnt->max_id = scsi_debug_num_tgts + 1; + else + hpnt->max_id = scsi_debug_num_tgts; + hpnt->max_lun = scsi_debug_max_luns; + } + spin_unlock(&sdebug_host_list_lock); } diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h --- a/drivers/scsi/scsi_debug.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/scsi_debug.h 2004-06-20 13:00:24 -07:00 @@ -5,7 +5,7 @@ static int scsi_debug_slave_alloc(struct scsi_device *); static int scsi_debug_slave_configure(struct scsi_device *); static void scsi_debug_slave_destroy(struct scsi_device *); -static int scsi_debug_queuecommand(struct scsi_cmnd *, +static int scsi_debug_queuecommand(struct scsi_cmnd *, void (*done) (struct scsi_cmnd *)); static int scsi_debug_ioctl(struct scsi_device *, int, void *); static int scsi_debug_biosparam(struct scsi_device *, struct block_device *, @@ -17,9 +17,6 @@ static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); static const char * scsi_debug_info(struct Scsi_Host *); -/* - * This driver is written for the lk 2.5 series - */ #define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */ #define SCSI_DEBUG_MAX_CMD_LEN 16 diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c --- a/drivers/scsi/scsi_devinfo.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/scsi_devinfo.c 2004-06-20 13:00:24 -07:00 @@ -9,7 +9,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "scsi_priv.h" /* @@ -27,7 +27,7 @@ static const char spaces[] = " "; /* 16 of them */ static unsigned scsi_default_dev_flags; static LIST_HEAD(scsi_dev_info_list); -static __init char scsi_dev_flags[256]; +static __initdata char scsi_dev_flags[256]; /* * scsi_static_device_list: deprecated list of devices that require @@ -117,8 +117,10 @@ */ {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, - {"BELKIN", "USB 2 HS-CF", "1.95", BLIST_SPARSELUN}, + {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN}, + {"BELKIN", "USB 2 HS-CF", "1.95", BLIST_FORCELUN}, {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN}, + {"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN}, {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ @@ -139,6 +141,7 @@ {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN}, {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN}, {"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN}, {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, @@ -171,6 +174,7 @@ {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN}, {"SGI", "RAID3", "*", BLIST_SPARSELUN}, {"SGI", "RAID5", "*", BLIST_SPARSELUN}, {"SGI", "TP9100", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, @@ -182,6 +186,7 @@ {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, {"TOSHIBA", "CDROM", NULL, BLIST_ISROM}, {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM}, + {"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN}, {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/scsi_error.c 2004-06-20 13:00:23 -07:00 @@ -26,25 +26,20 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "scsi_priv.h" #include "scsi_logging.h" -#ifdef DEBUG -#define SENSE_TIMEOUT SCSI_TIMEOUT -#else -#define SENSE_TIMEOUT (10*HZ) -#endif - -#define START_UNIT_TIMEOUT (30*HZ) +#define SENSE_TIMEOUT (10*HZ) +#define START_UNIT_TIMEOUT (30*HZ) /* * These should *probably* be handled by the host itself. * Since it is allowed to sleep, it probably should. */ -#define BUS_RESET_SETTLE_TIME 10*HZ -#define HOST_RESET_SETTLE_TIME 10*HZ +#define BUS_RESET_SETTLE_TIME (10*HZ) +#define HOST_RESET_SETTLE_TIME (10*HZ) /* called with shost->host_lock held */ void scsi_eh_wakeup(struct Scsi_Host *shost) @@ -1026,7 +1021,8 @@ spin_unlock_irqrestore(scmd->device->host->host_lock, flags); if (rtn == SUCCESS) { - scsi_sleep(BUS_RESET_SETTLE_TIME); + if (!scmd->device->host->hostt->skip_settle_delay) + scsi_sleep(BUS_RESET_SETTLE_TIME); spin_lock_irqsave(scmd->device->host->host_lock, flags); scsi_report_bus_reset(scmd->device->host, scmd->device->channel); spin_unlock_irqrestore(scmd->device->host->host_lock, flags); @@ -1057,7 +1053,8 @@ spin_unlock_irqrestore(scmd->device->host->host_lock, flags); if (rtn == SUCCESS) { - scsi_sleep(HOST_RESET_SETTLE_TIME); + if (!scmd->device->host->hostt->skip_settle_delay) + scsi_sleep(HOST_RESET_SETTLE_TIME); spin_lock_irqsave(scmd->device->host->host_lock, flags); scsi_report_bus_reset(scmd->device->host, scmd->device->channel); spin_unlock_irqrestore(scmd->device->host->host_lock, flags); diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c --- a/drivers/scsi/scsi_ioctl.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/scsi_ioctl.c 2004-06-20 13:00:26 -07:00 @@ -20,7 +20,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include "scsi_logging.h" @@ -446,20 +446,4 @@ return sdev->host->hostt->ioctl(sdev, cmd, arg); } return -EINVAL; -} - -/* - * Just like scsi_ioctl, only callable from kernel space with no - * fs segment fiddling. - */ - -int kernel_scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg) -{ - mm_segment_t oldfs; - int tmp; - oldfs = get_fs(); - set_fs(get_ds()); - tmp = scsi_ioctl(sdev, cmd, arg); - set_fs(oldfs); - return tmp; } diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/scsi_lib.c 2004-06-20 13:00:24 -07:00 @@ -255,7 +255,6 @@ sreq->sr_request->rq_status = RQ_SCSI_BUSY; scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done, timeout, retries); - generic_unplug_device(sreq->sr_device->request_queue); wait_for_completion(&wait); sreq->sr_request->waiting = NULL; if (sreq->sr_request->rq_status != RQ_SCSI_DONE) diff -Nru a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c --- a/drivers/scsi/scsi_module.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/scsi_module.c 2004-06-20 13:00:23 -07:00 @@ -12,7 +12,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include static int __init init_this_scsi_driver(void) diff -Nru a/drivers/scsi/scsi_pc98.c b/drivers/scsi/scsi_pc98.c --- a/drivers/scsi/scsi_pc98.c 2004-06-20 13:00:23 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2003 Osamu Tomita - * - * PC9801 BIOS geometry handling. - */ - -#include -#include -#include -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" - - -static int pc98_first_bios_param(struct scsi_device *sdev, int *ip) -{ - const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS) + sdev->id * 4); - - ip[0] = p[1]; /* # of heads */ - ip[1] = p[0]; /* # of sectors/track */ - ip[2] = *(u16 *)&p[2] & 0x0fff; /* # of cylinders */ - if (p[3] & (1 << 6)) { /* #-of-cylinders is 16-bit */ - ip[2] |= (ip[0] & 0xf0) << 8; - ip[0] &= 0x0f; - } - - return 0; -} - -int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *ip) -{ - struct Scsi_Host *first_real = first_real_host(); - - /* - * XXX - * XXX This needs to become a sysfs attribute that's set - * XXX by code that knows which host is the first one. - * XXX - * XXX Currently we support only one host on with a - * XXX PC98ish HBA. - * XXX - */ - if (1 || sdev->host == first_real && sdev->id < 7 && - __PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id)) - return pc98_first_bios_param(sdev, ip); - - /* Assume PC-9801-92 compatible parameters for HAs without BIOS. */ - ip[0] = 8; - ip[1] = 32; - ip[2] = capacity / (8 * 32); - if (ip[2] > 65535) { /* if capacity >= 8GB */ - /* Recent on-board adapters seem to use this parameter. */ - ip[1] = 128; - ip[2] = capacity / (8 * 128); - if (ip[2] > 65535) { /* if capacity >= 32GB */ - /* Clip the number of cylinders. Currently - this is the limit that we deal with. */ - ip[2] = 65535; - } - } - - return 0; -} - -EXPORT_SYMBOL(pc98_bios_param); diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/scsi_scan.c 2004-06-20 13:00:25 -07:00 @@ -45,6 +45,11 @@ " SCSI scanning, some SCSI devices might not be configured\n" /* + * Default timeout + */ +#define SCSI_TIMEOUT (2*HZ) + +/* * Prefix values for the SCSI id's (stored in driverfs name field) */ #define SCSI_UID_SER_NUM 'S' diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c --- a/drivers/scsi/scsi_syms.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/scsi_syms.c 2004-06-20 13:00:24 -07:00 @@ -46,15 +46,14 @@ EXPORT_SYMBOL(scsi_partsize); EXPORT_SYMBOL(scsi_bios_ptable); EXPORT_SYMBOL(scsi_ioctl); -EXPORT_SYMBOL(print_command); -EXPORT_SYMBOL(print_sense); -EXPORT_SYMBOL(print_req_sense); -EXPORT_SYMBOL(print_msg); -EXPORT_SYMBOL(print_status); +EXPORT_SYMBOL(scsi_print_command); +EXPORT_SYMBOL(__scsi_print_command); +EXPORT_SYMBOL(scsi_print_sense); +EXPORT_SYMBOL(scsi_print_req_sense); +EXPORT_SYMBOL(scsi_print_msg); +EXPORT_SYMBOL(scsi_print_status); EXPORT_SYMBOL(scsi_sense_key_string); EXPORT_SYMBOL(scsi_extd_sense_format); -EXPORT_SYMBOL(kernel_scsi_ioctl); -EXPORT_SYMBOL(print_Scsi_Cmnd); EXPORT_SYMBOL(scsi_block_when_processing_errors); EXPORT_SYMBOL(scsi_ioctl_send_command); EXPORT_SYMBOL(scsi_set_medium_removal); diff -Nru a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c --- a/drivers/scsi/scsi_transport_spi.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/scsi_transport_spi.c 2004-06-20 13:00:24 -07:00 @@ -173,7 +173,7 @@ spi_dv_device(sdev); return count; } -static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate) +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 */ @@ -390,10 +390,11 @@ { struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); struct scsi_device *sdev = sreq->sr_device; - int period, prevperiod = 0; + int period = 0, prevperiod = 0; for (;;) { + int newperiod; if (compare_fn(sreq, buffer, ptr, DV_LOOPS)) /* Successful DV */ break; @@ -401,7 +402,8 @@ /* OK, retrain, fallback */ if (i->f->get_period) i->f->get_period(sdev); - period = spi_period(sdev); + newperiod = spi_period(sdev); + period = newperiod > period ? newperiod : period; if (period < 0x0d) period++; else diff -Nru a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c --- a/drivers/scsi/scsicam.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/scsicam.c 2004-06-20 13:00:24 -07:00 @@ -19,7 +19,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds, diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c --- a/drivers/scsi/scsiiom.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/scsiiom.c 2004-06-20 13:00:23 -07:00 @@ -12,7 +12,7 @@ pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */ pSRB->TagNumber = 255; } -}; +} static UCHAR @@ -75,7 +75,7 @@ printk (KERN_WARNING "DC390: Out of tags for Dev. %02x %02x\n", pDCB->TargetID, pDCB->TargetLUN); return 1; //goto no_tag; - }; + } DC390_write8 (ScsiFifo, SIMPLE_QUEUE_TAG); pDCB->TagMask |= (1 << tag_no); pSRB->TagNumber = tag_no; DC390_write8 (ScsiFifo, tag_no); @@ -86,7 +86,7 @@ { // no_tag: DEBUG1(printk (KERN_DEBUG "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", (disc_allowed?"":"o"), pSRB->pcmd->pid, pSRB)); - }; + } pSRB->SRBState = SRB_START_; @@ -104,7 +104,7 @@ //pSRB->SRBState = SRB_MSGOUT_; pSRB->SRBState |= DO_SYNC_NEGO; cmd = SEL_W_ATN_STOP; - }; + } /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */ if (cmd != SEL_W_ATN_STOP) @@ -125,7 +125,7 @@ ptr = (PUCHAR) pSRB->pcmd->cmnd; for (i=0; ipcmd->cmd_len; i++) DC390_write8 (ScsiFifo, *(ptr++)); - }; + } } DEBUG0(if (pACB->pActiveDCB) \ printk (KERN_WARNING "DC390: ActiveDCB != 0\n")); @@ -141,7 +141,7 @@ //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pACB->SelLost++; return 1; - }; + } DC390_write8 (ScsiCmd, cmd); pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB; pACB->Connected = 1; @@ -176,7 +176,7 @@ { printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate); return dstate; - }; + } if (dstate & DMA_XFER_DONE) { UINT residual, xferCnt; int ctr = 6000000; @@ -253,7 +253,7 @@ { DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n")); return IRQ_NONE; - }; + } #else //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); //dstatus = DC390_read8 (DMA_Status); @@ -313,7 +313,7 @@ { printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n"); goto unlock; - }; + } pSRB = pDCB->pActiveSRB; if( pDCB->DCBFlag & ABORT_DEV_ ) dc390_EnableMsgOut_Abort (pACB, pSRB); @@ -549,7 +549,7 @@ DC390_write8 (CtrlReg3, pDCB->CtrlR3); DC390_write8 (CtrlReg4, pDCB->CtrlR4); dc390_SetXferRate (pACB, pDCB); -}; +} #ifdef DC390_DEBUG0 @@ -561,7 +561,7 @@ for (i = 1; i < len; i++) printk (" %02x", MsgBuf[i]); printk ("\n"); -}; +} #endif #define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD) @@ -671,11 +671,11 @@ { printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2); pSRB->MsgInBuf[3] = pDCB->NegoPeriod; - }; + } memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5); pSRB->MsgCnt = 5; DC390_ENABLE_MSGOUT; - }; + } pSRB->SRBState &= ~DO_SYNC_NEGO; pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; @@ -713,7 +713,7 @@ } dc390_reprog (pACB, pDCB); -}; +} /* handle RESTORE_PTR */ @@ -761,7 +761,7 @@ } pSRB->TotalXferredLen = pSRB->Saved_Ptr; -}; +} /* According to the docs, the AM53C974 reads the message and @@ -789,7 +789,7 @@ /* read and eval received messages */ -void +static void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { PDCB pDCB = pACB->pActiveDCB; @@ -832,7 +832,7 @@ dc390_MsgIn_set_async (pACB, pSRB); else dc390_MsgIn_set_sync (pACB, pSRB); - }; + } // nothing has to be done case COMMAND_COMPLETE: break; @@ -948,7 +948,7 @@ dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION); } -void +static void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { PDCB pDCB; @@ -989,7 +989,7 @@ //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } -void +static void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { UCHAR bval, i, cnt; @@ -1097,7 +1097,7 @@ } -void +static void dc390_Disconnect( PACB pACB ) { PDCB pDCB; @@ -1179,7 +1179,7 @@ } -void +static void dc390_Reselect( PACB pACB ) { PDCB pDCB; @@ -1276,7 +1276,7 @@ DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\ pDCB->TargetID, pDCB->TargetLUN, (int)pDCB, pDCB->GoingSRBCnt)); return; - }; + } pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN); // The first one @@ -1302,8 +1302,7 @@ if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB; kfree (pDCB); pACB->DCBCnt--; - /* pACB->DeviceCnt--; */ -}; +} static UCHAR __inline__ @@ -1314,7 +1313,7 @@ if (memcmp (name, dc390_baddevname1[i], 28) == 0) return 1; return 0; -}; +} static void @@ -1336,7 +1335,7 @@ else pDCB->MaxCommand = 1; } -}; +} static void @@ -1346,13 +1345,13 @@ pDCB->DevType = bval1; /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */ dc390_disc_tagq_set (pDCB, ptr); -}; +} -void +static void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) { - UCHAR bval, status, i, DCB_removed; + UCHAR bval, status, i; PSCSICMD pcmd; PSCSI_INQDATA ptr; PSGL ptr2; @@ -1362,11 +1361,10 @@ /* KG: Moved pci_unmap here */ dc390_pci_unmap(pSRB); - DCB_removed = 0; status = pSRB->TargetStatus; ptr = (PSCSI_INQDATA) (pcmd->request_buffer); if( pcmd->use_sg ) - ptr = (PSCSI_INQDATA) sg_dma_address((PSGL) ptr); + ptr = (PSCSI_INQDATA) (page_address(((PSGL) ptr)->page) + ((PSGL) ptr)->offset); DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\ pSRB, pcmd->pid)); @@ -1564,55 +1562,22 @@ pcmd->sense_buffer[2], pcmd->sense_buffer[3]); else printk ("\n"); #endif - if( (host_byte(pcmd->result) != DID_OK && !(status_byte(pcmd->result) & CHECK_CONDITION) && !(status_byte(pcmd->result) & BUSY)) || - ((driver_byte(pcmd->result) & DRIVER_SENSE) && (pcmd->sense_buffer[0] & 0x70) == 0x70 && - (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || host_byte(pcmd->result) & DID_ERROR ) - { - /* device not present: remove */ - //dc390_Going_remove (pDCB, pSRB); - dc390_remove_dev (pACB, pDCB); DCB_removed = 1; - - if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) && - ((pcmd->device->lun == 0) || (pcmd->device->lun == pACB->pScsiHost->max_lun - 1)) ) - pACB->scan_devices = 0; - } - else - { - /* device present: add */ - if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) && - (pcmd->device->lun == pACB->pScsiHost->max_lun - 1) ) - pACB->scan_devices = END_SCAN ; - /* pACB->DeviceCnt++; */ /* Dev is added on INQUIRY */ - } } } - - //if( pSRB->pcmd->cmnd[0] == INQUIRY && - // (host_byte(pcmd->result) == DID_OK || status_byte(pcmd->result) & CHECK_CONDITION) ) + if( pcmd->cmnd[0] == INQUIRY && (pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) ) { - if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV && !DCB_removed) - { - //printk ("DC390: Type = nodev! (%02i-%i)\n", pcmd->target, pcmd->lun); - /* device not present: remove */ - //dc390_Going_remove (pDCB, pSRB); - dc390_remove_dev (pACB, pDCB); DCB_removed = 1; - } - else + if ((ptr->DevType & SCSI_DEVTYPE) != TYPE_NODEV) { /* device found: add */ dc390_add_dev (pACB, pDCB, ptr); - if (pACB->scan_devices) pACB->DeviceCnt++; } - if( (pcmd->device->id == pACB->pScsiHost->max_id - 1) && - (pcmd->device->lun == pACB->pScsiHost->max_lun - 1) ) - pACB->scan_devices = 0; - }; + } pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen; - if (!DCB_removed) dc390_Going_remove (pDCB, pSRB); + dc390_Going_remove (pDCB, pSRB); /* Add to free list */ dc390_Free_insert (pACB, pSRB); @@ -1625,7 +1590,7 @@ /* Remove all SRBs from Going list and inform midlevel */ -void +static void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ) { PDCB pDCB, pdcb; @@ -1760,4 +1725,3 @@ if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) ) DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); } - diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/sd.c 2004-06-20 13:00:25 -07:00 @@ -52,7 +52,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include @@ -763,11 +763,11 @@ good_bytes = 0; break; - case RECOVERED_ERROR: + case RECOVERED_ERROR: /* an error occurred, but it recovered */ + case NO_SENSE: /* LLDD got sense data */ /* - * An error occurred, but it recovered. Inform the - * user, but make sure that it's not treated as a - * hard error. + * Inform the user, but make sure that it's not treated + * as a hard error. */ print_sense("sd", SCpnt); SCpnt->result = 0; diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c --- a/drivers/scsi/seagate.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/seagate.c 2004-06-20 13:00:24 -07:00 @@ -103,7 +103,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "seagate.h" #include diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/sg.c 2004-06-20 13:00:24 -07:00 @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include #include @@ -60,7 +59,7 @@ #ifdef CONFIG_SCSI_PROC_FS #include -static char *sg_version_date = "20040513"; +static char *sg_version_date = "20040516"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -73,7 +72,7 @@ #define SG_ALLOW_DIO_DEF 0 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ -#define SG_MAX_DEVS 8192 +#define SG_MAX_DEVS 32768 /* * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) @@ -718,7 +717,6 @@ (void *) SRpnt->sr_buffer, hp->dxfer_len, sg_cmd_done, timeout, SG_DEFAULT_RETRIES); /* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */ - generic_unplug_device(q); return 0; } @@ -1331,9 +1329,11 @@ void *old_sg_dev_arr = NULL; int k, error; - sdp = vmalloc(sizeof(Sg_device)); - if (!sdp) + sdp = kmalloc(sizeof(Sg_device), GFP_KERNEL); + if (!sdp) { + printk(KERN_WARNING "kmalloc Sg_device failure\n"); return -ENOMEM; + } write_lock_irqsave(&sg_dev_arr_lock, iflags); if (unlikely(sg_nr_dev >= sg_dev_max)) { /* try to resize */ @@ -1341,7 +1341,7 @@ int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - tmp_da = vmalloc(tmp_dev_max * sizeof(Sg_device *)); + tmp_da = kmalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL); if (unlikely(!tmp_da)) goto expand_failed; @@ -1375,12 +1375,12 @@ out: if (error < 0) - vfree(sdp); - vfree(old_sg_dev_arr); + kfree(sdp); + kfree(old_sg_dev_arr); return error; expand_failed: - printk(KERN_ERR "sg_alloc: device array cannot be resized\n"); + printk(KERN_WARNING "sg_alloc: device array cannot be resized\n"); error = -ENOMEM; goto out; @@ -1404,20 +1404,26 @@ int error, k; disk = alloc_disk(1); - if (!disk) + if (!disk) { + printk(KERN_WARNING "alloc_disk failed\n"); return -ENOMEM; + } disk->major = SCSI_GENERIC_MAJOR; error = -ENOMEM; cdev = cdev_alloc(); - if (!cdev) + if (!cdev) { + printk(KERN_WARNING "cdev_alloc failed\n"); goto out; + } cdev->owner = THIS_MODULE; cdev->ops = &sg_fops; error = sg_alloc(disk, scsidp); - if (error < 0) + if (error < 0) { + printk(KERN_WARNING "sg_alloc failed\n"); goto out; + } k = error; sdp = sg_dev_arr[k]; @@ -1525,7 +1531,7 @@ put_disk(sdp->disk); sdp->disk = NULL; if (NULL == sdp->headfp) - vfree((char *) sdp); + kfree((char *) sdp); } if (delay) @@ -1590,7 +1596,7 @@ unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS); if (sg_dev_arr != NULL) { - vfree((char *) sg_dev_arr); + kfree((char *) sg_dev_arr); sg_dev_arr = NULL; } sg_dev_max = 0; @@ -2492,7 +2498,7 @@ } if (k < maxd) sg_dev_arr[k] = NULL; - vfree((char *) sdp); + kfree((char *) sdp); res = 1; } write_unlock_irqrestore(&sg_dev_arr_lock, iflags); diff -Nru a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c --- a/drivers/scsi/sgiwd93.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/sgiwd93.c 2004-06-20 13:00:26 -07:00 @@ -31,7 +31,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "wd33c93.h" #include "sgiwd93.h" diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c --- a/drivers/scsi/sim710.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/sim710.c 2004-06-20 13:00:25 -07:00 @@ -35,9 +35,8 @@ #include #include #include +#include -#include "scsi.h" -#include "hosts.h" #include "53c700.h" @@ -86,7 +85,7 @@ } __setup("sim710=", param_setup); -static Scsi_Host_Template sim710_driver_template = { +static struct scsi_host_template sim710_driver_template = { .name = "LSI (Symbios) 710 MCA/EISA", .proc_name = "sim710", .this_id = 7, diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/sr.c 2004-06-20 13:00:26 -07:00 @@ -47,7 +47,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include /* For the door lock/unlock commands */ @@ -754,12 +754,11 @@ static void get_capabilities(struct scsi_cd *cd) { unsigned char *buffer; - int rc, n, mrw_write = 0, mrw = 1,ram_write=0; struct scsi_mode_data data; struct scsi_request *SRpnt; unsigned char cmd[MAX_COMMAND_SIZE]; unsigned int the_result; - int retries; + int retries, rc, n; static char *loadmech[] = { @@ -830,19 +829,6 @@ printk("%s: scsi-1 drive\n", cd->cdi.name); return; } - - if (cdrom_is_mrw(&cd->cdi, &mrw_write)) { - mrw = 0; - cd->cdi.mask |= CDC_MRW; - cd->cdi.mask |= CDC_MRW_W; - } - if (!mrw_write) - cd->cdi.mask |= CDC_MRW_W; - - if (cdrom_is_random_writable(&cd->cdi, &ram_write)) - cd->cdi.mask |= CDC_RAM; - if (!ram_write) - cd->cdi.mask |= CDC_RAM; n = data.header_length + data.block_descriptor_length; cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c --- a/drivers/scsi/sr_ioctl.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/sr_ioctl.c 2004-06-20 13:00:25 -07:00 @@ -11,7 +11,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include "sr.h" @@ -330,6 +330,9 @@ struct packet_command cgc; int result; unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + + if (!buffer) + return -ENOMEM; memset(&cgc, 0, sizeof(struct packet_command)); cgc.timeout = IOCTL_TIMEOUT; diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c --- a/drivers/scsi/sr_vendor.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/sr_vendor.c 2004-06-20 13:00:24 -07:00 @@ -41,7 +41,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/st.c 2004-06-20 13:00:25 -07:00 @@ -58,7 +58,7 @@ #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c --- a/drivers/scsi/sun3_scsi.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/sun3_scsi.c 2004-06-20 13:00:23 -07:00 @@ -75,7 +75,7 @@ #define REAL_DMA #include "scsi.h" -#include "hosts.h" +#include #include "sun3_scsi.h" #include "NCR5380.h" diff -Nru a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c --- a/drivers/scsi/sun3_scsi_vme.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/sun3_scsi_vme.c 2004-06-20 13:00:26 -07:00 @@ -41,7 +41,7 @@ #define REAL_DMA #include "scsi.h" -#include "hosts.h" +#include #include "sun3_scsi.h" #include "NCR5380.h" diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c --- a/drivers/scsi/sun3x_esp.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/sun3x_esp.c 2004-06-20 13:00:25 -07:00 @@ -16,7 +16,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "NCR53C9x.h" #include diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c --- a/drivers/scsi/sym53c416.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/scsi/sym53c416.c 2004-06-20 13:00:23 -07:00 @@ -43,7 +43,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include "sym53c416.h" #define VERSION_STRING "Version 1.0.0-ac" @@ -622,12 +622,13 @@ int ints[2]; ints[0] = 1; - for(; *base; base++) - { - if(!check_region(*base, IO_RANGE) && sym53c416_test(*base)) - { - ints[1] = *base; - sym53c416_setup(NULL, ints); + for(; *base; base++) { + if (request_region(*base, IO_RANGE, ID)) { + if (sym53c416_test(*base)) { + ints[1] = *base; + sym53c416_setup(NULL, ints); + } + release_region(*base, IO_RANGE); } } } @@ -702,44 +703,42 @@ sym53c416_probe(); /* Now we register and set up each host adapter found... */ - for(count = 0, i = 0; i < host_index; i++) - { - if(!sym53c416_test(hosts[i].base)) + for(count = 0, i = 0; i < host_index; i++) { + if (!request_region(hosts[i].base, IO_RANGE, ID)) + continue; + if (!sym53c416_test(hosts[i].base)) { printk(KERN_WARNING "No sym53c416 found at address 0x%03x\n", hosts[i].base); - else - { - if(hosts[i].irq == 0) - /* We don't have an irq yet, so we should probe for one */ - if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0) - printk(KERN_WARNING "IRQ autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base); - if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE)) - { - shpnt = scsi_register(tpnt, 0); - if(shpnt==NULL) - continue; - spin_lock_irqsave(&sym53c416_lock, flags); - /* Request for specified IRQ */ - if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, shpnt)) - { - spin_unlock_irqrestore(&sym53c416_lock, flags); - printk(KERN_ERR "sym53c416: Unable to assign IRQ %d\n", hosts[i].irq); - scsi_unregister(shpnt); - } - else - { - /* Inform the kernel of our IO range */ - request_region(hosts[i].base, IO_RANGE, ID); - shpnt->unique_id = hosts[i].base; - shpnt->io_port = hosts[i].base; - shpnt->n_io_port = IO_RANGE; - shpnt->irq = hosts[i].irq; - shpnt->this_id = hosts[i].scsi_id; - sym53c416_init(hosts[i].base, hosts[i].scsi_id); - count++; - spin_unlock_irqrestore(&sym53c416_lock, flags); - } - } + goto fail_release_region; } + + /* We don't have an irq yet, so we should probe for one */ + if (!hosts[i].irq) + hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id); + if (!hosts[i].irq) + goto fail_release_region; + + shpnt = scsi_register(tpnt, 0); + if (!shpnt) + goto fail_release_region; + /* Request for specified IRQ */ + if (request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, shpnt)) + goto fail_free_host; + + spin_lock_irqsave(&sym53c416_lock, flags); + shpnt->unique_id = hosts[i].base; + shpnt->io_port = hosts[i].base; + shpnt->n_io_port = IO_RANGE; + shpnt->irq = hosts[i].irq; + shpnt->this_id = hosts[i].scsi_id; + sym53c416_init(hosts[i].base, hosts[i].scsi_id); + count++; + spin_unlock_irqrestore(&sym53c416_lock, flags); + continue; + + fail_free_host: + scsi_unregister(shpnt); + fail_release_region: + release_region(hosts[i].base, IO_RANGE); } return count; } diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c --- a/drivers/scsi/t128.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/t128.c 2004-06-20 13:00:25 -07:00 @@ -118,7 +118,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "t128.h" #define AUTOPROBE_IRQ #include "NCR5380.h" diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/tmscsim.c 2004-06-20 13:00:26 -07:00 @@ -172,6 +172,11 @@ * 2.1b1 04/01/31 GL (applied 05.04) Remove internal * * command-queuing. * * 2.1b2 04/02/01 CH (applied 05.04) Fix error-handling * + * 2.1c 04/05/23 GL Update to use the new pci_driver API, * + * some scsi EH updates, more cleanup. * + * 2.1d 04/05/27 GL Moved setting of scan_devices to * + * slave_alloc/_configure/_destroy, as * + * suggested by CH. * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -239,7 +244,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include #include @@ -267,7 +272,6 @@ #include #include -#if defined(MODULE) static struct pci_device_id tmscsim_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_AMD, @@ -278,8 +282,7 @@ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl); -#endif - + #define USE_SPINLOCKS 1 #define DC390_IFLAGS unsigned long iflags @@ -342,6 +345,8 @@ static int DC390_release(struct Scsi_Host *host); static int dc390_shutdown (struct Scsi_Host *host); +static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, + off_t offset, int length, int inout); static PACB dc390_pACB_start= NULL; static PACB dc390_pACB_current = NULL; @@ -351,16 +356,14 @@ /* Startup values, to be overriden on the commandline */ static int tmscsim[] = {-2, -2, -2, -2, -2, -2}; +static int tmscsim_paramnum = ARRAY_SIZE(tmscsim); -#if defined(MODULE) -MODULE_PARM(tmscsim, "1-6i"); +module_param_array(tmscsim, int, tmscsim_paramnum, 0); MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)"); MODULE_AUTHOR("C.L. Huang / Kurt Garloff"); MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters"); MODULE_LICENSE("GPL"); - MODULE_SUPPORTED_DEVICE("sd,sr,sg,st"); -#endif static PVOID dc390_phase0[]={ dc390_DataOut_0, @@ -913,6 +916,14 @@ } } +static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length) +{ + memset(sg, 0, sizeof(struct scatterlist)); + sg->page = virt_to_page(addr); + sg->length = length; + sg->offset = (unsigned long)addr & ~PAGE_MASK; + return sg; +} /* Create pci mapping */ static int dc390_pci_map (PSRB pSRB) @@ -921,40 +932,43 @@ Scsi_Cmnd *pcmd = pSRB->pcmd; struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev; dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)); + /* Map sense buffer */ if (pSRB->SRBFlag & AUTO_REQSENSE) { - sg_dma_address(&pSRB->Segmentx) = cmdp->saved_dma_handle = - pci_map_page(pdev, virt_to_page(pcmd->sense_buffer), - (unsigned long)pcmd->sense_buffer & ~PAGE_MASK, sizeof(pcmd->sense_buffer), - DMA_FROM_DEVICE); - sg_dma_len(&pSRB->Segmentx) = sizeof(pcmd->sense_buffer); - pSRB->SGcount = 1; - pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, sizeof(pcmd->sense_buffer)); + pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1, + DMA_FROM_DEVICE); + cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList); + + /* TODO: error handling */ + if (pSRB->SGcount != 1) + error = 1; DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle)); - /* Make SG list */ + /* Map SG list */ } else if (pcmd->use_sg) { - pSRB->pSegmentList = (PSGL) pcmd->request_buffer; - pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, - pcmd->use_sg, - scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg, + scsi_to_pci_dma_dir(pcmd->sc_data_direction)); /* TODO: error handling */ if (!pSRB->SGcount) error = 1; - DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n", __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg)); + DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\ + __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg)); /* Map single segment */ } else if (pcmd->request_buffer && pcmd->request_bufflen) { - sg_dma_address(&pSRB->Segmentx) = cmdp->saved_dma_handle = - pci_map_page(pdev, virt_to_page(pcmd->request_buffer), - (unsigned long)pcmd->request_buffer & ~PAGE_MASK, - pcmd->request_bufflen, scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen); + pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1, + scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList); + /* TODO: error handling */ - sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen; - pSRB->SGcount = 1; - pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + if (pSRB->SGcount != 1) + error = 1; DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle)); /* No mapping !? */ } else pSRB->SGcount = 0; + return error; } @@ -963,21 +977,16 @@ { Scsi_Cmnd* pcmd = pSRB->pcmd; struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev; - dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)); + DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp))); if (pSRB->SRBFlag) { - pci_unmap_page(pdev, cmdp->saved_dma_handle, - sizeof(pcmd->sense_buffer), DMA_FROM_DEVICE); + pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE); DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle)); } else if (pcmd->use_sg) { - pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, - scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, scsi_to_pci_dma_dir(pcmd->sc_data_direction)); DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg)); } else if (pcmd->request_buffer && pcmd->request_bufflen) { - pci_unmap_page(pdev, - cmdp->saved_dma_handle, - pcmd->request_bufflen, - scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pci_unmap_sg(pdev, &pSRB->Segmentx, 1, scsi_to_pci_dma_dir(pcmd->sc_data_direction)); DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle)); } } @@ -1031,15 +1040,15 @@ * 2.0.x: always return 0 * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x * TO BE DONE: - * new model: return 0 if successful - * return 1 if command cannot be queued (queue full) + * new model: return 0 if successful, or must not be re-queued + * return 1 if command cannot be queued (queue full) * command will be inserted in midlevel queue then ... * ***********************************************************************/ static int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { - PDCB pDCB; + PDCB pDCB = (PDCB) cmd->device->hostdata; PSRB pSRB; PACB pACB = (PACB) cmd->device->host->hostdata; @@ -1050,42 +1059,19 @@ /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY * commands and alloc a DCB for the device if not yet there. DCB will * be removed in dc390_SRBdone if SEL_TIMEOUT */ - - if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) - pACB->scan_devices = 0; - - else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) ) - pACB->scan_devices = 0; - - if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && - !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) ) - { - pACB->scan_devices = 1; - - dc390_initDCB( pACB, &pDCB, cmd->device->id, cmd->device->lun ); - if (!pDCB) - { - printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - goto fail; - } - - } - else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) ) - { + if (!(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun))) { printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n", cmd->device->id, cmd->device->lun); goto fail; } - else - { - pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); - if (!pDCB) - { /* should never happen */ - printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - goto fail; - } + + /* Should it be: BUG_ON(!pDCB); ? */ + + if (!pDCB) + { /* should never happen */ + printk (KERN_ERR "DC390: no DCB found, target %02x lun %02x\n", + cmd->device->id, cmd->device->lun); + goto fail; } pACB->Cmds++; @@ -1304,7 +1290,7 @@ static int DC390_abort (Scsi_Cmnd *cmd) { - PDCB pDCB; + PDCB pDCB = (PDCB) cmd->device->hostdata; PSRB pSRB, psrb; UINT count, i; int status; @@ -1314,7 +1300,6 @@ printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n", cmd->pid, cmd->device->id, cmd->device->lun); - pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); if( !pDCB ) goto NOT_RUN; /* Added 98/07/02 KG */ @@ -1561,15 +1546,16 @@ { PEEprom prom; UCHAR index; - PDCB pDCB, pDCB2; + PDCB pDCB, pDCB2 = 0; pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC); DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n", \ id, lun, pDCB)); - + *ppDCB = pDCB; - if (!pDCB) return; - pDCB2 = 0; + if (!pDCB) + return; + if( pACB->DCBCnt == 0 ) { pACB->pLinkDCB = pDCB; @@ -1745,8 +1731,6 @@ pACB->SRBCount = MAX_SRB_CNT; pACB->AdapterIndex = index; pACB->status = 0; - psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID]; - pACB->DeviceCnt = 0; pACB->DCBCnt = 0; pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM]; pACB->ACBFlag = 0; @@ -1856,7 +1840,7 @@ * * Inputs : host - pointer to this host adapter's structure * io_port - IO ports mapped to this adapter - * Irq - IRQ assigned to this adpater + * irq - IRQ assigned to this adpater * struct pci_dev - PCI access handle * index - Adapter index * @@ -1865,10 +1849,8 @@ * Note: written in capitals, because the locking is only done here, * not in DC390_detect, called from outside ***********************************************************************/ - -static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, UCHAR index) +static int __init dc390_init (PSH psh, unsigned long io_port, u8 irq, struct pci_dev *pdev, UCHAR index) { - PSH psh; PACB pACB; if (dc390_CheckEEpromCheckSum (PDEV, index)) @@ -1890,25 +1872,16 @@ dc390_check_for_safe_settings (); dc390_EEprom_Override (index); } - - psh = scsi_register( psht, sizeof(DC390_ACB) ); - if( !psh ) return( -1 ); - - scsi_set_device(psh, &pdev->dev); pACB = (PACB) psh->hostdata; DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (UINT) psh, index)); - dc390_initACB( psh, io_port, Irq, index ); + dc390_initACB( psh, io_port, irq, index ); PDEVSET; - if( !dc390_initAdapter( psh, io_port, Irq, index ) ) + if( !dc390_initAdapter( psh, io_port, irq, index ) ) { - DEBUG0(printk("DC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\ - (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array)); - DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\ - sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) )); return (0); } else @@ -1927,42 +1900,131 @@ PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); } -int __init DC390_detect (Scsi_Host_Template *psht) +/** + * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new + * scsi device that we need to deal with. + * + * @scsi_device: The new scsi device that we need to handle. + */ +static int dc390_slave_alloc(struct scsi_device *scsi_device) { - struct pci_dev *pdev = NULL; - UCHAR irq; - ULONG io_port; + PDCB pDCB; + PACB pACB = (PACB) scsi_device->host->hostdata; + dc390_initDCB(pACB, &pDCB, scsi_device->id, scsi_device->lun); + if (pDCB != NULL) { + scsi_device->hostdata = pDCB; + pACB->scan_devices = 1; + return 0; + } + return -ENOMEM; +} - dc390_pACB_start = NULL; +/** + * dc390_slave_destroy - Called by the scsi mid layer to tell us about a + * device that is going away. + * + * @scsi_device: The scsi device that we need to remove. + */ +static void dc390_slave_destroy(struct scsi_device *scsi_device) +{ + PACB pACB = (PACB) scsi_device->host->hostdata; + PDCB pDCB = (PDCB) scsi_device->hostdata; + pACB->scan_devices = 0; + if (pDCB != NULL) + dc390_remove_dev(pACB, pDCB); + else + printk(KERN_ERR"%s() called for non-existing device!\n", __FUNCTION__); +} - if ( PCI_PRESENT ) - while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pdev))) - { - if (pci_enable_device (pdev)) - continue; +static int dc390_slave_configure(struct scsi_device *scsi_device) +{ + PACB pACB = (PACB) scsi_device->host->hostdata; + pACB->scan_devices = 0; + return 0; +} - if (pci_set_dma_mask(pdev, 0xffffffff)) { - printk(KERN_ERR "DC390(%i): No suitable DMA available.\n", dc390_adapterCnt); - continue; - } - PCI_GET_IO_AND_IRQ; - DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq)); +static Scsi_Host_Template driver_template = { + .module = THIS_MODULE, + .proc_name = "tmscsim", + .proc_info = DC390_proc_info, + .name = DC390_BANNER " V" DC390_VERSION, + .slave_alloc = dc390_slave_alloc, + .slave_configure = dc390_slave_configure, + .slave_destroy = dc390_slave_destroy, + .queuecommand = DC390_queue_command, + .eh_abort_handler = DC390_abort, + .eh_bus_reset_handler = DC390_reset, + .bios_param = DC390_bios_param, + .can_queue = 42, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 16, + .use_clustering = DISABLE_CLUSTERING, +}; - if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt)) - { - pci_set_master(pdev); - dc390_set_pci_cfg (PDEV); - dc390_adapterCnt++; - } +static int __devinit dc390_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct Scsi_Host *scsi_host; + unsigned long io_port; + u8 irq; + PACB pACB; + int ret = -ENOMEM; + + if (pci_enable_device(dev)) + return -ENODEV; + + io_port = pci_resource_start(dev, 0); + irq = dev->irq; + + /* allocate scsi host information (includes out adapter) */ + scsi_host = scsi_host_alloc(&driver_template, sizeof(struct _ACB)); + if (!scsi_host) + goto nomem; + + pACB = (PACB) scsi_host->hostdata; + + if (dc390_init(scsi_host, io_port, irq, dev, dc390_adapterCnt)) { + ret = -EBUSY; + goto busy; } - else - printk (KERN_ERR "DC390: No PCI BIOS found!\n"); - - if (dc390_adapterCnt) - psht->proc_name = "tmscsim"; - printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); - return( dc390_adapterCnt ); + pci_set_master(dev); + dc390_set_pci_cfg(dev); + dc390_adapterCnt++; + + /* get the scsi mid level to scan for new devices on the bus */ + if (scsi_add_host(scsi_host, &dev->dev)) { + ret = -ENODEV; + goto nodev; + } + pci_set_drvdata(dev, scsi_host); + scsi_scan_host(scsi_host); + + return 0; + +nodev: +busy: + scsi_host_put(scsi_host); +nomem: + pci_disable_device(dev); + return ret; +} + +/** + * dc390_remove_one - Called to remove a single instance of the adapter. + * + * @dev: The PCI device to remove. + */ +static void __devexit dc390_remove_one(struct pci_dev *dev) +{ + struct Scsi_Host *scsi_host = pci_get_drvdata(dev); + + scsi_remove_host(scsi_host); + DC390_release(scsi_host); + pci_disable_device(dev); + scsi_host_put(scsi_host); + pci_set_drvdata(dev, NULL); } /******************************************************************** @@ -2035,7 +2097,7 @@ SPRINTF(" Lost arbitrations %i, Sel. connected %i, Connected: %s\n", pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No"); - SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt); + SPRINTF("Nr of DCBs: %i\n", pACB->DCBCnt); SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n", pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]); @@ -2122,7 +2184,7 @@ static int dc390_shutdown (struct Scsi_Host *host) { UCHAR bval; - PACB pACB = (PACB)(host->hostdata); + PACB pACB = (PACB) host->hostdata; /* pACB->soft_reset(host); */ @@ -2142,7 +2204,7 @@ static void dc390_freeDCBs (struct Scsi_Host *host) { PDCB pDCB, nDCB; - PACB pACB = (PACB)(host->hostdata); + PACB pACB = (PACB) host->hostdata; pDCB = pACB->pLinkDCB; if (!pDCB) return; @@ -2161,7 +2223,7 @@ static int DC390_release (struct Scsi_Host *host) { DC390_IFLAGS; - PACB pACB = (PACB)(host->hostdata); + PACB pACB = (PACB) host->hostdata; DC390_LOCK_IO(host); @@ -2177,24 +2239,25 @@ release_region(host->io_port,host->n_io_port); dc390_freeDCBs (host); DC390_UNLOCK_IO(host); - scsi_unregister(host); return( 1 ); } -static Scsi_Host_Template driver_template = { - .proc_name = "tmscsim", - .proc_info = DC390_proc_info, - .name = DC390_BANNER " V" DC390_VERSION, - .detect = DC390_detect, - .release = DC390_release, - .queuecommand = DC390_queue_command, - .eh_abort_handler = DC390_abort, - .eh_bus_reset_handler = DC390_reset, - .bios_param = DC390_bios_param, - .can_queue = 42, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 16, - .use_clustering = DISABLE_CLUSTERING, +static struct pci_driver dc390_driver = { + .name = "tmscsim", + .id_table = tmscsim_pci_tbl, + .probe = dc390_init_one, + .remove = __devexit_p(dc390_remove_one), }; -#include "scsi_module.c" + +static int __init dc390_module_init(void) +{ + return pci_module_init(&dc390_driver); +} + +static void __exit dc390_module_exit(void) +{ + pci_unregister_driver(&dc390_driver); +} + +module_init(dc390_module_init); +module_exit(dc390_module_exit); diff -Nru a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h --- a/drivers/scsi/tmscsim.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/tmscsim.h 2004-06-20 13:00:25 -07:00 @@ -22,8 +22,6 @@ #define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */ -#define END_SCAN 2 - #define pci_dma_lo32(a) (a & 0xffffffff) typedef u8 UCHAR; /* 8 bits */ @@ -196,10 +194,8 @@ UCHAR SRBCount; UCHAR AdapterIndex; /*; nth Adapter this driver */ -UCHAR DeviceCnt; UCHAR DCBCnt; -/* 0x10: */ UCHAR TagMaxNum; UCHAR ACBFlag; UCHAR Gmode2; @@ -213,13 +209,11 @@ PSRB pFreeSRB; PSRB pTmpSRB; -/* 0x2c: */ UCHAR msgin123[4]; UCHAR DCBmap[MAX_SCSI_ID]; UCHAR Connected; UCHAR pad; -/* 0x30: */ #if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0) spinlock_t lock; #endif @@ -230,20 +224,17 @@ UCHAR Ignore_IRQ; /* Not used */ PDEVDECL1; /* Pointer to PCI cfg. space */ -/* 0x40/0x3c: */ + ULONG Cmds; UINT SelLost; UINT SelConn; UINT CmdInQ; UINT CmdOutOfSRB; -/* 0x54/0x50: */ struct timer_list Waiting_Timer; -/* 0x68/0x64: */ + DC390_SRB TmpSRB; -/* 0xcc/0xc8: */ DC390_SRB SRB_array[MAX_SRB_CNT]; /* 50 SRBs */ -/* 0xfa4/0xfa0: */ }; typedef struct _ACB DC390_ACB, *PACB; diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/u14-34f.c 2004-06-20 13:00:24 -07:00 @@ -423,7 +423,7 @@ #include #include #include "scsi.h" -#include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/scsi/ultrastor.c 2004-06-20 13:00:24 -07:00 @@ -145,7 +145,7 @@ #define ULTRASTOR_PRIVATE /* Get the private stuff from ultrastor.h */ #include "scsi.h" -#include "hosts.h" +#include #include "ultrastor.h" #define FALSE 0 diff -Nru a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c --- a/drivers/scsi/wd33c93.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/wd33c93.c 2004-06-20 13:00:25 -07:00 @@ -83,7 +83,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include "wd33c93.h" diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/scsi/wd7000.c 2004-06-20 13:00:26 -07:00 @@ -184,7 +184,7 @@ #include #include "scsi.h" -#include "hosts.h" +#include #include @@ -1605,6 +1605,7 @@ return 0; } +#if 0 /* * I have absolutely NO idea how to do an abort with the WD7000... */ @@ -1619,7 +1620,7 @@ } return FAILED; } - +#endif /* * I also have no idea how to do a reset... diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c --- a/drivers/scsi/zalon.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/scsi/zalon.c 2004-06-20 13:00:25 -07:00 @@ -24,7 +24,7 @@ #include "../parisc/gsc.h" #include "scsi.h" -#include "hosts.h" +#include #include "ncr53c8xx.h" diff -Nru a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c --- a/drivers/serial/8250_acpi.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/serial/8250_acpi.c 2004-06-20 13:00:26 -07:00 @@ -57,28 +57,18 @@ static acpi_status acpi_serial_ext_irq(struct serial_struct *req, struct acpi_resource_ext_irq *ext_irq) { - if (ext_irq->number_of_interrupts > 0) { -#ifdef CONFIG_IA64 - req->irq = acpi_register_irq(ext_irq->interrupts[0], - ext_irq->active_high_low, ext_irq->edge_level); -#else - req->irq = ext_irq->interrupts[0]; -#endif - } + if (ext_irq->number_of_interrupts > 0) + req->irq = acpi_register_gsi(ext_irq->interrupts[0], + ext_irq->edge_level, ext_irq->active_high_low); return AE_OK; } static acpi_status acpi_serial_irq(struct serial_struct *req, struct acpi_resource_irq *irq) { - if (irq->number_of_interrupts > 0) { -#ifdef CONFIG_IA64 - req->irq = acpi_register_irq(irq->interrupts[0], - irq->active_high_low, irq->edge_level); -#else - req->irq = irq->interrupts[0]; -#endif - } + if (irq->number_of_interrupts > 0) + req->irq = acpi_register_gsi(irq->interrupts[0], + irq->edge_level, irq->active_high_low); return AE_OK; } diff -Nru a/drivers/serial/8250_hcdp.c b/drivers/serial/8250_hcdp.c --- a/drivers/serial/8250_hcdp.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/serial/8250_hcdp.c 2004-06-20 13:00:25 -07:00 @@ -183,16 +183,12 @@ } if (HCDP_IRQ_SUPPORTED(hcdp_dev)) { -#ifdef CONFIG_IA64 if (HCDP_PCI_UART(hcdp_dev)) - port.irq = acpi_register_irq(gsi, - ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); + port.irq = acpi_register_gsi(gsi, + ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); else - port.irq = acpi_register_irq(gsi, - ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE); -#else - port.irq = gsi; -#endif + port.irq = acpi_register_gsi(gsi, + ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH); port.flags |= UPF_AUTO_IRQ; if (HCDP_PCI_UART(hcdp_dev)) diff -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c --- a/drivers/serial/8250_pnp.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/serial/8250_pnp.c 2004-06-20 13:00:23 -07:00 @@ -361,9 +361,6 @@ ((port->min == 0x2f8) || (port->min == 0x3f8) || (port->min == 0x2e8) || -#ifdef CONFIG_X86_PC9800 - (port->min == 0x8b0) || -#endif (port->min == 0x3e8))) return 1; } diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/serial/Kconfig 2004-06-20 13:00:25 -07:00 @@ -518,19 +518,6 @@ depends on V850E_UART select SERIAL_CORE_CONSOLE -config SERIAL98 - tristate "PC-9800 8251-based primary serial port support" - depends on X86_PC9800 - select SERIAL_CORE - help - If you want to use standard primary serial ports on PC-9800, - say Y. Otherwise, say N. - -config SERIAL98_CONSOLE - bool "Support for console on PC-9800 standard serial port" - depends on SERIAL98=y - select SERIAL_CORE_CONSOLE - config SERIAL_SH_SCI tristate "SH SCI(F) serial port support" depends on SUPERH || H8300 diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile 2004-06-20 13:00:24 -07:00 +++ b/drivers/serial/Makefile 2004-06-20 13:00:24 -07:00 @@ -33,7 +33,6 @@ obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_V850E_UART) += v850e_uart.o -obj-$(CONFIG_SERIAL98) += serial98.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o obj-$(CONFIG_SERIAL_DZ) += dz.o diff -Nru a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c --- a/drivers/serial/amba-pl011.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/serial/amba-pl011.c 2004-06-20 13:00:26 -07:00 @@ -44,6 +44,7 @@ #include #include #include +#include #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -68,6 +69,7 @@ */ struct uart_amba_port { struct uart_port port; + struct clk *clk; unsigned int im; /* interrupt mask */ unsigned int old_status; }; @@ -352,11 +354,20 @@ int retval; /* + * Try to enable the clock producer. + */ + retval = clk_enable(uap->clk); + if (retval) + goto out; + + uap->port.uartclk = clk_get_rate(uap->clk); + + /* * Allocate the IRQ */ retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); if (retval) - goto out; + goto clk_dis; writew(UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, uap->port.membase + UART011_IFLS); @@ -391,6 +402,8 @@ return 0; + clk_dis: + clk_disable(uap->clk); out: return retval; } @@ -425,6 +438,11 @@ val = readw(uap->port.membase + UART011_LCRH); val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); writew(val, uap->port.membase + UART011_LCRH); + + /* + * Shut down the clock producer + */ + clk_disable(uap->clk); } static void @@ -594,38 +612,40 @@ #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE static inline void -pl011_console_write_char(struct uart_port *port, char ch) +pl011_console_write_char(struct uart_amba_port *uap, char ch) { unsigned int status; do { - status = readw(port->membase + UART01x_FR); + status = readw(uap->port.membase + UART01x_FR); } while (status & UART01x_FR_TXFF); - writew(ch, port->membase + UART01x_DR); + writew(ch, uap->port.membase + UART01x_DR); } static void pl011_console_write(struct console *co, const char *s, unsigned int count) { - struct uart_port *port = &amba_ports[co->index]->port; + struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr, new_cr; int i; + clk_enable(uap->clk); + /* * First save the CR then disable the interrupts */ - old_cr = readw(port->membase + UART011_CR); + old_cr = readw(uap->port.membase + UART011_CR); new_cr = old_cr & ~UART011_CR_CTSEN; new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; - writew(new_cr, port->membase + UART011_CR); + writew(new_cr, uap->port.membase + UART011_CR); /* * Now, do each character */ for (i = 0; i < count; i++) { - pl011_console_write_char(port, s[i]); + pl011_console_write_char(uap, s[i]); if (s[i] == '\n') - pl011_console_write_char(port, '\r'); + pl011_console_write_char(uap, '\r'); } /* @@ -633,19 +653,21 @@ * and restore the TCR */ do { - status = readw(port->membase + UART01x_FR); + status = readw(uap->port.membase + UART01x_FR); } while (status & UART01x_FR_BUSY); - writew(old_cr, port->membase + UART011_CR); + writew(old_cr, uap->port.membase + UART011_CR); + + clk_disable(uap->clk); } static void __init -pl011_console_get_options(struct uart_port *port, int *baud, +pl011_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (readw(port->membase + UART011_CR) & UART01x_CR_UARTEN) { + if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, ibrd, fbrd; - lcr_h = readw(port->membase + UART011_LCRH); + lcr_h = readw(uap->port.membase + UART011_LCRH); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -660,10 +682,10 @@ else *bits = 8; - ibrd = readw(port->membase + UART011_IBRD); - fbrd = readw(port->membase + UART011_FBRD); + ibrd = readw(uap->port.membase + UART011_IBRD); + fbrd = readw(uap->port.membase + UART011_FBRD); - *baud = port->uartclk * 4 / (64 * ibrd + fbrd); + *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); } } @@ -685,10 +707,12 @@ co->index = 0; uap = amba_ports[co->index]; + uap->port.uartclk = clk_get_rate(uap->clk); + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else - pl011_console_get_options(&uap->port, &baud, &parity, &bits); + pl011_console_get_options(uap, &baud, &parity, &bits); return uart_set_options(&uap->port, co, baud, parity, bits, flow); } @@ -747,16 +771,21 @@ } memset(uap, 0, sizeof(struct uart_amba_port)); + uap->clk = clk_get(&dev->dev, "UARTCLK"); + if (IS_ERR(uap->clk)) { + ret = PTR_ERR(uap->clk); + goto unmap; + } + + ret = clk_use(uap->clk); + if (ret) + goto putclk; + uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; uap->port.membase = base; uap->port.iotype = UPIO_MEM; uap->port.irq = dev->irq[0]; -#if 0 /* FIXME */ - uap->port.uartclk = 14745600; -#else - uap->port.uartclk = 24000000; -#endif uap->port.fifosize = 16; uap->port.ops = &amba_pl011_pops; uap->port.flags = UPF_BOOT_AUTOCONF; @@ -769,6 +798,10 @@ if (ret) { amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; + clk_unuse(uap->clk); + putclk: + clk_put(uap->clk); + unmap: iounmap(base); free: kfree(uap); @@ -791,6 +824,8 @@ amba_ports[i] = NULL; iounmap(uap->port.membase); + clk_unuse(uap->clk); + clk_put(uap->clk); kfree(uap); return 0; } diff -Nru a/drivers/serial/pxa.c b/drivers/serial/pxa.c --- a/drivers/serial/pxa.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/serial/pxa.c 2004-06-20 13:00:25 -07:00 @@ -571,14 +571,9 @@ unsigned int oldstate) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; - if (state) { - /* sleep */ - CKEN &= ~up->cken; - } else { - /* wake */ - CKEN |= up->cken; + pxa_set_cken(up->cken, !state); + if (!state) udelay(1); - } } static void serial_pxa_release_port(struct uart_port *port) diff -Nru a/drivers/serial/serial98.c b/drivers/serial/serial98.c --- a/drivers/serial/serial98.c 2004-06-20 13:00:25 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,1120 +0,0 @@ -/* - * linux/drivers/serial/serial98.c - * - * Driver for NEC PC-9801/PC-9821 standard serial ports - * - * Based on drivers/serial/8250.c, by Russell King. - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * - * Copyright (C) 2002 Osamu Tomita - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(CONFIG_SERIAL98_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include - -#define SERIAL98_NR 1 -#define SERIAL98_ISR_PASS_LIMIT 256 -#define SERIAL98_EXT 0x434 - -//#define RX_8251F 0x130 /* In: Receive buffer */ -//#define TX_8251F 0x130 /* Out: Transmit buffer */ -//#define LSR_8251F 0x132 /* In: Line Status Register */ -//#define MSR_8251F 0x134 /* In: Modem Status Register */ -#define IIR_8251F 0x136 /* In: Interrupt ID Register */ -#define FCR_8251F 0x138 /* I/O: FIFO Control Register */ -#define VFAST_8251F 0x13a /* I/O: VFAST mode Register */ - -#define CMD_8251F 0x32 /* Out: 8251 Command Resister */ -#define IER2_8251F 0x34 /* I/O: Interrupt Enable Register */ -#define IER1_8251F 0x35 /* I/O: Interrupt Enable Register */ -#define IER1_CTL 0x37 /* Out: Interrupt Enable Register */ -#define DIS_RXR_INT 0x00 /* disable RxRDY Interrupt */ -#define ENA_RXR_INT 0x01 /* enable RxRDY Interrupt */ -#define DIS_TXE_INT 0x02 /* disable TxEMPTY Interrupt */ -#define ENA_TXE_INT 0x03 /* enable TxEMPTY Interrupt */ -#define DIS_TXR_INT 0x04 /* disable TxRDY Interrupt */ -#define ENA_TXR_INT 0x05 /* enable TxRDY Interrupt */ - -#define CMD_RESET 0x40 /* Reset Command */ -#define CMD_RTS 0x20 /* Set RTS line */ -#define CMD_CLR_ERR 0x10 /* Clear error flag */ -#define CMD_BREAK 0x08 /* Send Break */ -#define CMD_RXE 0x04 /* Enable receive */ -#define CMD_DTR 0x02 /* Set DTR line */ -#define CMD_TXE 0x01 /* Enable send */ -#define CMD_DUMMY 0x00 /* Dummy Command */ - -#define VFAST_ENABLE 0x80 /* V.Fast mode Enable */ - -/* Interrupt masks */ -#define INTR_8251_TXRE 0x04 -#define INTR_8251_TXEE 0x02 -#define INTR_8251_RXRE 0x01 -/* I/O Port */ -//#define PORT_8251_DATA 0 -//#define PORT_8251_CMD 2 -//#define PORT_8251_MOD 2 -//#define PORT_8251_STS 2 -/* status read */ -#define STAT_8251_TXRDY 0x01 -#define STAT_8251_RXRDY 0x02 -#define STAT_8251_TXEMP 0x04 -#define STAT_8251_PER 0x08 -#define STAT_8251_OER 0x10 -#define STAT_8251_FER 0x20 -#define STAT_8251_BRK 0x40 -#define STAT_8251_DSR 0x80 -#if 1 -#define STAT_8251F_TXEMP 0x01 -#define STAT_8251F_TXRDY 0x02 -#define STAT_8251F_RXRDY 0x04 -#define STAT_8251F_DSR 0x08 -#define STAT_8251F_OER 0x10 -#define STAT_8251F_PER 0x20 -#define STAT_8251F_FER 0x40 -#define STAT_8251F_BRK 0x80 -#else -#define STAT_8251F_TXEMP 0x01 -#define STAT_8251F_TEMT 0x01 -#define STAT_8251F_TXRDY 0x02 -#define STAT_8251F_THRE 0x02 -#define STAT_8251F_RXRDY 0x04 -#define STAT_8251F_DSR 0x04 -#define STAT_8251F_PER 0x08 -#define STAT_8251F_OER 0x10 -#define STAT_8251F_FER 0x20 -#define STAT_8251F_BRK 0x40 -#endif - -/* - * We wrap our port structure around the generic uart_port. - */ -struct serial98_port { - struct uart_port port; - unsigned int type; - unsigned int ext; - unsigned int lsr_break_flag; - unsigned char cmd; - unsigned char mode; - unsigned char msr; - unsigned char ier; - unsigned char rxchk; - unsigned char txemp; - unsigned char txrdy; - unsigned char rxrdy; - unsigned char brk; - unsigned char fe; - unsigned char oe; - unsigned char pe; - unsigned char dr; -}; - -#ifdef CONFIG_SERIAL98_CONSOLE -static void -serial98_console_write(struct console *co, const char *s, unsigned int count); -static int __init serial98_console_setup(struct console *co, char *options); - -extern struct uart_driver serial98_reg; -static struct console serial98_console = { - .name = "ttyS", - .write = serial98_console_write, - .device = uart_console_device, - .setup = serial98_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &serial98_reg, -}; - -#define SERIAL98_CONSOLE &serial98_console -#else -#define SERIAL98_CONSOLE NULL -#endif - -static struct uart_driver serial98_reg = { - .owner = THIS_MODULE, - .driver_name = "serial98", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, - .nr = SERIAL98_NR, - .cons = SERIAL98_CONSOLE, -}; - -static int serial98_clk; -static char type_str[48]; - -#define PORT98 ((struct serial98_port *)port) -#define PORT (PORT98->port) - -static void serial98_fifo_enable(struct uart_port *port, int enable) -{ - unsigned char fcr; - - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - fcr = inb(FCR_8251F); - if (enable) - fcr |= UART_FCR_ENABLE_FIFO; - else - fcr &= ~UART_FCR_ENABLE_FIFO; - outb(fcr, FCR_8251F); - } - - if (!enable) - return; - - outb(0, 0x5f); /* wait */ - outb(0, 0x5f); - outb(0, 0x5f); - outb(0, 0x5f); -} - -static void serial98_cmd_out(struct uart_port *port, unsigned char cmd) -{ - serial98_fifo_enable(port, 0); - outb(cmd, CMD_8251F); - serial98_fifo_enable(port, 1); -} - -static void serial98_mode_set(struct uart_port *port) -{ - serial98_cmd_out(port, CMD_DUMMY); - serial98_cmd_out(port, CMD_DUMMY); - serial98_cmd_out(port, CMD_DUMMY); - serial98_cmd_out(port, CMD_RESET); - serial98_cmd_out(port, PORT98->mode); -} - -static unsigned char serial98_msr_in(struct uart_port *port) -{ - unsigned long flags; - unsigned int ms, st; - unsigned int tmp; - - spin_lock_irqsave(&PORT.lock, flags); - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - PORT98->msr = inb(PORT.iobase + 4); - } else { - ms = inb(0x33); - st = inb(0x32); - tmp = 0; - if(!(ms & 0x20)) - tmp |= UART_MSR_DCD; - if(!(ms & 0x80)) { - tmp |= UART_MSR_RI; - PORT98->msr |= UART_MSR_RI; - } - if(!(ms & 0x40)) - tmp |= UART_MSR_CTS; - if(st & 0x80) - tmp |= UART_MSR_DSR; - PORT98->msr = ((PORT98->msr ^ tmp) >> 4) | tmp; - } - - spin_unlock_irqrestore(&PORT.lock, flags); - return PORT98->msr; -} - -static void serial98_stop_tx(struct uart_port *port, unsigned int tty_stop) -{ - unsigned int ier = inb(IER1_8251F); - - ier &= ~(INTR_8251_TXRE | INTR_8251_TXEE); - outb(ier, IER1_8251F); -} - -static void serial98_start_tx(struct uart_port *port, unsigned int tty_start) -{ - unsigned int ier = inb(IER1_8251F); - - ier |= INTR_8251_TXRE | INTR_8251_TXEE; - outb(ier, IER1_8251F); -} - -static void serial98_stop_rx(struct uart_port *port) -{ - PORT.read_status_mask &= ~PORT98->dr; - outb(DIS_RXR_INT, IER1_CTL); -} - -static void serial98_enable_ms(struct uart_port *port) -{ - outb(PORT98->ier | 0x80, IER2_8251F); -} - -static void serial98_rx_chars(struct uart_port *port, int *status, - struct pt_regs *regs) -{ - struct tty_struct *tty = PORT.info->tty; - unsigned char ch; - int max_count = 256; - - do { - if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; // if TTY_DONT_FLIP is set - } - ch = inb(PORT.iobase); - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; - PORT.icount.rx++; - - if (unlikely(*status & (PORT98->brk | PORT98->pe | - PORT98->fe | PORT98->oe))) { - /* - * For statistics only - */ - if (*status & PORT98->brk) { - *status &= ~(PORT98->fe | PORT98->pe); - PORT.icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(&PORT)) - goto ignore_char; - } else if (*status & PORT98->pe) - PORT.icount.parity++; - else if (*status & PORT98->fe) - PORT.icount.frame++; - if (*status & PORT98->oe) - PORT.icount.overrun++; - - /* - * Mask off conditions which should be ingored. - */ - *status &= PORT.read_status_mask; - -#ifdef CONFIG_SERIAL98_CONSOLE - if (PORT.line == PORT.cons->index) { - /* Recover the break flag from console xmit */ - *status |= PORT98->lsr_break_flag; - PORT98->lsr_break_flag = 0; - } -#endif - if (*status & PORT98->brk) { - *tty->flip.flag_buf_ptr = TTY_BREAK; - } else if (*status & PORT98->pe) - *tty->flip.flag_buf_ptr = TTY_PARITY; - else if (*status & PORT98->fe) - *tty->flip.flag_buf_ptr = TTY_FRAME; - } - if (uart_handle_sysrq_char(&PORT, ch, regs)) - goto ignore_char; - if ((*status & PORT.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - if ((*status & PORT98->oe) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - ignore_char: - *status = inb(PORT.iobase + 2); - } while ((*status & PORT98->rxchk) && (max_count-- > 0)); - tty_flip_buffer_push(tty); -} - -static void serial98_tx_chars(struct uart_port *port) -{ - struct circ_buf *xmit = &PORT.info->xmit; - int count; - - if (PORT.x_char) { - outb(PORT.x_char, PORT.iobase); - PORT.icount.tx++; - PORT.x_char = 0; - return; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&PORT)) { - serial98_stop_tx(port, 0); - return; - } - - count = PORT.fifosize; - do { - outb(xmit->buf[xmit->tail], PORT.iobase); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - PORT.icount.tx++; - if (uart_circ_empty(xmit)) - break; - } while (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&PORT); - - if (uart_circ_empty(xmit)) - serial98_stop_tx(&PORT, 0); -} - -static void serial98_modem_status(struct uart_port *port) -{ - int status; - - status = serial98_msr_in(port); - - if ((status & UART_MSR_ANY_DELTA) == 0) - return; - - if (status & UART_MSR_TERI) - PORT.icount.rng++; - if (status & UART_MSR_DDSR) - PORT.icount.dsr++; - if (status & UART_MSR_DDCD) - uart_handle_dcd_change(&PORT, status & UART_MSR_DCD); - if (status & UART_MSR_DCTS) - uart_handle_cts_change(&PORT, status & UART_MSR_CTS); - - wake_up_interruptible(&PORT.info->delta_msr_wait); -} - -static void serial98_int(int irq, void *port, struct pt_regs *regs) -{ - unsigned int status; - - spin_lock(&PORT.lock); - status = inb(PORT.iobase + 2); - if (status & PORT98->rxrdy) { - serial98_rx_chars(port, &status, regs); - } - serial98_modem_status(port); - if (status & PORT98->txrdy) { - serial98_tx_chars(port); - } - spin_unlock(&PORT.lock); -} - -static unsigned int serial98_tx_empty(struct uart_port *port) -{ - unsigned long flags; - unsigned int ret = 0; - - spin_lock_irqsave(&PORT.lock, flags); - if (inb(PORT.iobase + 2) & PORT98->txemp) - ret = TIOCSER_TEMT; - - spin_unlock_irqrestore(&PORT.lock, flags); - return ret; -} - -static unsigned int serial98_get_mctrl(struct uart_port *port) -{ - unsigned char status; - unsigned int ret = 0; - - status = serial98_msr_in(port); - if (status & UART_MSR_DCD) - ret |= TIOCM_CAR; - if (status & UART_MSR_RI) - ret |= TIOCM_RNG; - if (status & UART_MSR_DSR) - ret |= TIOCM_DSR; - if (status & UART_MSR_CTS) - ret |= TIOCM_CTS; - return ret; -} - -static void serial98_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - PORT98->cmd &= 0xdd; - if (mctrl & TIOCM_RTS) - PORT98->cmd |= CMD_RTS; - - if (mctrl & TIOCM_DTR) - PORT98->cmd |= CMD_DTR; - - serial98_cmd_out(port, PORT98->cmd); -} - -static void serial98_break_ctl(struct uart_port *port, int break_state) -{ - unsigned long flags; - - spin_lock_irqsave(&PORT.lock, flags); - if (break_state == -1) - PORT98->cmd |= CMD_BREAK; - else - PORT98->cmd &= ~CMD_BREAK; - - serial98_cmd_out(port, PORT98->cmd); - spin_unlock_irqrestore(&PORT.lock, flags); -} - -static int serial98_startup(struct uart_port *port) -{ - int retval; - - if (PORT.type == PORT_8251_PC98) { - /* Wake up UART */ - PORT98->mode = 0xfc; - serial98_mode_set(port); - outb(DIS_RXR_INT, IER1_CTL); - outb(DIS_TXE_INT, IER1_CTL); - outb(DIS_TXR_INT, IER1_CTL); - PORT98->mode = 0; - serial98_mode_set(port); - } - - /* - * Clear the FIFO buffers and disable them. - * (they will be reeanbled in set_termios()) - */ - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - outb(UART_FCR_ENABLE_FIFO, FCR_8251F); - outb((UART_FCR_ENABLE_FIFO - | UART_FCR_CLEAR_RCVR - | UART_FCR_CLEAR_XMIT), FCR_8251F); - outb(0, FCR_8251F); - } - - /* Clear the interrupt registers. */ - inb(0x30); - inb(0x32); - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - inb(PORT.iobase); - inb(PORT.iobase + 2); - inb(PORT.iobase + 4); - inb(PORT.iobase + 6); - } - - /* Allocate the IRQ */ - retval = request_irq(PORT.irq, serial98_int, 0, - serial98_reg.driver_name, port); - if (retval) - return retval; - - /* - * Now, initialize the UART - */ - PORT98->mode = 0x4e; - serial98_mode_set(port); - PORT98->cmd = 0x15; - serial98_cmd_out(port, PORT98->cmd); - PORT98->cmd = 0x05; - - /* - * Finally, enable interrupts - */ - outb(0x00, IER2_8251F); - outb(ENA_RXR_INT, IER1_CTL); - - /* - * And clear the interrupt registers again for luck. - */ - inb(0x30); - inb(0x32); - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - inb(PORT.iobase); - inb(PORT.iobase + 2); - inb(PORT.iobase + 4); - inb(PORT.iobase + 6); - } - - return 0; -} - -static void serial98_shutdown(struct uart_port *port) -{ - unsigned long flags; - - /* - * disable all interrupts - */ - spin_lock_irqsave(&PORT.lock, flags); - if (PORT.type == PORT_VFAST_PC98) - outb(0, VFAST_8251F); /* V.FAST mode off */ - - /* disnable all modem status interrupt */ - outb(0x80, IER2_8251F); - - /* disnable TX/RX interrupt */ - outb(0x00, IER2_8251F); - outb(DIS_RXR_INT, IER1_CTL); - outb(DIS_TXE_INT, IER1_CTL); - outb(DIS_TXR_INT, IER1_CTL); - PORT98->ier = 0; - - spin_unlock_irqrestore(&PORT.lock, flags); - - /* - * Free the interrupt - */ - free_irq(PORT.irq, port); - - /* disable break condition and disable the port */ - serial98_mode_set(port); - - /* disable FIFO's */ - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - outb((UART_FCR_ENABLE_FIFO - | UART_FCR_CLEAR_RCVR - | UART_FCR_CLEAR_XMIT), FCR_8251F); - outb(0, FCR_8251F); - } - - inb(PORT.iobase); -} - -static void -serial98_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) -{ - unsigned char stopbit, cval, fcr = 0, ier = 0; - unsigned long flags; - unsigned int baud, quot; - - stopbit = 0x80; - switch (termios->c_cflag & CSIZE) { - case CS5: - cval = 0x42; - stopbit = 0xc0; - break; - case CS6: - cval = 0x46; - break; - case CS7: - cval = 0x4a; - break; - default: - case CS8: - cval = 0x4e; - break; - } - - if (termios->c_cflag & CSTOPB) - cval ^= stopbit; - if (termios->c_cflag & PARENB) - cval |= 0x10; - if (!(termios->c_cflag & PARODD)) - cval |= 0x20; - - /* - * Ask the core to calculate the divisor for us. - */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); - - if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { - if ((PORT.uartclk / quot) < (2400 * 16)) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; - else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; - } - - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - */ - spin_lock_irqsave(&PORT.lock, flags); - - /* - * Update the per-port timeout. - */ - uart_update_timeout(port, termios->c_cflag, baud); - - PORT.read_status_mask = PORT98->oe | PORT98->txemp | PORT98->dr; - if (termios->c_iflag & INPCK) - PORT.read_status_mask |= PORT98->fe | PORT98->pe; - - if (termios->c_iflag & (BRKINT | PARMRK)) - PORT.read_status_mask |= PORT98->brk; - /* - * Characters to ignore - */ - PORT.ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - PORT.ignore_status_mask |= PORT98->fe | PORT98->pe; - - if (termios->c_iflag & IGNBRK) { - PORT.ignore_status_mask |= PORT98->brk; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - PORT.ignore_status_mask |= PORT98->oe; - } - - /* - * ignore all characters if CREAD is not set - */ - if ((termios->c_cflag & CREAD) == 0) - PORT.ignore_status_mask |= PORT98->dr; - - /* - * CTS flow control flag and modem status interrupts - */ - if (PORT.flags & UPF_HARDPPS_CD) - ier |= 0x80; /* enable modem status interrupt */ - if (termios->c_cflag & CRTSCTS) { - ier |= 0x08; /* enable CTS interrupt */ - ier |= 0x80; /* enable modem status interrupt */ - } - if (!(termios->c_cflag & CLOCAL)) { - ier |= 0x20; /* enable CD interrupt */ - ier |= 0x80; /* enable modem status interrupt */ - } - PORT98->ier = ier; - - PORT98->mode = cval; - serial98_mode_set(port); - if (PORT.type == PORT_VFAST_PC98 && quot <= 48) { - quot /= 4; - if (quot < 1) - quot = 1; - outb(quot | VFAST_ENABLE, VFAST_8251F); - } else { - quot /= 3; - if (quot < 1) - quot = 1; - if (PORT.type == PORT_VFAST_PC98) - outb(0, VFAST_8251F); /* V.FAST mode off */ - outb(0xb6, 0x77); - outb(quot & 0xff, 0x75); /* LS of divisor */ - outb(quot >> 8, 0x75); /* MS of divisor */ - } - - if (fcr & UART_FCR_ENABLE_FIFO) { - outb(UART_FCR_ENABLE_FIFO, FCR_8251F); - outb(fcr, FCR_8251F); - } - - /* enable RX/TX */ - PORT98->cmd = 0x15; - serial98_cmd_out(port, PORT98->cmd); - PORT98->cmd = 0x05; - /* enable interrupts */ - outb(0x00, IER2_8251F); - outb(ENA_RXR_INT, IER1_CTL); - spin_unlock_irqrestore(&PORT.lock, flags); -} - -static const char *serial98_type(struct uart_port *port) -{ - char *p; - - switch (PORT.type) { - case PORT_8251_PC98: - p = "PC98 onboard legacy 8251"; - break; - case PORT_19K_PC98: - p = "PC98 onboard max 19200bps"; - break; - case PORT_FIFO_PC98: - p = "PC98 onboard with FIFO"; - break; - case PORT_VFAST_PC98: - p = "PC98 onboard V.FAST"; - break; - case PORT_PC9861: - p = "PC-9861K RS-232C ext. board"; - break; - case PORT_PC9801_101: - p = "PC-9801-101 RS-232C ext. board"; - break; - default: - return NULL; - } - - sprintf(type_str, "%s Clock %dMHz", p, serial98_clk); - return type_str; -} - -/* Release the region(s) being used by 'port' */ -static void serial98_release_port(struct uart_port *port) -{ - switch (PORT.type) { - case PORT_VFAST_PC98: - release_region(PORT.iobase + 0xa, 1); - case PORT_FIFO_PC98: - release_region(PORT.iobase + 8, 1); - release_region(PORT.iobase + 6, 1); - release_region(PORT.iobase + 4, 1); - release_region(PORT.iobase + 2, 1); - release_region(PORT.iobase, 1); - case PORT_19K_PC98: - release_region(SERIAL98_EXT, 1); - release_region(0x34, 1); - case PORT_8251_PC98: - release_region(0x32, 1); - release_region(0x30, 1); - } -} - -/* Request the region(s) being used by 'port' */ -#define REQ_REGION98(base) (request_region((base), 1, serial98_reg.driver_name)) -static int serial98_request_region(unsigned int type) -{ - if (!REQ_REGION98(0x30)) - return -EBUSY; - if (REQ_REGION98(0x32)) { - if (type == PORT_8251_PC98) - return 0; - if (REQ_REGION98(0x34)) { - if (REQ_REGION98(SERIAL98_EXT)) { - unsigned long base; - - if (type == PORT_19K_PC98) - return 0; - for (base = 0x130; base <= 0x138; base += 2) { - if (!REQ_REGION98(base)) { - base -= 2; - goto err; - } - } - if (type == PORT_FIFO_PC98) - return 0; - if (type == PORT_VFAST_PC98) { - if (REQ_REGION98(0x13a)) - return 0; - } - err: - while (base >= 0x130) { - release_region(base, 1); - base -= 2; - } - release_region(SERIAL98_EXT, 1); - } - release_region(0x34, 1); - } - release_region(0x32, 1); - } - release_region(0x30, 1); - return -EBUSY; -} - -static int serial98_request_port(struct uart_port *port) -{ - return serial98_request_region(PORT.type); -} - -/* - * Configure/autoconfigure the port. - */ -static void serial98_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) - PORT.type = PORT98->type; -} - -/* - * verify the new serial_struct (for TIOCSSERIAL). - */ -static int serial98_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - switch (ser->type) { - case PORT_VFAST_PC98: - case PORT_FIFO_PC98: - case PORT_19K_PC98: - case PORT_8251_PC98: - /* not implemented yet - case PORT_PC9861: - case PORT_PC9801_101: - */ - case PORT_UNKNOWN: - break; - default: - return -EINVAL; - } - if (ser->irq < 0 || ser->irq >= NR_IRQS) - return -EINVAL; - if (ser->baud_base < 9600) - return -EINVAL; - return 0; -} - -static struct uart_ops serial98_ops = { - .tx_empty = serial98_tx_empty, - .set_mctrl = serial98_set_mctrl, - .get_mctrl = serial98_get_mctrl, - .stop_tx = serial98_stop_tx, - .start_tx = serial98_start_tx, - .stop_rx = serial98_stop_rx, - .enable_ms = serial98_enable_ms, - .break_ctl = serial98_break_ctl, - .startup = serial98_startup, - .shutdown = serial98_shutdown, - .set_termios = serial98_set_termios, - .type = serial98_type, - .release_port = serial98_release_port, - .request_port = serial98_request_port, - .config_port = serial98_config_port, - .verify_port = serial98_verify_port, -}; - -static struct serial98_port serial98_ports[SERIAL98_NR] = { - { - .port = { - .iobase = 0x30, - .iotype = SERIAL_IO_PORT, - .irq = 4, - .fifosize = 1, - .ops = &serial98_ops, - .flags = ASYNC_BOOT_AUTOCONF, - .line = 0, - }, - .rxchk = STAT_8251_RXRDY, - .txemp = STAT_8251_TXEMP, - .txrdy = STAT_8251_TXRDY, - .rxrdy = STAT_8251_RXRDY, - .brk = STAT_8251_BRK, - .fe = STAT_8251_FER, - .oe = STAT_8251_OER, - .pe = STAT_8251_PER, - .dr = STAT_8251_DSR, - }, -}; - -#ifdef CONFIG_SERIAL98_CONSOLE - -#define BOTH_EMPTY (PORT98->txemp | PORT98->txrdy) - -/* - * Wait for transmitter & holding register to empty - */ -static inline void wait_for_xmitr(struct uart_port *port) -{ - unsigned int status, tmout = 10000; - - /* Wait up to 10ms for the character(s) to be sent. */ - do { - status = inb(PORT.iobase + 2); - - if (status & PORT98->brk) - PORT98->lsr_break_flag = PORT98->brk; - - if (--tmout == 0) - break; - udelay(1); - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); - - /* Wait up to 1s for flow control if necessary */ - if (PORT.flags & UPF_CONS_FLOW) { - tmout = 1000000; - while (--tmout && - ((serial98_msr_in(port) & UART_MSR_CTS) == 0)) - udelay(1); - } -} - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console_lock must be held when we get here. - */ -static void -serial98_console_write(struct console *co, const char *s, unsigned int count) -{ - struct uart_port *port = (struct uart_port *)&serial98_ports[co->index]; - unsigned int ier1, ier2; - int i; - - /* - * First save the UER then disable the interrupts - */ - ier1 = inb(IER1_8251F); - ier2 = inb(IER2_8251F); - /* disnable all modem status interrupt */ - outb(0x80, IER2_8251F); - - /* disnable TX/RX interrupt */ - outb(0x00, IER2_8251F); - outb(DIS_RXR_INT, IER1_CTL); - outb(DIS_TXE_INT, IER1_CTL); - outb(DIS_TXR_INT, IER1_CTL); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(port); - - /* - * Send the character out. - * If a LF, also do CR... - */ - outb(*s, PORT.iobase); - if (*s == 10) { - wait_for_xmitr(port); - outb(13, PORT.iobase); - } - } - - /* - * Finally, wait for transmitter to become empty - * and restore the IER - */ - wait_for_xmitr(port); - - /* restore TX/RX interrupt */ - outb(0x00, IER2_8251F); - if (ier1 & 0x01) - outb(ENA_RXR_INT, IER1_CTL); - if (ier1 & 0x02) - outb(ENA_TXE_INT, IER1_CTL); - if (ier1 & 0x04) - outb(ENA_TXR_INT, IER1_CTL); - - /* restore modem status interrupt */ - outb(ier2, IER2_8251F); -} - -static int __init serial98_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (co->index >= SERIAL98_NR) - co->index = 0; - port = &serial98_ports[co->index].port; - - /* - * Temporary fix. - */ - spin_lock_init(&port->lock); - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -void __init serial98_console_init(void) -{ - register_console(&serial98_console); -} - -#endif /* CONFIG_SERIAL98_CONSOLE */ - - -static int __init serial98_init(void) -{ - int ret; - unsigned char iir1, iir2; - - if (PC9800_8MHz_P()) { - serial98_clk = 8; - serial98_ports[0].port.uartclk = 374400 * 16; - } else { - serial98_clk = 5; - serial98_ports[0].port.uartclk = 460800 * 16; - } - - printk(KERN_INFO "serial98: PC-9801 standard serial port driver Version 0.1alpha\n"); - serial98_ports[0].type = PORT_8251_PC98; - /* Check FIFO exist */ - iir1 = inb(IIR_8251F); - iir2 = inb(IIR_8251F); - if ((iir1 & 0x40) != (iir2 & 0x40) && (iir1 & 0x20) == (iir2 & 0x20)) { - serial98_ports[0].port.iobase = 0x130; - serial98_ports[0].port.fifosize = 16; - serial98_ports[0].rxchk = STAT_8251F_DSR; - serial98_ports[0].txemp = STAT_8251F_TXEMP; - serial98_ports[0].txrdy = STAT_8251F_TXRDY; - serial98_ports[0].rxrdy = STAT_8251F_RXRDY; - serial98_ports[0].brk = STAT_8251F_BRK; - serial98_ports[0].fe = STAT_8251F_FER; - serial98_ports[0].oe = STAT_8251F_OER; - serial98_ports[0].pe = STAT_8251F_PER; - serial98_ports[0].dr = STAT_8251F_DSR; - - if (*(unsigned char*)__va(PC9821SCA_RSFLAGS) & 0x10) - serial98_ports[0].type = PORT_VFAST_PC98; - else { - outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT); - serial98_ports[0].port.uartclk *= 4; - serial98_ports[0].type = PORT_FIFO_PC98; - } - } else if ((serial98_ports[0].ext = inb(SERIAL98_EXT)) != 0xff) { - outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT); - if (inb(SERIAL98_EXT) == (serial98_ports[0].ext | 0x40)) { - serial98_ports[0].port.uartclk *= 4; - serial98_ports[0].type = PORT_19K_PC98; - } else { - serial98_ops.enable_ms = NULL; - outb(serial98_ports[0].ext, SERIAL98_EXT); - } - } - - if (serial98_request_region(serial98_ports[0].type)) - return -EBUSY; - - ret = uart_register_driver(&serial98_reg); - if (ret == 0) { - int i; - - for (i = 0; i < SERIAL98_NR; i++) { - uart_add_one_port(&serial98_reg, - (struct uart_port *)&serial98_ports[i]); - } - } - - return ret; -} - -static void __exit serial98_exit(void) -{ - int i; - - if (serial98_ports[0].type == PORT_19K_PC98 - || serial98_ports[0].type == PORT_FIFO_PC98) - outb(serial98_ports[0].ext, SERIAL98_EXT); - - for (i = 0; i < SERIAL98_NR; i++) { - uart_remove_one_port(&serial98_reg, - (struct uart_port *)&serial98_ports[i]); - } - - uart_unregister_driver(&serial98_reg); -} - -module_init(serial98_init); -module_exit(serial98_exit); - -MODULE_AUTHOR("Osamu Tomita "); -MODULE_DESCRIPTION("PC-9801 standard serial port driver Version 0.1alpha"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c --- a/drivers/telephony/ixj.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/telephony/ixj.c 2004-06-20 13:00:23 -07:00 @@ -461,8 +461,8 @@ static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf); static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr); static int ixj_init_tone(IXJ *j, IXJ_TONE * ti); -static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp); -static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp); +static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp); +static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp); /* Serial Control Interface funtions */ static int SCI_Control(IXJ *j, int control); static int SCI_Prepare(IXJ *j); @@ -2855,7 +2855,7 @@ } } -static ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos) +static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos) { unsigned long i = *ppos; IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode)); @@ -2910,7 +2910,7 @@ } } -static ssize_t ixj_enhanced_read(struct file * file_p, char *buf, size_t length, +static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos) { int pre_retval; @@ -2935,7 +2935,7 @@ return read_retval; } -static ssize_t ixj_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos) +static ssize_t ixj_write(struct file *file_p, const char __user *buf, size_t count, loff_t * ppos) { unsigned long i = *ppos; IXJ *j = file_p->private_data; @@ -2989,7 +2989,7 @@ return min(count, j->write_buffer_size); } -static ssize_t ixj_enhanced_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos) +static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, size_t count, loff_t * ppos) { int pre_retval; ssize_t write_retval = 0; @@ -5938,31 +5938,41 @@ ixj_WriteDSPCommand(0x3001, j); /* Test External SRAM */ } -static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp) +static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp) { - IXJ_CADENCE *lcp; + ixj_cadence *lcp; + IXJ_CADENCE_ELEMENT __user *cep; IXJ_CADENCE_ELEMENT *lcep; IXJ_TONE ti; + int err; - lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL); + lcp = kmalloc(sizeof(ixj_cadence), GFP_KERNEL); if (lcp == NULL) return -ENOMEM; - if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)) || (unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT) ) - { - kfree(lcp); - return -EFAULT; - } + + err = -EFAULT; + if (copy_from_user(&lcp->elements_used, + &cp->elements_used, sizeof(int))) + goto out; + if (copy_from_user(&lcp->termination, + &cp->termination, sizeof(IXJ_CADENCE_TERM))) + goto out; + if (get_user(cep, &cp->ce)) + goto out; + + err = -EINVAL; + if ((unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT)) + goto out; + + err = -ENOMEM; lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL); - if (lcep == NULL) { - kfree(lcp); - return -ENOMEM; - } - if (copy_from_user(lcep, lcp->ce, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used)) - { - kfree(lcep); - kfree(lcp); - return -EFAULT; - } + if (!lcep) + goto out; + + err = -EFAULT; + if (copy_from_user(lcep, cep, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used)) + goto out1; + if (j->cadence_t) { kfree(j->cadence_t->ce); kfree(j->cadence_t); @@ -5982,9 +5992,14 @@ } ixj_play_tone(j, lcp->ce[0].index); return 1; +out1: + kfree(lcep); +out: + kfree(lcp); + return err; } -static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp) +static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp) { IXJ_FILTER_CADENCE *lcp; lcp = kmalloc(sizeof(IXJ_FILTER_CADENCE), GFP_KERNEL); @@ -5994,7 +6009,7 @@ } return -ENOMEM; } - if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE))) { + if (copy_from_user(lcp, cp, sizeof(IXJ_FILTER_CADENCE))) { if(ixjdebug & 0x0001) { printk(KERN_INFO "Could not copy cadence to kernel\n"); } @@ -6206,6 +6221,7 @@ IXJ_TONE ti; IXJ_FILTER jf; IXJ_FILTER_RAW jfr; + void __user *argp = (void __user *)arg; unsigned int raise, mant; unsigned int minor = iminor(inode); @@ -6251,7 +6267,7 @@ retval = j->serial; break; case IXJCTL_VERSION: - if (copy_to_user((char *) arg, ixj_c_revision, strlen(ixj_c_revision))) + if (copy_to_user(argp, ixj_c_revision, strlen(ixj_c_revision))) retval = -EFAULT; break; case PHONE_RING_CADENCE: @@ -6259,7 +6275,7 @@ break; case IXJCTL_CIDCW: if(arg) { - if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) { + if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) { retval = -EFAULT; break; } @@ -6274,7 +6290,7 @@ /* Fall through */ case PHONE_RING_START: if(arg) { - if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) { + if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) { retval = -EFAULT; break; } @@ -6432,22 +6448,22 @@ samplerate = arg; break; case IXJCTL_DRYBUFFER_READ: - put_user(j->drybuffer, (unsigned long *) arg); + put_user(j->drybuffer, (unsigned long __user *) argp); break; case IXJCTL_DRYBUFFER_CLEAR: j->drybuffer = 0; break; case IXJCTL_FRAMES_READ: - put_user(j->framesread, (unsigned long *) arg); + put_user(j->framesread, (unsigned long __user *) argp); break; case IXJCTL_FRAMES_WRITTEN: - put_user(j->frameswritten, (unsigned long *) arg); + put_user(j->frameswritten, (unsigned long __user *) argp); break; case IXJCTL_READ_WAIT: - put_user(j->read_wait, (unsigned long *) arg); + put_user(j->read_wait, (unsigned long __user *) argp); break; case IXJCTL_WRITE_WAIT: - put_user(j->write_wait, (unsigned long *) arg); + put_user(j->write_wait, (unsigned long __user *) argp); break; case PHONE_MAXRINGS: j->maxrings = arg; @@ -6573,7 +6589,7 @@ 12, 10, 16, 9, 8, 48, 5, 40, 40, 80, 40, 40, 6 }; - if(copy_from_user(&pd, (void *)arg, sizeof(pd))) { + if(copy_from_user(&pd, argp, sizeof(pd))) { retval = -EFAULT; break; } @@ -6590,7 +6606,7 @@ default:val=proto_size[pd.type]*3;break; } pd.buf_min=pd.buf_max=pd.buf_opt=val; - if(copy_to_user((void *)arg, &pd, sizeof(pd))) + if(copy_to_user(argp, &pd, sizeof(pd))) retval = -EFAULT; break; } @@ -6644,7 +6660,7 @@ ixj_write_vmwi(j, arg); break; case IXJCTL_CID: - if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID))) + if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID))) retval = -EFAULT; j->ex.bits.caller_id = 0; break; @@ -6666,13 +6682,13 @@ break; case PHONE_CAPABILITIES_LIST: add_caps(j); - if (copy_to_user((char *) arg, j->caplist, sizeof(struct phone_capability) * j->caps)) + if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps)) retval = -EFAULT; break; case PHONE_CAPABILITIES_CHECK: { struct phone_capability cap; - if (copy_from_user(&cap, (char *) arg, sizeof(cap))) + if (copy_from_user(&cap, argp, sizeof(cap))) retval = -EFAULT; else { add_caps(j); @@ -6688,12 +6704,12 @@ j->ex.bits.pstn_ring = 0; break; case IXJCTL_SET_FILTER: - if (copy_from_user(&jf, (char *) arg, sizeof(jf))) + if (copy_from_user(&jf, argp, sizeof(jf))) retval = -EFAULT; retval = ixj_init_filter(j, &jf); break; case IXJCTL_SET_FILTER_RAW: - if (copy_from_user(&jfr, (char *) arg, sizeof(jfr))) + if (copy_from_user(&jfr, argp, sizeof(jfr))) retval = -EFAULT; else retval = ixj_init_filter_raw(j, &jfr); @@ -6705,19 +6721,19 @@ retval = j->filter_hist[arg]; break; case IXJCTL_INIT_TONE: - if (copy_from_user(&ti, (char *) arg, sizeof(ti))) + if (copy_from_user(&ti, argp, sizeof(ti))) retval = -EFAULT; else retval = ixj_init_tone(j, &ti); break; case IXJCTL_TONE_CADENCE: - retval = ixj_build_cadence(j, (IXJ_CADENCE *) arg); + retval = ixj_build_cadence(j, argp); break; case IXJCTL_FILTER_CADENCE: - retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg); + retval = ixj_build_filter_cadence(j, argp); break; case IXJCTL_SIGCTL: - if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) { + if (copy_from_user(&j->sigdef, argp, sizeof(IXJ_SIGDEF))) { retval = -EFAULT; break; } diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h --- a/drivers/telephony/ixj.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/telephony/ixj.h 2004-06-20 13:00:26 -07:00 @@ -1167,6 +1167,12 @@ ******************************************************************************/ typedef struct { + int elements_used; + IXJ_CADENCE_TERM termination; + IXJ_CADENCE_ELEMENT *ce; +} ixj_cadence; + +typedef struct { struct phone_device p; struct timer_list timer; unsigned int board; @@ -1220,8 +1226,8 @@ char tone_index; char tone_state; char maxrings; - IXJ_CADENCE *cadence_t; - IXJ_CADENCE *cadence_r; + ixj_cadence *cadence_t; + ixj_cadence *cadence_r; int tone_cadence_state; IXJ_CADENCE_F cadence_f[6]; DTMF dtmf; diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig --- a/drivers/usb/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/Kconfig 2004-06-20 13:00:23 -07:00 @@ -7,7 +7,7 @@ # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. config USB tristate "Support for Host-side USB" - depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 + depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_LH7A404 ---help--- Universal Serial Bus (USB) is a specification for a serial bus subsystem which offers higher speeds and more features than the diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c --- a/drivers/usb/class/audio.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/class/audio.c 2004-06-20 13:00:26 -07:00 @@ -2008,6 +2008,7 @@ { struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data; int i, j, val; + int __user *user_arg = (int __user *)arg; if (!ms->state->usbdev) return -ENODEV; @@ -2034,7 +2035,7 @@ return 0; } if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int *)arg); + return put_user(SOUND_VERSION, user_arg); if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) return -EINVAL; if (_IOC_DIR(cmd) == _IOC_READ) { @@ -2043,27 +2044,27 @@ val = get_rec_src(ms); if (val < 0) return val; - return put_user(val, (int *)arg); + return put_user(val, user_arg); case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ for (val = i = 0; i < ms->numch; i++) val |= 1 << ms->ch[i].osschannel; - return put_user(val, (int *)arg); + return put_user(val, user_arg); case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ for (val = i = 0; i < ms->numch; i++) if (ms->ch[i].slctunitid) val |= 1 << ms->ch[i].osschannel; - return put_user(val, (int *)arg); + return put_user(val, user_arg); case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ for (val = i = 0; i < ms->numch; i++) if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) val |= 1 << ms->ch[i].osschannel; - return put_user(val, (int *)arg); + return put_user(val, user_arg); case SOUND_MIXER_CAPS: - return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); + return put_user(SOUND_CAP_EXCL_INPUT, user_arg); default: i = _IOC_NR(cmd); @@ -2071,7 +2072,7 @@ return -EINVAL; for (j = 0; j < ms->numch; j++) { if (ms->ch[j].osschannel == i) { - return put_user(ms->ch[j].value, (int *)arg); + return put_user(ms->ch[j].value, user_arg); } } return -EINVAL; @@ -2082,7 +2083,7 @@ ms->modcnt++; switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; return set_rec_src(ms, val); @@ -2093,11 +2094,11 @@ for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++); if (j >= ms->numch) return -EINVAL; - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (wrmixer(ms, j, val)) return -EIO; - return put_user(ms->ch[j].value, (int *)arg); + return put_user(ms->ch[j].value, user_arg); } } @@ -2370,6 +2371,7 @@ { struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; struct usb_audio_state *s = as->state; + int __user *user_arg = (int __user *)arg; unsigned long flags; audio_buf_info abinfo; count_info cinfo; @@ -2387,7 +2389,7 @@ #endif switch (cmd) { case OSS_GETVERSION: - return put_user(SOUND_VERSION, (int *)arg); + return put_user(SOUND_VERSION, user_arg); case SNDCTL_DSP_SYNC: if (file->f_mode & FMODE_WRITE) @@ -2399,7 +2401,7 @@ case SNDCTL_DSP_GETCAPS: return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | - DSP_CAP_MMAP | DSP_CAP_BATCH, (int *)arg); + DSP_CAP_MMAP | DSP_CAP_BATCH, user_arg); case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_WRITE) { @@ -2413,7 +2415,7 @@ return 0; case SNDCTL_DSP_SPEED: - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (val >= 0) { if (val < 4000) @@ -2423,10 +2425,12 @@ if (set_format(as, file->f_mode, AFMT_QUERY, val)) return -EIO; } - return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg); + return put_user((file->f_mode & FMODE_READ) ? + as->usbin.dma.srate : as->usbout.dma.srate, + user_arg); case SNDCTL_DSP_STEREO: - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; if (val) @@ -2438,7 +2442,7 @@ return 0; case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (val != 0) { val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; @@ -2450,14 +2454,14 @@ return -EIO; } val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg); + return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | - AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg); + AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, user_arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (val != AFMT_QUERY) { if (hweight32(val) != 1) @@ -2471,7 +2475,7 @@ return -EIO; } val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(val2 & ~AFMT_STEREO, (int *)arg); + return put_user(val2 & ~AFMT_STEREO, user_arg); case SNDCTL_DSP_POST: return 0; @@ -2482,10 +2486,10 @@ val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) val |= PCM_ENABLE_OUTPUT; - return put_user(val, (int *)arg); + return put_user(val, user_arg); case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { @@ -2543,7 +2547,7 @@ spin_lock_irqsave(&as->lock, flags); val = as->usbout.dma.count; spin_unlock_irqrestore(&as->lock, flags); - return put_user(val, (int *)arg); + return put_user(val, user_arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) @@ -2577,14 +2581,14 @@ if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf_out(as))) return val; - return put_user(as->usbout.dma.fragsize, (int *)arg); + return put_user(as->usbout.dma.fragsize, user_arg); } if ((val = prog_dmabuf_in(as))) return val; - return put_user(as->usbin.dma.fragsize, (int *)arg); + return put_user(as->usbin.dma.fragsize, user_arg); case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { as->usbin.dma.ossfragshift = val & 0xffff; @@ -2612,7 +2616,7 @@ if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) || (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision)) return -EINVAL; - if (get_user(val, (int *)arg)) + if (get_user(val, user_arg)) return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; @@ -2623,15 +2627,17 @@ return 0; case SOUND_PCM_READ_RATE: - return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg); + return put_user((file->f_mode & FMODE_READ) ? + as->usbin.dma.srate : as->usbout.dma.srate, + user_arg); case SOUND_PCM_READ_CHANNELS: val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg); + return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg); case SOUND_PCM_READ_BITS: val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; - return put_user(AFMT_IS16BIT(val2) ? 16 : 8, (int *)arg); + return put_user(AFMT_IS16BIT(val2) ? 16 : 8, user_arg); case SOUND_PCM_WRITE_FILTER: case SNDCTL_DSP_SETSYNCRO: diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c --- a/drivers/usb/class/cdc-acm.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/class/cdc-acm.c 2004-06-20 13:00:25 -07:00 @@ -27,6 +27,7 @@ * v0.22 - probe only the control interface. if usbcore doesn't choose the * config we want, sysadmin changes bConfigurationValue in sysfs. * v0.23 - use softirq for rx processing, as needed by tty layer + * v0.24 - change probe method to evaluate CDC union descriptor */ /* @@ -60,6 +61,8 @@ #include #include +#include "cdc-acm.h" + /* * Version Information */ @@ -67,102 +70,12 @@ #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik" #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" -/* - * CMSPAR, some architectures can't have space and mark parity. - */ - -#ifndef CMSPAR -#define CMSPAR 0 -#endif - -/* - * Major and minor numbers. - */ - -#define ACM_TTY_MAJOR 166 -#define ACM_TTY_MINORS 32 - -/* - * Requests. - */ - -#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) - -#define ACM_REQ_COMMAND 0x00 -#define ACM_REQ_RESPONSE 0x01 -#define ACM_REQ_SET_FEATURE 0x02 -#define ACM_REQ_GET_FEATURE 0x03 -#define ACM_REQ_CLEAR_FEATURE 0x04 - -#define ACM_REQ_SET_LINE 0x20 -#define ACM_REQ_GET_LINE 0x21 -#define ACM_REQ_SET_CONTROL 0x22 -#define ACM_REQ_SEND_BREAK 0x23 - -/* - * IRQs. - */ - -#define ACM_IRQ_NETWORK 0x00 -#define ACM_IRQ_LINE_STATE 0x20 - -/* - * Output control lines. - */ - -#define ACM_CTRL_DTR 0x01 -#define ACM_CTRL_RTS 0x02 - -/* - * Input control lines and line errors. - */ - -#define ACM_CTRL_DCD 0x01 -#define ACM_CTRL_DSR 0x02 -#define ACM_CTRL_BRK 0x04 -#define ACM_CTRL_RI 0x08 - -#define ACM_CTRL_FRAMING 0x10 -#define ACM_CTRL_PARITY 0x20 -#define ACM_CTRL_OVERRUN 0x40 - -/* - * Line speed and caracter encoding. - */ - -struct acm_line { - __u32 speed; - __u8 stopbits; - __u8 parity; - __u8 databits; -} __attribute__ ((packed)); - -/* - * Internal driver structures. - */ - -struct acm { - struct usb_device *dev; /* the corresponding usb device */ - struct usb_interface *control; /* control interface */ - struct usb_interface *data; /* data interface */ - struct tty_struct *tty; /* the corresponding tty */ - struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ - struct acm_line line; /* line coding (bits, stop, parity) */ - struct work_struct work; /* work queue entry for line discipline waking up */ - struct tasklet_struct bh; /* rx processing */ - unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ - unsigned int ctrlout; /* output control lines (DTR, RTS) */ - unsigned int writesize; /* max packet size for the output bulk endpoint */ - unsigned int used; /* someone has this acm's device open */ - unsigned int minor; /* acm minor number */ - unsigned char throttle; /* throttled by tty layer */ - unsigned char clocal; /* termios CLOCAL */ -}; - static struct usb_driver acm_driver; static struct tty_driver *acm_tty_driver; static struct acm *acm_table[ACM_TTY_MINORS]; +static DECLARE_MUTEX(open_sem); + #define ACM_READY(acm) (acm && acm->dev && acm->used) /* @@ -310,12 +223,14 @@ struct acm *acm = (struct acm *)urb->context; if (!ACM_READY(acm)) - return; + goto out; if (urb->status) dbg("nonzero write bulk status received: %d", urb->status); schedule_work(&acm->work); +out: + acm->ready_for_write = 1; } static void acm_softint(void *private) @@ -346,22 +261,23 @@ tty->driver_data = acm; acm->tty = tty; - lock_kernel(); + down(&open_sem); - if (acm->used++) { - unlock_kernel(); - return 0; + if (acm->used) { + goto done; } - unlock_kernel(); - acm->ctrlurb->dev = acm->dev; - if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) + if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dbg("usb_submit_urb(ctrl irq) failed"); + goto bail_out; + } acm->readurb->dev = acm->dev; - if (usb_submit_urb(acm->readurb, GFP_KERNEL)) + if (usb_submit_urb(acm->readurb, GFP_KERNEL)) { dbg("usb_submit_urb(read bulk) failed"); + goto bail_out_and_unlink; + } acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS); @@ -369,7 +285,16 @@ otherwise it is scheduled, and with high data rates data can get lost. */ tty->low_latency = 1; +done: + acm->used++; + up(&open_sem); return 0; + +bail_out_and_unlink: + usb_unlink_urb(acm->ctrlurb); +bail_out: + up(&open_sem); + return -EIO; } static void acm_tty_close(struct tty_struct *tty, struct file *filp) @@ -379,6 +304,7 @@ if (!acm || !acm->used) return; + down(&open_sem); if (!--acm->used) { if (acm->dev) { acm_set_control(acm, acm->ctrlout = 0); @@ -394,6 +320,7 @@ kfree(acm); } } + up(&open_sem); } static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) @@ -403,7 +330,7 @@ if (!ACM_READY(acm)) return -EINVAL; - if (acm->writeurb->status == -EINPROGRESS) + if (!acm->ready_for_write) return 0; if (!count) return 0; @@ -419,10 +346,11 @@ acm->writeurb->transfer_buffer_length = count; acm->writeurb->dev = acm->dev; - /* GFP_KERNEL probably works if from_user */ - stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC); + acm->ready_for_write = 0; + stat = usb_submit_urb(acm->writeurb, GFP_NOIO); if (stat < 0) { dbg("usb_submit_urb(write bulk) failed"); + acm->ready_for_write = 1; return stat; } @@ -434,7 +362,7 @@ struct acm *acm = tty->driver_data; if (!ACM_READY(acm)) return -EINVAL; - return acm->writeurb->status == -EINPROGRESS ? 0 : acm->writesize; + return !acm->ready_for_write ? 0 : acm->writesize; } static int acm_tty_chars_in_buffer(struct tty_struct *tty) @@ -442,7 +370,7 @@ struct acm *acm = tty->driver_data; if (!ACM_READY(acm)) return -EINVAL; - return acm->writeurb->status == -EINPROGRESS ? acm->writeurb->transfer_buffer_length : 0; + return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0; } static void acm_tty_throttle(struct tty_struct *tty) @@ -567,77 +495,102 @@ * USB probe and disconnect routines. */ -#define CHECK_XFERTYPE(descr, xfer_type) (((descr)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == xfer_type) - static int acm_probe (struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_device *dev; + struct union_desc *union_header = NULL; + char *buffer = intf->altsetting->extra; + int buflen = intf->altsetting->extralen; + struct usb_interface *control_interface; + struct usb_interface *data_interface; + struct usb_endpoint_descriptor *epctrl; + struct usb_endpoint_descriptor *epread; + struct usb_endpoint_descriptor *epwrite; + struct usb_device *usb_dev = interface_to_usbdev(intf); struct acm *acm; - struct usb_host_config *cfacm; - struct usb_interface *data = NULL; - struct usb_host_interface *ifcom, *ifdata = NULL; - struct usb_endpoint_descriptor *epctrl = NULL; - struct usb_endpoint_descriptor *epread = NULL; - struct usb_endpoint_descriptor *epwrite = NULL; - int readsize, ctrlsize, minor, j; - unsigned char *buf; - - dev = interface_to_usbdev (intf); - - cfacm = dev->actconfig; - - /* We know we're probe()d with the control interface. */ - ifcom = intf->cur_altsetting; - - /* ACM doesn't guarantee the data interface is - * adjacent to the control interface, or that if one - * is there it's not for call management ... so find - * it - */ - for (j = 0; j < cfacm->desc.bNumInterfaces; j++) { - ifdata = cfacm->interface[j]->cur_altsetting; - data = cfacm->interface[j]; - - if (ifdata->desc.bInterfaceClass == USB_CLASS_CDC_DATA - && ifdata->desc.bNumEndpoints == 2) { - - epctrl = &ifcom->endpoint[0].desc; - epread = &ifdata->endpoint[0].desc; - epwrite = &ifdata->endpoint[1].desc; - - if ((epctrl->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN - || !CHECK_XFERTYPE(epctrl, USB_ENDPOINT_XFER_INT) - || !CHECK_XFERTYPE(epread, USB_ENDPOINT_XFER_BULK) - || !CHECK_XFERTYPE(epwrite, USB_ENDPOINT_XFER_BULK) - || ((epread->bEndpointAddress & USB_DIR_IN) - ^ (epwrite->bEndpointAddress & USB_DIR_IN)) != USB_DIR_IN) { - /* not suitable */ - goto next_interface; - } - - if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) { - /* descriptors are swapped */ - epread = &ifdata->endpoint[1].desc; - epwrite = &ifdata->endpoint[0].desc; - } - dev_dbg(&intf->dev, "found data interface at %d\n", j); - break; - } else { -next_interface: - ifdata = NULL; - data = NULL; + int minor; + int ctrlsize,readsize; + char *buf; + + if (!buffer) { + err("Wierd descriptor references"); + return -EINVAL; + } + + while (buflen > 0) { + if (buffer [1] != USB_DT_CS_INTERFACE) { + err("skipping garbage"); + goto next_desc; } + + switch (buffer [2]) { + case CDC_UNION_TYPE: /* we've found it */ + if (union_header) { + err("More than one union descriptor, skipping ..."); + goto next_desc; + } + union_header = (struct union_desc *)buffer; + break; + default: + err("Ignoring extra header"); + break; + } +next_desc: + buflen -= buffer[0]; + buffer += buffer[0]; } - /* there's been a problem */ - if (!ifdata) { - dev_dbg(&intf->dev, "data interface not found\n"); + if (!union_header) { + dev_dbg(&intf->dev,"No union descriptor, giving up\n"); return -ENODEV; + } + control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); + data_interface = usb_ifnum_to_if(usb_dev, union_header->bSlaveInterface0); + if (!control_interface || !data_interface) { + dev_dbg(&intf->dev,"no interfaces\n"); + return -ENODEV; + } + + if (usb_interface_claimed(data_interface)) { /* valid in this context */ + dev_dbg(&intf->dev,"The data interface isn't available\n"); + return -EBUSY; } + /*workaround for switched interfaces */ + if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) { + if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) { + struct usb_interface *t; + dev_dbg(&intf->dev,"Your device has switched interfaces.\n"); + + t = control_interface; + control_interface = data_interface; + data_interface = t; + } else { + return -EINVAL; + } + } + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) + return -EINVAL; + + epctrl = &control_interface->cur_altsetting->endpoint[0].desc; + epread = &data_interface->cur_altsetting->endpoint[0].desc; + epwrite = &data_interface->cur_altsetting->endpoint[1].desc; + + + /* workaround for switched endpoints */ + if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) { + /* descriptors are swapped */ + struct usb_endpoint_descriptor *t; + dev_dbg(&intf->dev,"The data interface has switched endpoints\n"); + + t = epread; + epread = epwrite; + epwrite = t; + } + dbg("interfaces are valid"); for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); + if (acm_table[minor]) { err("no more free acm devices"); return -ENODEV; @@ -647,20 +600,21 @@ dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n"); return -ENOMEM; } - memset(acm, 0, sizeof(struct acm)); ctrlsize = epctrl->wMaxPacketSize; readsize = epread->wMaxPacketSize; acm->writesize = epwrite->wMaxPacketSize; - acm->control = intf; - acm->data = data; + acm->control = control_interface; + acm->data = data_interface; acm->minor = minor; - acm->dev = dev; + acm->dev = usb_dev; acm->bh.func = acm_rx_tasklet; acm->bh.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint, acm); + acm->ready_for_write = 1; + if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { dev_dbg(&intf->dev, "out of memory (buf kmalloc)\n"); @@ -693,29 +647,17 @@ return -ENOMEM; } - usb_fill_int_urb(acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), - buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); + usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), + buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); - usb_fill_bulk_urb(acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), - buf += ctrlsize, readsize, acm_read_bulk, acm); + usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress), + buf += ctrlsize, readsize, acm_read_bulk, acm); acm->readurb->transfer_flags |= URB_NO_FSBR; - usb_fill_bulk_urb(acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), - buf += readsize, acm->writesize, acm_write_bulk, acm); + usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + buf += readsize, acm->writesize, acm_write_bulk, acm); acm->writeurb->transfer_flags |= URB_NO_FSBR; - if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) { - err("claim failed"); - usb_free_urb(acm->ctrlurb); - usb_free_urb(acm->readurb); - usb_free_urb(acm->writeurb); - kfree(acm); - kfree(buf); - return j; - } - - tty_register_device(acm_tty_driver, minor, &intf->dev); - dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); acm_set_control(acm, acm->ctrlout); @@ -724,11 +666,14 @@ acm->line.databits = 8; acm_set_line(acm, &acm->line); + usb_driver_claim_interface(&acm_driver, data_interface, acm); + + tty_register_device(acm_tty_driver, minor, &intf->dev); + acm_table[minor] = acm; usb_set_intfdata (intf, acm); return 0; } -#undef CHECK_XFERTYPE static void acm_disconnect(struct usb_interface *intf) { @@ -745,6 +690,8 @@ usb_unlink_urb(acm->ctrlurb); usb_unlink_urb(acm->readurb); usb_unlink_urb(acm->writeurb); + + flush_scheduled_work(); /* wait for acm_softint */ kfree(acm->ctrlurb->transfer_buffer); diff -Nru a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/usb/class/cdc-acm.h 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,115 @@ +/* + * + * Includes for cdc-acm.c + * + * Mainly take from usbnet's cdc-ether part + * + */ + +/* + * CMSPAR, some architectures can't have space and mark parity. + */ + +#ifndef CMSPAR +#define CMSPAR 0 +#endif + +/* + * Major and minor numbers. + */ + +#define ACM_TTY_MAJOR 166 +#define ACM_TTY_MINORS 32 + +/* + * Requests. + */ + +#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) + +#define ACM_REQ_COMMAND 0x00 +#define ACM_REQ_RESPONSE 0x01 +#define ACM_REQ_SET_FEATURE 0x02 +#define ACM_REQ_GET_FEATURE 0x03 +#define ACM_REQ_CLEAR_FEATURE 0x04 + +#define ACM_REQ_SET_LINE 0x20 +#define ACM_REQ_GET_LINE 0x21 +#define ACM_REQ_SET_CONTROL 0x22 +#define ACM_REQ_SEND_BREAK 0x23 + +/* + * IRQs. + */ + +#define ACM_IRQ_NETWORK 0x00 +#define ACM_IRQ_LINE_STATE 0x20 + +/* + * Output control lines. + */ + +#define ACM_CTRL_DTR 0x01 +#define ACM_CTRL_RTS 0x02 + +/* + * Input control lines and line errors. + */ + +#define ACM_CTRL_DCD 0x01 +#define ACM_CTRL_DSR 0x02 +#define ACM_CTRL_BRK 0x04 +#define ACM_CTRL_RI 0x08 + +#define ACM_CTRL_FRAMING 0x10 +#define ACM_CTRL_PARITY 0x20 +#define ACM_CTRL_OVERRUN 0x40 + +/* + * Line speed and caracter encoding. + */ + +struct acm_line { + __u32 speed; + __u8 stopbits; + __u8 parity; + __u8 databits; +} __attribute__ ((packed)); + +/* + * Internal driver structures. + */ + +struct acm { + struct usb_device *dev; /* the corresponding usb device */ + struct usb_interface *control; /* control interface */ + struct usb_interface *data; /* data interface */ + struct tty_struct *tty; /* the corresponding tty */ + struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ + struct acm_line line; /* line coding (bits, stop, parity) */ + struct work_struct work; /* work queue entry for line discipline waking up */ + struct tasklet_struct bh; /* rx processing */ + unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ + unsigned int ctrlout; /* output control lines (DTR, RTS) */ + unsigned int writesize; /* max packet size for the output bulk endpoint */ + unsigned int used; /* someone has this acm's device open */ + unsigned int minor; /* acm minor number */ + unsigned char throttle; /* throttled by tty layer */ + unsigned char clocal; /* termios CLOCAL */ + unsigned char ready_for_write; /* write urb can be used */ +}; + +/* "Union Functional Descriptor" from CDC spec 5.2.3.X */ +struct union_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + + u8 bMasterInterface0; + u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__ ((packed)); + +#define CDC_UNION_TYPE 0x06 +#define CDC_DATA_INTERFACE_TYPE 0x0a + diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c --- a/drivers/usb/class/usblp.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/class/usblp.c 2004-06-20 13:00:23 -07:00 @@ -75,6 +75,7 @@ #define IOCNR_HP_SET_CHANNEL 4 #define IOCNR_GET_BUS_ADDRESS 5 #define IOCNR_GET_VID_PID 6 +#define IOCNR_SOFT_RESET 7 /* Get device_id string: */ #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* The following ioctls were added for http://hpoj.sourceforge.net: */ @@ -90,6 +91,8 @@ #define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len) /* Get two-int array: [0]=vendor ID, [1]=product ID: */ #define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len) +/* Perform class specific soft reset */ +#define LPIOC_SOFT_RESET _IOC(_IOC_NONE, 'P', IOCNR_SOFT_RESET, 0); /* * A DEVICE_ID string may include the printer's serial number. @@ -587,6 +590,13 @@ usblp->minor, twoints[0], twoints[1]); break; + case IOCNR_SOFT_RESET: + if (_IOC_DIR(cmd) != _IOC_NONE) { + retval = -EINVAL; + goto done; + } + retval = usblp_reset(usblp); + break; default: retval = -ENOTTY; } @@ -761,6 +771,7 @@ usblp->minor, usblp->readurb->status); usblp->readurb->dev = usblp->dev; usblp->readcount = 0; + usblp->rcomplete = 0; if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) dbg("error submitting urb"); count = -EIO; diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c --- a/drivers/usb/core/devices.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/core/devices.c 2004-06-20 13:00:26 -07:00 @@ -589,6 +589,8 @@ bus = list_entry(buslist, struct usb_bus, bus_list); /* recurse through all children of the root hub */ + if (!bus->root_hub) + continue; down(&bus->root_hub->serialize); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); up(&bus->root_hub->serialize); diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c --- a/drivers/usb/core/devio.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/core/devio.c 2004-06-20 13:00:24 -07:00 @@ -558,7 +558,7 @@ if (usbfs_snoop) { dev_info(&dev->dev, "control read: data "); for (j = 0; j < ctrl.wLength; ++j) - printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]); + printk ("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) { @@ -578,7 +578,7 @@ if (usbfs_snoop) { dev_info(&dev->dev, "control write: data: "); for (j = 0; j < ctrl.wLength; ++j) - printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]); + printk ("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/core/hcd-pci.c 2004-06-20 13:00:24 -07:00 @@ -229,7 +229,6 @@ void usb_hcd_pci_remove (struct pci_dev *dev) { struct usb_hcd *hcd; - struct usb_device *hub; hcd = pci_get_drvdata(dev); if (!hcd) @@ -239,12 +238,11 @@ if (in_interrupt ()) BUG (); - hub = hcd->self.root_hub; if (HCD_IS_RUNNING (hcd->state)) hcd->state = USB_STATE_QUIESCING; dev_dbg (hcd->self.controller, "roothub graceful disconnect\n"); - usb_disconnect (&hub); + usb_disconnect (&hcd->self.root_hub); hcd->driver->stop (hcd); hcd_buffer_destroy (hcd); diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/core/hcd.c 2004-06-20 13:00:24 -07:00 @@ -764,8 +764,9 @@ * * The USB host controller calls this function to register the root hub * properly with the USB subsystem. It sets up the device properly in - * the device model tree, and then calls usb_new_device() to register the - * usb device. It also assigns the root hub's USB address (always 1). + * the device tree and stores the root_hub pointer in the bus structure, + * then calls usb_new_device() to register the usb device. It also + * assigns the root hub's USB address (always 1). */ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev) { @@ -777,7 +778,10 @@ memset (&usb_dev->bus->devmap.devicemap, 0, sizeof usb_dev->bus->devmap.devicemap); set_bit (devnum, usb_dev->bus->devmap.devicemap); - usb_dev->state = USB_STATE_ADDRESS; + usb_set_device_state(usb_dev, USB_STATE_ADDRESS); + + down (&usb_bus_list_lock); + usb_dev->bus->root_hub = usb_dev; usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64; retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); @@ -787,14 +791,15 @@ return (retval < 0) ? retval : -EMSGSIZE; } - (void) usb_get_dev (usb_dev); down (&usb_dev->serialize); retval = usb_new_device (usb_dev); - if (retval) + up (&usb_dev->serialize); + if (retval) { + usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", usb_dev->dev.bus_id, retval); - up (&usb_dev->serialize); - usb_put_dev (usb_dev); + } + up (&usb_bus_list_lock); return retval; } EXPORT_SYMBOL (usb_register_root_hub); @@ -1574,11 +1579,13 @@ unsigned i; /* hc's root hub is removed later removed in hcd->stop() */ - hub->state = USB_STATE_NOTATTACHED; + down (&hub->serialize); + usb_set_device_state(hub, USB_STATE_NOTATTACHED); for (i = 0; i < hub->maxchild; i++) { if (hub->children [i]) usb_disconnect (&hub->children [i]); } + up (&hub->serialize); } /** diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/core/hcd.h 2004-06-20 13:00:24 -07:00 @@ -244,17 +244,10 @@ struct usb_bus *, unsigned port); extern int usb_new_device(struct usb_device *dev); extern void usb_disconnect(struct usb_device **); -extern void usb_choose_address(struct usb_device *dev); -extern void usb_release_address(struct usb_device *dev); -/* exported to hub driver ONLY to support usb_reset_device () */ extern int usb_get_configuration(struct usb_device *dev); extern void usb_destroy_configuration(struct usb_device *dev); -/* use these only before the device's address has been set */ -#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30)) -#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN) - /*-------------------------------------------------------------------------*/ /* @@ -346,7 +339,8 @@ extern int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev); -static inline int hcd_register_root (struct usb_hcd *hcd) +static inline int hcd_register_root (struct usb_device *usb_dev, + struct usb_hcd *hcd) { /* hcd->driver->start() reported can_wakeup, probably with * assistance from board's boot firmware. @@ -356,8 +350,7 @@ dev_dbg (hcd->self.controller, "supports USB remote wakeup\n"); hcd->remote_wakeup = hcd->can_wakeup; - return usb_register_root_hub ( - hcd_to_bus (hcd)->root_hub, hcd->self.controller); + return usb_register_root_hub (usb_dev, hcd->self.controller); } /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/core/hub.c 2004-06-20 13:00:24 -07:00 @@ -9,6 +9,11 @@ */ #include +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif #include #include #include @@ -19,11 +24,6 @@ #include #include #include -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif #include #include #include @@ -36,11 +36,13 @@ #include "hcd.h" #include "hub.h" +/* Protect all struct usb_device state members */ +static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED; + /* Wakes up khubd */ static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ -static LIST_HEAD(hub_list); /* List of all hubs (for cleanup) */ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); static pid_t khubd_pid = 0; /* PID of khubd */ @@ -229,6 +231,8 @@ { struct usb_hub *hub = (struct usb_hub *)urb->context; int status; + int i; + unsigned long bits; spin_lock(&hub_event_lock); hub->urb_active = 0; @@ -253,6 +257,11 @@ /* let khubd handle things */ case 0: /* we got data: port status changed */ + bits = 0; + for (i = 0; i < urb->actual_length; ++i) + bits |= ((unsigned long) ((*hub->buffer)[i])) + << (i*8); + hub->event_bits[0] = bits; break; } @@ -260,7 +269,7 @@ /* Something happened, let khubd figure it out */ if (list_empty(&hub->event_list)) { - list_add(&hub->event_list, &hub_event_list); + list_add_tail(&hub->event_list, &hub_event_list); wake_up(&khubd_wait); } @@ -268,7 +277,7 @@ if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 /* ENODEV means we raced disconnect() */ && status != -ENODEV) - dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status); + dev_err (&hub->intf->dev, "resubmit --> %d\n", status); if (status == 0) hub->urb_active = 1; done: @@ -632,7 +641,6 @@ { struct usb_hub *hub = usb_get_intfdata (intf); DECLARE_COMPLETION(urb_complete); - unsigned long flags; if (!hub) return; @@ -641,17 +649,13 @@ highspeed_hubs--; usb_set_intfdata (intf, NULL); - spin_lock_irqsave(&hub_event_lock, flags); + spin_lock_irq(&hub_event_lock); hub->urb_complete = &urb_complete; /* Delete it and then reset it */ list_del_init(&hub->event_list); - list_del_init(&hub->hub_list); - spin_unlock_irqrestore(&hub_event_lock, flags); - - down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */ - up(&hub->khubd_sem); + spin_unlock_irq(&hub_event_lock); /* assuming we used keventd, it must quiesce too */ if (hub->has_indicators) @@ -695,7 +699,6 @@ struct usb_device *hdev; struct usb_hub *hub; struct device *hub_dev; - unsigned long flags; desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); @@ -711,23 +714,19 @@ } /* Multiple endpoints? What kind of mutant ninja-hub is this? */ - if (desc->desc.bNumEndpoints != 1) { + if (desc->desc.bNumEndpoints != 1) goto descriptor_error; - } endpoint = &desc->endpoint[0].desc; /* Output endpoint? Curiouser and curiouser.. */ - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) goto descriptor_error; - } /* If it's not an interrupt endpoint, we'd better punt! */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) { + != USB_ENDPOINT_XFER_INT) goto descriptor_error; - return -EIO; - } /* We found a hub */ dev_info (hub_dev, "USB hub found\n"); @@ -742,15 +741,8 @@ INIT_LIST_HEAD(&hub->event_list); hub->intf = intf; - init_MUTEX(&hub->khubd_sem); INIT_WORK(&hub->leds, led_work, hub); - /* Record the new hub's existence */ - spin_lock_irqsave(&hub_event_lock, flags); - INIT_LIST_HEAD(&hub->hub_list); - list_add(&hub->hub_list, &hub_list); - spin_unlock_irqrestore(&hub_event_lock, flags); - usb_set_intfdata (intf, hub); if (hdev->speed == USB_SPEED_HIGH) @@ -827,6 +819,7 @@ return 0; } +/* FIXME! This routine should be subsumed into hub_reset */ static void hub_start_disconnect(struct usb_device *hdev) { struct usb_device *parent = hdev->parent; @@ -845,6 +838,289 @@ dev_err(&hdev->dev, "cannot disconnect hub!\n"); } + +static void recursively_mark_NOTATTACHED(struct usb_device *udev) +{ + int i; + + for (i = 0; i < udev->maxchild; ++i) { + if (udev->children[i]) + recursively_mark_NOTATTACHED(udev->children[i]); + } + udev->state = USB_STATE_NOTATTACHED; +} + +/** + * usb_set_device_state - change a device's current state (usbcore-internal) + * @udev: pointer to device whose state should be changed + * @new_state: new state value to be stored + * + * udev->state is _not_ protected by the udev->serialize semaphore. This + * is so that devices can be marked as disconnected as soon as possible, + * without having to wait for the semaphore to be released. Instead, + * changes to the state must be protected by the device_state_lock spinlock. + * + * Once a device has been added to the device tree, all changes to its state + * should be made using this routine. The state should _not_ be set directly. + * + * If udev->state is already USB_STATE_NOTATTACHED then no change is made. + * Otherwise udev->state is set to new_state, and if new_state is + * USB_STATE_NOTATTACHED then all of udev's descendant's states are also set + * to USB_STATE_NOTATTACHED. + */ +void usb_set_device_state(struct usb_device *udev, + enum usb_device_state new_state) +{ + unsigned long flags; + + spin_lock_irqsave(&device_state_lock, flags); + if (udev->state == USB_STATE_NOTATTACHED) + ; /* do nothing */ + else if (new_state != USB_STATE_NOTATTACHED) + udev->state = new_state; + else + recursively_mark_NOTATTACHED(udev); + spin_unlock_irqrestore(&device_state_lock, flags); +} + + +static void choose_address(struct usb_device *udev) +{ + int devnum; + struct usb_bus *bus = udev->bus; + + /* If khubd ever becomes multithreaded, this will need a lock */ + + /* Try to allocate the next devnum beginning at bus->devnum_next. */ + devnum = find_next_zero_bit(bus->devmap.devicemap, 128, + bus->devnum_next); + if (devnum >= 128) + devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1); + + bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); + + if (devnum < 128) { + set_bit(devnum, bus->devmap.devicemap); + udev->devnum = devnum; + } +} + +static void release_address(struct usb_device *udev) +{ + if (udev->devnum > 0) { + clear_bit(udev->devnum, udev->bus->devmap.devicemap); + udev->devnum = -1; + } +} + +/** + * usb_disconnect - disconnect a device (usbcore-internal) + * @pdev: pointer to device being disconnected + * Context: !in_interrupt () + * + * Something got disconnected. Get rid of it, and all of its children. + * If *pdev is a normal device then the parent hub should be locked. + * If *pdev is a root hub then this routine will acquire the + * usb_bus_list_lock on behalf of the caller. + * + * Only hub drivers (including virtual root hub drivers for host + * controllers) should ever call this. + * + * This call is synchronous, and may not be used in an interrupt context. + */ +void usb_disconnect(struct usb_device **pdev) +{ + struct usb_device *udev = *pdev; + int i; + + if (!udev) { + pr_debug ("%s nodev\n", __FUNCTION__); + return; + } + + /* mark the device as inactive, so any further urb submissions for + * this device will fail. + */ + usb_set_device_state(udev, USB_STATE_NOTATTACHED); + + /* lock the bus list on behalf of HCDs unregistering their root hubs */ + if (!udev->parent) + down(&usb_bus_list_lock); + down(&udev->serialize); + + dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); + + /* Free up all the children before we remove this device */ + for (i = 0; i < USB_MAXCHILDREN; i++) { + if (udev->children[i]) + usb_disconnect(&udev->children[i]); + } + + /* deallocate hcd/hardware state ... nuking all pending urbs and + * cleaning up all state associated with the current configuration + */ + usb_disable_device(udev, 0); + + /* Free the device number, remove the /proc/bus/usb entry and + * the sysfs attributes, and delete the parent's children[] + * (or root_hub) pointer. + */ + dev_dbg (&udev->dev, "unregistering device\n"); + release_address(udev); + usbfs_remove_device(udev); + usb_remove_sysfs_dev_files(udev); + + /* Avoid races with recursively_mark_NOTATTACHED() */ + spin_lock_irq(&device_state_lock); + *pdev = NULL; + spin_unlock_irq(&device_state_lock); + + up(&udev->serialize); + if (!udev->parent) + up(&usb_bus_list_lock); + + device_unregister(&udev->dev); +} + +static int choose_configuration(struct usb_device *udev) +{ + int c, i; + + /* NOTE: this should interact with hub power budgeting */ + + c = udev->config[0].desc.bConfigurationValue; + if (udev->descriptor.bNumConfigurations != 1) { + for (i = 0; i < udev->descriptor.bNumConfigurations; i++) { + struct usb_interface_descriptor *desc; + + /* heuristic: Linux is more likely to have class + * drivers, so avoid vendor-specific interfaces. + */ + desc = &udev->config[i].intf_cache[0] + ->altsetting->desc; + if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) + continue; + /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */ + if (desc->bInterfaceClass == USB_CLASS_COMM + && desc->bInterfaceSubClass == 2 + && desc->bInterfaceProtocol == 0xff) + continue; + c = udev->config[i].desc.bConfigurationValue; + break; + } + dev_info(&udev->dev, + "configuration #%d chosen from %d choices\n", + c, udev->descriptor.bNumConfigurations); + } + return c; +} + +#ifdef DEBUG +static void show_string(struct usb_device *udev, char *id, int index) +{ + char *buf; + + if (!index) + return; + if (!(buf = kmalloc(256, GFP_KERNEL))) + return; + if (usb_string(udev, index, buf, 256) > 0) + dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, buf); + kfree(buf); +} + +#else +static inline void show_string(struct usb_device *udev, char *id, int index) +{} +#endif + +/* + * usb_new_device - perform initial device setup (usbcore-internal) + * @udev: newly addressed device (in ADDRESS state) + * + * This is called with devices which have been enumerated, but not yet + * configured. The device descriptor is available, but not descriptors + * for any device configuration. The caller must have locked udev and + * either the parent hub (if udev is a normal device) or else the + * usb_bus_list_lock (if udev is a root hub). The parent's pointer to + * udev has already been installed, but udev is not yet visible through + * sysfs or other filesystem code. + * + * Returns 0 for success (device is configured and listed, with its + * interfaces, in sysfs); else a negative errno value. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Only the hub driver should ever call this; root hub registration + * uses it indirectly. + */ +int usb_new_device(struct usb_device *udev) +{ + int err; + int c; + + err = usb_get_configuration(udev); + if (err < 0) { + dev_err(&udev->dev, "can't read configurations, error %d\n", + err); + goto fail; + } + + /* Tell the world! */ + dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, " + "SerialNumber=%d\n", + udev->descriptor.iManufacturer, + udev->descriptor.iProduct, + udev->descriptor.iSerialNumber); + + if (udev->descriptor.iProduct) + show_string(udev, "Product", + udev->descriptor.iProduct); + if (udev->descriptor.iManufacturer) + show_string(udev, "Manufacturer", + udev->descriptor.iManufacturer); + if (udev->descriptor.iSerialNumber) + show_string(udev, "SerialNumber", + udev->descriptor.iSerialNumber); + + /* put device-specific files into sysfs */ + err = device_add (&udev->dev); + if (err) { + dev_err(&udev->dev, "can't device_add, error %d\n", err); + goto fail; + } + usb_create_sysfs_dev_files (udev); + + /* choose and set the configuration. that registers the interfaces + * with the driver core, and lets usb device drivers bind to them. + */ + c = choose_configuration(udev); + if (c < 0) + dev_warn(&udev->dev, + "can't choose an initial configuration\n"); + else { + err = usb_set_configuration(udev, c); + if (err) { + dev_err(&udev->dev, "can't set config #%d, error %d\n", + c, err); + usb_remove_sysfs_dev_files(udev); + device_del(&udev->dev); + goto fail; + } + } + + /* USB device state == configured ... usable */ + + /* add a /proc/bus/usb entry */ + usbfs_add_device(udev); + return 0; + +fail: + usb_set_device_state(udev, USB_STATE_NOTATTACHED); + return err; +} + + static int hub_port_status(struct usb_device *hdev, int port, u16 *status, u16 *change) { @@ -934,16 +1210,20 @@ /* Reset the port */ for (i = 0; i < PORT_RESET_TRIES; i++) { - set_port_feature(hdev, port + 1, USB_PORT_FEAT_RESET); + status = set_port_feature(hdev, port + 1, USB_PORT_FEAT_RESET); + if (status) + dev_err(hub_dev, "cannot reset port %d (err = %d)\n", + port + 1, status); + else + status = hub_port_wait_reset(hdev, port, udev, delay); /* return on disconnect or reset */ - status = hub_port_wait_reset(hdev, port, udev, delay); if (status == -ENOTCONN || status == 0) { clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_RESET); - udev->state = status + usb_set_device_state(udev, status ? USB_STATE_NOTATTACHED - : USB_STATE_DEFAULT; + : USB_STATE_DEFAULT); return status; } @@ -964,6 +1244,9 @@ { int ret; + if (hdev->children[port]) + usb_set_device_state(hdev->children[port], + USB_STATE_NOTATTACHED); ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE); if (ret) dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n", @@ -975,57 +1258,62 @@ /* USB 2.0 spec, 7.1.7.3 / fig 7-29: * * Between connect detection and reset signaling there must be a delay - * of 100ms at least for debounce and power-settling. The corresponding + * of 100ms at least for debounce and power-settling. The corresponding * timer shall restart whenever the downstream port detects a disconnect. * - * Apparently there are some bluetooth and irda-dongles and a number - * of low-speed devices which require longer delays of about 200-400ms. + * Apparently there are some bluetooth and irda-dongles and a number of + * low-speed devices for which this debounce period may last over a second. * Not covered by the spec - but easy to deal with. * - * This implementation uses 400ms minimum debounce timeout and checks - * every 25ms for transient disconnects to restart the delay. + * This implementation uses a 1500ms total debounce timeout; if the + * connection isn't stable by then it returns -ETIMEDOUT. It checks + * every 25ms for transient disconnects. When the port status has been + * unchanged for 100ms it returns the port status. */ -#define HUB_DEBOUNCE_TIMEOUT 400 -#define HUB_DEBOUNCE_STEP 25 -#define HUB_DEBOUNCE_STABLE 4 +#define HUB_DEBOUNCE_TIMEOUT 1500 +#define HUB_DEBOUNCE_STEP 25 +#define HUB_DEBOUNCE_STABLE 100 static int hub_port_debounce(struct usb_device *hdev, int port) { int ret; - int delay_time, stable_count; + int total_time, stable_time = 0; u16 portchange, portstatus; - unsigned connection; - - connection = 0; - stable_count = 0; - for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) { - msleep(HUB_DEBOUNCE_STEP); + unsigned connection = 0xffff; + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { ret = hub_port_status(hdev, port, &portstatus, &portchange); if (ret < 0) return ret; - if ((portstatus & USB_PORT_STAT_CONNECTION) == connection) { - if (connection) { - if (++stable_count == HUB_DEBOUNCE_STABLE) - break; - } + if (!(portchange & USB_PORT_STAT_C_CONNECTION) && + (portstatus & USB_PORT_STAT_CONNECTION) == connection) { + stable_time += HUB_DEBOUNCE_STEP; + if (stable_time >= HUB_DEBOUNCE_STABLE) + break; } else { - stable_count = 0; + stable_time = 0; + connection = portstatus & USB_PORT_STAT_CONNECTION; } - connection = portstatus & USB_PORT_STAT_CONNECTION; - if ((portchange & USB_PORT_STAT_C_CONNECTION)) { - clear_port_feature(hdev, port+1, USB_PORT_FEAT_C_CONNECTION); + if (portchange & USB_PORT_STAT_C_CONNECTION) { + clear_port_feature(hdev, port+1, + USB_PORT_FEAT_C_CONNECTION); } + + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + break; + msleep(HUB_DEBOUNCE_STEP); } dev_dbg (hubdev (hdev), - "debounce: port %d: delay %dms stable %d status 0x%x\n", - port + 1, delay_time, stable_count, portstatus); + "debounce: port %d: total %dms stable %dms status 0x%x\n", + port + 1, total_time, stable_time, portstatus); - return (portstatus & USB_PORT_STAT_CONNECTION) ? 0 : -ENOTCONN; + if (stable_time < HUB_DEBOUNCE_STABLE) + return -ETIMEDOUT; + return portstatus; } static int hub_set_address(struct usb_device *udev) @@ -1037,11 +1325,11 @@ if (udev->state != USB_STATE_DEFAULT && udev->state != USB_STATE_ADDRESS) return -EINVAL; - retval = usb_control_msg(udev, usb_snddefctrl(udev), + retval = usb_control_msg(udev, (PIPE_CONTROL << 30) /* Address 0 */, USB_REQ_SET_ADDRESS, 0, udev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); if (retval == 0) - udev->state = USB_STATE_ADDRESS; + usb_set_device_state(udev, USB_STATE_ADDRESS); return retval; } @@ -1109,33 +1397,9 @@ udev->epmaxpacketin [0] = i; udev->epmaxpacketout[0] = i; - /* set the address */ - if (udev->devnum <= 0) { - usb_choose_address(udev); - if (udev->devnum <= 0) - goto fail; - - /* Set up TT records, if needed */ - if (hdev->tt) { - udev->tt = hdev->tt; - udev->ttport = hdev->ttport; - } else if (udev->speed != USB_SPEED_HIGH - && hdev->speed == USB_SPEED_HIGH) { - struct usb_hub *hub; - - hub = usb_get_intfdata (hdev->actconfig - ->interface[0]); - udev->tt = &hub->tt; - udev->ttport = port + 1; - } - - /* force the right log message (below) at low speed */ - oldspeed = USB_SPEED_UNKNOWN; - } - dev_info (&udev->dev, "%s %s speed USB device using address %d\n", - (oldspeed == USB_SPEED_UNKNOWN) ? "new" : "reset", + (udev->config) ? "reset" : "new", ({ char *speed; switch (udev->speed) { case USB_SPEED_LOW: speed = "low"; break; case USB_SPEED_FULL: speed = "full"; break; @@ -1143,6 +1407,19 @@ default: speed = "?"; break; }; speed;}), udev->devnum); + + /* Set up TT records, if needed */ + if (hdev->tt) { + udev->tt = hdev->tt; + udev->ttport = hdev->ttport; + } else if (udev->speed != USB_SPEED_HIGH + && hdev->speed == USB_SPEED_HIGH) { + struct usb_hub *hub; + + hub = usb_get_intfdata(hdev->actconfig->interface[0]); + udev->tt = &hub->tt; + udev->ttport = port + 1; + } /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? * Because device hardware and firmware is sometimes buggy in @@ -1164,12 +1441,7 @@ dev_err(&udev->dev, "device not accepting address %d, error %d\n", udev->devnum, retval); - fail: - hub_port_disable(hdev, port); - usb_release_address(udev); - usb_put_dev(udev); - up(&usb_address0_sem); - return retval; + goto fail; } /* cope with hardware quirkiness: @@ -1192,7 +1464,8 @@ if (udev->speed == USB_SPEED_FULL && (udev->epmaxpacketin [0] != udev->descriptor.bMaxPacketSize0)) { - usb_disable_endpoint(udev, 0); + usb_disable_endpoint(udev, 0 + USB_DIR_IN); + usb_disable_endpoint(udev, 0 + USB_DIR_OUT); usb_endpoint_running(udev, 0, 1); usb_endpoint_running(udev, 0, 0); udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0; @@ -1208,11 +1481,11 @@ goto fail; } - /* now dev is visible to other tasks */ - hdev->children[port] = udev; + retval = 0; +fail: up(&usb_address0_sem); - return 0; + return retval; } static void @@ -1271,7 +1544,14 @@ } return remaining; } - + +/* Handle physical or logical connection change events. + * This routine is called when: + * a port connection-change occurs; + * a port enable-change occurs (often caused by EMI); + * usb_reset_device() encounters changed descriptors (as from + * a firmware download) + */ static void hub_port_connect_change(struct usb_hub *hub, int port, u16 portstatus, u16 portchange) { @@ -1282,9 +1562,6 @@ dev_dbg (hub_dev, "port %d, status %04x, change %04x, %s\n", port + 1, portstatus, portchange, portspeed (portstatus)); - - /* Clear the connection change status */ - clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_CONNECTION); if (hub->has_indicators) { set_port_led(hdev, port + 1, HUB_LED_AUTO); @@ -1295,6 +1572,17 @@ if (hdev->children[port]) usb_disconnect(&hdev->children[port]); + if (portchange & USB_PORT_STAT_C_CONNECTION) { + status = hub_port_debounce(hdev, port); + if (status < 0) { + dev_err (hub_dev, + "connect-debounce failed, port %d disabled\n", + port+1); + goto done; + } + portstatus = status; + } + /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { @@ -1308,13 +1596,6 @@ goto done; return; } - - if (hub_port_debounce(hdev, port)) { - dev_err (hub_dev, - "connect-debounce failed, port %d disabled\n", - port+1); - goto done; - } for (i = 0; i < SET_CONFIG_TRIES; i++) { struct usb_device *udev; @@ -1328,21 +1609,26 @@ "couldn't allocate port %d usb_device\n", port+1); goto done; } - udev->state = USB_STATE_POWERED; - + + usb_set_device_state(udev, USB_STATE_POWERED); + /* hub can tell if it's lowspeed already: D- pullup (not D+) */ if (portstatus & USB_PORT_STAT_LOW_SPEED) udev->speed = USB_SPEED_LOW; else udev->speed = USB_SPEED_UNKNOWN; + + /* set the address */ + choose_address(udev); + if (udev->devnum <= 0) { + status = -ENOTCONN; /* Don't retry */ + goto loop; + } - /* reset, set address, get descriptor, add to hub's children */ - down (&udev->serialize); + /* reset and get descriptor */ status = hub_port_init(hdev, udev, port); - if (status == -ENOTCONN) - break; if (status < 0) - continue; + goto loop; /* consecutive bus-powered hubs aren't reliable; they can * violate the voltage drop budget. if the new child has @@ -1358,7 +1644,7 @@ &devstat); if (status < 0) { dev_dbg(&udev->dev, "get status %d ?\n", status); - continue; + goto loop; } cpu_to_le16s(&devstat); if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { @@ -1370,10 +1656,8 @@ INDICATOR_AMBER_BLINK; schedule_work (&hub->leds); } - hdev->children[port] = NULL; - usb_put_dev(udev); - hub_port_disable(hdev, port); - return; + status = -ENOTCONN; /* Don't retry */ + goto loop; } } @@ -1383,13 +1667,37 @@ && highspeed_hubs != 0) check_highspeed (hub, udev, port); + /* Store the parent's children[] pointer. At this point + * udev becomes globally accessible, although presumably + * no one will look at it until hdev is unlocked. + */ + down (&udev->serialize); + status = 0; + + /* We mustn't add new devices if the parent hub has + * been disconnected; we would race with the + * recursively_mark_NOTATTACHED() routine. + */ + spin_lock_irq(&device_state_lock); + if (hdev->state == USB_STATE_NOTATTACHED) + status = -ENOTCONN; + else + hdev->children[port] = udev; + spin_unlock_irq(&device_state_lock); + /* Run it through the hoops (find a driver, etc) */ - status = usb_new_device(udev); - if (status != 0) { - hdev->children[port] = NULL; - continue; + if (!status) { + status = usb_new_device(udev); + if (status) { + spin_lock_irq(&device_state_lock); + hdev->children[port] = NULL; + spin_unlock_irq(&device_state_lock); + } } + up (&udev->serialize); + if (status) + goto loop; status = hub_power_remaining(hub, hdev); if (status) @@ -1398,6 +1706,15 @@ 2 * status); return; + +loop: + hub_port_disable(hdev, port); + usb_disable_endpoint(udev, 0 + USB_DIR_IN); + usb_disable_endpoint(udev, 0 + USB_DIR_OUT); + release_address(udev); + usb_put_dev(udev); + if (status == -ENOTCONN) + break; } done: @@ -1406,7 +1723,6 @@ static void hub_events(void) { - unsigned long flags; struct list_head *tmp; struct usb_device *hdev; struct usb_hub *hub; @@ -1416,6 +1732,7 @@ u16 portstatus; u16 portchange; int i, ret; + int connect_change; /* * We restart the list every time to avoid a deadlock with @@ -1424,24 +1741,32 @@ * Not the most efficient, but avoids deadlocks. */ while (1) { - spin_lock_irqsave(&hub_event_lock, flags); - if (list_empty(&hub_event_list)) + /* Grab the first entry at the beginning of the list */ + spin_lock_irq(&hub_event_lock); + if (list_empty(&hub_event_list)) { + spin_unlock_irq(&hub_event_lock); break; + } - /* Grab the next entry from the beginning of the list */ tmp = hub_event_list.next; + list_del_init(tmp); hub = list_entry(tmp, struct usb_hub, event_list); hdev = interface_to_usbdev(hub->intf); hub_dev = &hub->intf->dev; - list_del_init(tmp); - - if (unlikely(down_trylock(&hub->khubd_sem))) - BUG(); /* never blocks, we were on list */ + usb_get_dev(hdev); + spin_unlock_irq(&hub_event_lock); - spin_unlock_irqrestore(&hub_event_lock, flags); + /* Lock the device, then check to see if we were + * disconnected while waiting for the lock to succeed. */ + down(&hdev->serialize); + if (hdev->state != USB_STATE_CONFIGURED || + !hdev->actconfig || + hub != usb_get_intfdata( + hdev->actconfig->interface[0])) + goto loop; if (hub->error) { dev_dbg (hub_dev, "resetting for error %d\n", @@ -1450,27 +1775,35 @@ if (hub_reset(hub)) { dev_dbg (hub_dev, "can't reset; disconnecting\n"); - up(&hub->khubd_sem); hub_start_disconnect(hdev); - continue; + goto loop; } hub->nerrors = 0; hub->error = 0; } + /* deal with port status changes */ for (i = 0; i < hub->descriptor->bNbrPorts; i++) { + if (!test_and_clear_bit(i+1, hub->event_bits)) + continue; ret = hub_port_status(hdev, i, &portstatus, &portchange); - if (ret < 0) { + if (ret < 0) continue; - } + connect_change = 0; if (portchange & USB_PORT_STAT_C_CONNECTION) { - hub_port_connect_change(hub, i, portstatus, portchange); - } else if (portchange & USB_PORT_STAT_C_ENABLE) { - dev_dbg (hub_dev, - "port %d enable change, status %08x\n", - i + 1, portstatus); + clear_port_feature(hdev, + i + 1, USB_PORT_FEAT_C_CONNECTION); + connect_change = 1; + } + + if (portchange & USB_PORT_STAT_C_ENABLE) { + if (!connect_change) + dev_dbg (hub_dev, + "port %d enable change, " + "status %08x\n", + i + 1, portstatus); clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_ENABLE); @@ -1481,15 +1814,14 @@ * Works at least with mouse driver. */ if (!(portstatus & USB_PORT_STAT_ENABLE) - && (portstatus & USB_PORT_STAT_CONNECTION) - && (hdev->children[i])) { + && !connect_change + && hdev->children[i]) { dev_err (hub_dev, "port %i " "disabled by hub (EMI?), " "re-enabling...", i + 1); - hub_port_connect_change(hub, - i, portstatus, portchange); + connect_change = 1; } } @@ -1517,10 +1849,16 @@ clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_RESET); } + + if (connect_change) + hub_port_connect_change(hub, i, + portstatus, portchange); } /* end for i */ /* deal with hub status changes */ - if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) + if (test_and_clear_bit(0, hub->event_bits) == 0) + ; /* do nothing */ + else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) dev_err (hub_dev, "get_hub_status failed\n"); else { if (hubchange & HUB_CHANGE_LOCAL_POWER) { @@ -1534,10 +1872,12 @@ hub_power_on(hub); } } - up(&hub->khubd_sem); - } /* end while (1) */ - spin_unlock_irqrestore(&hub_event_lock, flags); +loop: + up(&hdev->serialize); + usb_put_dev(hdev); + + } /* end while (1) */ } static int hub_thread(void *__unused) @@ -1581,9 +1921,6 @@ .id_table = hub_id_table, }; -/* - * This should be a separate module. - */ int usb_hub_init(void) { pid_t pid; @@ -1726,7 +2063,7 @@ udev->actconfig->desc.bConfigurationValue, ret); goto re_enumerate; } - udev->state = USB_STATE_CONFIGURED; + usb_set_device_state(udev, USB_STATE_CONFIGURED); for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = udev->actconfig->interface[i]; @@ -1752,7 +2089,7 @@ re_enumerate: /* FIXME make some task re-enumerate; don't just mark unusable */ - udev->state = USB_STATE_NOTATTACHED; + hub_port_disable(parent, port); return -ENODEV; } EXPORT_SYMBOL(__usb_reset_device); diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h --- a/drivers/usb/core/hub.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/core/hub.h 2004-06-20 13:00:23 -07:00 @@ -202,11 +202,13 @@ int error; /* last reported error */ int nerrors; /* track consecutive errors */ - struct list_head hub_list; /* all hubs */ struct list_head event_list; /* hubs w/data or errs ready */ + unsigned long event_bits[1]; /* status change bitmask */ +#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ +#error event_bits[] is too short! +#endif struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct semaphore khubd_sem; struct usb_tt tt; /* Transaction Translator */ u8 power_budget; /* in 2mA units; or zero */ @@ -215,5 +217,16 @@ enum hub_led_mode indicator[USB_MAXCHILDREN]; struct work_struct leds; }; + +/* use this for low-powered root hubs */ +static inline void +hub_set_power_budget (struct usb_device *hubdev, unsigned mA) +{ + struct usb_hub *hub; + + hub = (struct usb_hub *) + usb_get_intfdata (hubdev->actconfig->interface[0]); + hub->power_budget = min(mA,(unsigned)500)/2; +} #endif /* __LINUX_HUB_H */ diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/core/message.c 2004-06-20 13:00:23 -07:00 @@ -566,22 +566,19 @@ */ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) { - int i = 5; + int i; int result; memset(buf,0,size); // Make sure we parse really received data - while (i--) { + for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ - if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (type << 8) + index, 0, buf, size, - HZ * USB_CTRL_GET_TIMEOUT)) > 0 - || result != -EPIPE) + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (type << 8) + index, 0, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); + if (!(result == 0 || result == -EPIPE)) break; - - dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result); - result = -ENOMSG; } return result; } @@ -830,6 +827,7 @@ interface = dev->actconfig->interface[i]; dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); + usb_remove_sysfs_intf_files(interface); device_del (&interface->dev); } @@ -842,7 +840,7 @@ } dev->actconfig = 0; if (dev->state == USB_STATE_CONFIGURED) - dev->state = USB_STATE_ADDRESS; + usb_set_device_state(dev, USB_STATE_ADDRESS); } } @@ -1047,7 +1045,7 @@ config->desc.bConfigurationValue, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); if (retval < 0) { - dev->state = USB_STATE_ADDRESS; + usb_set_device_state(dev, USB_STATE_ADDRESS); return retval; } @@ -1185,9 +1183,9 @@ dev->actconfig = cp; if (!cp) - dev->state = USB_STATE_ADDRESS; + usb_set_device_state(dev, USB_STATE_ADDRESS); else { - dev->state = USB_STATE_CONFIGURED; + usb_set_device_state(dev, USB_STATE_CONFIGURED); /* Initialize the new interface structures and the * hc/hcd/usbcore interface/endpoint state. @@ -1322,7 +1320,7 @@ */ err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); - if (err == -EPIPE) { + if (err == -EPIPE || err == 0) { dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2); err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); } @@ -1331,7 +1329,7 @@ len=tbuf[0]; err = usb_get_string(dev, dev->string_langid, index, tbuf, len); - if (err == -EPIPE) { + if (err == -EPIPE || err == 0) { dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len); err = usb_get_string(dev, dev->string_langid, index, tbuf, len); } diff -Nru a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c --- a/drivers/usb/core/sysfs.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/core/sysfs.c 2004-06-20 13:00:23 -07:00 @@ -2,8 +2,8 @@ * drivers/usb/core/sysfs.c * * (C) Copyright 2002 David Brownell - * (C) Copyright 2002 Greg Kroah-Hartman - * (C) Copyright 2002 IBM Corp. + * (C) Copyright 2002,2004 Greg Kroah-Hartman + * (C) Copyright 2002,2004 IBM Corp. * * All of the sysfs file attributes for usb devices and interfaces. * @@ -162,29 +162,35 @@ usb_descriptor_attr (bDeviceProtocol, "%02x\n") usb_descriptor_attr (bNumConfigurations, "%d\n") +static struct attribute *dev_attrs[] = { + /* current configuration's attributes */ + &dev_attr_bNumInterfaces.attr, + &dev_attr_bConfigurationValue.attr, + &dev_attr_bmAttributes.attr, + &dev_attr_bMaxPower.attr, + /* device attributes */ + &dev_attr_idVendor.attr, + &dev_attr_idProduct.attr, + &dev_attr_bcdDevice.attr, + &dev_attr_bDeviceClass.attr, + &dev_attr_bDeviceSubClass.attr, + &dev_attr_bDeviceProtocol.attr, + &dev_attr_bNumConfigurations.attr, + &dev_attr_speed.attr, + &dev_attr_devnum.attr, + &dev_attr_version.attr, + &dev_attr_maxchild.attr, + NULL, +}; +static struct attribute_group dev_attr_grp = { + .attrs = dev_attrs, +}; void usb_create_sysfs_dev_files (struct usb_device *udev) { struct device *dev = &udev->dev; - /* current configuration's attributes */ - device_create_file (dev, &dev_attr_bNumInterfaces); - device_create_file (dev, &dev_attr_bConfigurationValue); - device_create_file (dev, &dev_attr_bmAttributes); - device_create_file (dev, &dev_attr_bMaxPower); - - /* device attributes */ - device_create_file (dev, &dev_attr_idVendor); - device_create_file (dev, &dev_attr_idProduct); - device_create_file (dev, &dev_attr_bcdDevice); - device_create_file (dev, &dev_attr_bDeviceClass); - device_create_file (dev, &dev_attr_bDeviceSubClass); - device_create_file (dev, &dev_attr_bDeviceProtocol); - device_create_file (dev, &dev_attr_bNumConfigurations); - - /* speed varies depending on how you connect the device */ - device_create_file (dev, &dev_attr_speed); - // FIXME iff there are other speed configs, show how many + sysfs_create_group(&dev->kobj, &dev_attr_grp); if (udev->descriptor.iManufacturer) device_create_file (dev, &dev_attr_manufacturer); @@ -192,10 +198,20 @@ device_create_file (dev, &dev_attr_product); if (udev->descriptor.iSerialNumber) device_create_file (dev, &dev_attr_serial); +} + +void usb_remove_sysfs_dev_files (struct usb_device *udev) +{ + struct device *dev = &udev->dev; - device_create_file (dev, &dev_attr_devnum); - device_create_file (dev, &dev_attr_version); - device_create_file (dev, &dev_attr_maxchild); + sysfs_remove_group(&dev->kobj, &dev_attr_grp); + + if (udev->descriptor.iManufacturer) + device_remove_file(dev, &dev_attr_manufacturer); + if (udev->descriptor.iProduct) + device_remove_file(dev, &dev_attr_product); + if (udev->descriptor.iSerialNumber) + device_remove_file(dev, &dev_attr_serial); } /* Interface fields */ @@ -217,13 +233,26 @@ usb_intf_attr (bInterfaceProtocol, "%02x\n") usb_intf_attr (iInterface, "%02x\n") +static struct attribute *intf_attrs[] = { + &dev_attr_bInterfaceNumber.attr, + &dev_attr_bAlternateSetting.attr, + &dev_attr_bNumEndpoints.attr, + &dev_attr_bInterfaceClass.attr, + &dev_attr_bInterfaceSubClass.attr, + &dev_attr_bInterfaceProtocol.attr, + &dev_attr_iInterface.attr, + NULL, +}; +static struct attribute_group intf_attr_grp = { + .attrs = intf_attrs, +}; + void usb_create_sysfs_intf_files (struct usb_interface *intf) { - device_create_file (&intf->dev, &dev_attr_bInterfaceNumber); - device_create_file (&intf->dev, &dev_attr_bAlternateSetting); - device_create_file (&intf->dev, &dev_attr_bNumEndpoints); - device_create_file (&intf->dev, &dev_attr_bInterfaceClass); - device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass); - device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol); - device_create_file (&intf->dev, &dev_attr_iInterface); + sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); +} + +void usb_remove_sysfs_intf_files (struct usb_interface *intf) +{ + sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); } diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/core/usb.c 2004-06-20 13:00:24 -07:00 @@ -883,6 +883,8 @@ buslist != &usb_bus_list; buslist = buslist->next) { bus = container_of(buslist, struct usb_bus, bus_list); + if (!bus->root_hub) + continue; dev = match_device(bus->root_hub, vendor_id, product_id); if (dev) goto exit; @@ -942,235 +944,6 @@ size -= header->bLength; } return -1; -} - -/** - * usb_disconnect - disconnect a device (usbcore-internal) - * @pdev: pointer to device being disconnected - * Context: !in_interrupt () - * - * Something got disconnected. Get rid of it, and all of its children. - * - * Only hub drivers (including virtual root hub drivers for host - * controllers) should ever call this. - * - * This call is synchronous, and may not be used in an interrupt context. - */ -void usb_disconnect(struct usb_device **pdev) -{ - struct usb_device *dev = *pdev; - struct usb_bus *bus; - struct usb_operations *ops; - int i; - - might_sleep (); - - if (!dev) { - pr_debug ("%s nodev\n", __FUNCTION__); - return; - } - bus = dev->bus; - if (!bus) { - pr_debug ("%s nobus\n", __FUNCTION__); - return; - } - ops = bus->op; - - *pdev = NULL; - - /* mark the device as inactive, so any further urb submissions for - * this device will fail. - */ - dev->state = USB_STATE_NOTATTACHED; - down(&dev->serialize); - - dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum); - - /* Free up all the children before we remove this device */ - for (i = 0; i < USB_MAXCHILDREN; i++) { - struct usb_device **child = dev->children + i; - if (*child) - usb_disconnect(child); - } - - /* deallocate hcd/hardware state ... nuking all pending urbs and - * cleaning up all state associated with the current configuration - */ - usb_disable_device(dev, 0); - - /* Free the device number and remove the /proc/bus/usb entry */ - dev_dbg (&dev->dev, "unregistering device\n"); - usb_release_address(dev); - usbfs_remove_device(dev); - up(&dev->serialize); - device_unregister(&dev->dev); -} - -/** - * usb_choose_address - pick device address (usbcore-internal) - * @dev: newly detected device (in DEFAULT state) - * - * Picks a device address. It's up to the hub (or root hub) driver - * to handle and manage enumeration, starting from the DEFAULT state. - * Only hub drivers (but not virtual root hub drivers for host - * controllers) should ever call this. - */ -void usb_choose_address(struct usb_device *dev) -{ - int devnum; - // FIXME needs locking for SMP!! - /* why? this is called only from the hub thread, - * which hopefully doesn't run on multiple CPU's simultaneously 8-) - */ - - /* Try to allocate the next devnum beginning at bus->devnum_next. */ - devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next); - if (devnum >= 128) - devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); - - dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); - - if (devnum < 128) { - set_bit(devnum, dev->bus->devmap.devicemap); - dev->devnum = devnum; - } -} - -/** - * usb_release_address - deallocate device address (usbcore-internal) - * @dev: newly removed device - * - * Removes and deallocates the address assigned to a device. - * Only hub drivers (but not virtual root hub drivers for host - * controllers) should ever call this. - */ -void usb_release_address(struct usb_device *dev) -{ - if (dev->devnum > 0) { - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - dev->devnum = -1; - } -} - - -static inline void usb_show_string(struct usb_device *dev, char *id, int index) -{ - char *buf; - - if (!index) - return; - if (!(buf = kmalloc(256, GFP_KERNEL))) - return; - if (usb_string(dev, index, buf, 256) > 0) - dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf); - kfree(buf); -} - -static int usb_choose_configuration(struct usb_device *dev) -{ - int c, i; - - c = dev->config[0].desc.bConfigurationValue; - if (dev->descriptor.bNumConfigurations != 1) { - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { - struct usb_interface_descriptor *desc; - - /* heuristic: Linux is more likely to have class - * drivers, so avoid vendor-specific interfaces. - */ - desc = &dev->config[i].intf_cache[0] - ->altsetting->desc; - if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) - continue; - /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */ - if (desc->bInterfaceClass == USB_CLASS_COMM - && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff) - continue; - c = dev->config[i].desc.bConfigurationValue; - break; - } - dev_info(&dev->dev, - "configuration #%d chosen from %d choices\n", - c, dev->descriptor.bNumConfigurations); - } - return c; -} - -/* - * usb_new_device - perform initial device setup (usbcore-internal) - * @dev: newly addressed device (in ADDRESS state) - * - * This is called with devices which have been enumerated, but not yet - * configured. The device descriptor is available, but not descriptors - * for any device configuration. The caller owns dev->serialize, and - * the device is not visible through sysfs or other filesystem code. - * - * Returns 0 for success (device is configured and listed, with its - * interfaces, in sysfs); else a negative errno value. On error, one - * reference count to the device has been dropped. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Only the hub driver should ever call this; root hub registration - * uses it only indirectly. - */ -int usb_new_device(struct usb_device *dev) -{ - int err; - int c; - - err = usb_get_configuration(dev); - if (err < 0) { - dev_err(&dev->dev, "can't read configurations, error %d\n", - err); - goto fail; - } - - /* Tell the world! */ - dev_dbg(&dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", - dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); - -#ifdef DEBUG - if (dev->descriptor.iProduct) - usb_show_string(dev, "Product", dev->descriptor.iProduct); - if (dev->descriptor.iManufacturer) - usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer); - if (dev->descriptor.iSerialNumber) - usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); -#endif - - /* put device-specific files into sysfs */ - err = device_add (&dev->dev); - if (err) { - dev_err(&dev->dev, "can't device_add, error %d\n", err); - goto fail; - } - usb_create_sysfs_dev_files (dev); - - /* choose and set the configuration. that registers the interfaces - * with the driver core, and lets usb device drivers bind to them. - * NOTE: should interact with hub power budgeting. - */ - c = usb_choose_configuration(dev); - err = usb_set_configuration(dev, c); - if (err) { - dev_err(&dev->dev, "can't set config #%d, error %d\n", c, err); - device_del(&dev->dev); - goto fail; - } - - /* USB device state == configured ... usable */ - - /* add a /proc/bus/usb entry */ - usbfs_add_device(dev); - - return 0; -fail: - dev->state = USB_STATE_NOTATTACHED; - usb_release_address(dev); - usb_put_dev(dev); - return err; } /** diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h --- a/drivers/usb/core/usb.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/core/usb.h 2004-06-20 13:00:23 -07:00 @@ -1,7 +1,9 @@ /* Functions local to drivers/usb/core/ */ extern void usb_create_sysfs_dev_files (struct usb_device *dev); +extern void usb_remove_sysfs_dev_files (struct usb_device *dev); extern void usb_create_sysfs_intf_files (struct usb_interface *intf); +extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); extern int usb_probe_interface (struct device *dev); extern int usb_unbind_interface (struct device *dev); @@ -18,6 +20,9 @@ extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); extern int usb_set_configuration(struct usb_device *dev, int configuration); + +extern void usb_set_device_state(struct usb_device *udev, + enum usb_device_state new_state); /* for labeling diagnostics */ extern const char *usbcore_name; diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c --- a/drivers/usb/gadget/dummy_hcd.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/gadget/dummy_hcd.c 2004-06-20 13:00:23 -07:00 @@ -825,8 +825,7 @@ dum = container_of (hcd, struct dummy, hcd); spin_lock_irqsave (&dum->lock, flags); - if (!dum->hdev) - dum->hdev = urb->dev->hcpriv; + dum->hdev = urb->dev->hcpriv; urb->hcpriv = dum; if (usb_pipetype (urb->pipe) == PIPE_CONTROL) urb->error_count = 1; /* mark as a new urb */ @@ -994,10 +993,17 @@ return limit; } +#define is_active(dum) ((dum->port_status & \ + (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \ + USB_PORT_STAT_SUSPEND)) \ + == (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) + static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address) { int i; + if (!is_active (dum)) + return NULL; if ((address & ~USB_DIR_IN) == 0) return &dum->ep [0]; for (i = 1; i < DUMMY_ENDPOINTS; i++) { @@ -1011,6 +1017,8 @@ return NULL; } +#undef is_active + #define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE) #define Dev_InRequest (Dev_Request | USB_DIR_IN) #define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE) @@ -1152,11 +1160,6 @@ case USB_REQ_SET_ADDRESS: if (setup.bRequestType != Dev_Request) break; - if (dum->address != 0) { - maybe_set_status (urb, -ETIMEDOUT); - urb->actual_length = 0; - goto return_urb; - } dum->address = setup.wValue; maybe_set_status (urb, 0); dev_dbg (hardware, "set_address = %d\n", @@ -1404,9 +1407,8 @@ break; case USB_PORT_FEAT_POWER: dum->port_status = 0; - dum->address = 0; - dum->hdev = 0; dum->resuming = 0; + stop_activity(dum, dum->driver); break; default: dum->port_status &= ~(1 << wValue); @@ -1657,7 +1659,7 @@ INIT_LIST_HEAD (&hcd->dev_list); usb_register_bus (bus); - bus->root_hub = root = usb_alloc_dev (0, bus, 0); + root = usb_alloc_dev (0, bus, 0); if (!root) { retval = -ENOMEM; clean1: @@ -1671,13 +1673,15 @@ root->speed = USB_SPEED_HIGH; /* ...then configured, so khubd sees us. */ - if ((retval = hcd_register_root (&dum->hcd)) != 0) { - bus->root_hub = 0; + if ((retval = hcd_register_root (root, &dum->hcd)) != 0) { usb_put_dev (root); clean2: dum->hcd.state = USB_STATE_QUIESCING; goto clean1; } + + /* only show a low-power port: just 8mA */ + hub_set_power_budget (root, 8); dum->started = 1; diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- a/drivers/usb/gadget/ether.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/gadget/ether.c 2004-06-20 13:00:26 -07:00 @@ -118,6 +118,7 @@ unsigned zlp:1; unsigned cdc:1; unsigned rndis:1; + unsigned suspended:1; u16 cdc_filter; unsigned long todo; #define WORK_RX_MEMORY 0 @@ -1345,24 +1346,23 @@ static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req) { - struct eth_dev *dev = ep->driver_data; - if (req->status || req->actual != req->length) DEBUG (dev, "rndis response complete --> %d, %d/%d\n", req->status, req->actual, req->length); /* done sending after CDC_GET_ENCAPSULATED_RESPONSE */ - rndis_free_response (dev->rndis_config, req->buf); } static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req) { struct eth_dev *dev = ep->driver_data; + int status; /* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */ spin_lock(&dev->lock); - if (rndis_msg_parser (dev->rndis_config, (u8 *) req->buf)) - ERROR(dev, "%s: rndis parse error\n", __FUNCTION__ ); + status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf); + if (status < 0) + ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status); spin_unlock(&dev->lock); } @@ -1580,6 +1580,7 @@ if (buf) { memcpy (req->buf, buf, value); req->complete = rndis_response_complete; + rndis_free_response(dev->rndis_config, buf); } /* else stalls ... spec says to avoid that */ } @@ -2064,6 +2065,16 @@ } } +static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) +{ + if (req->status || req->actual != req->length) + DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n", + req->status, req->actual, req->length); + + usb_ep_free_buffer(ep, req->buf, req->dma, 8); + usb_ep_free_request(ep, req); +} + static int rndis_control_ack (struct net_device *net) { struct eth_dev *dev = (struct eth_dev *) net->priv; @@ -2095,7 +2106,7 @@ * CDC_NOTIFY_RESPONSE_AVAILABLE should work too */ resp->length = 8; - resp->complete = rndis_response_complete; + resp->complete = rndis_control_ack_complete; *((u32 *) resp->buf) = __constant_cpu_to_le32 (1); *((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); @@ -2103,7 +2114,7 @@ length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); if (length < 0) { resp->status = 0; - rndis_response_complete (dev->status_ep, resp); + rndis_control_ack_complete (dev->status_ep, resp); } return 0; @@ -2302,17 +2313,6 @@ UTS_SYSNAME " " UTS_RELEASE "/%s", gadget->name); - /* CDC subset ... recognized by Linux since 2.4.10, but Windows - * drivers aren't widely available. - */ - if (!cdc) { - device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; - device_desc.idVendor = - __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); - device_desc.idProduct = - __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM); - } - /* If there's an RNDIS configuration, that's what Windows wants to * be using ... so use these product IDs here and in the "linux.inf" * needed to install MSFT drivers. Current Linux kernels will use @@ -2326,6 +2326,16 @@ __constant_cpu_to_le16(RNDIS_PRODUCT_NUM); snprintf (product_desc, sizeof product_desc, "RNDIS/%s", driver_desc); + + /* CDC subset ... recognized by Linux since 2.4.10, but Windows + * drivers aren't widely available. + */ + } else if (!cdc) { + device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; + device_desc.idVendor = + __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); + device_desc.idProduct = + __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM); } /* support optional vendor/distro customization */ @@ -2554,6 +2564,26 @@ /*-------------------------------------------------------------------------*/ +static void +eth_suspend (struct usb_gadget *gadget) +{ + struct eth_dev *dev = get_gadget_data (gadget); + + DEBUG (dev, "suspend\n"); + dev->suspended = 1; +} + +static void +eth_resume (struct usb_gadget *gadget) +{ + struct eth_dev *dev = get_gadget_data (gadget); + + DEBUG (dev, "resume\n"); + dev->suspended = 0; +} + +/*-------------------------------------------------------------------------*/ + static struct usb_gadget_driver eth_driver = { #ifdef CONFIG_USB_GADGET_DUALSPEED .speed = USB_SPEED_HIGH, @@ -2566,6 +2596,9 @@ .setup = eth_setup, .disconnect = eth_disconnect, + + .suspend = eth_suspend, + .resume = eth_resume, .driver = { .name = (char *) shortname, diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c --- a/drivers/usb/gadget/file_storage.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/gadget/file_storage.c 2004-06-20 13:00:26 -07:00 @@ -2501,7 +2501,7 @@ /* Store and send the Bulk-only CSW */ csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); csw->Tag = fsg->tag; - csw->Residue = fsg->residue; + csw->Residue = cpu_to_le32(fsg->residue); csw->Status = status; bh->inreq->length = USB_BULK_CS_WRAP_LEN; @@ -2947,7 +2947,7 @@ fsg->data_dir = DATA_DIR_TO_HOST; else fsg->data_dir = DATA_DIR_FROM_HOST; - fsg->data_size = cbw->DataTransferLength; + fsg->data_size = le32_to_cpu(cbw->DataTransferLength); if (fsg->data_size == 0) fsg->data_dir = DATA_DIR_NONE; fsg->lun = cbw->Lun; @@ -3834,6 +3834,7 @@ } /* Find all the endpoints we will use */ + usb_ep_autoconfig_reset(gadget); ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc); if (!ep) goto autoconf_fail; diff -Nru a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h --- a/drivers/usb/gadget/ndis.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/gadget/ndis.h 2004-06-20 13:00:25 -07:00 @@ -26,10 +26,40 @@ #define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A #define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + /* NDIS_PNP_CAPABILITIES.Flags constants */ #define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 #define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +struct NDIS_PNP_CAPABILITIES { + u32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + u32 Priority; + u32 Reserved; + u32 MaskSize; + u32 PatternOffset; + u32 PatternSize; + u32 PatternFlags; +}; + /* Required Object IDs (OIDs) */ #define OID_GEN_SUPPORTED_LIST 0x00010101 diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/gadget/net2280.c 2004-06-20 13:00:23 -07:00 @@ -1902,6 +1902,8 @@ , &dev->usb->stdrsp); writel ( (1 << USB_ROOT_PORT_WAKEUP_ENABLE) | (1 << SELF_POWERED_USB_DEVICE) + /* erratum 0102 workaround */ + | ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY | (1 << REMOTE_WAKEUP_SUPPORT) | (1 << USB_DETECT_ENABLE) | (1 << SELF_POWERED_STATUS) @@ -1917,6 +1919,7 @@ | (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE) | (1 << VBUS_INTERRUPT_ENABLE) | (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE) + | (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE) , &dev->regs->pciirqenb1); /* don't leave any writes posted */ @@ -2513,19 +2516,24 @@ return; } - /* NOTE: we don't actually suspend the hardware; that starts to - * interact with PCI power management, and needs something like a - * controller->suspend() call to clear SUSPEND_REQUEST_INTERRUPT. - * we shouldn't see resume interrupts. - * for rev 0100, this also avoids erratum 0102. + /* NOTE: chip stays in PCI D0 state for now, but it could + * enter D1 to save more power */ tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT); if (stat & tmp) { - if (dev->driver->suspend) - dev->driver->suspend (&dev->gadget); + writel (tmp, &dev->regs->irqstat1); + if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) { + if (dev->driver->suspend) + dev->driver->suspend (&dev->gadget); + /* we use SUSPEND_IMMEDIATELY */ + stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT); + } else { + if (dev->driver->resume) + dev->driver->resume (&dev->gadget); + /* at high speed, note erratum 0133 */ + } stat &= ~tmp; } - stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT); /* clear any other status/irqs */ if (stat) @@ -2533,6 +2541,7 @@ /* some status we can just ignore */ stat &= ~((1 << CONTROL_STATUS_INTERRUPT) + | (1 << SUSPEND_REQUEST_INTERRUPT) | (1 << RESUME_INTERRUPT) | (1 << SOF_INTERRUPT)); if (!stat) diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c --- a/drivers/usb/gadget/pxa2xx_udc.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/gadget/pxa2xx_udc.c 2004-06-20 13:00:25 -07:00 @@ -1406,7 +1406,7 @@ #ifdef CONFIG_ARCH_PXA /* Disable clock for USB device */ - CKEN &= ~CKEN11_USB; + pxa_set_cken(CKEN11_USB, 0); #endif ep0_idle (dev); @@ -1452,7 +1452,7 @@ #ifdef CONFIG_ARCH_PXA /* Enable clock for USB device */ - CKEN |= CKEN11_USB; + pxa_set_cken(CKEN11_USB, 1); #endif /* try to clear these bits before we enable the udc */ diff -Nru a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c --- a/drivers/usb/gadget/rndis.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/gadget/rndis.c 2004-06-20 13:00:23 -07:00 @@ -18,6 +18,9 @@ * * 03/25/2004 Kai-Uwe Bloem * Fixed rndis_rm_hdr length bug. + * + * Copyright (C) 2004 by David Brownell + * updates to merge with Linux 2.6, better match RNDIS spec */ #include @@ -35,28 +38,34 @@ #include #include + +#undef RNDIS_PM +#undef VERBOSE + #include "rndis.h" /* The driver for your USB chip needs to support ep0 OUT to work with - * RNDIS, plus the same three descriptors as CDC Ethernet. + * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). * * Windows hosts need an INF file like Documentation/usb/linux.inf + * and will be happier if you provide the host_addr module parameter. */ -#ifndef __LITTLE_ENDIAN -#warning this code is missing all cpu_to_leXX() calls ... -#endif - #if 0 -#define DEBUG if (rndis_debug) printk +#define DEBUG(str,args...) do { \ + if (rndis_debug) \ + printk(KERN_DEBUG str , ## args ); \ + } while (0) static int rndis_debug = 0; module_param (rndis_debug, bool, 0); MODULE_PARM_DESC (rndis_debug, "enable debugging"); #else -#define DEBUG(str,args...) do{}while(0) + +#define rndis_debug 0 +#define DEBUG(str,args...) do{}while(0) #endif #define RNDIS_MAX_CONFIGS 1 @@ -79,16 +88,14 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length); -/* FIXME OMITTED OIDs, that RNDIS-on-USB "must" support, include - * - power management (OID_PNP_CAPABILITIES, ...) - * - network wakeup (OID_PNP_ENABLE_WAKE_UP, ...) - */ /* NDIS Functions */ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) { int retval = -ENOTSUPP; u32 length = 0; + u32 *tmp; + int i, count; rndis_query_cmplt_type *resp; if (!r) return -ENOMEM; @@ -97,11 +104,17 @@ if (!resp) return -ENOMEM; switch (OID) { + + /* general oids (table 4-1) */ + /* mandatory */ case OID_GEN_SUPPORTED_LIST: DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); length = sizeof (oid_supported_list); - memcpy ((u8 *) resp + 24, oid_supported_list, length); + count = length / sizeof (u32); + tmp = (u32 *) ((u8 *)resp + 24); + for (i = 0; i < count; i++) + tmp[i] = cpu_to_le32 (oid_supported_list[i]); retval = 0; break; @@ -115,7 +128,7 @@ * reddite ergo quae sunt Caesaris Caesari * et quae sunt Dei Deo! */ - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; @@ -123,7 +136,8 @@ case OID_GEN_MEDIA_SUPPORTED: DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].medium); retval = 0; break; @@ -132,24 +146,21 @@ DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); length = 4; /* one medium, one transport... (maybe you do it better) */ - *((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].medium); retval = 0; break; - case OID_GEN_MAXIMUM_LOOKAHEAD: - DEBUG("%s: OID_GEN_MAXIMUM_LOOKAHEAD\n", __FUNCTION__); - break; - /* mandatory */ case OID_GEN_MAXIMUM_FRAME_SIZE: DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr] - .dev->mtu; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].dev->mtu); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -160,30 +171,20 @@ length = 4; if (rndis_per_dev_params [configNr].media_state == NDIS_MEDIA_STATE_DISCONNECTED) - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); else - *((u32 *) resp + 6) = rndis_per_dev_params [configNr].speed; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].speed); retval = 0; break; - - case OID_GEN_TRANSMIT_BUFFER_SPACE: - DEBUG("%s: OID_GEN_TRANSMIT_BUFFER_SPACE\n", __FUNCTION__); - length = 4; - *((u32 *) resp + 6) = 0; - retval = 0; - break; - - case OID_GEN_RECEIVE_BUFFER_SPACE: - DEBUG("%s: OID_GEN_RECEIVE_BUFFER_SPACE\n", __FUNCTION__); - break; - + /* mandatory */ case OID_GEN_TRANSMIT_BLOCK_SIZE: DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr] - .dev->mtu; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].dev->mtu); retval = 0; } break; @@ -193,8 +194,8 @@ DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr] - .dev->mtu; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].dev->mtu); retval = 0; } break; @@ -203,7 +204,8 @@ case OID_GEN_VENDOR_ID: DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr].vendorID; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].vendorID); retval = 0; break; @@ -216,129 +218,92 @@ retval = 0; break; + case OID_GEN_VENDOR_DRIVER_VERSION: + DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); + length = 4; + /* Created as LE */ + *((u32 *) resp + 6) = rndis_driver_version; + retval = 0; + break; + /* mandatory */ case OID_GEN_CURRENT_PACKET_FILTER: DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params[configNr].filter; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params[configNr].filter); retval = 0; break; - - case OID_GEN_CURRENT_LOOKAHEAD: - DEBUG("%s: OID_GEN_CURRENT_LOOKAHEAD\n", __FUNCTION__); - break; - - case OID_GEN_DRIVER_VERSION: - DEBUG("%s: OID_GEN_DRIVER_VERSION\n", __FUNCTION__); - break; - + /* mandatory */ case OID_GEN_MAXIMUM_TOTAL_SIZE: DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = RNDIS_MAX_TOTAL_SIZE; - retval = 0; - break; - - case OID_GEN_PROTOCOL_OPTIONS: - DEBUG("%s: OID_GEN_PROTOCOL_OPTIONS\n", __FUNCTION__); - break; - - case OID_GEN_MAC_OPTIONS: - DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); - length = 4; - *((u32 *) resp + 6) = NDIS_MAC_OPTION_RECEIVE_SERIALIZED | - NDIS_MAC_OPTION_FULL_DUPLEX; + *((u32 *) resp + 6) = __constant_cpu_to_le32( + RNDIS_MAX_TOTAL_SIZE); retval = 0; break; - + /* mandatory */ case OID_GEN_MEDIA_CONNECT_STATUS: DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr] - .media_state; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .media_state); retval = 0; break; - - case OID_GEN_MAXIMUM_SEND_PACKETS: - DEBUG("%s: OID_GEN_MAXIMUM_SEND_PACKETS\n", __FUNCTION__); - break; - - /* mandatory */ - case OID_GEN_VENDOR_DRIVER_VERSION: - DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); - length = 4; - *((u32 *) resp + 6) = rndis_driver_version; - retval = 0; - break; - - case OID_GEN_SUPPORTED_GUIDS: - DEBUG("%s: OID_GEN_SUPPORTED_GUIDS\n", __FUNCTION__); - break; - - case OID_GEN_NETWORK_LAYER_ADDRESSES: - DEBUG("%s: OID_GEN_NETWORK_LAYER_ADDRESSES\n", __FUNCTION__); - break; - - case OID_GEN_TRANSPORT_HEADER_OFFSET: - DEBUG("%s: OID_GEN_TRANSPORT_HEADER_OFFSET\n", __FUNCTION__); - break; - - case OID_GEN_MACHINE_NAME: - DEBUG("%s: OID_GEN_MACHINE_NAME\n", __FUNCTION__); - break; - - case OID_GEN_RNDIS_CONFIG_PARAMETER: - DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__); + + case OID_GEN_PHYSICAL_MEDIUM: + DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; - - case OID_GEN_VLAN_ID: - DEBUG("%s: OID_GEN_VLAN_ID\n", __FUNCTION__); - break; - - case OID_GEN_MEDIA_CAPABILITIES: - DEBUG("%s: OID_GEN_MEDIA_CAPABILITIES\n", __FUNCTION__); - break; - - case OID_GEN_PHYSICAL_MEDIUM: - DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); + + /* The RNDIS specification is incomplete/wrong. Some versions + * of MS-Windows expect OIDs that aren't specified there. Other + * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! + */ + case OID_GEN_MAC_OPTIONS: /* from WinME */ + DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32( + NDIS_MAC_OPTION_RECEIVE_SERIALIZED + | NDIS_MAC_OPTION_FULL_DUPLEX); retval = 0; break; - + + /* statistics OIDs (table 4-2) */ + /* mandatory */ case OID_GEN_XMIT_OK: DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr] - .stats->tx_packets - + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].stats->tx_packets - rndis_per_dev_params [configNr].stats->tx_errors - - rndis_per_dev_params [configNr].stats->tx_dropped; + rndis_per_dev_params [configNr].stats->tx_dropped); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; - + /* mandatory */ case OID_GEN_RCV_OK: DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->rx_packets - + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr].stats->rx_packets - rndis_per_dev_params [configNr].stats->rx_errors - - rndis_per_dev_params [configNr].stats->rx_dropped; + rndis_per_dev_params [configNr].stats->rx_dropped); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -348,11 +313,12 @@ DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->tx_errors; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->tx_errors); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -361,11 +327,12 @@ case OID_GEN_RCV_ERROR: DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->rx_errors; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->rx_errors); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -374,15 +341,17 @@ case OID_GEN_RCV_NO_BUFFER: DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->rx_dropped; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->rx_dropped); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; - + +#ifdef RNDIS_OPTIONAL_STATS case OID_GEN_DIRECTED_BYTES_XMIT: DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); /* @@ -392,14 +361,17 @@ */ if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = (rndis_per_dev_params [configNr]. - stats->tx_packets - - rndis_per_dev_params [configNr].stats->tx_errors - - rndis_per_dev_params [configNr].stats->tx_dropped) - *123; + *((u32 *) resp + 6) = cpu_to_le32 ( + (rndis_per_dev_params [configNr] + .stats->tx_packets - + rndis_per_dev_params [configNr] + .stats->tx_errors - + rndis_per_dev_params [configNr] + .stats->tx_dropped) + * 123); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -409,14 +381,17 @@ /* dito */ if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = (rndis_per_dev_params [configNr]. - stats->tx_packets - - rndis_per_dev_params [configNr].stats->tx_errors - - rndis_per_dev_params [configNr].stats->tx_dropped) - /123; + *((u32 *) resp + 6) = cpu_to_le32 ( + (rndis_per_dev_params [configNr] + .stats->tx_packets - + rndis_per_dev_params [configNr] + .stats->tx_errors - + rndis_per_dev_params [configNr] + .stats->tx_dropped) + / 123); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -424,11 +399,12 @@ case OID_GEN_MULTICAST_BYTES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->multicast*1234; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->multicast*1234); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -436,11 +412,12 @@ case OID_GEN_MULTICAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->multicast; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->multicast); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -448,11 +425,12 @@ case OID_GEN_BROADCAST_BYTES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->tx_packets/42*255; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->tx_packets/42*255); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -460,35 +438,37 @@ case OID_GEN_BROADCAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->tx_packets/42; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->tx_packets/42); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; case OID_GEN_DIRECTED_BYTES_RCV: DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; case OID_GEN_DIRECTED_FRAMES_RCV: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; case OID_GEN_MULTICAST_BYTES_RCV: DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->multicast*1111; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->multicast * 1111); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -496,11 +476,12 @@ case OID_GEN_MULTICAST_FRAMES_RCV: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->multicast; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->multicast); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -508,11 +489,12 @@ case OID_GEN_BROADCAST_BYTES_RCV: DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->rx_packets/42*255; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->rx_packets/42*255); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -520,11 +502,12 @@ case OID_GEN_BROADCAST_FRAMES_RCV: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->rx_packets/42; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->rx_packets/42); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -532,61 +515,25 @@ case OID_GEN_RCV_CRC_ERROR: DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = rndis_per_dev_params [configNr]. - stats->rx_crc_errors; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->rx_crc_errors); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; case OID_GEN_TRANSMIT_QUEUE_LENGTH: DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; - - case OID_GEN_GET_TIME_CAPS: - DEBUG("%s: OID_GEN_GET_TIME_CAPS\n", __FUNCTION__); - break; - - case OID_GEN_GET_NETCARD_TIME: - DEBUG("%s: OID_GEN_GET_NETCARD_TIME\n", __FUNCTION__); - break; - - case OID_GEN_NETCARD_LOAD: - DEBUG("%s: OID_GEN_NETCARD_LOAD\n", __FUNCTION__); - break; - - case OID_GEN_DEVICE_PROFILE: - DEBUG("%s: OID_GEN_DEVICE_PROFILE\n", __FUNCTION__); - break; - - case OID_GEN_INIT_TIME_MS: - DEBUG("%s: OID_GEN_INIT_TIME_MS\n", __FUNCTION__); - break; - - case OID_GEN_RESET_COUNTS: - DEBUG("%s: OID_GEN_RESET_COUNTS\n", __FUNCTION__); - break; - - case OID_GEN_MEDIA_SENSE_COUNTS: - DEBUG("%s: OID_GEN_MEDIA_SENSE_COUNTS\n", __FUNCTION__); - break; - - case OID_GEN_FRIENDLY_NAME: - DEBUG("%s: OID_GEN_FRIENDLY_NAME\n", __FUNCTION__); - break; - - case OID_GEN_MINIPORT_INFO: - DEBUG("%s: OID_GEN_MINIPORT_INFO\n", __FUNCTION__); - break; - - case OID_GEN_RESET_VERIFY_PARAMETERS: - DEBUG("%s: OID_GEN_RESET_VERIFY_PARAMETERS\n", __FUNCTION__); - break; - +#endif /* RNDIS_OPTIONAL_STATS */ + + /* ieee802.3 OIDs (table 4-3) */ + /* mandatory */ case OID_802_3_PERMANENT_ADDRESS: DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); @@ -597,7 +544,7 @@ length); retval = 0; } else { - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -619,7 +566,7 @@ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); length = 4; /* Multicast base address only */ - *((u32 *) resp + 6) = 0xE0000000; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000); retval = 0; break; @@ -628,22 +575,25 @@ DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); length = 4; /* Multicast base address only */ - *((u32 *) resp + 6) = 1; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (1); retval = 0; break; case OID_802_3_MAC_OPTIONS: DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); break; - + + /* ieee802.3 statistics OIDs (table 4-4) */ + /* mandatory */ case OID_802_3_RCV_ERROR_ALIGNMENT: DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = rndis_per_dev_params [configNr] - .stats->rx_frame_errors; + *((u32 *) resp + 6) = cpu_to_le32 ( + rndis_per_dev_params [configNr] + .stats->rx_frame_errors); retval = 0; } break; @@ -652,7 +602,7 @@ case OID_802_3_XMIT_ONE_COLLISION: DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; @@ -660,10 +610,11 @@ case OID_802_3_XMIT_MORE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = 0; + *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; +#ifdef RNDIS_OPTIONAL_STATS case OID_802_3_XMIT_DEFERRED: DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); /* TODO */ @@ -698,14 +649,46 @@ DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); /* TODO */ break; - - default: printk (KERN_ERR "%s: unknown OID 0x%08X\n", +#endif /* RNDIS_OPTIONAL_STATS */ + +#ifdef RNDIS_PM + /* power management OIDs (table 4-5) */ + case OID_PNP_CAPABILITIES: + DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); + + /* just PM, and remote wakeup on link status change + * (not magic packet or pattern match) + */ + length = sizeof (struct NDIS_PNP_CAPABILITIES); + memset (resp, 0, length); + { + struct NDIS_PNP_CAPABILITIES *caps = (void *) resp; + + caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE; + caps->WakeUpCapabilities.MinLinkChangeWakeUp + = NdisDeviceStateD3; + + /* FIXME then use usb_gadget_wakeup(), and + * set USB_CONFIG_ATT_WAKEUP in config desc + */ + } + retval = 0; + break; + case OID_PNP_QUERY_POWER: + DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__); + /* sure, handle any power state that maps to USB suspend */ + retval = 0; + break; +#endif + + default: + printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", __FUNCTION__, OID); } - resp->InformationBufferOffset = 16; - resp->InformationBufferLength = length; - resp->MessageLength = 24 + length; + resp->InformationBufferOffset = __constant_cpu_to_le32 (16); + resp->InformationBufferLength = cpu_to_le32 (length); + resp->MessageLength = cpu_to_le32 (24 + length); r->length = 24 + length; return retval; } @@ -715,9 +698,7 @@ { rndis_set_cmplt_type *resp; int i, retval = -ENOTSUPP; - struct rndis_config_parameter *param; struct rndis_params *params; - u8 *cp; if (!r) return -ENOMEM; @@ -725,20 +706,37 @@ if (!resp) return -ENOMEM; - cp = (u8 *)resp; + DEBUG("set OID %08x value, len %d:\n", OID, buf_len); + for (i = 0; i < buf_len; i += 16) { + DEBUG ("%03d: " + " %02x %02x %02x %02x" + " %02x %02x %02x %02x" + " %02x %02x %02x %02x" + " %02x %02x %02x %02x" + "\n", + i, + buf[i], buf [i+1], + buf[i+2], buf[i+3], + buf[i+4], buf [i+5], + buf[i+6], buf[i+7], + buf[i+8], buf [i+9], + buf[i+10], buf[i+11], + buf[i+12], buf [i+13], + buf[i+14], buf[i+15]); + } switch (OID) { case OID_GEN_CURRENT_PACKET_FILTER: params = &rndis_per_dev_params [configNr]; retval = 0; - /* FIXME use this NDIS_PACKET_TYPE_* bitflags to + /* FIXME use these NDIS_PACKET_TYPE_* bitflags to * filter packets in hard_start_xmit() * NDIS_PACKET_TYPE_x == CDC_PACKET_TYPE_x for x in: * PROMISCUOUS, DIRECTED, * MULTICAST, ALL_MULTICAST, BROADCAST */ - params->filter = *(u32 *)buf; + params->filter = cpu_to_le32p((u32 *)buf); DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, params->filter); @@ -763,23 +761,40 @@ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); retval = 0; break; - +#if 0 case OID_GEN_RNDIS_CONFIG_PARAMETER: - DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__); + { + struct rndis_config_parameter *param; param = (struct rndis_config_parameter *) buf; - if (param) { - for (i = 0; i < param->ParameterNameLength; i++) { - DEBUG ("%c", - *(buf + param->ParameterNameOffset + i)); - } - DEBUG ("\n"); + DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", + __FUNCTION__, + min(cpu_to_le32(param->ParameterNameLength),80), + buf + param->ParameterNameOffset); + retval = 0; } - + break; +#endif + +#ifdef RNDIS_PM + case OID_PNP_SET_POWER: + DEBUG ("OID_PNP_SET_POWER\n"); + /* sure, handle any power state that maps to USB suspend */ retval = 0; break; - - default: printk (KERN_ERR "%s: unknown OID 0x%08X\n", - __FUNCTION__, OID); + + case OID_PNP_ENABLE_WAKE_UP: + /* always-connected ... */ + DEBUG ("OID_PNP_ENABLE_WAKE_UP\n"); + retval = 0; + break; + + // no PM resume patterns supported (specified where?) + // so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails +#endif + + default: + printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", + __FUNCTION__, OID, buf_len); } return retval; @@ -804,22 +819,24 @@ if (!resp) return -ENOMEM; - resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; - resp->MessageLength = 52; - resp->RequestID = buf->RequestID; - resp->Status = RNDIS_STATUS_SUCCESS; - resp->MajorVersion = RNDIS_MAJOR_VERSION; - resp->MinorVersion = RNDIS_MINOR_VERSION; - resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS; - resp->Medium = RNDIS_MEDIUM_802_3; - resp->MaxPacketsPerTransfer = 1; - resp->MaxTransferSize = rndis_per_dev_params [configNr].dev->mtu + resp->MessageType = __constant_cpu_to_le32 ( + REMOTE_NDIS_INITIALIZE_CMPLT); + resp->MessageLength = __constant_cpu_to_le32 (52); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); + resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION); + resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION); + resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS); + resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3); + resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1); + resp->MaxTransferSize = cpu_to_le32 ( + rndis_per_dev_params [configNr].dev->mtu + sizeof (struct ethhdr) + sizeof (struct rndis_packet_msg_type) - + 22; - resp->PacketAlignmentFactor = 0; - resp->AFListOffset = 0; - resp->AFListSize = 0; + + 22); + resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); + resp->AFListOffset = __constant_cpu_to_le32 (0); + resp->AFListSize = __constant_cpu_to_le32 (0); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( @@ -833,7 +850,7 @@ rndis_query_cmplt_type *resp; rndis_resp_t *r; - DEBUG("%s: OID = %08X\n", __FUNCTION__, buf->OID); + // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; /* @@ -847,17 +864,18 @@ if (!resp) return -ENOMEM; - resp->MessageType = REMOTE_NDIS_QUERY_CMPLT; - resp->MessageLength = 24; - resp->RequestID = buf->RequestID; + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); + resp->MessageLength = __constant_cpu_to_le32 (24); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_query_resp (configNr, buf->OID, r)) { + if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) { /* OID not supported */ - resp->Status = RNDIS_STATUS_NOT_SUPPORTED; - resp->InformationBufferLength = 0; - resp->InformationBufferOffset = 0; + resp->Status = __constant_cpu_to_le32 ( + RNDIS_STATUS_NOT_SUPPORTED); + resp->InformationBufferLength = __constant_cpu_to_le32 (0); + resp->InformationBufferOffset = __constant_cpu_to_le32 (0); } else - resp->Status = RNDIS_STATUS_SUCCESS; + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( @@ -867,38 +885,42 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) { + u32 BufLength, BufOffset; rndis_set_cmplt_type *resp; rndis_resp_t *r; - int i; r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_set_cmplt_type *) r->buf; if (!resp) return -ENOMEM; - - DEBUG("%s: Length: %d\n", __FUNCTION__, buf->InformationBufferLength); - DEBUG("%s: Offset: %d\n", __FUNCTION__, buf->InformationBufferOffset); + + BufLength = cpu_to_le32 (buf->InformationBufferLength); + BufOffset = cpu_to_le32 (buf->InformationBufferOffset); + +#ifdef VERBOSE + DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); + DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); DEBUG("%s: InfoBuffer: ", __FUNCTION__); - for (i = 0; i < buf->InformationBufferLength; i++) { - DEBUG ("%02x ", *(((u8 *) buf) + i + 12 + - buf->InformationBufferOffset)); + for (i = 0; i < BufLength; i++) { + DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); } DEBUG ("\n"); +#endif - resp->MessageType = REMOTE_NDIS_SET_CMPLT; - resp->MessageLength = 16; - resp->RequestID = buf->RequestID; - if (gen_ndis_set_resp (configNr, buf->OID, - ((u8 *) buf) + 28, - buf->InformationBufferLength, r)) - resp->Status = RNDIS_STATUS_NOT_SUPPORTED; - else resp->Status = RNDIS_STATUS_SUCCESS; + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); + resp->MessageLength = __constant_cpu_to_le32 (16); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID), + ((u8 *) buf) + 8 + BufOffset, BufLength, r)) + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); + else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack (rndis_per_dev_params [configNr].dev); + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } @@ -914,10 +936,11 @@ resp = (rndis_reset_cmplt_type *) r->buf; if (!resp) return -ENOMEM; - resp->MessageType = REMOTE_NDIS_RESET_CMPLT; - resp->MessageLength = 16; - resp->Status = RNDIS_STATUS_SUCCESS; - resp->AddressingReset = 1; /* resent information */ + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); + resp->MessageLength = __constant_cpu_to_le32 (16); + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); + /* resent information */ + resp->AddressingReset = __constant_cpu_to_le32 (1); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( @@ -938,10 +961,11 @@ resp = (rndis_keepalive_cmplt_type *) r->buf; if (!resp) return -ENOMEM; - resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; - resp->MessageLength = 16; - resp->RequestID = buf->RequestID; - resp->Status = RNDIS_STATUS_SUCCESS; + resp->MessageType = __constant_cpu_to_le32 ( + REMOTE_NDIS_KEEPALIVE_CMPLT); + resp->MessageLength = __constant_cpu_to_le32 (16); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( @@ -969,11 +993,12 @@ resp = (rndis_indicate_status_msg_type *) r->buf; if (!resp) return -ENOMEM; - resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; - resp->MessageLength = 20; - resp->Status = status; - resp->StatusBufferLength = 0; - resp->StatusBufferOffset = 0; + resp->MessageType = __constant_cpu_to_le32 ( + REMOTE_NDIS_INDICATE_STATUS_MSG); + resp->MessageLength = __constant_cpu_to_le32 (20); + resp->Status = cpu_to_le32 (status); + resp->StatusBufferLength = __constant_cpu_to_le32 (0); + resp->StatusBufferOffset = __constant_cpu_to_le32 (0); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( @@ -1014,8 +1039,8 @@ return -ENOMEM; tmp = (u32 *) buf; - MsgType = *tmp; - MsgLength = *(tmp + 1); + MsgType = cpu_to_le32p(tmp++); + MsgLength = cpu_to_le32p(tmp++); if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; @@ -1025,14 +1050,14 @@ switch (MsgType) { case REMOTE_NDIS_INITIALIZE_MSG: - DEBUG(KERN_INFO "%s: REMOTE_NDIS_INITIALIZE_MSG\n", + DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __FUNCTION__ ); params->state = RNDIS_INITIALIZED; return rndis_init_response (configNr, (rndis_init_msg_type *) buf); case REMOTE_NDIS_HALT_MSG: - DEBUG(KERN_INFO "%s: REMOTE_NDIS_HALT_MSG\n", + DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", __FUNCTION__ ); params->state = RNDIS_UNINITIALIZED; if (params->dev) { @@ -1042,34 +1067,57 @@ return 0; case REMOTE_NDIS_QUERY_MSG: - DEBUG(KERN_INFO "%s: REMOTE_NDIS_QUERY_MSG\n", - __FUNCTION__ ); return rndis_query_response (configNr, (rndis_query_msg_type *) buf); case REMOTE_NDIS_SET_MSG: - DEBUG(KERN_INFO "%s: REMOTE_NDIS_SET_MSG\n", - __FUNCTION__ ); return rndis_set_response (configNr, (rndis_set_msg_type *) buf); case REMOTE_NDIS_RESET_MSG: - DEBUG(KERN_INFO "%s: REMOTE_NDIS_RESET_MSG\n", + DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", __FUNCTION__ ); return rndis_reset_response (configNr, (rndis_reset_msg_type *) buf); case REMOTE_NDIS_KEEPALIVE_MSG: /* For USB: host does this every 5 seconds */ - DEBUG(KERN_INFO "%s: REMOTE_NDIS_KEEPALIVE_MSG\n", +#ifdef VERBOSE + DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __FUNCTION__ ); +#endif return rndis_keepalive_response (configNr, (rndis_keepalive_msg_type *) buf); default: - printk (KERN_ERR "%s: unknown RNDIS Message Type 0x%08X\n", - __FUNCTION__ , MsgType); + /* At least Windows XP emits some undefined RNDIS messages. + * In one case those messages seemed to relate to the host + * suspending itself. + */ + printk (KERN_WARNING + "%s: unknown RNDIS message 0x%08X len %d\n", + __FUNCTION__ , MsgType, MsgLength); + { + unsigned i; + for (i = 0; i < MsgLength; i += 16) { + DEBUG ("%03d: " + " %02x %02x %02x %02x" + " %02x %02x %02x %02x" + " %02x %02x %02x %02x" + " %02x %02x %02x %02x" + "\n", + i, + buf[i], buf [i+1], + buf[i+2], buf[i+3], + buf[i+4], buf [i+5], + buf[i+6], buf[i+7], + buf[i+8], buf [i+9], + buf[i+10], buf[i+11], + buf[i+12], buf [i+13], + buf[i+14], buf[i+15]); + } + } break; } @@ -1079,13 +1127,12 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *)) { u8 i; - DEBUG("%s: ", __FUNCTION__ ); for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { if (!rndis_per_dev_params [i].used) { rndis_per_dev_params [i].used = 1; rndis_per_dev_params [i].ack = rndis_control_ack; - DEBUG("configNr = %d\n", i); + DEBUG("%s: configNr = %d\n", __FUNCTION__, i); return i; } } @@ -1145,10 +1192,10 @@ if (!skb) return; skb_push (skb, sizeof (struct rndis_packet_msg_type)); memset (skb->data, 0, sizeof (struct rndis_packet_msg_type)); - *((u32 *) skb->data) = 1; - *((u32 *) skb->data + 1) = skb->len; - *((u32 *) skb->data + 2) = 36; - *((u32 *) skb->data + 3) = skb->len - 44; + *((u32 *) skb->data) = __constant_cpu_to_le32 (1); + *((u32 *) skb->data + 1) = cpu_to_le32(skb->len); + *((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36); + *((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44); return; } @@ -1208,14 +1255,16 @@ int rndis_rm_hdr (u8 *buf, u32 *length) { - u32 i, messageLen, dataOffset; + u32 i, messageLen, dataOffset, *tmp; + tmp = (u32 *) buf; + if (!buf || !length) return -1; - if (*((u32 *) buf) != 1) return -1; + if (cpu_to_le32p(tmp++) != 1) return -1; - messageLen = *((u32 *) buf + 1); - - dataOffset = *((u32 *) buf + 2) + 8; + messageLen = cpu_to_le32p(tmp++); + dataOffset = cpu_to_le32p(tmp++) + 8; + if (messageLen < dataOffset || messageLen > *length) return -1; for (i = dataOffset; i < messageLen; i++) diff -Nru a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h --- a/drivers/usb/gadget/rndis.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/gadget/rndis.h 2004-06-20 13:00:23 -07:00 @@ -59,10 +59,18 @@ #define RNDIS_MEDIUM_802_3 0x00000000U +/* from drivers/net/sk98lin/h/skgepnmi.h */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + + /* supported OIDs */ static const u32 oid_supported_list [] = { - /* mandatory general */ /* the general stuff */ OID_GEN_SUPPORTED_LIST, OID_GEN_HARDWARE_STATUS, @@ -70,7 +78,6 @@ OID_GEN_MEDIA_IN_USE, OID_GEN_MAXIMUM_FRAME_SIZE, OID_GEN_LINK_SPEED, - OID_GEN_TRANSMIT_BUFFER_SPACE, OID_GEN_TRANSMIT_BLOCK_SIZE, OID_GEN_RECEIVE_BLOCK_SIZE, OID_GEN_VENDOR_ID, @@ -78,10 +85,11 @@ OID_GEN_VENDOR_DRIVER_VERSION, OID_GEN_CURRENT_PACKET_FILTER, OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_MAC_OPTIONS, OID_GEN_MEDIA_CONNECT_STATUS, OID_GEN_PHYSICAL_MEDIUM, +#if 0 OID_GEN_RNDIS_CONFIG_PARAMETER, +#endif /* the statistical stuff */ OID_GEN_XMIT_OK, @@ -89,6 +97,7 @@ OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR, OID_GEN_RCV_NO_BUFFER, +#ifdef RNDIS_OPTIONAL_STATS OID_GEN_DIRECTED_BYTES_XMIT, OID_GEN_DIRECTED_FRAMES_XMIT, OID_GEN_MULTICAST_BYTES_XMIT, @@ -103,6 +112,7 @@ OID_GEN_BROADCAST_FRAMES_RCV, OID_GEN_RCV_CRC_ERROR, OID_GEN_TRANSMIT_QUEUE_LENGTH, +#endif /* RNDIS_OPTIONAL_STATS */ /* mandatory 802.3 */ /* the general stuff */ @@ -115,7 +125,30 @@ /* the statistical stuff */ OID_802_3_RCV_ERROR_ALIGNMENT, OID_802_3_XMIT_ONE_COLLISION, - OID_802_3_XMIT_MORE_COLLISIONS + OID_802_3_XMIT_MORE_COLLISIONS, +#ifdef RNDIS_OPTIONAL_STATS + OID_802_3_XMIT_DEFERRED, + OID_802_3_XMIT_MAX_COLLISIONS, + OID_802_3_RCV_OVERRUN, + OID_802_3_XMIT_UNDERRUN, + OID_802_3_XMIT_HEARTBEAT_FAILURE, + OID_802_3_XMIT_TIMES_CRS_LOST, + OID_802_3_XMIT_LATE_COLLISIONS, +#endif /* RNDIS_OPTIONAL_STATS */ + +#ifdef RNDIS_PM + /* PM and wakeup are mandatory for USB: */ + + /* power management */ + OID_PNP_CAPABILITIES, + OID_PNP_QUERY_POWER, + OID_PNP_SET_POWER, + + /* wake up host */ + OID_PNP_ENABLE_WAKE_UP, + OID_PNP_ADD_WAKE_UP_PATTERN, + OID_PNP_REMOVE_WAKE_UP_PATTERN, +#endif }; diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/host/ehci-hcd.c 2004-06-20 13:00:25 -07:00 @@ -290,16 +290,17 @@ { if (cap & (1 << 16)) { int msec = 500; + struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller); /* request handoff to OS */ - cap &= 1 << 24; - pci_write_config_dword (to_pci_dev(ehci->hcd.self.controller), where, cap); + cap |= 1 << 24; + pci_write_config_dword(pdev, where, cap); /* and wait a while for it to happen */ do { msleep(10); msec -= 10; - pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), where, &cap); + pci_read_config_dword(pdev, where, &cap); } while ((cap & (1 << 16)) && msec); if (cap & (1 << 16)) { ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", @@ -520,7 +521,7 @@ /* wire up the root hub */ bus = hcd_to_bus (hcd); - bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0); + udev = usb_alloc_dev (NULL, bus, 0); if (!udev) { done2: ehci_mem_cleanup (ehci); @@ -553,11 +554,10 @@ * and device drivers may start it running. */ udev->speed = USB_SPEED_HIGH; - if (hcd_register_root (hcd) != 0) { + if (hcd_register_root (udev, hcd) != 0) { if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); ehci_reset (ehci); - bus->root_hub = 0; usb_put_dev (udev); retval = -ENODEV; goto done2; diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c --- a/drivers/usb/host/ehci-sched.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/host/ehci-sched.c 2004-06-20 13:00:24 -07:00 @@ -483,7 +483,7 @@ qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= ~0xffff; + qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff); qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask; } else dbg ("reused previous qh %p schedule", qh); diff -Nru a/drivers/usb/host/hc_sl811_rh.c b/drivers/usb/host/hc_sl811_rh.c --- a/drivers/usb/host/hc_sl811_rh.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/host/hc_sl811_rh.c 2004-06-20 13:00:25 -07:00 @@ -557,18 +557,24 @@ static int rh_connect_rh (hci_t * hci) { struct usb_device *usb_dev; + int retval; hci->rh.devnum = 0; usb_dev = usb_alloc_dev (NULL, hci->bus, 0); if (!usb_dev) return -ENOMEM; - hci->bus->root_hub = usb_dev; usb_dev->devnum = 1; usb_dev->bus->devnum_next = usb_dev->devnum + 1; set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap); - if (usb_new_device (usb_dev) != 0) { + down (&usb_bus_list_lock); + hci->bus->root_hub = usb_dev; + retval = usb_new_device (usb_dev); + if (retval != 0) + hci->bus->root_hub = NULL; + up (&usb_bus_list_lock); + if (retval != 0) { usb_put_dev (usb_dev); return -ENODEV; } diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c --- a/drivers/usb/host/ohci-dbg.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/host/ohci-dbg.c 2004-06-20 13:00:25 -07:00 @@ -134,13 +134,13 @@ struct ohci_regs *regs = controller->regs; u32 temp; - temp = readl (®s->revision) & 0xff; + temp = ohci_readl (®s->revision) & 0xff; ohci_dbg_sw (controller, next, size, "OHCI %d.%d, %s legacy support registers\n", 0x03 & (temp >> 4), (temp & 0x0f), (temp & 0x10) ? "with" : "NO"); - temp = readl (®s->control); + temp = ohci_readl (®s->control); ohci_dbg_sw (controller, next, size, "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp, @@ -155,7 +155,7 @@ temp & OHCI_CTRL_CBSR ); - temp = readl (®s->cmdstatus); + temp = ohci_readl (®s->cmdstatus); ohci_dbg_sw (controller, next, size, "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp, (temp & OHCI_SOC) >> 16, @@ -166,26 +166,26 @@ ); ohci_dump_intr_mask (controller, "intrstatus", - readl (®s->intrstatus), next, size); + ohci_readl (®s->intrstatus), next, size); ohci_dump_intr_mask (controller, "intrenable", - readl (®s->intrenable), next, size); + ohci_readl (®s->intrenable), next, size); // intrdisable always same as intrenable maybe_print_eds (controller, "ed_periodcurrent", - readl (®s->ed_periodcurrent), next, size); + ohci_readl (®s->ed_periodcurrent), next, size); maybe_print_eds (controller, "ed_controlhead", - readl (®s->ed_controlhead), next, size); + ohci_readl (®s->ed_controlhead), next, size); maybe_print_eds (controller, "ed_controlcurrent", - readl (®s->ed_controlcurrent), next, size); + ohci_readl (®s->ed_controlcurrent), next, size); maybe_print_eds (controller, "ed_bulkhead", - readl (®s->ed_bulkhead), next, size); + ohci_readl (®s->ed_bulkhead), next, size); maybe_print_eds (controller, "ed_bulkcurrent", - readl (®s->ed_bulkcurrent), next, size); + ohci_readl (®s->ed_bulkcurrent), next, size); maybe_print_eds (controller, "donehead", - readl (®s->donehead), next, size); + ohci_readl (®s->donehead), next, size); } #define dbg_port_sw(hc,num,value,next,size) \ @@ -637,7 +637,7 @@ "hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca)); /* other registers mostly affect frame timings */ - rdata = readl (®s->fminterval); + rdata = ohci_readl (®s->fminterval); temp = scnprintf (next, size, "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", rdata, (rdata >> 31) ? " FIT" : "", @@ -645,20 +645,20 @@ size -= temp; next += temp; - rdata = readl (®s->fmremaining); + rdata = ohci_readl (®s->fmremaining); temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", rdata, (rdata >> 31) ? " FRT" : "", rdata & 0x3fff); size -= temp; next += temp; - rdata = readl (®s->periodicstart); + rdata = ohci_readl (®s->periodicstart); temp = scnprintf (next, size, "periodicstart 0x%04x\n", rdata & 0x3fff); size -= temp; next += temp; - rdata = readl (®s->lsthresh); + rdata = ohci_readl (®s->lsthresh); temp = scnprintf (next, size, "lsthresh 0x%04x\n", rdata & 0x3fff); size -= temp; diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/host/ohci-hcd.c 2004-06-20 13:00:23 -07:00 @@ -17,6 +17,7 @@ * * History: * + * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer) * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net) * 2003/02/24 show registers in sysfs (Kevin Brosius) * @@ -393,7 +394,7 @@ /* boot firmware should have set this up (5.1.1.3.1) */ if (!ohci->fminterval) { - temp = readl (&ohci->regs->fminterval); + temp = ohci_readl (&ohci->regs->fminterval); if (temp & 0x3fff0000) ohci->fminterval = temp; else @@ -405,7 +406,7 @@ * On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ #ifndef __hppa__ - if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n"); /* this timeout is arbitrary. we make it long, so systems @@ -416,7 +417,7 @@ writel (OHCI_INTR_OC, &ohci->regs->intrenable); writel (OHCI_OCR, &ohci->regs->cmdstatus); - while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { msleep (10); if (--temp == 0) { ohci_err (ohci, "USB HC TakeOver failed!\n"); @@ -430,13 +431,13 @@ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); ohci_dbg (ohci, "reset, control = 0x%x\n", - readl (&ohci->regs->control)); + ohci_readl (&ohci->regs->control)); /* Reset USB (needed by some controllers); RemoteWakeupConnected * saved if boot firmware (BIOS/SMM/...) told us it's connected * (for OHCI integrated on mainboard, it normally is) */ - ohci->hc_control = readl (&ohci->regs->control); + ohci->hc_control = ohci_readl (&ohci->regs->control); ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ if (ohci->hc_control) ohci->hcd.can_wakeup = 1; @@ -450,13 +451,13 @@ &ohci->regs->roothub.portstatus [temp]); } // flush those pci writes - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); msleep (50); /* HC Reset requires max 10 us delay */ writel (OHCI_HCR, &ohci->regs->cmdstatus); temp = 30; /* ... allow extra time */ - while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { if (--temp == 0) { ohci_err (ohci, "USB HC reset timed out!\n"); return -1; @@ -473,7 +474,7 @@ */ writel (ohci->hc_control, &ohci->regs->control); // flush those pci writes - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); return 0; } @@ -505,8 +506,8 @@ /* some OHCI implementations are finicky about how they init. * bogus values here mean not even enumeration could work. */ - if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 - || !readl (&ohci->regs->periodicstart)) { + if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 + || !ohci_readl (&ohci->regs->periodicstart)) { ohci_err (ohci, "init err\n"); return -EOVERFLOW; } @@ -548,7 +549,7 @@ writel (RH_HS_LPSC, &ohci->regs->roothub.status); writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b); // flush those pci writes - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((roothub_a (ohci) >> 23) & 0x1fe); @@ -560,7 +561,7 @@ } /* connect the virtual root hub */ - bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0); + udev = usb_alloc_dev (NULL, bus, 0); ohci->hcd.state = USB_STATE_RUNNING; if (!udev) { disable (ohci); @@ -570,9 +571,8 @@ } udev->speed = USB_SPEED_FULL; - if (hcd_register_root (&ohci->hcd) != 0) { + if (hcd_register_root (udev, &ohci->hcd) != 0) { usb_put_dev (udev); - bus->root_hub = NULL; disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; writel (ohci->hc_control, &ohci->regs->control); @@ -592,19 +592,20 @@ struct ohci_regs *regs = ohci->regs; int ints; - /* we can eliminate a (slow) readl() if _only_ WDH caused this irq */ + /* we can eliminate a (slow) ohci_readl() + if _only_ WDH caused this irq */ if ((ohci->hcca->done_head != 0) && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { ints = OHCI_INTR_WDH; /* cardbus/... hardware gone before remove() */ - } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { + } else if ((ints = ohci_readl (®s->intrstatus)) == ~(u32)0) { disable (ohci); ohci_dbg (ohci, "device removed!\n"); return IRQ_HANDLED; /* interrupt for some other device? */ - } else if ((ints &= readl (®s->intrenable)) == 0) { + } else if ((ints &= ohci_readl (®s->intrenable)) == 0) { return IRQ_NONE; } @@ -650,7 +651,7 @@ writel (ints, ®s->intrstatus); writel (OHCI_INTR_MIE, ®s->intrenable); // flush those pci writes - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); } return IRQ_HANDLED; @@ -798,6 +799,14 @@ #include "ohci-omap.c" #endif -#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111) || defined(CONFIG_ARCH_OMAP)) +#ifdef CONFIG_ARCH_LH7A404 +#include "ohci-lh7a404.c" +#endif + +#if !(defined(CONFIG_PCI) \ + || defined(CONFIG_SA1111) \ + || defined(CONFIG_ARCH_OMAP) \ + || defined (CONFIG_ARCH_LH7A404) \ + ) #error "missing bus glue for ohci-hcd" #endif diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c --- a/drivers/usb/host/ohci-hub.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/host/ohci-hub.c 2004-06-20 13:00:23 -07:00 @@ -20,20 +20,20 @@ * till some bits (mostly reserved) are clear; ok for all revs. */ #define read_roothub(hc, register, mask) ({ \ - u32 temp = readl (&hc->regs->roothub.register); \ + u32 temp = ohci_readl (&hc->regs->roothub.register); \ if (temp == -1) \ disable (hc); \ else if (hc->flags & OHCI_QUIRK_AMD756) \ while (temp & mask) \ - temp = readl (&hc->regs->roothub.register); \ + temp = ohci_readl (&hc->regs->roothub.register); \ temp; }) static u32 roothub_a (struct ohci_hcd *hc) { return read_roothub (hc, a, 0xfc0fe000); } static inline u32 roothub_b (struct ohci_hcd *hc) - { return readl (&hc->regs->roothub.b); } + { return ohci_readl (&hc->regs->roothub.b); } static inline u32 roothub_status (struct ohci_hcd *hc) - { return readl (&hc->regs->roothub.status); } + { return ohci_readl (&hc->regs->roothub.status); } static u32 roothub_portstatus (struct ohci_hcd *hc, int i) { return read_roothub (hc, portstatus [i], 0xffe0fce0); } @@ -83,14 +83,14 @@ spin_lock_irq (&ohci->lock); - ohci->hc_control = readl (&ohci->regs->control); + ohci->hc_control = ohci_readl (&ohci->regs->control); switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_RESUME: ohci_dbg (ohci, "resume/suspend?\n"); ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control |= OHCI_USB_RESET; writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); /* FALL THROUGH */ case OHCI_USB_RESET: status = -EBUSY; @@ -109,7 +109,7 @@ ohci->hc_control &= ~OHCI_SCHED_ENABLES; writel (ohci->hc_control, &ohci->regs->control); - ohci->hc_control = readl (&ohci->regs->control); + ohci->hc_control = ohci_readl (&ohci->regs->control); writel (OHCI_INTR_SF, &ohci->regs->intrstatus); /* sched disables take effect on the next frame, @@ -120,7 +120,7 @@ while (limit > 0) { udelay (250); limit =- 250; - if (readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) break; } dl_done_list (ohci, 0); @@ -128,7 +128,7 @@ } dl_done_list (ohci, 0); finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), 0); - writel (readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); + writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); /* maybe resume can wake root hub */ if (ohci->hcd.remote_wakeup) @@ -140,7 +140,7 @@ ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control |= OHCI_USB_SUSPEND; writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); /* no resumes until devices finish suspending */ ohci->next_statechange = jiffies + msecs_to_jiffies (5); @@ -179,13 +179,13 @@ return -EAGAIN; spin_lock_irq (&ohci->lock); - ohci->hc_control = readl (&ohci->regs->control); + ohci->hc_control = ohci_readl (&ohci->regs->control); switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_SUSPEND: ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES); ohci->hc_control |= OHCI_USB_RESUME; writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); ohci_dbg (ohci, "resume root hub\n"); break; case OHCI_USB_RESUME: @@ -210,7 +210,7 @@ temp = roothub_a (ohci) & RH_A_NDP; enables = 0; while (temp--) { - u32 stat = readl (&ohci->regs->roothub.portstatus [temp]); + u32 stat = ohci_readl (&ohci->regs->roothub.portstatus [temp]); /* force global, not selective, resume */ if (!(stat & RH_PS_PSS)) @@ -222,7 +222,7 @@ ohci->hcd.state = USB_STATE_RESUMING; mdelay (20 /* usb 11.5.1.10 */ + 15); - temp = readl (&ohci->regs->control); + temp = ohci_readl (&ohci->regs->control); temp &= OHCI_CTRL_HCFS; if (temp != OHCI_USB_RESUME) { ohci_err (ohci, "controller won't resume\n"); @@ -243,11 +243,11 @@ writel (OHCI_INTR_INIT, &ohci->regs->intrenable); if (ohci->ed_rm_list) writel (OHCI_INTR_SF, &ohci->regs->intrenable); - writel (readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); + writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); /* Then re-enable operations */ writel (OHCI_USB_OPER, &ohci->regs->control); - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); msleep (3); temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; @@ -255,7 +255,7 @@ temp |= OHCI_CTRL_RWC; ohci->hc_control = temp; writel (temp, &ohci->regs->control); - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); /* TRSMRCY */ msleep (10); @@ -290,7 +290,7 @@ writel (ohci->hc_control, &ohci->regs->control); if (temp) writel (status, &ohci->regs->cmdstatus); - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); } ohci->hcd.state = USB_STATE_RUNNING; @@ -332,7 +332,7 @@ if (!HCD_IS_RUNNING(ohci->hcd.state)) return -ESHUTDOWN; ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", - ports, readl (&ohci->regs->roothub.a) & RH_A_NDP); + ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ return 0; } @@ -496,7 +496,7 @@ goto error; } writel (temp, &ohci->regs->roothub.portstatus [wIndex]); - // readl (&ohci->regs->roothub.portstatus [wIndex]); + // ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); break; case GetHubDescriptor: ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); @@ -541,7 +541,7 @@ &ohci->regs->roothub.portstatus [wIndex]); break; case USB_PORT_FEAT_RESET: - temp = readl (&ohci->regs->roothub.portstatus [wIndex]); + temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); if (temp & RH_PS_CCS) writel (RH_PS_PRS, &ohci->regs->roothub.portstatus [wIndex]); diff -Nru a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/usb/host/ohci-lh7a404.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,385 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2002 Hewlett-Packard Company + * + * Bus Glue for Sharp LH7A404 + * + * Written by Christopher Hoover + * Based on fragments of previous driver by Rusell King et al. + * + * Modified for LH7A404 from ohci-sa1111.c + * by Durgesh Pattamatta + * + * This file is licenced under the GPL. + */ + +#include +#include +#include + + +extern int usb_disabled(void); + +/*-------------------------------------------------------------------------*/ + +static void lh7a404_start_hc(struct platform_device *dev) +{ + printk(KERN_DEBUG __FILE__ + ": starting LH7A404 OHCI USB Controller\n"); + + /* + * Now, carefully enable the USB clock, and take + * the USB host controller out of reset. + */ + CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */ + udelay(1000); + USBH_CMDSTATUS = OHCI_HCR; + + printk(KERN_DEBUG __FILE__ + ": Clock to USB host has been enabled \n"); +} + +static void lh7a404_stop_hc(struct platform_device *dev) +{ + printk(KERN_DEBUG __FILE__ + ": stopping LH7A404 OHCI USB Controller\n"); + + CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */ +} + + +/*-------------------------------------------------------------------------*/ + + +static irqreturn_t usb_hcd_lh7a404_hcim_irq (int irq, void *__hcd, + struct pt_regs * r) +{ + struct usb_hcd *hcd = __hcd; + + return usb_hcd_irq(irq, hcd, r); +} + +/*-------------------------------------------------------------------------*/ + +void usb_hcd_lh7a404_remove (struct usb_hcd *, struct platform_device *); + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + + +/** + * usb_hcd_lh7a404_probe - initialize LH7A404-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + */ +int usb_hcd_lh7a404_probe (const struct hc_driver *driver, + struct usb_hcd **hcd_out, + struct platform_device *dev) +{ + int retval; + struct usb_hcd *hcd = 0; + + unsigned int *addr = NULL; + + if (!request_mem_region(dev->resource[0].start, + dev->resource[0].end + - dev->resource[0].start + 1, hcd_name)) { + pr_debug("request_mem_region failed"); + return -EBUSY; + } + + + lh7a404_start_hc(dev); + + addr = ioremap(dev->resource[0].start, + dev->resource[0].end + - dev->resource[0].start + 1); + if (!addr) { + pr_debug("ioremap failed"); + retval = -ENOMEM; + goto err1; + } + + + hcd = driver->hcd_alloc (); + if (hcd == NULL){ + pr_debug ("hcd_alloc failed"); + retval = -ENOMEM; + goto err1; + } + + if(dev->resource[1].flags != IORESOURCE_IRQ){ + pr_debug ("resource[1] is not IORESOURCE_IRQ"); + retval = -ENOMEM; + goto err1; + } + + hcd->driver = (struct hc_driver *) driver; + hcd->description = driver->description; + hcd->irq = dev->resource[1].start; + hcd->regs = addr; + hcd->self.controller = &dev->dev; + + retval = hcd_buffer_create (hcd); + if (retval != 0) { + pr_debug ("pool alloc fail"); + goto err1; + } + + retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT, + hcd->description, hcd); + if (retval != 0) { + pr_debug("request_irq failed"); + retval = -EBUSY; + goto err2; + } + + pr_debug ("%s (LH7A404) at 0x%p, irq %d", + hcd->description, hcd->regs, hcd->irq); + + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; + hcd->self.hcpriv = (void *) hcd; + hcd->self.bus_name = "lh7a404"; + hcd->product_desc = "LH7A404 OHCI"; + + INIT_LIST_HEAD (&hcd->dev_list); + + usb_register_bus (&hcd->self); + + if ((retval = driver->start (hcd)) < 0) + { + usb_hcd_lh7a404_remove(hcd, dev); + return retval; + } + + *hcd_out = hcd; + return 0; + + err2: + hcd_buffer_destroy (hcd); + if (hcd) + driver->hcd_free(hcd); + err1: + lh7a404_stop_hc(dev); + release_mem_region(dev->resource[0].start, + dev->resource[0].end + - dev->resource[0].start + 1); + return retval; +} + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_lh7a404_remove - shutdown processing for LH7A404-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_lh7a404_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev) +{ + void *base; + + pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state); + + if (in_interrupt ()) + BUG (); + + hcd->state = USB_STATE_QUIESCING; + + pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name); + usb_disconnect (&hcd->self.root_hub); + + hcd->driver->stop (hcd); + hcd->state = USB_STATE_HALT; + + free_irq (hcd->irq, hcd); + hcd_buffer_destroy (hcd); + + usb_deregister_bus (&hcd->self); + + base = hcd->regs; + hcd->driver->hcd_free (hcd); + + lh7a404_stop_hc(dev); + release_mem_region(dev->resource[0].start, + dev->resource[0].end + - dev->resource[0].start + 1); +} + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_lh7a404_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci); + + ohci->hcca = dma_alloc_coherent (hcd->self.controller, + sizeof *ohci->hcca, &ohci->hcca_dma, 0); + if (!ohci->hcca) + return -ENOMEM; + + ohci_dbg (ohci, "ohci_lh7a404_start, ohci->hcca:%p", + ohci->hcca); + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + + if ((ret = ohci_mem_init (ohci)) < 0) { + ohci_stop (hcd); + return ret; + } + ohci->regs = hcd->regs; + + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; + } + + if (hc_start (ohci) < 0) { + err ("can't start %s", ohci->hcd.self.bus_name); + ohci_stop (hcd); + return -EBUSY; + } + create_debug_files (ohci); + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif /*DEBUG*/ + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ohci_lh7a404_hc_driver = { + .description = hcd_name, + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_USB11, + + /* + * basic lifecycle operations + */ + .start = ohci_lh7a404_start, +#ifdef CONFIG_PM + /* suspend: ohci_lh7a404_suspend, -- tbd */ + /* resume: ohci_lh7a404_resume, -- tbd */ +#endif /*CONFIG_PM*/ + .stop = ohci_stop, + + /* + * memory lifecycle (except per-request) + */ + .hcd_alloc = ohci_hcd_alloc, + .hcd_free = ohci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +}; + +/*-------------------------------------------------------------------------*/ + +static int ohci_hcd_lh7a404_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = NULL; + int ret; + + pr_debug ("In ohci_hcd_lh7a404_drv_probe"); + + if (usb_disabled()) + return -ENODEV; + + ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, &hcd, pdev); + + if (ret == 0) + dev_set_drvdata(dev, hcd); + + return ret; +} + +static int ohci_hcd_lh7a404_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_hcd_lh7a404_remove(hcd, pdev); + dev_set_drvdata(dev, NULL); + return 0; +} + /*TBD*/ +/*static int ohci_hcd_lh7a404_drv_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + return 0; +} +static int ohci_hcd_lh7a404_drv_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + + + return 0; +} +*/ + +static struct device_driver ohci_hcd_lh7a404_driver = { + .name = "lh7a404-ohci", + .bus = &platform_bus_type, + .probe = ohci_hcd_lh7a404_drv_probe, + .remove = ohci_hcd_lh7a404_drv_remove, + /*.suspend = ohci_hcd_lh7a404_drv_suspend, */ + /*.resume = ohci_hcd_lh7a404_drv_resume, */ +}; + +static int __init ohci_hcd_lh7a404_init (void) +{ + pr_debug (DRIVER_INFO " (LH7A404)"); + pr_debug ("block sizes: ed %d td %d\n", + sizeof (struct ed), sizeof (struct td)); + + return driver_register(&ohci_hcd_lh7a404_driver); +} + +static void __exit ohci_hcd_lh7a404_cleanup (void) +{ + driver_unregister(&ohci_hcd_lh7a404_driver); +} + +module_init (ohci_hcd_lh7a404_init); +module_exit (ohci_hcd_lh7a404_cleanup); diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c --- a/drivers/usb/host/ohci-omap.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/host/ohci-omap.c 2004-06-20 13:00:25 -07:00 @@ -454,7 +454,6 @@ */ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev) { - struct usb_device *hub; void *base; info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); @@ -462,11 +461,10 @@ if (in_interrupt ()) BUG (); - hub = hcd->self.root_hub; hcd->state = USB_STATE_QUIESCING; dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); - usb_disconnect (&hub); + usb_disconnect (&hcd->self.root_hub); hcd->driver->stop (hcd); hcd_buffer_destroy (hcd); diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/host/ohci-q.c 2004-06-20 13:00:25 -07:00 @@ -321,7 +321,7 @@ if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_CLE; writel (ohci->hc_control, &ohci->regs->control); - // a readl() later syncs CLE with the HC + // a ohci_readl() later syncs CLE with the HC } else writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); @@ -345,7 +345,7 @@ if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_BLE; writel (ohci->hc_control, &ohci->regs->control); - // a readl() later syncs BLE with the HC + // a ohci_readl() later syncs BLE with the HC } else writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); @@ -481,7 +481,7 @@ writel (OHCI_INTR_SF, &ohci->regs->intrstatus); writel (OHCI_INTR_SF, &ohci->regs->intrenable); // flush those writes, and get latest HCCA contents - (void) readl (&ohci->regs->control); + (void) ohci_readl (&ohci->regs->control); /* SF interrupt might get delayed; record the frame counter value that * indicates when the HC isn't looking at it, so concurrent unlinks diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c --- a/drivers/usb/host/ohci-sa1111.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/host/ohci-sa1111.c 2004-06-20 13:00:24 -07:00 @@ -237,7 +237,6 @@ */ void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev) { - struct usb_device *hub; void *base; info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); @@ -245,11 +244,10 @@ if (in_interrupt ()) BUG (); - hub = hcd->self.root_hub; hcd->state = USB_STATE_QUIESCING; dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); - usb_disconnect (&hub); + usb_disconnect (&hcd->self.root_hub); hcd->driver->stop (hcd); hcd->state = USB_STATE_HALT; diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/host/ohci.h 2004-06-20 13:00:26 -07:00 @@ -429,3 +429,22 @@ # define ohci_vdbg(ohci, fmt, args...) do { } while (0) #endif +#ifdef CONFIG_ARCH_LH7A404 + /* Marc Singer: at the time this code was written, the LH7A404 + * had a problem reading the USB host registers. This + * implementation of the ohci_readl function performs the read + * twice as a work-around. + */ +static inline unsigned int ohci_readl (void* regs) +{ + *(volatile unsigned int*) regs; + return *(volatile unsigned int*) regs; +} +#else + /* Standard version of ohci_readl uses standard, platform + * specific implementation. */ +static inline unsigned int ohci_readl (void* regs) +{ + return readl (regs); +} +#endif diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/host/uhci-hcd.c 2004-06-20 13:00:25 -07:00 @@ -103,8 +103,8 @@ static void hc_state_transitions(struct uhci_hcd *uhci); /* If a transfer is still active after this much time, turn off FSBR */ -#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ -#define FSBR_DELAY (HZ / 20) /* 50 ms */ +#define IDLE_TIMEOUT msecs_to_jiffies(50) +#define FSBR_DELAY msecs_to_jiffies(50) /* When we timeout an idle transfer for FSBR, we'll switch it over to */ /* depth first traversal. We'll do it in groups of this number of TD's */ @@ -1611,6 +1611,7 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct list_head list, *tmp, *head; unsigned long flags; + int called_uhci_finish_completion = 0; INIT_LIST_HEAD(&list); @@ -1619,6 +1620,7 @@ uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) { uhci_remove_pending_urbps(uhci); uhci_finish_completion(hcd, NULL); + called_uhci_finish_completion = 1; } head = &uhci->urb_list; @@ -1646,6 +1648,10 @@ } spin_unlock_irqrestore(&uhci->schedule_lock, flags); + /* Wake up anyone waiting for an URB to complete */ + if (called_uhci_finish_completion) + wake_up_all(&uhci->waitqh); + head = &list; tmp = head->next; while (tmp != head) { @@ -1676,7 +1682,7 @@ init_timer(&uhci->stall_timer); uhci->stall_timer.function = stall_callback; uhci->stall_timer.data = (unsigned long)hcd; - uhci->stall_timer.expires = jiffies + (HZ / 10); + uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100); add_timer(&uhci->stall_timer); return 0; @@ -1831,16 +1837,20 @@ { unsigned int io_addr = uhci->io_addr; + /* Turn off PIRQ, SMI, and all interrupts. This also turns off + * the BIOS's USB Legacy Support. + */ + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); + outw(0, uhci->io_addr + USBINTR); + /* Global reset for 50ms */ uhci->state = UHCI_RESET; outw(USBCMD_GRESET, io_addr + USBCMD); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((HZ*50+999) / 1000); + msleep(50); outw(0, io_addr + USBCMD); /* Another 10ms delay */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((HZ*10+999) / 1000); + msleep(10); uhci->resume_detect = 0; } @@ -1865,7 +1875,7 @@ /* Global resume for >= 20ms */ outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); uhci->state = UHCI_RESUMING_1; - uhci->state_end = jiffies + (20*HZ+999) / 1000; + uhci->state_end = jiffies + msecs_to_jiffies(20); break; case UHCI_RESUMING_1: /* End global resume */ @@ -1990,7 +2000,9 @@ } } - /* Turn on all interrupts */ + /* Turn on PIRQ and all interrupts */ + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, + USBLEGSUP_DEFAULT); outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); @@ -2054,15 +2066,10 @@ uhci->io_addr = (unsigned long) hcd->regs; - /* Turn off all interrupts */ - outw(0, uhci->io_addr + USBINTR); - - /* Maybe kick BIOS off this hardware. Then reset, so we won't get + /* Kick BIOS off this hardware and reset, so we won't get * interrupts from any previous setup. */ reset_hc(uhci); - pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, - USBLEGSUP_DEFAULT); return 0; } @@ -2178,7 +2185,7 @@ uhci->rh_numports = port; - hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self, 0); + udev = usb_alloc_dev(NULL, &hcd->self, 0); if (!udev) { dev_err(uhci_dev(uhci), "unable to allocate root hub\n"); goto err_alloc_root_hub; @@ -2260,7 +2267,7 @@ udev->speed = USB_SPEED_FULL; - if (usb_register_root_hub(udev, uhci_dev(uhci)) != 0) { + if (hcd_register_root(udev, &uhci->hcd) != 0) { dev_err(uhci_dev(uhci), "unable to start root hub\n"); retval = -ENOMEM; goto err_start_root_hub; @@ -2288,7 +2295,6 @@ err_alloc_term_td: usb_put_dev(udev); - hcd->self.root_hub = NULL; err_alloc_root_hub: dma_pool_destroy(uhci->qh_pool); @@ -2369,14 +2375,18 @@ /* * Some systems don't maintain the UHCI register values * during a PM suspend/resume cycle, so reinitialize - * the Frame Number, the Framelist Base Address, and the - * Interrupt Enable registers. + * the Frame Number, Framelist Base Address, Interrupt + * Enable, and Legacy Support registers. */ + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, + 0); outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM); outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, uhci->io_addr + USBINTR); uhci->resume_detect = 1; + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, + USBLEGSUP_DEFAULT); } else { reset_hc(uhci); start_hc(uhci); diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c --- a/drivers/usb/image/mdc800.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/image/mdc800.c 2004-06-20 13:00:24 -07:00 @@ -667,10 +667,10 @@ /* * The Device read callback Function */ -static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos) +static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos) { size_t left=len, sts=len; /* single transfer size */ - char* ptr=buf; + char __user *ptr = buf; long timeout; DECLARE_WAITQUEUE(wait, current); @@ -767,7 +767,7 @@ * After this the driver initiates the request for the answer or * just waits until the camera becomes ready. */ -static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos) +static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos) { size_t i=0; DECLARE_WAITQUEUE(wait, current); diff -Nru a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig --- a/drivers/usb/input/Kconfig 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/input/Kconfig 2004-06-20 13:00:25 -07:00 @@ -219,14 +219,16 @@ module will be called xpad. config USB_ATI_REMOTE - tristate "ATI USB RF remote control" + tristate "ATI / X10 USB RF remote control" depends on USB && INPUT ---help--- - Say Y here if you want to use one of ATI's USB remote controls. - These are RF remotes with USB receivers. They come with many of ATI's - All-In-Wonder video cards. This driver provides mouse pointer, left - and right mouse buttons, and maps all the other remote buttons to - keypress events. + Say Y here if you want to use an ATI or X10 "Lola" USB remote control. + These are RF remotes with USB receivers. + The ATI remote comes with many of ATI's All-In-Wonder video cards. + The X10 "Lola" remote is available at: + http://www.x10.com/products/lola_sg1.htm + This driver provides mouse pointer, left and right mouse buttons, + and maps all the other remote buttons to keypress events. To compile this driver as a module, choose M here: the module will be called ati_remote. diff -Nru a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c --- a/drivers/usb/input/ati_remote.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/input/ati_remote.c 2004-06-20 13:00:25 -07:00 @@ -16,6 +16,12 @@ * * Feb 2004: Torrey Hoffman * Version 2.2.0 + * Jun 2004: Torrey Hoffman + * Version 2.2.1 + * Added key repeat support contributed by: + * Vincent Vanackere + * Added support for the "Lola" remote contributed by: + * Seth Cohn * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -41,6 +47,11 @@ * "All-In-Wonder" video card packages. The receiver self-identifies as a * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". * + * The "Lola" remote is available from X10. See: + * http://www.x10.com/products/lola_sg1.htm + * The Lola is similar to the ATI remote but has no mouse support, and slightly + * different keys. + * * It is possible to use multiple receivers and remotes on multiple computers * simultaneously by configuring them to use specific channels. * @@ -90,8 +101,9 @@ #define ATI_REMOTE_VENDOR_ID 0x0bc7 #define ATI_REMOTE_PRODUCT_ID 0x004 +#define LOLA_REMOTE_PRODUCT_ID 0x002 -#define DRIVER_VERSION "2.2.0" +#define DRIVER_VERSION "2.2.1" #define DRIVER_AUTHOR "Torrey Hoffman " #define DRIVER_DESC "ATI/X10 RF USB Remote Control" @@ -113,6 +125,7 @@ static struct usb_device_id ati_remote_table[] = { { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, {} /* Terminating entry */ }; @@ -134,10 +147,13 @@ /* Duplicate event filtering time. * Sequential, identical KIND_FILTERED inputs with less than - * FILTER_TIME jiffies between them are dropped. - * (HZ >> 4) == 1/16th of a second and works well for me. + * FILTER_TIME jiffies between them are considered as repeat + * events. The hardware generates 5 events for the first keypress + * and we have to take this into account for an accurate repeat + * behaviour. + * (HZ / 20) == 50 ms and works well for me. */ -#define FILTER_TIME (HZ >> 4) +#define FILTER_TIME (HZ / 20) static DECLARE_MUTEX(disconnect_sem); @@ -161,6 +177,7 @@ unsigned char old_data[2]; /* Detect duplicate events */ unsigned long old_jiffies; unsigned long acc_jiffies; /* handle acceleration */ + unsigned int repeat_count; char name[NAME_BUFSIZE]; char phys[NAME_BUFSIZE]; @@ -256,6 +273,12 @@ {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ + {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ + {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ + {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ + {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ + {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ + {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} }; @@ -483,9 +506,20 @@ if ((ati_remote->old_data[0] == data[1]) && (ati_remote->old_data[1] == data[2]) && ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { - ati_remote->old_jiffies = jiffies; + ati_remote->repeat_count++; + } + else { + ati_remote->repeat_count = 0; + } + + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; + ati_remote->old_jiffies = jiffies; + + if ((ati_remote->repeat_count > 0) + && (ati_remote->repeat_count < 5)) return; - } + input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, @@ -494,9 +528,6 @@ ati_remote_tbl[index].code, 0); input_sync(dev); - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; - ati_remote->old_jiffies = jiffies; return; } @@ -697,9 +728,9 @@ /* See if the offered device matches what we can accept */ if ((udev->descriptor.idVendor != ATI_REMOTE_VENDOR_ID) || - (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID)) { + ( (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID) && + (udev->descriptor.idProduct != LOLA_REMOTE_PRODUCT_ID) )) return -ENODEV; - } /* Allocate and clear an ati_remote struct */ if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL))) @@ -856,4 +887,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- a/drivers/usb/input/hid-core.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/input/hid-core.c 2004-06-20 13:00:24 -07:00 @@ -1324,12 +1324,14 @@ } err = 0; - while ((ret = hid_wait_io(hid))) { + ret = hid_wait_io(hid); + while (ret) { err |= ret; if (test_bit(HID_CTRL_RUNNING, &hid->iofl)) usb_unlink_urb(hid->urbctrl); if (test_bit(HID_OUT_RUNNING, &hid->iofl)) usb_unlink_urb(hid->urbout); + ret = hid_wait_io(hid); } if (err) diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c --- a/drivers/usb/input/hiddev.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/input/hiddev.c 2004-06-20 13:00:24 -07:00 @@ -295,7 +295,7 @@ /* * "write" file op */ -static ssize_t hiddev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos) +static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { return -EINVAL; } @@ -303,7 +303,7 @@ /* * "read" file op */ -static ssize_t hiddev_read(struct file * file, char * buffer, size_t count, loff_t *ppos) +static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { DECLARE_WAITQUEUE(wait, current); struct hiddev_list *list = file->private_data; @@ -406,6 +406,7 @@ struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; + void __user *user_arg = (void __user *)arg; int i; if (!hiddev->exist) @@ -414,7 +415,7 @@ switch (cmd) { case HIDIOCGVERSION: - return put_user(HID_VERSION, (int *) arg); + return put_user(HID_VERSION, (int __user *)arg); case HIDIOCAPPLICATION: if (arg < 0 || arg >= hid->maxapplication) @@ -439,13 +440,13 @@ dinfo.product = dev->descriptor.idProduct; dinfo.version = dev->descriptor.bcdDevice; dinfo.num_applications = hid->maxapplication; - if (copy_to_user((void *) arg, &dinfo, sizeof(dinfo))) + if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) return -EFAULT; return 0; case HIDIOCGFLAG: - if (put_user(list->flags, (int *) arg)) + if (put_user(list->flags, (int __user *)arg)) return -EFAULT; return 0; @@ -453,7 +454,7 @@ case HIDIOCSFLAG: { int newflags; - if (get_user(newflags, (int *) arg)) + if (get_user(newflags, (int __user *)arg)) return -EFAULT; if ((newflags & ~HIDDEV_FLAGS) != 0 || @@ -471,7 +472,7 @@ int idx, len; char *buf; - if (get_user(idx, (int *) arg)) + if (get_user(idx, (int __user *)arg)) return -EFAULT; if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) @@ -482,7 +483,7 @@ return -EINVAL; } - if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) { + if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { kfree(buf); return -EFAULT; } @@ -498,7 +499,7 @@ return 0; case HIDIOCGREPORT: - if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo))) + if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) return -EFAULT; if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) @@ -513,7 +514,7 @@ return 0; case HIDIOCSREPORT: - if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo))) + if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) return -EFAULT; if (rinfo.report_type == HID_REPORT_TYPE_INPUT) @@ -527,7 +528,7 @@ return 0; case HIDIOCGREPORTINFO: - if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo))) + if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) return -EFAULT; if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) @@ -535,13 +536,13 @@ rinfo.num_fields = report->maxfield; - if (copy_to_user((void *) arg, &rinfo, sizeof(rinfo))) + if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) return -EFAULT; return 0; case HIDIOCGFIELDINFO: - if (copy_from_user(&finfo, (void *) arg, sizeof(finfo))) + if (copy_from_user(&finfo, user_arg, sizeof(finfo))) return -EFAULT; rinfo.report_type = finfo.report_type; rinfo.report_id = finfo.report_id; @@ -568,7 +569,7 @@ finfo.unit_exponent = field->unit_exponent; finfo.unit = field->unit; - if (copy_to_user((void *) arg, &finfo, sizeof(finfo))) + if (copy_to_user(user_arg, &finfo, sizeof(finfo))) return -EFAULT; return 0; @@ -578,7 +579,7 @@ if (!uref_multi) return -ENOMEM; uref = &uref_multi->uref; - if (copy_from_user(uref, (void *) arg, sizeof(*uref))) + if (copy_from_user(uref, user_arg, sizeof(*uref))) goto fault; rinfo.report_type = uref->report_type; @@ -595,7 +596,7 @@ uref->usage_code = field->usage[uref->usage_index].hid; - if (copy_to_user((void *) arg, uref, sizeof(*uref))) + if (copy_to_user(user_arg, uref, sizeof(*uref))) goto fault; kfree(uref_multi); @@ -611,11 +612,11 @@ return -ENOMEM; uref = &uref_multi->uref; if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { - if (copy_from_user(uref_multi, (void *) arg, + if (copy_from_user(uref_multi, user_arg, sizeof(*uref_multi))) goto fault; } else { - if (copy_from_user(uref, (void *) arg, sizeof(*uref))) + if (copy_from_user(uref, user_arg, sizeof(*uref))) goto fault; } @@ -652,7 +653,7 @@ switch (cmd) { case HIDIOCGUSAGE: uref->value = field->value[uref->usage_index]; - if (copy_to_user((void *) arg, uref, sizeof(*uref))) + if (copy_to_user(user_arg, uref, sizeof(*uref))) goto fault; goto goodreturn; @@ -667,7 +668,7 @@ for (i = 0; i < uref_multi->num_values; i++) uref_multi->values[i] = field->value[uref->usage_index + i]; - if (copy_to_user((void *) arg, uref_multi, + if (copy_to_user(user_arg, uref_multi, sizeof(*uref_multi))) goto fault; goto goodreturn; @@ -689,7 +690,7 @@ return -EINVAL; case HIDIOCGCOLLECTIONINFO: - if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo))) + if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) return -EFAULT; if (cinfo.index >= hid->maxcollection) @@ -699,7 +700,7 @@ cinfo.usage = hid->collection[cinfo.index].usage; cinfo.level = hid->collection[cinfo.index].level; - if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo))) + if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) return -EFAULT; return 0; @@ -715,7 +716,7 @@ len = strlen(hid->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user((char *) arg, hid->name, len) ? + return copy_to_user(user_arg, hid->name, len) ? -EFAULT : len; } @@ -726,7 +727,7 @@ len = strlen(hid->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user((char *) arg, hid->phys, len) ? + return copy_to_user(user_arg, hid->phys, len) ? -EFAULT : len; } } diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig --- a/drivers/usb/media/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/media/Kconfig 2004-06-20 13:00:23 -07:00 @@ -108,7 +108,7 @@ config USB_PWC tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_DEV && CONFIG_BROKEN ---help--- Say Y or M here if you want to use one of these Philips & OEM webcams: diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c --- a/drivers/usb/media/dabusb.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/media/dabusb.c 2004-06-20 13:00:24 -07:00 @@ -476,7 +476,7 @@ return 0; } -static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos) +static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) { pdabusb_t s = (pdabusb_t) file->private_data; unsigned long flags; @@ -670,7 +670,7 @@ break; } - if (copy_from_user (pbulk, (void *) arg, sizeof (bulk_transfer_t))) { + if (copy_from_user (pbulk, (void __user *) arg, sizeof (bulk_transfer_t))) { ret = -EFAULT; kfree (pbulk); break; @@ -678,18 +678,18 @@ ret=dabusb_bulk (s, pbulk); if(ret==0) - if (copy_to_user((void *)arg, pbulk, + if (copy_to_user((void __user *)arg, pbulk, sizeof(bulk_transfer_t))) ret = -EFAULT; kfree (pbulk); break; case IOCTL_DAB_OVERRUNS: - ret = put_user (s->overruns, (unsigned int *) arg); + ret = put_user (s->overruns, (unsigned int __user *) arg); break; case IOCTL_DAB_VERSION: - ret = put_user (version, (unsigned int *) arg); + ret = put_user (version, (unsigned int __user *) arg); break; default: diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c --- a/drivers/usb/media/ov511.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/media/ov511.c 2004-06-20 13:00:24 -07:00 @@ -4593,7 +4593,7 @@ } static ssize_t -ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos) +ov51x_v4l1_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos) { struct video_device *vdev = file->private_data; int noblock = file->f_flags&O_NONBLOCK; diff -Nru a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h --- a/drivers/usb/media/ov511.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/media/ov511.h 2004-06-20 13:00:24 -07:00 @@ -11,7 +11,7 @@ #ifdef OV511_DEBUG #define PDEBUG(level, fmt, args...) \ if (debug >= (level)) info("[%s:%d] " fmt, \ - __PRETTY_FUNCTION__, __LINE__ , ## args) + __FUNCTION__, __LINE__ , ## args) #else #define PDEBUG(level, fmt, args...) do {} while(0) #endif diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c --- a/drivers/usb/media/pwc-if.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/media/pwc-if.c 2004-06-20 13:00:25 -07:00 @@ -129,7 +129,7 @@ static int pwc_video_open(struct inode *inode, struct file *file); static int pwc_video_close(struct inode *inode, struct file *file); -static ssize_t pwc_video_read(struct file *file, char *buf, +static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static unsigned int pwc_video_poll(struct file *file, poll_table *wait); static int pwc_video_ioctl(struct inode *inode, struct file *file, @@ -1132,7 +1132,7 @@ device is tricky anyhow. */ -static ssize_t pwc_video_read(struct file *file, char *buf, +static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *vdev = file->private_data; diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c --- a/drivers/usb/media/se401.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/media/se401.c 2004-06-20 13:00:24 -07:00 @@ -1121,7 +1121,7 @@ return video_usercopy(inode, file, cmd, arg, se401_do_ioctl); } -static ssize_t se401_read(struct file *file, char *buf, +static ssize_t se401_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int realcount=count, ret=0; diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c --- a/drivers/usb/media/stv680.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/media/stv680.c 2004-06-20 13:00:25 -07:00 @@ -1309,7 +1309,7 @@ return 0; } -static ssize_t stv680_read (struct file *file, char *buf, +static ssize_t stv680_read (struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *dev = file->private_data; diff -Nru a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c --- a/drivers/usb/media/usbvideo.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/media/usbvideo.c 2004-06-20 13:00:26 -07:00 @@ -46,7 +46,7 @@ unsigned int cmd, unsigned long arg); static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); static int usbvideo_v4l_open(struct inode *inode, struct file *file); -static ssize_t usbvideo_v4l_read(struct file *file, char *buf, +static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static int usbvideo_v4l_close(struct inode *inode, struct file *file); @@ -1587,7 +1587,7 @@ * 20-Oct-2000 Created. * 01-Nov-2000 Added mutex (uvd->lock). */ -static ssize_t usbvideo_v4l_read(struct file *file, char *buf, +static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct uvd *uvd = file->private_data; diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c --- a/drivers/usb/media/vicam.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/media/vicam.c 2004-06-20 13:00:24 -07:00 @@ -523,9 +523,9 @@ } static int -vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long ul_arg) +vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg) { - void *arg = (void *)ul_arg; + void __user *user_arg = (void __user *)arg; struct vicam_camera *cam = file->private_data; int retval = 0; @@ -549,7 +549,7 @@ b.minwidth = 320; /* VIDEOSIZE_48_48 */ b.minheight = 240; - if (copy_to_user(arg, &b, sizeof (b))) + if (copy_to_user(user_arg, &b, sizeof(b))) retval = -EFAULT; break; @@ -560,7 +560,7 @@ struct video_channel v; DBG("VIDIOCGCHAN\n"); - if (copy_from_user(&v, arg, sizeof (v))) { + if (copy_from_user(&v, user_arg, sizeof(v))) { retval = -EFAULT; break; } @@ -576,7 +576,7 @@ v.type = VIDEO_TYPE_CAMERA; v.norm = 0; - if (copy_to_user(arg, &v, sizeof (v))) + if (copy_to_user(user_arg, &v, sizeof(v))) retval = -EFAULT; break; } @@ -585,7 +585,7 @@ { int v; - if (copy_from_user(&v, arg, sizeof (v))) + if (copy_from_user(&v, user_arg, sizeof(v))) retval = -EFAULT; DBG("VIDIOCSCHAN %d\n", v); @@ -604,8 +604,7 @@ vp.brightness = cam->gain << 8; vp.depth = 24; vp.palette = VIDEO_PALETTE_RGB24; - if (copy_to_user - (arg, &vp, sizeof (struct video_picture))) + if (copy_to_user(user_arg, &vp, sizeof (struct video_picture))) retval = -EFAULT; break; } @@ -614,7 +613,7 @@ { struct video_picture vp; - if (copy_from_user(&vp, arg, sizeof(vp))) { + if (copy_from_user(&vp, user_arg, sizeof(vp))) { retval = -EFAULT; break; } @@ -646,8 +645,7 @@ DBG("VIDIOCGWIN\n"); - if (copy_to_user - ((void *) arg, (void *) &vw, sizeof (vw))) + if (copy_to_user(user_arg, (void *)&vw, sizeof(vw))) retval = -EFAULT; // I'm not sure what the deal with a capture window is, it is very poorly described @@ -660,7 +658,7 @@ struct video_window vw; - if (copy_from_user(&vw, arg, sizeof(vw))) { + if (copy_from_user(&vw, user_arg, sizeof(vw))) { retval = -EFAULT; break; } @@ -687,8 +685,7 @@ for (i = 0; i < VICAM_FRAMES; i++) vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; - if (copy_to_user - ((void *) arg, (void *) &vm, sizeof (vm))) + if (copy_to_user(user_arg, (void *)&vm, sizeof(vm))) retval = -EFAULT; break; @@ -699,8 +696,7 @@ struct video_mmap vm; // int video_size; - if (copy_from_user - ((void *) &vm, (void *) arg, sizeof (vm))) { + if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) { retval = -EFAULT; break; } @@ -723,7 +719,7 @@ { int frame; - if (copy_from_user((void *) &frame, arg, sizeof (int))) { + if (copy_from_user((void *)&frame, user_arg, sizeof(int))) { retval = -EFAULT; break; } @@ -1003,7 +999,7 @@ } static ssize_t -vicam_read( struct file *file, char *buf, size_t count, loff_t *ppos ) +vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ) { struct vicam_camera *cam = file->private_data; diff -Nru a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c --- a/drivers/usb/media/w9968cf.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/media/w9968cf.c 2004-06-20 13:00:25 -07:00 @@ -388,7 +388,7 @@ static struct file_operations w9968cf_fops; static int w9968cf_open(struct inode*, struct file*); static int w9968cf_release(struct inode*, struct file*); -static ssize_t w9968cf_read(struct file*, char*, size_t, loff_t*); +static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*); static int w9968cf_mmap(struct file*, struct vm_area_struct*); static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long); static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int, void*); @@ -444,8 +444,8 @@ /* High-level CMOS sensor control functions */ static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val); static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val); -static inline int w9968cf_sensor_cmd(struct w9968cf_device*, - unsigned int cmd, void *arg); +static int w9968cf_sensor_cmd(struct w9968cf_device*, + unsigned int cmd, void *arg); static int w9968cf_sensor_init(struct w9968cf_device*); static int w9968cf_sensor_update_settings(struct w9968cf_device*); static int w9968cf_sensor_get_picture(struct w9968cf_device*); @@ -461,7 +461,7 @@ static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); static int w9968cf_set_window(struct w9968cf_device*, struct video_window); static inline u16 w9968cf_valid_palette(u16 palette); -static inline u16 w9968cf_valid_depth(u16 palette); +static u16 w9968cf_valid_depth(u16 palette); static inline u8 w9968cf_need_decompression(u16 palette); static int w9968cf_postprocess_frame(struct w9968cf_device*, struct w9968cf_frame_t*); @@ -1959,7 +1959,7 @@ Return the depth corresponding to the given palette. Palette _must_ be supported ! --------------------------------------------------------------------------*/ -static inline u16 w9968cf_valid_depth(u16 palette) +static u16 w9968cf_valid_depth(u16 palette) { u8 i=0; while (w9968cf_formatlist[i].palette != palette) @@ -2178,7 +2178,7 @@ } -static inline int +static int w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) { struct i2c_client* c = cam->sensor_client; @@ -2770,7 +2770,7 @@ static ssize_t -w9968cf_read(struct file* filp, char* buf, size_t count, loff_t* f_pos) +w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) { struct w9968cf_device* cam; struct w9968cf_frame_t* fr; @@ -2915,6 +2915,7 @@ unsigned int cmd, void* arg) { struct w9968cf_device* cam; + void __user *user_arg = (void __user *)arg; const char* v4l1_ioctls[] = { "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF", @@ -2948,7 +2949,7 @@ cap.maxheight = (cam->upscaling && w9968cf_vppmod_present) ? W9968CF_MAX_HEIGHT : cam->maxheight; - if (copy_to_user(arg, &cap, sizeof(cap))) + if (copy_to_user(user_arg, &cap, sizeof(cap))) return -EFAULT; DBG(5, "VIDIOCGCAP successfully called.") @@ -2958,7 +2959,7 @@ case VIDIOCGCHAN: /* get video channel informations */ { struct video_channel chan; - if (copy_from_user(&chan, arg, sizeof(chan))) + if (copy_from_user(&chan, user_arg, sizeof(chan))) return -EFAULT; if (chan.channel != 0) @@ -2970,7 +2971,7 @@ chan.type = VIDEO_TYPE_CAMERA; chan.norm = VIDEO_MODE_AUTO; - if (copy_to_user(arg, &chan, sizeof(chan))) + if (copy_to_user(user_arg, &chan, sizeof(chan))) return -EFAULT; DBG(5, "VIDIOCGCHAN successfully called.") @@ -2981,7 +2982,7 @@ { struct video_channel chan; - if (copy_from_user(&chan, arg, sizeof(chan))) + if (copy_from_user(&chan, user_arg, sizeof(chan))) return -EFAULT; if (chan.channel != 0) @@ -2996,7 +2997,7 @@ if (w9968cf_sensor_get_picture(cam)) return -EIO; - if (copy_to_user(arg, &cam->picture, sizeof(cam->picture))) + if (copy_to_user(user_arg, &cam->picture, sizeof(cam->picture))) return -EFAULT; DBG(5, "VIDIOCGPICT successfully called.") @@ -3008,7 +3009,7 @@ struct video_picture pict; int err = 0; - if (copy_from_user(&pict, arg, sizeof(pict))) + if (copy_from_user(&pict, user_arg, sizeof(pict))) return -EFAULT; if ( (cam->force_palette || !w9968cf_vppmod_present) @@ -3087,7 +3088,7 @@ struct video_window win; int err = 0; - if (copy_from_user(&win, arg, sizeof(win))) + if (copy_from_user(&win, user_arg, sizeof(win))) return -EFAULT; DBG(6, "VIDIOCSWIN called: clipcount=%d, flags=%d, " @@ -3141,7 +3142,7 @@ case VIDIOCGWIN: /* get current window properties */ { - if (copy_to_user(arg,&cam->window,sizeof(struct video_window))) + if (copy_to_user(user_arg, &cam->window, sizeof(struct video_window))) return -EFAULT; DBG(5, "VIDIOCGWIN successfully called.") @@ -3159,7 +3160,7 @@ mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer - (unsigned long)cam->frame[0].buffer; - if (copy_to_user(arg, &mbuf, sizeof(mbuf))) + if (copy_to_user(user_arg, &mbuf, sizeof(mbuf))) return -EFAULT; DBG(5, "VIDIOCGMBUF successfully called.") @@ -3172,7 +3173,7 @@ struct w9968cf_frame_t* fr; int err = 0; - if (copy_from_user(&mmap, arg, sizeof(mmap))) + if (copy_from_user(&mmap, user_arg, sizeof(mmap))) return -EFAULT; DBG(6, "VIDIOCMCAPTURE called: frame #%d, format=%s, %dx%d", @@ -3295,7 +3296,7 @@ struct w9968cf_frame_t* fr; int err = 0; - if (copy_from_user(&f_num, arg, sizeof(f_num))) + if (copy_from_user(&f_num, user_arg, sizeof(f_num))) return -EFAULT; if (f_num >= cam->nbuffers) { @@ -3348,7 +3349,7 @@ .teletext = VIDEO_NO_UNIT, }; - if (copy_to_user(arg, &unit, sizeof(unit))) + if (copy_to_user(user_arg, &unit, sizeof(unit))) return -EFAULT; DBG(5, "VIDIOCGUNIT successfully called.") @@ -3360,7 +3361,7 @@ case VIDIOCGFBUF: { - if (clear_user(arg, sizeof(struct video_buffer))) + if (clear_user(user_arg, sizeof(struct video_buffer))) return -EFAULT; DBG(5, "VIDIOCGFBUF successfully called.") @@ -3370,7 +3371,7 @@ case VIDIOCGTUNER: { struct video_tuner tuner; - if (copy_from_user(&tuner, arg, sizeof(tuner))) + if (copy_from_user(&tuner, user_arg, sizeof(tuner))) return -EFAULT; if (tuner.tuner != 0) @@ -3383,7 +3384,7 @@ tuner.mode = VIDEO_MODE_AUTO; tuner.signal = 0xffff; - if (copy_to_user(arg, &tuner, sizeof(tuner))) + if (copy_to_user(user_arg, &tuner, sizeof(tuner))) return -EFAULT; DBG(5, "VIDIOCGTUNER successfully called.") @@ -3393,7 +3394,7 @@ case VIDIOCSTUNER: { struct video_tuner tuner; - if (copy_from_user(&tuner, arg, sizeof(tuner))) + if (copy_from_user(&tuner, user_arg, sizeof(tuner))) return -EFAULT; if (tuner.tuner != 0) diff -Nru a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h --- a/drivers/usb/media/w9968cf.h 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/media/w9968cf.h 2004-06-20 13:00:23 -07:00 @@ -293,7 +293,7 @@ warn(fmt, ## args); \ else if ((level) >= 5) \ info("[%s:%d] " fmt, \ - __PRETTY_FUNCTION__, __LINE__ , ## args); \ + __FUNCTION__, __LINE__ , ## args); \ } \ } #else diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c --- a/drivers/usb/misc/auerswald.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/misc/auerswald.c 2004-06-20 13:00:24 -07:00 @@ -1452,6 +1452,8 @@ audevinfo_t devinfo; pauerswald_t cp = NULL; unsigned int u; + unsigned int __user *user_arg = (unsigned int __user *)arg; + dbg ("ioctl"); /* get the mutexes */ @@ -1483,14 +1485,14 @@ u = ccp->auerdev && (ccp->scontext.id != AUH_UNASSIGNED) && !list_empty (&cp->bufctl.free_buff_list); - ret = put_user (u, (unsigned int *) arg); + ret = put_user (u, user_arg); break; /* return != 0 if connected to a service channel */ case IOCTL_AU_CONNECT: dbg ("IOCTL_AU_CONNECT"); u = (ccp->scontext.id != AUH_UNASSIGNED); - ret = put_user (u, (unsigned int *) arg); + ret = put_user (u, user_arg); break; /* return != 0 if Receive Data available */ @@ -1511,14 +1513,14 @@ u = 1; } } - ret = put_user (u, (unsigned int *) arg); + ret = put_user (u, user_arg); break; /* return the max. buffer length for the device */ case IOCTL_AU_BUFLEN: dbg ("IOCTL_AU_BUFLEN"); u = cp->maxControlLength; - ret = put_user (u, (unsigned int *) arg); + ret = put_user (u, user_arg); break; /* requesting a service channel */ @@ -1527,7 +1529,7 @@ /* requesting a service means: release the previous one first */ auerswald_removeservice (cp, &ccp->scontext); /* get the channel number */ - ret = get_user (u, (unsigned int *) arg); + ret = get_user (u, user_arg); if (ret) { break; } @@ -1564,7 +1566,7 @@ case IOCTL_AU_SLEN: dbg ("IOCTL_AU_SLEN"); u = AUSI_DLEN; - ret = put_user (u, (unsigned int *) arg); + ret = put_user (u, user_arg); break; default: diff -Nru a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c --- a/drivers/usb/misc/legousbtower.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/misc/legousbtower.c 2004-06-20 13:00:24 -07:00 @@ -236,8 +236,8 @@ /* local function prototypes */ -static ssize_t tower_read (struct file *file, char *buffer, size_t count, loff_t *ppos); -static ssize_t tower_write (struct file *file, const char *buffer, size_t count, loff_t *ppos); +static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos); +static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos); static inline void tower_delete (struct lego_usb_tower *dev); static int tower_open (struct inode *inode, struct file *file); static int tower_release (struct inode *inode, struct file *file); @@ -560,7 +560,7 @@ /** * tower_read */ -static ssize_t tower_read (struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct lego_usb_tower *dev; size_t bytes_to_read; @@ -651,7 +651,7 @@ /** * tower_write */ -static ssize_t tower_write (struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t tower_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct lego_usb_tower *dev; size_t bytes_to_write; diff -Nru a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c --- a/drivers/usb/misc/phidgetservo.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/misc/phidgetservo.c 2004-06-20 13:00:25 -07:00 @@ -17,6 +17,10 @@ * * CAUTION: Generally you should use 0 < degrees < 180 as anything else * is probably beyond the range of your servo and may damage it. + * + * Jun 16, 2004: Sean Young + * - cleanups + * - was using memory after kfree() */ #include @@ -33,19 +37,36 @@ #define DRIVER_AUTHOR "Sean Young " #define DRIVER_DESC "USB PhidgetServo Driver" -#define VENDOR_ID_GLAB 0x06c2 -#define DEVICE_ID_4MOTOR_SERVO_30 0x0038 -#define DEVICE_ID_1MOTOR_SERVO_30 0x0039 - -#define VENDOR_ID_WISEGROUP 0x0925 -#define DEVICE_ID_1MOTOR_SERVO_20 0x8101 -#define DEVICE_ID_4MOTOR_SERVO_20 0x8104 +#define VENDOR_ID_GLAB 0x06c2 +#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD 0x0038 +#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI 0x0039 + +#define VENDOR_ID_WISEGROUP 0x0925 +#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD 0x8101 +#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI 0x8104 + +#define SERVO_VERSION_30 0x01 +#define SERVO_COUNT_QUAD 0x02 static struct usb_device_id id_table[] = { - {USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_4MOTOR_SERVO_30)}, - {USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_1MOTOR_SERVO_30)}, - {USB_DEVICE(VENDOR_ID_WISEGROUP, DEVICE_ID_4MOTOR_SERVO_20)}, - {USB_DEVICE(VENDOR_ID_WISEGROUP, DEVICE_ID_1MOTOR_SERVO_20)}, + { + USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD), + .driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD + }, + { + USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI), + .driver_info = SERVO_VERSION_30 + }, + { + USB_DEVICE(VENDOR_ID_WISEGROUP, + VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD), + .driver_info = SERVO_COUNT_QUAD + }, + { + USB_DEVICE(VENDOR_ID_WISEGROUP, + VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI), + .driver_info = 0 + }, {} }; @@ -53,14 +74,13 @@ struct phidget_servo { struct usb_device *udev; - int version; - int quad_servo; + ulong type; int pulse[4]; int degrees[4]; int minutes[4]; }; -static void +static int change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, int minutes) { @@ -71,7 +91,7 @@ if (!buffer) { dev_err(&servo->udev->dev, "%s - out of memory\n", __FUNCTION__); - return; + return -ENOMEM; } /* @@ -124,12 +144,13 @@ retval = usb_control_msg(servo->udev, usb_sndctrlpipe(servo->udev, 0), 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2 * HZ); - if (retval != 6) - dev_err(&servo->udev->dev, "retval = %d\n", retval); + kfree(buffer); + + return retval; } -static void +static int change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, int minutes) { @@ -140,7 +161,7 @@ if (!buffer) { dev_err(&servo->udev->dev, "%s - out of memory\n", __FUNCTION__); - return; + return -ENOMEM; } /* @@ -171,16 +192,17 @@ retval = usb_control_msg(servo->udev, usb_sndctrlpipe(servo->udev, 0), 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2 * HZ); - if (retval != 2) - dev_err(&servo->udev->dev, "retval = %d\n", retval); + kfree(buffer); + + return retval; } #define show_set(value) \ static ssize_t set_servo##value (struct device *dev, \ const char *buf, size_t count) \ { \ - int degrees, minutes; \ + int degrees, minutes, retval; \ struct usb_interface *intf = to_usb_interface (dev); \ struct phidget_servo *servo = usb_get_intfdata (intf); \ \ @@ -195,12 +217,14 @@ return -EINVAL; \ } \ \ - if (servo->version >= 3) \ - change_position_v30 (servo, value, degrees, minutes); \ + if (servo->type & SERVO_VERSION_30) \ + retval = change_position_v30 (servo, value, degrees, \ + minutes); \ else \ - change_position_v20 (servo, value, degrees, minutes); \ + retval = change_position_v20 (servo, value, degrees, \ + minutes); \ \ - return count; \ + return retval < 0 ? retval : count; \ } \ \ static ssize_t show_servo##value (struct device *dev, char *buf) \ @@ -223,7 +247,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); - struct phidget_servo *dev = NULL; + struct phidget_servo *dev; dev = kmalloc(sizeof (struct phidget_servo), GFP_KERNEL); if (dev == NULL) { @@ -233,37 +257,21 @@ memset(dev, 0x00, sizeof (*dev)); dev->udev = usb_get_dev(udev); - switch (udev->descriptor.idVendor) { - case VENDOR_ID_WISEGROUP: - dev->version = 2; - break; - case VENDOR_ID_GLAB: - dev->version = 3; - break; - } - switch (udev->descriptor.idProduct) { - case DEVICE_ID_4MOTOR_SERVO_20: - case DEVICE_ID_4MOTOR_SERVO_30: - dev->quad_servo = 1; - break; - case DEVICE_ID_1MOTOR_SERVO_20: - case DEVICE_ID_1MOTOR_SERVO_30: - dev->quad_servo = 0; - break; - } - + dev->type = id->driver_info; usb_set_intfdata(interface, dev); device_create_file(&interface->dev, &dev_attr_servo0); - if (dev->quad_servo) { + if (dev->type & SERVO_COUNT_QUAD) { device_create_file(&interface->dev, &dev_attr_servo1); device_create_file(&interface->dev, &dev_attr_servo2); device_create_file(&interface->dev, &dev_attr_servo3); } dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", - dev->quad_servo ? 4 : 1, dev->version); - if (dev->version == 2) + dev->type & SERVO_COUNT_QUAD ? 4 : 1, + dev->type & SERVO_VERSION_30 ? 3 : 2); + + if(!(dev->type & SERVO_VERSION_30)) dev_info(&interface->dev, "WARNING: v2.0 not tested! Please report if it works.\n"); @@ -279,7 +287,7 @@ usb_set_intfdata(interface, NULL); device_remove_file(&interface->dev, &dev_attr_servo0); - if (dev->quad_servo) { + if (dev->type & SERVO_COUNT_QUAD) { device_remove_file(&interface->dev, &dev_attr_servo1); device_remove_file(&interface->dev, &dev_attr_servo2); device_remove_file(&interface->dev, &dev_attr_servo3); @@ -287,10 +295,11 @@ usb_put_dev(dev->udev); - kfree(dev); - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", - dev->quad_servo ? 4 : 1, dev->version); + dev->type & SERVO_COUNT_QUAD ? 4 : 1, + dev->type & SERVO_VERSION_30 ? 3 : 2); + + kfree(dev); } static struct usb_driver servo_driver = { @@ -304,7 +313,7 @@ static int __init phidget_servo_init(void) { - int retval = 0; + int retval; retval = usb_register(&servo_driver); if (retval) diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c --- a/drivers/usb/misc/usbtest.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/misc/usbtest.c 2004-06-20 13:00:26 -07:00 @@ -459,8 +459,8 @@ * or remote wakeup (which needs human interaction). */ -static int realworld = 1; -MODULE_PARM (realworld, "i"); +static unsigned realworld = 1; +module_param (realworld, uint, 0); MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance"); static int get_altsetting (struct usbtest_dev *dev) @@ -1808,17 +1808,17 @@ /*-------------------------------------------------------------------------*/ -static int force_interrupt = 0; -MODULE_PARM (force_interrupt, "i"); +static unsigned force_interrupt = 0; +module_param (force_interrupt, uint, 0); MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt"); #ifdef GENERIC -static int vendor; -MODULE_PARM (vendor, "h"); +static unsigned short vendor; +module_param(vendor, ushort, 0); MODULE_PARM_DESC (vendor, "vendor code (from usb-if)"); -static int product; -MODULE_PARM (product, "h"); +static unsigned short product; +module_param(product, ushort, 0); MODULE_PARM_DESC (product, "product code (from vendor)"); #endif diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h --- a/drivers/usb/net/pegasus.h 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/net/pegasus.h 2004-06-20 13:00:26 -07:00 @@ -121,6 +121,7 @@ #define VENDOR_ADMTEK 0x07a6 #define VENDOR_AEILAB 0x3334 #define VENDOR_ALLIEDTEL 0x07c9 +#define VENDOR_ATEN 0x0557 #define VENDOR_BELKIN 0x050d #define VENDOR_BILLIONTON 0x08dd #define VENDOR_COMPAQ 0x049f @@ -149,6 +150,8 @@ #else /* PEGASUS_DEV */ PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "ATEN USB Ethernet UC-110T", VENDOR_ATEN, 0x2007, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c, DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/net/rtl8150.c 2004-06-20 13:00:25 -07:00 @@ -398,6 +398,21 @@ usb_unlink_urb(dev->ctrl_urb); } +static inline struct sk_buff *pull_skb(rtl8150_t *dev) +{ + struct sk_buff *skb; + int i; + + for (i = 0; i < RX_SKB_POOL_SIZE; i++) { + if (dev->rx_skb_pool[i]) { + skb = dev->rx_skb_pool[i]; + dev->rx_skb_pool[i] = NULL; + return skb; + } + } + return NULL; +} + static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) { rtl8150_t *dev; @@ -601,21 +616,6 @@ for (i = 0; i < RX_SKB_POOL_SIZE; i++) if (dev->rx_skb_pool[i]) dev_kfree_skb(dev->rx_skb_pool[i]); -} - -static inline struct sk_buff *pull_skb(rtl8150_t *dev) -{ - struct sk_buff *skb; - int i; - - for (i = 0; i < RX_SKB_POOL_SIZE; i++) { - if (dev->rx_skb_pool[i]) { - skb = dev->rx_skb_pool[i]; - dev->rx_skb_pool[i] = NULL; - return skb; - } - } - return NULL; } static int enable_net_traffic(rtl8150_t * dev) diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c --- a/drivers/usb/net/usbnet.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/net/usbnet.c 2004-06-20 13:00:24 -07:00 @@ -104,6 +104,8 @@ * disconnect; other cleanups. (db) Flush net1080 fifos * after several sequential framing errors. (Johannes Erdfelt) * 22-aug-2003 AX8817X support (Dave Hollis). + * 14-jun-2004 Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan + * (Neil Bortnak) * *-------------------------------------------------------------------------*/ @@ -1157,6 +1159,7 @@ status = get_ethernet_addr (dev, info->ether); if (status < 0) { + usb_set_intfdata(info->data, NULL); usb_driver_release_interface (&usbnet_driver, info->data); return status; } @@ -3203,6 +3206,10 @@ }, { // ATEN UC210T USB_DEVICE (0x0557, 0x2009), + .driver_info = (unsigned long) &ax8817x_info, +}, { + // Buffalo LUA-U2-KTX + USB_DEVICE (0x0411, 0x003d), .driver_info = (unsigned long) &ax8817x_info, }, #endif diff -Nru a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c --- a/drivers/usb/serial/bus.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/serial/bus.c 2004-06-20 13:00:26 -07:00 @@ -78,8 +78,8 @@ minor = port->number; tty_register_device (usb_serial_tty_driver, minor, dev); dev_info(&port->serial->dev->dev, - "%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n", - driver->name, minor, minor); + "%s converter now attached to ttyUSB%d\n", + driver->name, minor); exit: return retval; diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c --- a/drivers/usb/serial/ftdi_sio.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/serial/ftdi_sio.c 2004-06-20 13:00:25 -07:00 @@ -1022,7 +1022,7 @@ } -static int get_serial_info(struct usb_serial_port * port, struct serial_struct * retinfo) +static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct serial_struct tmp; @@ -1039,7 +1039,7 @@ } /* get_serial_info */ -static int set_serial_info(struct usb_serial_port * port, struct serial_struct * newinfo) +static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo) { /* set_serial_info */ struct ftdi_private *priv = usb_get_serial_port_data(port); struct serial_struct new_serial; @@ -1504,6 +1504,7 @@ if (status) { err("%s - failed submitting write urb, error %d", __FUNCTION__, status); count = status; + kfree (buffer); } /* we are done with this urb, so let the host driver @@ -2042,7 +2043,7 @@ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ dbg("%s TIOCMBIS", __FUNCTION__); - if (get_user(mask, (unsigned long *) arg)) + if (get_user(mask, (unsigned long __user *) arg)) return -EFAULT; if (mask & TIOCM_DTR){ if ((ret = set_dtr(port, HIGH)) < 0) { @@ -2061,7 +2062,7 @@ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ dbg("%s TIOCMBIC", __FUNCTION__); - if (get_user(mask, (unsigned long *) arg)) + if (get_user(mask, (unsigned long __user *) arg)) return -EFAULT; if (mask & TIOCM_DTR){ if ((ret = set_dtr(port, LOW)) < 0){ @@ -2088,10 +2089,10 @@ */ case TIOCGSERIAL: /* gets serial port data */ - return get_serial_info(port, (struct serial_struct *) arg); + return get_serial_info(port, (struct serial_struct __user *) arg); case TIOCSSERIAL: /* sets serial port data */ - return set_serial_info(port, (struct serial_struct *) arg); + return set_serial_info(port, (struct serial_struct __user *) arg); /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c --- a/drivers/usb/serial/io_edgeport.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/serial/io_edgeport.c 2004-06-20 13:00:23 -07:00 @@ -1705,7 +1705,7 @@ * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. *****************************************************************************/ -static int get_lsr_info(struct edgeport_port *edge_port, unsigned int *value) +static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value) { unsigned int result = 0; @@ -1720,7 +1720,7 @@ return 0; } -static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int *value) +static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value) { unsigned int result = 0; struct tty_struct *tty = edge_port->port->tty; @@ -1790,7 +1790,7 @@ return result; } -static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo) +static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -1812,7 +1812,6 @@ // tmp.hub6 = state->hub6; // tmp.io_type = state->io_type; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; return 0; @@ -1838,17 +1837,17 @@ // return number of bytes available case TIOCINQ: dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number); - return get_number_bytes_avail(edge_port, (unsigned int *) arg); + return get_number_bytes_avail(edge_port, (unsigned int __user *) arg); break; case TIOCSERGETLSR: dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number); - return get_lsr_info(edge_port, (unsigned int *) arg); + return get_lsr_info(edge_port, (unsigned int __user *) arg); return 0; case TIOCGSERIAL: dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number); - return get_serial_info(edge_port, (struct serial_struct *) arg); + return get_serial_info(edge_port, (struct serial_struct __user *) arg); case TIOCSSERIAL: dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number); @@ -1893,7 +1892,7 @@ icount.buf_overrun = cnow.buf_overrun; dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, icount.rx, icount.tx ); - if (copy_to_user((void *)arg, &icount, sizeof(icount))) + if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) return -EFAULT; return 0; } diff -Nru a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c --- a/drivers/usb/serial/io_ti.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/serial/io_ti.c 2004-06-20 13:00:26 -07:00 @@ -2428,7 +2428,7 @@ return result; } -static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct * retinfo) +static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -2477,7 +2477,7 @@ case TIOCGSERIAL: dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number); - return get_serial_info(edge_port, (struct serial_struct *) arg); + return get_serial_info(edge_port, (struct serial_struct __user *) arg); break; case TIOCSSERIAL: @@ -2510,7 +2510,7 @@ case TIOCGICOUNT: dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, edge_port->icount.rx, edge_port->icount.tx); - if (copy_to_user((void *)arg, &edge_port->icount, sizeof(edge_port->icount))) + if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount))) return -EFAULT; return 0; } diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c --- a/drivers/usb/serial/kl5kusb105.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/serial/kl5kusb105.c 2004-06-20 13:00:24 -07:00 @@ -926,6 +926,7 @@ unsigned int cmd, unsigned long arg) { struct klsi_105_private *priv = usb_get_serial_port_data(port); + void __user *user_arg = (void __user *)arg; dbg("%scmd=0x%x", __FUNCTION__, cmd); @@ -948,13 +949,12 @@ dbg("%s - TCGETS data faked/incomplete", __FUNCTION__); - retval = verify_area(VERIFY_WRITE, (void *)arg, + retval = verify_area(VERIFY_WRITE, user_arg, sizeof(struct termios)); - if (retval) - return(retval); + return retval; - if (kernel_termios_to_user_termios((struct termios *)arg, + if (kernel_termios_to_user_termios((struct termios __user *)arg, &priv->termios)) return -EFAULT; return(0); @@ -965,14 +965,13 @@ dbg("%s - TCSETS not handled", __FUNCTION__); - retval = verify_area(VERIFY_READ, (void *)arg, + retval = verify_area(VERIFY_READ, user_arg, sizeof(struct termios)); - if (retval) - return(retval); + return retval; if (user_termios_to_kernel_termios(&priv->termios, - (struct termios *)arg)) + (struct termios __user *)arg)) return -EFAULT; klsi_105_set_termios(port, &priv->termios); return(0); diff -Nru a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c --- a/drivers/usb/serial/kobil_sct.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/serial/kobil_sct.c 2004-06-20 13:00:25 -07:00 @@ -643,6 +643,7 @@ unsigned char *transfer_buffer; int transfer_buffer_length = 8; char *settings; + void __user *user_arg = (void __user *)arg; priv = usb_get_serial_port_data(port); if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) { @@ -652,12 +653,12 @@ switch (cmd) { case TCGETS: // 0x5401 - result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct termios)); + result = verify_area(VERIFY_WRITE, user_arg, sizeof(struct termios)); if (result) { dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number); return(result); } - if (kernel_termios_to_user_termios((struct termios *)arg, + if (kernel_termios_to_user_termios((struct termios __user *)arg, &priv->internal_termios)) return -EFAULT; return 0; @@ -667,13 +668,13 @@ dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); return -ENOTTY; } - result = verify_area(VERIFY_READ, (void *)arg, sizeof(struct termios)); + result = verify_area(VERIFY_READ, user_arg, sizeof(struct termios)); if (result) { dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number); return result; } if (user_termios_to_kernel_termios(&priv->internal_termios, - (struct termios *)arg)) + (struct termios __user *)arg)) return -EFAULT; settings = (unsigned char *) kmalloc(50, GFP_KERNEL); diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/serial/visor.c 2004-06-20 13:00:24 -07:00 @@ -247,6 +247,8 @@ .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { }, /* optional parameter entry */ { } /* Terminating entry */ }; @@ -290,6 +292,7 @@ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) }, { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) }, { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) }, { }, /* optional parameter entry */ { } /* Terminating entry */ }; @@ -515,6 +518,7 @@ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __FUNCTION__, status); count = status; + kfree (buffer); } else { bytes_out += count; } @@ -795,7 +799,7 @@ dev_err(dev, "%s - error %d getting connection info\n", __FUNCTION__, retval); else - usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer); + usb_serial_debug_data (__FILE__, __FUNCTION__, retval, transfer_buffer); kfree (transfer_buffer); return 0; @@ -881,18 +885,19 @@ /* Only do this endpoint hack for the Handspring devices with * interrupt in endpoints, which for now are the Treo devices. */ - if ((serial->dev->descriptor.idVendor != HANDSPRING_VENDOR_ID) || + if (!((serial->dev->descriptor.idVendor == HANDSPRING_VENDOR_ID) || + (serial->dev->descriptor.idVendor == KYOCERA_VENDOR_ID)) || (serial->num_interrupt_in == 0)) return 0; dbg("%s", __FUNCTION__); /* - * It appears that Treos want to use the 1st interrupt endpoint to - * communicate with the 2nd bulk out endpoint, so let's swap the 1st - * and 2nd bulk in and interrupt endpoints. Note that swapping the - * bulk out endpoints would break lots of apps that want to communicate - * on the second port. + * It appears that Treos and Kyoceras want to use the + * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, + * so let's swap the 1st and 2nd bulk in and interrupt endpoints. + * Note that swapping the bulk out endpoints would break lots of + * apps that want to communicate on the second port. */ #define COPY_PORT(dest, src) \ dest->read_urb = src->read_urb; \ diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h --- a/drivers/usb/serial/visor.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/serial/visor.h 2004-06-20 13:00:25 -07:00 @@ -55,6 +55,9 @@ #define ACEECA_VENDOR_ID 0x4766 #define ACEECA_MEZ1000_ID 0x0001 +#define KYOCERA_VENDOR_ID 0x0C88 +#define KYOCERA_7135_ID 0x0021 + /**************************************************************************** * Handspring Visor Vendor specific request codes (bRequest values) * A big thank you to Handspring for providing the following information. diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c --- a/drivers/usb/serial/whiteheat.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/serial/whiteheat.c 2004-06-20 13:00:24 -07:00 @@ -835,6 +835,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) { struct serial_struct serstruct; + void __user *user_arg = (void __user *)arg; dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd); @@ -851,13 +852,13 @@ serstruct.close_delay = CLOSING_DELAY; serstruct.closing_wait = CLOSING_DELAY; - if (copy_to_user((void *)arg, &serstruct, sizeof(serstruct))) + if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) return -EFAULT; break; case TIOCSSERIAL: - if (copy_from_user(&serstruct, (void *)arg, sizeof(serstruct))) + if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) return -EFAULT; /* diff -Nru a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig --- a/drivers/usb/storage/Kconfig 2004-06-20 13:00:26 -07:00 +++ b/drivers/usb/storage/Kconfig 2004-06-20 13:00:26 -07:00 @@ -23,6 +23,28 @@ Say Y here in order to have the USB Mass Storage code generate verbose debugging messages. +config USB_STORAGE_RW_DETECT + bool "USB Mass Storage Write-Protected Media Detection (EXPERIMENTAL)" + depends on USB_STORAGE && EXPERIMENTAL + help + Say Y here in order to have the USB Mass Storage code indicate to + the SCSI layer that using MODE SENSE(6) and MODE SENSE(10) to + determine if the media is write-protected is a good thing to do. + + Many devices have historically had trouble with these commands, + hence the default 2.6.x behavior has been to suppress their use. + 2.4.x used these commands with (at best) mixed results, often + crashing the firmware of the device. However, the SCSI layer now + issues these commands in a manner more consistent with other + "popular" OSes, in an attempt to improve compatibility. + + Saying Y here allows these commands to be sent to a USB device. + If you find a device this doesn't work for, switch to N and let + us know at usb-storage@lists.one-eyed-alien.net + + If you say N here, the kernel will assume that all disk-like USB + devices are write-enabled. + config USB_STORAGE_DATAFAB bool "Datafab Compact Flash Reader support (EXPERIMENTAL)" depends on USB_STORAGE && EXPERIMENTAL diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c --- a/drivers/usb/storage/jumpshot.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/storage/jumpshot.c 2004-06-20 13:00:23 -07:00 @@ -471,7 +471,7 @@ // build the reply // - ((u32 *) ptr)[0] = cpu_to_be32(info->sectors); + ((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); ((u32 *) ptr)[1] = cpu_to_be32(info->ssize); usb_stor_set_xfer_buf(ptr, 8, srb); diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/storage/scsiglue.c 2004-06-20 13:00:24 -07:00 @@ -48,13 +48,13 @@ #include "usb.h" #include "debug.h" #include "transport.h" +#include "protocol.h" #include #include #include #include - /*********************************************************************** * Host functions ***********************************************************************/ @@ -68,10 +68,13 @@ { /* * Set default bflags. These can be overridden for individual - * models and vendors via the scsi devinfo mechanism. + * models and vendors via the scsi devinfo mechanism. The only + * flag we need is to force 36-byte INQUIRYs; we don't use any + * of the extra data and many devices choke if asked for more or + * less than 36 bytes. */ - sdev->sdev_bflags = (BLIST_MS_SKIP_PAGE_08 | BLIST_MS_SKIP_PAGE_3F | - BLIST_USE_10_BYTE_MS); + sdev->sdev_bflags = BLIST_INQUIRY_36; + return 0; } @@ -95,11 +98,48 @@ * reduce the maximum transfer size to 64 KB = 128 sectors. */ #define USB_VENDOR_ID_GENESYS 0x05e3 // Needs a standard location + if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS && - us->pusb_dev->speed == USB_SPEED_HIGH) + us->pusb_dev->speed == USB_SPEED_HIGH && + sdev->request_queue->max_sectors > 128) blk_queue_max_sectors(sdev->request_queue, 128); - /* this is to satisify the compiler, tho I don't think the + /* We can't put these settings in slave_alloc() because that gets + * called before the device type is known. Consequently these + * settings can't be overridden via the scsi devinfo mechanism. */ + if (sdev->type == TYPE_DISK) { + + /* Disk-type devices use MODE SENSE(6) if the protocol + * (SubClass) is Transparent SCSI, otherwise they use + * MODE SENSE(10). */ + if (us->subclass != US_SC_SCSI) + sdev->use_10_for_ms = 1; + + /* Many disks only accept MODE SENSE transfer lengths of + * 192 bytes (that's what Windows uses). */ + sdev->use_192_bytes_for_3f = 1; + + /* A number of devices have problems with MODE SENSE for + * page x08, so we will skip it. */ + sdev->skip_ms_page_8 = 1; + +#ifndef CONFIG_USB_STORAGE_RW_DETECT + /* Some devices may not like MODE SENSE with page=0x3f. + * Now that we're using 192-byte transfers this may no + * longer be a problem. So this will be a configuration + * option. */ + sdev->skip_ms_page_3f = 1; +#endif + + } else { + + /* Non-disk-type devices don't need to blacklist any pages + * or to force 192-byte transfer lengths for MODE SENSE. + * But they do need to use MODE SENSE(10). */ + sdev->use_10_for_ms = 1; + } + + /* this is to satisfy the compiler, tho I don't think the * return code is ever checked anywhere. */ return 0; } @@ -408,6 +448,9 @@ /* emulated HBA */ .emulated = TRUE, + + /* we do our own delay after a device or bus reset */ + .skip_settle_delay = 1, /* sysfs device attributes */ .sdev_attrs = sysfs_device_attr_list, diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/usb/storage/transport.c 2004-06-20 13:00:24 -07:00 @@ -908,26 +908,29 @@ USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, 1, HZ); + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", + result, us->iobuf[0]); + + /* if we have a successful request, return the result */ + if (result == 1) + return us->iobuf[0]; + /* * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices * (regardless of if they stall or not). */ - if (result < 0) { + if (result == -EPIPE) { usb_stor_clear_halt(us, us->recv_bulk_pipe); usb_stor_clear_halt(us, us->send_bulk_pipe); + /* return the default -- no LUNs */ + return 0; } - US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", - result, us->iobuf[0]); - - /* if we have a successful request, return the result */ - if (result == 1) - return us->iobuf[0]; - - /* return the default -- no LUNs */ - return 0; + /* An answer or a STALL are the only valid responses. If we get + * something else, return an indication of error */ + return -1; } int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) @@ -1110,10 +1113,11 @@ goto Done; } - /* long wait for reset, so unlock to allow disconnects */ - up(&us->dev_semaphore); - msleep(6000); - down(&us->dev_semaphore); + /* Give the device some time to recover from the reset, + * but don't delay disconnect processing. */ + wait_event_interruptible_timeout(us->dev_reset_wait, + test_bit(US_FLIDX_DISCONNECTING, &us->flags), + HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("Reset interrupted by disconnect\n"); goto Done; diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h --- a/drivers/usb/storage/unusual_devs.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/storage/unusual_devs.h 2004-06-20 13:00:25 -07:00 @@ -207,7 +207,7 @@ UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0205, "Shuttle", "eUSB MMC Adapter", - US_SC_SCSI, US_PR_CB, NULL, + US_SC_SCSI, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN), UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200, @@ -359,13 +359,19 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", "Digital Camera EX-20 DSC", - US_SC_8070, US_PR_CBI, NULL, 0 ), + US_SC_8070, US_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, "LaCie", "USB Hard Disk", US_SC_RBC, US_PR_CB, NULL, 0 ), +/* Submitted by Jol Bourquard */ +UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, + "In-System", + "PyroGate External CD-ROM Enclosure (FCD-523)", + US_SC_SCSI, US_PR_BULK, NULL, 0 ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, "In-System", @@ -396,8 +402,8 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, "Lexar", "Jumpshot USB CF Reader", - US_SC_DEVICE, US_PR_JUMPSHOT, NULL, - US_FL_MODE_XLATE ), + US_SC_SCSI, US_PR_JUMPSHOT, NULL, + US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE ), #endif /* Reported by Blake Matheny */ @@ -628,19 +634,13 @@ * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have * bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB). * So don't remove the US_PR_CB override! + * - Cameras with bcdDevice=0x9009 require the US_SC_8070 override. */ -UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009, +UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, "Casio", "QV DigitalCamera", - US_SC_DEVICE, US_PR_CB, NULL, + US_SC_8070, US_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), - -/* Later Casio cameras apparently tell the truth */ -UNUSUAL_DEV( 0x07cf, 0x1001, 0x9010, 0x9999, - "Casio", - "QV DigitalCamera", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_INQUIRY ), /* Submitted by Hartmut Wahl */ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/usb/storage/usb.c 2004-06-20 13:00:23 -07:00 @@ -266,6 +266,7 @@ static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; + struct Scsi_Host *host = us->host; lock_kernel(); @@ -283,19 +284,21 @@ complete(&(us->notify)); for(;;) { - struct Scsi_Host *host; US_DEBUGP("*** thread sleeping.\n"); if(down_interruptible(&us->sema)) break; US_DEBUGP("*** thread awakened.\n"); + /* lock the device pointers */ + down(&(us->dev_semaphore)); + /* if us->srb is NULL, we are being asked to exit */ if (us->srb == NULL) { US_DEBUGP("-- exit command received\n"); + up(&(us->dev_semaphore)); break; } - host = us->srb->device->host; /* lock access to the state */ scsi_lock(host); @@ -306,23 +309,20 @@ goto SkipForAbort; } - /* set the state and release the lock */ - us->sm_state = US_STATE_RUNNING; - scsi_unlock(host); - - /* lock the device pointers */ - down(&(us->dev_semaphore)); - /* don't do anything if we are disconnecting */ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("No command during disconnect\n"); - us->srb->result = DID_BAD_TARGET << 16; + goto SkipForDisconnect; } + /* set the state and release the lock */ + us->sm_state = US_STATE_RUNNING; + scsi_unlock(host); + /* reject the command if the direction indicator * is UNKNOWN */ - else if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) { + if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) { US_DEBUGP("UNKNOWN data direction\n"); us->srb->result = DID_ERROR << 16; } @@ -362,9 +362,6 @@ us->proto_handler(us->srb, us); } - /* unlock the device pointers */ - up(&(us->dev_semaphore)); - /* lock access to the state */ scsi_lock(host); @@ -374,7 +371,7 @@ us->srb->result); us->srb->scsi_done(us->srb); } else { - SkipForAbort: +SkipForAbort: US_DEBUGP("scsi command aborted\n"); } @@ -387,9 +384,13 @@ complete(&(us->notify)); /* empty the queue, reset the state, and release the lock */ +SkipForDisconnect: us->srb = NULL; us->sm_state = US_STATE_IDLE; scsi_unlock(host); + + /* unlock the device pointers */ + up(&(us->dev_semaphore)); } /* for (;;) */ /* notify the exit routine that we're actually exiting now @@ -423,10 +424,8 @@ us->pusb_intf = intf; us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - /* Store our private data in the interface and increment the - * device's reference count */ + /* Store our private data in the interface */ usb_set_intfdata(intf, us); - usb_get_dev(us->pusb_dev); /* Allocate the device-related DMA-mapped buffers */ us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr), @@ -754,8 +753,14 @@ down(&us->dev_semaphore); /* For bulk-only devices, determine the max LUN value */ - if (us->protocol == US_PR_BULK) - us->max_lun = usb_stor_Bulk_max_lun(us); + if (us->protocol == US_PR_BULK) { + p = usb_stor_Bulk_max_lun(us); + if (p < 0) { + up(&us->dev_semaphore); + return p; + } + us->max_lun = p; + } /* Just before we start our control thread, initialize * the device if it needs initialization */ @@ -764,19 +769,6 @@ up(&us->dev_semaphore); - /* Start up our control thread */ - us->sm_state = US_STATE_IDLE; - p = kernel_thread(usb_stor_control_thread, us, CLONE_VM); - if (p < 0) { - printk(KERN_WARNING USB_STORAGE - "Unable to start control thread\n"); - return p; - } - us->pid = p; - - /* Wait for the thread to start */ - wait_for_completion(&(us->notify)); - /* * Since this is a new device, we need to register a SCSI * host definition with the higher SCSI layers. @@ -784,69 +776,61 @@ us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us)); if (!us->host) { printk(KERN_WARNING USB_STORAGE - "Unable to register the scsi host\n"); + "Unable to allocate the scsi host\n"); return -EBUSY; } /* Set the hostdata to prepare for scanning */ us->host->hostdata[0] = (unsigned long) us; - return 0; -} - -/* Dissociate from the USB device */ -static void dissociate_dev(struct us_data *us) -{ - US_DEBUGP("-- %s\n", __FUNCTION__); - down(&us->dev_semaphore); - - /* Free the device-related DMA-mapped buffers */ - if (us->cr) { - usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, - us->cr_dma); - us->cr = NULL; - } - if (us->iobuf) { - usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, - us->iobuf_dma); - us->iobuf = NULL; + /* Start up our control thread */ + us->sm_state = US_STATE_IDLE; + p = kernel_thread(usb_stor_control_thread, us, CLONE_VM); + if (p < 0) { + printk(KERN_WARNING USB_STORAGE + "Unable to start control thread\n"); + return p; } + us->pid = p; - /* Remove our private data from the interface and decrement the - * device's reference count */ - usb_set_intfdata(us->pusb_intf, NULL); - usb_put_dev(us->pusb_dev); + /* Wait for the thread to start */ + wait_for_completion(&(us->notify)); - us->pusb_dev = NULL; - us->pusb_intf = NULL; - up(&us->dev_semaphore); + return 0; } -/* Release all our static and dynamic resources */ +/* Release all our dynamic resources */ void usb_stor_release_resources(struct us_data *us) { - /* - * The host must already have been removed - * and dissociate_dev() must have been called. - */ - - /* Finish the SCSI host removal sequence */ - if (us->host) { - us->host->hostdata[0] = 0; - scsi_host_put(us->host); - } + US_DEBUGP("-- %s\n", __FUNCTION__); - /* Kill the control thread - * - * Enqueue the command, wake up the thread, and wait for - * notification that it has exited. + /* Kill the control thread. The SCSI host must already have been + * removed so it won't try to queue any more commands. */ if (us->pid) { + + /* Wait for the thread to be idle */ + down(&us->dev_semaphore); US_DEBUGP("-- sending exit command to thread\n"); BUG_ON(us->sm_state != US_STATE_IDLE); + + /* If the SCSI midlayer queued a final command just before + * scsi_remove_host() was called, us->srb might not be + * NULL. We can overwrite it safely, because the midlayer + * will not wait for the command to finish. Also the + * control thread will already have been awakened. + * That's okay, an extra up() on us->sema won't hurt. + * + * Enqueue the command, wake up the thread, and wait for + * notification that it has exited. + */ + scsi_lock(us->host); us->srb = NULL; - up(&(us->sema)); - wait_for_completion(&(us->notify)); + scsi_unlock(us->host); + up(&us->dev_semaphore); + + up(&us->sema); + wait_for_completion(&us->notify); } /* Call the destructor routine, if it exists */ @@ -855,15 +839,36 @@ us->extra_destructor(us->extra); } + /* Finish the host removal sequence */ + if (us->host) + scsi_host_put(us->host); + /* Free the extra data and the URB */ if (us->extra) kfree(us->extra); if (us->current_urb) usb_free_urb(us->current_urb); +} + +/* Dissociate from the USB device */ +static void dissociate_dev(struct us_data *us) +{ + US_DEBUGP("-- %s\n", __FUNCTION__); + + /* Free the device-related DMA-mapped buffers */ + if (us->cr) + usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, + us->cr_dma); + if (us->iobuf) + usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, + us->iobuf_dma); + + /* Remove our private data from the interface */ + usb_set_intfdata(us->pusb_intf, NULL); + /* Free the structure itself */ kfree(us); - US_DEBUGP("-- %s finished\n", __FUNCTION__); } /* Probe to see if we can drive a newly-connected USB device */ @@ -889,6 +894,7 @@ init_MUTEX(&(us->dev_semaphore)); init_MUTEX_LOCKED(&(us->sema)); init_completion(&(us->notify)); + init_waitqueue_head(&us->dev_reset_wait); /* Associate the us_data structure with the USB device */ result = associate_dev(us, intf); @@ -959,8 +965,8 @@ /* We come here if there are any problems */ BadDevice: US_DEBUGP("storage_probe() failed\n"); - dissociate_dev(us); usb_stor_release_resources(us); + dissociate_dev(us); return result; } @@ -971,20 +977,20 @@ US_DEBUGP("storage_disconnect() called\n"); - /* Prevent new USB transfers and stop the current command */ + /* Prevent new USB transfers, stop the current command, and + * interrupt a device-reset delay */ set_bit(US_FLIDX_DISCONNECTING, &us->flags); usb_stor_stop_transport(us); + wake_up(&us->dev_reset_wait); - /* Dissociate from the USB device */ - dissociate_dev(us); - + /* Wait for the current command to finish, then remove the host */ + down(&us->dev_semaphore); + up(&us->dev_semaphore); scsi_remove_host(us->host); - /* TODO: somehow, wait for the device to - * be 'idle' (tasklet completion) */ - - /* Release all our other resources */ + /* Wait for everything to become idle and release all our resources */ usb_stor_release_resources(us); + dissociate_dev(us); } /*********************************************************************** @@ -1017,47 +1023,6 @@ */ US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; - -#if 0 - /* While there are still virtual hosts, unregister them - * Note that it's important to do this completely before removing - * the structures because of possible races with the /proc - * interface - */ - for (next = us_list; next; next = next->next) { - US_DEBUGP("-- calling scsi_unregister_host()\n"); - scsi_unregister_host(&usb_stor_host_template); - } - - /* While there are still structures, free them. Note that we are - * now race-free, since these structures can no longer be accessed - * from either the SCSI command layer or the /proc interface - */ - while (us_list) { - /* keep track of where the next one is */ - next = us_list->next; - - /* If there's extra data in the us_data structure then - * free that first */ - if (us_list->extra) { - /* call the destructor routine, if it exists */ - if (us_list->extra_destructor) { - US_DEBUGP("-- calling extra_destructor()\n"); - us_list->extra_destructor(us_list->extra); - } - - /* destroy the extra data */ - US_DEBUGP("-- freeing the data structure\n"); - kfree(us_list->extra); - } - - /* free the structure itself */ - kfree (us_list); - - /* advance the list pointer */ - us_list = next; - } -#endif } module_init(usb_stor_init); diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h --- a/drivers/usb/storage/usb.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/usb/storage/usb.h 2004-06-20 13:00:25 -07:00 @@ -158,9 +158,10 @@ dma_addr_t cr_dma; /* buffer DMA addresses */ dma_addr_t iobuf_dma; - /* mutual exclusion structures */ + /* mutual exclusion and synchronization structures */ struct semaphore sema; /* to sleep thread on */ - struct completion notify; /* thread begin/end */ + struct completion notify; /* thread begin/end */ + wait_queue_head_t dev_reset_wait; /* wait during reset */ /* subdriver information */ void *extra; /* Any extra data */ diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig --- a/drivers/video/Kconfig 2004-06-20 13:00:23 -07:00 +++ b/drivers/video/Kconfig 2004-06-20 13:00:23 -07:00 @@ -432,6 +432,11 @@ To compile this driver as a module, choose M here: the module will be called rivafb. +config FB_RIVA_I2C + bool "Enable DDC Support" + depends on FB_RIVA && I2C + help + config FB_I810 tristate "Intel 810/815 support (EXPERIMENTAL)" depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI diff -Nru a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c --- a/drivers/video/aty/radeon_accel.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/video/aty/radeon_accel.c 2004-06-20 13:00:25 -07:00 @@ -38,8 +38,8 @@ return; } - vxres = info->var.xres; - vyres = info->var.yres; + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; memcpy(&modded, region, sizeof(struct fb_fillrect)); @@ -104,8 +104,8 @@ return; } - vxres = info->var.xres; - vyres = info->var.yres; + vxres = info->var.xres_virtual; + vyres = info->var.yres_virtual; if(!modded.width || !modded.height || modded.sx >= vxres || modded.sy >= vyres || diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c --- a/drivers/video/aty/radeon_base.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/video/aty/radeon_base.c 2004-06-20 13:00:24 -07:00 @@ -858,6 +858,7 @@ if (rinfo->asleep) return 0; + radeon_fifo_wait(2); OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel / 8) & ~7); return 0; @@ -882,11 +883,12 @@ if (!rinfo->is_mobility) return -EINVAL; - rc = get_user(value, (__u32*)arg); + rc = get_user(value, (__u32 __user *)arg); if (rc) return rc; + radeon_fifo_wait(2); if (value & 0x01) { tmp = INREG(LVDS_GEN_CNTL); @@ -926,7 +928,7 @@ if (CRTC_CRT_ON & tmp) value |= 0x02; - return put_user(value, (__u32*)arg); + return put_user(value, (__u32 __user *)arg); default: return -EINVAL; } @@ -963,6 +965,7 @@ break; } + radeon_fifo_wait(1); switch (rinfo->mon1_type) { case MT_LCD: OUTREG(LVDS_GEN_CNTL, val2); @@ -1021,6 +1024,7 @@ if (!rinfo->asleep) { u32 dac_cntl2, vclk_cntl = 0; + radeon_fifo_wait(9); if (rinfo->is_mobility) { vclk_cntl = INPLL(VCLK_ECP_CNTL); OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb); @@ -1112,6 +1116,8 @@ { int i; + radeon_fifo_wait(20); + /* Workaround from XFree */ if (rinfo->is_mobility) { /* A temporal workaround for the occational blanking on certain laptop panels. @@ -1198,6 +1204,8 @@ { struct radeonfb_info *rinfo = (struct radeonfb_info *)data; + radeon_fifo_wait(3); + OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); if (rinfo->pending_pixclks_cntl) { OUTPLL(PIXCLKS_CNTL, rinfo->pending_pixclks_cntl); @@ -1222,6 +1230,7 @@ radeon_screen_blank(rinfo, VESA_POWERDOWN); + radeon_fifo_wait(31); for (i=0; i<10; i++) OUTREG(common_regs[i].reg, common_regs[i].val); @@ -1249,6 +1258,7 @@ radeon_write_pll_regs(rinfo, mode); if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { + radeon_fifo_wait(10); OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); @@ -1288,6 +1298,7 @@ radeon_screen_blank(rinfo, VESA_NO_BLANKING); + radeon_fifo_wait(2); OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); return; @@ -1696,7 +1707,7 @@ -static ssize_t radeonfb_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t radeonfb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; @@ -1723,7 +1734,7 @@ return count; } -static ssize_t radeonfb_write(struct file *file, const char *buf, size_t count, +static ssize_t radeonfb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -1864,6 +1875,7 @@ del_timer_sync(&rinfo->lvds_timer); lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON); + radeon_fifo_wait(3); if (on && (level > BACKLIGHT_OFF)) { lvds_gen_cntl |= LVDS_DIGON; if (!(lvds_gen_cntl & LVDS_ON)) { @@ -2136,6 +2148,7 @@ u32 tom = INREG(NB_TOM); tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); + radeon_fifo_wait(6); OUTREG(MC_FB_LOCATION, tom); OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c --- a/drivers/video/console/fbcon.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/video/console/fbcon.c 2004-06-20 13:00:25 -07:00 @@ -601,8 +601,9 @@ int display_fg = (*default_mode)->vc_num; int logo = 1, rows, cols, charcnt = 256; unsigned short *save = NULL, *r, *q; + int cap = info->flags; - if (vc->vc_num != display_fg || (info->flags & FBINFO_FLAG_MODULE) || + if (vc->vc_num != display_fg || (info->flags & FBINFO_MODULE) || (info->fix.type == FB_TYPE_TEXT)) logo = 0; @@ -635,10 +636,10 @@ rows = info->var.yres / vc->vc_font.height; vc_resize(vc->vc_num, cols, rows); - if (info->var.accel_flags) - p->scrollmode = SCROLL_YNOMOVE; - else - p->scrollmode = SCROLL_YREDRAW; + if ((cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED)) + p->scrollmode = SCROLL_ACCEL; + else /* default to something safe */ + p->scrollmode = SCROLL_REDRAW; /* * ++guenther: console.c:vc_allocate() relies on initializing @@ -1245,7 +1246,7 @@ { struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; - int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); + int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; if (!info->fbops->fb_blank && console_blanked) return 0; @@ -1269,15 +1270,15 @@ fbcon_softback_note(vc, t, count); if (logo_shown >= 0) goto redraw_up; - switch (p->scrollmode & __SCROLL_YMASK) { - case __SCROLL_YMOVE: + switch (p->scrollmode) { + case SCROLL_ACCEL: accel_bmove(vc, info, t + count, 0, t, 0, b - t - count, vc->vc_cols); accel_clear(vc, info, b - count, 0, count, vc->vc_cols); break; - case __SCROLL_YWRAP: + case SCROLL_WRAP: if (b - t - count > 3 * vc->vc_rows >> 2) { if (t > 0) fbcon_bmove(vc, 0, 0, count, 0, t, @@ -1287,15 +1288,15 @@ fbcon_bmove(vc, b - count, 0, b, 0, vc->vc_rows - b, vc->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_up; - else + } else if (info->flags & FBINFO_READS_FAST) fbcon_bmove(vc, t + count, 0, t, 0, b - t - count, vc->vc_cols); + else + goto redraw_up; fbcon_clear(vc, b - count, 0, count, vc->vc_cols); break; - case __SCROLL_YPAN: + case SCROLL_PAN: if ((p->yscroll + count <= 2 * (p->vrows - vc->vc_rows)) && ((!scroll_partial && (b - t == vc->vc_rows)) @@ -1310,15 +1311,15 @@ fbcon_bmove(vc, b - count, 0, b, 0, vc->vc_rows - b, vc->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_up; - else + } else if (info->flags & FBINFO_READS_FAST) fbcon_bmove(vc, t + count, 0, t, 0, b - t - count, vc->vc_cols); + else + goto redraw_up; fbcon_clear(vc, b - count, 0, count, vc->vc_cols); break; - case __SCROLL_YREDRAW: + case SCROLL_REDRAW: redraw_up: fbcon_redraw(vc, p, t, b - t - count, count * vc->vc_cols); @@ -1336,14 +1337,14 @@ case SM_DOWN: if (count > vc->vc_rows) /* Maximum realistic size */ count = vc->vc_rows; - switch (p->scrollmode & __SCROLL_YMASK) { - case __SCROLL_YMOVE: + switch (p->scrollmode) { + case SCROLL_ACCEL: accel_bmove(vc, info, t, 0, t + count, 0, b - t - count, vc->vc_cols); accel_clear(vc, info, t, 0, count, vc->vc_cols); break; - case __SCROLL_YWRAP: + case SCROLL_WRAP: if (b - t - count > 3 * vc->vc_rows >> 2) { if (vc->vc_rows - b > 0) fbcon_bmove(vc, b, 0, b - count, 0, @@ -1353,15 +1354,15 @@ if (t > 0) fbcon_bmove(vc, count, 0, 0, 0, t, vc->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_down; - else + } else if (info->flags & FBINFO_READS_FAST) fbcon_bmove(vc, t, 0, t + count, 0, b - t - count, vc->vc_cols); + else + goto redraw_down; fbcon_clear(vc, t, 0, count, vc->vc_cols); break; - case __SCROLL_YPAN: + case SCROLL_PAN: if ((count - p->yscroll <= p->vrows - vc->vc_rows) && ((!scroll_partial && (b - t == vc->vc_rows)) || (scroll_partial @@ -1375,15 +1376,15 @@ if (t > 0) fbcon_bmove(vc, count, 0, 0, 0, t, vc->vc_cols); - } else if (p->scrollmode & __SCROLL_YPANREDRAW) - goto redraw_down; - else + } else if (info->flags & FBINFO_READS_FAST) fbcon_bmove(vc, t, 0, t + count, 0, b - t - count, vc->vc_cols); + else + goto redraw_down; fbcon_clear(vc, t, 0, count, vc->vc_cols); break; - case __SCROLL_YREDRAW: + case SCROLL_REDRAW: redraw_down: fbcon_redraw(vc, p, b - 1, b - t - count, -count * vc->vc_cols); @@ -1467,21 +1468,27 @@ static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, struct vc_data *vc) { - int m; - - if (p->scrollmode & __SCROLL_YFIXED) - return; - if (divides(info->fix.ywrapstep, vc->vc_font.height) && - divides(vc->vc_font.height, info->var.yres_virtual)) - m = __SCROLL_YWRAP; - else if (divides(info->fix.ypanstep, vc->vc_font.height) && - info->var.yres_virtual >= info->var.yres + vc->vc_font.height) - m = __SCROLL_YPAN; - else if (p->scrollmode & __SCROLL_YNOMOVE) - m = __SCROLL_YREDRAW; - else - m = __SCROLL_YMOVE; - p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m; + int cap = info->flags; + int good_pan = (cap & FBINFO_HWACCEL_YPAN) + && divides(info->fix.ypanstep, vc->vc_font.height) + && info->var.yres_virtual >= 2*info->var.yres; + int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) + && divides(info->fix.ywrapstep, vc->vc_font.height) + && divides(vc->vc_font.height, info->var.yres_virtual); + int reading_fast = cap & FBINFO_READS_FAST; + int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED); + + if (good_wrap || good_pan) { + if (reading_fast || fast_copyarea) + p->scrollmode = good_wrap ? SCROLL_WRAP : SCROLL_PAN; + else + p->scrollmode = SCROLL_REDRAW; + } else { + if (reading_fast || fast_copyarea) + p->scrollmode = SCROLL_ACCEL; + else + p->scrollmode = SCROLL_REDRAW; + } } static int fbcon_resize(struct vc_data *vc, unsigned int width, @@ -1505,9 +1512,10 @@ if (!info->fbops->fb_set_par) return -EINVAL; - sprintf(mode, "%dx%d", var.xres, var.yres); - err = fb_find_mode(&var, info, mode, NULL, 0, NULL, - info->var.bits_per_pixel); + snprintf(mode, 40, "%ix%i", var.xres, var.yres); + err = fb_find_mode(&var, info, mode, info->monspecs.modedb, + info->monspecs.modedb_len, NULL, + info->var.bits_per_pixel); if (!err || width > var.xres/fw || height > var.yres/fh) return -EINVAL; DPRINTK("resize now %ix%i\n", var.xres, var.yres); @@ -1555,12 +1563,12 @@ } if (info) info->var.yoffset = p->yscroll = 0; - fbcon_resize(vc, vc->vc_cols, vc->vc_rows); - switch (p->scrollmode & __SCROLL_YMASK) { - case __SCROLL_YWRAP: + fbcon_resize(vc, vc->vc_cols, vc->vc_rows); + switch (p->scrollmode) { + case SCROLL_WRAP: scrollback_phys_max = p->vrows - vc->vc_rows; break; - case __SCROLL_YPAN: + case SCROLL_PAN: scrollback_phys_max = p->vrows - 2 * vc->vc_rows; if (scrollback_phys_max < 0) scrollback_phys_max = 0; @@ -2133,11 +2141,11 @@ offset = p->yscroll - scrollback_current; limit = p->vrows; - switch (p->scrollmode && __SCROLL_YMASK) { - case __SCROLL_YWRAP: + switch (p->scrollmode) { + case SCROLL_WRAP: info->var.vmode |= FB_VMODE_YWRAP; break; - case __SCROLL_YPAN: + case SCROLL_PAN: limit -= vc->vc_rows; info->var.vmode &= ~FB_VMODE_YWRAP; break; diff -Nru a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h --- a/drivers/video/console/fbcon.h 2004-06-20 13:00:25 -07:00 +++ b/drivers/video/console/fbcon.h 2004-06-20 13:00:25 -07:00 @@ -67,40 +67,27 @@ * Scroll Method */ -/* Internal flags */ -#define __SCROLL_YPAN 0x001 -#define __SCROLL_YWRAP 0x002 -#define __SCROLL_YMOVE 0x003 -#define __SCROLL_YREDRAW 0x004 -#define __SCROLL_YMASK 0x00f -#define __SCROLL_YFIXED 0x010 -#define __SCROLL_YNOMOVE 0x020 -#define __SCROLL_YPANREDRAW 0x040 -#define __SCROLL_YNOPARTIAL 0x080 - -/* Only these should be used by the drivers */ -/* Which one should you use? If you have a fast card and slow bus, - then probably just 0 to indicate fbcon should choose between - YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus - and even better if your card can do fonting (1->8/32bit painting), - you should consider either SCROLL_YREDRAW (if your card is - able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE. - The best is to test it with some real life scrolling (usually, not - all lines on the screen are filled completely with non-space characters, - and REDRAW performs much better on such lines, so don't cat a file - with every line covering all screen columns, it would not be the right - benchmark). +/* There are several methods fbcon can use to move text around the screen: + * + * + use the hardware engine to move the text + * (hw-accelerated copyarea() and fillrect()) + * + use hardware-supported panning on a large virtual screen + * + amifb can not only pan, but also wrap the display by N lines + * (i.e. visible line i = physical line (i+N) % yres). + * + read what's already rendered on the screen and + * write it in a different place (this is cfb_copyarea()) + * + re-render the text to the screen + * + * Whether to use wrapping or panning can only be figured out at + * runtime (when we know whether our font height is a multiple + * of the pan/wrap step) + * */ -#define SCROLL_YREDRAW (__SCROLL_YFIXED|__SCROLL_YREDRAW) -#define SCROLL_YNOMOVE (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW) -/* SCROLL_YNOPARTIAL, used in combination with the above, is for video - cards which can not handle using panning to scroll a portion of the - screen without excessive flicker. Panning will only be used for - whole screens. - */ -/* Namespace consistency */ -#define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL +#define SCROLL_ACCEL 0x001 +#define SCROLL_PAN 0x002 +#define SCROLL_WRAP 0x003 +#define SCROLL_REDRAW 0x004 extern int fb_console_init(void); diff -Nru a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c --- a/drivers/video/console/sticore.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/video/console/sticore.c 2004-06-20 13:00:23 -07:00 @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff -Nru a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c --- a/drivers/video/console/vgacon.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/video/console/vgacon.c 2004-06-20 13:00:24 -07:00 @@ -963,6 +963,8 @@ p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + lines * c->vc_size_row; st = (c->vc_origin - vga_vram_base - ul + we) % we; + if (st < 2 * margin) + margin = 0; if (p < margin) p = 0; if (p > st - margin) diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c --- a/drivers/video/fbmem.c 2004-06-20 13:00:22 -07:00 +++ b/drivers/video/fbmem.c 2004-06-20 13:00:22 -07:00 @@ -172,6 +172,7 @@ extern int kyrofb_setup(char*); extern int mc68x328fb_init(void); extern int mc68x328fb_setup(char *); +extern int asiliantfb_init(void); static struct { const char *name; @@ -385,6 +386,9 @@ #ifdef CONFIG_FB_68328 { "68328fb", mc68x328fb_init, mc68x328fb_setup }, #endif +#ifdef CONFIG_FB_ASILIANT + { "asiliantfb", asiliantfb_init, NULL }, +#endif /* * Generic drivers that don't use resource management (yet) @@ -802,7 +806,7 @@ } static ssize_t -fb_read(struct file *file, char *buf, size_t count, loff_t *ppos) +fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; @@ -839,7 +843,7 @@ } static ssize_t -fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; @@ -916,26 +920,30 @@ if (cursor.set & FB_CUR_SETSHAPE) { int size = ((cursor.image.width + 7) >> 3) * cursor.image.height; + char *data, *mask; + if ((cursor.image.height != info->cursor.image.height) || (cursor.image.width != info->cursor.image.width)) cursor.set |= FB_CUR_SETSIZE; - cursor.image.data = kmalloc(size, GFP_KERNEL); - if (!cursor.image.data) + data = kmalloc(size, GFP_KERNEL); + if (!data) return -ENOMEM; - cursor.mask = kmalloc(size, GFP_KERNEL); - if (!cursor.mask) { - kfree(cursor.image.data); + mask = kmalloc(size, GFP_KERNEL); + if (!mask) { + kfree(data); return -ENOMEM; } - if (copy_from_user(cursor.image.data, sprite->image.data, size) || - copy_from_user(cursor.mask, sprite->mask, size)) { - kfree(cursor.image.data); - kfree(cursor.mask); + if (copy_from_user(data, sprite->image.data, size) || + copy_from_user(mask, sprite->mask, size)) { + kfree(data); + kfree(mask); return -EFAULT; } + cursor.image.data = data; + cursor.mask = mask; } info->cursor.set = cursor.set; info->cursor.rop = cursor.rop; diff -Nru a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c --- a/drivers/video/imsttfb.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/video/imsttfb.c 2004-06-20 13:00:24 -07:00 @@ -1267,48 +1267,49 @@ u_long arg, struct fb_info *info) { struct imstt_par *par = (struct imstt_par *) info->par; + void __user *argp = (void __user *)arg; __u32 reg[2]; __u8 idx[2]; switch (cmd) { case FBIMSTT_SETREG: - if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) + if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; write_reg_le32(par->dc_regs, reg[0], reg[1]); return 0; case FBIMSTT_GETREG: - if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) + if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; reg[1] = read_reg_le32(par->dc_regs, reg[0]); - if (copy_to_user((void *)(arg + 4), ®[1], 4)) + if (copy_to_user((void __user *)(arg + 4), ®[1], 4)) return -EFAULT; return 0; case FBIMSTT_SETCMAPREG: - if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) + if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; write_reg_le32(((u_int *)par->cmap_regs), reg[0], reg[1]); return 0; case FBIMSTT_GETCMAPREG: - if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) + if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; reg[1] = read_reg_le32(((u_int *)par->cmap_regs), reg[0]); - if (copy_to_user((void *)(arg + 4), ®[1], 4)) + if (copy_to_user((void __user *)(arg + 4), ®[1], 4)) return -EFAULT; return 0; case FBIMSTT_SETIDXREG: - if (copy_from_user(idx, (void *)arg, 2)) + if (copy_from_user(idx, argp, 2)) return -EFAULT; par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = idx[0]; eieio(); par->cmap_regs[PIDXDATA] = idx[1]; eieio(); return 0; case FBIMSTT_GETIDXREG: - if (copy_from_user(idx, (void *)arg, 1)) + if (copy_from_user(idx, argp, 1)) return -EFAULT; par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = idx[0]; eieio(); idx[1] = par->cmap_regs[PIDXDATA]; - if (copy_to_user((void *)(arg + 1), &idx[1], 1)) + if (copy_to_user((void __user *)(arg + 1), &idx[1], 1)) return -EFAULT; return 0; default: diff -Nru a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c --- a/drivers/video/kyro/fbdev.c 2004-06-20 13:00:23 -07:00 +++ b/drivers/video/kyro/fbdev.c 2004-06-20 13:00:23 -07:00 @@ -592,11 +592,11 @@ { overlay_create ol_create; overlay_viewport_set ol_viewport_set; + void __user *argp = (void __user *)arg; switch (cmd) { case KYRO_IOCTL_OVERLAY_CREATE: - copy_from_user((void *) &ol_create, (void *) arg, - sizeof(overlay_create)); + copy_from_user(&ol_create, argp, sizeof(overlay_create)); if (kyro_dev_overlay_create(ol_create.ulWidth, ol_create.ulHeight, 0) < 0) { @@ -606,7 +606,7 @@ } break; case KYRO_IOCTL_OVERLAY_VIEWPORT_SET: - copy_from_user((void *) &ol_viewport_set, (void *) arg, + copy_from_user(&ol_viewport_set, argp, sizeof(overlay_viewport_set)); if (kyro_dev_overlay_viewport_set(ol_viewport_set.xOrgin, @@ -627,13 +627,13 @@ } break; case KYRO_IOCTL_UVSTRIDE: - copy_to_user((void *)arg, (void *)&deviceInfo.ulOverlayUVStride, sizeof(unsigned long)); + copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)); break; case KYRO_IOCTL_STRIDE: - copy_to_user((void *)arg, (void *)&deviceInfo.ulOverlayStride, sizeof(unsigned long)); + copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)); break; case KYRO_IOCTL_OVERLAY_OFFSET: - copy_to_user((void *)arg, (void *)&deviceInfo.ulOverlayOffset, sizeof(unsigned long)); + copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)); break; } diff -Nru a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c --- a/drivers/video/matrox/matroxfb_base.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/video/matrox/matroxfb_base.c 2004-06-20 13:00:25 -07:00 @@ -874,6 +874,7 @@ unsigned int cmd, unsigned long arg, struct fb_info *info) { + void __user *argp = (void __user *)arg; MINFO_FROM_INFO(info); DBG(__FUNCTION__) @@ -891,7 +892,7 @@ err = matroxfb_get_vblank(PMINFO &vblank); if (err) return err; - if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank))) + if (copy_to_user(argp, &vblank, sizeof(vblank))) return -EFAULT; return 0; } @@ -899,7 +900,7 @@ { u_int32_t crt; - if (get_user(crt, (u_int32_t *)arg)) + if (get_user(crt, (u_int32_t __user *)arg)) return -EFAULT; return matroxfb_wait_for_sync(PMINFO crt); @@ -910,7 +911,7 @@ struct matrox_altout *oproc; int val; - if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) + if (copy_from_user(&mom, argp, sizeof(mom))) return -EFAULT; if (mom.output >= MATROXFB_MAX_OUTPUTS) return -ENXIO; @@ -960,7 +961,7 @@ struct matrox_altout *oproc; int val; - if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) + if (copy_from_user(&mom, argp, sizeof(mom))) return -EFAULT; if (mom.output >= MATROXFB_MAX_OUTPUTS) return -ENXIO; @@ -975,7 +976,7 @@ up_read(&ACCESS_FBINFO(altout.lock)); if (val) return val; - if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom))) + if (copy_to_user(argp, &mom, sizeof(mom))) return -EFAULT; return 0; } @@ -985,7 +986,7 @@ int i; int changes; - if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp))) + if (copy_from_user(&tmp, argp, sizeof(tmp))) return -EFAULT; for (i = 0; i < 32; i++) { if (tmp & (1 << i)) { @@ -1040,7 +1041,7 @@ conn |= 1 << i; } } - if (put_user(conn, (u_int32_t*)arg)) + if (put_user(conn, (u_int32_t __user *)arg)) return -EFAULT; return 0; } @@ -1065,7 +1066,7 @@ if (conn & MATROXFB_OUTPUT_CONN_SECONDARY) conn &= ~MATROXFB_OUTPUT_CONN_DFP; } - if (put_user(conn, (u_int32_t*)arg)) + if (put_user(conn, (u_int32_t __user *)arg)) return -EFAULT; return 0; } @@ -1079,7 +1080,7 @@ conn |= 1 << i; } } - if (put_user(conn, (u_int32_t*)arg)) + if (put_user(conn, (u_int32_t __user *)arg)) return -EFAULT; return 0; } @@ -1093,7 +1094,7 @@ sprintf(r.bus_info, "PCI:%s", pci_name(ACCESS_FBINFO(pcidev))); r.version = KERNEL_VERSION(1,0,0); r.capabilities = V4L2_CAP_VIDEO_OUTPUT; - if (copy_to_user((void*)arg, &r, sizeof(r))) + if (copy_to_user(argp, &r, sizeof(r))) return -EFAULT; return 0; @@ -1103,7 +1104,7 @@ struct v4l2_queryctrl qctrl; int err; - if (copy_from_user(&qctrl, (struct v4l2_queryctrl*)arg, sizeof(qctrl))) + if (copy_from_user(&qctrl, argp, sizeof(qctrl))) return -EFAULT; down_read(&ACCESS_FBINFO(altout).lock); @@ -1116,7 +1117,7 @@ } up_read(&ACCESS_FBINFO(altout).lock); if (err >= 0 && - copy_to_user((struct v4l2_queryctrl*)arg, &qctrl, sizeof(qctrl))) + copy_to_user(argp, &qctrl, sizeof(qctrl))) return -EFAULT; return err; } @@ -1125,7 +1126,7 @@ struct v4l2_control ctrl; int err; - if (copy_from_user(&ctrl, (struct v4l2_control*)arg, sizeof(ctrl))) + if (copy_from_user(&ctrl, argp, sizeof(ctrl))) return -EFAULT; down_read(&ACCESS_FBINFO(altout).lock); @@ -1138,7 +1139,7 @@ } up_read(&ACCESS_FBINFO(altout).lock); if (err >= 0 && - copy_to_user((struct v4l2_control*)arg, &ctrl, sizeof(ctrl))) + copy_to_user(argp, &ctrl, sizeof(ctrl))) return -EFAULT; return err; } @@ -1147,7 +1148,7 @@ struct v4l2_control ctrl; int err; - if (copy_from_user(&ctrl, (struct v4l2_control*)arg, sizeof(ctrl))) + if (copy_from_user(&ctrl, argp, sizeof(ctrl))) return -EFAULT; down_read(&ACCESS_FBINFO(altout).lock); diff -Nru a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c --- a/drivers/video/matrox/matroxfb_crtc2.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/video/matrox/matroxfb_crtc2.c 2004-06-20 13:00:25 -07:00 @@ -437,7 +437,7 @@ err = matroxfb_dh_get_vblank(m2info, &vblank); if (err) return err; - if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank))) + if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank))) return -EFAULT; return 0; } @@ -445,7 +445,7 @@ { u_int32_t crt; - if (get_user(crt, (u_int32_t *)arg)) + if (get_user(crt, (u_int32_t __user *)arg)) return -EFAULT; if (crt != 0) @@ -464,7 +464,7 @@ int out; int changes; - if (get_user(tmp, (u_int32_t*)arg)) + if (get_user(tmp, (u_int32_t __user *)arg)) return -EFAULT; for (out = 0; out < 32; out++) { if (tmp & (1 << out)) { @@ -514,7 +514,7 @@ conn |= 1 << out; } } - if (put_user(conn, (u_int32_t*)arg)) + if (put_user(conn, (u_int32_t __user *)arg)) return -EFAULT; return 0; } @@ -539,7 +539,7 @@ tmp = 0; } } - if (put_user(tmp, (u_int32_t*)arg)) + if (put_user(tmp, (u_int32_t __user *)arg)) return -EFAULT; return 0; } diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c --- a/drivers/video/modedb.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/video/modedb.c 2004-06-20 13:00:24 -07:00 @@ -490,6 +490,7 @@ int res_specified = 0, bpp_specified = 0, refresh_specified = 0; unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; int yres_specified = 0; + u32 best = -1, diff = -1; for (i = namelen-1; i >= 0; i--) { switch (name[i]) { @@ -529,14 +530,30 @@ } done: for (i = refresh_specified; i >= 0; i--) { - DPRINTK("Trying specified video mode%s\n", - i ? "" : " (ignoring refresh rate)"); + DPRINTK("Trying specified video mode%s %ix%i\n", + i ? "" : " (ignoring refresh rate)", xres, yres); for (j = 0; j < dbsize; j++) if ((name_matches(db[j], name, namelen) || (res_specified && res_matches(db[j], xres, yres))) && (!i || db[j].refresh == refresh) && !fb_try_mode(var, info, &db[j], bpp)) return 2-i; + } + DPRINTK("Trying best-fit modes\n"); + for (i = 0; i < dbsize; i++) { + if (xres <= db[i].xres && yres <= db[i].yres) { + DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); + if (!fb_try_mode(var, info, &db[i], bpp)) { + if (diff > (db[i].xres - xres) + (db[i].yres - yres)) { + diff = (db[i].xres - xres) + (db[i].yres - yres); + best = i; + } + } + } + } + if (best != -1) { + fb_try_mode(var, info, &db[best], bpp); + return 5; } } diff -Nru a/drivers/video/pxafb.c b/drivers/video/pxafb.c --- a/drivers/video/pxafb.c 2004-06-20 13:00:24 -07:00 +++ b/drivers/video/pxafb.c 2004-06-20 13:00:24 -07:00 @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -109,10 +108,13 @@ u_int val, ret = 1; if (regno < fbi->palette_size) { - val = ((red >> 0) & 0xf800); - val |= ((green >> 5) & 0x07e0); - val |= ((blue >> 11) & 0x001f); - + if (fbi->fb.var.grayscale) { + val = ((blue >> 8) & 0x00ff); + } else { + val = ((red >> 0) & 0xf800); + val |= ((green >> 5) & 0x07e0); + val |= ((blue >> 11) & 0x001f); + } fbi->palette_cpu[regno] = val; ret = 0; } @@ -150,7 +152,7 @@ switch (fbi->fb.fix.visual) { case FB_VISUAL_TRUECOLOR: /* - * 12 or 16-bit True Colour. We encode the RGB value + * 16-bit True Colour. We encode the RGB value * according to the RGB bitfield information. */ if (regno < 16) { @@ -242,7 +244,7 @@ * The pixel packing format is described on page 7-11 of the * PXA2XX Developer's Manual. */ - if ( var->bits_per_pixel == 16 ) { + if (var->bits_per_pixel == 16) { var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; @@ -297,7 +299,10 @@ fbi->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; - fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; + if (var->bits_per_pixel == 16) + fbi->palette_size = 0; + else + fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel; palette_mem_size = fbi->palette_size * sizeof(u16); @@ -311,6 +316,11 @@ */ pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); + if (fbi->fb.var.bits_per_pixel == 16) + fb_dealloc_cmap(&fbi->fb.cmap); + else + fb_alloc_cmap(&fbi->fb.cmap, 1<fb.var.bits_per_pixel, 0); + pxafb_activate_var(var, fbi); return 0; @@ -349,7 +359,7 @@ /* * pxafb_blank(): * Blank the display by setting all palette values to zero. Note, the - * 12 and 16 bpp modes don't really use the palette, so this will not + * 16 bpp mode does not really use the palette, so this will not * blank the display in all modes. */ static int pxafb_blank(int blank, struct fb_info *info) @@ -514,7 +524,7 @@ * the YRES parameter. */ lines_per_panel = var->yres; - if (fbi->lccr0 & LCCR0_SDS) + if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) lines_per_panel /= 2; new_regs.lccr2 = @@ -566,20 +576,16 @@ fbi->dmadesc_palette_cpu->fidr = 0; fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL; - if( var->bits_per_pixel < 12) - { - /* assume any mode with <12 bpp is palette driven */ - fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma; - fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma; - fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */ - } - else - { + if (var->bits_per_pixel == 16) { /* palette shouldn't be loaded in true-color mode */ fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma; fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */ /* init it to something, even though we won't be using it */ fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_palette_dma; + } else { + fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma; + fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma; + fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */ } #if 0 @@ -696,7 +702,7 @@ } else { - printk( KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n"); + printk(KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n"); } } @@ -1010,7 +1016,7 @@ struct pxafb_mach_info *inf = dev->platform_data; /* Alloc the pxafb_info and pseudo_palette in one step */ - fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 17, GFP_KERNEL); + fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL); if (!fbi) return NULL; @@ -1123,11 +1129,11 @@ res_specified = 1; } done: - if ( res_specified ) { - dev_info(dev, "overriding resolution: %dx%x\n", xres, yres); + if (res_specified) { + dev_info(dev, "overriding resolution: %dx%d\n", xres, yres); inf->xres = xres; inf->yres = yres; } - if ( bpp_specified ) + if (bpp_specified) switch (bpp) { case 1: case 2: @@ -1142,7 +1148,7 @@ } } else if (!strncmp(this_opt, "pixclock:", 9)) { inf->pixclock = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override pixclock: %u\n", inf->pixclock); + dev_info(dev, "override pixclock: %ld\n", inf->pixclock); } else if (!strncmp(this_opt, "left:", 5)) { inf->left_margin = simple_strtoul(this_opt+5, NULL, 0); dev_info(dev, "override left: %u\n", inf->left_margin); @@ -1162,7 +1168,7 @@ inf->vsync_len = simple_strtoul(this_opt+9, NULL, 0); dev_info(dev, "override vsynclen: %u\n", inf->vsync_len); } else if (!strncmp(this_opt, "hsync:", 6)) { - if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) { + if (simple_strtoul(this_opt+6, NULL, 0) == 0) { dev_info(dev, "override hsync: Active Low\n"); inf->sync &= ~FB_SYNC_HOR_HIGH_ACT; } else { @@ -1170,7 +1176,7 @@ inf->sync |= FB_SYNC_HOR_HIGH_ACT; } } else if (!strncmp(this_opt, "vsync:", 6)) { - if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) { + if (simple_strtoul(this_opt+6, NULL, 0) == 0) { dev_info(dev, "override vsync: Active Low\n"); inf->sync &= ~FB_SYNC_VERT_HIGH_ACT; } else { @@ -1178,7 +1184,7 @@ inf->sync |= FB_SYNC_VERT_HIGH_ACT; } } else if (!strncmp(this_opt, "dpc:", 4)) { - if ( simple_strtoul(this_opt+4, NULL, 0) == 0 ) { + if (simple_strtoul(this_opt+4, NULL, 0) == 0) { dev_info(dev, "override double pixel clock: false\n"); inf->lccr3 &= ~LCCR3_DPC; } else { @@ -1186,20 +1192,20 @@ inf->lccr3 |= LCCR3_DPC; } } else if (!strncmp(this_opt, "outputen:", 9)) { - if ( simple_strtoul(this_opt+9, NULL, 0) == 0 ) { + if (simple_strtoul(this_opt+9, NULL, 0) == 0) { dev_info(dev, "override output enable: active low\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_OEP ) | LCCR3_OutEnL; + inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL; } else { dev_info(dev, "override output enable: active high\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_OEP ) | LCCR3_OutEnH; + inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH; } } else if (!strncmp(this_opt, "pixclockpol:", 12)) { - if ( simple_strtoul(this_opt+12, NULL, 0) == 0 ) { + if (simple_strtoul(this_opt+12, NULL, 0) == 0) { dev_info(dev, "override pixel clock polarity: falling edge\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_PCP ) | LCCR3_PixFlEdg; + inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg; } else { dev_info(dev, "override pixel clock polarity: rising edge\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_PCP ) | LCCR3_PixRsEdg; + inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg; } } else if (!strncmp(this_opt, "color", 5)) { inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color; @@ -1231,7 +1237,6 @@ { struct pxafb_info *fbi; struct pxafb_mach_info *inf; - unsigned long flags; int ret; dev_dbg(dev, "pxafb_probe\n"); @@ -1244,7 +1249,7 @@ #ifdef CONFIG_FB_PXA_PARAMETERS ret = pxafb_parse_options(dev, g_options); - if ( ret < 0 ) + if (ret < 0) goto failed; #endif @@ -1252,23 +1257,23 @@ /* Check for various illegal bit-combinations. Currently only * a warning is given. */ - if ( inf->lccr0 & LCCR0_INVALID_CONFIG_MASK ) + if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) dev_warn(dev, "machine LCCR0 setting contains illegal bits: %08x\n", inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); - if ( inf->lccr3 & LCCR3_INVALID_CONFIG_MASK ) + if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) dev_warn(dev, "machine LCCR3 setting contains illegal bits: %08x\n", inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); - if ( inf->lccr0 & LCCR0_DPD && - ( ( inf->lccr0 & LCCR0_PAS ) != LCCR0_Pas || - ( inf->lccr0 & LCCR0_SDS ) != LCCR0_Sngl || - ( inf->lccr0 & LCCR0_CMS ) != LCCR0_Mono ) ) + if (inf->lccr0 & LCCR0_DPD && + ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || + (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || + (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) dev_warn(dev, "Double Pixel Data (DPD) mode is only valid in passive mono" " single panel mode\n"); - if ( (inf->lccr0 & LCCR0_PAS) == LCCR0_Act && - ( inf->lccr0 & LCCR0_SDS ) == LCCR0_Dual ) + if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && + (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) dev_warn(dev, "Dual panel only valid in passive mode\n"); - if ( (inf->lccr0 & LCCR0_PAS ) == LCCR0_Pas && - (inf->upper_margin || inf->lower_margin) ) + if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && + (inf->upper_margin || inf->lower_margin)) dev_warn(dev, "Upper and lower margins must be 0 in passive mode\n"); #endif @@ -1295,9 +1300,7 @@ goto failed; } /* enable LCD controller clock */ - local_irq_save(flags); - CKEN |= CKEN16_LCD; - local_irq_restore(flags); + pxa_set_cken(CKEN16_LCD, 1); ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c --- a/drivers/video/radeonfb.c 2004-06-20 13:00:26 -07:00 +++ b/drivers/video/radeonfb.c 2004-06-20 13:00:26 -07:00 @@ -1544,7 +1544,7 @@ break; } - rc = get_user(value, (__u32*)arg); + rc = get_user(value, (__u32 __user *)arg); if (rc) return rc; @@ -1598,7 +1598,7 @@ if (CRTC_CRT_ON & tmp) value |= 0x02; - return put_user(value, (__u32*)arg); + return put_user(value, (__u32 __user *)arg); default: return -EINVAL; } diff -Nru a/drivers/video/riva/Makefile b/drivers/video/riva/Makefile --- a/drivers/video/riva/Makefile 2004-06-20 13:00:23 -07:00 +++ b/drivers/video/riva/Makefile 2004-06-20 13:00:23 -07:00 @@ -2,6 +2,10 @@ # Makefile for the Riva framebuffer driver # -obj-$(CONFIG_FB_RIVA) += rivafb.o +obj-$(CONFIG_FB_RIVA) += rivafb.o -rivafb-objs := fbdev.o riva_hw.o nv_driver.o +rivafb-objs := fbdev.o riva_hw.o nv_driver.o + +ifdef CONFIG_FB_RIVA_I2C + rivafb-objs += rivafb-i2c.o +endif diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c --- a/drivers/video/riva/fbdev.c 2004-06-20 13:00:25 -07:00 +++ b/drivers/video/riva/fbdev.c 2004-06-20 13:00:25 -07:00 @@ -296,9 +296,8 @@ static int nomtrr __initdata = 0; #endif -#ifndef MODULE static char *mode_option __initdata = NULL; -#endif +static int strictmode = 0; static struct fb_fix_screeninfo rivafb_fix = { .id = "nVidia", @@ -493,54 +492,30 @@ * rivafb_cursor() */ static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8, - u8 *mask8, u16 bg, u16 fg, u32 w, u32 h) + u16 bg, u16 fg, u32 w, u32 h) { int i, j, k = 0; - u32 b, m, tmp; + u32 b, tmp; u32 *data = (u32 *)data8; - u32 *mask = (u32 *)mask8; for (i = 0; i < h; i++) { b = *data++; - m = *mask++; reverse_order(&b); for (j = 0; j < w/2; j++) { tmp = 0; #if defined (__BIG_ENDIAN) - if (m & (1 << 31)) { - fg |= 1 << 15; - bg |= 1 << 15; - } tmp = (b & (1 << 31)) ? fg << 16 : bg << 16; b <<= 1; - m <<= 1; - - if (m & (1 << 31)) { - fg |= 1 << 15; - bg |= 1 << 15; - } tmp |= (b & (1 << 31)) ? fg : bg; b <<= 1; - m <<= 1; #else - if (m & 1) { - fg |= 1 << 15; - bg |= 1 << 15; - } tmp = (b & 1) ? fg : bg; b >>= 1; - m >>= 1; - - if (m & 1) { - fg |= 1 << 15; - bg |= 1 << 15; - } tmp |= (b & 1) ? fg << 16 : bg << 16; b >>= 1; - m >>= 1; #endif - writel(tmp, par->riva.CURSOR + k++); + writel(tmp, &par->riva.CURSOR[k++]); } k += (MAX_CURS - w)/2; } @@ -833,6 +808,24 @@ rivafb_blank(0, info); } +static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb) +{ + var->xres = var->xres_virtual = modedb->xres; + var->yres = modedb->yres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + var->xoffset = var->yoffset = 0; + var->pixclock = modedb->pixclock; + var->left_margin = modedb->left_margin; + var->right_margin = modedb->right_margin; + var->upper_margin = modedb->upper_margin; + var->lower_margin = modedb->lower_margin; + var->hsync_len = modedb->hsync_len; + var->vsync_len = modedb->vsync_len; + var->sync = modedb->sync; + var->vmode = modedb->vmode; +} + /** * rivafb_do_maximize - * @info: pointer to fb_info object containing info for current riva board @@ -872,7 +865,7 @@ "using maximum available virtual resolution\n"); for (i = 0; modes[i].xres != -1; i++) { if (modes[i].xres * nom / den * modes[i].yres < - info->fix.smem_len / 2) + info->fix.smem_len) break; } if (modes[i].xres == -1) { @@ -927,35 +920,47 @@ "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual); return -EINVAL; } + if (var->xres_virtual > 0x7fff) + var->xres_virtual = 0x7fff; + if (var->yres_virtual > 0x7fff) + var->yres_virtual = 0x7fff; return 0; } +static void +riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1) +{ + RIVA_FIFO_FREE(par->riva, Patt, 4); + par->riva.Patt->Color0 = clr0; + par->riva.Patt->Color1 = clr1; + par->riva.Patt->Monochrome[0] = pat0; + par->riva.Patt->Monochrome[1] = pat1; +} + /* acceleration routines */ inline void wait_for_idle(struct riva_par *par) { while (par->riva.Busy(&par->riva)); } -/* set copy ROP, no mask */ -static void riva_setup_ROP(struct riva_par *par) +/* + * Set ROP. Translate X rop into ROP3. Internal routine. + */ +static void +riva_set_rop_solid(struct riva_par *par, int rop) { - RIVA_FIFO_FREE(par->riva, Patt, 5); - par->riva.Patt->Shape = 0; - par->riva.Patt->Color0 = 0xffffffff; - par->riva.Patt->Color1 = 0xffffffff; - par->riva.Patt->Monochrome[0] = 0xffffffff; - par->riva.Patt->Monochrome[1] = 0xffffffff; + riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); + RIVA_FIFO_FREE(par->riva, Rop, 1); + par->riva.Rop->Rop3 = rop; - RIVA_FIFO_FREE(par->riva, Rop, 1); - par->riva.Rop->Rop3 = 0xCC; } void riva_setup_accel(struct riva_par *par) { RIVA_FIFO_FREE(par->riva, Clip, 2); par->riva.Clip->TopLeft = 0x0; - par->riva.Clip->WidthHeight = 0x80008000; - riva_setup_ROP(par); + par->riva.Clip->WidthHeight = 0x7fff7fff; + riva_set_rop_solid(par, 0xcc); wait_for_idle(par); } @@ -1043,7 +1048,9 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { + struct fb_monspecs *specs = &info->monspecs; int nom, den; /* translating from pixels->bytes */ + int mode_valid = 0; switch (var->bits_per_pixel) { case 1 ... 8: @@ -1094,6 +1101,73 @@ return -EINVAL; } + if (!strictmode) { + if (!fb_validate_mode(var, info)) + mode_valid = 1; + } + + /* find best mode from modedb */ + if (!mode_valid && specs->modedb_len) { + int i, best, best_refresh, best_x, best_y, diff_x, diff_y; + + best_refresh = best = best_x = best_y = 0; + diff_x = diff_y = -1; + + for (i = 0; i < specs->modedb_len; i++) { + if (var->xres <= specs->modedb[i].xres && + !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) && + specs->modedb[i].xres - var->xres < diff_x) { + best_x = specs->modedb[i].xres; + diff_x = best_x - var->xres; + } + if (!diff_x) break; + } + + if (diff_x != -1) { + for (i = 0; i < specs->modedb_len; i++) { + if (best_x == specs->modedb[i].xres && + var->yres <= specs->modedb[i].yres && + !(specs->modedb[i].flag & + FB_MODE_IS_CALCULATED) && + specs->modedb[i].yres-var->yres < diff_y) { + best_y = specs->modedb[i].yres; + diff_y = best_y - var->yres; + } + if (!diff_y) break; + } + } + + if (diff_y != -1) { + for (i = 0; i < specs->modedb_len; i++) { + if (best_x == specs->modedb[i].xres && + best_y == specs->modedb[i].yres && + !(specs->modedb[i].flag & + FB_MODE_IS_CALCULATED) && + specs->modedb[i].refresh > best_refresh) { + best_refresh=specs->modedb[i].refresh; + best = i; + } + } + } + + if (best_refresh) { + riva_update_var(var, &specs->modedb[best]); + mode_valid = 1; + } + } + + /* calculate modeline if supported by monitor */ + if (!mode_valid && info->monspecs.gtf) { + if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info)) + mode_valid = 1; + } + if (!mode_valid && info->monspecs.modedb_len) + return -EINVAL; + + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual <= var->yres) + var->yres_virtual = -1; if (rivafb_do_maximize(info, var, nom, den) < 0) return -EINVAL; @@ -1329,8 +1403,7 @@ break; } - RIVA_FIFO_FREE(par->riva, Rop, 1); - par->riva.Rop->Rop3 = rop; + riva_set_rop_solid(par, rop); RIVA_FIFO_FREE(par->riva, Bitmap, 1); par->riva.Bitmap->Color1A = color; @@ -1338,10 +1411,12 @@ RIVA_FIFO_FREE(par->riva, Bitmap, 2); par->riva.Bitmap->UnclippedRectangle[0].TopLeft = (rect->dx << 16) | rect->dy; + mb(); par->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (rect->width << 16) | rect->height; - RIVA_FIFO_FREE(par->riva, Rop, 1); - par->riva.Rop->Rop3 = 0xCC; // back to COPY + mb(); + riva_set_rop_solid(par, 0xcc); + } /** @@ -1362,8 +1437,9 @@ RIVA_FIFO_FREE(par->riva, Blt, 3); par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx; par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx; + mb(); par->riva.Blt->WidthHeight = (region->height << 16) | region->width; - wait_for_idle(par); + mb(); } static inline void convert_bgcolor_16(u32 *col) @@ -1372,6 +1448,7 @@ | ((*col & 0x000003E0) << 6) | ((*col & 0x0000001F) << 3) | 0xFF000000; + mb(); } /** @@ -1478,7 +1555,6 @@ { struct riva_par *par = (struct riva_par *) info->par; u8 data[MAX_CURS * MAX_CURS/8]; - u8 mask[MAX_CURS * MAX_CURS/8]; u16 fg, bg; int i; @@ -1508,7 +1584,7 @@ info->cursor.image.fg_color = cursor->image.fg_color; } - if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) { + if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) { u32 bg_idx = info->cursor.image.bg_color; u32 fg_idx = info->cursor.image.fg_color; u32 s_pitch = (info->cursor.image.width+7) >> 3; @@ -1517,34 +1593,35 @@ u8 *msk = (u8 *) info->cursor.mask; u8 src[64]; + info->cursor.image.data = cursor->image.data; switch (info->cursor.rop) { case ROP_XOR: - for (i = 0; i < s_pitch * info->cursor.image.height; i++) - src[i] = dat[i] ^ msk[i]; + for (i = 0; i < s_pitch * info->cursor.image.height; + i++) + src[i] = dat[i] ^ msk[i]; break; case ROP_COPY: default: - for (i = 0; i < s_pitch * info->cursor.image.height; i++) - - src[i] = dat[i] & msk[i]; + for (i = 0; i < s_pitch * info->cursor.image.height; + i++) + src[i] = dat[i] & msk[i]; break; } - fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src, s_pitch, info->cursor.image.height); - - fb_move_buf_aligned(info, &info->sprite, mask, d_pitch, msk, s_pitch, info->cursor.image.height); + fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src, + s_pitch, info->cursor.image.height); bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) | ((info->cmap.green[bg_idx] & 0xf8) << 2) | - ((info->cmap.blue[bg_idx] & 0xf8) >> 3); + ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15; fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | ((info->cmap.green[fg_idx] & 0xf8) << 2) | - ((info->cmap.blue[fg_idx] & 0xf8) >> 3); + ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15; par->riva.LockUnlock(&par->riva, 0); - rivafb_load_cursor_image(par, data, mask, bg, fg, + rivafb_load_cursor_image(par, data, bg, fg, info->cursor.image.width, info->cursor.image.height); } @@ -1586,24 +1663,19 @@ static int __devinit riva_set_fbinfo(struct fb_info *info) { - struct riva_par *par = (struct riva_par *) info->par; unsigned int cmap_len; - info->flags = FBINFO_FLAG_DEFAULT; + info->flags = FBINFO_DEFAULT + | FBINFO_HWACCEL_XPAN + | FBINFO_HWACCEL_YPAN + | FBINFO_HWACCEL_COPYAREA + | FBINFO_HWACCEL_FILLRECT + | FBINFO_HWACCEL_IMAGEBLIT; info->var = rivafb_default_var; - info->fix = rivafb_fix; - info->fbops = &riva_fb_ops; + info->fix.visual = (info->var.bits_per_pixel == 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; info->pseudo_palette = pseudo_palette; -#ifndef MODULE - if (mode_option) - fb_find_mode(&info->var, info, mode_option, - NULL, 0, NULL, 8); -#endif - if (par->use_default_var) - /* We will use the modified default var */ - info->var = rivafb_default_var; - cmap_len = riva_get_cmap_len(&info->var); fb_alloc_cmap(&info->cmap, cmap_len, 0); @@ -1611,7 +1683,8 @@ info->pixmap.buf_align = 4; info->pixmap.scan_align = 4; info->pixmap.flags = FB_PIXMAP_SYSTEM; - return 0; + info->var.yres_virtual = -1; + return (rivafb_check_var(&info->var, info)); } #ifdef CONFIG_PPC_OF @@ -1645,77 +1718,35 @@ } #endif /* CONFIG_PPC_OF */ -static int riva_dfp_parse_EDID(struct riva_par *par) +static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info) { - unsigned char *block = par->EDID; - - if (!block) - return 0; + struct fb_monspecs *specs = &info->monspecs; + struct fb_videomode modedb; - /* jump to detailed timing block section */ - block += 54; - - par->clock = (block[0] + (block[1] << 8)); - par->panel_xres = (block[2] + ((block[4] & 0xf0) << 4)); - par->hblank = (block[3] + ((block[4] & 0x0f) << 8)); - par->panel_yres = (block[5] + ((block[7] & 0xf0) << 4)); - par->vblank = (block[6] + ((block[7] & 0x0f) << 8)); - par->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2)); - par->hSync_width = (block[9] + ((block[11] & 0x30) << 4)); - par->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2)); - par->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4)); - par->interlaced = ((block[17] & 0x80) >> 7); - par->synct = ((block[17] & 0x18) >> 3); - par->misc = ((block[17] & 0x06) >> 1); - par->hAct_high = par->vAct_high = 0; - if (par->synct == 3) { - if (par->misc & 2) - par->hAct_high = 1; - if (par->misc & 1) - par->vAct_high = 1; + /* respect mode options */ + if (mode_option) { + fb_find_mode(var, info, mode_option, + specs->modedb, specs->modedb_len, + NULL, 8); + } else if (specs->modedb != NULL) { + /* get preferred timing */ + if (info->monspecs.misc & FB_MISC_1ST_DETAIL) { + int i; + + for (i = 0; i < specs->modedb_len; i++) { + if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { + modedb = specs->modedb[i]; + break; + } + } + } else { + /* otherwise, get first mode in database */ + modedb = specs->modedb[0]; + } + var->bits_per_pixel = 8; + riva_update_var(var, &modedb); } - - printk(KERN_INFO PFX - "detected DFP panel size from EDID: %dx%d\n", - par->panel_xres, par->panel_yres); - par->got_dfpinfo = 1; - return 1; -} - -static void riva_update_default_var(struct fb_info *info) -{ - struct fb_var_screeninfo *var = &rivafb_default_var; - struct riva_par *par = (struct riva_par *) info->par; - - var->xres = par->panel_xres; - var->yres = par->panel_yres; - var->xres_virtual = par->panel_xres; - var->yres_virtual = par->panel_yres; - var->xoffset = var->yoffset = 0; - var->bits_per_pixel = 8; - var->pixclock = 100000000 / par->clock; - var->left_margin = (par->hblank - par->hOver_plus - par->hSync_width); - var->right_margin = par->hOver_plus; - var->upper_margin = (par->vblank - par->vOver_plus - par->vSync_width); - var->lower_margin = par->vOver_plus; - var->hsync_len = par->hSync_width; - var->vsync_len = par->vSync_width; - var->sync = 0; - - if (par->synct == 3) { - if (par->hAct_high) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (par->vAct_high) - var->sync |= FB_SYNC_VERT_HIGH_ACT; - } - - var->vmode = 0; - if (par->interlaced) - var->vmode |= FB_VMODE_INTERLACED; - var->accel_flags |= FB_ACCELF_TEXT; - - par->use_default_var = 1; } @@ -1726,19 +1757,27 @@ printk("rivafb: could not retrieve EDID from OF\n"); #else /* XXX use other methods later */ +#ifdef CONFIG_FB_RIVA_I2C + struct riva_par *par = (struct riva_par *) info->par; + + riva_create_i2c_busses(par); + riva_probe_i2c_connector(par, 1, &par->EDID); + riva_delete_i2c_busses(par); +#endif #endif } -static void riva_get_dfpinfo(struct fb_info *info) +static void riva_get_edidinfo(struct fb_info *info) { + struct fb_var_screeninfo *var = &rivafb_default_var; struct riva_par *par = (struct riva_par *) info->par; - if (riva_dfp_parse_EDID(par)) - riva_update_default_var(info); + fb_edid_to_monspecs(par->EDID, &info->monspecs); + riva_update_default_var(var, info); /* if user specified flatpanel, we respect that */ - if (par->got_dfpinfo == 1) + if (info->monspecs.input & FB_DISP_DDI) par->FlatPanel = 1; } @@ -1768,6 +1807,7 @@ memset(info, 0, sizeof(struct fb_info)); memset(default_par, 0, sizeof(struct riva_par)); + default_par->pdev = pd; info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL); if (info->pixmap.addr == NULL) @@ -1815,10 +1855,6 @@ info->par = default_par; - riva_get_EDID(info, pd); - - riva_get_dfpinfo(info); - switch (default_par->riva.Architecture) { case NV_ARCH_03: /* Riva128's PRAMIN is in the "framebuffer" space @@ -1883,6 +1919,11 @@ } #endif /* CONFIG_MTRR */ + info->fbops = &riva_fb_ops; + info->fix = rivafb_fix; + riva_get_EDID(info, pd); + riva_get_edidinfo(info); + if (riva_set_fbinfo(info) < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); goto err_out_iounmap_fb; @@ -1991,6 +2032,8 @@ } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; #endif + } else if (!strncmp(this_opt, "strictmode", 10)) { + strictmode = 1; } else mode_option = this_opt; } @@ -2039,6 +2082,8 @@ #ifdef CONFIG_MTRR MODULE_PARM(nomtrr, "i"); MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)"); +MODULE_PARM(strictmode, "i"); +MODULE_PARM_DESC(strictmode, "Only use video modes from EDID"); #endif #endif /* MODULE */ diff -Nru a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/video/riva/rivafb-i2c.c 2004-06-20 13:00:26 -07:00 @@ -0,0 +1,209 @@ +/* + * linux/drivers/video/riva/fbdev-i2c.c - nVidia i2c + * + * Maintained by Ani Joshi + * + * Copyright 2004 Antonino A. Daplas + * + * Based on radeonfb-i2c.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rivafb.h" +#include "../edid.h" + +#define RIVA_DDC 0x50 + +static void riva_gpio_setscl(void* data, int state) +{ + struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_par *par = chan->par; + u32 val; + + VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1); + val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0; + + if (state) + val |= 0x20; + else + val &= ~0x20; + + VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1); + VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1); +} + +static void riva_gpio_setsda(void* data, int state) +{ + struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_par *par = chan->par; + u32 val; + + VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1); + val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0; + + if (state) + val |= 0x10; + else + val &= ~0x10; + + VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1); + VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1); +} + +static int riva_gpio_getscl(void* data) +{ + struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_par *par = chan->par; + u32 val = 0; + + VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base); + if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04) + val = 1; + + val = VGA_RD08(par->riva.PCIO, 0x3d5); + + return val; +} + +static int riva_gpio_getsda(void* data) +{ + struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data; + struct riva_par *par = chan->par; + u32 val = 0; + + VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base); + if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x08) + val = 1; + + return val; +} + +#define I2C_ALGO_RIVA 0x0e0000 +static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name) +{ + int rc; + + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; + chan->adapter.id = I2C_ALGO_RIVA; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->pdev->dev; + chan->algo.setsda = riva_gpio_setsda; + chan->algo.setscl = riva_gpio_setscl; + chan->algo.getsda = riva_gpio_getsda; + chan->algo.getscl = riva_gpio_getscl; + chan->algo.udelay = 40; + chan->algo.timeout = 20; + chan->algo.data = chan; + + i2c_set_adapdata(&chan->adapter, chan); + + /* Raise SCL and SDA */ + riva_gpio_setsda(chan, 1); + riva_gpio_setscl(chan, 1); + udelay(20); + + rc = i2c_bit_add_bus(&chan->adapter); + if (rc == 0) + dev_dbg(&chan->par->pdev->dev, "I2C bus %s registered.\n", name); + else + dev_warn(&chan->par->pdev->dev, "Failed to register I2C bus %s.\n", name); + return rc; +} + +void riva_create_i2c_busses(struct riva_par *par) +{ + par->chan[0].par = par; + par->chan[1].par = par; + par->chan[2].par = par; + + switch (par->riva.Architecture) { +#if 0 /* no support yet for other nVidia chipsets */ + par->chan[2].ddc_base = 0x50; + riva_setup_i2c_bus(&par->chan[2], "BUS2"); +#endif + case NV_ARCH_10: + case NV_ARCH_20: + case NV_ARCH_04: + par->chan[1].ddc_base = 0x36; + riva_setup_i2c_bus(&par->chan[1], "BUS1"); + case NV_ARCH_03: + par->chan[0].ddc_base = 0x3e; + riva_setup_i2c_bus(&par->chan[0], "BUS0"); + } +} + +void riva_delete_i2c_busses(struct riva_par *par) +{ + if (par->chan[0].par) + i2c_bit_del_bus(&par->chan[0].adapter); + par->chan[0].par = NULL; + + if (par->chan[1].par) + i2c_bit_del_bus(&par->chan[1].adapter); + par->chan[1].par = NULL; + +} + +static u8 *riva_do_probe_i2c_edid(struct riva_i2c_chan *chan) +{ + u8 start = 0x0; + struct i2c_msg msgs[] = { + { + .addr = RIVA_DDC, + .len = 1, + .buf = &start, + }, { + .addr = RIVA_DDC, + .flags = I2C_M_RD, + .len = EDID_LENGTH, + }, + }; + u8 *buf; + + buf = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (!buf) { + dev_warn(&chan->par->pdev->dev, "Out of memory!\n"); + return NULL; + } + msgs[1].buf = buf; + + if (i2c_transfer(&chan->adapter, msgs, 2) == 2) + return buf; + dev_dbg(&chan->par->pdev->dev, "Unable to read EDID block.\n"); + kfree(buf); + return NULL; +} + +int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid) +{ + u8 *edid = NULL; + int i; + + for (i = 0; i < 3; i++) { + /* Do the real work */ + edid = riva_do_probe_i2c_edid(&par->chan[conn-1]); + if (edid) + break; + } + if (out_edid) + *out_edid = edid; + if (!edid) + return 1; + + return 0; +} + diff -Nru a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h --- a/drivers/video/riva/rivafb.h 2004-06-20 13:00:24 -07:00 +++ b/drivers/video/riva/rivafb.h 2004-06-20 13:00:24 -07:00 @@ -4,6 +4,10 @@ #include #include #include