Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-x86
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 12 Oct 2007 22:39:39 +0000 (15:39 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 12 Oct 2007 22:39:39 +0000 (15:39 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-x86: (40 commits)
  x86: HPET add another ICH7 PCI id
  x86: HPET force enable ICH5 suspend/resume fix
  x86: HPET force enable for ICH5
  x86: HPET try to activate force detected hpet
  x86: HPET force enable o ICH7 and later
  x86: HPET restructure hpet code for hpet force enable
  clock events: allow replacement of broadcast timer
  i386/x8664: cleanup the shared hpet code
  i386: Remove the useless #ifdef in i8253.h
  ACPI: remove the now unused ifdef code
  jiffies: remove unused macros
  x86_64: cleanup apic.c after clock events switch
  x86_64: remove now unused code
  x86: unify timex.h variants
  x86: kill 8253pit.h
  x86: disable apic timer for AMD C1E enabled CPUs
  x86: Fix irq0 / local apic timer accounting
  x86_64: convert to clock events
  x86_64: Add (not yet used) clock event functions
  x86_64: prepare idle loop for dynamic ticks
  ...

149 files changed:
Documentation/DocBook/Makefile
Documentation/DocBook/s390-drivers.tmpl [new file with mode: 0644]
Documentation/filesystems/ntfs.txt
Documentation/s390/00-INDEX [new file with mode: 0644]
Documentation/s390/CommonIO
Documentation/s390/cds.txt
arch/s390/appldata/appldata_base.c
arch/s390/kernel/audit.c
arch/s390/kernel/audit.h [new file with mode: 0644]
arch/s390/kernel/compat_audit.c
arch/s390/kernel/cpcmd.c
arch/s390/kernel/dis.c
arch/s390/kernel/ipl.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/mm/fault.c
block/Kconfig
block/Makefile
drivers/block/Kconfig
drivers/isdn/hisax/avm_pci.c
drivers/isdn/hisax/bkm_a8.c
drivers/isdn/hisax/diva.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/sedlbauer.c
drivers/isdn/hisax/telespci.c
drivers/isdn/hisax/w6692.c
drivers/isdn/hysdn/hysdn_init.c
drivers/mmc/core/host.c
drivers/net/bnx2.c
drivers/net/tg3.c
drivers/s390/block/dasd_int.h
drivers/s390/block/xpram.c
drivers/s390/char/con3215.c
drivers/s390/char/con3270.c
drivers/s390/char/sclp.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tty3270.c
drivers/s390/char/tty3270.h [new file with mode: 0644]
drivers/s390/char/vmwatchdog.c
drivers/s390/char/zcore.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/chp.c
drivers/s390/cio/cio.c
drivers/s390/cio/cmf.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/zcrypt_mono.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/crypto/zcrypt_pcixcc.h
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_erp.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lock.h
fs/dlm/lockspace.c
fs/dlm/lowcomms.c
fs/dlm/member.c
fs/dlm/midcomms.c
fs/dlm/rcom.c
fs/dlm/rcom.h
fs/dlm/recoverd.c
fs/dlm/requestqueue.c
fs/dlm/requestqueue.h
fs/gfs2/bmap.c
fs/gfs2/daemon.c
fs/gfs2/daemon.h
fs/gfs2/dir.c
fs/gfs2/eaops.c
fs/gfs2/eaops.h
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/locking/dlm/lock_dlm.h
fs/gfs2/locking/dlm/plock.c
fs/gfs2/locking/dlm/thread.c
fs/gfs2/locking/nolock/main.c
fs/gfs2/log.c
fs/gfs2/log.h
fs/gfs2/lops.c
fs/gfs2/main.c
fs/gfs2/meta_io.c
fs/gfs2/meta_io.h
fs/gfs2/mount.c
fs/gfs2/ops_address.c
fs/gfs2/ops_export.c
fs/gfs2/ops_file.c
fs/gfs2/ops_fstype.c
fs/gfs2/ops_inode.c
fs/gfs2/ops_super.c
fs/gfs2/quota.c
fs/gfs2/recovery.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/sys.c
fs/gfs2/trans.c
fs/gfs2/trans.h
fs/ntfs/ChangeLog
fs/ntfs/Makefile
fs/ntfs/aops.c
fs/ntfs/attrib.c
fs/ntfs/file.c
fs/ntfs/inode.c
fs/ntfs/logfile.c
fs/ntfs/runlist.c
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/dir.c
fs/ocfs2/dir.h
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h
fs/ocfs2/export.c
fs/ocfs2/extent_map.c
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/namei.c
fs/ocfs2/namei.h
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/super.c
fs/ocfs2/sysfile.c
include/asm-s390/cache.h
include/asm-s390/ccwdev.h
include/asm-s390/ccwgroup.h
include/asm-s390/cio.h
include/asm-s390/cmb.h
include/asm-s390/page.h
include/asm-s390/pgtable.h
include/asm-s390/s390_ext.h
include/asm-s390/system.h
include/asm-s390/zcrypt.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/gfs2_ondisk.h
include/linux/kernel.h

index 08687e45e19dcf7f68f84a70901a1abc4a95d829..1a7f53068ec2a01f0881be61c22d707b40381a67 100644 (file)
@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
            procfs-guide.xml writing_usb_driver.xml \
            kernel-api.xml filesystems.xml lsm.xml usb.xml \
            gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
-           genericirq.xml
+           genericirq.xml s390-drivers.xml
 
 ###
 # The build process is as follows (targets):
diff --git a/Documentation/DocBook/s390-drivers.tmpl b/Documentation/DocBook/s390-drivers.tmpl
new file mode 100644 (file)
index 0000000..254e769
--- /dev/null
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="s390drivers">
+ <bookinfo>
+  <title>Writing s390 channel device drivers</title>
+
+  <authorgroup>
+   <author>
+    <firstname>Cornelia</firstname>
+    <surname>Huck</surname>
+    <affiliation>
+     <address>
+       <email>cornelia.huck@de.ibm.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2007</year>
+   <holder>IBM Corp.</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+   <title>Introduction</title>
+  <para>
+    This document describes the interfaces available for device drivers that
+    drive s390 based channel attached devices. This includes interfaces for
+    interaction with the hardware and interfaces for interacting with the
+    common driver core. Those interfaces are provided by the s390 common I/O
+    layer.
+  </para>
+  <para>
+    The document assumes a familarity with the technical terms associated
+    with the s390 channel I/O architecture. For a description of this
+    architecture, please refer to the "z/Architecture: Principles of
+    Operation", IBM publication no. SA22-7832.
+  </para>
+  <para>
+    While most I/O devices on a s390 system are typically driven through the
+    channel I/O mechanism described here, there are various other methods
+    (like the diag interface). These are out of the scope of this document.
+  </para>
+  <para>
+    Some additional information can also be found in the kernel source
+    under Documentation/s390/driver-model.txt.
+  </para>
+  </chapter>
+  <chapter id="ccw">
+   <title>The ccw bus</title>
+  <para>
+       The ccw bus typically contains the majority of devices available to
+       a s390 system. Named after the channel command word (ccw), the basic
+       command structure used to address its devices, the ccw bus contains
+       so-called channel attached devices. They are addressed via subchannels,
+       visible on the css bus. A device driver, however, will never interact
+       with the subchannel directly, but only via the device on the ccw bus,
+       the ccw device.
+  </para>
+    <sect1 id="channelIO">
+     <title>I/O functions for channel-attached devices</title>
+    <para>
+      Some hardware structures have been translated into C structures for use
+      by the common I/O layer and device drivers. For more information on
+      the hardware structures represented here, please consult the Principles
+      of Operation.
+    </para>
+!Iinclude/asm-s390/cio.h
+    </sect1>
+    <sect1 id="ccwdev">
+     <title>ccw devices</title>
+    <para>
+      Devices that want to initiate channel I/O need to attach to the ccw bus.
+      Interaction with the driver core is done via the common I/O layer, which
+      provides the abstractions of ccw devices and ccw device drivers.
+    </para>
+    <para>
+      The functions that initiate or terminate channel I/O all act upon a
+      ccw device structure. Device drivers must not bypass those functions
+      or strange side effects may happen.
+    </para>
+!Iinclude/asm-s390/ccwdev.h
+!Edrivers/s390/cio/device.c
+!Edrivers/s390/cio/device_ops.c
+    </sect1>
+    <sect1 id="cmf">
+     <title>The channel-measurement facility</title>
+  <para>
+       The channel-measurement facility provides a means to collect
+       measurement data which is made available by the channel subsystem
+       for each channel attached device.
+  </para>
+!Iinclude/asm-s390/cmb.h
+!Edrivers/s390/cio/cmf.c
+    </sect1>
+  </chapter>
+
+  <chapter id="ccwgroup">
+   <title>The ccwgroup bus</title>
+  <para>
+       The ccwgroup bus only contains artificial devices, created by the user.
+       Many networking devices (e.g. qeth) are in fact composed of several
+       ccw devices (like read, write and data channel for qeth). The
+       ccwgroup bus provides a mechanism to create a meta-device which
+       contains those ccw devices as slave devices and can be associated
+       with the netdevice.
+  </para>
+   <sect1 id="ccwgroupdevices">
+    <title>ccw group devices</title>
+!Iinclude/asm-s390/ccwgroup.h
+!Edrivers/s390/cio/ccwgroup.c
+   </sect1>
+  </chapter>
+
+</book>
index 8ee10ec882936d1725e948554da052b3c7d09426..e79ee2db183a0a19f09bccb810a29794ab72031e 100644 (file)
@@ -407,7 +407,7 @@ raiddev /dev/md0
        device          /dev/hda5
        raid-disk       0
        device          /dev/hdb1
-       raid-disl       1
+       raid-disk       1
 
 For linear raid, just change the raid-level above to "raid-level linear", for
 mirrors, change it to "raid-level 1", and for stripe sets with parity, change
@@ -457,6 +457,8 @@ ChangeLog
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.1.29:
+       - Fix a deadlock when mounting read-write.
 2.1.28:
        - Fix a deadlock.
 2.1.27:
diff --git a/Documentation/s390/00-INDEX b/Documentation/s390/00-INDEX
new file mode 100644 (file)
index 0000000..3a2b963
--- /dev/null
@@ -0,0 +1,26 @@
+00-INDEX
+       - this file.
+3270.ChangeLog
+       - ChangeLog for the UTS Global 3270-support patch (outdated).
+3270.txt
+       - how to use the IBM 3270 display system support.
+cds.txt
+       - s390 common device support (common I/O layer).
+CommonIO
+       - common I/O layer command line parameters, procfs and debugfs  entries
+config3270.sh
+       - example configuration for 3270 devices.
+DASD
+       - information on the DASD disk device driver.
+Debugging390.txt
+       - hints for debugging on s390 systems.
+driver-model.txt
+       - information on s390 devices and the driver model.
+monreader.txt
+       - information on accessing the z/VM monitor stream from Linux.
+s390dbf.txt
+       - information on using the s390 debug feature.
+TAPE
+       - information on the driver for channel-attached tapes.
+zfcpdump
+       - information on the s390 SCSI dump tool.
index 22f82f21bc605395b4fa34d7a85cc8ad63bd2e07..86320aa3fb0b4728c2e6f581c2e346f3d018088d 100644 (file)
@@ -1,5 +1,5 @@
-S/390 common I/O-Layer - command line parameters and /proc entries
-==================================================================
+S/390 common I/O-Layer - command line parameters, procfs and debugfs entries
+============================================================================
 
 Command line parameters
 -----------------------
@@ -7,9 +7,9 @@ Command line parameters
 * cio_msg = yes | no
   
   Determines whether information on found devices and sensed device 
-  characteristics should be shown during startup, i. e. messages of the types 
-  "Detected device 0.0.4711 on subchannel 0.0.0042" and "SenseID: Device
-  0.0.4711 reports: ...".
+  characteristics should be shown during startup or when new devices are
+  found, i. e. messages of the types "Detected device 0.0.4711 on subchannel
+  0.0.0042" and "SenseID: Device 0.0.4711 reports: ...".
 
   Default is off.
 
@@ -26,8 +26,10 @@ Command line parameters
   An ignored device can be un-ignored later; see the "/proc entries"-section for
   details.
 
-  The devices must be given either as bus ids (0.0.abcd) or as hexadecimal
-  device numbers (0xabcd or abcd, for 2.4 backward compatibility).
+  The devices must be given either as bus ids (0.x.abcd) or as hexadecimal
+  device numbers (0xabcd or abcd, for 2.4 backward compatibility). If you
+  give a device number 0xabcd, it will be interpreted as 0.0.abcd.
+
   You can use the 'all' keyword to ignore all devices.
   The '!' operator will cause the I/O-layer to _not_ ignore a device.
   The command line is parsed from left to right.
@@ -81,31 +83,36 @@ Command line parameters
   will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored
   devices.
 
-  The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward
-  compatibility, by the device number in hexadecimal (0xabcd or abcd).
+  The devices can be specified either by bus id (0.x.abcd) or, for 2.4 backward
+  compatibility, by the device number in hexadecimal (0xabcd or abcd). Device
+  numbers given as 0xabcd will be interpreted as 0.0.abcd.
+
+* For some of the information present in the /proc filesystem in 2.4 (namely,
+  /proc/subchannels and /proc/chpids), see driver-model.txt.
+  Information formerly in /proc/irq_count is now in /proc/interrupts.
+
 
+debugfs entries
+---------------
 
-* /proc/s390dbf/cio_*/ (S/390 debug feature)
+* /sys/kernel/debug/s390dbf/cio_*/ (S/390 debug feature)
 
   Some views generated by the debug feature to hold various debug outputs.
 
-  - /proc/s390dbf/cio_crw/sprintf
+  - /sys/kernel/debug/s390dbf/cio_crw/sprintf
     Messages from the processing of pending channel report words (machine check
-    handling), which will also show when CONFIG_DEBUG_CRW is defined.
+    handling).
 
-  - /proc/s390dbf/cio_msg/sprintf
-    Various debug messages from the common I/O-layer; generally, messages which 
-    will also show when CONFIG_DEBUG_IO is defined.
+  - /sys/kernel/debug/s390dbf/cio_msg/sprintf
+    Various debug messages from the common I/O-layer, including messages
+    printed when cio_msg=yes.
 
-  - /proc/s390dbf/cio_trace/hex_ascii
+  - /sys/kernel/debug/s390dbf/cio_trace/hex_ascii
     Logs the calling of functions in the common I/O-layer and, if applicable, 
     which subchannel they were called for, as well as dumps of some data
     structures (like irb in an error case).
 
   The level of logging can be changed to be more or less verbose by piping to 
-  /proc/s390dbf/cio_*/level a number between 0 and 6; see the documentation on
-  the S/390 debug feature (Documentation/s390/s390dbf.txt) for details.
-
-* For some of the information present in the /proc filesystem in 2.4 (namely,
-  /proc/subchannels and /proc/chpids), see driver-model.txt.
-  Information formerly in /proc/irq_count is now in /proc/interrupts.
+  /sys/kernel/debug/s390dbf/cio_*/level a number between 0 and 6; see the
+  documentation on the S/390 debug feature (Documentation/s390/s390dbf.txt)
+  for details.
index 58919d6a593ae0b0f91badb0e1e66d424f735738..3081927cc2d64048c1bc02ddf0e33f737082f993 100644 (file)
@@ -286,10 +286,10 @@ first:
             timeout value
 -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 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.
+If the concurrent sense flag in the extended status word (esw) in the irb is
+set, the field erw.scnt in the esw describes the number of device specific
+sense bytes available in the extended control word irb->scsw.ecw[]. No device
+sensing by the device driver itself is required.
 
 The device interrupt handler can use the following definitions to investigate
 the primary unit check source coded in sense byte 0 :
index 62391fb1f61f0ed158c304bd0c939e77595d5191..ac61cf43a7d950b36cf1316165ea499c63c6283d 100644 (file)
@@ -547,8 +547,7 @@ static void __cpuinit appldata_online_cpu(int cpu)
        spin_unlock(&appldata_timer_lock);
 }
 
-static void
-appldata_offline_cpu(int cpu)
+static void __cpuinit appldata_offline_cpu(int cpu)
 {
        del_virt_timer(&per_cpu(appldata_timer, cpu));
        if (atomic_dec_and_test(&appldata_expire_count)) {
@@ -560,9 +559,9 @@ appldata_offline_cpu(int cpu)
        spin_unlock(&appldata_timer_lock);
 }
 
-static int __cpuinit
-appldata_cpu_notify(struct notifier_block *self,
-                   unsigned long action, void *hcpu)
+static int __cpuinit appldata_cpu_notify(struct notifier_block *self,
+                                        unsigned long action,
+                                        void *hcpu)
 {
        switch (action) {
        case CPU_ONLINE:
@@ -608,63 +607,15 @@ static int __init appldata_init(void)
        register_hotcpu_notifier(&appldata_nb);
 
        appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
-#ifdef MODULE
-       appldata_dir_table[0].de->owner = THIS_MODULE;
-       appldata_table[0].de->owner = THIS_MODULE;
-       appldata_table[1].de->owner = THIS_MODULE;
-#endif
 
        P_DEBUG("Base interface initialized.\n");
        return 0;
 }
 
-/*
- * appldata_exit()
- *
- * stop timer, unregister /proc entries
- */
-static void __exit appldata_exit(void)
-{
-       struct list_head *lh;
-       struct appldata_ops *ops;
-       int rc, i;
+__initcall(appldata_init);
 
-       P_DEBUG("Unloading module ...\n");
-       /*
-        * ops list should be empty, but just in case something went wrong...
-        */
-       spin_lock(&appldata_ops_lock);
-       list_for_each(lh, &appldata_ops_list) {
-               ops = list_entry(lh, struct appldata_ops, list);
-               rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
-                               (unsigned long) ops->data, ops->size,
-                               ops->mod_lvl);
-               if (rc != 0) {
-                       P_ERROR("STOP DIAG 0xDC for %s failed, "
-                               "return code: %d\n", ops->name, rc);
-               }
-       }
-       spin_unlock(&appldata_ops_lock);
-
-       for_each_online_cpu(i)
-               appldata_offline_cpu(i);
-
-       appldata_timer_active = 0;
-
-       unregister_sysctl_table(appldata_sysctl_header);
-
-       destroy_workqueue(appldata_wq);
-       P_DEBUG("... module unloaded!\n");
-}
 /**************************** init / exit <END> ******************************/
 
-
-module_init(appldata_init);
-module_exit(appldata_exit);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Gerald Schaefer");
-MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure");
-
 EXPORT_SYMBOL_GPL(appldata_register_ops);
 EXPORT_SYMBOL_GPL(appldata_unregister_ops);
 EXPORT_SYMBOL_GPL(appldata_diag);
index d1c76fe10f29e0d8630979abc973a54f4e230472..f4932c22ebe4f86d6bf13c02c099e81f58a4569d 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/types.h>
 #include <linux/audit.h>
 #include <asm/unistd.h>
+#include "audit.h"
 
 static unsigned dir_class[] = {
 #include <asm-generic/audit_dir_write.h>
@@ -40,7 +41,6 @@ int audit_classify_arch(int arch)
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_COMPAT
-       extern int s390_classify_syscall(unsigned);
        if (abi == AUDIT_ARCH_S390)
                return s390_classify_syscall(syscall);
 #endif
@@ -61,11 +61,6 @@ int audit_classify_syscall(int abi, unsigned syscall)
 static int __init audit_classes_init(void)
 {
 #ifdef CONFIG_COMPAT
-       extern __u32 s390_dir_class[];
-       extern __u32 s390_write_class[];
-       extern __u32 s390_read_class[];
-       extern __u32 s390_chattr_class[];
-       extern __u32 s390_signal_class[];
        audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
        audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
        audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
diff --git a/arch/s390/kernel/audit.h b/arch/s390/kernel/audit.h
new file mode 100644 (file)
index 0000000..12b56f4
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ARCH_S390_KERNEL_AUDIT_H
+#define __ARCH_S390_KERNEL_AUDIT_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_COMPAT
+extern int s390_classify_syscall(unsigned);
+extern __u32 s390_dir_class[];
+extern __u32 s390_write_class[];
+extern __u32 s390_read_class[];
+extern __u32 s390_chattr_class[];
+extern __u32 s390_signal_class[];
+#endif /* CONFIG_COMPAT */
+
+#endif /* __ARCH_S390_KERNEL_AUDIT_H */
index 0569f5126e499ea4bdd477301eeb8e5cc35f42df..d6487bf879e5bc098d67339764ee1d03fa43d1ef 100644 (file)
@@ -1,5 +1,6 @@
 #undef __s390x__
 #include <asm/unistd.h>
+#include "audit.h"
 
 unsigned s390_dir_class[] = {
 #include <asm-generic/audit_dir_write.h>
index 6c89f30c8e31ea39f181fe610dffada543254129..d8c1131e081568927e7f4460aa4febd912c869bf 100644 (file)
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/cpcmd.c
  *
  *  S390 version
- *    Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999,2007
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Christian Borntraeger (cborntra@de.ibm.com),
  */
 static DEFINE_SPINLOCK(cpcmd_lock);
 static char cpcmd_buf[241];
 
+static int diag8_noresponse(int cmdlen)
+{
+       register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+       register unsigned long reg3 asm ("3") = cmdlen;
+
+       asm volatile(
+#ifndef CONFIG_64BIT
+               "       diag    %1,%0,0x8\n"
+#else /* CONFIG_64BIT */
+               "       sam31\n"
+               "       diag    %1,%0,0x8\n"
+               "       sam64\n"
+#endif /* CONFIG_64BIT */
+               : "+d" (reg3) : "d" (reg2) : "cc");
+       return reg3;
+}
+
+static int diag8_response(int cmdlen, char *response, int *rlen)
+{
+       register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+       register unsigned long reg3 asm ("3") = (addr_t) response;
+       register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
+       register unsigned long reg5 asm ("5") = *rlen;
+
+       asm volatile(
+#ifndef CONFIG_64BIT
+               "       diag    %2,%0,0x8\n"
+               "       brc     8,1f\n"
+               "       ar      %1,%4\n"
+#else /* CONFIG_64BIT */
+               "       sam31\n"
+               "       diag    %2,%0,0x8\n"
+               "       sam64\n"
+               "       brc     8,1f\n"
+               "       agr     %1,%4\n"
+#endif /* CONFIG_64BIT */
+               "1:\n"
+               : "+d" (reg4), "+d" (reg5)
+               : "d" (reg2), "d" (reg3), "d" (*rlen) : "cc");
+       *rlen = reg5;
+       return reg4;
+}
+
 /*
  * __cpcmd has some restrictions over cpcmd
  *  - the response buffer must reside below 2GB (if any)
@@ -28,59 +71,27 @@ static char cpcmd_buf[241];
  */
 int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
-       unsigned cmdlen;
-       int return_code, return_len;
+       int cmdlen;
+       int rc;
+       int response_len;
 
        cmdlen = strlen(cmd);
        BUG_ON(cmdlen > 240);
        memcpy(cpcmd_buf, cmd, cmdlen);
        ASCEBC(cpcmd_buf, cmdlen);
 
-       if (response != NULL && rlen > 0) {
-               register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
-               register unsigned long reg3 asm ("3") = (addr_t) response;
-               register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
-               register unsigned long reg5 asm ("5") = rlen;
-
+       if (response) {
                memset(response, 0, rlen);
-               asm volatile(
-#ifndef CONFIG_64BIT
-                       "       diag    %2,%0,0x8\n"
-                       "       brc     8,1f\n"
-                       "       ar      %1,%4\n"
-#else /* CONFIG_64BIT */
-                       "       sam31\n"
-                       "       diag    %2,%0,0x8\n"
-                       "       sam64\n"
-                       "       brc     8,1f\n"
-                       "       agr     %1,%4\n"
-#endif /* CONFIG_64BIT */
-                       "1:\n"
-                       : "+d" (reg4), "+d" (reg5)
-                       : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
-               return_code = (int) reg4;
-               return_len = (int) reg5;
-                EBCASC(response, rlen);
+               response_len = rlen;
+               rc = diag8_response(cmdlen, response, &rlen);
+               EBCASC(response, response_len);
         } else {
-               register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
-               register unsigned long reg3 asm ("3") = cmdlen;
-               return_len = 0;
-               asm volatile(
-#ifndef CONFIG_64BIT
-                       "       diag    %1,%0,0x8\n"
-#else /* CONFIG_64BIT */
-                       "       sam31\n"
-                       "       diag    %1,%0,0x8\n"
-                       "       sam64\n"
-#endif /* CONFIG_64BIT */
-                       : "+d" (reg3) : "d" (reg2) : "cc");
-               return_code = (int) reg3;
+               rc = diag8_noresponse(cmdlen);
         }
-       if (response_code != NULL)
-               *response_code = return_code;
-       return return_len;
+       if (response_code)
+               *response_code = rc;
+       return rlen;
 }
-
 EXPORT_SYMBOL(__cpcmd);
 
 int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
@@ -109,5 +120,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
        }
        return len;
 }
-
 EXPORT_SYMBOL(cpcmd);
index 50d2235df732456482201077904cddad27e99970..c14a336f63002c2d166ab86731a4c876a6a51d62 100644 (file)
@@ -1162,6 +1162,7 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
        unsigned int value;
        char separator;
        char *ptr;
+       int i;
 
        ptr = buffer;
        insn = find_insn(code);
@@ -1169,7 +1170,8 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
                ptr += sprintf(ptr, "%.5s\t", insn->name);
                /* Extract the operands. */
                separator = 0;
-               for (ops = formats[insn->format] + 1; *ops != 0; ops++) {
+               for (ops = formats[insn->format] + 1, i = 0;
+                    *ops != 0 && i < 6; ops++, i++) {
                        operand = operands + *ops;
                        value = extract_operand(code, operand);
                        if ((operand->flags & OPERAND_INDEX)  && value == 0)
@@ -1241,7 +1243,6 @@ void show_code(struct pt_regs *regs)
        }
        /* Find a starting point for the disassembly. */
        while (start < 32) {
-               hops = 0;
                for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
                        if (!find_insn(code + start + i))
                                break;
index 8b8f136d9cc76b582a96699bdb76a9c3a491760e..66b51901c87d29be81d8c25cc0b8546ae1e970b1 100644 (file)
@@ -735,10 +735,10 @@ void do_reipl(void)
        case REIPL_METHOD_CCW_VM:
                reipl_get_ascii_loadparm(loadparm);
                if (strlen(loadparm) == 0)
-                       sprintf(buf, "IPL %X",
+                       sprintf(buf, "IPL %X CLEAR",
                                reipl_block_ccw->ipl_info.ccw.devno);
                else
-                       sprintf(buf, "IPL %X LOADPARM '%s'",
+                       sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
                                reipl_block_ccw->ipl_info.ccw.devno, loadparm);
                __cpcmd(buf, NULL, 0, NULL);
                break;
index b4622a3889b0575f86dea86ccf6ffa96bd25ec2d..849120e3e28a0b6e7c2dddaa16c82e09dc086bc9 100644 (file)
@@ -2,6 +2,7 @@
  * Written by Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
+#include <asm/page.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #ifndef CONFIG_64BIT
@@ -18,121 +19,142 @@ jiffies = jiffies_64;
 
 SECTIONS
 {
-  . = 0x00000000;
-  _text = .;                   /* Text and read-only data */
-  .text : {
-       *(.text.head)
+       . = 0x00000000;
+       .text : {
+       _text = .;              /* Text and read-only data */
+               *(.text.head)
        TEXT_TEXT
-       SCHED_TEXT
-       LOCK_TEXT
-       KPROBES_TEXT
-       *(.fixup)
-       *(.gnu.warning)
+               SCHED_TEXT
+               LOCK_TEXT
+               KPROBES_TEXT
+               *(.fixup)
+               *(.gnu.warning)
        } = 0x0700
 
-  _etext = .;                  /* End of text section */
+       _etext = .;             /* End of text section */
 
-  RODATA
+       RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
-  . = ALIGN(1048576);          /* VM shared segments are 1MB aligned */
+       . = ALIGN(0x100000);    /* VM shared segments are 1MB aligned */
 #endif
 
-  . = ALIGN(4096);
-  _eshared = .;                        /* End of shareable data */
-
-  . = ALIGN(16);               /* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  NOTES
-
-  BUG_TABLE
-
-  .data : {                    /* Data */
-       DATA_DATA
-       CONSTRUCTORS
-       }
-
-  . = ALIGN(4096);
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(256);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  . = ALIGN(256);
-  .data.read_mostly : { *(.data.read_mostly) }
-  _edata = .;                  /* End of data section */
-
-  . = ALIGN(8192);             /* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  /* will be freed after init */
-  . = ALIGN(4096);             /* Init code and data */
-  __init_begin = .;
-  .init.text : { 
-       _sinittext = .;
-       *(.init.text)
-       _einittext = .;
-  }
-  /*
-   * .exit.text is discarded at runtime, not link time,
-   * to deal with references from __bug_table
-   */
-  .exit.text :  { *(.exit.text) }
-
-  .init.data : { *(.init.data) }
-  . = ALIGN(256);
-  __setup_start = .;
-  .init.setup : { *(.init.setup) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : {
-       INITCALLS
-  }
-  __initcall_end = .;
-  __con_initcall_start = .;
-  .con_initcall.init : { *(.con_initcall.init) }
-  __con_initcall_end = .;
-  SECURITY_INIT
+       . = ALIGN(PAGE_SIZE);
+       _eshared = .;           /* End of shareable data */
+
+       . = ALIGN(16);          /* Exception table */
+       __ex_table : {
+               __start___ex_table = .;
+               *(__ex_table)
+               __stop___ex_table = .;
+       }
+
+       NOTES
+       BUG_TABLE
+
+       .data : {               /* Data */
+               DATA_DATA
+               CONSTRUCTORS
+       }
+
+       . = ALIGN(PAGE_SIZE);
+       .data_nosave : {
+       __nosave_begin = .;
+               *(.data.nosave)
+       }
+       . = ALIGN(PAGE_SIZE);
+       __nosave_end = .;
+
+       . = ALIGN(PAGE_SIZE);
+       .data.page_aligned : {
+               *(.data.idt)
+       }
+
+       . = ALIGN(0x100);
+       .data.cacheline_aligned : {
+               *(.data.cacheline_aligned)
+       }
+
+       . = ALIGN(0x100);
+       .data.read_mostly : {
+               *(.data.read_mostly)
+       }
+       _edata = .;             /* End of data section */
+
+       . = ALIGN(2 * PAGE_SIZE);       /* init_task */
+       .data.init_task : {
+               *(.data.init_task)
+       }
+
+       /* will be freed after init */
+       . = ALIGN(PAGE_SIZE);   /* Init code and data */
+       __init_begin = .;
+       .init.text : {
+               _sinittext = .;
+               *(.init.text)
+               _einittext = .;
+       }
+       /*
+        * .exit.text is discarded at runtime, not link time,
+        * to deal with references from __bug_table
+       */
+       .exit.text : {
+               *(.exit.text)
+       }
+
+       .init.data : {
+               *(.init.data)
+       }
+       . = ALIGN(0x100);
+       .init.setup : {
+               __setup_start = .;
+               *(.init.setup)
+               __setup_end = .;
+       }
+       .initcall.init : {
+               __initcall_start = .;
+               INITCALLS
+               __initcall_end = .;
+       }
+
+       .con_initcall.init : {
+               __con_initcall_start = .;
+               *(.con_initcall.init)
+               __con_initcall_end = .;
+       }
+       SECURITY_INIT
 
 #ifdef CONFIG_BLK_DEV_INITRD
-  . = ALIGN(256);
-  __initramfs_start = .;
-  .init.ramfs : { *(.init.initramfs) }
-  . = ALIGN(2);
-  __initramfs_end = .;
+       . = ALIGN(0x100);
+       .init.ramfs : {
+               __initramfs_start = .;
+               *(.init.ramfs)
+               . = ALIGN(2);
+               __initramfs_end = .;
+       }
 #endif
-  PERCPU(4096)
-  . = ALIGN(4096);
-  __init_end = .;
-  /* freed after init ends here */
-
-  __bss_start = .;             /* BSS */
-  .bss : { *(.bss) }
-  . = ALIGN(2);
-  __bss_stop = .;
-
-  _end = . ;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-       *(.exit.data) *(.exitcall.exit)
-       }
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
+
+       PERCPU(PAGE_SIZE)
+       . = ALIGN(PAGE_SIZE);
+       __init_end = .;         /* freed after init ends here */
+
+       /* BSS */
+       .bss : {
+               __bss_start = .;
+               *(.bss)
+               . = ALIGN(2);
+               __bss_stop = .;
+       }
+
+       _end = . ;
+
+       /* Sections to be discarded */
+       /DISCARD/ : {
+               *(.exit.data)
+               *(.exitcall.exit)
+       }
+
+       /* Debugging sections.  */
+       STABS_DEBUG
+       DWARF_DEBUG
 }
index 54055194e9af320e3b9e675bdebaab77014419c2..4c1ac341ec80633c95194f3c83ab7f358b36189a 100644 (file)
@@ -468,7 +468,7 @@ typedef struct {
        __u64 refselmk;
        __u64 refcmpmk;
        __u64 reserved;
-} __attribute__ ((packed)) pfault_refbk_t;
+} __attribute__ ((packed, aligned(8))) pfault_refbk_t;
 
 int pfault_init(void)
 {
index 2484e0e9d89c9127c0678052b18bfa879b8a827d..e10895647f728bc2cca05c1f39a37a0f49659d5e 100644 (file)
@@ -62,6 +62,10 @@ config BLK_DEV_BSG
        protocols (e.g. Task Management Functions and SMP in Serial
        Attached SCSI).
 
+config BLOCK_COMPAT
+       bool
+       default y
+
 endif # BLOCK
 
 source block/Kconfig.iosched
index 3cfe7cebaa6ad3222eb3161367101b755dccd79d..826108190f00d3ed9afc1cba7869424584cd6dd4 100644 (file)
@@ -11,4 +11,4 @@ obj-$(CONFIG_IOSCHED_DEADLINE)        += deadline-iosched.o
 obj-$(CONFIG_IOSCHED_CFQ)      += cfq-iosched.o
 
 obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
-obj-$(CONFIG_COMPAT)           += compat_ioctl.o
+obj-$(CONFIG_BLOCK_COMPAT)     += compat_ioctl.o
index 4245b7f80a49de11d2709ffd66a23f7d371137a3..ca4d7f0d09b79af954b814ce11299b4e69e996b8 100644 (file)
@@ -361,8 +361,7 @@ config BLK_DEV_RAM_SIZE
        default "4096"
        help
          The default value is 4096 kilobytes. Only change this if you know
-         what are you doing. If you are using IBM S/390, then set this to
-         8192.
+         what are you doing.
 
 config BLK_DEV_RAM_BLOCKSIZE
        int "Default RAM disk block size (bytes)"
index b04a178e502102e96270963a1028e22c7c5cae83..f8b79783c8b375128a50bf119785e849e1b3e7f1 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/isapnp.h>
 #include <linux/interrupt.h>
 
-extern const char *CardType[];
 static const char *avm_pci_rev = "$Revision: 1.29.2.4 $";
 
 #define  AVM_FRITZ_PCI         1
@@ -726,100 +725,15 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-#ifdef CONFIG_PCI
-static struct pci_dev *dev_avm __devinitdata = NULL;
-#endif
-#ifdef __ISAPNP__
-static struct pnp_card *pnp_avm_c __devinitdata = NULL;
-#endif
-
-int __devinit
-setup_avm_pcipnp(struct IsdnCard *card)
+static int __devinit avm_setup_rest(struct IsdnCardState *cs)
 {
        u_int val, ver;
-       struct IsdnCardState *cs = card->cs;
-       char tmp[64];
 
-       strcpy(tmp, avm_pci_rev);
-       printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
-       if (cs->typ != ISDN_CTYPE_FRITZPCI)
-               return (0);
-       if (card->para[1]) {
-               /* old manual method */
-               cs->hw.avm.cfg_reg = card->para[1];
-               cs->irq = card->para[0];
-               cs->subtyp = AVM_FRITZ_PNP;
-               goto ready;
-       }
-#ifdef __ISAPNP__
-       if (isapnp_present()) {
-               struct pnp_dev *pnp_avm_d = NULL;
-               if ((pnp_avm_c = pnp_find_card(
-                       ISAPNP_VENDOR('A', 'V', 'M'),
-                       ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
-                       if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
-                               ISAPNP_VENDOR('A', 'V', 'M'),
-                               ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
-                               int err;
-
-                               pnp_disable_dev(pnp_avm_d);
-                               err = pnp_activate_dev(pnp_avm_d);
-                               if (err<0) {
-                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-                                               __FUNCTION__, err);
-                                       return(0);
-                               }
-                               cs->hw.avm.cfg_reg =
-                                       pnp_port_start(pnp_avm_d, 0);
-                               cs->irq = pnp_irq(pnp_avm_d, 0);
-                               if (!cs->irq) {
-                                       printk(KERN_ERR "FritzPnP:No IRQ\n");
-                                       return(0);
-                               }
-                               if (!cs->hw.avm.cfg_reg) {
-                                       printk(KERN_ERR "FritzPnP:No IO address\n");
-                                       return(0);
-                               }
-                               cs->subtyp = AVM_FRITZ_PNP;
-                               goto ready;
-                       }
-               }
-       } else {
-               printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
-       }
-#endif
-#ifdef CONFIG_PCI
-       if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
-               PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-               if (pci_enable_device(dev_avm))
-                       return(0);
-               cs->irq = dev_avm->irq;
-               if (!cs->irq) {
-                       printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-                       return(0);
-               }
-               cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-               if (!cs->hw.avm.cfg_reg) {
-                       printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-                       return(0);
-               }
-               cs->subtyp = AVM_FRITZ_PCI;
-       } else {
-               printk(KERN_WARNING "FritzPCI: No PCI card found\n");
-               return(0);
-       }
-       cs->irq_flags |= IRQF_SHARED;
-#else
-       printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
-       return (0);
-#endif /* CONFIG_PCI */
-ready:
        cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
        if (!request_region(cs->hw.avm.cfg_reg, 32,
                (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {
                printk(KERN_WARNING
-                      "HiSax: %s config port %x-%x already in use\n",
-                      CardType[card->typ],
+                      "HiSax: Fritz!PCI/PNP config port %x-%x already in use\n",
                       cs->hw.avm.cfg_reg,
                       cs->hw.avm.cfg_reg + 31);
                return (0);
@@ -860,3 +774,137 @@ ready:
        ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
        return (1);
 }
+
+#ifndef __ISAPNP__
+
+static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
+{
+       return(1);      /* no-op: success */
+}
+
+#else
+
+static struct pnp_card *pnp_avm_c __devinitdata = NULL;
+
+static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
+{
+       struct pnp_dev *pnp_avm_d = NULL;
+
+       if (!isapnp_present())
+               return(1);      /* no-op: success */
+
+       if ((pnp_avm_c = pnp_find_card(
+               ISAPNP_VENDOR('A', 'V', 'M'),
+               ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
+               if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
+                       ISAPNP_VENDOR('A', 'V', 'M'),
+                       ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
+                       int err;
+
+                       pnp_disable_dev(pnp_avm_d);
+                       err = pnp_activate_dev(pnp_avm_d);
+                       if (err<0) {
+                               printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+                                       __FUNCTION__, err);
+                               return(0);
+                       }
+                       cs->hw.avm.cfg_reg =
+                               pnp_port_start(pnp_avm_d, 0);
+                       cs->irq = pnp_irq(pnp_avm_d, 0);
+                       if (!cs->irq) {
+                               printk(KERN_ERR "FritzPnP:No IRQ\n");
+                               return(0);
+                       }
+                       if (!cs->hw.avm.cfg_reg) {
+                               printk(KERN_ERR "FritzPnP:No IO address\n");
+                               return(0);
+                       }
+                       cs->subtyp = AVM_FRITZ_PNP;
+
+                       return (2);     /* goto 'ready' label */
+               }
+       }
+
+       return (1);
+}
+
+#endif /* __ISAPNP__ */
+
+#ifndef CONFIG_PCI
+
+static int __devinit avm_pci_setup(struct IsdnCardState *cs)
+{
+       return(1);      /* no-op: success */
+}
+
+#else
+
+static struct pci_dev *dev_avm __devinitdata = NULL;
+
+static int __devinit avm_pci_setup(struct IsdnCardState *cs)
+{
+       if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
+               PCI_DEVICE_ID_AVM_A1, dev_avm))) {
+
+               if (pci_enable_device(dev_avm))
+                       return(0);
+
+               cs->irq = dev_avm->irq;
+               if (!cs->irq) {
+                       printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
+                       return(0);
+               }
+
+               cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
+               if (!cs->hw.avm.cfg_reg) {
+                       printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
+                       return(0);
+               }
+
+               cs->subtyp = AVM_FRITZ_PCI;
+       } else {
+               printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+               return(0);
+       }
+
+       cs->irq_flags |= IRQF_SHARED;
+
+       return (1);
+}
+
+#endif /* CONFIG_PCI */
+
+int __devinit
+setup_avm_pcipnp(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       char tmp[64];
+       int rc;
+
+       strcpy(tmp, avm_pci_rev);
+       printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
+
+       if (cs->typ != ISDN_CTYPE_FRITZPCI)
+               return (0);
+
+       if (card->para[1]) {
+               /* old manual method */
+               cs->hw.avm.cfg_reg = card->para[1];
+               cs->irq = card->para[0];
+               cs->subtyp = AVM_FRITZ_PNP;
+               goto ready;
+       }
+
+       rc = avm_pnp_setup(cs);
+       if (rc < 1)
+               return (0);
+       if (rc == 2)
+               goto ready;
+
+       rc = avm_pci_setup(cs);
+       if (rc < 1)
+               return (0);
+
+ready:
+       return avm_setup_rest(cs);
+}
index 6339bb443f624e56f4fbfe97b3f400d968e5d8ac..99ef3b43fcd79ebf276dfcd6ce48c0b60f80433f 100644 (file)
@@ -20,8 +20,6 @@
 #include <linux/pci.h>
 #include "bkm_ax.h"
 
-#ifdef CONFIG_PCI
-
 #define        ATTEMPT_PCI_REMAPPING   /* Required for PLX rev 1 */
 
 extern const char *CardType[];
@@ -279,12 +277,9 @@ static u_char pci_bus __devinitdata = 0;
 static u_char pci_device_fn __devinitdata = 0;
 static u_char pci_irq __devinitdata = 0;
 
-#endif /* CONFIG_PCI */
-
 int __devinit
 setup_sct_quadro(struct IsdnCard *card)
 {
-#ifdef CONFIG_PCI
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
        u_int found = 0;
@@ -442,7 +437,4 @@ setup_sct_quadro(struct IsdnCard *card)
                sct_quadro_subtypes[cs->subtyp],
                readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
        return (1);
-#else
-       printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
-#endif /* CONFIG_PCI */
 }
index 6eebeb441bfd1ec7482a9b42bbdfd198c65acf86..82674507874647a07504e295c1a890962ce2dd98 100644 (file)
@@ -25,8 +25,6 @@
 #include <linux/pci.h>
 #include <linux/isapnp.h>
 
-extern const char *CardType[];
-
 static const char *Diva_revision = "$Revision: 1.33.2.6 $";
 
 #define byteout(addr,val) outb(val,addr)
@@ -906,225 +904,15 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *dev_diva __devinitdata = NULL;
-static struct pci_dev *dev_diva_u __devinitdata = NULL;
-static struct pci_dev *dev_diva201 __devinitdata = NULL;
-static struct pci_dev *dev_diva202 __devinitdata = NULL;
-
-#ifdef __ISAPNP__
-static struct isapnp_device_id diva_ids[] __devinitdata = {
-       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
-         ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 
-         (unsigned long) "Diva picola" },
-       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
-         ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), 
-         (unsigned long) "Diva picola" },
-       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
-         ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 
-         (unsigned long) "Diva 2.0" },
-       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
-         ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), 
-         (unsigned long) "Diva 2.0" },
-       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
-         ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 
-         (unsigned long) "Diva 2.01" },
-       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
-         ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), 
-         (unsigned long) "Diva 2.01" },
-       { 0, }
-};
-
-static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0];
-static struct pnp_card *pnp_c __devinitdata = NULL;
-#endif
-
-
-int __devinit
-setup_diva(struct IsdnCard *card)
+static int __devinit setup_diva_common(struct IsdnCardState *cs)
 {
-       int bytecnt = 8;
+       int bytecnt;
        u_char val;
-       struct IsdnCardState *cs = card->cs;
-       char tmp[64];
-
-       strcpy(tmp, Diva_revision);
-       printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
-       if (cs->typ != ISDN_CTYPE_DIEHLDIVA)
-               return(0);
-       cs->hw.diva.status = 0;
-       if (card->para[1]) {
-               cs->hw.diva.ctrl_reg = 0;
-               cs->hw.diva.cfg_reg = card->para[1];
-               val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
-                       cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
-               printk(KERN_INFO "Diva: IPAC version %x\n", val);
-               if ((val == 1) || (val==2)) {
-                       cs->subtyp = DIVA_IPAC_ISA;
-                       cs->hw.diva.ctrl = 0;
-                       cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
-                       cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
-                       cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
-                       cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
-                       test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-               } else {
-                       cs->subtyp = DIVA_ISA;
-                       cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
-                       cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
-                       cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
-                       cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
-                       cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
-               }
-               cs->irq = card->para[0];
-       } else {
-#ifdef __ISAPNP__
-               if (isapnp_present()) {
-                       struct pnp_dev *pnp_d;
-                       while(ipid->card_vendor) {
-                               if ((pnp_c = pnp_find_card(ipid->card_vendor,
-                                       ipid->card_device, pnp_c))) {
-                                       pnp_d = NULL;
-                                       if ((pnp_d = pnp_find_dev(pnp_c,
-                                               ipid->vendor, ipid->function, pnp_d))) {
-                                               int err;
-
-                                               printk(KERN_INFO "HiSax: %s detected\n",
-                                                       (char *)ipid->driver_data);
-                                               pnp_disable_dev(pnp_d);
-                                               err = pnp_activate_dev(pnp_d);
-                                               if (err<0) {
-                                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-                                                               __FUNCTION__, err);
-                                                       return(0);
-                                               }
-                                               card->para[1] = pnp_port_start(pnp_d, 0);
-                                               card->para[0] = pnp_irq(pnp_d, 0);
-                                               if (!card->para[0] || !card->para[1]) {
-                                                       printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
-                                                               card->para[0], card->para[1]);
-                                                       pnp_disable_dev(pnp_d); 
-                                                       return(0);
-                                               }
-                                               cs->hw.diva.cfg_reg  = card->para[1];
-                                               cs->irq = card->para[0];
-                                               if (ipid->function == ISAPNP_FUNCTION(0xA1)) {
-                                                       cs->subtyp = DIVA_IPAC_ISA;
-                                                       cs->hw.diva.ctrl = 0;
-                                                       cs->hw.diva.isac =
-                                                               card->para[1] + DIVA_IPAC_DATA;
-                                                       cs->hw.diva.hscx =
-                                                               card->para[1] + DIVA_IPAC_DATA;
-                                                       cs->hw.diva.isac_adr =
-                                                               card->para[1] + DIVA_IPAC_ADR;
-                                                       cs->hw.diva.hscx_adr =
-                                                               card->para[1] + DIVA_IPAC_ADR;
-                                                       test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-                                               } else {
-                                                       cs->subtyp = DIVA_ISA;
-                                                       cs->hw.diva.ctrl =
-                                                               card->para[1] + DIVA_ISA_CTRL;
-                                                       cs->hw.diva.isac =
-                                                               card->para[1] + DIVA_ISA_ISAC_DATA;
-                                                       cs->hw.diva.hscx =
-                                                               card->para[1] + DIVA_HSCX_DATA;
-                                                       cs->hw.diva.isac_adr =
-                                                               card->para[1] + DIVA_ISA_ISAC_ADR;
-                                                       cs->hw.diva.hscx_adr =
-                                                               card->para[1] + DIVA_HSCX_ADR;
-                                               }
-                                               goto ready;
-                                       } else {
-                                               printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
-                                               return(0);
-                                       }
-                               }
-                               ipid++;
-                               pnp_c=NULL;
-                       } 
-                       if (!ipid->card_vendor) {
-                               printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
-                       }
-               }
-#endif
-#ifdef CONFIG_PCI
-               cs->subtyp = 0;
-               if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
-                       PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
-                       if (pci_enable_device(dev_diva))
-                               return(0);
-                       cs->subtyp = DIVA_PCI;
-                       cs->irq = dev_diva->irq;
-                       cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
-               } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
-                       PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
-                       if (pci_enable_device(dev_diva_u))
-                               return(0);
-                       cs->subtyp = DIVA_PCI;
-                       cs->irq = dev_diva_u->irq;
-                       cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
-               } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
-                       PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
-                       if (pci_enable_device(dev_diva201))
-                               return(0);
-                       cs->subtyp = DIVA_IPAC_PCI;
-                       cs->irq = dev_diva201->irq;
-                       cs->hw.diva.pci_cfg =
-                               (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
-                       cs->hw.diva.cfg_reg =
-                               (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
-               } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,
-                       PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {
-                       if (pci_enable_device(dev_diva202))
-                               return(0);
-                       cs->subtyp = DIVA_IPACX_PCI;
-                       cs->irq = dev_diva202->irq;
-                       cs->hw.diva.pci_cfg =
-                               (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);
-                       cs->hw.diva.cfg_reg =
-                               (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);
-               } else {
-                       printk(KERN_WARNING "Diva: No PCI card found\n");
-                       return(0);
-               }
-
-               if (!cs->irq) {
-                       printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
-                       iounmap_diva(cs);
-                       return(0);
-               }
-
-               if (!cs->hw.diva.cfg_reg) {
-                       printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
-                       iounmap_diva(cs);
-                       return(0);
-               }
-               cs->irq_flags |= IRQF_SHARED;
-#else
-               printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
-               printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
-               return (0);
-#endif /* CONFIG_PCI */
-               if ((cs->subtyp == DIVA_IPAC_PCI) ||
-                   (cs->subtyp == DIVA_IPACX_PCI)   ) {
-                       cs->hw.diva.ctrl = 0;
-                       cs->hw.diva.isac = 0;
-                       cs->hw.diva.hscx = 0;
-                       cs->hw.diva.isac_adr = 0;
-                       cs->hw.diva.hscx_adr = 0;
-                       test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-                       bytecnt = 0;
-               } else {
-                       cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
-                       cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
-                       cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
-                       cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
-                       cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
-                       bytecnt = 32;
-               }
-       }
 
-#ifdef __ISAPNP__
-ready:
-#endif
+       if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
+               bytecnt = 8;
+       else
+               bytecnt = 32;
 
        printk(KERN_INFO
                "Diva: %s card configured at %#lx IRQ %d\n",
@@ -1145,7 +933,7 @@ ready:
                if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) {
                        printk(KERN_WARNING
                               "HiSax: %s config port %lx-%lx already in use\n",
-                              CardType[card->typ],
+                              "diva",
                               cs->hw.diva.cfg_reg,
                               cs->hw.diva.cfg_reg + bytecnt);
                        iounmap_diva(cs);
@@ -1206,3 +994,290 @@ ready:
        }
        return (1);
 }
+
+#ifdef CONFIG_ISA
+
+static int __devinit setup_diva_isa(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       u_char val;
+
+       if (!card->para[1])
+               return (-1);    /* card not found; continue search */
+
+       cs->hw.diva.ctrl_reg = 0;
+       cs->hw.diva.cfg_reg = card->para[1];
+       val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+               cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+       printk(KERN_INFO "Diva: IPAC version %x\n", val);
+       if ((val == 1) || (val==2)) {
+               cs->subtyp = DIVA_IPAC_ISA;
+               cs->hw.diva.ctrl = 0;
+               cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
+               cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
+               cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+               cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
+               test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+       } else {
+               cs->subtyp = DIVA_ISA;
+               cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
+               cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
+               cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
+               cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+               cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+       }
+       cs->irq = card->para[0];
+
+       return (1);             /* card found */
+}
+
+#else  /* if !CONFIG_ISA */
+
+static int __devinit setup_diva_isa(struct IsdnCard *card)
+{
+       return (-1);    /* card not found; continue search */
+}
+
+#endif /* CONFIG_ISA */
+
+#ifdef __ISAPNP__
+static struct isapnp_device_id diva_ids[] __devinitdata = {
+       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+         ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 
+         (unsigned long) "Diva picola" },
+       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+         ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), 
+         (unsigned long) "Diva picola" },
+       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+         ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 
+         (unsigned long) "Diva 2.0" },
+       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+         ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), 
+         (unsigned long) "Diva 2.0" },
+       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+         ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 
+         (unsigned long) "Diva 2.01" },
+       { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+         ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), 
+         (unsigned long) "Diva 2.01" },
+       { 0, }
+};
+
+static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0];
+static struct pnp_card *pnp_c __devinitdata = NULL;
+
+static int __devinit setup_diva_isapnp(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       struct pnp_dev *pnp_d;
+
+       if (!isapnp_present())
+               return (-1);    /* card not found; continue search */
+
+       while(ipid->card_vendor) {
+               if ((pnp_c = pnp_find_card(ipid->card_vendor,
+                       ipid->card_device, pnp_c))) {
+                       pnp_d = NULL;
+                       if ((pnp_d = pnp_find_dev(pnp_c,
+                               ipid->vendor, ipid->function, pnp_d))) {
+                               int err;
+
+                               printk(KERN_INFO "HiSax: %s detected\n",
+                                       (char *)ipid->driver_data);
+                               pnp_disable_dev(pnp_d);
+                               err = pnp_activate_dev(pnp_d);
+                               if (err<0) {
+                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+                                               __FUNCTION__, err);
+                                       return(0);
+                               }
+                               card->para[1] = pnp_port_start(pnp_d, 0);
+                               card->para[0] = pnp_irq(pnp_d, 0);
+                               if (!card->para[0] || !card->para[1]) {
+                                       printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+                                               card->para[0], card->para[1]);
+                                       pnp_disable_dev(pnp_d); 
+                                       return(0);
+                               }
+                               cs->hw.diva.cfg_reg  = card->para[1];
+                               cs->irq = card->para[0];
+                               if (ipid->function == ISAPNP_FUNCTION(0xA1)) {
+                                       cs->subtyp = DIVA_IPAC_ISA;
+                                       cs->hw.diva.ctrl = 0;
+                                       cs->hw.diva.isac =
+                                               card->para[1] + DIVA_IPAC_DATA;
+                                       cs->hw.diva.hscx =
+                                               card->para[1] + DIVA_IPAC_DATA;
+                                       cs->hw.diva.isac_adr =
+                                               card->para[1] + DIVA_IPAC_ADR;
+                                       cs->hw.diva.hscx_adr =
+                                               card->para[1] + DIVA_IPAC_ADR;
+                                       test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+                               } else {
+                                       cs->subtyp = DIVA_ISA;
+                                       cs->hw.diva.ctrl =
+                                               card->para[1] + DIVA_ISA_CTRL;
+                                       cs->hw.diva.isac =
+                                               card->para[1] + DIVA_ISA_ISAC_DATA;
+                                       cs->hw.diva.hscx =
+                                               card->para[1] + DIVA_HSCX_DATA;
+                                       cs->hw.diva.isac_adr =
+                                               card->para[1] + DIVA_ISA_ISAC_ADR;
+                                       cs->hw.diva.hscx_adr =
+                                               card->para[1] + DIVA_HSCX_ADR;
+                               }
+                               return (1);             /* card found */
+                       } else {
+                               printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
+                               return(0);
+                       }
+               }
+               ipid++;
+               pnp_c=NULL;
+       } 
+
+       return (-1);    /* card not found; continue search */
+}
+
+#else  /* if !ISAPNP */
+
+static int __devinit setup_diva_isapnp(struct IsdnCard *card)
+{
+       return (-1);    /* card not found; continue search */
+}
+
+#endif /* ISAPNP */
+
+#ifdef CONFIG_PCI
+static struct pci_dev *dev_diva __devinitdata = NULL;
+static struct pci_dev *dev_diva_u __devinitdata = NULL;
+static struct pci_dev *dev_diva201 __devinitdata = NULL;
+static struct pci_dev *dev_diva202 __devinitdata = NULL;
+
+static int __devinit setup_diva_pci(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+
+       cs->subtyp = 0;
+       if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
+               PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
+               if (pci_enable_device(dev_diva))
+                       return(0);
+               cs->subtyp = DIVA_PCI;
+               cs->irq = dev_diva->irq;
+               cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
+       } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+               PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
+               if (pci_enable_device(dev_diva_u))
+                       return(0);
+               cs->subtyp = DIVA_PCI;
+               cs->irq = dev_diva_u->irq;
+               cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
+       } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+               PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
+               if (pci_enable_device(dev_diva201))
+                       return(0);
+               cs->subtyp = DIVA_IPAC_PCI;
+               cs->irq = dev_diva201->irq;
+               cs->hw.diva.pci_cfg =
+                       (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
+               cs->hw.diva.cfg_reg =
+                       (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
+       } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,
+               PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {
+               if (pci_enable_device(dev_diva202))
+                       return(0);
+               cs->subtyp = DIVA_IPACX_PCI;
+               cs->irq = dev_diva202->irq;
+               cs->hw.diva.pci_cfg =
+                       (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);
+               cs->hw.diva.cfg_reg =
+                       (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);
+       } else {
+               return (-1);    /* card not found; continue search */
+       }
+
+       if (!cs->irq) {
+               printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
+               iounmap_diva(cs);
+               return(0);
+       }
+
+       if (!cs->hw.diva.cfg_reg) {
+               printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
+               iounmap_diva(cs);
+               return(0);
+       }
+       cs->irq_flags |= IRQF_SHARED;
+
+       if ((cs->subtyp == DIVA_IPAC_PCI) ||
+           (cs->subtyp == DIVA_IPACX_PCI)   ) {
+               cs->hw.diva.ctrl = 0;
+               cs->hw.diva.isac = 0;
+               cs->hw.diva.hscx = 0;
+               cs->hw.diva.isac_adr = 0;
+               cs->hw.diva.hscx_adr = 0;
+               test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+       } else {
+               cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+               cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+               cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+               cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+               cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+       }
+
+       return (1);             /* card found */
+}
+
+#else  /* if !CONFIG_PCI */
+
+static int __devinit setup_diva_pci(struct IsdnCard *card)
+{
+       return (-1);    /* card not found; continue search */
+}
+
+#endif /* CONFIG_PCI */
+
+int __devinit
+setup_diva(struct IsdnCard *card)
+{
+       int rc, have_card = 0;
+       struct IsdnCardState *cs = card->cs;
+       char tmp[64];
+
+       strcpy(tmp, Diva_revision);
+       printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
+       if (cs->typ != ISDN_CTYPE_DIEHLDIVA)
+               return(0);
+       cs->hw.diva.status = 0;
+
+       rc = setup_diva_isa(card);
+       if (!rc)
+               return rc;
+       if (rc > 0) {
+               have_card = 1;
+               goto ready;
+       }
+
+       rc = setup_diva_isapnp(card);
+       if (!rc)
+               return rc;
+       if (rc > 0) {
+               have_card = 1;
+               goto ready;
+       }
+
+       rc = setup_diva_pci(card);
+       if (!rc)
+               return rc;
+       if (rc > 0)
+               have_card = 1;
+
+ready:
+       if (!have_card) {
+               printk(KERN_WARNING "Diva: No ISA, ISAPNP or PCI card found\n");
+               return(0);
+       }
+
+       return setup_diva_common(card->cs);
+}
index fab3e4ea05957c1b7abe9fa147011d871355c045..0c1351b23840f8946e151cb45c0e829921ce4c93 100644 (file)
@@ -30,8 +30,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 
-extern const char *CardType[];
-
 static const char *Elsa_revision = "$Revision: 2.32.2.4 $";
 static const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
@@ -832,8 +830,75 @@ probe_elsa(struct IsdnCardState *cs)
        return (CARD_portlist[i]);
 }
 
-static         struct pci_dev *dev_qs1000 __devinitdata = NULL;
-static         struct pci_dev *dev_qs3000 __devinitdata = NULL;
+static int __devinit
+setup_elsa_isa(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       u_char val;
+
+       cs->hw.elsa.base = card->para[0];
+       printk(KERN_INFO "Elsa: Microlink IO probing\n");
+       if (cs->hw.elsa.base) {
+               if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
+                                                 cs->typ))) {
+                       printk(KERN_WARNING
+                              "Elsa: no Elsa Microlink at %#lx\n",
+                              cs->hw.elsa.base);
+                       return (0);
+               }
+       } else
+               cs->hw.elsa.base = probe_elsa(cs);
+
+       if (!cs->hw.elsa.base) {
+               printk(KERN_WARNING
+                      "No Elsa Microlink found\n");
+               return (0);
+       }
+
+       cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
+       cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
+       cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
+       cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
+       cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
+       cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+       cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+       cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+       val = bytein(cs->hw.elsa.cfg);
+       if (cs->subtyp == ELSA_PC) {
+               const u_char CARD_IrqTab[8] =
+               {7, 3, 5, 9, 0, 0, 0, 0};
+               cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
+       } else if (cs->subtyp == ELSA_PCC8) {
+               const u_char CARD_IrqTab[8] =
+               {7, 3, 5, 9, 0, 0, 0, 0};
+               cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
+       } else {
+               const u_char CARD_IrqTab[8] =
+               {15, 10, 15, 3, 11, 5, 11, 9};
+               cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
+       }
+       val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
+       if (val < 3)
+               val |= 8;
+       val += 'A' - 3;
+       if (val == 'B' || val == 'C')
+               val ^= 1;
+       if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
+               val = 'C';
+       printk(KERN_INFO
+              "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
+              Elsa_Types[cs->subtyp],
+              cs->hw.elsa.base,
+              val, cs->irq);
+       val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
+       if (val) {
+               printk(KERN_WARNING
+                  "Elsa: Microlink S0 bus power bad\n");
+               cs->hw.elsa.status |= ELSA_BAD_PWR;
+       }
+
+       return (1);
+}
 
 #ifdef __ISAPNP__
 static struct isapnp_device_id elsa_ids[] __devinitdata = {
@@ -848,233 +913,194 @@ static struct isapnp_device_id elsa_ids[] __devinitdata = {
 
 static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
-#endif
+#endif /* __ISAPNP__ */
 
-int __devinit
-setup_elsa(struct IsdnCard *card)
+static int __devinit
+setup_elsa_isapnp(struct IsdnCard *card)
 {
-       int bytecnt;
-       u_char val;
        struct IsdnCardState *cs = card->cs;
-       char tmp[64];
 
-       strcpy(tmp, Elsa_revision);
-       printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
-       cs->hw.elsa.ctrl_reg = 0;
-       cs->hw.elsa.status = 0;
-       cs->hw.elsa.MFlag = 0;
-       cs->subtyp = 0;
-       if (cs->typ == ISDN_CTYPE_ELSA) {
-               cs->hw.elsa.base = card->para[0];
-               printk(KERN_INFO "Elsa: Microlink IO probing\n");
-               if (cs->hw.elsa.base) {
-                       if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
-                                                         cs->typ))) {
-                               printk(KERN_WARNING
-                                      "Elsa: no Elsa Microlink at %#lx\n",
-                                      cs->hw.elsa.base);
-                               return (0);
-                       }
-               } else
-                       cs->hw.elsa.base = probe_elsa(cs);
-               if (cs->hw.elsa.base) {
-                       cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-                       cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-                       cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-                       cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-                       cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
-                       cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-                       cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-                       cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-                       val = bytein(cs->hw.elsa.cfg);
-                       if (cs->subtyp == ELSA_PC) {
-                               const u_char CARD_IrqTab[8] =
-                               {7, 3, 5, 9, 0, 0, 0, 0};
-                               cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
-                       } else if (cs->subtyp == ELSA_PCC8) {
-                               const u_char CARD_IrqTab[8] =
-                               {7, 3, 5, 9, 0, 0, 0, 0};
-                               cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
-                       } else {
-                               const u_char CARD_IrqTab[8] =
-                               {15, 10, 15, 3, 11, 5, 11, 9};
-                               cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
-                       }
-                       val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
-                       if (val < 3)
-                               val |= 8;
-                       val += 'A' - 3;
-                       if (val == 'B' || val == 'C')
-                               val ^= 1;
-                       if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
-                               val = 'C';
-                       printk(KERN_INFO
-                              "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
-                              Elsa_Types[cs->subtyp],
-                              cs->hw.elsa.base,
-                              val, cs->irq);
-                       val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
-                       if (val) {
-                               printk(KERN_WARNING
-                                  "Elsa: Microlink S0 bus power bad\n");
-                               cs->hw.elsa.status |= ELSA_BAD_PWR;
-                       }
-               } else {
-                       printk(KERN_WARNING
-                              "No Elsa Microlink found\n");
-                       return (0);
-               }
-       } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
 #ifdef __ISAPNP__
-               if (!card->para[1] && isapnp_present()) {
-                       struct pnp_dev *pnp_d;
-                       while(ipid->card_vendor) {
-                               if ((pnp_c = pnp_find_card(ipid->card_vendor,
-                                       ipid->card_device, pnp_c))) {
-                                       pnp_d = NULL;
-                                       if ((pnp_d = pnp_find_dev(pnp_c,
-                                               ipid->vendor, ipid->function, pnp_d))) {
-                                               int err;
-
-                                               printk(KERN_INFO "HiSax: %s detected\n",
-                                                       (char *)ipid->driver_data);
+       if (!card->para[1] && isapnp_present()) {
+               struct pnp_dev *pnp_d;
+               while(ipid->card_vendor) {
+                       if ((pnp_c = pnp_find_card(ipid->card_vendor,
+                               ipid->card_device, pnp_c))) {
+                               pnp_d = NULL;
+                               if ((pnp_d = pnp_find_dev(pnp_c,
+                                       ipid->vendor, ipid->function, pnp_d))) {
+                                       int err;
+
+                                       printk(KERN_INFO "HiSax: %s detected\n",
+                                               (char *)ipid->driver_data);
+                                       pnp_disable_dev(pnp_d);
+                                       err = pnp_activate_dev(pnp_d);
+                                       if (err<0) {
+                                               printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+                                                       __FUNCTION__, err);
+                                               return(0);
+                                       }
+                                       card->para[1] = pnp_port_start(pnp_d, 0);
+                                       card->para[0] = pnp_irq(pnp_d, 0);
+
+                                       if (!card->para[0] || !card->para[1]) {
+                                               printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
+                                                       card->para[0], card->para[1]);
                                                pnp_disable_dev(pnp_d);
-                                               err = pnp_activate_dev(pnp_d);
-                                               if (err<0) {
-                                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-                                                               __FUNCTION__, err);
-                                                       return(0);
-                                               }
-                                               card->para[1] = pnp_port_start(pnp_d, 0);
-                                               card->para[0] = pnp_irq(pnp_d, 0);
-
-                                               if (!card->para[0] || !card->para[1]) {
-                                                       printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
-                                                               card->para[0], card->para[1]);
-                                                       pnp_disable_dev(pnp_d);
-                                                       return(0);
-                                               }
-                                               if (ipid->function == ISAPNP_FUNCTION(0x133))
-                                                       cs->subtyp = ELSA_QS1000;
-                                               else
-                                                       cs->subtyp = ELSA_QS3000;
-                                               break;
-                                       } else {
-                                               printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
                                                return(0);
                                        }
+                                       if (ipid->function == ISAPNP_FUNCTION(0x133))
+                                               cs->subtyp = ELSA_QS1000;
+                                       else
+                                               cs->subtyp = ELSA_QS3000;
+                                       break;
+                               } else {
+                                       printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
+                                       return(0);
                                }
-                               ipid++;
-                               pnp_c=NULL;
-                       } 
-                       if (!ipid->card_vendor) {
-                               printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
-                               return(0);
                        }
+                       ipid++;
+                       pnp_c=NULL;
+               } 
+               if (!ipid->card_vendor) {
+                       printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
+                       return(0);
                }
-#endif
-               if (card->para[1] && card->para[0]) { 
-                       cs->hw.elsa.base = card->para[1];
-                       cs->irq = card->para[0];
-                       if (!cs->subtyp)
-                               cs->subtyp = ELSA_QS1000;
-               } else {
-                       printk(KERN_ERR "Elsa PnP: no parameter\n");
-               }
-               cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-               cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-               cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-               cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-               cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-               cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-               cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-               printk(KERN_INFO
-                      "Elsa: %s defined at %#lx IRQ %d\n",
-                      Elsa_Types[cs->subtyp],
-                      cs->hw.elsa.base,
-                      cs->irq);
-       } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
+       }
+#endif /* __ISAPNP__ */
+
+       if (card->para[1] && card->para[0]) { 
                cs->hw.elsa.base = card->para[1];
                cs->irq = card->para[0];
-               val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID);
-               if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
-                       cs->subtyp = ELSA_PCMCIA_IPAC;
-                       cs->hw.elsa.ale = cs->hw.elsa.base + 0;
-                       cs->hw.elsa.isac = cs->hw.elsa.base + 2;
-                       cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
-                       test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-               } else {
-                       cs->subtyp = ELSA_PCMCIA;
-                       cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
-                       cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
-                       cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-               }
-               cs->hw.elsa.timer = 0;
-               cs->hw.elsa.trig = 0;
-               cs->hw.elsa.ctrl = 0;
-               cs->irq_flags |= IRQF_SHARED;
-               printk(KERN_INFO
-                      "Elsa: %s defined at %#lx IRQ %d\n",
-                      Elsa_Types[cs->subtyp],
-                      cs->hw.elsa.base,
-                      cs->irq);
-       } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
+               if (!cs->subtyp)
+                       cs->subtyp = ELSA_QS1000;
+       } else {
+               printk(KERN_ERR "Elsa PnP: no parameter\n");
+       }
+       cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
+       cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
+       cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
+       cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+       cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+       cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+       cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
+       printk(KERN_INFO
+              "Elsa: %s defined at %#lx IRQ %d\n",
+              Elsa_Types[cs->subtyp],
+              cs->hw.elsa.base,
+              cs->irq);
+
+       return (1);
+}
+
+static void __devinit
+setup_elsa_pcmcia(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       u_char val;
+
+       cs->hw.elsa.base = card->para[1];
+       cs->irq = card->para[0];
+       val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID);
+       if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
+               cs->subtyp = ELSA_PCMCIA_IPAC;
+               cs->hw.elsa.ale = cs->hw.elsa.base + 0;
+               cs->hw.elsa.isac = cs->hw.elsa.base + 2;
+               cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
+               test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+       } else {
+               cs->subtyp = ELSA_PCMCIA;
+               cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
+               cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
+               cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+       }
+       cs->hw.elsa.timer = 0;
+       cs->hw.elsa.trig = 0;
+       cs->hw.elsa.ctrl = 0;
+       cs->irq_flags |= IRQF_SHARED;
+       printk(KERN_INFO
+              "Elsa: %s defined at %#lx IRQ %d\n",
+              Elsa_Types[cs->subtyp],
+              cs->hw.elsa.base,
+              cs->irq);
+}
+
 #ifdef CONFIG_PCI
-               cs->subtyp = 0;
-               if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
-                       PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
-                       if (pci_enable_device(dev_qs1000))
-                               return(0);
-                       cs->subtyp = ELSA_QS1000PCI;
-                       cs->irq = dev_qs1000->irq;
-                       cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
-                       cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
-               } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
-                       PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
-                       if (pci_enable_device(dev_qs3000))
-                               return(0);
-                       cs->subtyp = ELSA_QS3000PCI;
-                       cs->irq = dev_qs3000->irq;
-                       cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
-                       cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
-               } else {
-                       printk(KERN_WARNING "Elsa: No PCI card found\n");
+static         struct pci_dev *dev_qs1000 __devinitdata = NULL;
+static         struct pci_dev *dev_qs3000 __devinitdata = NULL;
+
+static int __devinit
+setup_elsa_pci(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+
+       cs->subtyp = 0;
+       if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
+               PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
+               if (pci_enable_device(dev_qs1000))
                        return(0);
-               }
-               if (!cs->irq) {
-                       printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
+               cs->subtyp = ELSA_QS1000PCI;
+               cs->irq = dev_qs1000->irq;
+               cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
+               cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
+       } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
+               PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
+               if (pci_enable_device(dev_qs3000))
                        return(0);
-               }
+               cs->subtyp = ELSA_QS3000PCI;
+               cs->irq = dev_qs3000->irq;
+               cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
+               cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
+       } else {
+               printk(KERN_WARNING "Elsa: No PCI card found\n");
+               return(0);
+       }
+       if (!cs->irq) {
+               printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
+               return(0);
+       }
+
+       if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
+               printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
+               return(0);
+       }
+       if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
+               printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
+               printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
+               printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
+       }
+       cs->hw.elsa.ale  = cs->hw.elsa.base;
+       cs->hw.elsa.isac = cs->hw.elsa.base +1;
+       cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
+       test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+       cs->hw.elsa.timer = 0;
+       cs->hw.elsa.trig  = 0;
+       cs->irq_flags |= IRQF_SHARED;
+       printk(KERN_INFO
+              "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
+              Elsa_Types[cs->subtyp],
+              cs->hw.elsa.base,
+              cs->hw.elsa.cfg,
+              cs->irq);
+
+       return (1);
+}
 
-               if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
-                       printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
-                       return(0);
-               }
-               if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
-                       printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
-                       printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
-                       printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
-               }
-               cs->hw.elsa.ale  = cs->hw.elsa.base;
-               cs->hw.elsa.isac = cs->hw.elsa.base +1;
-               cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
-               test_and_set_bit(HW_IPAC, &cs->HW_Flags);
-               cs->hw.elsa.timer = 0;
-               cs->hw.elsa.trig  = 0;
-               cs->irq_flags |= IRQF_SHARED;
-               printk(KERN_INFO
-                      "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
-                      Elsa_Types[cs->subtyp],
-                      cs->hw.elsa.base,
-                      cs->hw.elsa.cfg,
-                      cs->irq);
 #else
-               printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n");
-               printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n");
-               return (0);
+
+static void __devinit
+setup_elsa_pci(struct IsdnCard *card)
+{
+       return (1);
+}
 #endif /* CONFIG_PCI */
-       } else 
-               return (0);
+
+static int __devinit
+setup_elsa_common(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       u_char val;
+       int bytecnt;
 
        switch (cs->subtyp) {
                case ELSA_PC:
@@ -1104,8 +1130,7 @@ setup_elsa(struct IsdnCard *card)
           here, it would fail. */
        if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) {
                printk(KERN_WARNING
-                      "HiSax: %s config port %#lx-%#lx already in use\n",
-                      CardType[card->typ],
+                      "HiSax: ELSA config port %#lx-%#lx already in use\n",
                       cs->hw.elsa.base,
                       cs->hw.elsa.base + bytecnt);
                return (0);
@@ -1113,8 +1138,7 @@ setup_elsa(struct IsdnCard *card)
        if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
                if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) {
                        printk(KERN_WARNING
-                              "HiSax: %s pci port %x-%x already in use\n",
-                               CardType[card->typ],
+                              "HiSax: ELSA pci port %x-%x already in use\n",
                                cs->hw.elsa.cfg,
                                cs->hw.elsa.cfg + 0x80);
                        release_region(cs->hw.elsa.base, bytecnt);
@@ -1186,3 +1210,41 @@ setup_elsa(struct IsdnCard *card)
        }
        return (1);
 }
+
+int __devinit
+setup_elsa(struct IsdnCard *card)
+{
+       int rc;
+       struct IsdnCardState *cs = card->cs;
+       char tmp[64];
+
+       strcpy(tmp, Elsa_revision);
+       printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
+       cs->hw.elsa.ctrl_reg = 0;
+       cs->hw.elsa.status = 0;
+       cs->hw.elsa.MFlag = 0;
+       cs->subtyp = 0;
+
+       if (cs->typ == ISDN_CTYPE_ELSA) {
+               rc = setup_elsa_isa(card);
+               if (!rc)
+                       return (0);
+
+       } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
+               rc = setup_elsa_isapnp(card);
+               if (!rc)
+                       return (0);
+
+       } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA)
+               setup_elsa_pcmcia(card);
+
+       else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
+               rc = setup_elsa_pci(card);
+               if (!rc)
+                       return (0);
+
+       } else 
+               return (0);
+
+       return setup_elsa_common(card);
+}
index ad06f3cc60fb9c478fdbb2c7560e95b9996e4212..03dfc32166a09ea057e861d8eaa93d47e6239dfe 100644 (file)
@@ -518,8 +518,6 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *dev_sedl __devinitdata = NULL;
-
 #ifdef __ISAPNP__
 static struct isapnp_device_id sedl_ids[] __devinitdata = {
        { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
@@ -533,15 +531,158 @@ static struct isapnp_device_id sedl_ids[] __devinitdata = {
 
 static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0];
 static struct pnp_card *pnp_c __devinitdata = NULL;
-#endif
+
+static int __devinit
+setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
+{
+       struct IsdnCardState *cs = card->cs;
+       struct pnp_dev *pnp_d;
+
+       if (!isapnp_present())
+               return -1;
+
+       while(ipid->card_vendor) {
+               if ((pnp_c = pnp_find_card(ipid->card_vendor,
+                       ipid->card_device, pnp_c))) {
+                       pnp_d = NULL;
+                       if ((pnp_d = pnp_find_dev(pnp_c,
+                               ipid->vendor, ipid->function, pnp_d))) {
+                               int err;
+
+                               printk(KERN_INFO "HiSax: %s detected\n",
+                                       (char *)ipid->driver_data);
+                               pnp_disable_dev(pnp_d);
+                               err = pnp_activate_dev(pnp_d);
+                               if (err<0) {
+                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+                                               __FUNCTION__, err);
+                                       return(0);
+                               }
+                               card->para[1] = pnp_port_start(pnp_d, 0);
+                               card->para[0] = pnp_irq(pnp_d, 0);
+
+                               if (!card->para[0] || !card->para[1]) {
+                                       printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+                                               card->para[0], card->para[1]);
+                                       pnp_disable_dev(pnp_d);
+                                       return(0);
+                               }
+                               cs->hw.sedl.cfg_reg = card->para[1];
+                               cs->irq = card->para[0];
+                               if (ipid->function == ISAPNP_FUNCTION(0x2)) {
+                                       cs->subtyp = SEDL_SPEED_FAX;
+                                       cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+                                       *bytecnt = 16;
+                               } else {
+                                       cs->subtyp = SEDL_SPEED_CARD_WIN;
+                                       cs->hw.sedl.chip = SEDL_CHIP_TEST;
+                               }
+
+                               return (1);
+                       } else {
+                               printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+                               return(0);
+                       }
+               }
+               ipid++;
+               pnp_c = NULL;
+       } 
+
+       printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
+       return -1;
+}
+#else
+
+static int __devinit
+setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt)
+{
+       return -1;
+}
+#endif /* __ISAPNP__ */
+
+#ifdef CONFIG_PCI
+static struct pci_dev *dev_sedl __devinitdata = NULL;
+
+static int __devinit
+setup_sedlbauer_pci(struct IsdnCard *card)
+{
+       struct IsdnCardState *cs = card->cs;
+       u16 sub_vendor_id, sub_id;
+
+       if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+                       PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
+               if (pci_enable_device(dev_sedl))
+                       return(0);
+               cs->irq = dev_sedl->irq;
+               if (!cs->irq) {
+                       printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+                       return(0);
+               }
+               cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
+       } else {
+               printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+               return(0);
+       }
+       cs->irq_flags |= IRQF_SHARED;
+       cs->hw.sedl.bus = SEDL_BUS_PCI;
+       sub_vendor_id = dev_sedl->subsystem_vendor;
+       sub_id = dev_sedl->subsystem_device;
+       printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
+               sub_vendor_id, sub_id);
+       printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
+               cs->hw.sedl.cfg_reg);
+       if (sub_id != PCI_SUB_ID_SEDLBAUER) {
+               printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
+               return(0);
+       }
+       if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
+               cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+               cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+       } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
+               cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+               cs->subtyp = SEDL_SPEEDFAX_PCI;
+       } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
+               cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+               cs->subtyp = HST_SAPHIR3;
+       } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
+               cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+               cs->subtyp = SEDL_SPEED_PCI;
+       } else {
+               printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
+                       sub_vendor_id);
+               return(0);
+       }
+
+       cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+       cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+       byteout(cs->hw.sedl.cfg_reg, 0xff);
+       byteout(cs->hw.sedl.cfg_reg, 0x00);
+       byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+       byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */
+       byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+       mdelay(2);
+       byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+       mdelay(10);
+
+       return (1);
+}
+
+#else
+
+static int __devinit
+setup_sedlbauer_pci(struct IsdnCard *card)
+{
+       return (1);
+}
+
+#endif /* CONFIG_PCI */
 
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
 {
-       int bytecnt, ver, val;
+       int bytecnt = 8, ver, val, rc;
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
-       u16 sub_vendor_id, sub_id;
 
        strcpy(tmp, Sedlbauer_revision);
        printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
@@ -569,124 +710,21 @@ setup_sedlbauer(struct IsdnCard *card)
                        bytecnt = 16;
                }
        } else {
-#ifdef __ISAPNP__
-               if (isapnp_present()) {
-                       struct pnp_dev *pnp_d;
-                       while(ipid->card_vendor) {
-                               if ((pnp_c = pnp_find_card(ipid->card_vendor,
-                                       ipid->card_device, pnp_c))) {
-                                       pnp_d = NULL;
-                                       if ((pnp_d = pnp_find_dev(pnp_c,
-                                               ipid->vendor, ipid->function, pnp_d))) {
-                                               int err;
-
-                                               printk(KERN_INFO "HiSax: %s detected\n",
-                                                       (char *)ipid->driver_data);
-                                               pnp_disable_dev(pnp_d);
-                                               err = pnp_activate_dev(pnp_d);
-                                               if (err<0) {
-                                                       printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-                                                               __FUNCTION__, err);
-                                                       return(0);
-                                               }
-                                               card->para[1] = pnp_port_start(pnp_d, 0);
-                                               card->para[0] = pnp_irq(pnp_d, 0);
-
-                                               if (!card->para[0] || !card->para[1]) {
-                                                       printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
-                                                               card->para[0], card->para[1]);
-                                                       pnp_disable_dev(pnp_d);
-                                                       return(0);
-                                               }
-                                               cs->hw.sedl.cfg_reg = card->para[1];
-                                               cs->irq = card->para[0];
-                                               if (ipid->function == ISAPNP_FUNCTION(0x2)) {
-                                                       cs->subtyp = SEDL_SPEED_FAX;
-                                                       cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-                                                       bytecnt = 16;
-                                               } else {
-                                                       cs->subtyp = SEDL_SPEED_CARD_WIN;
-                                                       cs->hw.sedl.chip = SEDL_CHIP_TEST;
-                                               }
-                                               goto ready;
-                                       } else {
-                                               printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
-                                               return(0);
-                                       }
-                               }
-                               ipid++;
-                               pnp_c = NULL;
-                       } 
-                       if (!ipid->card_vendor) {
-                               printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
-                       }
-               }
-#endif
-/* Probe for Sedlbauer speed pci */
-#ifdef CONFIG_PCI
-               if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-                               PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
-                       if (pci_enable_device(dev_sedl))
-                               return(0);
-                       cs->irq = dev_sedl->irq;
-                       if (!cs->irq) {
-                               printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
-                               return(0);
-                       }
-                       cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
-               } else {
-                       printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
-                       return(0);
-               }
-               cs->irq_flags |= IRQF_SHARED;
-               cs->hw.sedl.bus = SEDL_BUS_PCI;
-               sub_vendor_id = dev_sedl->subsystem_vendor;
-               sub_id = dev_sedl->subsystem_device;
-               printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
-                       sub_vendor_id, sub_id);
-               printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
-                       cs->hw.sedl.cfg_reg);
-               if (sub_id != PCI_SUB_ID_SEDLBAUER) {
-                       printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
-                       return(0);
-               }
-               if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
-                       cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-                       cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
-               } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
-                       cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-                       cs->subtyp = SEDL_SPEEDFAX_PCI;
-               } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
-                       cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-                       cs->subtyp = HST_SAPHIR3;
-               } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
-                       cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-                       cs->subtyp = SEDL_SPEED_PCI;
-               } else {
-                       printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
-                               sub_vendor_id);
-                       return(0);
-               }
+               rc = setup_sedlbauer_isapnp(card, &bytecnt);
+               if (!rc)
+                       return (0);
+               if (rc > 0)
+                       goto ready;
+
+               /* Probe for Sedlbauer speed pci */
+               rc = setup_sedlbauer_pci(card);
+               if (!rc)
+                       return (0);
+
                bytecnt = 256;
-               cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
-               cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
-               byteout(cs->hw.sedl.cfg_reg, 0xff);
-               byteout(cs->hw.sedl.cfg_reg, 0x00);
-               byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-               byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */
-               byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-               mdelay(2);
-               byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-               mdelay(10);
-#else
-               printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
-               return (0);
-#endif /* CONFIG_PCI */
        }       
 
-#ifdef __ISAPNP__
 ready: 
-#endif
 
        /* In case of the sedlbauer pcmcia card, this region is in use,
         * reserved for us by the card manager. So we do not check it
index d09f6d033f156c96c46a8411a5e41dc14c3abf88..4393003ae162b5d7a7bd83991c3d53909d0f894d 100644 (file)
@@ -295,11 +295,12 @@ setup_telespci(struct IsdnCard *card)
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
+
        strcpy(tmp, telespci_revision);
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
                return (0);
-#ifdef CONFIG_PCI
+
        if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
                if (pci_enable_device(dev_tel))
                        return(0);
@@ -317,11 +318,6 @@ setup_telespci(struct IsdnCard *card)
                printk(KERN_WARNING "TelesPCI: No PCI card found\n");
                return(0);
        }
-#else
-       printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
-       printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
-       return (0);
-#endif /* CONFIG_PCI */
 
        /* Initialize Zoran PCI controller */
        writel(0x00000000, cs->hw.teles0.membase + 0x28);
index 3aeceaf9769e5dc30a7cbefd30b4995082f8c7f6..39129b94f8be503340686e7122584dfa8a14021a 100644 (file)
@@ -1009,7 +1009,7 @@ setup_w6692(struct IsdnCard *card)
        printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_W6692)
                return (0);
-#ifdef CONFIG_PCI
+
        while (id_list[id_idx].vendor_id) {
                dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
                                            id_list[id_idx].device_id,
@@ -1061,11 +1061,6 @@ setup_w6692(struct IsdnCard *card)
                       cs->hw.w6692.iobase + 255);
                return (0);
        }
-#else
-       printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
-       printk(KERN_WARNING "HiSax: W6692 unable to config\n");
-       return (0);
-#endif                         /* CONFIG_PCI */
 
        printk(KERN_INFO
               "HiSax: %s config irq:%d I/O:%x\n",
index 9e01748a176e95c2726c2842ff102bca5fd3c4eb..b7cc5c2f08c66c2ed38a01752b5ced0fe4ee3eb0 100644 (file)
 #include "hysdn_defs.h"
 
 static struct pci_device_id hysdn_pci_tbl[] = {
-       {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO},
-       {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2},
-       {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO},
-       {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO},
+       { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
+         PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO, 0, 0, BD_METRO },
+       { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
+         PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, 0, 0, BD_CHAMP2 },
+       { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
+         PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, 0, 0, BD_ERGO },
+       { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
+         PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, 0, 0, BD_ERGO },
+
        { }                             /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
@@ -34,128 +39,7 @@ MODULE_LICENSE("GPL");
 static char *hysdn_init_revision = "$Revision: 1.6.6.6 $";
 static int cardmax;            /* number of found cards */
 hysdn_card *card_root = NULL;  /* pointer to first card */
-
-/**********************************************/
-/* table assigning PCI-sub ids to board types */
-/* the last entry contains all 0              */
-/**********************************************/
-static struct {
-       unsigned short subid;           /* PCI sub id */
-       unsigned char cardtyp;          /* card type assigned */
-} pci_subid_map[] = {
-
-       {
-               PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO
-       },
-       {
-               PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2
-       },
-       {
-               PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO
-       },
-       {
-               PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO
-       },
-       {
-               0, 0
-       }                       /* terminating entry */
-};
-
-
-/*********************************************************************/
-/* search_cards searches for available cards in the pci config data. */
-/* If a card is found, the card structure is allocated and the cards */
-/* ressources are reserved. cardmax is incremented.                  */
-/*********************************************************************/
-static void
-search_cards(void)
-{
-       struct pci_dev *akt_pcidev = NULL;
-       hysdn_card *card, *card_last;
-       int i;
-
-       card_root = NULL;
-       card_last = NULL;
-       while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
-                                            akt_pcidev)) != NULL) {
-               if (pci_enable_device(akt_pcidev))
-                       continue;
-
-               if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) {
-                       printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
-                       return;
-               }
-               card->myid = cardmax;   /* set own id */
-               card->bus = akt_pcidev->bus->number;
-               card->devfn = akt_pcidev->devfn;        /* slot + function */
-               card->subsysid = akt_pcidev->subsystem_device;
-               card->irq = akt_pcidev->irq;
-               card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE);
-               card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE);
-               card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE);
-               card->brdtype = BD_NONE;        /* unknown */
-               card->debug_flags = DEF_DEB_FLAGS;      /* set default debug */
-               card->faxchans = 0;     /* default no fax channels */
-               card->bchans = 2;       /* and 2 b-channels */
-               for (i = 0; pci_subid_map[i].subid; i++)
-                       if (pci_subid_map[i].subid == card->subsysid) {
-                               card->brdtype = pci_subid_map[i].cardtyp;
-                               break;
-                       }
-               if (card->brdtype != BD_NONE) {
-                       if (ergo_inithardware(card)) {
-                               printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase);
-                               kfree(card);
-                               continue;
-                       }
-               } else {
-                       printk(KERN_WARNING "HYSDN: unknown card id 0x%04x\n", card->subsysid);
-                       kfree(card);    /* release mem */
-                       continue;
-               }
-               cardmax++;
-               card->next = NULL;      /*end of chain */
-               if (card_last)
-                       card_last->next = card;         /* pointer to next card */
-               else
-                       card_root = card;
-               card_last = card;       /* new chain end */
-       }                       /* device found */
-}                              /* search_cards */
-
-/************************************************************************************/
-/* free_resources frees the acquired PCI resources and returns the allocated memory */
-/************************************************************************************/
-static void
-free_resources(void)
-{
-       hysdn_card *card;
-
-       while (card_root) {
-               card = card_root;
-               if (card->releasehardware)
-                       card->releasehardware(card);    /* free all hardware resources */
-               card_root = card_root->next;    /* remove card from chain */
-               kfree(card);    /* return mem */
-
-       }                       /* while card_root */
-}                              /* free_resources */
-
-/**************************************************************************/
-/* stop_cards disables (hardware resets) all cards and disables interrupt */
-/**************************************************************************/
-static void
-stop_cards(void)
-{
-       hysdn_card *card;
-
-       card = card_root;       /* first in chain */
-       while (card) {
-               if (card->stopcard)
-                       card->stopcard(card);
-               card = card->next;      /* remove card from chain */
-       }                       /* while card */
-}                              /* stop_cards */
+static hysdn_card *card_last = NULL;   /* pointer to first card */
 
 
 /****************************************************************************/
@@ -191,31 +75,138 @@ hysdn_getrev(const char *revision)
 /* and the module is added to the list in /proc/modules, otherwise an error */
 /* is assumed and the module will not be kept in memory.                    */
 /****************************************************************************/
+
+static int __devinit hysdn_pci_init_one(struct pci_dev *akt_pcidev,
+                                       const struct pci_device_id *ent)
+{
+       hysdn_card *card;
+       int rc;
+
+       rc = pci_enable_device(akt_pcidev);
+       if (rc)
+               return rc;
+
+       if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) {
+               printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
+               rc = -ENOMEM;
+               goto err_out;
+       }
+       card->myid = cardmax;   /* set own id */
+       card->bus = akt_pcidev->bus->number;
+       card->devfn = akt_pcidev->devfn;        /* slot + function */
+       card->subsysid = akt_pcidev->subsystem_device;
+       card->irq = akt_pcidev->irq;
+       card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE);
+       card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE);
+       card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE);
+       card->brdtype = BD_NONE;        /* unknown */
+       card->debug_flags = DEF_DEB_FLAGS;      /* set default debug */
+       card->faxchans = 0;     /* default no fax channels */
+       card->bchans = 2;       /* and 2 b-channels */
+       card->brdtype = ent->driver_data;
+
+       if (ergo_inithardware(card)) {
+               printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase);
+               rc = -EBUSY;
+               goto err_out_card;
+       }
+
+       cardmax++;
+       card->next = NULL;      /*end of chain */
+       if (card_last)
+               card_last->next = card;         /* pointer to next card */
+       else
+               card_root = card;
+       card_last = card;       /* new chain end */
+
+       pci_set_drvdata(akt_pcidev, card);
+       return 0;
+
+err_out_card:
+       kfree(card);
+err_out:
+       pci_disable_device(akt_pcidev);
+       return rc;
+}
+
+static void __devexit hysdn_pci_remove_one(struct pci_dev *akt_pcidev)
+{
+       hysdn_card *card = pci_get_drvdata(akt_pcidev);
+
+       pci_set_drvdata(akt_pcidev, NULL);
+
+       if (card->stopcard)
+               card->stopcard(card);
+
+#ifdef CONFIG_HYSDN_CAPI
+       hycapi_capi_release(card);
+#endif
+
+       if (card->releasehardware)
+               card->releasehardware(card);   /* free all hardware resources */
+
+       if (card == card_root) {
+               card_root = card_root->next;
+               if (!card_root)
+                       card_last = NULL;
+       } else {
+               hysdn_card *tmp = card_root;
+               while (tmp) {
+                       if (tmp->next == card)
+                               tmp->next = card->next;
+                       card_last = tmp;
+                       tmp = tmp->next;
+               }
+       }
+
+       kfree(card);
+       pci_disable_device(akt_pcidev);
+}
+
+static struct pci_driver hysdn_pci_driver = {
+       .name           = "hysdn",
+       .id_table       = hysdn_pci_tbl,
+       .probe          = hysdn_pci_init_one,
+       .remove         = __devexit_p(hysdn_pci_remove_one),
+};
+
+static int hysdn_have_procfs;
+
 static int __init
 hysdn_init(void)
 {
        char tmp[50];
+       int rc;
 
        strcpy(tmp, hysdn_init_revision);
        printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp));
        strcpy(tmp, hysdn_net_revision);
        printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp));
-       search_cards();
+
+       rc = pci_register_driver(&hysdn_pci_driver);
+       if (rc)
+               return rc;
+
        printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax);
 
-       if (hysdn_procconf_init()) {
-               free_resources();       /* proc file_sys not created */
-               return (-1);
-       }
+       if (!hysdn_procconf_init())
+               hysdn_have_procfs = 1;
+
 #ifdef CONFIG_HYSDN_CAPI
        if(cardmax > 0) {
                if(hycapi_init()) {
                        printk(KERN_ERR "HYCAPI: init failed\n");
-                       return(-1);
+
+                       if (hysdn_have_procfs)
+                               hysdn_procconf_release();
+
+                       pci_unregister_driver(&hysdn_pci_driver);
+                       return -ESPIPE;
                }
        }
 #endif /* CONFIG_HYSDN_CAPI */
-       return (0);             /* no error */
+
+       return 0;               /* no error */
 }                              /* init_module */
 
 
@@ -230,20 +221,15 @@ hysdn_init(void)
 static void __exit
 hysdn_exit(void)
 {
+       if (hysdn_have_procfs)
+               hysdn_procconf_release();
+
+       pci_unregister_driver(&hysdn_pci_driver);
+
 #ifdef CONFIG_HYSDN_CAPI
-       hysdn_card *card;
-#endif /* CONFIG_HYSDN_CAPI */
-       stop_cards();
-#ifdef CONFIG_HYSDN_CAPI
-       card = card_root;       /* first in chain */
-       while (card) {
-               hycapi_capi_release(card);
-               card = card->next;      /* remove card from chain */
-       }                       /* while card */
        hycapi_cleanup();
 #endif /* CONFIG_HYSDN_CAPI */
-       hysdn_procconf_release();
-       free_resources();
+
        printk(KERN_NOTICE "HYSDN: module unloaded\n");
 }                              /* cleanup_module */
 
index 64fbc9759a30757426de0270b0afa25d5c31ea94..c65d203a846d6e91dc5689e0bee82311474468a2 100644 (file)
@@ -143,7 +143,7 @@ void mmc_remove_host(struct mmc_host *host)
 
        device_del(&host->class_dev);
 
-       led_trigger_unregister(host->led);
+       led_trigger_unregister_simple(host->led);
 
        spin_lock(&mmc_host_lock);
        idr_remove(&mmc_host_idr, host->index);
index d68accea380bb3adcf40aaeece00d607d006d4bc..78ed633ceb829e121161a8a230a1350d9de06017 100644 (file)
@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
                REG_RD(bp, BNX2_HC_COMMAND);
        }
 
-       if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
+       if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
                bnx2_tx_int(bp);
 
-       if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
+       if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
                work_done += bnx2_rx_int(bp, budget - work_done);
 
        return work_done;
@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
 {
        struct bnx2 *bp = container_of(napi, struct bnx2, napi);
        int work_done = 0;
+       struct status_block *sblk = bp->status_blk;
 
        while (1) {
                work_done = bnx2_poll_work(bp, work_done, budget);
@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
                if (unlikely(work_done >= budget))
                        break;
 
+               /* bp->last_status_idx is used below to tell the hw how
+                * much work has been processed, so we must read it before
+                * checking for more work.
+                */
+               bp->last_status_idx = sblk->status_idx;
+               rmb();
                if (likely(!bnx2_has_work(bp))) {
-                       bp->last_status_idx = bp->status_blk->status_idx;
-                       rmb();
-
                        netif_rx_complete(bp->dev, napi);
                        if (likely(bp->flags & USING_MSI_FLAG)) {
                                REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                                       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
                                       bp->last_status_idx);
-                               return 0;
+                               break;
                        }
                        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
index e795c33b982de885e0ab290d3d325ede7b06b114..30b1cca8144ce360b23db4106983fb9c1cf45822 100644 (file)
@@ -3576,7 +3576,7 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget)
        if (sblk->idx[0].tx_consumer != tp->tx_cons) {
                tg3_tx(tp);
                if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
-                       return 0;
+                       return work_done;
        }
 
        /* run RX thread, within the bounds set by NAPI.
@@ -3593,6 +3593,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 {
        struct tg3 *tp = container_of(napi, struct tg3, napi);
        int work_done = 0;
+       struct tg3_hw_status *sblk = tp->hw_status;
 
        while (1) {
                work_done = tg3_poll_work(tp, work_done, budget);
@@ -3603,15 +3604,17 @@ static int tg3_poll(struct napi_struct *napi, int budget)
                if (unlikely(work_done >= budget))
                        break;
 
-               if (likely(!tg3_has_work(tp))) {
-                       struct tg3_hw_status *sblk = tp->hw_status;
-
-                       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
-                               tp->last_tag = sblk->status_tag;
-                               rmb();
-                       } else
-                               sblk->status &= ~SD_STATUS_UPDATED;
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+                       /* tp->last_tag is used in tg3_restart_ints() below
+                        * to tell the hw how much work has been processed,
+                        * so we must read it before checking for more work.
+                        */
+                       tp->last_tag = sblk->status_tag;
+                       rmb();
+               } else
+                       sblk->status &= ~SD_STATUS_UPDATED;
 
+               if (likely(!tg3_has_work(tp))) {
                        netif_rx_complete(tp->dev, napi);
                        tg3_restart_ints(tp);
                        break;
@@ -3621,9 +3624,10 @@ static int tg3_poll(struct napi_struct *napi, int budget)
        return work_done;
 
 tx_recovery:
+       /* work_done is guaranteed to be less than budget. */
        netif_rx_complete(tp->dev, napi);
        schedule_work(&tp->reset_task);
-       return 0;
+       return work_done;
 }
 
 static void tg3_irq_quiesce(struct tg3 *tp)
index aeda52682446cc475770b918e82cdb3ae4a0431c..d427daeef511bd1bfaddf153b9c1c363da4e9cf3 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/interrupt.h>
+#include <linux/log2.h>
 #include <asm/ccwdev.h>
 #include <linux/workqueue.h>
 #include <asm/debug.h>
@@ -456,7 +457,7 @@ dasd_free_chunk(struct list_head *chunk_list, void *mem)
 static inline int
 dasd_check_blocksize(int bsize)
 {
-       if (bsize < 512 || bsize > 4096 || (bsize & (bsize - 1)) != 0)
+       if (bsize < 512 || bsize > 4096 || !is_power_of_2(bsize))
                return -EMEDIUMTYPE;
        return 0;
 }
index 0fbacc8b106345cd6255fc6d46a94775bbb27963..f231bc21b1cafd3465dcf97cc3c4f6618b5b804c 100644 (file)
@@ -230,7 +230,7 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio)
                }
        }
        set_bit(BIO_UPTODATE, &bio->bi_flags);
-       bio_end_io(bio, 0);
+       bio_endio(bio, 0);
        return 0;
 fail:
        bio_io_error(bio);
index 6000bdee4082830b87e978d0b5538e2765ff2c98..0e1f35c9ed9d4e0be6dc928d0d3bf69182799149 100644 (file)
@@ -667,6 +667,9 @@ raw3215_probe (struct ccw_device *cdev)
        struct raw3215_info *raw;
        int line;
 
+       /* Console is special. */
+       if (raw3215[0] && (cdev->dev.driver_data == raw3215[0]))
+               return 0;
        raw = kmalloc(sizeof(struct raw3215_info) +
                      RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA);
        if (raw == NULL)
index fd3479119eb4e1bc568a4f5d5b5e428bc6a5d8d8..0b040557db02d5ee67ad91c4179f4179d14d6a54 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/ebcdic.h>
 
 #include "raw3270.h"
+#include "tty3270.h"
 #include "ctrlchar.h"
 
 #define CON3270_OUTPUT_BUFFER_SIZE 1024
@@ -507,8 +508,6 @@ con3270_write(struct console *co, const char *str, unsigned int count)
        spin_unlock_irqrestore(&cp->view.lock,flags);
 }
 
-extern struct tty_driver *tty3270_driver;
-
 static struct tty_driver *
 con3270_device(struct console *c, int *index)
 {
index fa62e69440578375fb8028721a6e2c8c0a52ad96..25629b92dec362ef2e22c4343ca383e0976e49c8 100644 (file)
@@ -93,6 +93,7 @@ static volatile enum sclp_mask_state_t {
 #define SCLP_RETRY_INTERVAL    30
 
 static void sclp_process_queue(void);
+static void __sclp_make_read_req(void);
 static int sclp_init_mask(int calculate);
 static int sclp_init(void);
 
@@ -115,7 +116,6 @@ sclp_service_call(sclp_cmdw_t command, void *sccb)
        return 0;
 }
 
-static inline void __sclp_make_read_req(void);
 
 static void
 __sclp_queue_read_req(void)
@@ -318,8 +318,7 @@ sclp_read_cb(struct sclp_req *req, void *data)
 }
 
 /* Prepare read event data request. Called while sclp_lock is locked. */
-static inline void
-__sclp_make_read_req(void)
+static void __sclp_make_read_req(void)
 {
        struct sccb_header *sccb;
 
index 9f244c591eeb320c3533368f84a53595d6c5ae4c..da25f8e24152b7da94a52c79eff4903fabe17eae 100644 (file)
@@ -708,16 +708,22 @@ static void tape_3590_med_state_set(struct tape_device *device,
 
        c_info = &TAPE_3590_CRYPT_INFO(device);
 
-       if (sense->masst == MSENSE_UNASSOCIATED) {
+       DBF_EVENT(6, "medium state: %x:%x\n", sense->macst, sense->masst);
+       switch (sense->macst) {
+       case 0x04:
+       case 0x05:
+       case 0x06:
                tape_med_state_set(device, MS_UNLOADED);
                TAPE_3590_CRYPT_INFO(device).medium_status = 0;
                return;
-       }
-       if (sense->masst != MSENSE_ASSOCIATED_MOUNT) {
-               PRINT_ERR("Unknown medium state: %x\n", sense->masst);
+       case 0x08:
+       case 0x09:
+               tape_med_state_set(device, MS_LOADED);
+               break;
+       default:
+               tape_med_state_set(device, MS_UNKNOWN);
                return;
        }
-       tape_med_state_set(device, MS_LOADED);
        c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK;
        if (sense->flags & MSENSE_CRYPT_MASK) {
                PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags);
@@ -835,15 +841,17 @@ tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb)
                /* Probably result of halt ssch */
                return TAPE_IO_PENDING;
        else if (irb->scsw.dstat == 0x85)
-               /* Device Ready -> check medium state */
-               tape_3590_schedule_work(device, TO_MSEN);
-       else if (irb->scsw.dstat & DEV_STAT_ATTENTION)
+               /* Device Ready */
+               DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id);
+       else if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
                tape_3590_schedule_work(device, TO_READ_ATTMSG);
-       else {
+       else {
                DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
                PRINT_WARN("Unsolicited IRQ (Device End) caught.\n");
                tape_dump_sense(device, NULL, irb);
        }
+       /* check medium state */
+       tape_3590_schedule_work(device, TO_MSEN);
        return TAPE_IO_SUCCESS;
 }
 
index bc33068b9ce2b3556bdc02ee0878ded5fb5233cc..70b1980a08b66380c075355d81101c90a784032f 100644 (file)
@@ -25,8 +25,8 @@
 #include <asm/ebcdic.h>
 #include <asm/uaccess.h>
 
-
 #include "raw3270.h"
+#include "tty3270.h"
 #include "keyboard.h"
 
 #define TTY3270_CHAR_BUF_SIZE 256
@@ -1338,8 +1338,11 @@ tty3270_getpar(struct tty3270 *tp, int ix)
 static void
 tty3270_goto_xy(struct tty3270 *tp, int cx, int cy)
 {
-       tp->cx = min_t(int, tp->view.cols - 1, max_t(int, 0, cx));
-       cy = min_t(int, tp->view.rows - 3, max_t(int, 0, cy));
+       int max_cx = max(0, cx);
+       int max_cy = max(0, cy);
+
+       tp->cx = min_t(int, tp->view.cols - 1, max_cx);
+       cy = min_t(int, tp->view.rows - 3, max_cy);
        if (cy != tp->cy) {
                tty3270_convert_line(tp, tp->cy);
                tp->cy = cy;
diff --git a/drivers/s390/char/tty3270.h b/drivers/s390/char/tty3270.h
new file mode 100644 (file)
index 0000000..799da57
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  drivers/s390/char/tty3270.h
+ *
+ *    Copyright IBM Corp. 2007
+ *
+ */
+
+#ifndef __DRIVERS_S390_CHAR_TTY3270_H
+#define __DRIVERS_S390_CHAR_TTY3270_H
+
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+
+extern struct tty_driver *tty3270_driver;
+
+#endif /* __DRIVERS_S390_CHAR_TTY3270_H */
index 680b9b58b80ea0ce6479b8085cdf9b70767289fd..6f40facb1c4d7e3b8f89c49e254bf22dcc959189 100644 (file)
@@ -66,8 +66,8 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout,
                "0:     la      %0,0\n"
                "1:\n"
                EX_TABLE(0b,1b)
-               : "=d" (err) : "d"(__func), "d"(__timeout),
-                 "d"(__cmdp), "d"(__cmdl), "0" (-EINVAL) : "1", "cc");
+               : "+d" (err) : "d"(__func), "d"(__timeout),
+                 "d"(__cmdp), "d"(__cmdl) : "1", "cc");
        return err;
 }
 
index 3712ede167235fcecd2ceeab4b0b9faac7f74461..7073daf77981005e7edfe0c6f59c08b2a3251212 100644 (file)
@@ -141,15 +141,16 @@ static int memcpy_real(void *dest, unsigned long src, size_t count)
 
        if (count == 0)
                return 0;
-       flags = __raw_local_irq_stnsm(0xf8); /* switch to real mode */
+       flags = __raw_local_irq_stnsm(0xf8UL); /* switch to real mode */
        asm volatile (
                "0:     mvcle   %1,%2,0x0\n"
                "1:     jo      0b\n"
                "       lhi     %0,0x0\n"
                "2:\n"
                EX_TABLE(1b,2b)
-               : "+d" (rc)
-               : "d" (_dest), "d" (_src), "d" (_len1), "d" (_len2)
+               : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1),
+                 "+d" (_len2), "=m" (*((long*)dest))
+               : "m" (*((long*)src))
                : "cc", "memory");
        __raw_local_irq_ssm(flags);
 
index b0a18f5176aa3e07ecde788944f4061d1f0974d6..9c3b9ea1e66f9de6cd6c1f11c128822587523762 100644 (file)
@@ -152,16 +152,24 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
        return 0;
 }
 
-/*
- * try to add a new ccwgroup device for one driver
- * argc and argv[] are a list of bus_id's of devices
- * belonging to the driver.
+/**
+ * ccwgroup_create() - create and register a ccw group device
+ * @root: parent device for the new device
+ * @creator_id: identifier of creating driver
+ * @cdrv: ccw driver of slave devices
+ * @argc: number of slave devices
+ * @argv: bus ids of slave devices
+ *
+ * Create and register a new ccw group device as a child of @root. Slave
+ * devices are obtained from the list of bus ids given in @argv[] and must all
+ * belong to @cdrv.
+ * Returns:
+ *  %0 on success and an error code on failure.
+ * Context:
+ *  non-atomic
  */
-int
-ccwgroup_create(struct device *root,
-               unsigned int creator_id,
-               struct ccw_driver *cdrv,
-               int argc, char *argv[])
+int ccwgroup_create(struct device *root, unsigned int creator_id,
+                   struct ccw_driver *cdrv, int argc, char *argv[])
 {
        struct ccwgroup_device *gdev;
        int i;
@@ -390,8 +398,13 @@ static struct bus_type ccwgroup_bus_type = {
        .remove = ccwgroup_remove,
 };
 
-int
-ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
+/**
+ * ccwgroup_driver_register() - register a ccw group driver
+ * @cdriver: driver to be registered
+ *
+ * This function is mainly a wrapper around driver_register().
+ */
+int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
 {
        /* register our new driver with the core */
        cdriver->driver.bus = &ccwgroup_bus_type;
@@ -406,8 +419,13 @@ __ccwgroup_match_all(struct device *dev, void *data)
        return 1;
 }
 
-void
-ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
+/**
+ * ccwgroup_driver_unregister() - deregister a ccw group driver
+ * @cdriver: driver to be deregistered
+ *
+ * This function is mainly a wrapper around driver_unregister().
+ */
+void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver)
 {
        struct device *dev;
 
@@ -427,8 +445,16 @@ ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
        driver_unregister(&cdriver->driver);
 }
 
-int
-ccwgroup_probe_ccwdev(struct ccw_device *cdev)
+/**
+ * ccwgroup_probe_ccwdev() - probe function for slave devices
+ * @cdev: ccw device to be probed
+ *
+ * This is a dummy probe function for ccw devices that are slave devices in
+ * a ccw group device.
+ * Returns:
+ *  always %0
+ */
+int ccwgroup_probe_ccwdev(struct ccw_device *cdev)
 {
        return 0;
 }
@@ -452,8 +478,15 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
        return NULL;
 }
 
-void
-ccwgroup_remove_ccwdev(struct ccw_device *cdev)
+/**
+ * ccwgroup_remove_ccwdev() - remove function for slave devices
+ * @cdev: ccw device to be removed
+ *
+ * This is a remove function for ccw devices that are slave devices in a ccw
+ * group device. It sets the ccw device offline and also deregisters the
+ * embedding ccw group device.
+ */
+void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
 {
        struct ccwgroup_device *gdev;
 
index 920dd71e643457fbf541842f07e380e5a80cd407..42c1f4659adb41d605557f7cb254937e15781d08 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/jiffies.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 #include <asm/chpid.h>
 #include <asm/sclp.h>
 
@@ -55,7 +55,7 @@ static wait_queue_head_t cfg_wait_queue;
 /* Return channel_path struct for given chpid. */
 static inline struct channel_path *chpid_to_chp(struct chp_id chpid)
 {
-       return css[chpid.cssid]->chps[chpid.id];
+       return channel_subsystems[chpid.cssid]->chps[chpid.id];
 }
 
 /* Set vary state for given chpid. */
@@ -86,7 +86,7 @@ u8 chp_get_sch_opm(struct subchannel *sch)
 
        opm = 0;
        chp_id_init(&chpid);
-       for (i=0; i < 8; i++) {
+       for (i = 0; i < 8; i++) {
                opm <<= 1;
                chpid.id = sch->schib.pmcw.chpid[i];
                if (chp_get_status(chpid) != 0)
@@ -118,7 +118,7 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
 
        sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid,
                chpid.id);
-       CIO_TRACE_EVENT( 2, dbf_text);
+       CIO_TRACE_EVENT(2, dbf_text);
 
        status = chp_get_status(chpid);
        if (!on && !status) {
@@ -140,9 +140,11 @@ static ssize_t chp_measurement_chars_read(struct kobject *kobj,
                                          char *buf, loff_t off, size_t count)
 {
        struct channel_path *chp;
+       struct device *device;
        unsigned int size;
 
-       chp = to_channelpath(container_of(kobj, struct device, kobj));
+       device = container_of(kobj, struct device, kobj);
+       chp = to_channelpath(device);
        if (!chp->cmg_chars)
                return 0;
 
@@ -193,9 +195,11 @@ static ssize_t chp_measurement_read(struct kobject *kobj,
 {
        struct channel_path *chp;
        struct channel_subsystem *css;
+       struct device *device;
        unsigned int size;
 
-       chp = to_channelpath(container_of(kobj, struct device, kobj));
+       device = container_of(kobj, struct device, kobj);
+       chp = to_channelpath(device);
        css = to_css(chp->dev.parent);
 
        size = sizeof(struct cmg_entry);
@@ -353,7 +357,7 @@ static ssize_t chp_shared_show(struct device *dev,
 
 static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL);
 
-static struct attribute * chp_attrs[] = {
+static struct attribute *chp_attrs[] = {
        &dev_attr_status.attr,
        &dev_attr_configure.attr,
        &dev_attr_type.attr,
@@ -395,7 +399,7 @@ int chp_new(struct chp_id chpid)
        /* fill in status, etc. */
        chp->chpid = chpid;
        chp->state = 1;
-       chp->dev.parent = &css[chpid.cssid]->device;
+       chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
        chp->dev.release = chp_release;
        snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid,
                 chpid.id);
@@ -430,18 +434,18 @@ int chp_new(struct chp_id chpid)
                device_unregister(&chp->dev);
                goto out_free;
        }
-       mutex_lock(&css[chpid.cssid]->mutex);
-       if (css[chpid.cssid]->cm_enabled) {
+       mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
+       if (channel_subsystems[chpid.cssid]->cm_enabled) {
                ret = chp_add_cmg_attr(chp);
                if (ret) {
                        sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
                        device_unregister(&chp->dev);
-                       mutex_unlock(&css[chpid.cssid]->mutex);
+                       mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
                        goto out_free;
                }
        }
-       css[chpid.cssid]->chps[chpid.id] = chp;
-       mutex_unlock(&css[chpid.cssid]->mutex);
+       channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
+       mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
        return ret;
 out_free:
        kfree(chp);
index f2708d65be5a1d8bb14cedb874b950f21859f5f8..46905345159e6705036d7d20030de558a534b60d 100644 (file)
@@ -619,6 +619,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        sch->schib.pmcw.ena = 0;
        if ((sch->lpm & (sch->lpm - 1)) != 0)
                sch->schib.pmcw.mp = 1; /* multipath mode */
+       /* clean up possible residual cmf stuff */
+       sch->schib.pmcw.mme = 0;
+       sch->schib.pmcw.mbfc = 0;
+       sch->schib.pmcw.mbi = 0;
+       sch->schib.mba = 0;
        return 0;
 out:
        if (!cio_is_console(schid))
index 34a796913b0604a787630beae9be87952982a8dc..b960f66843e4919e1645806258368763fcaeec84 100644 (file)
@@ -45,7 +45,8 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-/* parameter to enable cmf during boot, possible uses are:
+/*
+ * parameter to enable cmf during boot, possible uses are:
  *  "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be
  *               used on any subchannel
  *  "s390cmf=<num>" -- enable cmf and allocate enough memory to measure
@@ -73,18 +74,20 @@ enum cmb_index {
  * enum cmb_format - types of supported measurement block formats
  *
  * @CMF_BASIC:      traditional channel measurement blocks supported
- *                 by all machines that we run on
+ *                 by all machines that we run on
  * @CMF_EXTENDED:   improved format that was introduced with the z990
- *                 machine
- * @CMF_AUTODETECT: default: use extended format when running on a z990
- *                  or later machine, otherwise fall back to basic format
- **/
+ *                 machine
+ * @CMF_AUTODETECT: default: use extended format when running on a machine
+ *                 supporting extended format, otherwise fall back to
+ *                 basic format
+ */
 enum cmb_format {
        CMF_BASIC,
        CMF_EXTENDED,
        CMF_AUTODETECT = -1,
 };
-/**
+
+/*
  * format - actual format for all measurement blocks
  *
  * The format module parameter can be set to a value of 0 (zero)
@@ -105,20 +108,21 @@ module_param(format, bool, 0444);
  *             either with the help of a special pool or with kmalloc
  * @free:      free memory allocated with @alloc
  * @set:       enable or disable measurement
+ * @read:      read a measurement entry at an index
  * @readall:   read a measurement block in a common format
  * @reset:     clear the data in the associated measurement block and
  *             reset its time stamp
  * @align:     align an allocated block so that the hardware can use it
  */
 struct cmb_operations {
-       int (*alloc)  (struct ccw_device*);
-       void(*free)   (struct ccw_device*);
-       int (*set)    (struct ccw_device*, u32);
-       u64 (*read)   (struct ccw_device*, int);
-       int (*readall)(struct ccw_device*, struct cmbdata *);
-       void (*reset) (struct ccw_device*);
-       void * (*align) (void *);
-
+       int  (*alloc)  (struct ccw_device *);
+       void (*free)   (struct ccw_device *);
+       int  (*set)    (struct ccw_device *, u32);
+       u64  (*read)   (struct ccw_device *, int);
+       int  (*readall)(struct ccw_device *, struct cmbdata *);
+       void (*reset)  (struct ccw_device *);
+       void *(*align) (void *);
+/* private: */
        struct attribute_group *attr_group;
 };
 static struct cmb_operations *cmbops;
@@ -130,9 +134,11 @@ struct cmb_data {
        unsigned long long last_update;  /* when last_block was updated */
 };
 
-/* our user interface is designed in terms of nanoseconds,
+/*
+ * Our user interface is designed in terms of nanoseconds,
  * while the hardware measures total times in its own
- * unit.*/
+ * unit.
+ */
 static inline u64 time_to_nsec(u32 value)
 {
        return ((u64)value) * 128000ull;
@@ -159,12 +165,13 @@ static inline u64 time_to_avg_nsec(u32 value, u32 count)
        return ret;
 }
 
-/* activate or deactivate the channel monitor. When area is NULL,
+/*
+ * Activate or deactivate the channel monitor. When area is NULL,
  * the monitor is deactivated. The channel monitor needs to
  * be active in order to measure subchannels, which also need
- * to be enabled. */
-static inline void
-cmf_activate(void *area, unsigned int onoff)
+ * to be enabled.
+ */
+static inline void cmf_activate(void *area, unsigned int onoff)
 {
        register void * __gpr2 asm("2");
        register long __gpr1 asm("1");
@@ -175,8 +182,8 @@ cmf_activate(void *area, unsigned int onoff)
        asm("schm" : : "d" (__gpr2), "d" (__gpr1) );
 }
 
-static int
-set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
+static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
+                    unsigned long address)
 {
        int ret;
        int retry;
@@ -466,6 +473,7 @@ static void cmf_generic_reset(struct ccw_device *cdev)
  *
  * @mem:       pointer to CMBs (only in basic measurement mode)
  * @list:      contains a linked list of all subchannels
+ * @num_channels: number of channels to be measured
  * @lock:      protect concurrent access to @mem and @list
  */
 struct cmb_area {
@@ -481,28 +489,36 @@ static struct cmb_area cmb_area = {
        .num_channels  = 1024,
 };
 
-\f
 /* ****** old style CMB handling ********/
 
-/** int maxchannels
- *
+/*
  * Basic channel measurement blocks are allocated in one contiguous
  * block of memory, which can not be moved as long as any channel
  * is active. Therefore, a maximum number of subchannels needs to
  * be defined somewhere. This is a module parameter, defaulting to
  * a resonable value of 1024, or 32 kb of memory.
  * Current kernels don't allow kmalloc with more than 128kb, so the
- * maximum is 4096
+ * maximum is 4096.
  */
 
 module_param_named(maxchannels, cmb_area.num_channels, uint, 0444);
 
 /**
  * struct cmb - basic channel measurement block
+ * @ssch_rsch_count: number of ssch and rsch
+ * @sample_count: number of samples
+ * @device_connect_time: time of device connect
+ * @function_pending_time: time of function pending
+ * @device_disconnect_time: time of device disconnect
+ * @control_unit_queuing_time: time of control unit queuing
+ * @device_active_only_time: time of device active only
+ * @reserved: unused in basic measurement mode
+ *
+ * The measurement block as used by the hardware. The fields are described
+ * further in z/Architecture Principles of Operation, chapter 17.
  *
- * cmb as used by the hardware the fields are described in z/Architecture
- * Principles of Operation, chapter 17.
- * The area to be a contiguous array and may not be reallocated or freed.
+ * The cmb area made up from these blocks must be a contiguous array and may
+ * not be reallocated or freed.
  * Only one cmb area can be present in the system.
  */
 struct cmb {
@@ -516,8 +532,9 @@ struct cmb {
        u32 reserved[2];
 };
 
-/* insert a single device into the cmb_area list
- * called with cmb_area.lock held from alloc_cmb
+/*
+ * Insert a single device into the cmb_area list.
+ * Called with cmb_area.lock held from alloc_cmb.
  */
 static int alloc_cmb_single(struct ccw_device *cdev,
                            struct cmb_data *cmb_data)
@@ -532,9 +549,11 @@ static int alloc_cmb_single(struct ccw_device *cdev,
                goto out;
        }
 
-       /* find first unused cmb in cmb_area.mem.
-        * this is a little tricky: cmb_area.list
-        * remains sorted by ->cmb->hw_data pointers */
+       /*
+        * Find first unused cmb in cmb_area.mem.
+        * This is a little tricky: cmb_area.list
+        * remains sorted by ->cmb->hw_data pointers.
+        */
        cmb = cmb_area.mem;
        list_for_each_entry(node, &cmb_area.list, cmb_list) {
                struct cmb_data *data;
@@ -558,8 +577,7 @@ out:
        return ret;
 }
 
-static int
-alloc_cmb (struct ccw_device *cdev)
+static int alloc_cmb(struct ccw_device *cdev)
 {
        int ret;
        struct cmb *mem;
@@ -670,7 +688,7 @@ static int set_cmb(struct ccw_device *cdev, u32 mme)
        return set_schib_wait(cdev, mme, 0, offset);
 }
 
-static u64 read_cmb (struct ccw_device *cdev, int index)
+static u64 read_cmb(struct ccw_device *cdev, int index)
 {
        struct cmb *cmb;
        u32 val;
@@ -720,7 +738,7 @@ out:
        return ret;
 }
 
-static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
+static int readall_cmb(struct ccw_device *cdev, struct cmbdata *data)
 {
        struct cmb *cmb;
        struct cmb_data *cmb_data;
@@ -793,14 +811,25 @@ static struct cmb_operations cmbops_basic = {
        .align      = align_cmb,
        .attr_group = &cmf_attr_group,
 };
-\f
+
 /* ******** extended cmb handling ********/
 
 /**
  * struct cmbe - extended channel measurement block
+ * @ssch_rsch_count: number of ssch and rsch
+ * @sample_count: number of samples
+ * @device_connect_time: time of device connect
+ * @function_pending_time: time of function pending
+ * @device_disconnect_time: time of device disconnect
+ * @control_unit_queuing_time: time of control unit queuing
+ * @device_active_only_time: time of device active only
+ * @device_busy_time: time of device busy
+ * @initial_command_response_time: initial command response time
+ * @reserved: unused
  *
- * cmb as used by the hardware, may be in any 64 bit physical location,
- * the fields are described in z/Architecture Principles of Operation,
+ * The measurement block as used by the hardware. May be in any 64 bit physical
+ * location.
+ * The fields are described further in z/Architecture Principles of Operation,
  * third edition, chapter 17.
  */
 struct cmbe {
@@ -816,10 +845,12 @@ struct cmbe {
        u32 reserved[7];
 };
 
-/* kmalloc only guarantees 8 byte alignment, but we need cmbe
+/*
+ * kmalloc only guarantees 8 byte alignment, but we need cmbe
  * pointers to be naturally aligned. Make sure to allocate
- * enough space for two cmbes */
-static inline struct cmbe* cmbe_align(struct cmbe *c)
+ * enough space for two cmbes.
+ */
+static inline struct cmbe *cmbe_align(struct cmbe *c)
 {
        unsigned long addr;
        addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) &
@@ -827,7 +858,7 @@ static inline struct cmbe* cmbe_align(struct cmbe *c)
        return (struct cmbe*)addr;
 }
 
-static int alloc_cmbe (struct ccw_device *cdev)
+static int alloc_cmbe(struct ccw_device *cdev)
 {
        struct cmbe *cmbe;
        struct cmb_data *cmb_data;
@@ -873,7 +904,7 @@ out_free:
        return ret;
 }
 
-static void free_cmbe (struct ccw_device *cdev)
+static void free_cmbe(struct ccw_device *cdev)
 {
        struct cmb_data *cmb_data;
 
@@ -912,7 +943,7 @@ static int set_cmbe(struct ccw_device *cdev, u32 mme)
 }
 
 
-static u64 read_cmbe (struct ccw_device *cdev, int index)
+static u64 read_cmbe(struct ccw_device *cdev, int index)
 {
        struct cmbe *cmb;
        struct cmb_data *cmb_data;
@@ -970,7 +1001,7 @@ out:
        return ret;
 }
 
-static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
+static int readall_cmbe(struct ccw_device *cdev, struct cmbdata *data)
 {
        struct cmbe *cmb;
        struct cmb_data *cmb_data;
@@ -1047,17 +1078,16 @@ static struct cmb_operations cmbops_extended = {
        .align      = align_cmbe,
        .attr_group = &cmf_attr_group_ext,
 };
-\f
 
-static ssize_t
-cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx)
+static ssize_t cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx)
 {
        return sprintf(buf, "%lld\n",
                (unsigned long long) cmf_read(to_ccwdev(dev), idx));
 }
 
-static ssize_t
-cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t cmb_show_avg_sample_interval(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
 {
        struct ccw_device *cdev;
        long interval;
@@ -1079,8 +1109,9 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%ld\n", interval);
 }
 
-static ssize_t
-cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t cmb_show_avg_utilization(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
 {
        struct cmbdata data;
        u64 utilization;
@@ -1112,14 +1143,16 @@ cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char
 }
 
 #define cmf_attr(name) \
-static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
-{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
-static DEVICE_ATTR(name, 0444, show_ ## name, NULL);
+static ssize_t show_##name(struct device *dev, \
+                          struct device_attribute *attr, char *buf)    \
+{ return cmb_show_attr((dev), buf, cmb_##name); } \
+static DEVICE_ATTR(name, 0444, show_##name, NULL);
 
 #define cmf_attr_avg(name) \
-static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
-{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
-static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL);
+static ssize_t show_avg_##name(struct device *dev, \
+                              struct device_attribute *attr, char *buf) \
+{ return cmb_show_attr((dev), buf, cmb_##name); } \
+static DEVICE_ATTR(avg_##name, 0444, show_avg_##name, NULL);
 
 cmf_attr(ssch_rsch_count);
 cmf_attr(sample_count);
@@ -1131,7 +1164,8 @@ cmf_attr_avg(device_active_only_time);
 cmf_attr_avg(device_busy_time);
 cmf_attr_avg(initial_command_response_time);
 
-static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, NULL);
+static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval,
+                  NULL);
 static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL);
 
 static struct attribute *cmf_attributes[] = {
@@ -1172,12 +1206,16 @@ static struct attribute_group cmf_attr_group_ext = {
        .attrs = cmf_attributes_ext,
 };
 
-static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t cmb_enable_show(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
 {
        return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0);
 }
 
-static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c)
+static ssize_t cmb_enable_store(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t c)
 {
        struct ccw_device *cdev;
        int ret;
@@ -1202,9 +1240,16 @@ static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *att
 
 DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store);
 
-/* enable_cmf/disable_cmf: module interface for cmf (de)activation */
-int
-enable_cmf(struct ccw_device *cdev)
+/**
+ * enable_cmf() - switch on the channel measurement for a specific device
+ *  @cdev:     The ccw device to be enabled
+ *
+ *  Returns %0 for success or a negative error value.
+ *
+ *  Context:
+ *    non-atomic
+ */
+int enable_cmf(struct ccw_device *cdev)
 {
        int ret;
 
@@ -1225,8 +1270,16 @@ enable_cmf(struct ccw_device *cdev)
        return ret;
 }
 
-int
-disable_cmf(struct ccw_device *cdev)
+/**
+ * disable_cmf() - switch off the channel measurement for a specific device
+ *  @cdev:     The ccw device to be disabled
+ *
+ *  Returns %0 for success or a negative error value.
+ *
+ *  Context:
+ *    non-atomic
+ */
+int disable_cmf(struct ccw_device *cdev)
 {
        int ret;
 
@@ -1238,14 +1291,32 @@ disable_cmf(struct ccw_device *cdev)
        return ret;
 }
 
-u64
-cmf_read(struct ccw_device *cdev, int index)
+/**
+ * cmf_read() - read one value from the current channel measurement block
+ * @cdev:      the channel to be read
+ * @index:     the index of the value to be read
+ *
+ * Returns the value read or %0 if the value cannot be read.
+ *
+ *  Context:
+ *    any
+ */
+u64 cmf_read(struct ccw_device *cdev, int index)
 {
        return cmbops->read(cdev, index);
 }
 
-int
-cmf_readall(struct ccw_device *cdev, struct cmbdata *data)
+/**
+ * cmf_readall() - read the current channel measurement block
+ * @cdev:      the channel to be read
+ * @data:      a pointer to a data block that will be filled
+ *
+ * Returns %0 on success, a negative error value otherwise.
+ *
+ *  Context:
+ *    any
+ */
+int cmf_readall(struct ccw_device *cdev, struct cmbdata *data)
 {
        return cmbops->readall(cdev, data);
 }
@@ -1257,15 +1328,16 @@ int cmf_reenable(struct ccw_device *cdev)
        return cmbops->set(cdev, 2);
 }
 
-static int __init
-init_cmf(void)
+static int __init init_cmf(void)
 {
        char *format_string;
        char *detect_string = "parameter";
 
-       /* We cannot really autoprobe this. If the user did not give a parameter,
-          see if we are running on z990 or up, otherwise fall back to basic mode. */
-
+       /*
+        * If the user did not give a parameter, see if we are running on a
+        * machine supporting extended measurement blocks, otherwise fall back
+        * to basic mode.
+        */
        if (format == CMF_AUTODETECT) {
                if (!css_characteristics_avail ||
                    !css_general_characteristics.ext_mb) {
@@ -1284,7 +1356,7 @@ init_cmf(void)
                cmbops = &cmbops_basic;
                break;
        case CMF_EXTENDED:
-               format_string = "extended";
+               format_string = "extended";
                cmbops = &cmbops_extended;
                break;
        default:
index 5635e656c1a369b92bd0027c0e8beca261baed3c..5d83dd471461a6b13124348709cca88e191eb6e6 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/list.h>
+#include <linux/reboot.h>
 
 #include "css.h"
 #include "cio.h"
@@ -27,7 +28,7 @@ int css_init_done = 0;
 static int need_reprobe = 0;
 static int max_ssid = 0;
 
-struct channel_subsystem *css[__MAX_CSSID + 1];
+struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1];
 
 int css_characteristics_avail = 0;
 
@@ -177,7 +178,7 @@ static int css_register_subchannel(struct subchannel *sch)
        int ret;
 
        /* Initialize the subchannel structure */
-       sch->dev.parent = &css[0]->device;
+       sch->dev.parent = &channel_subsystems[0]->device;
        sch->dev.bus = &css_bus_type;
        sch->dev.release = &css_subchannel_release;
        sch->dev.groups = subch_attr_groups;
@@ -606,30 +607,55 @@ static int __init setup_css(int nr)
 {
        u32 tod_high;
        int ret;
+       struct channel_subsystem *css;
 
-       memset(css[nr], 0, sizeof(struct channel_subsystem));
-       css[nr]->pseudo_subchannel =
-               kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL);
-       if (!css[nr]->pseudo_subchannel)
+       css = channel_subsystems[nr];
+       memset(css, 0, sizeof(struct channel_subsystem));
+       css->pseudo_subchannel =
+               kzalloc(sizeof(*css->pseudo_subchannel), GFP_KERNEL);
+       if (!css->pseudo_subchannel)
                return -ENOMEM;
-       css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device;
-       css[nr]->pseudo_subchannel->dev.release = css_subchannel_release;
-       sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct");
-       ret = cio_create_sch_lock(css[nr]->pseudo_subchannel);
+       css->pseudo_subchannel->dev.parent = &css->device;
+       css->pseudo_subchannel->dev.release = css_subchannel_release;
+       sprintf(css->pseudo_subchannel->dev.bus_id, "defunct");
+       ret = cio_create_sch_lock(css->pseudo_subchannel);
        if (ret) {
-               kfree(css[nr]->pseudo_subchannel);
+               kfree(css->pseudo_subchannel);
                return ret;
        }
-       mutex_init(&css[nr]->mutex);
-       css[nr]->valid = 1;
-       css[nr]->cssid = nr;
-       sprintf(css[nr]->device.bus_id, "css%x", nr);
-       css[nr]->device.release = channel_subsystem_release;
+       mutex_init(&css->mutex);
+       css->valid = 1;
+       css->cssid = nr;
+       sprintf(css->device.bus_id, "css%x", nr);
+       css->device.release = channel_subsystem_release;
        tod_high = (u32) (get_clock() >> 32);
-       css_generate_pgid(css[nr], tod_high);
+       css_generate_pgid(css, tod_high);
        return 0;
 }
 
+static int css_reboot_event(struct notifier_block *this,
+                           unsigned long event,
+                           void *ptr)
+{
+       int ret, i;
+
+       ret = NOTIFY_DONE;
+       for (i = 0; i <= __MAX_CSSID; i++) {
+               struct channel_subsystem *css;
+
+               css = channel_subsystems[i];
+               if (css->cm_enabled)
+                       if (chsc_secm(css, 0))
+                               ret = NOTIFY_BAD;
+       }
+
+       return ret;
+}
+
+static struct notifier_block css_reboot_notifier = {
+       .notifier_call = css_reboot_event,
+};
+
 /*
  * Now that the driver core is running, we can setup our channel subsystem.
  * The struct subchannel's are created during probing (except for the
@@ -670,51 +696,63 @@ init_channel_subsystem (void)
        }
        /* Setup css structure. */
        for (i = 0; i <= __MAX_CSSID; i++) {
-               css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
-               if (!css[i]) {
+               struct channel_subsystem *css;
+
+               css = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
+               if (!css) {
                        ret = -ENOMEM;
                        goto out_unregister;
                }
+               channel_subsystems[i] = css;
                ret = setup_css(i);
                if (ret)
                        goto out_free;
-               ret = device_register(&css[i]->device);
+               ret = device_register(&css->device);
                if (ret)
                        goto out_free_all;
                if (css_characteristics_avail &&
                    css_chsc_characteristics.secm) {
-                       ret = device_create_file(&css[i]->device,
+                       ret = device_create_file(&css->device,
                                                 &dev_attr_cm_enable);
                        if (ret)
                                goto out_device;
                }
-               ret = device_register(&css[i]->pseudo_subchannel->dev);
+               ret = device_register(&css->pseudo_subchannel->dev);
                if (ret)
                        goto out_file;
        }
+       ret = register_reboot_notifier(&css_reboot_notifier);
+       if (ret)
+               goto out_pseudo;
        css_init_done = 1;
 
        ctl_set_bit(6, 28);
 
        for_each_subchannel(__init_channel_subsystem, NULL);
        return 0;
+out_pseudo:
+       device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
 out_file:
-       device_remove_file(&css[i]->device, &dev_attr_cm_enable);
+       device_remove_file(&channel_subsystems[i]->device,
+                          &dev_attr_cm_enable);
 out_device:
-       device_unregister(&css[i]->device);
+       device_unregister(&channel_subsystems[i]->device);
 out_free_all:
-       kfree(css[i]->pseudo_subchannel->lock);
-       kfree(css[i]->pseudo_subchannel);
+       kfree(channel_subsystems[i]->pseudo_subchannel->lock);
+       kfree(channel_subsystems[i]->pseudo_subchannel);
 out_free:
-       kfree(css[i]);
+       kfree(channel_subsystems[i]);
 out_unregister:
        while (i > 0) {
+               struct channel_subsystem *css;
+
                i--;
-               device_unregister(&css[i]->pseudo_subchannel->dev);
+               css = channel_subsystems[i];
+               device_unregister(&css->pseudo_subchannel->dev);
                if (css_characteristics_avail && css_chsc_characteristics.secm)
-                       device_remove_file(&css[i]->device,
+                       device_remove_file(&css->device,
                                           &dev_attr_cm_enable);
-               device_unregister(&css[i]->device);
+               device_unregister(&css->device);
        }
 out_bus:
        bus_unregister(&css_bus_type);
index 5d65e83ca66e818428ccf003b2f2a4ddc4e5b365..81215ef3243575bfa451218c96be4c0506772310 100644 (file)
@@ -167,7 +167,7 @@ struct channel_subsystem {
 #define to_css(dev) container_of(dev, struct channel_subsystem, device)
 
 extern struct bus_type css_bus_type;
-extern struct channel_subsystem *css[];
+extern struct channel_subsystem *channel_subsystems[];
 
 /* Some helper functions for disconnected state. */
 int device_is_disconnected(struct subchannel *);
@@ -191,6 +191,5 @@ int sch_is_pseudo_sch(struct subchannel *);
 
 extern struct workqueue_struct *slow_path_wq;
 
-int subchannel_add_files (struct device *);
 extern struct attribute_group *subch_attr_groups[];
 #endif
index e44d92eac8e9e8f80fb0f4c57f05b096bb3c494d..39f02b48e4c7dbf46ac7cf8defe35d9cbb257f38 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
 #include <asm/param.h>         /* HZ */
+#include <asm/cmb.h>
 
 #include "cio.h"
 #include "cio_debug.h"
@@ -357,8 +358,18 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
                              cdev->private->dev_id.devno);
 }
 
-int
-ccw_device_set_offline(struct ccw_device *cdev)
+/**
+ * ccw_device_set_offline() - disable a ccw device for I/O
+ * @cdev: target ccw device
+ *
+ * This function calls the driver's set_offline() function for @cdev, if
+ * given, and then disables @cdev.
+ * Returns:
+ *   %0 on success and a negative error value on failure.
+ * Context:
+ *  enabled, ccw device lock not held
+ */
+int ccw_device_set_offline(struct ccw_device *cdev)
 {
        int ret;
 
@@ -396,8 +407,19 @@ ccw_device_set_offline(struct ccw_device *cdev)
        return ret;
 }
 
-int
-ccw_device_set_online(struct ccw_device *cdev)
+/**
+ * ccw_device_set_online() - enable a ccw device for I/O
+ * @cdev: target ccw device
+ *
+ * This function first enables @cdev and then calls the driver's set_online()
+ * function for @cdev, if given. If set_online() returns an error, @cdev is
+ * disabled again.
+ * Returns:
+ *   %0 on success and a negative error value on failure.
+ * Context:
+ *  enabled, ccw device lock not held
+ */
+int ccw_device_set_online(struct ccw_device *cdev)
 {
        int ret;
 
@@ -947,8 +969,7 @@ out:
                wake_up(&ccw_device_init_wq);
 }
 
-void
-ccw_device_call_sch_unregister(struct work_struct *work)
+static void ccw_device_call_sch_unregister(struct work_struct *work)
 {
        struct ccw_device_private *priv;
        struct ccw_device *cdev;
@@ -1101,6 +1122,7 @@ io_subchannel_probe (struct subchannel *sch)
                 * device, e.g. the console.
                 */
                cdev = sch->dev.driver_data;
+               cdev->dev.groups = ccwdev_attr_groups;
                device_initialize(&cdev->dev);
                ccw_device_register(cdev);
                /*
@@ -1326,8 +1348,19 @@ __ccwdev_check_busid(struct device *dev, void *id)
 }
 
 
-struct ccw_device *
-get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
+/**
+ * get_ccwdev_by_busid() - obtain device from a bus id
+ * @cdrv: driver the device is owned by
+ * @bus_id: bus id of the device to be searched
+ *
+ * This function searches all devices owned by @cdrv for a device with a bus
+ * id matching @bus_id.
+ * Returns:
+ *  If a match is found, its reference count of the found device is increased
+ *  and it is returned; else %NULL is returned.
+ */
+struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv,
+                                      const char *bus_id)
 {
        struct device *dev;
        struct device_driver *drv;
@@ -1401,16 +1434,34 @@ ccw_device_remove (struct device *dev)
        return 0;
 }
 
+static void ccw_device_shutdown(struct device *dev)
+{
+       struct ccw_device *cdev;
+
+       cdev = to_ccwdev(dev);
+       if (cdev->drv && cdev->drv->shutdown)
+               cdev->drv->shutdown(cdev);
+       disable_cmf(cdev);
+}
+
 struct bus_type ccw_bus_type = {
        .name   = "ccw",
        .match  = ccw_bus_match,
        .uevent = ccw_uevent,
        .probe  = ccw_device_probe,
        .remove = ccw_device_remove,
+       .shutdown = ccw_device_shutdown,
 };
 
-int
-ccw_driver_register (struct ccw_driver *cdriver)
+/**
+ * ccw_driver_register() - register a ccw driver
+ * @cdriver: driver to be registered
+ *
+ * This function is mainly a wrapper around driver_register().
+ * Returns:
+ *   %0 on success and a negative error value on failure.
+ */
+int ccw_driver_register(struct ccw_driver *cdriver)
 {
        struct device_driver *drv = &cdriver->driver;
 
@@ -1420,8 +1471,13 @@ ccw_driver_register (struct ccw_driver *cdriver)
        return driver_register(drv);
 }
 
-void
-ccw_driver_unregister (struct ccw_driver *cdriver)
+/**
+ * ccw_driver_unregister() - deregister a ccw driver
+ * @cdriver: driver to be deregistered
+ *
+ * This function is mainly a wrapper around driver_unregister().
+ */
+void ccw_driver_unregister(struct ccw_driver *cdriver)
 {
        driver_unregister(&cdriver->driver);
 }
index b66338b7657936d7de03780537637f81f559ad4f..0d4089600439263c65c4ddb05479d636e8eae67b 100644 (file)
@@ -80,7 +80,6 @@ void io_subchannel_recog_done(struct ccw_device *cdev);
 int ccw_device_cancel_halt_clear(struct ccw_device *);
 
 void ccw_device_do_unreg_rereg(struct work_struct *);
-void ccw_device_call_sch_unregister(struct work_struct *);
 void ccw_device_move_to_orphanage(struct work_struct *);
 int ccw_device_is_orphan(struct ccw_device *);
 
index 8633dc537695db3a99a03d35e462133fca0fa829..8867443b806049e9b3a7ac19a076b3147fdb6b71 100644 (file)
@@ -446,7 +446,8 @@ static void __ccw_device_get_common_pgid(struct ccw_device *cdev)
        if (cdev->private->pgid[last].inf.ps.state1 ==
            SNID_STATE1_RESET)
                /* No previous pgid found */
-               memcpy(&cdev->private->pgid[0], &css[0]->global_pgid,
+               memcpy(&cdev->private->pgid[0],
+                      &channel_subsystems[0]->global_pgid,
                       sizeof(struct pgid));
        else
                /* Use existing pgid */
@@ -543,51 +544,6 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event)
 }
 
 
-static void
-ccw_device_nopath_notify(struct work_struct *work)
-{
-       struct ccw_device_private *priv;
-       struct ccw_device *cdev;
-       struct subchannel *sch;
-       int ret;
-       unsigned long flags;
-
-       priv = container_of(work, struct ccw_device_private, kick_work);
-       cdev = priv->cdev;
-       spin_lock_irqsave(cdev->ccwlock, flags);
-       sch = to_subchannel(cdev->dev.parent);
-       /* Extra sanity. */
-       if (sch->lpm)
-               goto out_unlock;
-       if (sch->driver && sch->driver->notify) {
-               spin_unlock_irqrestore(cdev->ccwlock, flags);
-               ret = sch->driver->notify(&sch->dev, CIO_NO_PATH);
-               spin_lock_irqsave(cdev->ccwlock, flags);
-       } else
-               ret = 0;
-       if (!ret) {
-               if (get_device(&sch->dev)) {
-                       /* Driver doesn't want to keep device. */
-                       cio_disable_subchannel(sch);
-                       if (get_device(&cdev->dev)) {
-                               PREPARE_WORK(&cdev->private->kick_work,
-                                            ccw_device_call_sch_unregister);
-                               queue_work(ccw_device_work,
-                                          &cdev->private->kick_work);
-                       } else
-                               put_device(&sch->dev);
-               }
-       } else {
-               cio_disable_subchannel(sch);
-               ccw_device_set_timeout(cdev, 0);
-               cdev->private->flags.fake_irb = 0;
-               cdev->private->state = DEV_STATE_DISCONNECTED;
-               wake_up(&cdev->private->wait_q);
-       }
-out_unlock:
-       spin_unlock_irqrestore(cdev->ccwlock, flags);
-}
-
 void
 ccw_device_verify_done(struct ccw_device *cdev, int err)
 {
@@ -631,12 +587,9 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
        default:
                /* Reset oper notify indication after verify error. */
                cdev->private->flags.donotify = 0;
-               if (cdev->online) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify);
-                       queue_work(ccw_device_notify_work,
-                                  &cdev->private->kick_work);
-               } else
+               if (cdev->online)
+                       dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
+               else
                        ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
        }
@@ -690,11 +643,7 @@ ccw_device_disband_done(struct ccw_device *cdev, int err)
                break;
        default:
                cdev->private->flags.donotify = 0;
-               if (get_device(&cdev->dev)) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_call_sch_unregister);
-                       queue_work(ccw_device_work, &cdev->private->kick_work);
-               }
+               dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
                ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
        }
@@ -765,59 +714,16 @@ ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event)
 }
 
 /*
- * Handle not operational event while offline.
+ * Handle not operational event in non-special state.
  */
-static void
-ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
+static void ccw_device_generic_notoper(struct ccw_device *cdev,
+                                      enum dev_event dev_event)
 {
        struct subchannel *sch;
 
        cdev->private->state = DEV_STATE_NOT_OPER;
        sch = to_subchannel(cdev->dev.parent);
-       if (get_device(&cdev->dev)) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister);
-               queue_work(ccw_device_work, &cdev->private->kick_work);
-       }
-       wake_up(&cdev->private->wait_q);
-}
-
-/*
- * Handle not operational event while online.
- */
-static void
-ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
-{
-       struct subchannel *sch;
-       int ret;
-
-       sch = to_subchannel(cdev->dev.parent);
-       if (sch->driver->notify) {
-               spin_unlock_irq(cdev->ccwlock);
-               ret = sch->driver->notify(&sch->dev,
-                                         sch->lpm ? CIO_GONE : CIO_NO_PATH);
-               spin_lock_irq(cdev->ccwlock);
-       } else
-               ret = 0;
-       if (ret) {
-               ccw_device_set_timeout(cdev, 0);
-               cdev->private->flags.fake_irb = 0;
-               cdev->private->state = DEV_STATE_DISCONNECTED;
-               wake_up(&cdev->private->wait_q);
-               return;
-       }
-       cdev->private->state = DEV_STATE_NOT_OPER;
-       cio_disable_subchannel(sch);
-       if (sch->schib.scsw.actl != 0) {
-               // FIXME: not-oper indication to device driver ?
-               ccw_device_call_handler(cdev);
-       }
-       if (get_device(&cdev->dev)) {
-               PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_call_sch_unregister);
-               queue_work(ccw_device_work, &cdev->private->kick_work);
-       }
-       wake_up(&cdev->private->wait_q);
+       css_schedule_eval(sch->schid);
 }
 
 /*
@@ -915,18 +821,9 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                cdev->private->state = DEV_STATE_TIMEOUT_KILL;
                return;
        }
-       if (ret == -ENODEV) {
-               struct subchannel *sch;
-
-               sch = to_subchannel(cdev->dev.parent);
-               if (!sch->lpm) {
-                       PREPARE_WORK(&cdev->private->kick_work,
-                                    ccw_device_nopath_notify);
-                       queue_work(ccw_device_notify_work,
-                                  &cdev->private->kick_work);
-               } else
-                       dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
-       } else if (cdev->handler)
+       if (ret == -ENODEV)
+               dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
+       else if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-ETIMEDOUT));
 }
@@ -1233,7 +1130,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
        },
        [DEV_STATE_SENSE_PGID] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_sense_pgid_irq,
                [DEV_EVENT_TIMEOUT]     = ccw_device_onoff_timeout,
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
@@ -1245,50 +1142,50 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
        },
        [DEV_STATE_OFFLINE] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_offline_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_offline_irq,
                [DEV_EVENT_TIMEOUT]     = ccw_device_nop,
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
        },
        [DEV_STATE_VERIFY] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_verify_irq,
                [DEV_EVENT_TIMEOUT]     = ccw_device_onoff_timeout,
                [DEV_EVENT_VERIFY]      = ccw_device_delay_verify,
        },
        [DEV_STATE_ONLINE] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_irq,
                [DEV_EVENT_TIMEOUT]     = ccw_device_online_timeout,
                [DEV_EVENT_VERIFY]      = ccw_device_online_verify,
        },
        [DEV_STATE_W4SENSE] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_w4sense,
                [DEV_EVENT_TIMEOUT]     = ccw_device_nop,
                [DEV_EVENT_VERIFY]      = ccw_device_online_verify,
        },
        [DEV_STATE_DISBAND_PGID] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_disband_irq,
                [DEV_EVENT_TIMEOUT]     = ccw_device_onoff_timeout,
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
        },
        [DEV_STATE_BOXED] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_offline_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_stlck_done,
                [DEV_EVENT_TIMEOUT]     = ccw_device_stlck_done,
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
        },
        /* states to wait for i/o completion before doing something */
        [DEV_STATE_CLEAR_VERIFY] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_clear_verify,
                [DEV_EVENT_TIMEOUT]     = ccw_device_nop,
                [DEV_EVENT_VERIFY]      = ccw_device_nop,
        },
        [DEV_STATE_TIMEOUT_KILL] = {
-               [DEV_EVENT_NOTOPER]     = ccw_device_online_notoper,
+               [DEV_EVENT_NOTOPER]     = ccw_device_generic_notoper,
                [DEV_EVENT_INTERRUPT]   = ccw_device_killing_irq,
                [DEV_EVENT_TIMEOUT]     = ccw_device_killing_timeout,
                [DEV_EVENT_VERIFY]      = ccw_device_nop, //FIXME
index 14eba854b1556e8bad206828105ea8c5974aeb24..7fd2dadc32979272ad77fc16c1112e423e1e48e2 100644 (file)
 #include "device.h"
 #include "chp.h"
 
+/**
+ * ccw_device_set_options_mask() - set some options and unset the rest
+ * @cdev: device for which the options are to be set
+ * @flags: options to be set
+ *
+ * All flags specified in @flags are set, all flags not specified in @flags
+ * are cleared.
+ * Returns:
+ *   %0 on success, -%EINVAL on an invalid flag combination.
+ */
 int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
 {
        /*
@@ -40,6 +50,15 @@ int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
        return 0;
 }
 
+/**
+ * ccw_device_set_options() - set some options
+ * @cdev: device for which the options are to be set
+ * @flags: options to be set
+ *
+ * All flags specified in @flags are set, the remainder is left untouched.
+ * Returns:
+ *   %0 on success, -%EINVAL if an invalid flag combination would ensue.
+ */
 int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
 {
        /*
@@ -59,6 +78,13 @@ int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
        return 0;
 }
 
+/**
+ * ccw_device_clear_options() - clear some options
+ * @cdev: device for which the options are to be cleared
+ * @flags: options to be cleared
+ *
+ * All flags specified in @flags are cleared, the remainder is left untouched.
+ */
 void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
 {
        cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
@@ -67,8 +93,22 @@ void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
        cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
 }
 
-int
-ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
+/**
+ * ccw_device_clear() - terminate I/O request processing
+ * @cdev: target ccw device
+ * @intparm: interruption parameter; value is only used if no I/O is
+ *          outstanding, otherwise the intparm associated with the I/O request
+ *          is returned
+ *
+ * ccw_device_clear() calls csch on @cdev's subchannel.
+ * Returns:
+ *  %0 on success,
+ *  -%ENODEV on device not operational,
+ *  -%EINVAL on invalid device state.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
 {
        struct subchannel *sch;
        int ret;
@@ -89,10 +129,33 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
        return ret;
 }
 
-int
-ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
-                    unsigned long intparm, __u8 lpm, __u8 key,
-                    unsigned long flags)
+/**
+ * ccw_device_start_key() - start a s390 channel program with key
+ * @cdev: target ccw device
+ * @cpa: logical start address of channel program
+ * @intparm: user specific interruption parameter; will be presented back to
+ *          @cdev's interrupt handler. Allows a device driver to associate
+ *          the interrupt with a particular I/O request.
+ * @lpm: defines the channel path to be used for a specific I/O request. A
+ *      value of 0 will make cio use the opm.
+ * @key: storage key to be used for the I/O
+ * @flags: additional flags; defines the action to be performed for I/O
+ *        processing.
+ *
+ * Start a S/390 channel program. When the interrupt arrives, the
+ * IRQ handler is called, either immediately, delayed (dev-end missing,
+ * or sense required) or never (no IRQ handler registered).
+ * Returns:
+ *  %0, if the operation was successful;
+ *  -%EBUSY, if the device is busy, or status pending;
+ *  -%EACCES, if no path specified in @lpm is operational;
+ *  -%ENODEV, if the device is not operational.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
+                        unsigned long intparm, __u8 lpm, __u8 key,
+                        unsigned long flags)
 {
        struct subchannel *sch;
        int ret;
@@ -135,11 +198,38 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
        return ret;
 }
 
-
-int
-ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
-                            unsigned long intparm, __u8 lpm, __u8 key,
-                            unsigned long flags, int expires)
+/**
+ * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
+ * @cdev: target ccw device
+ * @cpa: logical start address of channel program
+ * @intparm: user specific interruption parameter; will be presented back to
+ *          @cdev's interrupt handler. Allows a device driver to associate
+ *          the interrupt with a particular I/O request.
+ * @lpm: defines the channel path to be used for a specific I/O request. A
+ *      value of 0 will make cio use the opm.
+ * @key: storage key to be used for the I/O
+ * @flags: additional flags; defines the action to be performed for I/O
+ *        processing.
+ * @expires: timeout value in jiffies
+ *
+ * Start a S/390 channel program. When the interrupt arrives, the
+ * IRQ handler is called, either immediately, delayed (dev-end missing,
+ * or sense required) or never (no IRQ handler registered).
+ * This function notifies the device driver if the channel program has not
+ * completed during the time specified by @expires. If a timeout occurs, the
+ * channel program is terminated via xsch, hsch or csch, and the device's
+ * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
+ * Returns:
+ *  %0, if the operation was successful;
+ *  -%EBUSY, if the device is busy, or status pending;
+ *  -%EACCES, if no path specified in @lpm is operational;
+ *  -%ENODEV, if the device is not operational.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
+                                unsigned long intparm, __u8 lpm, __u8 key,
+                                unsigned long flags, int expires)
 {
        int ret;
 
@@ -152,18 +242,67 @@ ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
        return ret;
 }
 
-int
-ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
-                unsigned long intparm, __u8 lpm, unsigned long flags)
+/**
+ * ccw_device_start() - start a s390 channel program
+ * @cdev: target ccw device
+ * @cpa: logical start address of channel program
+ * @intparm: user specific interruption parameter; will be presented back to
+ *          @cdev's interrupt handler. Allows a device driver to associate
+ *          the interrupt with a particular I/O request.
+ * @lpm: defines the channel path to be used for a specific I/O request. A
+ *      value of 0 will make cio use the opm.
+ * @flags: additional flags; defines the action to be performed for I/O
+ *        processing.
+ *
+ * Start a S/390 channel program. When the interrupt arrives, the
+ * IRQ handler is called, either immediately, delayed (dev-end missing,
+ * or sense required) or never (no IRQ handler registered).
+ * Returns:
+ *  %0, if the operation was successful;
+ *  -%EBUSY, if the device is busy, or status pending;
+ *  -%EACCES, if no path specified in @lpm is operational;
+ *  -%ENODEV, if the device is not operational.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
+                    unsigned long intparm, __u8 lpm, unsigned long flags)
 {
        return ccw_device_start_key(cdev, cpa, intparm, lpm,
                                    PAGE_DEFAULT_KEY, flags);
 }
 
-int
-ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
-                        unsigned long intparm, __u8 lpm, unsigned long flags,
-                        int expires)
+/**
+ * ccw_device_start_timeout() - start a s390 channel program with timeout
+ * @cdev: target ccw device
+ * @cpa: logical start address of channel program
+ * @intparm: user specific interruption parameter; will be presented back to
+ *          @cdev's interrupt handler. Allows a device driver to associate
+ *          the interrupt with a particular I/O request.
+ * @lpm: defines the channel path to be used for a specific I/O request. A
+ *      value of 0 will make cio use the opm.
+ * @flags: additional flags; defines the action to be performed for I/O
+ *        processing.
+ * @expires: timeout value in jiffies
+ *
+ * Start a S/390 channel program. When the interrupt arrives, the
+ * IRQ handler is called, either immediately, delayed (dev-end missing,
+ * or sense required) or never (no IRQ handler registered).
+ * This function notifies the device driver if the channel program has not
+ * completed during the time specified by @expires. If a timeout occurs, the
+ * channel program is terminated via xsch, hsch or csch, and the device's
+ * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
+ * Returns:
+ *  %0, if the operation was successful;
+ *  -%EBUSY, if the device is busy, or status pending;
+ *  -%EACCES, if no path specified in @lpm is operational;
+ *  -%ENODEV, if the device is not operational.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
+                            unsigned long intparm, __u8 lpm,
+                            unsigned long flags, int expires)
 {
        return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
                                            PAGE_DEFAULT_KEY, flags,
@@ -171,8 +310,23 @@ ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
 }
 
 
-int
-ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
+/**
+ * ccw_device_halt() - halt I/O request processing
+ * @cdev: target ccw device
+ * @intparm: interruption parameter; value is only used if no I/O is
+ *          outstanding, otherwise the intparm associated with the I/O request
+ *          is returned
+ *
+ * ccw_device_halt() calls hsch on @cdev's subchannel.
+ * Returns:
+ *  %0 on success,
+ *  -%ENODEV on device not operational,
+ *  -%EINVAL on invalid device state,
+ *  -%EBUSY on device busy or interrupt pending.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
 {
        struct subchannel *sch;
        int ret;
@@ -193,8 +347,20 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
        return ret;
 }
 
-int
-ccw_device_resume(struct ccw_device *cdev)
+/**
+ * ccw_device_resume() - resume channel program execution
+ * @cdev: target ccw device
+ *
+ * ccw_device_resume() calls rsch on @cdev's subchannel.
+ * Returns:
+ *  %0 on success,
+ *  -%ENODEV on device not operational,
+ *  -%EINVAL on invalid device state,
+ *  -%EBUSY on device busy or interrupt pending.
+ * Context:
+ *  Interrupts disabled, ccw device lock held
+ */
+int ccw_device_resume(struct ccw_device *cdev)
 {
        struct subchannel *sch;
 
@@ -260,11 +426,21 @@ ccw_device_call_handler(struct ccw_device *cdev)
        return 1;
 }
 
-/*
- * Search for CIW command in extended sense data.
+/**
+ * ccw_device_get_ciw() - Search for CIW command in extended sense data.
+ * @cdev: ccw device to inspect
+ * @ct: command type to look for
+ *
+ * During SenseID, command information words (CIWs) describing special
+ * commands available to the device may have been stored in the extended
+ * sense data. This function searches for CIWs of a specified command
+ * type in the extended sense data.
+ * Returns:
+ *  %NULL if no extended sense data has been stored or if no CIW of the
+ *  specified command type could be found,
+ *  else a pointer to the CIW of the specified command type.
  */
-struct ciw *
-ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
+struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
 {
        int ciw_cnt;
 
@@ -276,8 +452,14 @@ ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
        return NULL;
 }
 
-__u8
-ccw_device_get_path_mask(struct ccw_device *cdev)
+/**
+ * ccw_device_get_path_mask() - get currently available paths
+ * @cdev: ccw device to be queried
+ * Returns:
+ *  %0 if no subchannel for the device is available,
+ *  else the mask of currently available paths for the ccw device's subchannel.
+ */
+__u8 ccw_device_get_path_mask(struct ccw_device *cdev)
 {
        struct subchannel *sch;
 
@@ -357,8 +539,7 @@ out_unlock:
        return ret;
 }
 
-void *
-ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
+void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
 {
        struct subchannel *sch;
        struct chp_id chpid;
index d8d479876ec7ad7de402ada7cb8cf079cd1a0583..40a3208c7cf3defbc2c47429a8a4654d32290630 100644 (file)
@@ -1024,9 +1024,9 @@ __qdio_outbound_processing(struct qdio_q *q)
 }
 
 static void
-qdio_outbound_processing(struct qdio_q *q)
+qdio_outbound_processing(unsigned long q)
 {
-       __qdio_outbound_processing(q);
+       __qdio_outbound_processing((struct qdio_q *) q);
 }
 
 /************************* INBOUND ROUTINES *******************************/
@@ -1449,9 +1449,10 @@ out:
 }
 
 static void
-tiqdio_inbound_processing(struct qdio_q *q)
+tiqdio_inbound_processing(unsigned long q)
 {
-       __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount));
+       __tiqdio_inbound_processing((struct qdio_q *) q,
+                                   atomic_read(&spare_indicator_usecount));
 }
 
 static void
@@ -1494,9 +1495,9 @@ again:
 }
 
 static void
-qdio_inbound_processing(struct qdio_q *q)
+qdio_inbound_processing(unsigned long q)
 {
-       __qdio_inbound_processing(q);
+       __qdio_inbound_processing((struct qdio_q *) q);
 }
 
 /************************* MAIN ROUTINES *******************************/
@@ -1760,12 +1761,15 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
                q->handler=input_handler;
                q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind;
 
-               q->tasklet.data=(unsigned long)q;
                /* q->is_thinint_q isn't valid at this time, but
-                * irq_ptr->is_thinint_irq is */
-               q->tasklet.func=(void(*)(unsigned long))
-                       ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:
-                        &qdio_inbound_processing);
+                * irq_ptr->is_thinint_irq is
+                */
+               if (irq_ptr->is_thinint_irq)
+                       tasklet_init(&q->tasklet, tiqdio_inbound_processing,
+                                    (unsigned long) q);
+               else
+                       tasklet_init(&q->tasklet, qdio_inbound_processing,
+                                    (unsigned long) q);
 
                /* actually this is not used for inbound queues. yet. */
                atomic_set(&q->busy_siga_counter,0);
@@ -1836,13 +1840,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
                q->last_move_ftc=0;
                q->handler=output_handler;
 
-               q->tasklet.data=(unsigned long)q;
-               q->tasklet.func=(void(*)(unsigned long))
-                       &qdio_outbound_processing;
-               q->timer.function=(void(*)(unsigned long))
-                       &qdio_outbound_processing;
-               q->timer.data = (long)q;
-               init_timer(&q->timer);
+               tasklet_init(&q->tasklet, qdio_outbound_processing,
+                            (unsigned long) q);
+               setup_timer(&q->timer, qdio_outbound_processing,
+                           (unsigned long) q);
 
                atomic_set(&q->busy_siga_counter,0);
                q->timing.busy_start=0;
@@ -3726,7 +3727,7 @@ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count
 #endif /* CONFIG_64BIT */
                }
        } else {
-               QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n");
+               QDIO_PRINT_ERR("QDIO performance_stats: write 0 or 1 to this file!\n");
                return -EINVAL;
        }
        return count;
index 90bd22014513e7c56d05b7dd7eefe586c982761a..d334b0f7a1ec29dfea4f3f94290dd41ce762d5e6 100644 (file)
@@ -1231,8 +1231,9 @@ static void ap_reset_domain(void)
 {
        int i;
 
-       for (i = 0; i < AP_DEVICES; i++)
-               ap_reset_queue(AP_MKQID(i, ap_domain_index));
+       if (ap_domain_index != -1)
+               for (i = 0; i < AP_DEVICES; i++)
+                       ap_reset_queue(AP_MKQID(i, ap_domain_index));
 }
 
 static void ap_reset_all(void)
index 2a9349ad68b7e20848fc909582a5a08f8d842aba..44253fdd41364436a6057d1100bba3f0a93892fe 100644 (file)
@@ -45,7 +45,7 @@
 /**
  * The module initialization code.
  */
-int __init zcrypt_init(void)
+static int __init zcrypt_init(void)
 {
        int rc;
 
@@ -86,7 +86,7 @@ out:
 /**
  * The module termination code.
  */
-void __exit zcrypt_exit(void)
+static void __exit zcrypt_exit(void)
 {
        zcrypt_cex2a_exit();
        zcrypt_pcixcc_exit();
index 64948788d30157c7237d43a68a8d3cdac509509f..70b9ddc8cf9d6270db525c7a62e6d7c019aedccf 100644 (file)
@@ -277,7 +277,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
        };
        struct {
                struct type6_hdr hdr;
-               struct ica_CPRBX cprbx;
+               struct CPRBX cprbx;
        } __attribute__((packed)) *msg = ap_msg->message;
 
        int rcblen = CEIL4(xcRB->request_control_blk_length);
@@ -432,14 +432,17 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
                }
                if (service_rc == 8 && service_rs == 770) {
                        PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
-                       zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
-                       return -EAGAIN;
+                       return -EINVAL;
                }
                if (service_rc == 8 && service_rs == 783) {
                        PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
                        return -EAGAIN;
                }
+               if (service_rc == 12 && service_rs == 769) {
+                       PDEBUG("Invalid key on PCIXCC/CEX2C\n");
+                       return -EINVAL;
+               }
                PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
                       service_rc, service_rs);
                zdev->online = 0;
index a78ff307fd191d22a67ef9dc017f6b8af309d517..8cb7d7a6973b4e19c89f10a0d18fc9bb797f2cf0 100644 (file)
 #ifndef _ZCRYPT_PCIXCC_H_
 #define _ZCRYPT_PCIXCC_H_
 
-/**
- * CPRBX
- *       Note that all shorts and ints are big-endian.
- *       All pointer fields are 16 bytes long, and mean nothing.
- *
- *       A request CPRB is followed by a request_parameter_block.
- *
- *       The request (or reply) parameter block is organized thus:
- *         function code
- *         VUD block
- *         key block
- */
-struct CPRBX {
-       unsigned short cprb_len;        /* CPRB length        220        */
-       unsigned char  cprb_ver_id;     /* CPRB version id.   0x02       */
-       unsigned char  pad_000[3];      /* Alignment pad bytes           */
-       unsigned char  func_id[2];      /* function id        0x5432     */
-       unsigned char  cprb_flags[4];   /* Flags                         */
-       unsigned int   req_parml;       /* request parameter buffer len  */
-       unsigned int   req_datal;       /* request data buffer           */
-       unsigned int   rpl_msgbl;       /* reply  message block length   */
-       unsigned int   rpld_parml;      /* replied parameter block len   */
-       unsigned int   rpl_datal;       /* reply data block len          */
-       unsigned int   rpld_datal;      /* replied data block len        */
-       unsigned int   req_extbl;       /* request extension block len   */
-       unsigned char  pad_001[4];      /* reserved                      */
-       unsigned int   rpld_extbl;      /* replied extension block len   */
-       unsigned char  req_parmb[16];   /* request parm block 'address'  */
-       unsigned char  req_datab[16];   /* request data block 'address'  */
-       unsigned char  rpl_parmb[16];   /* reply parm block 'address'    */
-       unsigned char  rpl_datab[16];   /* reply data block 'address'    */
-       unsigned char  req_extb[16];    /* request extension block 'addr'*/
-       unsigned char  rpl_extb[16];    /* reply extension block 'addres'*/
-       unsigned short ccp_rtcode;      /* server return code            */
-       unsigned short ccp_rscode;      /* server reason code            */
-       unsigned int   mac_data_len;    /* Mac Data Length               */
-       unsigned char  logon_id[8];     /* Logon Identifier              */
-       unsigned char  mac_value[8];    /* Mac Value                     */
-       unsigned char  mac_content_flgs;/* Mac content flag byte         */
-       unsigned char  pad_002;         /* Alignment                     */
-       unsigned short domain;          /* Domain                        */
-       unsigned char  pad_003[12];     /* Domain masks                  */
-       unsigned char  pad_004[36];     /* reserved                      */
-} __attribute__((packed));
-
 int zcrypt_pcixcc_init(void);
 void zcrypt_pcixcc_exit(void);
 
index 1c8f71a59855b26b2123e611b3ce3978ee6d5dd2..c0d1c0eb32099f225a8d972cc164d1a19d3ae25b 100644 (file)
@@ -28,7 +28,7 @@ static void zfcp_ccw_remove(struct ccw_device *);
 static int zfcp_ccw_set_online(struct ccw_device *);
 static int zfcp_ccw_set_offline(struct ccw_device *);
 static int zfcp_ccw_notify(struct ccw_device *, int);
-static void zfcp_ccw_shutdown(struct device *);
+static void zfcp_ccw_shutdown(struct ccw_device *);
 
 static struct ccw_device_id zfcp_ccw_device_id[] = {
        {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE,
@@ -51,9 +51,7 @@ static struct ccw_driver zfcp_ccw_driver = {
        .set_online  = zfcp_ccw_set_online,
        .set_offline = zfcp_ccw_set_offline,
        .notify      = zfcp_ccw_notify,
-       .driver      = {
-               .shutdown = zfcp_ccw_shutdown,
-       },
+       .shutdown    = zfcp_ccw_shutdown,
 };
 
 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
@@ -277,12 +275,12 @@ zfcp_ccw_register(void)
  * Makes sure that QDIO queues are down when the system gets stopped.
  */
 static void
-zfcp_ccw_shutdown(struct device *dev)
+zfcp_ccw_shutdown(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter;
 
        down(&zfcp_data.config_sema);
-       adapter = dev_get_drvdata(dev);
+       adapter = dev_get_drvdata(&cdev->dev);
        zfcp_erp_adapter_shutdown(adapter, 0);
        zfcp_erp_wait(adapter);
        up(&zfcp_data.config_sema);
index 5f3212440f68594b304e9c0b48074b1c3c0618bd..ffa3bf756943f6aa142c8bf66bc74e70de1c3fc5 100644 (file)
@@ -19,8 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <asm/debug.h>
 #include <linux/ctype.h>
+#include <asm/debug.h>
 #include "zfcp_ext.h"
 
 static u32 dbfsize = 4;
@@ -35,17 +35,17 @@ static int
 zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
 {
        unsigned long long sec;
-       struct timespec xtime;
+       struct timespec dbftime;
        int len = 0;
 
        stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
        sec = stck >> 12;
        do_div(sec, 1000000);
-       xtime.tv_sec = sec;
+       dbftime.tv_sec = sec;
        stck -= (sec * 1000000) << 12;
-       xtime.tv_nsec = ((stck * 1000) >> 12);
+       dbftime.tv_nsec = ((stck * 1000) >> 12);
        len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
-                      label, xtime.tv_sec, xtime.tv_nsec);
+                      label, dbftime.tv_sec, dbftime.tv_nsec);
 
        return len;
 }
index d8cd75ce2d9a37c1675d3c29af6fc9884dc00b66..16b4418ab257460069342c8518fa3d6fc6ed438d 100644 (file)
@@ -54,7 +54,7 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int);
 static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *,
                                         struct zfcp_port *,
                                         struct zfcp_unit *, int);
-static inline int zfcp_erp_strategy_statechange_detected(atomic_t *, u32);
+static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32);
 static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *,
                                              struct zfcp_port *,
                                              struct zfcp_unit *, int);
@@ -106,8 +106,8 @@ static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *,
 static void zfcp_erp_action_ready(struct zfcp_erp_action *);
 static int  zfcp_erp_action_exists(struct zfcp_erp_action *);
 
-static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *);
-static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *);
+static void zfcp_erp_action_to_ready(struct zfcp_erp_action *);
+static void zfcp_erp_action_to_running(struct zfcp_erp_action *);
 
 static void zfcp_erp_memwait_handler(unsigned long);
 
@@ -952,7 +952,7 @@ zfcp_erp_memwait_handler(unsigned long data)
  *             action gets an appropriate flag and will be processed
  *             accordingly
  */
-void zfcp_erp_timeout_handler(unsigned long data)
+static void zfcp_erp_timeout_handler(unsigned long data)
 {
        struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
        struct zfcp_adapter *adapter = erp_action->adapter;
@@ -1491,7 +1491,7 @@ zfcp_erp_strategy_statechange(int action,
        return retval;
 }
 
-static inline int
+static int
 zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
 {
        return
@@ -2001,7 +2001,7 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
  * returns:    0 - successful setup
  *             !0 - failed setup
  */
-int
+static int
 zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
 {
        int retval;
@@ -3248,8 +3248,7 @@ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
                zfcp_erp_action_dismiss(&unit->erp_action);
 }
 
-static inline void
-zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
+static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_adapter *adapter = erp_action->adapter;
 
@@ -3258,8 +3257,7 @@ zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
        list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
 }
 
-static inline void
-zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
+static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_adapter *adapter = erp_action->adapter;
 
index 74901e981e1089363bdc501fefc9c4ed106c70bb..d2fc2384c3bed34e32b83ed98804d01961eb7d5a 100644 (file)
@@ -491,6 +491,7 @@ struct dlm_ls {
        uint64_t                ls_recover_seq;
        struct dlm_recover      *ls_recover_args;
        struct rw_semaphore     ls_in_recovery; /* block local requests */
+       struct rw_semaphore     ls_recv_active; /* block dlm_recv */
        struct list_head        ls_requestqueue;/* queue remote requests */
        struct mutex            ls_requestqueue_mutex;
        char                    *ls_recover_buf;
index 2082daf083d86cdec3b3697e061f8f3ff703e867..3915b8e1414623db82bce20d0d4b4c41fc6b9fa3 100644 (file)
@@ -3638,55 +3638,8 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
        dlm_put_lkb(lkb);
 }
 
-int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
+static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
 {
-       struct dlm_message *ms = (struct dlm_message *) hd;
-       struct dlm_ls *ls;
-       int error = 0;
-
-       if (!recovery)
-               dlm_message_in(ms);
-
-       ls = dlm_find_lockspace_global(hd->h_lockspace);
-       if (!ls) {
-               log_print("drop message %d from %d for unknown lockspace %d",
-                         ms->m_type, nodeid, hd->h_lockspace);
-               return -EINVAL;
-       }
-
-       /* recovery may have just ended leaving a bunch of backed-up requests
-          in the requestqueue; wait while dlm_recoverd clears them */
-
-       if (!recovery)
-               dlm_wait_requestqueue(ls);
-
-       /* recovery may have just started while there were a bunch of
-          in-flight requests -- save them in requestqueue to be processed
-          after recovery.  we can't let dlm_recvd block on the recovery
-          lock.  if dlm_recoverd is calling this function to clear the
-          requestqueue, it needs to be interrupted (-EINTR) if another
-          recovery operation is starting. */
-
-       while (1) {
-               if (dlm_locking_stopped(ls)) {
-                       if (recovery) {
-                               error = -EINTR;
-                               goto out;
-                       }
-                       error = dlm_add_requestqueue(ls, nodeid, hd);
-                       if (error == -EAGAIN)
-                               continue;
-                       else {
-                               error = -EINTR;
-                               goto out;
-                       }
-               }
-
-               if (dlm_lock_recovery_try(ls))
-                       break;
-               schedule();
-       }
-
        switch (ms->m_type) {
 
        /* messages sent to a master node */
@@ -3761,17 +3714,90 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
                log_error(ls, "unknown message type %d", ms->m_type);
        }
 
-       dlm_unlock_recovery(ls);
- out:
-       dlm_put_lockspace(ls);
        dlm_astd_wake();
-       return error;
 }
 
+/* If the lockspace is in recovery mode (locking stopped), then normal
+   messages are saved on the requestqueue for processing after recovery is
+   done.  When not in recovery mode, we wait for dlm_recoverd to drain saved
+   messages off the requestqueue before we process new ones. This occurs right
+   after recovery completes when we transition from saving all messages on
+   requestqueue, to processing all the saved messages, to processing new
+   messages as they arrive. */
 
-/*
- * Recovery related
- */
+static void dlm_receive_message(struct dlm_ls *ls, struct dlm_message *ms,
+                               int nodeid)
+{
+       if (dlm_locking_stopped(ls)) {
+               dlm_add_requestqueue(ls, nodeid, (struct dlm_header *) ms);
+       } else {
+               dlm_wait_requestqueue(ls);
+               _receive_message(ls, ms);
+       }
+}
+
+/* This is called by dlm_recoverd to process messages that were saved on
+   the requestqueue. */
+
+void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms)
+{
+       _receive_message(ls, ms);
+}
+
+/* This is called by the midcomms layer when something is received for
+   the lockspace.  It could be either a MSG (normal message sent as part of
+   standard locking activity) or an RCOM (recovery message sent as part of
+   lockspace recovery). */
+
+void dlm_receive_buffer(struct dlm_header *hd, int nodeid)
+{
+       struct dlm_message *ms = (struct dlm_message *) hd;
+       struct dlm_rcom *rc = (struct dlm_rcom *) hd;
+       struct dlm_ls *ls;
+       int type = 0;
+
+       switch (hd->h_cmd) {
+       case DLM_MSG:
+               dlm_message_in(ms);
+               type = ms->m_type;
+               break;
+       case DLM_RCOM:
+               dlm_rcom_in(rc);
+               type = rc->rc_type;
+               break;
+       default:
+               log_print("invalid h_cmd %d from %u", hd->h_cmd, nodeid);
+               return;
+       }
+
+       if (hd->h_nodeid != nodeid) {
+               log_print("invalid h_nodeid %d from %d lockspace %x",
+                         hd->h_nodeid, nodeid, hd->h_lockspace);
+               return;
+       }
+
+       ls = dlm_find_lockspace_global(hd->h_lockspace);
+       if (!ls) {
+               log_print("invalid h_lockspace %x from %d cmd %d type %d",
+                         hd->h_lockspace, nodeid, hd->h_cmd, type);
+
+               if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS)
+                       dlm_send_ls_not_ready(nodeid, rc);
+               return;
+       }
+
+       /* this rwsem allows dlm_ls_stop() to wait for all dlm_recv threads to
+          be inactive (in this ls) before transitioning to recovery mode */
+
+       down_read(&ls->ls_recv_active);
+       if (hd->h_cmd == DLM_MSG)
+               dlm_receive_message(ls, ms, nodeid);
+       else
+               dlm_receive_rcom(ls, rc, nodeid);
+       up_read(&ls->ls_recv_active);
+
+       dlm_put_lockspace(ls);
+}
 
 static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb)
 {
@@ -4429,7 +4455,8 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 
        if (lvb_in && ua->lksb.sb_lvbptr)
                memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
-       ua->castparam = ua_tmp->castparam;
+       if (ua_tmp->castparam)
+               ua->castparam = ua_tmp->castparam;
        ua->user_lksb = ua_tmp->user_lksb;
 
        error = set_unlock_args(flags, ua, &args);
@@ -4474,7 +4501,8 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
                goto out;
 
        ua = (struct dlm_user_args *)lkb->lkb_astparam;
-       ua->castparam = ua_tmp->castparam;
+       if (ua_tmp->castparam)
+               ua->castparam = ua_tmp->castparam;
        ua->user_lksb = ua_tmp->user_lksb;
 
        error = set_unlock_args(flags, ua, &args);
index 1720313c22dfc455fd6c25f47d94fc02db075a64..ada04680a1e5d9ff994aa82a35c899b6a975692b 100644 (file)
@@ -16,7 +16,8 @@
 void dlm_print_rsb(struct dlm_rsb *r);
 void dlm_dump_rsb(struct dlm_rsb *r);
 void dlm_print_lkb(struct dlm_lkb *lkb);
-int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery);
+void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
+void dlm_receive_buffer(struct dlm_header *hd, int nodeid);
 int dlm_modes_compat(int mode1, int mode2);
 int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen,
        unsigned int flags, struct dlm_rsb **r_ret);
index 1dc72105ab125171b4bb3356ea0a09577178ec77..628eaa669e68a8eb2842356dd778122cc6367c3f 100644 (file)
@@ -519,6 +519,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
        ls->ls_recover_seq = 0;
        ls->ls_recover_args = NULL;
        init_rwsem(&ls->ls_in_recovery);
+       init_rwsem(&ls->ls_recv_active);
        INIT_LIST_HEAD(&ls->ls_requestqueue);
        mutex_init(&ls->ls_requestqueue_mutex);
        mutex_init(&ls->ls_clear_proc_locks);
index 9e9d2e82f40fb36a62307e92b5ab48285a3c4654..58bf3f5cdbe25ac6cbd2c527be2df7c286d01ede 100644 (file)
@@ -334,18 +334,8 @@ static void close_connection(struct connection *con, bool and_other)
                con->rx_page = NULL;
        }
 
-       /* If we are an 'othercon' then NULL the pointer to us
-          from the parent and tidy ourself up */
-       if (test_bit(CF_IS_OTHERCON, &con->flags)) {
-               struct connection *parent = __nodeid2con(con->nodeid, 0);
-               parent->othercon = NULL;
-               kmem_cache_free(con_cache, con);
-       }
-       else {
-               /* Parent connections get reused */
-               con->retries = 0;
-               mutex_unlock(&con->sock_mutex);
-       }
+       con->retries = 0;
+       mutex_unlock(&con->sock_mutex);
 }
 
 /* We only send shutdown messages to nodes that are not part of the cluster */
@@ -731,6 +721,8 @@ static int tcp_accept_from_sock(struct connection *con)
                        INIT_WORK(&othercon->swork, process_send_sockets);
                        INIT_WORK(&othercon->rwork, process_recv_sockets);
                        set_bit(CF_IS_OTHERCON, &othercon->flags);
+               }
+               if (!othercon->sock) {
                        newcon->othercon = othercon;
                        othercon->sock = newsock;
                        newsock->sk->sk_user_data = othercon;
@@ -1272,14 +1264,15 @@ static void send_to_sock(struct connection *con)
                if (len) {
                        ret = sendpage(con->sock, e->page, offset, len,
                                       msg_flags);
-                       if (ret == -EAGAIN || ret == 0)
+                       if (ret == -EAGAIN || ret == 0) {
+                               cond_resched();
                                goto out;
+                       }
                        if (ret <= 0)
                                goto send_error;
-               } else {
+               }
                        /* Don't starve people filling buffers */
                        cond_resched();
-               }
 
                spin_lock(&con->writequeue_lock);
                e->offset += ret;
index d09977528f692c7e133a9d7702cae88411536e75..e9cdcab306e2a06037c4e0c32ac1c0e7be3097dc 100644 (file)
 #include "rcom.h"
 #include "config.h"
 
-/*
- * Following called by dlm_recoverd thread
- */
-
 static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new)
 {
        struct dlm_member *memb = NULL;
@@ -250,18 +246,30 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
        return error;
 }
 
-/*
- * Following called from lockspace.c
- */
+/* Userspace guarantees that dlm_ls_stop() has completed on all nodes before
+   dlm_ls_start() is called on any of them to start the new recovery. */
 
 int dlm_ls_stop(struct dlm_ls *ls)
 {
        int new;
 
        /*
-        * A stop cancels any recovery that's in progress (see RECOVERY_STOP,
-        * dlm_recovery_stopped()) and prevents any new locks from being
-        * processed (see RUNNING, dlm_locking_stopped()).
+        * Prevent dlm_recv from being in the middle of something when we do
+        * the stop.  This includes ensuring dlm_recv isn't processing a
+        * recovery message (rcom), while dlm_recoverd is aborting and
+        * resetting things from an in-progress recovery.  i.e. we want
+        * dlm_recoverd to abort its recovery without worrying about dlm_recv
+        * processing an rcom at the same time.  Stopping dlm_recv also makes
+        * it easy for dlm_receive_message() to check locking stopped and add a
+        * message to the requestqueue without races.
+        */
+
+       down_write(&ls->ls_recv_active);
+
+       /*
+        * Abort any recovery that's in progress (see RECOVERY_STOP,
+        * dlm_recovery_stopped()) and tell any other threads running in the
+        * dlm to quit any processing (see RUNNING, dlm_locking_stopped()).
         */
 
        spin_lock(&ls->ls_recover_lock);
@@ -270,9 +278,15 @@ int dlm_ls_stop(struct dlm_ls *ls)
        ls->ls_recover_seq++;
        spin_unlock(&ls->ls_recover_lock);
 
+       /*
+        * Let dlm_recv run again, now any normal messages will be saved on the
+        * requestqueue for later.
+        */
+
+       up_write(&ls->ls_recv_active);
+
        /*
         * This in_recovery lock does two things:
-        *
         * 1) Keeps this function from returning until all threads are out
         *    of locking routines and locking is truely stopped.
         * 2) Keeps any new requests from being processed until it's unlocked
@@ -284,9 +298,8 @@ int dlm_ls_stop(struct dlm_ls *ls)
 
        /*
         * The recoverd suspend/resume makes sure that dlm_recoverd (if
-        * running) has noticed the clearing of RUNNING above and quit
-        * processing the previous recovery.  This will be true for all nodes
-        * before any nodes start the new recovery.
+        * running) has noticed RECOVERY_STOP above and quit processing the
+        * previous recovery.
         */
 
        dlm_recoverd_suspend(ls);
index a5126e0c68a69e6983e7d77833586bd928e7a3a7..f8c69dda16a080af8e960f2111772bed46d2c8c2 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -27,7 +27,6 @@
 #include "dlm_internal.h"
 #include "lowcomms.h"
 #include "config.h"
-#include "rcom.h"
 #include "lock.h"
 #include "midcomms.h"
 
@@ -117,19 +116,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
                offset &= (limit - 1);
                len -= msglen;
 
-               switch (msg->h_cmd) {
-               case DLM_MSG:
-                       dlm_receive_message(msg, nodeid, 0);
-                       break;
-
-               case DLM_RCOM:
-                       dlm_receive_rcom(msg, nodeid);
-                       break;
-
-               default:
-                       log_print("unknown msg type %x from %u: %u %u %u %u",
-                                 msg->h_cmd, nodeid, msglen, len, offset, ret);
-               }
+               dlm_receive_buffer(msg, nodeid);
        }
 
        if (msg != (struct dlm_header *) __tmp)
index 188b91c027e4b16a811c30b398654018ad63a771..ae2fd97fa4adc8392b720f1e455e4a53968c8d0c 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -386,7 +386,10 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
        dlm_recover_process_copy(ls, rc_in);
 }
 
-static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
+/* If the lockspace doesn't exist then still send a status message
+   back; it's possible that it just doesn't have its global_id yet. */
+
+int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
 {
        struct dlm_rcom *rc;
        struct rcom_config *rf;
@@ -446,28 +449,11 @@ static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
        return rv;
 }
 
-/* Called by dlm_recvd; corresponds to dlm_receive_message() but special
+/* Called by dlm_recv; corresponds to dlm_receive_message() but special
    recovery-only comms are sent through here. */
 
-void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
+void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
 {
-       struct dlm_rcom *rc = (struct dlm_rcom *) hd;
-       struct dlm_ls *ls;
-
-       dlm_rcom_in(rc);
-
-       /* If the lockspace doesn't exist then still send a status message
-          back; it's possible that it just doesn't have its global_id yet. */
-
-       ls = dlm_find_lockspace_global(hd->h_lockspace);
-       if (!ls) {
-               log_print("lockspace %x from %d type %x not found",
-                         hd->h_lockspace, nodeid, rc->rc_type);
-               if (rc->rc_type == DLM_RCOM_STATUS)
-                       send_ls_not_ready(nodeid, rc);
-               return;
-       }
-
        if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
                log_debug(ls, "ignoring recovery message %x from %d",
                          rc->rc_type, nodeid);
@@ -477,12 +463,6 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
        if (is_old_reply(ls, rc))
                goto out;
 
-       if (nodeid != rc->rc_header.h_nodeid) {
-               log_error(ls, "bad rcom nodeid %d from %d",
-                         rc->rc_header.h_nodeid, nodeid);
-               goto out;
-       }
-
        switch (rc->rc_type) {
        case DLM_RCOM_STATUS:
                receive_rcom_status(ls, rc);
@@ -520,6 +500,6 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
                DLM_ASSERT(0, printk("rc_type=%x\n", rc->rc_type););
        }
  out:
-       dlm_put_lockspace(ls);
+       return;
 }
 
index d7984321ff4152d5030094f78b113e28a618f195..b09abd29ba38cfc3ff64dd2666f3945054520c62 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -18,7 +18,8 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid);
 int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len);
 int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid);
 int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
-void dlm_receive_rcom(struct dlm_header *hd, int nodeid);
+void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid);
+int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in);
 
 #endif
 
index 66575997861cad1da5e02e9528deaaf6240751b7..4b89e20eebe702f32a9214d2f377e1efc2768001 100644 (file)
 
 
 /* If the start for which we're re-enabling locking (seq) has been superseded
-   by a newer stop (ls_recover_seq), we need to leave locking disabled. */
+   by a newer stop (ls_recover_seq), we need to leave locking disabled.
+
+   We suspend dlm_recv threads here to avoid the race where dlm_recv a) sees
+   locking stopped and b) adds a message to the requestqueue, but dlm_recoverd
+   enables locking and clears the requestqueue between a and b. */
 
 static int enable_locking(struct dlm_ls *ls, uint64_t seq)
 {
        int error = -EINTR;
 
+       down_write(&ls->ls_recv_active);
+
        spin_lock(&ls->ls_recover_lock);
        if (ls->ls_recover_seq == seq) {
                set_bit(LSFL_RUNNING, &ls->ls_flags);
+               /* unblocks processes waiting to enter the dlm */
                up_write(&ls->ls_in_recovery);
                error = 0;
        }
        spin_unlock(&ls->ls_recover_lock);
+
+       up_write(&ls->ls_recv_active);
        return error;
 }
 
index 65008d79c96d2e651091dbd7bcbe47f1e17221ec..0de04f17cceaeec20383d5613e9fd17152e5df10 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -20,7 +20,7 @@
 struct rq_entry {
        struct list_head list;
        int nodeid;
-       char request[1];
+       char request[0];
 };
 
 /*
@@ -30,42 +30,39 @@ struct rq_entry {
  * lockspace is enabled on some while still suspended on others.
  */
 
-int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd)
+void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd)
 {
        struct rq_entry *e;
        int length = hd->h_length;
-       int rv = 0;
 
        e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL);
        if (!e) {
-               log_print("dlm_add_requestqueue: out of memory\n");
-               return 0;
+               log_print("dlm_add_requestqueue: out of memory len %d", length);
+               return;
        }
 
        e->nodeid = nodeid;
        memcpy(e->request, hd, length);
 
-       /* We need to check dlm_locking_stopped() after taking the mutex to
-          avoid a race where dlm_recoverd enables locking and runs
-          process_requestqueue between our earlier dlm_locking_stopped check
-          and this addition to the requestqueue. */
-
        mutex_lock(&ls->ls_requestqueue_mutex);
-       if (dlm_locking_stopped(ls))
-               list_add_tail(&e->list, &ls->ls_requestqueue);
-       else {
-               log_debug(ls, "dlm_add_requestqueue skip from %d", nodeid);
-               kfree(e);
-               rv = -EAGAIN;
-       }
+       list_add_tail(&e->list, &ls->ls_requestqueue);
        mutex_unlock(&ls->ls_requestqueue_mutex);
-       return rv;
 }
 
+/*
+ * Called by dlm_recoverd to process normal messages saved while recovery was
+ * happening.  Normal locking has been enabled before this is called.  dlm_recv
+ * upon receiving a message, will wait for all saved messages to be drained
+ * here before processing the message it got.  If a new dlm_ls_stop() arrives
+ * while we're processing these saved messages, it may block trying to suspend
+ * dlm_recv if dlm_recv is waiting for us in dlm_wait_requestqueue.  In that
+ * case, we don't abort since locking_stopped is still 0.  If dlm_recv is not
+ * waiting for us, then this processing may be aborted due to locking_stopped.
+ */
+
 int dlm_process_requestqueue(struct dlm_ls *ls)
 {
        struct rq_entry *e;
-       struct dlm_header *hd;
        int error = 0;
 
        mutex_lock(&ls->ls_requestqueue_mutex);
@@ -79,14 +76,7 @@ int dlm_process_requestqueue(struct dlm_ls *ls)
                e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list);
                mutex_unlock(&ls->ls_requestqueue_mutex);
 
-               hd = (struct dlm_header *) e->request;
-               error = dlm_receive_message(hd, e->nodeid, 1);
-
-               if (error == -EINTR) {
-                       /* entry is left on requestqueue */
-                       log_debug(ls, "process_requestqueue abort eintr");
-                       break;
-               }
+               dlm_receive_message_saved(ls, (struct dlm_message *)e->request);
 
                mutex_lock(&ls->ls_requestqueue_mutex);
                list_del(&e->list);
@@ -106,10 +96,12 @@ int dlm_process_requestqueue(struct dlm_ls *ls)
 
 /*
  * After recovery is done, locking is resumed and dlm_recoverd takes all the
- * saved requests and processes them as they would have been by dlm_recvd.  At
- * the same time, dlm_recvd will start receiving new requests from remote
- * nodes.  We want to delay dlm_recvd processing new requests until
- * dlm_recoverd has finished processing the old saved requests.
+ * saved requests and processes them as they would have been by dlm_recv.  At
+ * the same time, dlm_recv will start receiving new requests from remote nodes.
+ * We want to delay dlm_recv processing new requests until dlm_recoverd has
+ * finished processing the old saved requests.  We don't check for locking
+ * stopped here because dlm_ls_stop won't stop locking until it's suspended us
+ * (dlm_recv).
  */
 
 void dlm_wait_requestqueue(struct dlm_ls *ls)
@@ -118,8 +110,6 @@ void dlm_wait_requestqueue(struct dlm_ls *ls)
                mutex_lock(&ls->ls_requestqueue_mutex);
                if (list_empty(&ls->ls_requestqueue))
                        break;
-               if (dlm_locking_stopped(ls))
-                       break;
                mutex_unlock(&ls->ls_requestqueue_mutex);
                schedule();
        }
index 6a53ea03335dae50b9d22f1c0c156ff01dfd581d..aba34fc05ee442ba98eb47e14c87b5d3530d67a4 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -13,7 +13,7 @@
 #ifndef __REQUESTQUEUE_DOT_H__
 #define __REQUESTQUEUE_DOT_H__
 
-int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd);
+void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd);
 int dlm_process_requestqueue(struct dlm_ls *ls);
 void dlm_wait_requestqueue(struct dlm_ls *ls);
 void dlm_purge_requestqueue(struct dlm_ls *ls);
index cd805a66880ddd3f24459be574bd868d29f2d801..93fa427bb5f501cee6da6ab88afbfd921f584295 100644 (file)
@@ -93,9 +93,10 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
                map_bh(bh, inode->i_sb, block);
 
        set_buffer_uptodate(bh);
+       if (!gfs2_is_jdata(ip))
+               mark_buffer_dirty(bh);
        if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
                gfs2_trans_add_bh(ip->i_gl, bh, 0);
-       mark_buffer_dirty(bh);
 
        if (release) {
                unlock_page(page);
@@ -1085,6 +1086,33 @@ static int do_shrink(struct gfs2_inode *ip, u64 size)
        return error;
 }
 
+static int do_touch(struct gfs2_inode *ip, u64 size)
+{
+       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       struct buffer_head *dibh;
+       int error;
+
+       error = gfs2_trans_begin(sdp, RES_DINODE, 0);
+       if (error)
+               return error;
+
+       down_write(&ip->i_rw_mutex);
+
+       error = gfs2_meta_inode_buffer(ip, &dibh);
+       if (error)
+               goto do_touch_out;
+
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+       gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+       gfs2_dinode_out(ip, dibh->b_data);
+       brelse(dibh);
+
+do_touch_out:
+       up_write(&ip->i_rw_mutex);
+       gfs2_trans_end(sdp);
+       return error;
+}
+
 /**
  * gfs2_truncatei - make a file a given size
  * @ip: the inode
@@ -1105,8 +1133,11 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
 
        if (size > ip->i_di.di_size)
                error = do_grow(ip, size);
-       else
+       else if (size < ip->i_di.di_size)
                error = do_shrink(ip, size);
+       else
+               /* update time stamps */
+               error = do_touch(ip, size);
 
        return error;
 }
diff --git