Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc
authorLinus Torvalds <torvalds@woody.osdl.org>
Tue, 5 Dec 2006 03:22:33 +0000 (19:22 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Tue, 5 Dec 2006 03:22:33 +0000 (19:22 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc: (194 commits)
  [POWERPC] Add missing EXPORTS for mpc52xx support
  [POWERPC] Remove obsolete PPC_52xx and update CLASSIC32 comment
  [POWERPC] ps3: add a default zImage target
  [POWERPC] Add of_platform_bus support to mpc52xx psc uart driver
  [POWERPC] typo fix and whitespace cleanup on mpc52xx-uart driver
  [POWERPC] Fix debug printks for 32-bit resources in the PCI code
  [POWERPC] Replace kmalloc+memset with kzalloc
  [POWERPC] Linkstation / kurobox support
  [POWERPC] Add the e300c3 core to the CPU table.
  [POWERPC] ppc: m48t35 add missing bracket
  [POWERPC] iSeries: don't build head_64.o unnecessarily
  [POWERPC] iSeries: stop dt_mod.o being rebuilt unnecessarily
  [POWERPC] Fix cputable.h for combined build
  [POWERPC] Allow CONFIG_BOOTX_TEXT on iSeries
  [POWERPC] Allow xmon to build on legacy iSeries
  [POWERPC] Change ppc64_defconfig to use AUTOFS_V4 not V3
  [POWERPC] Tell firmware we can handle POWER6 compatible mode
  [POWERPC] Clean images in arch/powerpc/boot
  [POWERPC] Fix OF pci flags parsing
  [POWERPC] defconfig for lite5200 board
  ...

301 files changed:
Documentation/00-INDEX
Documentation/feature-removal-schedule.txt
Documentation/ftape.txt [deleted file]
Documentation/kernel-parameters.txt
Documentation/s390/CommonIO
Documentation/s390/Debugging390.txt
Documentation/s390/cds.txt
Documentation/s390/crypto/crypto-API.txt
Documentation/s390/s390dbf.txt
MAINTAINERS
arch/i386/kernel/acpi/cstate.c
arch/i386/kernel/alternative.c
arch/i386/kernel/cpu/mcheck/therm_throt.c
arch/m68knommu/Kconfig
arch/m68knommu/kernel/process.c
arch/m68knommu/kernel/setup.c
arch/m68knommu/kernel/sys_m68k.c
arch/m68knommu/kernel/traps.c
arch/m68knommu/platform/5307/head.S
arch/m68knommu/platform/68360/head-ram.S
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/kernel/Makefile
arch/s390/kernel/cpcmd.c
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/reipl.S
arch/s390/kernel/reipl64.S
arch/s390/kernel/relocate_kernel.S
arch/s390/kernel/relocate_kernel64.S
arch/s390/kernel/reset.S [new file with mode: 0644]
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/traps.c
arch/s390/lib/Makefile
arch/s390/lib/uaccess_mvcos.c
arch/s390/lib/uaccess_pt.c [new file with mode: 0644]
arch/s390/lib/uaccess_std.c
arch/s390/mm/extmem.c
arch/s390/mm/fault.c
drivers/acpi/dock.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_artop.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_cypress.c
drivers/ata/pata_efar.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_isapnp.c
drivers/ata/pata_it821x.c
drivers/ata/pata_ixp4xx_cf.c [new file with mode: 0644]
drivers/ata/pata_jmicron.c
drivers/ata/pata_legacy.c
drivers/ata/pata_marvell.c [new file with mode: 0644]
drivers/ata/pata_mpiix.c
drivers/ata/pata_netcell.c
drivers/ata/pata_ns87410.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_opti.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_pdc202xx_old.c
drivers/ata/pata_platform.c [new file with mode: 0644]
drivers/ata/pata_qdi.c
drivers/ata/pata_radisys.c
drivers/ata/pata_rz1000.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_serverworks.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_triflex.c
drivers/ata/pata_via.c
drivers/ata/pata_winbond.c [new file with mode: 0644]
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_sil.c
drivers/ata/sata_sil24.c
drivers/ata/sata_sis.c
drivers/base/cpu.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/ftape/Kconfig [deleted file]
drivers/char/ftape/Makefile [deleted file]
drivers/char/ftape/README.PCI [deleted file]
drivers/char/ftape/RELEASE-NOTES [deleted file]
drivers/char/ftape/compressor/Makefile [deleted file]
drivers/char/ftape/compressor/lzrw3.c [deleted file]
drivers/char/ftape/compressor/lzrw3.h [deleted file]
drivers/char/ftape/compressor/zftape-compress.c [deleted file]
drivers/char/ftape/compressor/zftape-compress.h [deleted file]
drivers/char/ftape/lowlevel/Makefile [deleted file]
drivers/char/ftape/lowlevel/fc-10.c [deleted file]
drivers/char/ftape/lowlevel/fc-10.h [deleted file]
drivers/char/ftape/lowlevel/fdc-io.c [deleted file]
drivers/char/ftape/lowlevel/fdc-io.h [deleted file]
drivers/char/ftape/lowlevel/fdc-isr.c [deleted file]
drivers/char/ftape/lowlevel/fdc-isr.h [deleted file]
drivers/char/ftape/lowlevel/ftape-bsm.c [deleted file]
drivers/char/ftape/lowlevel/ftape-bsm.h [deleted file]
drivers/char/ftape/lowlevel/ftape-buffer.c [deleted file]
drivers/char/ftape/lowlevel/ftape-buffer.h [deleted file]
drivers/char/ftape/lowlevel/ftape-calibr.c [deleted file]
drivers/char/ftape/lowlevel/ftape-calibr.h [deleted file]
drivers/char/ftape/lowlevel/ftape-ctl.c [deleted file]
drivers/char/ftape/lowlevel/ftape-ctl.h [deleted file]
drivers/char/ftape/lowlevel/ftape-ecc.c [deleted file]
drivers/char/ftape/lowlevel/ftape-ecc.h [deleted file]
drivers/char/ftape/lowlevel/ftape-format.c [deleted file]
drivers/char/ftape/lowlevel/ftape-format.h [deleted file]
drivers/char/ftape/lowlevel/ftape-init.c [deleted file]
drivers/char/ftape/lowlevel/ftape-init.h [deleted file]
drivers/char/ftape/lowlevel/ftape-io.c [deleted file]
drivers/char/ftape/lowlevel/ftape-io.h [deleted file]
drivers/char/ftape/lowlevel/ftape-proc.c [deleted file]
drivers/char/ftape/lowlevel/ftape-proc.h [deleted file]
drivers/char/ftape/lowlevel/ftape-read.c [deleted file]
drivers/char/ftape/lowlevel/ftape-read.h [deleted file]
drivers/char/ftape/lowlevel/ftape-rw.c [deleted file]
drivers/char/ftape/lowlevel/ftape-rw.h [deleted file]
drivers/char/ftape/lowlevel/ftape-setup.c [deleted file]
drivers/char/ftape/lowlevel/ftape-tracing.c [deleted file]
drivers/char/ftape/lowlevel/ftape-tracing.h [deleted file]
drivers/char/ftape/lowlevel/ftape-write.c [deleted file]
drivers/char/ftape/lowlevel/ftape-write.h [deleted file]
drivers/char/ftape/lowlevel/ftape_syms.c [deleted file]
drivers/char/ftape/zftape/Makefile [deleted file]
drivers/char/ftape/zftape/zftape-buffers.c [deleted file]
drivers/char/ftape/zftape/zftape-buffers.h [deleted file]
drivers/char/ftape/zftape/zftape-ctl.c [deleted file]
drivers/char/ftape/zftape/zftape-ctl.h [deleted file]
drivers/char/ftape/zftape/zftape-eof.c [deleted file]
drivers/char/ftape/zftape/zftape-eof.h [deleted file]
drivers/char/ftape/zftape/zftape-init.c [deleted file]
drivers/char/ftape/zftape/zftape-init.h [deleted file]
drivers/char/ftape/zftape/zftape-read.c [deleted file]
drivers/char/ftape/zftape/zftape-read.h [deleted file]
drivers/char/ftape/zftape/zftape-rw.c [deleted file]
drivers/char/ftape/zftape/zftape-rw.h [deleted file]
drivers/char/ftape/zftape/zftape-vtbl.c [deleted file]
drivers/char/ftape/zftape/zftape-vtbl.h [deleted file]
drivers/char/ftape/zftape/zftape-write.c [deleted file]
drivers/char/ftape/zftape/zftape-write.h [deleted file]
drivers/char/ftape/zftape/zftape_syms.c [deleted file]
drivers/char/hpet.c
drivers/char/hw_random/core.c
drivers/char/tpm/tpm.h
drivers/hwmon/abituguru.c
drivers/hwmon/hdaps.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/isdn/divert/isdn_divert.c
drivers/leds/ledtrig-ide-disk.c
drivers/leds/ledtrig-timer.c
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/net/ehea/ehea_qmr.c
drivers/net/lance.c
drivers/net/ne3210.c
drivers/net/sk98lin/skge.c
drivers/net/starfire.c
drivers/net/sun3lance.c
drivers/net/sungem.c
drivers/net/sunhme.c
drivers/net/typhoon.c
drivers/pci/access.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/char/con3215.c
drivers/s390/char/sclp_quiesce.c
drivers/s390/cio/chsc.c
drivers/s390/cio/cio.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_id.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/device_status.c
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/crypto/ap_bus.c
drivers/s390/net/lcs.c
drivers/s390/net/lcs.h
drivers/s390/net/qeth.h
drivers/s390/net/qeth_main.c
drivers/scsi/scsi_transport_sas.c
drivers/spi/spi_butterfly.c
drivers/w1/slaves/w1_therm.c
fs/9p/conv.c
fs/9p/fcall.c
fs/9p/fid.c
fs/9p/v9fs.c
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/compat.c
fs/gfs2/locking/dlm/plock.c
fs/inotify.c
fs/jffs2/acl.c
fs/jffs2/wbuf.c
fs/jfs/ioctl.c
fs/partitions/mac.c
fs/proc/root.c
fs/super.c
fs/sync.c
fs/utimes.c
include/asm-arm/arch-ixp4xx/platform.h
include/asm-m68knommu/dma-mapping.h
include/asm-m68knommu/m520xsim.h
include/asm-m68knommu/scatterlist.h
include/asm-s390/cio.h
include/asm-s390/cpcmd.h
include/asm-s390/kexec.h
include/asm-s390/lowcore.h
include/asm-s390/pgtable.h
include/asm-s390/reset.h [new file with mode: 0644]
include/asm-s390/setup.h
include/asm-s390/smp.h
include/asm-s390/system.h
include/asm-s390/termios.h
include/asm-s390/uaccess.h
include/asm-s390/zcrypt.h
include/asm-x86_64/elf.h
include/asm-x86_64/uaccess.h
include/linux/Kbuild
include/linux/acct.h
include/linux/ata.h
include/linux/fs.h
include/linux/ftape-header-segment.h [deleted file]
include/linux/ftape-vendors.h [deleted file]
include/linux/ftape.h [deleted file]
include/linux/igmp.h
include/linux/kernelcapi.h
include/linux/libata.h
include/linux/module.h
include/linux/netdevice.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/pata_platform.h [new file with mode: 0644]
include/linux/poll.h
include/linux/radix-tree.h
include/linux/skbuff.h
include/linux/zftape.h [deleted file]
include/net/inet_connection_sock.h
include/net/irda/timer.h
include/net/netfilter/nf_conntrack.h
include/net/netlink.h
include/net/sock.h
include/net/udp.h
include/scsi/libiscsi.h
include/sound/pcm.h
kernel/auditsc.c
kernel/latency.c
kernel/module.c
lib/random32.c
net/appletalk/ddp.c
net/core/kmap_skb.h [new file with mode: 0644]
net/core/skbuff.c
net/core/sock.c
net/dccp/ccids/Kconfig
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.h
net/dccp/ccids/lib/tfrc_equation.c
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_crypt_wep.c
net/ipv4/ip_output.c
net/ipv4/ipvs/ip_vs_lblc.c
net/ipv4/ipvs/ip_vs_lblcr.c
net/irda/discovery.c
net/irda/iriap.c
net/irda/irttp.c
net/netfilter/nf_conntrack_core.c
net/netfilter/x_tables.c
net/netfilter/xt_hashlimit.c
net/packet/af_packet.c
net/xfrm/xfrm_user.c
sound/oss/cs46xx.c
sound/oss/dmabuf.c
sound/oss/emu10k1/audio.c
sound/oss/es1371.c
sound/oss/i810_audio.c
sound/oss/soundcard.c
sound/oss/sscape.c
sound/oss/trident.c

index 02457ec9c94fe27ec74dc943186283137774e232..f08ca953573392ec710a27db0f7f87f14ad54527 100644 (file)
@@ -104,8 +104,6 @@ firmware_class/
        - request_firmware() hotplug interface info.
 floppy.txt
        - notes and driver options for the floppy disk driver.
-ftape.txt
-       - notes about the floppy tape device driver.
 hayes-esp.txt
        - info on using the Hayes ESP serial driver.
 highuid.txt
index f81819364b7ab9ebade50ccc24ed494219160ed6..226ecf2ffd568158a2927b24e27e21bde00b6d30 100644 (file)
@@ -234,14 +234,6 @@ Who:       Jean Delvare <khali@linux-fr.org>
 
 ---------------------------
 
-What:  ftape
-When:  2.6.20
-Why:   Orphaned for ages.  SMP bugs long unfixed.  Few users left
-       in the world.
-Who:   Jeff Garzik <jeff@garzik.org>
-
----------------------------
-
 What:  IPv4 only connection tracking/NAT/helpers
 When:  2.6.22
 Why:   The new layer 3 independant connection tracking replaces the old
diff --git a/Documentation/ftape.txt b/Documentation/ftape.txt
deleted file mode 100644 (file)
index 7d8bb33..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-Intro
-=====
-
-This file describes some issues involved when using the "ftape"
-floppy tape device driver that comes with the Linux kernel.
-
-ftape has a home page at
-
-http://ftape.dot-heine.de/
-
-which contains further information about ftape. Please cross check
-this WWW address against the address given (if any) in the MAINTAINERS
-file located in the top level directory of the Linux kernel source
-tree.
-
-NOTE: This is an unmaintained set of drivers, and it is not guaranteed to work.
-If you are interested in taking over maintenance, contact Claus-Justus Heine
-<ch@dot-heine.de>, the former maintainer.
-
-Contents
-========
-
-A minus 1: Ftape documentation
-
-A. Changes
-   1. Goal
-   2. I/O Block Size
-   3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)
-   4. Formatting
-   5. Interchanging cartridges with other operating systems
-
-B. Debugging Output
-   1. Introduction
-   2. Tuning the debugging output
-
-C. Boot and load time configuration
-   1. Setting boot time parameters
-   2. Module load time parameters
-   3. Ftape boot- and load time options
-   4. Example kernel parameter setting
-   5. Example module parameter setting
-
-D. Support and contacts
-
-*******************************************************************************
-
-A minus 1. Ftape documentation
-==============================
-
-Unluckily, the ftape-HOWTO is out of date. This really needs to be
-changed. Up to date documentation as well as recent development
-versions of ftape and useful links to related topics can be found at
-the ftape home page at
-
-http://ftape.dot-heine.de/
-
-*******************************************************************************
-
-A. Changes
-==========
-
-1. Goal
-   ~~~~
-   The goal of all that incompatibilities was to give ftape an interface
-   that resembles the interface provided by SCSI tape drives as close
-   as possible. Thus any Unix backup program that is known to work
-   with SCSI tape drives should also work.
-
-   The concept of a fixed block size for read/write transfers is
-   rather unrelated to this SCSI tape compatibility at the file system
-   interface level. It developed out of a feature of zftape, a
-   block wise user transparent on-the-fly compression. That compression
-   support will not be dropped in future releases for compatibility
-   reasons with previous releases of zftape.
-
-2. I/O Block Size
-   ~~~~~~~~~~~~~~
-   The block size defaults to 10k which is the default block size of
-   GNU tar.
-
-   The block size can be tuned either during kernel configuration or
-   at runtime with the MTIOCTOP ioctl using the MTSETBLK operation
-   (i.e. do "mt -f /dev/qft0" setblk #BLKSZ). A block size of 0
-   switches to variable block size mode i.e. "mt setblk 0" switches
-   off the block size restriction. However, this disables zftape's
-   built in on-the-fly compression which doesn't work with variable
-   block size mode.
-
-   The BLKSZ parameter must be given as a byte count and must be a
-   multiple of 32k or 0, i.e. use "mt setblk 32768" to switch to a
-   block size of 32k.
-
-   The typical symptom of a block size mismatch is an "invalid
-   argument" error message.
-
-3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   zftape (the file system interface of ftape-3.x) denies write access
-   to the tape cartridge when it isn't positioned either at BOT or
-   EOD.
-
-4. Formatting
-   ~~~~~~~~~~
-   ftape DOES support formatting of floppy tape cartridges. You need the
-   `ftformat' program that is shipped with the modules version of ftape.
-   Please get the latest version of ftape from
-
-   ftp://sunsite.unc.edu/pub/Linux/kernel/tapes
-
-   or from the ftape home page at
-
-   http://ftape.dot-heine.de/
-
-   `ftformat' is contained in the `./contrib/' subdirectory of that
-   separate ftape package.
-
-5. Interchanging cartridges with other operating systems
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-   The internal emulation of Unix tape device file marks has changed
-   completely. ftape now uses the volume table segment as specified
-   by the QIC-40/80/3010/3020/113 standards to emulate file marks. As
-   a consequence there is limited support to interchange cartridges
-   with other operating systems.
-
-   To be more precise: ftape will detect volumes written by other OS's
-   programs and other OS's programs will detect volumes written by
-   ftape.
-
-   However, it isn't possible to extract the data dumped to the tape
-   by some MSDOS program with ftape. This exceeds the scope of a
-   kernel device driver. If you need such functionality, then go ahead
-   and write a user space utility that is able to do that. ftape already
-   provides all kernel level support necessary to do that.
-
-*******************************************************************************
-
-B. Debugging Output
-   ================
-
-1. Introduction
-   ~~~~~~~~~~~~
-   The ftape driver can be very noisy in that is can print lots of
-   debugging messages to the kernel log files and the system console.
-   While this is useful for debugging it might be annoying during
-   normal use and enlarges the size of the driver by several kilobytes.
-
-   To reduce the size of the driver you can trim the maximal amount of
-   debugging information available during kernel configuration. Please
-   refer to the kernel configuration script and its on-line help
-   functionality.
-
-   The amount of debugging output maps to the "tracing" boot time
-   option and the "ft_tracing" modules option as follows:
-
-   0              bugs
-   1              + errors (with call-stack dump)
-   2              + warnings
-   3              + information
-   4              + more information
-   5              + program flow
-   6              + fdc/dma info
-   7              + data flow
-   8              + everything else
-
-2. Tuning the debugging output
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   To reduce the amount of debugging output printed to the system
-   console you can
-
-   i)  trim the debugging output at run-time with
-
-       mt -f /dev/nqft0 setdensity #DBGLVL
-
-       where "#DBGLVL" is a number between 0 and 9
-
-   ii) trim the debugging output at module load time with
-
-       modprobe ftape ft_tracing=#DBGLVL
-
-       Of course, this applies only if you have configured ftape to be
-       compiled as a module.
-
-   iii) trim the debugging output during system boot time. Add the
-       following to the kernel command line:
-
-       ftape=#DBGLVL,tracing
-
-       Please refer also to the next section if you don't know how to
-       set boot time parameters.
-
-*******************************************************************************
-
-C. Boot and load time configuration
-   ================================
-
-1. Setting boot time parameters
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
-   Assuming that you use lilo, the LI)nux LO)ader, boot time kernel
-   parameters can be set by adding a line
-
-   append some_kernel_boot_time_parameter
-
-   to `/etc/lilo.conf' or at real boot time by typing in the options
-   at the prompt provided by LILO. I can't give you advice on how to
-   specify those parameters with other loaders as I don't use them.
-
-   For ftape, each "some_kernel_boot_time_parameter" looks like
-   "ftape=value,option". As an example, the debugging output can be
-   increased with
-
-   ftape=4,tracing
-
-   NOTE: the value precedes the option name.
-
-2. Module load time parameters
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   Module parameters can be specified either directly when invoking
-   the program 'modprobe' at the shell prompt:
-
-   modprobe ftape ft_tracing=4
-
-   or by editing the file `/etc/modprobe.conf' in which case they take
-   effect each time when the module is loaded with `modprobe' (please
-   refer to the respective manual pages). Thus, you should add a line
-
-   options ftape ft_tracing=4
-
-   to `/etc/modprobe.conf` if you intend to increase the debugging
-   output of the driver.
-
-
-3. Ftape boot- and load time options
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-   i.   Controlling the amount of debugging output
-        DBGLVL has to be replaced by a number between 0 and 8.
-
-        module                 |  kernel command line
-        -----------------------|----------------------
-        ft_tracing=DBGLVL      |  ftape=DBGLVL,tracing
-
-   ii.  Hardware setup
-       BASE is the base address of your floppy disk controller,
-        IRQ and DMA give its interrupt and DMA channel, respectively.
-        BOOL is an integer, "0" means "no"; any other value means
-       "yes". You don't need to specify anything if connecting your tape
-        drive to the standard floppy disk controller. All of these
-       values have reasonable defaults. The defaults can be modified
-       during kernel configuration, i.e. while running "make config",
-       "make menuconfig" or "make xconfig" in the top level directory
-       of the Linux kernel source tree. Please refer also to the on
-       line documentation provided during that kernel configuration
-       process.
-
-       ft_probe_fc10 is set to a non-zero value if you wish for ftape to
-       probe for a Colorado FC-10 or FC-20 controller.
-
-       ft_mach2 is set to a non-zero value if you wish for ftape to probe
-       for a Mountain MACH-2 controller.
-
-        module                 |  kernel command line
-        -----------------------|----------------------
-        ft_fdc_base=BASE       |  ftape=BASE,ioport
-        ft_fdc_irq=IRQ         |  ftape=IRQ,irq
-        ft_fdc_dma=DMA         |  ftape=DMA,dma
-        ft_probe_fc10=BOOL     |  ftape=BOOL,fc10
-        ft_mach2=BOOL          |  ftape=BOOL,mach2
-        ft_fdc_threshold=THR   |  ftape=THR,threshold
-        ft_fdc_rate_limit=RATE |  ftape=RATE,datarate
-
-4. Example kernel parameter setting
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
-   To configure ftape to probe for a Colorado FC-10/FC-20 controller
-   and to increase the amount of debugging output a little bit, add
-   the following line to `/etc/lilo.conf':
-
-   append ftape=1,fc10 ftape=4,tracing
-
-5. Example module parameter setting
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   To do the same, but with ftape compiled as a loadable kernel
-   module, add the following line to `/etc/modprobe.conf':
-
-   options ftape ft_probe_fc10=1 ft_tracing=4
-
-*******************************************************************************
-
-D. Support and contacts
-   ====================
-
-   Ftape is distributed under the GNU General Public License. There is
-   absolutely no warranty for this software. However, you can reach
-   the current maintainer of the ftape package under the email address
-   given in the MAINTAINERS file which is located in the top level
-   directory of the Linux kernel source tree. There you'll find also
-   the relevant mailing list to use as a discussion forum and the web
-   page to query for the most recent documentation, related work and
-   development versions of ftape.
-
-   Changelog:
-   ==========
-
-~1996:         Original Document
-
-10-24-2004:    General cleanup and updating, noting additional module options.
-               James Nelson <james4765@gmail.com>
index 67473849f20e0e42cc4d2ef6ae015634b4c830ba..15e4fed127f69bd3200d2a8ae1e59832570def7e 100644 (file)
@@ -557,9 +557,6 @@ and is between 256 and 4096 characters. It is defined in the file
        floppy=         [HW]
                        See Documentation/floppy.txt.
 
-       ftape=          [HW] Floppy Tape subsystem debugging options.
-                       See Documentation/ftape.txt.
-
        gamecon.map[2|3]=
                        [HW,JOY] Multisystem joystick and NES/SNES/PSX pad
                        support via parallel port (up to 5 devices per port)
index d684a6ac69a8ec2b8e06016f31e23bef2faf5130..22f82f21bc605395b4fa34d7a85cc8ad63bd2e07 100644 (file)
@@ -74,7 +74,7 @@ Command line parameters
 
   Note: While already known devices can be added to the list of devices to be
         ignored, there will be no effect on then. However, if such a device
-        disappears and then reappeares, it will then be ignored.
+       disappears and then reappears, it will then be ignored.
 
   For example,
        "echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
@@ -82,7 +82,7 @@ Command line parameters
   devices.
 
   The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward
-  compatibilty, by the device number in hexadecimal (0xabcd or abcd).
+  compatibility, by the device number in hexadecimal (0xabcd or abcd).
 
 
 * /proc/s390dbf/cio_*/ (S/390 debug feature)
index 4dd25ee549e9d14aa1b431e5cabd44c2e320a8fd..3f9ddbc23b27111db424af21d7c0b92cc34f9e68 100644 (file)
@@ -7,7 +7,7 @@
 
 Overview of Document:
 =====================
-This document is intended to give an good overview of how to debug 
+This document is intended to give a good overview of how to debug
 Linux for s/390 & z/Architecture. It isn't intended as a complete reference & not a
 tutorial on the fundamentals of C & assembly. It doesn't go into
 390 IO in any detail. It is intended to complement the documents in the
@@ -300,7 +300,7 @@ On z/Architecture our page indexes are now 2k in size
 but only mess with 2 segment indices each time we mess with
 a PMD.
 
-3) As z/Architecture supports upto a massive 5-level page table lookup we 
+3) As z/Architecture supports up to a massive 5-level page table lookup we
 can only use 3 currently on Linux ( as this is all the generic kernel
 currently supports ) however this may change in future
 this allows us to access ( according to my sums )
@@ -502,7 +502,7 @@ Notes:
 ------
 1) The only requirement is that registers which are used
 by the callee are saved, e.g. the compiler is perfectly
-capible of using r11 for purposes other than a frame a
+capable of using r11 for purposes other than a frame a
 frame pointer if a frame pointer is not needed.
 2) In functions with variable arguments e.g. printf the calling procedure 
 is identical to one without variable arguments & the same number of 
@@ -846,7 +846,7 @@ of time searching for debugging info. The following self explanatory line should
 instead if the code isn't compiled -g, as it is much faster:
 objdump --disassemble-all --syms vmlinux > vmlinux.lst  
 
-As hard drive space is valuble most of us use the following approach.
+As hard drive space is valuable most of us use the following approach.
 1) Look at the emitted psw on the console to find the crash address in the kernel.
 2) Look at the file System.map ( in the linux directory ) produced when building 
 the kernel to find the closest address less than the current PSW to find the
@@ -902,7 +902,7 @@ A. It is a tool for intercepting calls to the kernel & logging them
 to a file & on the screen.
 
 Q. What use is it ?
-A. You can used it to find out what files a particular program opens.
+A. You can use it to find out what files a particular program opens.
 
 
 
@@ -911,7 +911,7 @@ Example 1
 If you wanted to know does ping work but didn't have the source 
 strace ping -c 1 127.0.0.1  
 & then look at the man pages for each of the syscalls below,
-( In fact this is sometimes easier than looking at some spagetti
+( In fact this is sometimes easier than looking at some spaghetti
 source which conditionally compiles for several architectures ).
 Not everything that it throws out needs to make sense immediately.
 
@@ -1037,7 +1037,7 @@ e.g. man strace, man alarm, man socket.
 
 Performance Debugging
 =====================
-gcc is capible of compiling in profiling code just add the -p option
+gcc is capable of compiling in profiling code just add the -p option
 to the CFLAGS, this obviously affects program size & performance.
 This can be used by the gprof gnu profiling tool or the
 gcov the gnu code coverage tool ( code coverage is a means of testing
@@ -1419,7 +1419,7 @@ On a SMP guest issue a command to all CPUs try prefixing the command with cpu al
 To issue a command to a particular cpu try cpu <cpu number> e.g.
 CPU 01 TR I R 2000.3000
 If you are running on a guest with several cpus & you have a IO related problem
-& cannot follow the flow of code but you know it isnt smp related.
+& cannot follow the flow of code but you know it isn't smp related.
 from the bash prompt issue
 shutdown -h now or halt.
 do a Q CPUS to find out how many cpus you have
@@ -1602,7 +1602,7 @@ V000FFFD0  00010400 80010802 8001085A 000FFFA0
 our 3rd return address is 8001085A
 
 as the 04B52002 looks suspiciously like rubbish it is fair to assume that the kernel entry routines
-for the sake of optimisation dont set up a backchain.
+for the sake of optimisation don't set up a backchain.
 
 now look at System.map to see if the addresses make any sense.
 
@@ -1638,11 +1638,11 @@ more useful information.
 
 Unlike other bus architectures modern 390 systems do their IO using mostly
 fibre optics & devices such as tapes & disks can be shared between several mainframes,
-also S390 can support upto 65536 devices while a high end PC based system might be choking 
+also S390 can support up to 65536 devices while a high end PC based system might be choking
 with around 64. Here is some of the common IO terminology
 
 Subchannel:
-This is the logical number most IO commands use to talk to an IO device there can be upto
+This is the logical number most IO commands use to talk to an IO device there can be up to
 0x10000 (65536) of these in a configuration typically there is a few hundred. Under VM
 for simplicity they are allocated contiguously, however on the native hardware they are not
 they typically stay consistent between boots provided no new hardware is inserted or removed.
@@ -1651,7 +1651,7 @@ HALT SUBCHANNEL,MODIFY SUBCHANNEL,RESUME SUBCHANNEL,START SUBCHANNEL,STORE SUBCH
 TEST SUBCHANNEL ) we use this as the ID of the device we wish to talk to, the most
 important of these instructions are START SUBCHANNEL ( to start IO ), TEST SUBCHANNEL ( to check
 whether the IO completed successfully ), & HALT SUBCHANNEL ( to kill IO ), a subchannel
-can have up to 8 channel paths to a device this offers redunancy if one is not available.
+can have up to 8 channel paths to a device this offers redundancy if one is not available.
 
 
 Device Number:
@@ -1659,7 +1659,7 @@ This number remains static & Is closely tied to the hardware, there are 65536 of
 also they are made up of a CHPID ( Channel Path ID, the most significant 8 bits ) 
 & another lsb 8 bits. These remain static even if more devices are inserted or removed
 from the hardware, there is a 1 to 1 mapping between Subchannels & Device Numbers provided
-devices arent inserted or removed.
+devices aren't inserted or removed.
 
 Channel Control Words:
 CCWS are linked lists of instructions initially pointed to by an operation request block (ORB),
@@ -1674,7 +1674,7 @@ concurrently, you check how the IO went on by issuing a TEST SUBCHANNEL at each
 from which you receive an Interruption response block (IRB). If you get channel & device end 
 status in the IRB without channel checks etc. your IO probably went okay. If you didn't you
 probably need a doctor to examine the IRB & extended status word etc.
-If an error occurs, more sophistocated control units have a facitity known as
+If an error occurs, more sophisticated control units have a facility known as
 concurrent sense this means that if an error occurs Extended sense information will
 be presented in the Extended status word in the IRB if not you have to issue a
 subsequent SENSE CCW command after the test subchannel. 
@@ -1749,7 +1749,7 @@ Interface (OEMI).
 This byte wide Parallel channel path/bus has parity & data on the "Bus" cable 
 & control lines on the "Tag" cable. These can operate in byte multiplex mode for
 sharing between several slow devices or burst mode & monopolize the channel for the
-whole burst. Upto 256 devices can be addressed  on one of these cables. These cables are
+whole burst. Up to 256 devices can be addressed  on one of these cables. These cables are
 about one inch in diameter. The maximum unextended length supported by these cables is
 125 Meters but this can be extended up to 2km with a fibre optic channel extended 
 such as a 3044. The maximum burst speed supported is 4.5 megabytes per second however
@@ -1759,7 +1759,7 @@ One of these paths can be daisy chained to up to 8 control units.
 
 ESCON if fibre optic it is also called FICON 
 Was introduced by IBM in 1990. Has 2 fibre optic cables & uses either leds or lasers
-for communication at a signaling rate of upto 200 megabits/sec. As 10bits are transferred
+for communication at a signaling rate of up to 200 megabits/sec. As 10bits are transferred
 for every 8 bits info this drops to 160 megabits/sec & to 18.6 Megabytes/sec once
 control info & CRC are added. ESCON only operates in burst mode.
  
@@ -1767,7 +1767,7 @@ ESCONs typical max cable length is 3km for the led version & 20km for the laser
 known as XDF ( extended distance facility ). This can be further extended by using an
 ESCON director which triples the above mentioned ranges. Unlike Bus & Tag as ESCON is
 serial it uses a packet switching architecture the standard Bus & Tag control protocol
-is however present within the packets. Upto 256 devices can be attached to each control 
+is however present within the packets. Up to 256 devices can be attached to each control
 unit that uses one of these interfaces.
 
 Common 390 Devices include:
@@ -2050,7 +2050,7 @@ list test.c:1,10
 
 directory:
 Adds directories to be searched for source if gdb cannot find the source.
-(note it is a bit sensititive about slashes) 
+(note it is a bit sensitive about slashes)
 e.g. To add the root of the filesystem to the searchpath do
 directory //
 
@@ -2152,7 +2152,7 @@ program as if it just crashed on your system, it is usually called core & create
 current working directory.
 This is very useful in that a customer can mail a core dump to a technical support department
 & the technical support department can reconstruct what happened.
-Provided the have an identical copy of this program with debugging symbols compiled in & 
+Provided they have an identical copy of this program with debugging symbols compiled in &
 the source base of this build is available.
 In short it is far more useful than something like a crash log could ever hope to be.
 
index 32a96cc392151abf7e04f505069e5a6499c80860..05a2b4f7e38f7ea17256d3f59461e68a04c485f7 100644 (file)
@@ -98,7 +98,7 @@ The following chapters describe the I/O related interface routines the
 Linux/390 common device support (CDS) provides to allow for device specific
 driver implementations on the IBM ESA/390 hardware platform. Those interfaces
 intend to provide the functionality required by every device driver
-implementaion to allow to drive a specific hardware device on the ESA/390
+implementation to allow to drive a specific hardware device on the ESA/390
 platform. Some of the interface routines are specific to Linux/390 and some
 of them can be found on other Linux platforms implementations too.
 Miscellaneous function prototypes, data declarations, and macro definitions
@@ -114,7 +114,7 @@ the ESA/390 architecture has implemented a so called channel subsystem, that
 provides a unified view of the devices physically attached to the systems.
 Though the ESA/390 hardware platform knows about a huge variety of different
 peripheral attachments like disk devices (aka. DASDs), tapes, communication
-controllers, etc. they can all by accessed by a well defined access method and
+controllers, etc. they can all be accessed by a well defined access method and
 they are presenting I/O completion a unified way : I/O interruptions. Every
 single device is uniquely identified to the system by a so called subchannel,
 where the ESA/390 architecture allows for 64k devices be attached.
@@ -338,7 +338,7 @@ DOIO_REPORT_ALL          - report all interrupt conditions
 The ccw_device_start() function returns :
 
       0 - successful completion or request successfully initiated
--EBUSY  - The device is currently processing a previous I/O request, or ther is
+-EBUSY - The device is currently processing a previous I/O request, or there is
           a status pending at the device.
 -ENODEV - cdev is invalid, the device is not operational or the ccw_device is
           not online.
@@ -361,7 +361,7 @@ first:
 -EIO:       the common I/O layer terminated the request due to an error state
 
 If the concurrent sense flag in the extended status word in the irb is set, the
-field irb->scsw.count describes the numer of device specific sense bytes
+field irb->scsw.count describes the number of device specific sense bytes
 available in the extended control word irb->scsw.ecw[0]. No device sensing by
 the device driver itself is required.
 
@@ -410,7 +410,7 @@ ccw_device_start() must be called disabled and with the ccw device lock held.
 
 The device driver is allowed to issue the next ccw_device_start() call from
 within its interrupt handler already. It is not required to schedule a
-bottom-half, unless an non deterministically long running error recovery procedure
+bottom-half, unless a non deterministically long running error recovery procedure
 or similar needs to be scheduled. During I/O processing the Linux/390 generic
 I/O device driver support has already obtained the IRQ lock, i.e. the handler
 must not try to obtain it again when calling ccw_device_start() or we end in a
@@ -431,7 +431,7 @@ information prior to device-end the device driver urgently relies on. In this
 case all I/O interruptions are presented to the device driver until final
 status is recognized.
 
-If a device is able to recover from asynchronosly presented I/O errors, it can
+If a device is able to recover from asynchronously presented I/O errors, it can
 perform overlapping I/O using the DOIO_EARLY_NOTIFICATION flag. While some
 devices always report channel-end and device-end together, with a single
 interrupt, others present primary status (channel-end) when the channel is
index 41a8b07da05ad48c2ee048e28c3b0541b4960ee3..71ae6ca9f2c24ae68f1da9a379a844865ceb6c62 100644 (file)
@@ -17,8 +17,8 @@ arch/s390/crypto directory.
 2. Probing for availability of MSA
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 It should be possible to use Kernels with the z990 crypto implementations both
-on machines with MSA available an on those without MSA (pre z990 or z990
-without MSA). Therefore a simple probing mechanisms has been implemented:
+on machines with MSA available and on those without MSA (pre z990 or z990
+without MSA). Therefore a simple probing mechanism has been implemented:
 In the init function of each crypto module the availability of MSA and of the
 respective crypto algorithm in particular will be tested. If the algorithm is
 available the module will load and register its algorithm with the crypto API.
@@ -26,7 +26,7 @@ available the module will load and register its algorithm with the crypto API.
 If the respective crypto algorithm is not available, the init function will
 return -ENOSYS. In that case a fallback to the standard software implementation
 of the crypto algorithm must be taken ( -> the standard crypto modules are
-also build when compiling the kernel).
+also built when compiling the kernel).
 
 
 3. Ensuring z990 crypto module preference
index 000230cd26dbe49659b5d8001ba7fda3ffb1cbad..0eb7c58916de4821abf9c954753567efac58f375 100644 (file)
@@ -36,7 +36,7 @@ switches to the next debug area. This is done in order to be sure
 that the records which describe the origin of the exception are not
 overwritten when a wrap around for the current area occurs.
 
-The debug areas itselve are also ordered in form of a ring buffer. 
+The debug areas themselves are also ordered in form of a ring buffer.
 When an exception is thrown in the last debug area, the following debug 
 entries are then written again in the very first area.
 
@@ -55,7 +55,7 @@ The debug logs can be inspected in a live system through entries in
 the debugfs-filesystem. Under the toplevel directory "s390dbf" there is
 a directory for each registered component, which is named like the
 corresponding component. The debugfs normally should be mounted to
-/sys/kernel/debug therefore the debug feature can be accessed unter
+/sys/kernel/debug therefore the debug feature can be accessed under
 /sys/kernel/debug/s390dbf.
 
 The content of the directories are files which represent different views
@@ -87,11 +87,11 @@ There are currently 2 possible triggers, which stop the debug feature
 globally. The first possibility is to use the "debug_active" sysctl. If
 set to 1 the debug feature is running. If "debug_active" is set to 0 the
 debug feature is turned off.
-The second trigger which stops the debug feature is an kernel oops.
+The second trigger which stops the debug feature is a kernel oops.
 That prevents the debug feature from overwriting debug information that
 happened before the oops. After an oops you can reactivate the debug feature
 by piping 1 to /proc/sys/s390dbf/debug_active. Nevertheless, its not
-suggested to use an oopsed kernel in an production environment.
+suggested to use an oopsed kernel in a production environment.
 If you want to disallow the deactivation of the debug feature, you can use
 the "debug_stoppable" sysctl. If you set "debug_stoppable" to 0 the debug
 feature cannot be stopped. If the debug feature is already stopped, it
index fd3b2ca0c0317e1caa35b54778dfa74635e2bd7e..5dff26814a06067c6122816fced3ce675638747d 100644 (file)
@@ -1166,11 +1166,6 @@ P:       David Howells
 M:     dhowells@redhat.com
 S:     Maintained
 
-FTAPE/QIC-117
-L:     linux-tape@vger.kernel.org
-W:     http://sourceforge.net/projects/ftape
-S:     Orphan
-
 FUSE: FILESYSTEM IN USERSPACE
 P:     Miklos Szeredi
 M:     miklos@szeredi.hu
index 20563e52c62248853e9d4fbc9af48461c27696bd..4664b55f623ef2b349a510c0dcd487d8149063c3 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/cpu.h>
+#include <linux/sched.h>
 
 #include <acpi/processor.h>
 #include <asm/acpi.h>
index 583c238e17fb2e9550fbbcb490ba1a41288b97dc..535f9794fba1aa811cb7a1ea270fa3c285fc0f98 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <asm/alternative.h>
index 2d8703b7ce65ead94dc3d6d26cf37421ad87d236..bad8b4420709c3ee984dc89476929ad953e5d7a9 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/cpu.h>
 #include <asm/cpu.h>
 #include <linux/notifier.h>
+#include <linux/jiffies.h>
 #include <asm/therm_throt.h>
 
 /* How long to wait between reporting thermal events */
index c1bc22c6d0d817e019a7022450b00425c52df587..aa70dde54228266f55027b7544e4de6520215af9 100644 (file)
@@ -173,7 +173,7 @@ config CLOCK_DIV
          On many SoC style CPUs the master CPU clock is also used to drive 
          on-chip peripherals. The clock that is distributed to these
          peripherals is sometimes a fixed ratio of the master clock
-         frequency. If so then set this to the divider ration of the
+         frequency. If so then set this to the divider ratio of the
          master clock to the peripheral clock. If not sure then select 1.
 
 config OLDMASK
@@ -192,7 +192,7 @@ config PILOT3
          Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
 
 config XCOPILOT_BUGS
-       bool "  (X)Copilot support"
+       bool "(X)Copilot support"
        depends on PILOT3
        help
          Support the bugs of Xcopilot.
@@ -216,20 +216,20 @@ config DRAGEN2
          Support for the DragenEngine II board.
 
 config DIRECT_IO_ACCESS
-       bool "  Allow user to access IO directly"
+       bool "Allow user to access IO directly"
        depends on (UCSIMM || UCDIMM || DRAGEN2)
        help
          Disable the CPU internal registers protection in user mode,
           to allow a user application to read/write them.
 
 config INIT_LCD
-       bool "  Initialize LCD"
+       bool "Initialize LCD"
        depends on (UCSIMM || UCDIMM || DRAGEN2)
        help
          Initialize the LCD controller of the 68x328 processor.
 
 config MEMORY_RESERVE
-       int "  Memory reservation (MiB)"
+       int "Memory reservation (MiB)"
        depends on (UCSIMM || UCDIMM)
        help
          Reserve certain memory regions on 68x328 based boards.
@@ -409,7 +409,7 @@ config MOD5272
          Support for the Netburner MOD-5272 board.
 
 config ROMFS_FROM_ROM
-       bool "  ROMFS image not RAM resident"
+       bool "ROMFS image not RAM resident"
        depends on (NETtel || SNAPGEAR)
        help
          The ROMfs filesystem will stay resident in the FLASH/ROM, not be
index c18a83306953c663079faaac5d573ffbfffc78ca..941955dc3b7c5bab8e8c42ee492db86891faff96 100644 (file)
@@ -290,7 +290,7 @@ void dump(struct pt_regs *fp)
        unsigned char   *tp;
        int             i;
 
-       printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
+       printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n");
        printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
 
        if (current->mm) {
@@ -301,7 +301,8 @@ void dump(struct pt_regs *fp)
                        (int) current->mm->end_data,
                        (int) current->mm->end_data,
                        (int) current->mm->brk);
-               printk(KERN_EMERG "USER-STACK=%08x  KERNEL-STACK=%08x\n\n",
+               printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n"
+                       KERN_EMERG "\n",
                        (int) current->mm->start_stack,
                        (int)(((unsigned long) current) + THREAD_SIZE));
        }
@@ -312,36 +313,35 @@ void dump(struct pt_regs *fp)
                fp->d0, fp->d1, fp->d2, fp->d3);
        printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
                fp->d4, fp->d5, fp->a0, fp->a1);
-       printk(KERN_EMERG "\nUSP: %08x   TRAPFRAME: %08x\n", (unsigned int) rdusp(),
-               (unsigned int) fp);
+       printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x   TRAPFRAME: %08x\n",
+               (unsigned int) rdusp(), (unsigned int) fp);
 
-       printk(KERN_EMERG "\nCODE:");
+       printk(KERN_EMERG "\n" KERN_EMERG "CODE:");
        tp = ((unsigned char *) fp->pc) - 0x20;
        for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
                if ((i % 0x10) == 0)
-                       printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
-               printk(KERN_EMERG "%08x ", (int) *sp++);
+                       printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+               printk("%08x ", (int) *sp++);
        }
-       printk(KERN_EMERG "\n");
+       printk("\n" KERN_EMERG "\n");
 
-       printk(KERN_EMERG "\nKERNEL STACK:");
+       printk(KERN_EMERG "KERNEL STACK:");
        tp = ((unsigned char *) fp) - 0x40;
        for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
                if ((i % 0x10) == 0)
-                       printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
-               printk(KERN_EMERG "%08x ", (int) *sp++);
+                       printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+               printk("%08x ", (int) *sp++);
        }
-       printk(KERN_EMERG "\n");
-       printk(KERN_EMERG "\n");
+       printk("\n" KERN_EMERG "\n");
 
-       printk(KERN_EMERG "\nUSER STACK:");
+       printk(KERN_EMERG "USER STACK:");
        tp = (unsigned char *) (rdusp() - 0x10);
        for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
                if ((i % 0x10) == 0)
-                       printk(KERN_EMERG "\n%08x: ", (int) (tp + i));
-               printk(KERN_EMERG "%08x ", (int) *sp++);
+                       printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+               printk("%08x ", (int) *sp++);
        }
-       printk(KERN_EMERG "\n\n");
+       printk("\n" KERN_EMERG "\n");
 }
 
 /*
index 7b21959eaeae66b17f08f5337e42f06cb2842299..9cf2e4d1fc77e3cf725069b37084e2bb01877063 100644 (file)
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/machdep.h>
-
-#ifdef CONFIG_BLK_DEV_INITRD
 #include <asm/pgtable.h>
-#endif
 
 unsigned long memory_start;
 unsigned long memory_end;
index c3494b8447d155f890a319097b97fdf352eb4319..3265b2d734dbb8b9fc37659475d4863506b86015 100644 (file)
@@ -137,7 +137,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
 asmlinkage int sys_ipc (uint call, int first, int second,
                        int third, void *ptr, long fifth)
 {
-       int version;
+       int version, ret;
 
        version = call >> 16; /* hack for backward compatibility */
        call &= 0xffff;
@@ -190,6 +190,27 @@ asmlinkage int sys_ipc (uint call, int first, int second,
                default:
                        return -EINVAL;
                }
+       if (call <= SHMCTL)
+               switch (call) {
+               case SHMAT:
+                       switch (version) {
+                       default: {
+                               ulong raddr;
+                               ret = do_shmat (first, ptr, second, &raddr);
+                               if (ret)
+                                       return ret;
+                               return put_user (raddr, (ulong __user *) third);
+                       }
+                       }
+               case SHMDT:
+                       return sys_shmdt (ptr);
+               case SHMGET:
+                       return sys_shmget (first, second, third);
+               case SHMCTL:
+                       return sys_shmctl (first, second, ptr);
+               default:
+                       return -ENOSYS;
+               }
 
        return -EINVAL;
 }
index 17649d2543efa211423c5228d872ceaeb985fa5e..9129b3a5258bc28a8e832eea7dcd809bb7860c44 100644 (file)
@@ -127,11 +127,12 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                if (stack + 1 > endstack)
                        break;
                if (i % 8 == 0)
-                       printk(KERN_EMERG "\n       ");
-               printk(KERN_EMERG " %08lx", *stack++);
+                       printk("\n" KERN_EMERG "       ");
+               printk(" %08lx", *stack++);
        }
+       printk("\n");
 
-       printk(KERN_EMERG "\nCall Trace:");
+       printk(KERN_EMERG "Call Trace:");
        i = 0;
        while (stack + 1 <= endstack) {
                addr = *stack++;
@@ -146,12 +147,12 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                if (((addr >= (unsigned long) &_start) &&
                     (addr <= (unsigned long) &_etext))) {
                        if (i % 4 == 0)
-                               printk(KERN_EMERG "\n       ");
-                       printk(KERN_EMERG " [<%08lx>]", addr);
+                               printk("\n" KERN_EMERG "       ");
+                       printk(" [<%08lx>]", addr);
                        i++;
                }
        }
-       printk(KERN_EMERG "\n");
+       printk("\n");
 }
 
 void bad_super_trap(struct frame *fp)
index f2edb6498cd981cef3f57a733185918b8afb1553..b9aa0ca29bfba45ca1bf74e917ec243a67aa666d 100644 (file)
        negl    %d0                     /* negate bits */
 .endm
 
+#elif defined(CONFIG_M520x)
+.macro GET_MEM_SIZE
+       clrl    %d0
+       movel   MCF_MBAR+MCFSIM_SDCS0, %d2 /* Get SDRAM chip select 0 config */
+       andl    #0x1f, %d2              /* Get only the chip select size */
+       beq     3f                      /* Check if it is enabled */
+       addql   #1, %d2                 /* Form exponent */
+       moveql  #1, %d0
+       lsll    %d2, %d0                /* 2 ^ exponent */
+3:
+       movel   MCF_MBAR+MCFSIM_SDCS1, %d2 /* Get SDRAM chip select 1 config */
+       andl    #0x1f, %d2              /* Get only the chip select size */
+       beq     4f                      /* Check if it is enabled */
+       addql   #1, %d2                 /* Form exponent */
+       moveql  #1, %d1
+       lsll    %d2, %d1                /* 2 ^ exponent */
+       addl    %d1, %d0                /* Total size of SDRAM in d0 */
+4:
+.endm
+
 #else
 #error "ERROR: I don't know how to probe your boards memory size?"
 #endif
index 2ea51479f13a4b23d14c44bacbec4791e7bfc294..2ef06242398bf8bbad01b207f6436ff38cfe6ddb 100644 (file)
@@ -25,6 +25,7 @@
 .global _periph_base
 
 #define        RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
+#define        ROMEND                      (CONFIG_ROMBASE + CONFIG_ROMSIZE)
 
 #define REGB                        0x1000
 #define PEPAR                       (_dprbase + REGB + 0x0016)
@@ -175,7 +176,7 @@ configure_chip_select_0:
        move.l  %d0, BR0
 
 configure_chip_select_1:
-       move.l  #__rom_end, %d0
+       move.l  #ROMEND, %d0
        subi.l  #__rom_start, %d0
        subq.l  #0x01, %d0
        eori.l  #SIM_OR_MASK, %d0
index 245b81bc71573609487e6f16d5ce62f8b9bcd0f8..583d9ff0a571a4c75a1370472e9c03ff7333a076 100644 (file)
@@ -33,9 +33,6 @@ config GENERIC_CALIBRATE_DELAY
 config GENERIC_TIME
        def_bool y
 
-config GENERIC_BUST_SPINLOCK
-       bool
-
 mainmenu "Linux Kernel Configuration"
 
 config S390
@@ -181,7 +178,7 @@ config PACK_STACK
 
 config SMALL_STACK
        bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb"
-       depends on PACK_STACK
+       depends on PACK_STACK && !LOCKDEP
        help
          If you say Y here and the compiler supports the -mkernel-backchain
          option the kernel will use a smaller kernel stack size. For 31 bit
index 5deb9f7544a1da444b1ba0034685d511c74fc67b..6598e526857334bdf3f167cd8e9d721842e10a9d 100644 (file)
@@ -35,6 +35,9 @@ cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
 cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
 cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
 
+#KBUILD_IMAGE is necessary for make rpm
+KBUILD_IMAGE   :=arch/s390/boot/image
+
 #
 # Prevent tail-call optimizations, to get clearer backtraces:
 #
index aa978978d3d1a96bbdb0121e43cc25faadacd634..a81881c9b29760dee818bcff9f3baf348af1b0b7 100644 (file)
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS   := -traditional
 
-obj-y  :=  bitmap.o traps.o time.o process.o \
+obj-y  :=  bitmap.o traps.o time.o process.o reset.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
            semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o
 
index 1eae74e72f9525f91a11f56a012f815582157500..a5972f1541fea7525afc6c12f868cb7aa5d0efbd 100644 (file)
@@ -21,14 +21,15 @@ static DEFINE_SPINLOCK(cpcmd_lock);
 static char cpcmd_buf[241];
 
 /*
- * the caller of __cpcmd has to ensure that the response buffer is below 2 GB
+ * __cpcmd has some restrictions over cpcmd
+ *  - the response buffer must reside below 2GB (if any)
+ *  - __cpcmd is unlocked and therefore not SMP-safe
  */
 int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
-       unsigned long flags, cmdlen;
+       unsigned cmdlen;
        int return_code, return_len;
 
-       spin_lock_irqsave(&cpcmd_lock, flags);
        cmdlen = strlen(cmd);
        BUG_ON(cmdlen > 240);
        memcpy(cpcmd_buf, cmd, cmdlen);
@@ -74,7 +75,6 @@ int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
                        : "+d" (reg3) : "d" (reg2) : "cc");
                return_code = (int) reg3;
         }
-       spin_unlock_irqrestore(&cpcmd_lock, flags);
        if (response_code != NULL)
                *response_code = return_code;
        return return_len;
@@ -82,15 +82,18 @@ int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 
 EXPORT_SYMBOL(__cpcmd);
 
-#ifdef CONFIG_64BIT
 int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
        char *lowbuf;
        int len;
+       unsigned long flags;
 
        if ((rlen == 0) || (response == NULL)
-           || !((unsigned long)response >> 31))
+           || !((unsigned long)response >> 31)) {
+               spin_lock_irqsave(&cpcmd_lock, flags);
                len = __cpcmd(cmd, response, rlen, response_code);
+               spin_unlock_irqrestore(&cpcmd_lock, flags);
+       }
        else {
                lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
                if (!lowbuf) {
@@ -98,7 +101,9 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
                                "cpcmd: could not allocate response buffer\n");
                        return -ENOMEM;
                }
+               spin_lock_irqsave(&cpcmd_lock, flags);
                len = __cpcmd(cmd, lowbuf, rlen, response_code);
+               spin_unlock_irqrestore(&cpcmd_lock, flags);
                memcpy(response, lowbuf, rlen);
                kfree(lowbuf);
        }
@@ -106,4 +111,3 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 }
 
 EXPORT_SYMBOL(cpcmd);
-#endif         /* CONFIG_64BIT */
index 0cf59bb7a857d40eba3ecd9445a470af6b68d68d..8f8c802f1bcfd86a07660a1b2e7dbd1d3cf80a06 100644 (file)
@@ -418,24 +418,6 @@ start:
 .gotr:
        l       %r10,.tbl               # EBCDIC to ASCII table
        tr      0(240,%r8),0(%r10)
-       stidp   __LC_CPUID              # Are we running on VM maybe
-       cli     __LC_CPUID,0xff
-       bnz     .test
-       .long   0x83300060              # diag 3,0,x'0060' - storage size
-       b       .done
-.test:
-       mvc     0x68(8),.pgmnw          # set up pgm check handler
-       l       %r2,.fourmeg
-       lr      %r3,%r2
-       bctr    %r3,%r0                 # 4M-1
-.loop: iske    %r0,%r3
-       ar      %r3,%r2
-.pgmx:
-       sr      %r3,%r2
-       la      %r3,1(%r3)
-.done:
-       l       %r1,.memsize
-       st      %r3,ARCH_OFFSET(%r1)
        slr     %r0,%r0
        st      %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
        st      %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
@@ -443,9 +425,6 @@ start:
 .tbl:  .long   _ebcasc                 # translate table
 .cmd:  .long   COMMAND_LINE            # address of command line buffer
 .parm: .long   PARMAREA
-.memsize: .long memory_size
-.fourmeg: .long 0x00400000             # 4M
-.pgmnw:        .long   0x00080000,.pgmx
 .lowcase:
        .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
        .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
index 0a2c929486abf0ab96b361be6396f546e5e20e7b..4388b3309e0cbac3d3879e504d18021c32733378 100644 (file)
@@ -131,10 +131,11 @@ startup_continue:
        .long   init_thread_union
 .Lpmask:
        .byte   0
-.align 8
+       .align  8
 .Lpcext:.long  0x00080000,0x80000000
 .Lcr:
        .long   0x00                    # place holder for cr0
+       .align  8
 .Lwaitsclp:
        .long 0x010a0000,0x80000000 + .Lsclph
 .Lrcp:
@@ -156,7 +157,7 @@ startup_continue:
        slr     %r4,%r4                 # set start of chunk to zero
        slr     %r5,%r5                 # set end of chunk to zero
        slr     %r6,%r6                 # set access code to zero
-       la      %r10, MEMORY_CHUNKS     # number of chunks
+       la      %r10,MEMORY_CHUNKS      # number of chunks
 .Lloop:
        tprot   0(%r5),0                # test protection of first byte
        ipm     %r7
@@ -176,8 +177,6 @@ startup_continue:
        st      %r0,4(%r3)              # store size of chunk
        st      %r6,8(%r3)              # store type of chunk
        la      %r3,12(%r3)
-       l       %r4,.Lmemsize-.LPG1(%r13)        # address of variable memory_size
-       st      %r5,0(%r4)              # store last end to memory size
        ahi     %r10,-1                 # update chunk number
 .Lchkloop:
        lr      %r6,%r7                 # set access code to last cc
@@ -292,7 +291,6 @@ startup_continue:
 .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
 .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
 .Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
-.Lmemsize:.long memory_size
 .Lmchunk:.long memory_chunk
 .Lmflags:.long machine_flags
 .Lbss_bgn:  .long __bss_start
index 42f54d482441fdbc73a75fcbc7f716f9f5cb508b..c526279e11239dc65e5c8c8a0b585d3ca1556a04 100644 (file)
@@ -70,7 +70,20 @@ startup_continue:
        sgr     %r5,%r5                 # set src,length and pad to zero
        mvcle   %r2,%r4,0               # clear mem
        jo      .-4                     # branch back, if not finish
+                                       # set program check new psw mask
+       mvc     __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
+       larl    %r1,.Lslowmemdetect     # set program check address
+       stg     %r1,__LC_PGM_NEW_PSW+8
+       lghi    %r1,0xc
+       diag    %r0,%r1,0x260           # get memory size of virtual machine
+       cgr     %r0,%r1                 # different? -> old detection routine
+       jne     .Lslowmemdetect
+       aghi    %r1,1                   # size is one more than end
+       larl    %r2,memory_chunk
+       stg     %r1,8(%r2)              # store size of chunk
+       j       .Ldonemem
 
+.Lslowmemdetect:
        l       %r2,.Lrcp-.LPG1(%r13)   # Read SCP forced command word
 .Lservicecall:
        stosm   .Lpmask-.LPG1(%r13),0x01        # authorize ext interrupts
@@ -139,8 +152,6 @@ startup_continue:
        .int    0x100000
 
 .Lfchunk:
-                                       # set program check new psw mask
-       mvc     __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
 
 #
 # find memory chunks.
@@ -175,8 +186,6 @@ startup_continue:
        stg     %r0,8(%r3)              # store size of chunk
        st      %r6,20(%r3)             # store type of chunk
        la      %r3,24(%r3)
-       larl    %r8,memory_size
-       stg     %r5,0(%r8)              # store memory size
        ahi     %r10,-1                 # update chunk number
 .Lchkloop:
        lr      %r6,%r7                 # set access code to last cc
index 1f5e782b3d050173741898bfb4ca4fdb6af0e963..a36bea1188d9270feb11c792c1bd2499ad771508 100644 (file)
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
+#include <linux/ctype.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
 #include <asm/cpcmd.h>
 #include <asm/cio.h>
+#include <asm/ebcdic.h>
+#include <asm/reset.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
+#define LOADPARM_LEN 8
+
+extern char s390_readinfo_sccb[];
+#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010)
+#define SCCB_LOADPARM (&s390_readinfo_sccb[24])
+#define SCCB_FLAG (s390_readinfo_sccb[91])
 
 enum ipl_type {
        IPL_TYPE_NONE    = 1,
@@ -289,9 +298,25 @@ static struct attribute_group ipl_fcp_attr_group = {
 
 /* CCW ipl device attributes */
 
+static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+{
+       char loadparm[LOADPARM_LEN + 1] = {};
+
+       if (!SCCB_VALID)
+               return sprintf(page, "#unknown#\n");
+       memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
+       EBCASC(loadparm, LOADPARM_LEN);
+       strstrip(loadparm);
+       return sprintf(page, "%s\n", loadparm);
+}
+
+static struct subsys_attribute sys_ipl_ccw_loadparm_attr =
+       __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
+
 static struct attribute *ipl_ccw_attrs[] = {
        &sys_ipl_type_attr.attr,
        &sys_ipl_device_attr.attr,
+       &sys_ipl_ccw_loadparm_attr.attr,
        NULL,
 };
 
@@ -348,8 +373,57 @@ static struct attribute_group reipl_fcp_attr_group = {
 DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
        reipl_block_ccw->ipl_info.ccw.devno);
 
+static void reipl_get_ascii_loadparm(char *loadparm)
+{
+       memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
+              LOADPARM_LEN);
+       EBCASC(loadparm, LOADPARM_LEN);
+       loadparm[LOADPARM_LEN] = 0;
+       strstrip(loadparm);
+}
+
+static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+{
+       char buf[LOADPARM_LEN + 1];
+
+       reipl_get_ascii_loadparm(buf);
+       return sprintf(page, "%s\n", buf);
+}
+
+static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
+                                       const char *buf, size_t len)
+{
+       int i, lp_len;
+
+       /* ignore trailing newline */
+       lp_len = len;
+       if ((len > 0) && (buf[len - 1] == '\n'))
+               lp_len--;
+       /* loadparm can have max 8 characters and must not start with a blank */
+       if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
+               return -EINVAL;
+       /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
+       for (i = 0; i < lp_len; i++) {
+               if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
+                   (buf[i] == '.'))
+                       continue;
+               return -EINVAL;
+       }
+       /* initialize loadparm with blanks */
+       memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
+       /* copy and convert to ebcdic */
+       memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
+       ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
+       return len;
+}
+
+static struct subsys_attribute sys_reipl_ccw_loadparm_attr =
+       __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
+              reipl_ccw_loadparm_store);
+
 static struct attribute *reipl_ccw_attrs[] = {
        &sys_reipl_ccw_device_attr.attr,
+       &sys_reipl_ccw_loadparm_attr.attr,
        NULL,
 };
 
@@ -502,23 +576,6 @@ static struct subsys_attribute dump_type_attr =
 
 static decl_subsys(dump, NULL, NULL);
 
-#ifdef CONFIG_SMP
-static void dump_smp_stop_all(void)
-{
-       int cpu;
-       preempt_disable();
-       for_each_online_cpu(cpu) {
-               if (cpu == smp_processor_id())
-                       continue;
-               while (signal_processor(cpu, sigp_stop) == sigp_busy)
-                       udelay(10);
-       }
-       preempt_enable();
-}
-#else
-#define dump_smp_stop_all() do { } while (0)
-#endif
-
 /*
  * Shutdown actions section
  */
@@ -571,11 +628,14 @@ void do_reipl(void)
 {
        struct ccw_dev_id devid;
        static char buf[100];
+       char loadparm[LOADPARM_LEN + 1];
 
        switch (reipl_type) {
        case IPL_TYPE_CCW:
+               reipl_get_ascii_loadparm(loadparm);
                printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n",
                        reipl_block_ccw->ipl_info.ccw.devno);
+               printk(KERN_EMERG "loadparm = '%s'\n", loadparm);
                break;
        case IPL_TYPE_FCP:
                printk(KERN_EMERG "reboot on fcp device:\n");
@@ -588,12 +648,19 @@ void do_reipl(void)
        switch (reipl_method) {
        case IPL_METHOD_CCW_CIO:
                devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
+               if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno)
+                       diag308(DIAG308_IPL, NULL);
                devid.ssid  = 0;
                reipl_ccw_dev(&devid);
                break;
        case IPL_METHOD_CCW_VM:
-               sprintf(buf, "IPL %X", reipl_block_ccw->ipl_info.ccw.devno);
-               cpcmd(buf, NULL, 0, NULL);
+               if (strlen(loadparm) == 0)
+                       sprintf(buf, "IPL %X",
+                               reipl_block_ccw->ipl_info.ccw.devno);
+               else
+                       sprintf(buf, "IPL %X LOADPARM '%s'",
+                               reipl_block_ccw->ipl_info.ccw.devno, loadparm);
+               __cpcmd(buf, NULL, 0, NULL);
                break;
        case IPL_METHOD_CCW_DIAG:
                diag308(DIAG308_SET, reipl_block_ccw);
@@ -607,16 +674,17 @@ void do_reipl(void)
                diag308(DIAG308_IPL, NULL);
                break;
        case IPL_METHOD_FCP_RO_VM:
-               cpcmd("IPL", NULL, 0, NULL);
+               __cpcmd("IPL", NULL, 0, NULL);
                break;
        case IPL_METHOD_NONE:
        default:
                if (MACHINE_IS_VM)
-                       cpcmd("IPL", NULL, 0, NULL);
+                       __cpcmd("IPL", NULL, 0, NULL);
                diag308(DIAG308_IPL, NULL);
                break;
        }
-       panic("reipl failed!\n");
+       printk(KERN_EMERG "reboot failed!\n");
+       signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
 static void do_dump(void)
@@ -639,17 +707,17 @@ static void do_dump(void)
 
        switch (dump_method) {
        case IPL_METHOD_CCW_CIO:
-               dump_smp_stop_all();
+               smp_send_stop();
                devid.devno = dump_block_ccw->ipl_info.ccw.devno;
                devid.ssid  = 0;
                reipl_ccw_dev(&devid);
                break;
        case IPL_METHOD_CCW_VM:
-               dump_smp_stop_all();
+               smp_send_stop();
                sprintf(buf, "STORE STATUS");
-               cpcmd(buf, NULL, 0, NULL);
+               __cpcmd(buf, NULL, 0, NULL);
                sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
-               cpcmd(buf, NULL, 0, NULL);
+               __cpcmd(buf, NULL, 0, NULL);
                break;
        case IPL_METHOD_CCW_DIAG:
                diag308(DIAG308_SET, dump_block_ccw);
@@ -746,6 +814,17 @@ static int __init reipl_ccw_init(void)
        reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
        reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
        reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+       /* check if read scp info worked and set loadparm */
+       if (SCCB_VALID)
+               memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
+                      SCCB_LOADPARM, LOADPARM_LEN);
+       else
+               /* read scp info failed: set empty loadparm (EBCDIC blanks) */
+               memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
+                      LOADPARM_LEN);
+       /* FIXME: check for diag308_set_works when enabling diag ccw reipl */
+       if (!MACHINE_IS_VM)
+               sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
        if (ipl_get_type() == IPL_TYPE_CCW)
                reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
        reipl_capabilities |= IPL_TYPE_CCW;
@@ -827,13 +906,11 @@ static int __init dump_ccw_init(void)
        return 0;
 }
 
-extern char s390_readinfo_sccb[];
-
 static int __init dump_fcp_init(void)
 {
        int rc;
 
-       if(!(s390_readinfo_sccb[91] & 0x2))
+       if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
                return 0; /* LDIPL DUMP is not installed */
        if (!diag308_set_works)
                return 0;
@@ -931,3 +1008,53 @@ static int __init s390_ipl_init(void)
 }
 
 __initcall(s390_ipl_init);
+
+static LIST_HEAD(rcall);
+static DEFINE_MUTEX(rcall_mutex);
+
+void register_reset_call(struct reset_call *reset)
+{
+       mutex_lock(&rcall_mutex);
+       list_add(&reset->list, &rcall);
+       mutex_unlock(&rcall_mutex);
+}
+EXPORT_SYMBOL_GPL(register_reset_call);
+
+void unregister_reset_call(struct reset_call *reset)
+{
+       mutex_lock(&rcall_mutex);
+       list_del(&reset->list);
+       mutex_unlock(&rcall_mutex);
+}
+EXPORT_SYMBOL_GPL(unregister_reset_call);
+
+static void do_reset_calls(void)
+{
+       struct reset_call *reset;
+
+       list_for_each_entry(reset, &rcall, list)
+               reset->fn();
+}
+
+extern void reset_mcck_handler(void);
+
+void s390_reset_system(void)
+{
+       struct _lowcore *lc;
+
+       /* Stack for interrupt/machine check handler */
+       lc = (struct _lowcore *)(unsigned long) store_prefix();
+       lc->panic_stack = S390_lowcore.panic_stack;
+
+       /* Disable prefixing */
+       set_prefix(0);
+
+       /* Disable lowcore protection */
+       __ctl_clear_bit(0,28);
+
+       /* Set new machine check handler */
+       S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
+       S390_lowcore.mcck_new_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
+       do_reset_calls();
+}
index 60b1ea9f946beb137b33573a76483c189488cb5c..f6d9bcc0f75bf2fdc017b924456ea10607628b46 100644 (file)
@@ -1,15 +1,10 @@
 /*
  * arch/s390/kernel/machine_kexec.c
  *
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005,2006
  *
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
- *
- */
-
-/*
- * s390_machine_kexec.c - handle the transition of Linux booting another kernel
- * on the S390 architecture.
+ * Author(s): Rolf Adelsberger,
+ *           Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
 #include <linux/device.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 #include <asm/smp.h>
+#include <asm/reset.h>
 
-static void kexec_halt_all_cpus(void *);
-
-typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
+typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
 
 extern const unsigned char relocate_kernel[];
 extern const unsigned long long relocate_kernel_len;
 
-int
-machine_kexec_prepare(struct kimage *image)
+int machine_kexec_prepare(struct kimage *image)
 {
-       unsigned long reboot_code_buffer;
+       void *reboot_code_buffer;
 
        /* We don't support anything but the default image type for now. */
        if (image->type != KEXEC_TYPE_DEFAULT)
                return -EINVAL;
 
        /* Get the destination where the assembler code should be copied to.*/
-       reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT;
+       reboot_code_buffer = (void *) page_to_phys(image->control_code_page);
 
        /* Then copy it */
-       memcpy((void *) reboot_code_buffer, relocate_kernel,
-              relocate_kernel_len);
+       memcpy(reboot_code_buffer, relocate_kernel, relocate_kernel_len);
        return 0;
 }
 
-void
-machine_kexec_cleanup(struct kimage *image)
+void machine_kexec_cleanup(struct kimage *image)
 {
 }
 
-void
-machine_shutdown(void)
+void machine_shutdown(void)
 {
        printk(KERN_INFO "kexec: machine_shutdown called\n");
 }
 
-NORET_TYPE void
-machine_kexec(struct kimage *image)
+void machine_kexec(struct kimage *image)
 {
-       clear_all_subchannels();
-       cio_reset_channel_paths();
-
-       /* Disable lowcore protection */
-       ctl_clear_bit(0,28);
-
-       on_each_cpu(kexec_halt_all_cpus, image, 0, 0);
-       for (;;);
-}
-
-extern void pfault_fini(void);
-
-static void
-kexec_halt_all_cpus(void *kernel_image)
-{
-       static atomic_t cpuid = ATOMIC_INIT(-1);
-       int cpu;
-       struct kimage *image;
        relocate_kernel_t data_mover;
 
-#ifdef CONFIG_PFAULT
-       if (MACHINE_IS_VM)
-               pfault_fini();
-#endif
+       smp_send_stop();
+       pfault_fini();
+       s390_reset_system();
 
-       if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
-               signal_processor(smp_processor_id(), sigp_stop);
-
-       /* Wait for all other cpus to enter stopped state */
-       for_each_online_cpu(cpu) {
-               if (cpu == smp_processor_id())
-                       continue;
-               while (!smp_cpu_not_running(cpu))
-                       cpu_relax();
-       }
-
-       image = (struct kimage *) kernel_image;
-       data_mover = (relocate_kernel_t)
-               (page_to_pfn(image->control_code_page) << PAGE_SHIFT);
+       data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page);
 
        /* Call the moving routine */
-       (*data_mover) (&image->head, image->start);
+       (*data_mover)(&image->head, image->start);
+       for (;;);
 }
index 0340477f3b084d7f35498dff495d9755928647d7..f9434d42ce9f60f65ec2b57d84684b4d82677300 100644 (file)
                .globl  do_reipl_asm
 do_reipl_asm:  basr    %r13,0
 .Lpg0:         lpsw    .Lnewpsw-.Lpg0(%r13)
-
-               # switch off lowcore protection
-
-.Lpg1:         stctl   %c0,%c0,.Lctlsave1-.Lpg0(%r13)
-               stctl   %c0,%c0,.Lctlsave2-.Lpg0(%r13)
-               ni      .Lctlsave1-.Lpg0(%r13),0xef
-               lctl    %c0,%c0,.Lctlsave1-.Lpg0(%r13)
-
-               # do store status of all registers
+.Lpg1:         # do store status of all registers
 
                stm     %r0,%r15,__LC_GPREGS_SAVE_AREA
                stctl   %c0,%c15,__LC_CREGS_SAVE_AREA
-               mvc     __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13)
                stam    %a0,%a15,__LC_AREGS_SAVE_AREA
                stpx    __LC_PREFIX_SAVE_AREA
                stckc   .Lclkcmp-.Lpg0(%r13)
@@ -56,8 +47,7 @@ do_reipl_asm: basr    %r13,0
 .L002:         tm      .Liplirb+8-.Lpg0(%r13),0xf3
                jz      .L003
                bas     %r14,.Ldisab-.Lpg0(%r13)
-.L003:         spx     .Lnull-.Lpg0(%r13)
-               st      %r1,__LC_SUBCHANNEL_ID
+.L003:         st      %r1,__LC_SUBCHANNEL_ID
                lpsw    0
                sigp    0,0,0(6)
 .Ldisab:       st      %r14,.Ldispsw+4-.Lpg0(%r13)
@@ -65,9 +55,6 @@ do_reipl_asm: basr    %r13,0
                .align  8
 .Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .long   0xff000000
-.Lnull:                .long   0x00000000
-.Lctlsave1:    .long   0x00000000
-.Lctlsave2:    .long   0x00000000
                .align  8
 .Lnewpsw:      .long   0x00080000,0x80000000+.Lpg1
 .Lpcnew:       .long   0x00080000,0x80000000+.Lecs
index de7435054f7ccd4c45754824d8808d7ee83cfb8e..f18ef260ca237bb53f9fb04958dbc99a0d4de886 100644 (file)
 #include <asm/lowcore.h>
                .globl  do_reipl_asm
 do_reipl_asm:  basr    %r13,0
+.Lpg0:         lpswe   .Lnewpsw-.Lpg0(%r13)
+.Lpg1:         # do store status of all registers
 
-               # do store status of all registers
-
-.Lpg0:         stg     %r1,.Lregsave-.Lpg0(%r13)
+               stg     %r1,.Lregsave-.Lpg0(%r13)
                lghi    %r1,0x1000
                stmg    %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1)
                lg      %r0,.Lregsave-.Lpg0(%r13)
@@ -27,11 +27,7 @@ do_reipl_asm:        basr    %r13,0
                stpt    __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
                stg     %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
 
-               lpswe   .Lnewpsw-.Lpg0(%r13)
-.Lpg1:         lctlg   %c6,%c6,.Lall-.Lpg0(%r13)
-               stctg   %c0,%c0,.Lregsave-.Lpg0(%r13)
-               ni      .Lregsave+4-.Lpg0(%r13),0xef
-               lctlg   %c0,%c0,.Lregsave-.Lpg0(%r13)
+               lctlg   %c6,%c6,.Lall-.Lpg0(%r13)
                lgr     %r1,%r2
                mvc     __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
                stsch   .Lschib-.Lpg0(%r13)
@@ -56,8 +52,7 @@ do_reipl_asm: basr    %r13,0
 .L002:         tm      .Liplirb+8-.Lpg0(%r13),0xf3
                jz      .L003
                bas     %r14,.Ldisab-.Lpg0(%r13)
-.L003:         spx     .Lnull-.Lpg0(%r13)
-               st      %r1,__LC_SUBCHANNEL_ID
+.L003:         st      %r1,__LC_SUBCHANNEL_ID
                lhi     %r1,0            # mode 0 = esa
                slr     %r0,%r0          # set cpuid to zero
                sigp    %r1,%r0,0x12     # switch to esa mode
@@ -70,7 +65,6 @@ do_reipl_asm: basr    %r13,0
 .Lclkcmp:      .quad   0x0000000000000000
 .Lall:         .quad   0x00000000ff000000
 .Lregsave:     .quad   0x0000000000000000
-.Lnull:                .long   0x0000000000000000
                .align  16
 /*
  * These addresses have to be 31 bit otherwise
index f9899ff2e5b0a928a297e2998a5f6b8bb40f7363..3b456b80bcee839f5df358d8af6f3e8c24df8fa7 100644 (file)
@@ -26,8 +26,7 @@
        relocate_kernel:
                basr    %r13,0          # base address
        .base:
-               stnsm   sys_msk-.base(%r13),0xf8        # disable DAT and IRQ (external)
-               spx     zero64-.base(%r13)      # absolute addressing mode
+               stnsm   sys_msk-.base(%r13),0xfb        # disable DAT
                stctl   %c0,%c15,ctlregs-.base(%r13)
                stm     %r0,%r15,gprregs-.base(%r13)
                la      %r1,load_psw-.base(%r13)
@@ -97,8 +96,6 @@
                lpsw    0               # hopefully start new kernel...
 
                .align  8
-       zero64:
-               .quad   0
        load_psw:
                .long   0x00080000,0x80000000
        sys_msk:
index 4fb443042d9cc39bd64cf8502aed48636cd608bd..1f9ea2067b5979668252ee96c34a7dbe4bf2a85b 100644 (file)
@@ -27,8 +27,7 @@
        relocate_kernel:
                basr    %r13,0          # base address
        .base:
-               stnsm   sys_msk-.base(%r13),0xf8        # disable DAT and IRQs
-               spx     zero64-.base(%r13)      # absolute addressing mode
+               stnsm   sys_msk-.base(%r13),0xfb        # disable DAT
                stctg   %c0,%c15,ctlregs-.base(%r13)
                stmg    %r0,%r15,gprregs-.base(%r13)
                lghi    %r0,3
                lpsw    0               # hopefully start new kernel...
 
                .align  8
-       zero64:
-               .quad   0
        load_psw:
                .long   0x00080000,0x80000000
        sys_msk:
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
new file mode 100644 (file)
index 0000000..be8688c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  arch/s390/kernel/reset.S
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <asm/ptrace.h>
+#include <asm/lowcore.h>
+
+#ifdef CONFIG_64BIT
+
+       .globl  reset_mcck_handler
+reset_mcck_handler:
+       basr    %r13,0
+0:     lg      %r15,__LC_PANIC_STACK   # load panic stack
+       aghi    %r15,-STACK_FRAME_OVERHEAD
+       lg      %r1,s390_reset_mcck_handler-0b(%r13)
+       ltgr    %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+1:     la      %r1,4095
+       lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
+       lpswe   __LC_MCK_OLD_PSW
+
+       .globl  s390_reset_mcck_handler
+s390_reset_mcck_handler:
+       .quad   0
+
+#else /* CONFIG_64BIT */
+
+       .globl  reset_mcck_handler
+reset_mcck_handler:
+       basr    %r13,0
+0:     l       %r15,__LC_PANIC_STACK   # load panic stack
+       ahi     %r15,-STACK_FRAME_OVERHEAD
+       l       %r1,s390_reset_mcck_handler-0b(%r13)
+       ltr     %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+1:     lm      %r0,%r15,__LC_GPREGS_SAVE_AREA
+       lpsw    __LC_MCK_OLD_PSW
+
+       .globl  s390_reset_mcck_handler
+s390_reset_mcck_handler:
+       .long   0
+
+#endif /* CONFIG_64BIT */
index 2aa13e8e000acdc26b23ddbdf84ba742fd0c853d..b928fecdc743e61760364be8492a1735ebef0f9c 100644 (file)
@@ -62,13 +62,9 @@ EXPORT_SYMBOL_GPL(uaccess);
 unsigned int console_mode = 0;
 unsigned int console_devno = -1;
 unsigned int console_irq = -1;
-unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
-struct {
-       unsigned long addr, size, type;
-} memory_chunk[MEMORY_CHUNKS] = { { 0 } };
-#define CHUNK_READ_WRITE 0
-#define CHUNK_READ_ONLY 1
+
+struct mem_chunk memory_chunk[MEMORY_CHUNKS];
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
 unsigned long __initdata zholes_size[MAX_NR_ZONES];
 static unsigned long __initdata memory_end;
@@ -229,11 +225,11 @@ static void __init conmode_default(void)
        char *ptr;
 
         if (MACHINE_IS_VM) {
-               __cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
+               cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
                console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
                ptr = strstr(query_buffer, "SUBCHANNEL =");
                console_irq = simple_strtoul(ptr + 13, NULL, 16);
-               __cpcmd("QUERY TERM", query_buffer, 1024, NULL);
+               cpcmd("QUERY TERM", query_buffer, 1024, NULL);
                ptr = strstr(query_buffer, "CONMODE");
                /*
                 * Set the conmode to 3215 so that the device recognition 
@@ -242,7 +238,7 @@ static void __init conmode_default(void)
                 * 3215 and the 3270 driver will try to access the console
                 * device (3215 as console and 3270 as normal tty).
                 */
-               __cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
+               cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
                if (ptr == NULL) {
 #if defined(CONFIG_SCLP_CONSOLE)
                        SET_CONSOLE_SCLP;
@@ -299,14 +295,14 @@ static void do_machine_restart_nonsmp(char * __unused)
 static void do_machine_halt_nonsmp(void)
 {
         if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
-                cpcmd(vmhalt_cmd, NULL, 0, NULL);
+               __cpcmd(vmhalt_cmd, NULL, 0, NULL);
         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
 static void do_machine_power_off_nonsmp(void)
 {
         if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
-                cpcmd(vmpoff_cmd, NULL, 0, NULL);
+               __cpcmd(vmpoff_cmd, NULL, 0, NULL);
         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
@@ -489,6 +485,37 @@ setup_resources(void)
        }
 }
 
+static void __init setup_memory_end(void)
+{
+       unsigned long real_size, memory_size;
+       unsigned long max_mem, max_phys;
+       int i;
+
+       memory_size = real_size = 0;
+       max_phys = VMALLOC_END - VMALLOC_MIN_SIZE;
+       memory_end &= PAGE_MASK;
+
+       max_mem = memory_end ? min(max_phys, memory_end) : max_phys;
+
+       for (i = 0; i < MEMORY_CHUNKS; i++) {
+               struct mem_chunk *chunk = &memory_chunk[i];
+
+               real_size = max(real_size, chunk->addr + chunk->size);
+               if (chunk->addr >= max_mem) {
+                       memset(chunk, 0, sizeof(*chunk));
+                       continue;
+               }
+               if (chunk->addr + chunk->size > max_mem)
+                       chunk->size = max_mem - chunk->addr;
+               memory_size = max(memory_size, chunk->addr + chunk->size);
+       }
+       if (!memory_end)
+               memory_end = memory_size;
+       if (real_size > memory_end)
+               printk("More memory detected than supported. Unused: %luk\n",
+                      (real_size - memory_end) >> 10);
+}
+
 static void __init
 setup_memory(void)
 {
@@ -645,8 +672,6 @@ setup_arch(char **cmdline_p)
        init_mm.end_data = (unsigned long) &_edata;
        init_mm.brk = (unsigned long) &_end;
 
-       memory_end = memory_size;
-
        if (MACHINE_HAS_MVCOS)
                memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess));
        else
@@ -654,20 +679,7 @@ setup_arch(char **cmdline_p)
 
        parse_early_param();
 
-#ifndef CONFIG_64BIT
-       memory_end &= ~0x400000UL;
-
-        /*
-         * We need some free virtual space to be able to do vmalloc.
-         * On a machine with 2GB memory we make sure that we have at
-         * least 128 MB free space for vmalloc.
-         */
-        if (memory_end > 1920*1024*1024)
-                memory_end = 1920*1024*1024;
-#else /* CONFIG_64BIT */
-       memory_end &= ~0x200000UL;
-#endif /* CONFIG_64BIT */
-
+       setup_memory_end();
        setup_memory();
        setup_resources();
        setup_lowcore();
index 62822245f9be95e25927ec5461f635d28df6efd7..19090f7d4f517e6799619bf1b4398d750994285c 100644 (file)
@@ -230,18 +230,37 @@ static inline void do_store_status(void)
         }
 }
 
+static inline void do_wait_for_stop(void)
+{
+       int cpu;
+
+       /* Wait for all other cpus to enter stopped state */
+       for_each_online_cpu(cpu) {
+               if (cpu == smp_processor_id())
+                       continue;
+               while(!smp_cpu_not_running(cpu))
+                       cpu_relax();
+       }
+}
+
 /*
  * this function sends a 'stop' sigp to all other CPUs in the system.
  * it goes straight through.
  */
 void smp_send_stop(void)
 {
+       /* Disable all interrupts/machine checks */
+       __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
+
         /* write magic number to zero page (absolute 0) */
        lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
 
        /* stop other processors. */
        do_send_stop();
 
+       /* wait until other processors are stopped */
+       do_wait_for_stop();
+
        /* store status of other processors. */
        do_store_status();
 }
@@ -250,88 +269,28 @@ void smp_send_stop(void)
  * Reboot, halt and power_off routines for SMP.
  */
 
-static void do_machine_restart(void * __unused)
-{
-       int cpu;
-       static atomic_t cpuid = ATOMIC_INIT(-1);
-
-       if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
-               signal_processor(smp_processor_id(), sigp_stop);
-
-       /* Wait for all other cpus to enter stopped state */
-       for_each_online_cpu(cpu) {
-               if (cpu == smp_processor_id())
-                       continue;
-               while(!smp_cpu_not_running(cpu))
-                       cpu_relax();
-       }
-
-       /* Store status of other cpus. */
-       do_store_status();
-
-       /*
-        * Finally call reipl. Because we waited for all other
-        * cpus to enter this function we know that they do
-        * not hold any s390irq-locks (the cpus have been
-        * interrupted by an external interrupt and s390irq
-        * locks are always held disabled).
-        */
-       do_reipl();
-}
-
 void machine_restart_smp(char * __unused) 
 {
-        on_each_cpu(do_machine_restart, NULL, 0, 0);
-}
-
-static void do_wait_for_stop(void)
-{
-       unsigned long cr[16];
-
-       __ctl_store(cr, 0, 15);
-       cr[0] &= ~0xffff;
-       cr[6] = 0;
-       __ctl_load(cr, 0, 15);
-       for (;;)
-               enabled_wait();
-}
-
-static void do_machine_halt(void * __unused)
-{
-       static atomic_t cpuid = ATOMIC_INIT(-1);
-
-       if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
-               smp_send_stop();
-               if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
-                       cpcmd(vmhalt_cmd, NULL, 0, NULL);
-               signal_processor(smp_processor_id(),
-                                sigp_stop_and_store_status);
-       }
-       do_wait_for_stop();
+       smp_send_stop();
+       do_reipl();
 }
 
 void machine_halt_smp(void)
 {
-        on_each_cpu(do_machine_halt, NULL, 0, 0);
-}
-
-static void do_machine_power_off(void * __unused)
-{
-       static atomic_t cpuid = ATOMIC_INIT(-1);
-
-       if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
-               smp_send_stop();
-               if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
-                       cpcmd(vmpoff_cmd, NULL, 0, NULL);
-               signal_processor(smp_processor_id(),
-                                sigp_stop_and_store_status);
-       }
-       do_wait_for_stop();
+       smp_send_stop();
+       if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+               __cpcmd(vmhalt_cmd, NULL, 0, NULL);
+       signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+       for (;;);
 }
 
 void machine_power_off_smp(void)
 {
-        on_each_cpu(do_machine_power_off, NULL, 0, 0);
+       smp_send_stop();
+       if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+               __cpcmd(vmpoff_cmd, NULL, 0, NULL);
+       signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+       for (;;);
 }
 
 /*
@@ -501,8 +460,6 @@ __init smp_count_cpus(void)
  */
 extern void init_cpu_timer(void);
 extern void init_cpu_vtimer(void);
-extern int pfault_init(void);
-extern void pfault_fini(void);
 
 int __devinit start_secondary(void *cpuvoid)
 {
@@ -514,11 +471,9 @@ int __devinit start_secondary(void *cpuvoid)
 #ifdef CONFIG_VIRT_TIMER
         init_cpu_vtimer();
 #endif
-#ifdef CONFIG_PFAULT
        /* Enable pfault pseudo page faults on this cpu. */
-       if (MACHINE_IS_VM)
-               pfault_init();
-#endif
+       pfault_init();
+
        /* Mark this cpu as online */
        cpu_set(smp_processor_id(), cpu_online_map);
        /* Switch on interrupts */
@@ -708,11 +663,8 @@ __cpu_disable(void)
        }
        cpu_clear(cpu, cpu_online_map);
 
-#ifdef CONFIG_PFAULT
        /* Disable pfault pseudo page faults on this cpu. */
-       if (MACHINE_IS_VM)
-               pfault_fini();
-#endif
+       pfault_fini();
 
        memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
        memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
@@ -860,4 +812,3 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
 EXPORT_SYMBOL(smp_call_function);
 EXPORT_SYMBOL(smp_get_cpu);
 EXPORT_SYMBOL(smp_put_cpu);
-
index 92ecffbc8d8233352589b700f5eefa4f165fe832..3cbb0dcf1f1dc845d744077c95c416796e85ddb0 100644 (file)
@@ -58,12 +58,6 @@ int sysctl_userprocess_debug = 0;
 
 extern pgm_check_handler_t do_protection_exception;
 extern pgm_check_handler_t do_dat_exception;
-#ifdef CONFIG_PFAULT
-extern int pfault_init(void);
-extern void pfault_fini(void);
-extern void pfault_interrupt(__u16 error_code);
-static ext_int_info_t ext_int_pfault;
-#endif
 extern pgm_check_handler_t do_monitor_call;
 
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -135,7 +129,7 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high)
        }
 }
 
-void show_trace(struct task_struct *task, unsigned long * stack)
+void show_trace(struct task_struct *task, unsigned long *stack)
 {
        register unsigned long __r15 asm ("15");
        unsigned long sp;
@@ -157,6 +151,9 @@ void show_trace(struct task_struct *task, unsigned long * stack)
                __show_trace(sp, S390_lowcore.thread_info,
                             S390_lowcore.thread_info + THREAD_SIZE);
        printk("\n");
+       if (!task)
+               task = current;
+       debug_show_held_locks(task);
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
@@ -739,22 +736,5 @@ void __init trap_init(void)
         pgm_check_table[0x1C] = &space_switch_exception;
         pgm_check_table[0x1D] = &hfp_sqrt_exception;
        pgm_check_table[0x40] = &do_monitor_call;
-
-       if (MACHINE_IS_VM) {
-#ifdef CONFIG_PFAULT
-               /*
-                * Try to get pfault pseudo page faults going.
-                */
-               if (register_early_external_interrupt(0x2603, pfault_interrupt,
-                                                     &ext_int_pfault) != 0)
-                       panic("Couldn't request external interrupt 0x2603");
-
-               if (pfault_init() == 0) 
-                       return;
-               
-               /* Tough luck, no pfault. */
-               unregister_early_external_interrupt(0x2603, pfault_interrupt,
-                                                   &ext_int_pfault);
-#endif
-       }
+       pfault_irq_init();
 }
index b0cfa6c4883d57e7a848970beca6657c3907b0b5..b5f94cf3bde8d190d09c66fec8bfcc289d5f3292 100644 (file)
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y += delay.o string.o uaccess_std.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
 lib-$(CONFIG_32BIT) += div64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
index 121b2935a422a2e724ce97cd9dd49aaa61cc26a7..f9a23d57eb79fa63713a7ac87e85f1991c30280f 100644 (file)
@@ -27,6 +27,9 @@
 #define SLR    "slgr"
 #endif
 
+extern size_t copy_from_user_std(size_t, const void __user *, void *);
+extern size_t copy_to_user_std(size_t, void __user *, const void *);
+
 size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
 {
        register unsigned long reg0 asm("0") = 0x81UL;
@@ -66,6 +69,13 @@ size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
        return size;
 }
 
+size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
+{
+       if (size <= 256)
+               return copy_from_user_std(size, ptr, x);
+       return copy_from_user_mvcos(size, ptr, x);
+}
+
 size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
 {
        register unsigned long reg0 asm("0") = 0x810000UL;
@@ -95,6 +105,13 @@ size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
        return size;
 }
 
+size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, const void *x)
+{
+       if (size <= 256)
+               return copy_to_user_std(size, ptr, x);
+       return copy_to_user_mvcos(size, ptr, x);
+}
+
 size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from)
 {
        register unsigned long reg0 asm("0") = 0x810081UL;
@@ -145,18 +162,16 @@ size_t clear_user_mvcos(size_t size, void __user *to)
        return size;
 }
 
-extern size_t copy_from_user_std_small(size_t, const void __user *, void *);
-extern size_t copy_to_user_std_small(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
 extern int futex_atomic_op(int, int __user *, int, int *);
 extern int futex_atomic_cmpxchg(int __user *, int, int);
 
 struct uaccess_ops uaccess_mvcos = {
-       .copy_from_user = copy_from_user_mvcos,
-       .copy_from_user_small = copy_from_user_std_small,
-       .copy_to_user = copy_to_user_mvcos,
-       .copy_to_user_small = copy_to_user_std_small,
+       .copy_from_user = copy_from_user_mvcos_check,
+       .copy_from_user_small = copy_from_user_std,
+       .copy_to_user = copy_to_user_mvcos_check,
+       .copy_to_user_small = copy_to_user_std,
        .copy_in_user = copy_in_user_mvcos,
        .clear_user = clear_user_mvcos,
        .strnlen_user = strnlen_user_std,
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
new file mode 100644 (file)
index 0000000..8741bdc
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  arch/s390/lib/uaccess_pt.c
+ *
+ *  User access functions based on page table walks.
+ *
+ *    Copyright IBM Corp. 2006
+ *    Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
+ */
+
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <asm/futex.h>
+
+static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
+                                int write_access)
+{
+       struct vm_area_struct *vma;
+       int ret = -EFAULT;
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, address);
+       if (unlikely(!vma))
+               goto out;
+       if (unlikely(vma->vm_start > address)) {
+               if (!(vma->vm_flags & VM_GROWSDOWN))
+                       goto out;
+               if (expand_stack(vma, address))
+                       goto out;
+       }
+
+       if (!write_access) {
+               /* page not present, check vm flags */
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+                       goto out;
+       } else {
+               if (!(vma->vm_flags & VM_WRITE))
+                       goto out;
+       }
+
+survive:
+       switch (handle_mm_fault(mm, vma, address, write_access)) {
+       case VM_FAULT_MINOR:
+               current->min_flt++;
+               break;
+       case VM_FAULT_MAJOR:
+               current->maj_flt++;
+               break;
+       case VM_FAULT_SIGBUS:
+               goto out_sigbus;
+       case VM_FAULT_OOM:
+               goto out_of_memory;
+       default:
+               BUG();
+       }
+       ret = 0;
+out:
+       up_read(&mm->mmap_sem);
+       return ret;
+
+out_of_memory:
+       up_read(&mm->mmap_sem);
+       if (current->pid == 1) {
+               yield();
+               goto survive;
+       }
+       printk("VM: killing process %s\n", current->comm);
+       return ret;
+
+out_sigbus:
+       up_read(&mm->mmap_sem);
+       current->thread.prot_addr = address;
+       current->thread.trap_no = 0x11;
+       force_sig(SIGBUS, current);
+       return ret;
+}
+
+static inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
+                                   size_t n, int write_user)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long offset, pfn, done, size;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+       void *from, *to;
+
+       done = 0;
+retry:
+       spin_lock(&mm->page_table_lock);
+       do {
+               pgd = pgd_offset(mm, uaddr);
+               if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+                       goto fault;
+
+               pmd = pmd_offset(pgd, uaddr);
+               if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+                       goto fault;
+
+               pte = pte_offset_map(pmd, uaddr);
+               if (!pte || !pte_present(*pte) ||
+                   (write_user && !pte_write(*pte)))
+                       goto fault;
+
+               pfn = pte_pfn(*pte);
+               if (!pfn_valid(pfn))
+                       goto out;
+
+               offset = uaddr & (PAGE_SIZE - 1);
+               size = min(n - done, PAGE_SIZE - offset);
+               if (write_user) {
+                       to = (void *)((pfn << PAGE_SHIFT) + offset);
+                       from = kptr + done;
+               } else {
+                       from = (void *)((pfn << PAGE_SHIFT) + offset);
+                       to = kptr + done;
+               }
+               memcpy(to, from, size);
+               done += size;
+               uaddr += size;
+       } while (done < n);
+out:
+       spin_unlock(&mm->page_table_lock);
+       return n - done;
+fault:
+       spin_unlock(&mm->page_table_lock);
+       if (__handle_fault(mm, uaddr, write_user))
+               return n - done;
+       goto retry;
+}
+
+size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
+{
+       size_t rc;
+
+       if (segment_eq(get_fs(), KERNEL_DS)) {
+               memcpy(to, (void __kernel __force *) from, n);
+               return 0;
+       }
+       rc = __user_copy_pt((unsigned long) from, to, n, 0);
+       if (unlikely(rc))
+               memset(to + n - rc, 0, rc);
+       return rc;
+}
+
+size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
+{
+       if (segment_eq(get_fs(), KERNEL_DS)) {
+               memcpy((void __kernel __force *) to, from, n);
+               return 0;
+       }
+       return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
+}
index f44f0078b354538d86908b949e4d6f4a4cee8d7e..2d549ed2e11399dfe17975fcae72aa512b9f52fe 100644 (file)
@@ -28,6 +28,9 @@
 #define SLR    "slgr"
 #endif
 
+extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to);
+extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from);
+
 size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
 {
        unsigned long tmp1, tmp2;
@@ -69,34 +72,11 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
        return size;
 }
 
-size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x)
+size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x)
 {
-       unsigned long tmp1, tmp2;
-
-       tmp1 = 0UL;
-       asm volatile(
-               "0: mvcp  0(%0,%2),0(%1),%3\n"
-               "  "SLR"  %0,%0\n"
-               "   j     5f\n"
-               "1: la    %4,255(%1)\n" /* %4 = ptr + 255 */
-               "  "LHI"  %3,-4096\n"
-               "   nr    %4,%3\n"      /* %4 = (ptr + 255) & -4096 */
-               "  "SLR"  %4,%1\n"
-               "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
-               "   jnh   5f\n"
-               "2: mvcp  0(%4,%2),0(%1),%3\n"
-               "  "SLR"  %0,%4\n"
-               "  "ALR"  %2,%4\n"
-               "3:"LHI"  %4,-1\n"
-               "  "ALR"  %4,%0\n"      /* copy remaining size, subtract 1 */
-               "   bras  %3,4f\n"
-               "   xc    0(1,%2),0(%2)\n"
-               "4: ex    %4,0(%3)\n"
-               "5:\n"
-               EX_TABLE(0b,1b) EX_TABLE(2b,3b)
-               : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
-               : : "cc", "memory");
-       return size;
+       if (size <= 1024)
+               return copy_from_user_std(size, ptr, x);
+       return copy_from_user_pt(size, ptr, x);
 }
 
 size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
@@ -130,28 +110,11 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
        return size;
 }
 
-size_t copy_to_user_std_small(size_t size, void __user *ptr, const void *x)
+size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x)
 {
-       unsigned long tmp1, tmp2;
-
-       tmp1 = 0UL;
-       asm volatile(
-               "0: mvcs  0(%0,%1),0(%2),%3\n"
-               "  "SLR"  %0,%0\n"
-               "   j     3f\n"
-               "1: la    %4,255(%1)\n" /* ptr + 255 */
-               "  "LHI"  %3,-4096\n"
-               "   nr    %4,%3\n"      /* (ptr + 255) & -4096UL */
-               "  "SLR"  %4,%1\n"
-               "  "CLR"  %0,%4\n"      /* copy crosses next page boundary? */
-               "   jnh   3f\n"
-               "2: mvcs  0(%4,%1),0(%2),%3\n"
-               "  "SLR"  %0,%4\n"
-               "3:\n"
-               EX_TABLE(0b,1b) EX_TABLE(2b,3b)
-               : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
-               : : "cc", "memory");
-       return size;
+       if (size <= 1024)
+               return copy_to_user_std(size, ptr, x);
+       return copy_to_user_pt(size, ptr, x);
 }
 
 size_t copy_in_user_std(size_t size, void __user *to, const void __user *from)
@@ -343,10 +306,10 @@ int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval)
 }
 
 struct uaccess_ops uaccess_std = {
-       .copy_from_user = copy_from_user_std,
-       .copy_from_user_small = copy_from_user_std_small,
-       .copy_to_user = copy_to_user_std,
-       .copy_to_user_small = copy_to_user_std_small,
+       .copy_from_user = copy_from_user_std_check,
+       .copy_from_user_small = copy_from_user_std,
+       .copy_to_user = copy_to_user_std_check,
+       .copy_to_user_small = copy_to_user_std,
        .copy_in_user = copy_in_user_std,
        .clear_user = clear_user_std,
        .strnlen_user = strnlen_user_std,
index 226275d5c4f60a39a506635d961399e51479e25c..9e9bc48463a546493f432df4164a1a49f3409259 100644 (file)
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/bootmem.h>
+#include <linux/ctype.h>
 #include <asm/page.h>
 #include <asm/ebcdic.h>
 #include <asm/errno.h>
 #include <asm/extmem.h>
 #include <asm/cpcmd.h>
-#include <linux/ctype.h>
+#include <asm/setup.h>
 
 #define DCSS_DEBUG     /* Debug messages on/off */
 
@@ -77,15 +78,11 @@ struct dcss_segment {
        int segcnt;
 };
 
-static DEFINE_SPINLOCK(dcss_lock);
+static DEFINE_MUTEX(dcss_lock);
 static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list);
 static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
                                        "EW/EN-MIXED" };
 
-extern struct {
-       unsigned long addr, size, type;
-} memory_chunk[MEMORY_CHUNKS];
-
 /*
  * Create the 8 bytes, ebcdic VM segment name from
  * an ascii name.
@@ -117,7 +114,7 @@ segment_by_name (char *name)
        struct list_head *l;
        struct dcss_segment *tmp, *retval = NULL;
 
-       assert_spin_locked(&dcss_lock);
+       BUG_ON(!mutex_is_locked(&dcss_lock));
        dcss_mkname (name, dcss_name);
        list_for_each (l, &dcss_list) {
                tmp = list_entry (l, struct dcss_segment, list);
@@ -249,8 +246,8 @@ segment_overlaps_storage(struct dcss_segment *seg)
 {
        int i;
 
-       for (i=0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
-               if (memory_chunk[i].type != 0)
+       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+               if (memory_chunk[i].type != CHUNK_READ_WRITE)
                        continue;
                if ((memory_chunk[i].addr >> 20) > (seg->end >> 20))
                        continue;
@@ -272,7 +269,7 @@ segment_overlaps_others (struct dcss_segment *seg)
        struct list_head *l;
        struct dcss_segment *tmp;
 
-       assert_spin_locked(&dcss_lock);
+       BUG_ON(!mutex_is_locked(&dcss_lock));
        list_for_each(l, &dcss_list) {
                tmp = list_entry(l, struct dcss_segment, list);
                if ((tmp->start_addr >> 20) > (seg->end >> 20))
@@ -429,7 +426,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
        if (!MACHINE_IS_VM)
                return -ENOSYS;
 
-       spin_lock (&dcss_lock);
+       mutex_lock(&dcss_lock);
        seg = segment_by_name (name);
        if (seg == NULL)
                rc = __segment_load (name, do_nonshared, addr, end);
@@ -444,7 +441,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
                        rc    = -EPERM;
                }
        }
-       spin_unlock (&dcss_lock);
+       mutex_unlock(&dcss_lock);
        return rc;
 }
 
@@ -467,7 +464,7 @@ segment_modify_shared (char *name, int do_nonshared)
        unsigned long dummy;
        int dcss_command, rc, diag_cc;
 
-       spin_lock (&dcss_lock);
+       mutex_lock(&dcss_lock);
        seg = segment_by_name (name);
        if (seg == NULL) {
                rc = -EINVAL;
@@ -508,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared)
                  &dummy, &dummy);
        kfree(seg);
  out_unlock:
-       spin_unlock(&dcss_lock);
+       mutex_unlock(&dcss_lock);
        return rc;
 }
 
@@ -526,7 +523,7 @@ segment_unload(char *name)
        if (!MACHINE_IS_VM)
                return;
 
-       spin_lock(&dcss_lock);
+       mutex_lock(&dcss_lock);
        seg = segment_by_name (name);
        if (seg == NULL) {
                PRINT_ERR ("could not find segment %s in segment_unload, "
@@ -540,7 +537,7 @@ segment_unload(char *name)
                kfree(seg);
        }
 out_unlock:
-       spin_unlock(&dcss_lock);
+       mutex_unlock(&dcss_lock);
 }
 
 /*
@@ -559,12 +556,13 @@ segment_save(char *name)
        if (!MACHINE_IS_VM)
                return;
 
-       spin_lock(&dcss_lock);
+       mutex_lock(&dcss_lock);
        seg = segment_by_name (name);
 
        if (seg == NULL) {
-               PRINT_ERR ("could not find segment %s in segment_save, please report to linux390@de.ibm.com\n",name);
-               return;
+               PRINT_ERR("could not find segment %s in segment_save, please "
+                         "report to linux390@de.ibm.com\n", name);
+               goto out;
        }
 
        startpfn = seg->start_addr >> PAGE_SHIFT;
@@ -591,7 +589,7 @@ segment_save(char *name)
                goto out;
        }
 out:
-       spin_unlock(&dcss_lock);
+       mutex_unlock(&dcss_lock);
 }
 
 EXPORT_SYMBOL(segment_load);
index 1c323bbfda91cdfce7ae38e8d921533afebedbaf..cd85e34d8703551bdb7fa640be56792bcf32eaf0 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/kdebug.h>
+#include <asm/s390_ext.h>
 
 #ifndef CONFIG_64BIT
 #define __FAIL_ADDR_MASK 0x7ffff000
@@ -394,6 +395,7 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code)
 /*
  * 'pfault' pseudo page faults routines.
  */
+static ext_int_info_t ext_int_pfault;
 static int pfault_disable = 0;
 
 static int __init nopfault(char *str)
@@ -422,7 +424,7 @@ int pfault_init(void)
                  __PF_RES_FIELD };
         int rc;
 
-       if (pfault_disable)
+       if (!MACHINE_IS_VM || pfault_disable)
                return -1;
        asm volatile(
                "       diag    %1,%0,0x258\n"
@@ -440,7 +442,7 @@ void pfault_fini(void)
        pfault_refbk_t refbk =
        { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL };
 
-       if (pfault_disable)
+       if (!MACHINE_IS_VM || pfault_disable)
                return;
        __ctl_clear_bit(0,9);
        asm volatile(
@@ -500,5 +502,25 @@ pfault_interrupt(__u16 error_code)
                        set_tsk_need_resched(tsk);
        }
 }
-#endif
 
+void __init pfault_irq_init(void)
+{
+       if (!MACHINE_IS_VM)
+               return;
+
+       /*
+        * Try to get pfault pseudo page faults going.
+        */
+       if (register_early_external_interrupt(0x2603, pfault_interrupt,
+                                             &ext_int_pfault) != 0)
+               panic("Couldn't request external interrupt 0x2603");
+
+       if (pfault_init() == 0)
+               return;
+
+       /* Tough luck, no pfault. */
+       pfault_disable = 1;
+       unregister_early_external_interrupt(0x2603, pfault_interrupt,
+                                           &ext_int_pfault);
+}
+#endif
index 578b99b71d9ce12556fe398bf5dfb196e8739f27..bf5b79ed36131111b59527223e71a5a930b55e07 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/notifier.h>
+#include <linux/jiffies.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
index 03f6338acc8fb7223e040078b1f196d28835c444..984ab284382ae41fcd4c2c1aaaab80396359e023 100644 (file)
@@ -328,6 +328,15 @@ config PATA_TRIFLEX
 
          If unsure, say N.
 
+config PATA_MARVELL
+       tristate "Marvell PATA support via legacy mode"
+       depends on PCI
+       help
+         This option enables limited support for the Marvell 88SE6145 ATA
+         controller.
+
+         If unsure, say N.
+
 config PATA_MPIIX
        tristate "Intel PATA MPIIX support"
        depends on PCI
@@ -483,6 +492,32 @@ config PATA_WINBOND
 
          If unsure, say N.
 
+config PATA_WINBOND_VLB
+       tristate "Winbond W83759A VLB PATA support (Experimental)"
+       depends on ISA && EXPERIMENTAL
+       help
+         Support for the Winbond W83759A controller on Vesa Local Bus
+         systems.
+
+config PATA_PLATFORM
+       tristate "Generic platform device PATA support"
+       depends on EMBEDDED
+       help
+         This option enables support for generic directly connected ATA
+         devices commonly found on embedded systems.
+
+         If unsure, say N.
+
+config PATA_IXP4XX_CF
+       tristate "IXP4XX Compact Flash support"
+       depends on ARCH_IXP4XX
+       help
+         This option enables support for a Compact Flash connected on
+         the ixp4xx expansion bus. This driver had been written for
+         Loft/Avila boards in mind but can work with others.
+
+         If unsure, say N.
+
 endif
 endmenu
 
index 72243a677f9be7675267fc27bfbed0901a553f28..bc3d81ae757e64e9b98869a3ef1204e420553400 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL)    += pata_netcell.o
 obj-$(CONFIG_PATA_NS87410)     += pata_ns87410.o
 obj-$(CONFIG_PATA_OPTI)                += pata_opti.o
 obj-$(CONFIG_PATA_OPTIDMA)     += pata_optidma.o
+obj-$(CONFIG_PATA_MARVELL)     += pata_marvell.o
 obj-$(CONFIG_PATA_MPIIX)       += pata_mpiix.o
 obj-$(CONFIG_PATA_OLDPIIX)     += pata_oldpiix.o
 obj-$(CONFIG_PATA_PCMCIA)      += pata_pcmcia.o
@@ -51,8 +52,11 @@ obj-$(CONFIG_PATA_SERVERWORKS)       += pata_serverworks.o
 obj-$(CONFIG_PATA_SIL680)      += pata_sil680.o
 obj-$(CONFIG_PATA_VIA)         += pata_via.o
 obj-$(CONFIG_PATA_WINBOND)     += pata_sl82c105.o
+obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
 obj-$(CONFIG_PATA_SIS)         += pata_sis.o
 obj-$(CONFIG_PATA_TRIFLEX)     += pata_triflex.o
+obj-$(CONFIG_PATA_IXP4XX_CF)   += pata_ixp4xx_cf.o
+obj-$(CONFIG_PATA_PLATFORM)    += pata_platform.o
 # Should be last but one libata driver
 obj-$(CONFIG_ATA_GENERIC)      += ata_generic.o
 # Should be last libata driver
index bddb14e91d3cf22596287c38deeb92ab083e2dcd..f36da488a2c1c1ee9a62e54637bf1d46e7f4c0fd 100644 (file)
@@ -53,6 +53,7 @@
 
 enum {
        AHCI_PCI_BAR            = 5,
+       AHCI_MAX_PORTS          = 32,
        AHCI_MAX_SG             = 168, /* hardware max is 64K */
        AHCI_DMA_BOUNDARY       = 0xffffffff,
        AHCI_USE_CLUSTERING     = 0,
@@ -77,8 +78,9 @@ enum {
        RX_FIS_UNK              = 0x60, /* offset of Unknown FIS data */
 
        board_ahci              = 0,
-       board_ahci_vt8251       = 1,
-       board_ahci_ign_iferr    = 2,
+       board_ahci_pi           = 1,
+       board_ahci_vt8251       = 2,
+       board_ahci_ign_iferr    = 3,
 
        /* global controller registers */
        HOST_CAP                = 0x00, /* host capabilities */
@@ -167,9 +169,9 @@ enum {
        AHCI_FLAG_MSI           = (1 << 0),
 
        /* ap->flags bits */
-       AHCI_FLAG_RESET_NEEDS_CLO       = (1 << 24),
-       AHCI_FLAG_NO_NCQ                = (1 << 25),
-       AHCI_FLAG_IGN_IRQ_IF_ERR        = (1 << 26), /* ignore IRQ_IF_ERR */
+       AHCI_FLAG_NO_NCQ                = (1 << 24),
+       AHCI_FLAG_IGN_IRQ_IF_ERR        = (1 << 25), /* ignore IRQ_IF_ERR */
+       AHCI_FLAG_HONOR_PI              = (1 << 26), /* honor PORTS_IMPL */
 };
 
 struct ahci_cmd_hdr {
@@ -216,6 +218,7 @@ static u8 ahci_check_status(struct ata_port *ap);
 static void ahci_freeze(struct ata_port *ap);
 static void ahci_thaw(struct ata_port *ap);
 static void ahci_error_handler(struct ata_port *ap);
+static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
 static int ahci_port_resume(struct ata_port *ap);
@@ -275,6 +278,37 @@ static const struct ata_port_operations ahci_ops = {
        .port_stop              = ahci_port_stop,
 };
 
+static const struct ata_port_operations ahci_vt8251_ops = {
+       .port_disable           = ata_port_disable,
+
+       .check_status           = ahci_check_status,
+       .check_altstatus        = ahci_check_status,
+       .dev_select             = ata_noop_dev_select,
+
+       .tf_read                = ahci_tf_read,
+
+       .qc_prep                = ahci_qc_prep,
+       .qc_issue               = ahci_qc_issue,
+
+       .irq_handler            = ahci_interrupt,
+       .irq_clear              = ahci_irq_clear,
+
+       .scr_read               = ahci_scr_read,
+       .scr_write              = ahci_scr_write,
+
+       .freeze                 = ahci_freeze,
+       .thaw                   = ahci_thaw,
+
+       .error_handler          = ahci_vt8251_error_handler,
+       .post_internal_cmd      = ahci_post_internal_cmd,
+
+       .port_suspend           = ahci_port_suspend,
+       .port_resume            = ahci_port_resume,
+
+       .port_start             = ahci_port_start,
+       .port_stop              = ahci_port_stop,
+};
+
 static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci */
        {
@@ -286,16 +320,26 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &ahci_ops,
        },
+       /* board_ahci_pi */
+       {
+               .sht            = &ahci_sht,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &ahci_ops,
+       },
        /* board_ahci_vt8251 */
        {
                .sht            = &ahci_sht,
                .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                  ATA_FLAG_SKIP_D2H_BSY |
-                                 AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ,
+                                 ATA_FLAG_HRST_TO_RESUME | AHCI_FLAG_NO_NCQ,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
-               .port_ops       = &ahci_ops,
+               .port_ops       = &ahci_vt8251_ops,
        },
        /* board_ahci_ign_iferr */
        {
@@ -322,22 +366,22 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
        { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
        { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
-       { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
-       { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
-       { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
-       { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
-       { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
-       { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
-       { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
-       { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
-       { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
-       { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
-       { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
-       { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
-       { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
-       { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
-       { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
-       { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */
+       { PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */
+       { PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */
+       { PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */
+       { PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */
+       { PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */
+       { PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */
+       { PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */
+       { PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */
+       { PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */
+       { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */
+       { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */
+       { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */
 
        /* JMicron */
        { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */
@@ -372,6 +416,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
        { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
 
+       /* Generic, PCI class code for AHCI */
+       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+         0x010601, 0xffffff, board_ahci },
+
        { }     /* terminate list */
 };
 
@@ -386,6 +434,11 @@ static struct pci_driver ahci_pci_driver = {
 };
 
 
+static inline int ahci_nr_ports(u32 cap)
+{
+       return (cap & 0x1f) + 1;
+}
+
 static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port)
 {
        return base + 0x100 + (port * 0x80);
@@ -559,9 +612,6 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
 static void ahci_init_port(void __iomem *port_mmio, u32 cap,
                           dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
 {
-       /* power up */
-       ahci_power_up(port_mmio, cap);
-
        /* enable FIS reception */
        ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
 
@@ -587,19 +637,17 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
                return rc;
        }
 
-       /* put device into slumber mode */
-       ahci_power_down(port_mmio, cap);
-
        return 0;
 }
 
 static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
 {
-       u32 cap_save, tmp;
+       u32 cap_save, impl_save, tmp;
 
        cap_save = readl(mmio + HOST_CAP);
        cap_save &= ( (1<<28) | (1<<17) );
        cap_save |= (1 << 27);
+       impl_save = readl(mmio + HOST_PORTS_IMPL);
 
        /* global controller reset */
        tmp = readl(mmio + HOST_CTL);
@@ -620,10 +668,21 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
                return -EIO;
        }
 
+       /* turn on AHCI mode */
        writel(HOST_AHCI_EN, mmio + HOST_CTL);
        (void) readl(mmio + HOST_CTL);  /* flush */
+
+       /* These write-once registers are normally cleared on reset.
+        * Restore BIOS values... which we HOPE were present before
+        * reset.
+        */
+       if (!impl_save) {
+               impl_save = (1 << ahci_nr_ports(cap_save)) - 1;
+               dev_printk(KERN_WARNING, &pdev->dev,
+                          "PORTS_IMPL is zero, forcing 0x%x\n", impl_save);
+       }
        writel(cap_save, mmio + HOST_CAP);
-       writel(0xf, mmio + HOST_PORTS_IMPL);
+       writel(impl_save, mmio + HOST_PORTS_IMPL);
        (void) readl(mmio + HOST_PORTS_IMPL);   /* flush */
 
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
@@ -639,7 +698,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
 }
 
 static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
-                                int n_ports, u32 cap)
+                                int n_ports, unsigned int port_flags,
+                                struct ahci_host_priv *hpriv)
 {
        int i, rc;
        u32 tmp;
@@ -648,13 +708,12 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
                void __iomem *port_mmio = ahci_port_base(mmio, i);
                const char *emsg = NULL;
 
-#if 0 /* BIOSen initialize this incorrectly */
-               if (!(hpriv->port_map & (1 << i)))
+               if ((port_flags & AHCI_FLAG_HONOR_PI) &&
+                   !(hpriv->port_map & (1 << i)))
                        continue;
-#endif
 
                /* make sure port is not active */
-               rc = ahci_deinit_port(port_mmio, cap, &emsg);
+               rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
                if (rc)
                        dev_printk(KERN_WARNING, &pdev->dev,
                                   "%s (%d)\n", emsg, rc);
@@ -729,17 +788,6 @@ static int ahci_clo(struct ata_port *ap)
        return 0;
 }
 
-static int ahci_prereset(struct ata_port *ap)
-{
-       if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
-           (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
-               /* ATA_BUSY hasn't cleared, so send a CLO */
-               ahci_clo(ap);
-       }
-
-       return ata_std_prereset(ap);
-}
-
 static int ahci_softreset(struct ata_port *ap, unsigned int *class)
 {
        struct ahci_port_priv *pp = ap->private_data;
@@ -877,6 +925,31 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
        return rc;
 }
 
+static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
+{
+       void __iomem *mmio = ap->host->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       ahci_stop_engine(port_mmio);
+
+       rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
+
+       /* vt8251 needs SError cleared for the port to operate */
+       ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
+
+       ahci_start_engine(port_mmio);
+
+       DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+
+       /* vt8251 doesn't clear BSY on signature FIS reception,
+        * request follow-up softreset.
+        */
+       return rc ?: -EAGAIN;
+}
+
 static void ahci_postreset(struct ata_port *ap, unsigned int *class)
 {
        void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
@@ -1196,7 +1269,23 @@ static void ahci_error_handler(struct ata_port *ap)
        }
 
        /* perform recovery */
-       ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
+       ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset,
+                 ahci_postreset);
+}
+
+static void ahci_vt8251_error_handler(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+       if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+               /* restart engine */
+               ahci_stop_engine(port_mmio);
+               ahci_start_engine(port_mmio);
+       }
+
+       /* perform recovery */
+       ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
                  ahci_postreset);
 }
 
@@ -1226,7 +1315,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
        int rc;
 
        rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
-       if (rc) {
+       if (rc == 0)
+               ahci_power_down(port_mmio, hpriv->cap);
+       else {
                ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
                ahci_init_port(port_mmio, hpriv->cap,
                               pp->cmd_slot_dma, pp->rx_fis_dma);
@@ -1242,6 +1333,7 @@ static int ahci_port_resume(struct ata_port *ap)
        void __iomem *mmio = ap->host->mmio_base;
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
+       ahci_power_up(port_mmio, hpriv->cap);
        ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
 
        return 0;
@@ -1281,7 +1373,8 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
                if (rc)
                        return rc;
 
-               ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap);
+               ahci_init_controller(mmio, pdev, host->n_ports,
+                                    host->ports[0]->flags, hpriv);
        }
 
        ata_host_resume(host);
@@ -1347,6 +1440,9 @@ static int ahci_port_start(struct ata_port *ap)
 
        ap->private_data = pp;
 
+       /* power up port */
+       ahci_power_up(port_mmio, hpriv->cap);
+
        /* initialize port */
        ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
 
@@ -1393,7 +1489,7 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
        struct ahci_host_priv *hpriv = probe_ent->private_data;
        struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
        void __iomem *mmio = probe_ent->mmio_base;
-       unsigned int i, using_dac;
+       unsigned int i, cap_n_ports, using_dac;
        int rc;
 
        rc = ahci_reset_controller(mmio, pdev);
@@ -1402,10 +1498,34 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
 
        hpriv->cap = readl(mmio + HOST_CAP);
        hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-       probe_ent->n_ports = (hpriv->cap & 0x1f) + 1;
+       cap_n_ports = ahci_nr_ports(hpriv->cap);
 
        VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
-               hpriv->cap, hpriv->port_map, probe_ent->n_ports);
+               hpriv->cap, hpriv->port_map, cap_n_ports);
+
+       if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
+               unsigned int n_ports = cap_n_ports;
+               u32 port_map = hpriv->port_map;
+               int max_port = 0;
+
+               for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
+                       if (port_map & (1 << i)) {
+                               n_ports--;
+                               port_map &= ~(1 << i);
+                               max_port = i;
+                       } else
+                               probe_ent->dummy_port_mask |= 1 << i;
+               }
+
+               if (n_ports || port_map)
+                       dev_printk(KERN_WARNING, &pdev->dev,
+                                  "nr_ports (%u) and implemented port map "
+                                  "(0x%x) don't match\n",
+                                  cap_n_ports, hpriv->port_map);
+
+               probe_ent->n_ports = max_port + 1;
+       } else
+               probe_ent->n_ports = cap_n_ports;
 
        using_dac = hpriv->cap & HOST_CAP_64;
        if (using_dac &&
@@ -1437,7 +1557,8 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
        for (i = 0; i < probe_ent->n_ports; i++)
                ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
 
-       ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
+       ahci_init_controller(mmio, pdev, probe_ent->n_ports,
+                            probe_ent->port_flags, hpriv);
 
        pci_set_master(pdev);
 
index 4a80ff9312b8c313ace7277619db1ad3445c778e..908751d27e76f1141d9ca56ad43d7acb944d8329 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "ata_generic"
-#define DRV_VERSION "0.2.6"
+#define DRV_VERSION "0.2.10"
 
 /*
  *     A generic parallel ATA driver using libata
@@ -109,7 +109,6 @@ static struct scsi_host_template generic_sht = {
        .can_queue              = ATA_DEF_QUEUE,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = LIBATA_MAX_PRD,
-       .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
        .use_clustering         = ATA_SHT_USE_CLUSTERING,
@@ -118,6 +117,8 @@ static struct scsi_host_template generic_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+       .resume                 = ata_scsi_device_resume,
+       .suspend                = ata_scsi_device_suspend,
 };
 
 static struct ata_port_operations generic_port_ops = {
@@ -226,12 +227,14 @@ static struct pci_driver ata_generic_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = ata_generic,
        .probe          = ata_generic_init_one,
-       .remove         = ata_pci_remove_one
+       .remove         = ata_pci_remove_one,
+       .suspend        = ata_pci_device_suspend,
+       .resume         = ata_pci_device_resume,
 };
 
 static int __init ata_generic_init(void)
 {
-       return pci_module_init(&ata_generic_pci_driver);
+       return pci_register_driver(&ata_generic_pci_driver);
 }
 
 
index 720174d628fa762d4ee3e2367645229d14771b06..c7de0bb1591f2b7c2b85e15cf633c2a004ec6a8b 100644 (file)
@@ -40,7 +40,7 @@
  * Documentation
  *     Publically available from Intel web site. Errata documentation
  * is also publically available. As an aide to anyone hacking on this
- * driver the list of errata that are relevant is below.going back to
+ * driver the list of errata that are relevant is belowgoing back to
  * PIIX4. Older device documentation is now a bit tricky to find.
  *
  * The chipsets all follow very much the same design. The orginal Triton
@@ -93,7 +93,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ata_piix"
-#define DRV_VERSION    "2.00ac6"
+#define DRV_VERSION    "2.00ac7"
 
 enum {
        PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
@@ -101,11 +101,13 @@ enum {
        ICH5_PCS                = 0x92, /* port control and status */
        PIIX_SCC                = 0x0A, /* sub-class code register */
 
-       PIIX_FLAG_IGNORE_PCS    = (1 << 25), /* ignore PCS present bits */
        PIIX_FLAG_SCR           = (1 << 26), /* SCR available */
        PIIX_FLAG_AHCI          = (1 << 27), /* AHCI possible */
        PIIX_FLAG_CHECKINTR     = (1 << 28), /* make sure PCI INTx enabled */
 
+       PIIX_PATA_FLAGS         = ATA_FLAG_SLAVE_POSS,
+       PIIX_SATA_FLAGS         = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+
        /* combined mode.  if set, PATA is channel 0.
         * if clear, PATA is channel 1.
         */
@@ -122,11 +124,10 @@ enum {
        ich_pata_100            = 3,    /* ICH up to UDMA 100 */
        ich_pata_133            = 4,    /* ICH up to UDMA 133 */
        ich5_sata               = 5,
-       esb_sata                = 6,
-       ich6_sata               = 7,
-       ich6_sata_ahci          = 8,
-       ich6m_sata_ahci         = 9,
-       ich8_sata_ahci          = 10,
+       ich6_sata               = 6,
+       ich6_sata_ahci          = 7,
+       ich6m_sata_ahci         = 8,
+       ich8_sata_ahci          = 9,
 
        /* constants for mapping table */
        P0                      = 0,  /* port 0 */
@@ -143,13 +144,11 @@ enum {
 struct piix_map_db {
        const u32 mask;
        const u16 port_enable;
-       const int present_shift;
        const int map[][4];
 };
 
 struct piix_host_priv {
        const int *map;
-       const struct piix_map_db *map_db;
 };
 
 static int piix_init_one (struct pci_dev *pdev,
@@ -214,9 +213,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* 82801EB (ICH5) */
        { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
        /* 6300ESB (ICH5 variant with broken PCS present bits) */
-       { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+       { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
        /* 6300ESB pretending RAID */
-       { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
+       { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
        /* 82801FB/FW (ICH6/ICH6W) */
        { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
        /* 82801FR/FRW (ICH6R/ICH6RW) */
@@ -367,7 +366,6 @@ static const struct ata_port_operations piix_sata_ops = {
 static const struct piix_map_db ich5_map_db = {
        .mask = 0x7,
        .port_enable = 0x3,
-       .present_shift = 4,
        .map = {
                /* PM   PS   SM   SS       MAP  */
                {  P0,  NA,  P1,  NA }, /* 000b */
@@ -384,7 +382,6 @@ static const struct piix_map_db ich5_map_db = {
 static const struct piix_map_db ich6_map_db = {
        .mask = 0x3,
        .port_enable = 0xf,
-       .present_shift = 4,
        .map = {
                /* PM   PS   SM   SS       MAP */
                {  P0,  P2,  P1,  P3 }, /* 00b */
@@ -397,7 +394,6 @@ static const struct piix_map_db ich6_map_db = {
 static const struct piix_map_db ich6m_map_db = {
        .mask = 0x3,
        .port_enable = 0x5,
-       .present_shift = 4,
 
        /* Map 01b isn't specified in the doc but some notebooks use
         * it anyway.  MAP 01b have been spotted on both ICH6M and
@@ -415,7 +411,6 @@ static const struct piix_map_db ich6m_map_db = {
 static const struct piix_map_db ich8_map_db = {
        .mask = 0x3,
        .port_enable = 0x3,
-       .present_shift = 8,
        .map = {
                /* PM   PS   SM   SS       MAP */
                {  P0,  P2,  P1,  P3 }, /* 00b (hardwired when in AHCI) */
@@ -427,7 +422,6 @@ static const struct piix_map_db ich8_map_db = {
 
 static const struct piix_map_db *piix_map_db_table[] = {
        [ich5_sata]             = &ich5_map_db,
-       [esb_sata]              = &ich5_map_db,
        [ich6_sata]             = &ich6_map_db,
        [ich6_sata_ahci]        = &ich6_map_db,
        [ich6m_sata_ahci]       = &ich6m_map_db,
@@ -438,7 +432,7 @@ static struct ata_port_info piix_port_info[] = {
        /* piix_pata_33: 0:  PIIX3 or 4 at 33MHz */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+               .flags          = PIIX_PATA_FLAGS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
                .udma_mask      = ATA_UDMA_MASK_40C,
@@ -448,7 +442,7 @@ static struct ata_port_info piix_port_info[] = {
        /* ich_pata_33: 1       ICH0 - ICH at 33Mhz*/
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+               .flags          = PIIX_PATA_FLAGS,
                .pio_mask       = 0x1f, /* pio 0-4 */
                .mwdma_mask     = 0x06, /* Check: maybe 0x07  */
                .udma_mask      = ATA_UDMA2, /* UDMA33 */
@@ -457,7 +451,7 @@ static struct ata_port_info piix_port_info[] = {
        /* ich_pata_66: 2       ICH controllers up to 66MHz */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
+               .flags          = PIIX_PATA_FLAGS,
                .pio_mask       = 0x1f, /* pio 0-4 */
                .mwdma_mask     = 0x06, /* MWDMA0 is broken on chip */
                .udma_mask      = ATA_UDMA4,
@@ -467,7 +461,7 @@ static struct ata_port_info piix_port_info[] = {
        /* ich_pata_100: 3 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+               .flags          = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x06, /* mwdma1-2 */
                .udma_mask      = ATA_UDMA5, /* udma0-5 */
@@ -477,7 +471,7 @@ static struct ata_port_info piix_port_info[] = {
        /* ich_pata_133: 4      ICH with full UDMA6 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
+               .flags          = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
                .pio_mask       = 0x1f, /* pio 0-4 */
                .mwdma_mask     = 0x06, /* Check: maybe 0x07  */
                .udma_mask      = ATA_UDMA6, /* UDMA133 */
@@ -487,41 +481,27 @@ static struct ata_port_info piix_port_info[] = {
        /* ich5_sata: 5 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
-                                 PIIX_FLAG_IGNORE_PCS,
-               .pio_mask       = 0x1f, /* pio0-4 */
-               .mwdma_mask     = 0x07, /* mwdma0-2 */
-               .udma_mask      = 0x7f, /* udma0-6 */
-               .port_ops       = &piix_sata_ops,
-       },
-
-       /* i6300esb_sata: 6 */
-       {
-               .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
+               .flags          = PIIX_SATA_FLAGS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &piix_sata_ops,
        },
 
-       /* ich6_sata: 7 */
+       /* ich6_sata: 6 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &piix_sata_ops,
        },
 
-       /* ich6_sata_ahci: 8 */
+       /* ich6_sata_ahci: 7 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
                                  PIIX_FLAG_AHCI,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
@@ -529,11 +509,10 @@ static struct ata_port_info piix_port_info[] = {
                .port_ops       = &piix_sata_ops,
        },
 
-       /* ich6m_sata_ahci: 9 */
+       /* ich6m_sata_ahci: 8 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
                                  PIIX_FLAG_AHCI,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
@@ -541,11 +520,10 @@ static struct ata_port_info piix_port_info[] = {
                .port_ops       = &piix_sata_ops,
        },
 
-       /* ich8_sata_ahci: 10 */
+       /* ich8_sata_ahci: 9 */
        {
                .sht            = &piix_sht,
-               .flags          = ATA_FLAG_SATA |
-                                 PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
                                  PIIX_FLAG_AHCI,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
@@ -566,10 +544,22 @@ MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
-static int force_pcs = 0;
-module_param(force_pcs, int, 0444);
-MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
-                "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
+struct ich_laptop {
+       u16 device;
+       u16 subvendor;
+       u16 subdevice;
+};
+
+/*
+ *     List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+       /* devid, subvendor, subdev */
+       { 0x27DF, 0x0005, 0x0280 },     /* ICH7 on Acer 5602WLMi */
+       /* end marker */
+       { 0, }
+};
 
 /**
  *     piix_pata_cbl_detect - Probe host controller cable detect info
@@ -585,12 +575,24 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
 static void ich_pata_cbl_detect(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+       const struct ich_laptop *lap = &ich_laptop[0];
        u8 tmp, mask;
 
        /* no 80c support in host controller? */
        if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
                goto cbl40;
 
+       /* Check for specials - Acer Aspire 5602WLMi */
+       while (lap->device) {
+               if (lap->device == pdev->device &&
+                   lap->subvendor == pdev->subsystem_vendor &&
+                   lap->subdevice == pdev->subsystem_device) {
+                       ap->cbl = ATA_CBL_PATA40_SHORT;
+                       return;
+               }
+               lap++;
+       }
+
        /* check BIOS cable detect results */
        mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
        pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
@@ -659,84 +661,9 @@ static void ich_pata_error_handler(struct ata_port *ap)
                           ata_std_postreset);
 }
 
-/**
- *     piix_sata_present_mask - determine present mask for SATA host controller
- *     @ap: Target port
- *
- *     Reads SATA PCI device's PCI config register Port Configuration
- *     and Status (PCS) to determine port and device availability.
- *
- *     LOCKING:
- *     None (inherited from caller).
- *
- *     RETURNS:
- *     determined present_mask
- */
-static unsigned int piix_sata_present_mask(struct ata_port *ap)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-       struct piix_host_priv *hpriv = ap->host->private_data;
-       const unsigned int *map = hpriv->map;
-       int base = 2 * ap->port_no;
-       unsigned int present_mask = 0;
-       int port, i;
-       u16 pcs;
-
-       pci_read_config_word(pdev, ICH5_PCS, &pcs);
-       DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
-
-       for (i = 0; i < 2; i++) {
-               port = map[base + i];
-               if (port < 0)
-                       continue;
-               if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
-                   (pcs & 1 << (hpriv->map_db->present_shift + port)))
-                       present_mask |= 1 << i;
-       }
-
-       DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
-               ap->id, pcs, present_mask);
-
-       return present_mask;
-}
-
-/**
- *     piix_sata_softreset - reset SATA host port via ATA SRST
- *     @ap: port to reset
- *     @classes: resulting classes of attached devices
- *
- *     Reset SATA host port via ATA SRST.  On controllers with
- *     reliable PCS present bits, the bits are used to determine
- *     device presence.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- *
- *     RETURNS:
- *     0 on success, -errno otherwise.
- */
-static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes)
-{
-       unsigned int present_mask;
-       int i, rc;
-
-       present_mask = piix_sata_present_mask(ap);
-
-       rc = ata_std_softreset(ap, classes);
-       if (rc)
-               return rc;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               if (!(present_mask & (1 << i)))
-                       classes[i] = ATA_DEV_NONE;
-       }
-
-       return 0;
-}
-
 static void piix_sata_error_handler(struct ata_port *ap)
 {
-       ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL,
+       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
                           ata_std_postreset);
 }
 
@@ -1051,18 +978,6 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
                pci_write_config_word(pdev, ICH5_PCS, new_pcs);
                msleep(150);
        }
-
-       if (force_pcs == 1) {
-               dev_printk(KERN_INFO, &pdev->dev,
-                          "force ignoring PCS (0x%x)\n", new_pcs);
-               pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS;
-               pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS;
-       } else if (force_pcs == 2) {
-               dev_printk(KERN_INFO, &pdev->dev,
-                          "force honoring PCS (0x%x)\n", new_pcs);
-               pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS;
-               pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS;
-       }
 }
 
 static void __devinit piix_init_sata_map(struct pci_dev *pdev,
@@ -1112,7 +1027,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
                           "invalid MAP value %u\n", map_value);
 
        hpriv->map = map;
-       hpriv->map_db = map_db;
 }
 
 /**
index 915a55a6cc14ea8dc230cefb31f15f8b9c48dc04..f8ec3896b793e21c14e5352c0589a11f22fa0c7b 100644 (file)
@@ -199,7 +199,8 @@ static const u8 ata_rw_cmds[] = {
 
 /**
  *     ata_rwcmd_protocol - set taskfile r/w commands and protocol
- *     @qc: command to examine and configure
+ *     @tf: command to examine and configure
+ *     @dev: device tf belongs to
  *
  *     Examine the device configuration and tf->flags to calculate
  *     the proper read/write commands and protocol to use.
@@ -207,10 +208,8 @@ static const u8 ata_rw_cmds[] = {
  *     LOCKING:
  *     caller.
  */
-int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev)
 {
-       struct ata_taskfile *tf = &qc->tf;
-       struct ata_device *dev = qc->dev;
        u8 cmd;
 
        int index, fua, lba48, write;
@@ -222,7 +221,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
        if (dev->flags & ATA_DFLAG_PIO) {
                tf->protocol = ATA_PROT_PIO;
                index = dev->multi_count ? 0 : 8;
-       } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+       } else if (lba48 && (dev->ap->flags & ATA_FLAG_PIO_LBA48)) {
                /* Unable to use DMA due to host limitation */
                tf->protocol = ATA_PROT_PIO;
                index = dev->multi_count ? 0 : 8;
@@ -239,6 +238,174 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
        return -1;
 }
 
+/**
+ *     ata_tf_read_block - Read block address from ATA taskfile
+ *     @tf: ATA taskfile of interest
+ *     @dev: ATA device @tf belongs to
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     Read block address from @tf.  This function can handle all
+ *     three address formats - LBA, LBA48 and CHS.  tf->protocol and
+ *     flags select the address format to use.
+ *
+ *     RETURNS:
+ *     Block address read from @tf.
+ */
+u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
+{
+       u64 block = 0;
+
+       if (tf->flags & ATA_TFLAG_LBA) {
+               if (tf->flags & ATA_TFLAG_LBA48) {
+                       block |= (u64)tf->hob_lbah << 40;
+                       block |= (u64)tf->hob_lbam << 32;
+                       block |= tf->hob_lbal << 24;
+               } else
+                       block |= (tf->device & 0xf) << 24;
+
+               block |= tf->lbah << 16;
+               block |= tf->lbam << 8;
+               block |= tf->lbal;
+       } else {
+               u32 cyl, head, sect;
+
+               cyl = tf->lbam | (tf->lbah << 8);
+               head = tf->device & 0xf;
+               sect = tf->lbal;
+
+               block = (cyl * dev->heads + head) * dev->sectors + sect;
+       }
+
+       return block;
+}
+
+/**
+ *     ata_build_rw_tf - Build ATA taskfile for given read/write request
+ *     @tf: Target ATA taskfile
+ *     @dev: ATA device @tf belongs to
+ *     @block: Block address
+ *     @n_block: Number of blocks
+ *     @tf_flags: RW/FUA etc...
+ *     @tag: tag
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     Build ATA taskfile @tf for read/write request described by
+ *     @block, @n_block, @tf_flags and @tag on @dev.
+ *
+ *     RETURNS:
+ *
+ *     0 on success, -ERANGE if the request is too large for @dev,
+ *     -EINVAL if the request is invalid.
+ */
+int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
+                   u64 block, u32 n_block, unsigned int tf_flags,
+                   unsigned int tag)
+{
+       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf->flags |= tf_flags;
+
+       if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
+                          ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ &&
+           likely(tag != ATA_TAG_INTERNAL)) {
+               /* yay, NCQ */
+               if (!lba_48_ok(block, n_block))
+                       return -ERANGE;
+
+               tf->protocol = ATA_PROT_NCQ;
+               tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+               if (tf->flags & ATA_TFLAG_WRITE)
+                       tf->command = ATA_CMD_FPDMA_WRITE;
+               else
+                       tf->command = ATA_CMD_FPDMA_READ;
+
+               tf->nsect = tag << 3;
+               tf->hob_feature = (n_block >> 8) & 0xff;
+               tf->feature = n_block & 0xff;
+
+               tf->hob_lbah = (block >> 40) & 0xff;
+               tf->hob_lbam = (block >> 32) & 0xff;
+               tf->hob_lbal = (block >> 24) & 0xff;
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device = 1 << 6;
+               if (tf->flags & ATA_TFLAG_FUA)
+                       tf->device |= 1 << 7;
+       } else if (dev->flags & ATA_DFLAG_LBA) {
+               tf->flags |= ATA_TFLAG_LBA;
+
+               if (lba_28_ok(block, n_block)) {
+                       /* use LBA28 */
+                       tf->device |= (block >> 24) & 0xf;
+               } else if (lba_48_ok(block, n_block)) {
+                       if (!(dev->flags & ATA_DFLAG_LBA48))
+                               return -ERANGE;
+
+                       /* use LBA48 */
+                       tf->flags |= ATA_TFLAG_LBA48;
+
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
+
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else
+                       /* request too large even for LBA48 */
+                       return -ERANGE;
+
+               if (unlikely(ata_rwcmd_protocol(tf, dev) < 0))
+                       return -EINVAL;
+
+               tf->nsect = n_block & 0xff;
+
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device |= ATA_LBA;
+       } else {
+               /* CHS */
+               u32 sect, head, cyl, track;
+
+               /* The request -may- be too large for CHS addressing. */
+               if (!lba_28_ok(block, n_block))
+                       return -ERANGE;
+
+               if (unlikely(ata_rwcmd_protocol(tf, dev) < 0))
+                       return -EINVAL;
+
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
+
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+                       (u32)block, track, cyl, head, sect);
+
+               /* Check whether the converted CHS can fit.
+                  Cylinder: 0-65535
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+                       return -ERANGE;
+
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
+       }
+
+       return 0;
+}
+
 /**
  *     ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
  *     @pio_mask: pio_mask
@@ -999,13 +1166,13 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_exec_internal - execute libata internal command
+ *     ata_exec_internal_sg - execute libata internal command
  *     @dev: Device to which the command is sent
  *     @tf: Taskfile registers for the command and the result
  *     @cdb: CDB for packet command
  *     @dma_dir: Data tranfer direction of the command
- *     @buf: Data buffer of the command
- *     @buflen: Length of data buffer
+ *     @sg: sg list for the data buffer of the command
+ *     @n_elem: Number of sg entries
  *
  *     Executes libata internal command with timeout.  @tf contains
  *     command on entry and result on return.  Timeout and error
@@ -1019,9 +1186,10 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc)
  *     RETURNS:
  *     Zero on success, AC_ERR_* mask on failure
  */
-unsigned ata_exec_internal(struct ata_device *dev,
-                          struct ata_taskfile *tf, const u8 *cdb,
-                          int dma_dir, void *buf, unsigned int buflen)
+unsigned ata_exec_internal_sg(struct ata_device *dev,
+                             struct ata_taskfile *tf, const u8 *cdb,
+                             int dma_dir, struct scatterlist *sg,
+                             unsigned int n_elem)
 {
        struct ata_port *ap = dev->ap;
        u8 command = tf->command;
@@ -1077,7 +1245,12 @@ unsigned ata_exec_internal(struct ata_device *dev,
        qc->flags |= ATA_QCFLAG_RESULT_TF;
        qc->dma_dir = dma_dir;
        if (dma_dir != DMA_NONE) {
-               ata_sg_init_one(qc, buf, buflen);
+               unsigned int i, buflen = 0;
+
+               for (i = 0; i < n_elem; i++)
+                       buflen += sg[i].length;
+
+               ata_sg_init(qc, sg, n_elem);
                qc->nsect = buflen / ATA_SECT_SIZE;
        }
 
@@ -1160,6 +1333,35 @@ unsigned ata_exec_internal(struct ata_device *dev,
        return err_mask;
 }
 
+/**
+ *     ata_exec_internal_sg - execute libata internal command
+ *     @dev: Device to which the command is sent
+ *     @tf: Taskfile registers for the command and the result
+ *     @cdb: CDB for packet command
+ *     @dma_dir: Data tranfer direction of the command
+ *     @buf: Data buffer of the command
+ *     @buflen: Length of data buffer
+ *
+ *     Wrapper around ata_exec_internal_sg() which takes simple
+ *     buffer instead of sg list.
+ *
+ *     LOCKING:
+ *     None.  Should be called with kernel context, might sleep.
+ *
+ *     RETURNS:
+ *     Zero on success, AC_ERR_* mask on failure
+ */
+unsigned ata_exec_internal(struct ata_device *dev,
+                          struct ata_taskfile *tf, const u8 *cdb,
+                          int dma_dir, void *buf, unsigned int buflen)
+{
+       struct scatterlist sg;
+
+       sg_init_one(&sg, buf, buflen);
+
+       return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1);
+}
+
 /**
  *     ata_do_simple_cmd - execute simple internal command
  *     @dev: Device to which the command is sent
@@ -1224,7 +1426,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
  *     ata_dev_read_id - Read ID data from the specified device
  *     @dev: target device
  *     @p_class: pointer to class of the target device (may be changed)
- *     @post_reset: is this read ID post-reset?
+ *     @flags: ATA_READID_* flags
  *     @id: buffer to read IDENTIFY data into
  *
  *     Read ID data from the specified device.  ATA_CMD_ID_ATA is
@@ -1239,7 +1441,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
  *     0 on success, -errno otherwise.
  */
 int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
-                   int post_reset, u16 *id)
+                   unsigned int flags, u16 *id)
 {
        struct ata_port *ap = dev->ap;
        unsigned int class = *p_class;
@@ -1271,10 +1473,17 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
        }
 
        tf.protocol = ATA_PROT_PIO;
+       tf.flags |= ATA_TFLAG_POLLING; /* for polling presence detection */
 
        err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
                                     id, sizeof(id[0]) * ATA_ID_WORDS);
        if (err_mask) {
+               if (err_mask & AC_ERR_NODEV_HINT) {
+                       DPRINTK("ata%u.%d: NODEV after polling detection\n",
+                               ap->id, dev->devno);
+                       return -ENOENT;
+               }
+
                rc = -EIO;
                reason = "I/O error";
                goto err_out;
@@ -1294,7 +1503,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
                        goto err_out;
        }
 
-       if (post_reset && class == ATA_DEV_ATA) {
+       if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
                /*
                 * The exact sequence expected by certain pre-ATA4 drives is:
                 * SRST RESET
@@ -1314,7 +1523,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
                        /* current CHS translation info (id[53-58]) might be
                         * changed. reread the identify device info.
                         */
-                       post_reset = 0;
+                       flags &= ~ATA_READID_POSTRESET;
                        goto retry;
                }
        }
@@ -1345,7 +1554,10 @@ static void ata_dev_config_ncq(struct ata_device *dev,
                desc[0] = '\0';
                return;
        }
-
+       if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
+               snprintf(desc, desc_sz, "NCQ (not used)");
+               return;
+       }
        if (ap->flags & ATA_FLAG_NCQ) {
                hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
                dev->flags |= ATA_DFLAG_NCQ;
@@ -1374,7 +1586,6 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap)
 /**
  *     ata_dev_configure - Configure the specified ATA/ATAPI device
  *     @dev: Target device to configure
- *     @print_info: Enable device info printout
  *
  *     Configure @dev according to @dev->id.  Generic and low-level
  *     driver specific fixups are also applied.
@@ -1385,9 +1596,10 @@ static void ata_set_port_max_cmd_len(struct ata_port *ap)
  *     RETURNS:
  *     0 on success, -errno otherwise
  */
-int ata_dev_configure(struct ata_device *dev, int print_info)
+int ata_dev_configure(struct ata_device *dev)
 {
        struct ata_port *ap = dev->ap;
+       int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
        const u16 *id = dev->id;
        unsigned int xfer_mask;
        char revbuf[7];         /* XYZ-99\0 */
@@ -1454,6 +1666,10 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
                        if (ata_id_has_lba48(id)) {
                                dev->flags |= ATA_DFLAG_LBA48;
                                lba_desc = "LBA48";
+
+                               if (dev->n_sectors >= (1UL << 28) &&
+                                   ata_id_has_flush_ext(id))
+                                       dev->flags |= ATA_DFLAG_FLUSH_EXT;
                        }
 
                        /* config NCQ */
@@ -1530,6 +1746,11 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
                                       cdb_intr_string);
        }
 
+       /* determine max_sectors */
+       dev->max_sectors = ATA_MAX_SECTORS;
+       if (dev->flags & ATA_DFLAG_LBA48)
+               dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
        if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
                /* Let the user know. We don't want to disallow opens for
                   rescue purposes, or in case the vendor is just a blithering
@@ -1631,11 +1852,14 @@ int ata_bus_probe(struct ata_port *ap)
                if (!ata_dev_enabled(dev))
                        continue;
 
-               rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+               rc = ata_dev_read_id(dev, &dev->class, ATA_READID_POSTRESET,
+                                    dev->id);
                if (rc)
                        goto fail;
 
-               rc = ata_dev_configure(dev, 1);
+               ap->eh_context.i.flags |= ATA_EHI_PRINTINFO;
+               rc = ata_dev_configure(dev);
+               ap->eh_context.i.flags &= ~ATA_EHI_PRINTINFO;
                if (rc)
                        goto fail;
        }
@@ -2153,6 +2377,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
 
 static int ata_dev_set_mode(struct ata_device *dev)
 {
+       struct ata_eh_context *ehc = &dev->ap->eh_context;
        unsigned int err_mask;
        int rc;
 
@@ -2167,7 +2392,9 @@ static int ata_dev_set_mode(struct ata_device *dev)
                return -EIO;
        }
 
+       ehc->i.flags |= ATA_EHI_POST_SETMODE;
        rc = ata_dev_revalidate(dev, 0);
+       ehc->i.flags &= ~ATA_EHI_POST_SETMODE;
        if (rc)
                return rc;
 
@@ -2325,11 +2552,14 @@ static inline void ata_tf_to_host(struct ata_port *ap,
  *     Sleep until ATA Status register bit BSY clears,
  *     or a timeout occurs.
  *
- *     LOCKING: None.
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
  */
-
-unsigned int ata_busy_sleep (struct ata_port *ap,
-                            unsigned long tmout_pat, unsigned long tmout)
+int ata_busy_sleep(struct ata_port *ap,
+                  unsigned long tmout_pat, unsigned long tmout)
 {
        unsigned long timer_start, timeout;
        u8 status;
@@ -2337,27 +2567,32 @@ unsigned int ata_busy_sleep (struct ata_port *ap,
        status = ata_busy_wait(ap, ATA_BUSY, 300);
        timer_start = jiffies;
        timeout = timer_start + tmout_pat;
-       while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+       while (status != 0xff && (status & ATA_BUSY) &&
+              time_before(jiffies, timeout)) {
                msleep(50);
                status = ata_busy_wait(ap, ATA_BUSY, 3);
        }
 
-       if (status & ATA_BUSY)
+       if (status != 0xff && (status & ATA_BUSY))
                ata_port_printk(ap, KERN_WARNING,
                                "port is slow to respond, please be patient "
                                "(Status 0x%x)\n", status);
 
        timeout = timer_start + tmout;
-       while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+       while (status != 0xff && (status & ATA_BUSY) &&
+              time_before(jiffies, timeout)) {
                msleep(50);
                status = ata_chk_status(ap);
        }
 
+       if (status == 0xff)
+               return -ENODEV;
+
        if (status & ATA_BUSY) {
                ata_port_printk(ap, KERN_ERR, "port failed to respond "
                                "(%lu secs, Status 0x%x)\n",
                                tmout / HZ, status);
-               return 1;
+               return -EBUSY;
        }
 
        return 0;
@@ -2448,10 +2683,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
         * the bus shows 0xFF because the odd clown forgets the D7
         * pulldown resistor.
         */
-       if (ata_check_status(ap) == 0xFF) {
-               ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
-               return AC_ERR_OTHER;
-       }
+       if (ata_check_status(ap) == 0xFF)
+               return 0;
 
        ata_bus_post_reset(ap, devmask);
 
@@ -2777,9 +3010,9 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
 }
 
 /**
- *     sata_std_hardreset - reset host port via SATA phy reset
+ *     sata_port_hardreset - reset port via SATA phy reset
  *     @ap: port to reset
- *     @class: resulting class of attached device
+ *     @timing: timing parameters { interval, duratinon, timeout } in msec
  *
  *     SATA phy-reset host port using DET bits of SControl register.
  *
@@ -2789,10 +3022,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
+int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
 {
-       struct ata_eh_context *ehc = &ap->eh_context;
-       const unsigned long *timing = sata_ehc_deb_timing(ehc);
        u32 scontrol;
        int rc;
 
@@ -2805,24 +3036,24 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
                 * and Sil3124.
                 */
                if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
-                       return rc;
+                       goto out;
 
                scontrol = (scontrol & 0x0f0) | 0x304;
 
                if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
-                       return rc;
+                       goto out;
 
                sata_set_spd(ap);
        }
 
        /* issue phy wake/reset */
        if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
-               return rc;
+               goto out;
 
        scontrol = (scontrol & 0x0f0) | 0x301;
 
        if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
-               return rc;
+               goto out;
 
        /* Couldn't find anything in SATA I/II specs, but AHCI-1.1
         * 10.4.2 says at least 1 ms.
@@ -2830,7 +3061,40 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
        msleep(1);
 
        /* bring phy back */
-       sata_phy_resume(ap, timing);
+       rc = sata_phy_resume(ap, timing);
+ out:
+       DPRINTK("EXIT, rc=%d\n", rc);
+       return rc;
+}
+
+/**
+ *     sata_std_hardreset - reset host port via SATA phy reset
+ *     @ap: port to reset
+ *     @class: resulting class of attached device
+ *
+ *     SATA phy-reset host port using DET bits of SControl register,
+ *     wait for !BSY and classify the attached device.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
+{
+       const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       /* do hardreset */
+       rc = sata_port_hardreset(ap, timing);
+       if (rc) {
+               ata_port_printk(ap, KERN_ERR,
+                               "COMRESET failed (errno=%d)\n", rc);
+               return rc;
+       }
 
        /* TODO: phy layer with polling, timeouts, etc. */
        if (ata_port_offline(ap)) {
@@ -2969,7 +3233,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
 /**
  *     ata_dev_revalidate - Revalidate ATA device
  *     @dev: device to revalidate
- *     @post_reset: is this revalidation after reset?
+ *     @readid_flags: read ID flags
  *
  *     Re-read IDENTIFY page and make sure @dev is still attached to
  *     the port.
@@ -2980,7 +3244,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
  *     RETURNS:
  *     0 on success, negative errno otherwise
  */
-int ata_dev_revalidate(struct ata_device *dev, int post_reset)
+int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
 {
        unsigned int class = dev->class;
        u16 *id = (void *)dev->ap->sector_buf;
@@ -2992,7 +3256,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
        }
 
        /* read ID data */
-       rc = ata_dev_read_id(dev, &class, post_reset, id);
+       rc = ata_dev_read_id(dev, &class, readid_flags, id);
        if (rc)
                goto fail;
 
@@ -3005,7 +3269,7 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
        memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
 
        /* configure device according to the new ID */
-       rc = ata_dev_configure(dev, 0);
+       rc = ata_dev_configure(dev);
        if (rc == 0)
                return 0;
 
@@ -3014,37 +3278,55 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
        return rc;
 }
 
-static const char * const ata_dma_blacklist [] = {
-       "WDC AC11000H", NULL,
-       "WDC AC22100H", NULL,
-       "WDC AC32500H", NULL,
-       "WDC AC33100H", NULL,
-       "WDC AC31600H", NULL,
-       "WDC AC32100H", "24.09P07",
-       "WDC AC23200L", "21.10N21",
-       "Compaq CRD-8241B",  NULL,
-       "CRD-8400B", NULL,
-       "CRD-8480B", NULL,
-       "CRD-8482B", NULL,
-       "CRD-84", NULL,
-       "SanDisk SDP3B", NULL,
-       "SanDisk SDP3B-64", NULL,
-       "SANYO CD-ROM CRD", NULL,
-       "HITACHI CDR-8", NULL,
-       "HITACHI CDR-8335", NULL,
-       "HITACHI CDR-8435", NULL,
-       "Toshiba CD-ROM XM-6202B", NULL,
-       "TOSHIBA CD-ROM XM-1702BC", NULL,
-       "CD-532E-A", NULL,
-       "E-IDE CD-ROM CR-840", NULL,
-       "CD-ROM Drive/F5A", NULL,
-       "WPI CDD-820", NULL,
-       "SAMSUNG CD-ROM SC-148C", NULL,
-       "SAMSUNG CD-ROM SC", NULL,
-       "SanDisk SDP3B-64", NULL,
-       "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,
-       "_NEC DV5800A", NULL,
-       "SAMSUNG CD-ROM SN-124", "N001"
+struct ata_blacklist_entry {
+       const char *model_num;
+       const char *model_rev;
+       unsigned long horkage;
+};
+
+static const struct ata_blacklist_entry ata_device_blacklist [] = {
+       /* Devices with DMA related problems under Linux */
+       { "WDC AC11000H",       NULL,           ATA_HORKAGE_NODMA },
+       { "WDC AC22100H",       NULL,           ATA_HORKAGE_NODMA },
+       { "WDC AC32500H",       NULL,           ATA_HORKAGE_NODMA },
+       { "WDC AC33100H",       NULL,           ATA_HORKAGE_NODMA },
+       { "WDC AC31600H",       NULL,           ATA_HORKAGE_NODMA },
+       { "WDC AC32100H",       "24.09P07",     ATA_HORKAGE_NODMA },
+       { "WDC AC23200L",       "21.10N21",     ATA_HORKAGE_NODMA },
+       { "Compaq CRD-8241B",   NULL,           ATA_HORKAGE_NODMA },
+       { "CRD-8400B",          NULL,           ATA_HORKAGE_NODMA },
+       { "CRD-8480B",          NULL,           ATA_HORKAGE_NODMA },
+       { "CRD-8482B",          NULL,           ATA_HORKAGE_NODMA },
+       { "CRD-84",             NULL,           ATA_HORKAGE_NODMA },
+       { "SanDisk SDP3B",      NULL,           ATA_HORKAGE_NODMA },
+       { "SanDisk SDP3B-64",   NULL,           ATA_HORKAGE_NODMA },
+       { "SANYO CD-ROM CRD",   NULL,           ATA_HORKAGE_NODMA },
+       { "HITACHI CDR-8",      NULL,           ATA_HORKAGE_NODMA },
+       { "HITACHI CDR-8335",   NULL,           ATA_HORKAGE_NODMA },
+       { "HITACHI CDR-8435",   NULL,           ATA_HORKAGE_NODMA },
+       { "Toshiba CD-ROM XM-6202B", NULL,      ATA_HORKAGE_NODMA },
+       { "TOSHIBA CD-ROM XM-1702BC", NULL,     ATA_HORKAGE_NODMA },
+       { "CD-532E-A",          NULL,           ATA_HORKAGE_NODMA },
+       { "E-IDE CD-ROM CR-840",NULL,           ATA_HORKAGE_NODMA },
+       { "CD-ROM Drive/F5A",   NULL,           ATA_HORKAGE_NODMA },
+       { "WPI CDD-820",        NULL,           ATA_HORKAGE_NODMA },
+       { "SAMSUNG CD-ROM SC-148C", NULL,       ATA_HORKAGE_NODMA },
+       { "SAMSUNG CD-ROM SC",  NULL,           ATA_HORKAGE_NODMA },
+       { "SanDisk SDP3B-64",   NULL,           ATA_HORKAGE_NODMA },
+       { "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
+       { "_NEC DV5800A",       NULL,           ATA_HORKAGE_NODMA },
+       { "SAMSUNG CD-ROM SN-124","N001",       ATA_HORKAGE_NODMA },
+
+       /* Devices we expect to fail diagnostics */
+
+       /* Devices where NCQ should be avoided */
+       /* NCQ is slow */
+        { "WDC WD740ADFD-00",   NULL,          ATA_HORKAGE_NONCQ },
+
+       /* Devices with NCQ limits */
+
+       /* End Marker */
+       { }
 };
 
 static int ata_strim(char *s, size_t len)
@@ -3059,20 +3341,12 @@ static int ata_strim(char *s, size_t len)
        return len;
 }
 
-static int ata_dma_blacklisted(const struct ata_device *dev)
+unsigned long ata_device_blacklisted(const struct ata_device *dev)
 {
        unsigned char model_num[40];
        unsigned char model_rev[16];
        unsigned int nlen, rlen;
-       int i;
-
-       /* We don't support polling DMA.
-        * DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
-        * if the LLDD handles only interrupts in the HSM_ST_LAST state.
-        */
-       if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
-           (dev->flags & ATA_DFLAG_CDB_INTR))
-               return 1;
+       const struct ata_blacklist_entry *ad = ata_device_blacklist;
 
        ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
                          sizeof(model_num));
@@ -3081,17 +3355,30 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
        nlen = ata_strim(model_num, sizeof(model_num));
        rlen = ata_strim(model_rev, sizeof(model_rev));
 
-       for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) {
-               if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) {
-                       if (ata_dma_blacklist[i+1] == NULL)
-                               return 1;
-                       if (!strncmp(ata_dma_blacklist[i], model_rev, rlen))
-                               return 1;
+       while (ad->model_num) {
+               if (!strncmp(ad->model_num, model_num, nlen)) {
+                       if (ad->model_rev == NULL)
+                               return ad->horkage;
+                       if (!strncmp(ad->model_rev, model_rev, rlen))
+                               return ad->horkage;
                }
+               ad++;
        }
        return 0;
 }
 
+static int ata_dma_blacklisted(const struct ata_device *dev)
+{
+       /* We don't support polling DMA.
+        * DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
+        * if the LLDD handles only interrupts in the HSM_ST_LAST state.
+        */
+       if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
+           (dev->flags & ATA_DFLAG_CDB_INTR))
+               return 1;
+       return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
+}
+
 /**
  *     ata_dev_xfermask - Compute supported xfermask of the given device
  *     @dev: Device to compute xfermask for
@@ -3119,6 +3406,13 @@ static void ata_dev_xfermask(struct ata_device *dev)
         */
        if (ap->cbl == ATA_CBL_PATA40)
                xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
+       /* Apply drive side cable rule. Unknown or 80 pin cables reported
+        * host side are checked drive side as well. Cases where we know a
+        * 40wire cable is used safely for 80 are not checked here.
+        */
+        if (ata_drive_40wire(dev->id) && (ap->cbl == ATA_CBL_PATA_UNK || ap->cbl == ATA_CBL_PATA80))
+               xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
+
 
        xfer_mask &= ata_pack_xfermask(dev->pio_mask,
                                       dev->mwdma_mask, dev->udma_mask);
@@ -3236,8 +3530,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-static void ata_sg_clean(struct ata_queued_cmd *qc)
+void ata_sg_clean(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct scatterlist *sg = qc->__sg;
@@ -3395,19 +3688,15 @@ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
 
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
-       struct scatterlist *sg;
-
        qc->flags |= ATA_QCFLAG_SINGLE;
 
-       memset(&qc->sgent, 0, sizeof(qc->sgent));
        qc->__sg = &qc->sgent;
        qc->n_elem = 1;
        qc->orig_n_elem = 1;
        qc->buf_virt = buf;
        qc->nbytes = buflen;
 
-       sg = qc->__sg;
-       sg_init_one(sg, buf, buflen);
+       sg_init_one(&qc->sgent, buf, buflen);
 }
 
 /**
@@ -4200,8 +4489,12 @@ fsm_start:
                                        /* device stops HSM for abort/error */
                                        qc->err_mask |= AC_ERR_DEV;
                                else
-                                       /* HSM violation. Let EH handle this */
-                                       qc->err_mask |= AC_ERR_HSM;
+                                       /* HSM violation. Let EH handle this.
+                                        * Phantom devices also trigger this
+                                        * condition.  Mark hint.
+                                        */
+                                       qc->err_mask |= AC_ERR_HSM |
+                                                       AC_ERR_NODEV_HINT;
 
                                ap->hsm_task_state = HSM_ST_ERR;
                                goto fsm_start;
@@ -4440,6 +4733,14 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
        qc->complete_fn(qc);
 }
 
+static void fill_result_tf(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       ap->ops->tf_read(ap, &qc->result_tf);
+       qc->result_tf.flags = qc->tf.flags;
+}
+
 /**
  *     ata_qc_complete - Complete an active ATA command
  *     @qc: Command to complete
@@ -4477,7 +4778,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
                        if (!ata_tag_internal(qc->tag)) {
                                /* always fill result TF for failed qc */
-                               ap->ops->tf_read(ap, &qc->result_tf);
+                               fill_result_tf(qc);
                                ata_qc_schedule_eh(qc);
                                return;
                        }
@@ -4485,7 +4786,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 
                /* read result TF if requested */
                if (qc->flags & ATA_QCFLAG_RESULT_TF)
-                       ap->ops->tf_read(ap, &qc->result_tf);
+                       fill_result_tf(qc);
 
                __ata_qc_complete(qc);
        } else {
@@ -4494,7 +4795,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 
                /* read result TF if failed or requested */
                if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
-                       ap->ops->tf_read(ap, &qc->result_tf);
+                       fill_result_tf(qc);
 
                __ata_qc_complete(qc);
        }
@@ -4674,6 +4975,14 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
                }
        }
 
+       /* Some controllers show flaky interrupt behavior after
+        * setting xfer mode.  Use polling instead.
+        */
+       if (unlikely(qc->tf.command == ATA_CMD_SET_FEATURES &&
+                    qc->tf.feature == SETFEATURES_XFER) &&
+           (ap->flags & ATA_FLAG_SETXFER_POLLING))
+               qc->tf.flags |= ATA_TFLAG_POLLING;
+
        /* select the device */
        ata_dev_select(ap, qc->dev->devno, 1, 0);
 
@@ -4782,6 +5091,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 inline unsigned int ata_host_intr (struct ata_port *ap,
                                   struct ata_queued_cmd *qc)
 {
+       struct ata_eh_info *ehi = &ap->eh_info;
        u8 status, host_stat = 0;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
@@ -4842,6 +5152,11 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
        ap->ops->irq_clear(ap);
 
        ata_hsm_move(ap, qc, status, 0);
+
+       if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+                                      qc->tf.protocol == ATA_PROT_ATAPI_DMA))
+               ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+
        return 1;       /* irq handled */
 
 idle_irq:
@@ -5048,7 +5363,7 @@ int ata_flush_cache(struct ata_device *dev)
        if (!ata_try_flush_cache(dev))
                return 0;
 
-       if (ata_id_has_flush_ext(dev->id))
+       if (dev->flags & ATA_DFLAG_FLUSH_EXT)
                cmd = ATA_CMD_FLUSH_EXT;
        else
                cmd = ATA_CMD_FLUSH;
@@ -5520,9 +5835,8 @@ int ata_device_add(const struct ata_probe_ent *ent)
                                ap->ioaddr.bmdma_addr,
                                irq_line);
 
-               ata_chk_status(ap);
-               host->ops->irq_clear(ap);
-               ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
+               /* freeze port before requesting IRQ */
+               ata_eh_freeze_port(ap);
        }
 
        /* obtain irq, that may be shared between channels */
@@ -6120,6 +6434,7 @@ EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
 EXPORT_SYMBOL_GPL(ata_std_prereset);
 EXPORT_SYMBOL_GPL(ata_std_softreset);
+EXPORT_SYMBOL_GPL(sata_port_hardreset);
 EXPORT_SYMBOL_GPL(sata_std_hardreset);
 EXPORT_SYMBOL_GPL(ata_std_postreset);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
@@ -6146,6 +6461,7 @@ EXPORT_SYMBOL_GPL(ata_host_suspend);
 EXPORT_SYMBOL_GPL(ata_host_resume);
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
+EXPORT_SYMBOL_GPL(ata_device_blacklisted);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
index 02b2b2787d9b85a33a420fc77b5dc18aac7e29ad..76a85dfb7307176e93107218c82e604a95b9c4b4 100644 (file)
@@ -1136,19 +1136,21 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
                break;
 
        case ATA_DEV_ATAPI:
-               tmp = atapi_eh_request_sense(qc->dev,
-                                            qc->scsicmd->sense_buffer);
-               if (!tmp) {
-                       /* ATA_QCFLAG_SENSE_VALID is used to tell
-                        * atapi_qc_complete() that sense data is
-                        * already valid.
-                        *
-                        * TODO: interpret sense data and set
-                        * appropriate err_mask.
-                        */
-                       qc->flags |= ATA_QCFLAG_SENSE_VALID;
-               } else
-                       qc->err_mask |= tmp;
+               if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
+                       tmp = atapi_eh_request_sense(qc->dev,
+                                                    qc->scsicmd->sense_buffer);
+                       if (!tmp) {
+                               /* ATA_QCFLAG_SENSE_VALID is used to
+                                * tell atapi_qc_complete() that sense
+                                * data is already valid.
+                                *
+                                * TODO: interpret sense data and set
+                                * appropriate err_mask.
+                                */
+                               qc->flags |= ATA_QCFLAG_SENSE_VALID;
+                       } else
+                               qc->err_mask |= tmp;
+               }
        }
 
        if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
@@ -1433,16 +1435,39 @@ static void ata_eh_report(struct ata_port *ap)
        }
 
        for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               static const char *dma_str[] = {
+                       [DMA_BIDIRECTIONAL]     = "bidi",
+                       [DMA_TO_DEVICE]         = "out",
+                       [DMA_FROM_DEVICE]       = "in",
+                       [DMA_NONE]              = "",
+               };
                struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+               struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
+               unsigned int nbytes;
 
                if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
                        continue;
 
-               ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
-                              "Emask 0x%x stat 0x%x err 0x%x (%s)\n",
-                              qc->tag, qc->tf.command, qc->err_mask,
-                              qc->result_tf.command, qc->result_tf.feature,
-                              ata_err_string(qc->err_mask));
+               nbytes = qc->nbytes;
+               if (!nbytes)
+                       nbytes = qc->nsect << 9;
+
+               ata_dev_printk(qc->dev, KERN_ERR,
+                       "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
+                       "tag %d cdb 0x%x data %u %s\n         "
+                       "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
+                       "Emask 0x%x (%s)\n",
+                       cmd->command, cmd->feature, cmd->nsect,
+                       cmd->lbal, cmd->lbam, cmd->lbah,
+                       cmd->hob_feature, cmd->hob_nsect,
+                       cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah,
+                       cmd->device, qc->tag, qc->cdb[0], nbytes,
+                       dma_str[qc->dma_dir],
+                       res->command, res->feature, res->nsect,
+                       res->lbal, res->lbam, res->lbah,
+                       res->hob_feature, res->hob_nsect,
+                       res->hob_lbal, res->hob_lbam, res->hob_lbah,
+                       res->device, qc->err_mask, ata_err_string(qc->err_mask));
        }
 }
 
@@ -1634,11 +1659,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
        DPRINTK("ENTER\n");
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               unsigned int action;
+               unsigned int action, readid_flags = 0;
 
                dev = &ap->device[i];
                action = ata_eh_dev_action(dev);
 
+               if (ehc->i.flags & ATA_EHI_DID_RESET)
+                       readid_flags |= ATA_READID_POSTRESET;
+
                if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
                        if (ata_port_offline(ap)) {
                                rc = -EIO;
@@ -1646,13 +1674,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
                        }
 
                        ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
-                       rc = ata_dev_revalidate(dev,
-                                       ehc->i.flags & ATA_EHI_DID_RESET);
+                       rc = ata_dev_revalidate(dev, readid_flags);
                        if (rc)
                                break;
 
                        ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
 
+                       /* Configuration may have changed, reconfigure
+                        * transfer mode.
+                        */
+                       ehc->i.flags |= ATA_EHI_SETMODE;
+
                        /* schedule the scsi_rescan_device() here */
                        queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
                } else if (dev->class == ATA_DEV_UNKNOWN &&
@@ -1660,18 +1692,35 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
                           ata_class_enabled(ehc->classes[dev->devno])) {
                        dev->class = ehc->classes[dev->devno];
 
-                       rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
-                       if (rc == 0)
-                               rc = ata_dev_configure(dev, 1);
+                       rc = ata_dev_read_id(dev, &dev->class, readid_flags,
+                                            dev->id);
+                       if (rc == 0) {
+                               ehc->i.flags |= ATA_EHI_PRINTINFO;
+                               rc = ata_dev_configure(dev);
+                               ehc->i.flags &= ~ATA_EHI_PRINTINFO;
+                       } else if (rc == -ENOENT) {
+                               /* IDENTIFY was issued to non-existent
+                                * device.  No need to reset.  Just
+                                * thaw and kill the device.
+                                */
+                               ata_eh_thaw_port(ap);
+                               dev->class = ATA_DEV_UNKNOWN;
+                               rc = 0;
+                       }
 
                        if (rc) {
                                dev->class = ATA_DEV_UNKNOWN;
                                break;
                        }
 
-                       spin_lock_irqsave(ap->lock, flags);
-                       ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
-                       spin_unlock_irqrestore(ap->lock, flags);
+                       if (ata_dev_enabled(dev)) {
+                               spin_lock_irqsave(ap->lock, flags);
+                               ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+                               spin_unlock_irqrestore(ap->lock, flags);
+
+                               /* new device discovered, configure xfermode */
+                               ehc->i.flags |= ATA_EHI_SETMODE;
+                       }
                }
        }
 
@@ -1987,13 +2036,14 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
        if (rc)
                goto dev_fail;
 
-       /* configure transfer mode if the port has been reset */
-       if (ehc->i.flags & ATA_EHI_DID_RESET) {
+       /* configure transfer mode if necessary */
+       if (ehc->i.flags & ATA_EHI_SETMODE) {
                rc = ata_set_mode(ap, &dev);
                if (rc) {
                        down_xfermask = 1;
                        goto dev_fail;
                }
+               ehc->i.flags &= ~ATA_EHI_SETMODE;
        }
 
        /* suspend devices */
index 47ea111d5acee837d20d8939b9c52c6a46f0357e..8eaace94d9631e9e2b64fdc3443ca26d0d41bf66 100644 (file)
@@ -671,7 +671,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
 }
 
 /*
- *     ata_gen_ata_desc_sense - Generate check condition sense block.
+ *     ata_gen_passthru_sense - Generate check condition sense block.
  *     @qc: Command that completed.
  *
  *     This function is specific to the ATA descriptor format sense
@@ -681,9 +681,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
  *     block. Clear sense key, ASC & ASCQ if there is no error.
  *
  *     LOCKING:
- *     spin_lock_irqsave(host lock)
+ *     None.
  */
-void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
        struct ata_taskfile *tf = &qc->result_tf;
@@ -713,12 +713,9 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
 
        desc[0] = 0x09;
 
-       /*
-        * Set length of additional sense data.
-        * Since we only populate descriptor 0, the total
-        * length is the same (fixed) length as descriptor 0.
-        */
-       desc[1] = sb[7] = 14;
+       /* set length of additional sense data */
+       sb[7] = 14;
+       desc[1] = 12;
 
        /*
         * Copy registers into sense buffer.
@@ -746,56 +743,56 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_gen_fixed_sense - generate a SCSI fixed sense block
+ *     ata_gen_ata_sense - generate a SCSI fixed sense block
  *     @qc: Command that we are erroring out
  *
- *     Leverage ata_to_sense_error() to give us the codes.  Fit our
- *     LBA in here if there's room.
+ *     Generate sense block for a failed ATA command @qc.  Descriptor
+ *     format is used to accomodate LBA48 block address.
  *
  *     LOCKING:
- *     inherited from caller
+ *     None.
  */
-void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
 {
+       struct ata_device *dev = qc->dev;
        struct scsi_cmnd *cmd = qc->scsicmd;
        struct ata_taskfile *tf = &qc->result_tf;
        unsigned char *sb = cmd->sense_buffer;
+       unsigned char *desc = sb + 8;
        int verbose = qc->ap->ops->error_handler == NULL;
+       u64 block;
 
        memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
        cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-       /*
-        * Use ata_to_sense_error() to map status register bits
+       /* sense data is current and format is descriptor */
+       sb[0] = 0x72;
+
+       /* Use ata_to_sense_error() to map status register bits
         * onto sense key, asc & ascq.
         */
        if (qc->err_mask ||
            tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
                ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-                                  &sb[2], &sb[12], &sb[13], verbose);
-               sb[2] &= 0x0f;
+                                  &sb[1], &sb[2], &sb[3], verbose);
+               sb[1] &= 0x0f;
        }
 
-       sb[0] = 0x70;
-       sb[7] = 0x0a;
-
-       if (tf->flags & ATA_TFLAG_LBA48) {
-               /* TODO: find solution for LBA48 descriptors */
-       }
+       block = ata_tf_read_block(&qc->result_tf, dev);
 
-       else if (tf->flags & ATA_TFLAG_LBA) {
-               /* A small (28b) LBA will fit in the 32b info field */
-               sb[0] |= 0x80;          /* set valid bit */
-               sb[3] = tf->device & 0x0f;
-               sb[4] = tf->lbah;
-               sb[5] = tf->lbam;
-               sb[6] = tf->lbal;
-       }
+       /* information sense data descriptor */
+       sb[7] = 12;
+       desc[0] = 0x00;
+       desc[1] = 10;
 
-       else {
-               /* TODO: C/H/S */
-       }
+       desc[2] |= 0x80;        /* valid */
+       desc[6] = block >> 40;
+       desc[7] = block >> 32;
+       desc[8] = block >> 24;
+       desc[9] = block >> 16;
+       desc[10] = block >> 8;
+       desc[11] = block;
 }
 
 static void ata_scsi_sdev_config(struct scsi_device *sdev)
@@ -807,23 +804,10 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
 static void ata_scsi_dev_config(struct scsi_device *sdev,
                                struct ata_device *dev)
 {
-       unsigned int max_sectors;
-
-       /* TODO: 2048 is an arbitrary number, not the
-        * hardware maximum.  This should be increased to
-        * 65534 when Jens Axboe's patch for dynamically
-        * determining max_sectors is merged.
-        */
-       max_sectors = ATA_MAX_SECTORS;
-       if (dev->flags & ATA_DFLAG_LBA48)
-               max_sectors = ATA_MAX_SECTORS_LBA48;
-       if (dev->max_sectors)
-               max_sectors = dev->max_sectors;
+       /* configure max sectors */
+       blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);
 
-       blk_queue_max_sectors(sdev->request_queue, max_sectors);
-
-       /*
-        * SATA DMA transfers must be multiples of 4 byte, so
+       /* SATA DMA transfers must be multiples of 4 byte, so
         * we need to pad ATAPI transfers using an extra sg.
         * Decrement max hw segments accordingly.
         */
@@ -1040,8 +1024,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs
        tf->flags |= ATA_TFLAG_DEVICE;
        tf->protocol = ATA_PROT_NODATA;
 
-       if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
-           (ata_id_has_flush_ext(qc->dev->id)))
+       if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT)
                tf->command = ATA_CMD_FLUSH_EXT;
        else
                tf->command = ATA_CMD_FLUSH;
@@ -1282,17 +1265,14 @@ nothing_to_do:
 
 static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
 {
-       struct ata_taskfile *tf = &qc->tf;
-       struct ata_device *dev = qc->dev;
+       unsigned int tf_flags = 0;
        u64 block;
        u32 n_block;
-
-       qc->flags |= ATA_QCFLAG_IO;
-       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       int rc;
 
        if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
            scsicmd[0] == WRITE_16)
-               tf->flags |= ATA_TFLAG_WRITE;
+               tf_flags |= ATA_TFLAG_WRITE;
 
        /* Calculate the SCSI LBA, transfer length and FUA. */
        switch (scsicmd[0]) {
@@ -1300,7 +1280,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
        case WRITE_10:
                scsi_10_lba_len(scsicmd, &block, &n_block);
                if (unlikely(scsicmd[1] & (1 << 3)))
-                       tf->flags |= ATA_TFLAG_FUA;
+                       tf_flags |= ATA_TFLAG_FUA;
                break;
        case READ_6:
        case WRITE_6:
@@ -1316,7 +1296,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
        case WRITE_16:
                scsi_16_lba_len(scsicmd, &block, &n_block);
                if (unlikely(scsicmd[1] & (1 << 3)))
-                       tf->flags |= ATA_TFLAG_FUA;
+                       tf_flags |= ATA_TFLAG_FUA;
                break;
        default:
                DPRINTK("no-byte command\n");
@@ -1334,106 +1314,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
                 */
                goto nothing_to_do;
 
-       if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
-                          ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
-               /* yay, NCQ */
-               if (!lba_48_ok(block, n_block))
-                       goto out_of_range;
-
-               tf->protocol = ATA_PROT_NCQ;
-               tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
-
-               if (tf->flags & ATA_TFLAG_WRITE)
-                       tf->command = ATA_CMD_FPDMA_WRITE;
-               else
-                       tf->command = ATA_CMD_FPDMA_READ;
-
-               qc->nsect = n_block;
-
-               tf->nsect = qc->tag << 3;
-               tf->hob_feature = (n_block >> 8) & 0xff;
-               tf->feature = n_block & 0xff;
-
-               tf->hob_lbah = (block >> 40) & 0xff;
-               tf->hob_lbam = (block >> 32) & 0xff;
-               tf->hob_lbal = (block >> 24) & 0xff;
-               tf->lbah = (block >> 16) & 0xff;
-               tf->lbam = (block >> 8) & 0xff;
-               tf->lbal = block & 0xff;
-
-               tf->device = 1 << 6;
-               if (tf->flags & ATA_TFLAG_FUA)
-                       tf->device |= 1 << 7;
-       } else if (dev->flags & ATA_DFLAG_LBA) {
-               tf->flags |= ATA_TFLAG_LBA;
-
-               if (lba_28_ok(block, n_block)) {
-                       /* use LBA28 */
-                       tf->device |= (block >> 24) & 0xf;
-               } else if (lba_48_ok(block, n_block)) {
-                       if (!(dev->flags & ATA_DFLAG_LBA48))
-                               goto out_of_range;
-
-                       /* use LBA48 */
-                       tf->flags |= ATA_TFLAG_LBA48;
-
-                       tf->hob_nsect = (n_block >> 8) & 0xff;
-
-                       tf->hob_lbah = (block >> 40) & 0xff;
-                       tf->hob_lbam = (block >> 32) & 0xff;
-                       tf->hob_lbal = (block >> 24) & 0xff;
-               } else
-                       /* request too large even for LBA48 */
-                       goto out_of_range;
-
-               if (unlikely(ata_rwcmd_protocol(qc) < 0))
-                       goto invalid_fld;
-
-               qc->nsect = n_block;
-               tf->nsect = n_block & 0xff;
-
-               tf->lbah = (block >> 16) & 0xff;
-               tf->lbam = (block >> 8) & 0xff;
-               tf->lbal = block & 0xff;
-
-               tf->device |= ATA_LBA;
-       } else {
-               /* CHS */
-               u32 sect, head, cyl, track;
-
-               /* The request -may- be too large for CHS addressing. */
-               if (!lba_28_ok(block, n_block))
-                       goto out_of_range;
-
-               if (unlikely(ata_rwcmd_protocol(qc) < 0))
-                       goto invalid_fld;
-
-               /* Convert LBA to CHS */
-               track = (u32)block / dev->sectors;
-               cyl   = track / dev->heads;
-               head  = track % dev->heads;
-               sect  = (u32)block % dev->sectors + 1;
-
-               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
-                       (u32)block, track, cyl, head, sect);
-
-               /* Check whether the converted CHS can fit.
-                  Cylinder: 0-65535
-                  Head: 0-15
-                  Sector: 1-255*/
-               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
-                       goto out_of_range;
-
-               qc->nsect = n_block;
-               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
-               tf->lbal = sect;
-               tf->lbam = cyl;
-               tf->lbah = cyl >> 8;
-               tf->device |= head;
-       }
+       qc->flags |= ATA_QCFLAG_IO;
+       qc->nsect = n_block;
 
-       return 0;
+       rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
+                            qc->tag);
+       if (likely(rc == 0))
+               return 0;
 
+       if (rc == -ERANGE)
+               goto out_of_range;
+       /* treat all other errors as -EINVAL, fall through */
 invalid_fld:
        ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
        /* "Invalid field in cbd" */
@@ -1477,7 +1368,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
         */
        if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
            ((cdb[2] & 0x20) || need_sense)) {
-               ata_gen_ata_desc_sense(qc);
+               ata_gen_passthru_sense(qc);
        } else {
                if (!need_sense) {
                        cmd->result = SAM_STAT_GOOD;
@@ -1488,7 +1379,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
                         * good for smaller LBA (and maybe CHS?)
                         * devices.
                         */
-                       ata_gen_fixed_sense(qc);
+                       ata_gen_ata_sense(qc);
                }
        }
 
@@ -1714,6 +1605,22 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
        args->done(cmd);
 }
 
+/**
+ *     ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
+ *     @idx: byte index into SCSI response buffer
+ *     @val: value to set
+ *
+ *     To be used by SCSI command simulator functions.  This macros
+ *     expects two local variables, u8 *rbuf and unsigned int buflen,
+ *     are in scope.
+ *
+ *     LOCKING:
+ *     None.
+ */
+#define ATA_SCSI_RBUF_SET(idx, val) do { \
+               if ((idx) < buflen) rbuf[(idx)] = (u8)