Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
David S. Miller [Sat, 5 Dec 2009 23:22:26 +0000 (15:22 -0800)]
Conflicts:
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/wireless/ray_cs.c

325 files changed:
Documentation/RCU/trace.txt
Documentation/RCU/whatisRCU.txt
Documentation/dontdiff
Documentation/kernel-parameters.txt
Documentation/pcmcia/driver-changes.txt
Documentation/trace/ftrace-design.txt
MAINTAINERS
Makefile
arch/avr32/include/asm/bug.h
arch/ia64/include/asm/swiotlb.h
arch/ia64/kernel/pci-swiotlb.c
arch/mips/include/asm/bug.h
arch/mips/kernel/syscall.c
arch/mips/rb532/devices.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/s390/Kconfig
arch/s390/include/asm/bug.h
arch/s390/include/asm/spinlock.h
arch/s390/kernel/ftrace.c
arch/x86/include/asm/amd_iommu.h
arch/x86/include/asm/amd_iommu_proto.h [new file with mode: 0644]
arch/x86/include/asm/amd_iommu_types.h
arch/x86/include/asm/bug.h
arch/x86/include/asm/calgary.h
arch/x86/include/asm/device.h
arch/x86/include/asm/dma-mapping.h
arch/x86/include/asm/gart.h
arch/x86/include/asm/iommu.h
arch/x86/include/asm/swiotlb.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/aperture_64.c
arch/x86/kernel/crash.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/ftrace.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/pci-nommu.c
arch/x86/kernel/pci-swiotlb.c
arch/x86/kernel/reboot.c
arch/x86/kernel/x86_init.c
arch/x86/mm/testmmiotrace.c
drivers/ata/pata_pcmcia.c
drivers/block/aoe/aoecmd.c
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/char/agp/Kconfig
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/ipwireless/hardware.c
drivers/char/pcmcia/ipwireless/main.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm_tis.c
drivers/gpio/langwell_gpio.c
drivers/ide/ide-cs.c
drivers/input/serio/i8042-x86ia64io.h
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/md/raid1.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/mfd/wm831x-core.c
drivers/mmc/host/pxamci.c
drivers/mtd/maps/pcmciamtd.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/com20020_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/wireless/airo_cs.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/b43/pcmcia.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/orinoco/orinoco_cs.c
drivers/net/wireless/orinoco/spectrum_cs.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/wl3501_cs.c
drivers/parport/parport_cs.c
drivers/pci/dmar.c
drivers/pci/intel-iommu.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/cardbus.c
drivers/pcmcia/cirrus.h
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/o2micro.h
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/pd6729.h
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/pxa2xx_base.h
drivers/pcmcia/pxa2xx_cm_x255.c
drivers/pcmcia/pxa2xx_cm_x270.c
drivers/pcmcia/pxa2xx_e740.c
drivers/pcmcia/pxa2xx_lubbock.c
drivers/pcmcia/pxa2xx_mainstone.c
drivers/pcmcia/pxa2xx_palmld.c
drivers/pcmcia/pxa2xx_palmtx.c
drivers/pcmcia/pxa2xx_sharpsl.c
drivers/pcmcia/pxa2xx_trizeps4.c
drivers/pcmcia/pxa2xx_viper.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/sa1100_assabet.c
drivers/pcmcia/sa1100_badge4.c
drivers/pcmcia/sa1100_cerf.c
drivers/pcmcia/sa1100_generic.c
drivers/pcmcia/sa1100_h3600.c
drivers/pcmcia/sa1100_jornada720.c
drivers/pcmcia/sa1100_neponset.c
drivers/pcmcia/sa1100_shannon.c
drivers/pcmcia/sa1100_simpad.c
drivers/pcmcia/sa1111_generic.c
drivers/pcmcia/sa1111_generic.h
drivers/pcmcia/sa11xx_base.c
drivers/pcmcia/sa11xx_base.h
drivers/pcmcia/soc_common.c
drivers/pcmcia/soc_common.h
drivers/pcmcia/tcic.c
drivers/pcmcia/topic.h
drivers/regulator/wm831x-isink.c
drivers/rtc/rtc-pcf50633.c
drivers/rtc/rtc-x1205.c
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/serial/serial_cs.c
drivers/spi/spi_txx9.c
drivers/ssb/pcmcia.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/das08_cs.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_daq_dio24.c
drivers/staging/comedi/drivers/ni_labpc_cs.c
drivers/staging/comedi/drivers/ni_mio_cs.c
drivers/staging/comedi/drivers/quatech_daqp_cs.c
drivers/staging/netwave/netwave_cs.c
drivers/staging/wavelan/wavelan_cs.c
drivers/telephony/ixj_pcmcia.c
drivers/usb/host/sl811_cs.c
drivers/video/da8xx-fb.c
drivers/video/gbefb.c
drivers/watchdog/rc32434_wdt.c
fs/exec.c
fs/file_table.c
fs/gfs2/Kconfig
fs/gfs2/acl.c
fs/gfs2/acl.h
fs/gfs2/aops.c
fs/gfs2/dir.c
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/log.c
fs/gfs2/lops.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/quota.h
fs/gfs2/recovery.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/super.h
fs/gfs2/sys.c
fs/gfs2/xattr.c
fs/gfs2/xattr.h
fs/inode.c
fs/namespace.c
fs/open.c
fs/quota/Kconfig
fs/quota/dquot.c
fs/quota/quota.c
fs/xattr_acl.c
include/linux/Kbuild
include/linux/bootmem.h
include/linux/capability.h
include/linux/compiler-gcc.h
include/linux/compiler-gcc4.h
include/linux/compiler.h
include/linux/dmar.h
include/linux/gfs2_ondisk.h
include/linux/hardirq.h
include/linux/init_task.h
include/linux/interrupt.h
include/linux/irqflags.h
include/linux/kernel.h
include/linux/lsm_audit.h
include/linux/mfd/wm831x/regulator.h
include/linux/net.h
include/linux/pci_ids.h
include/linux/posix_acl.h
include/linux/quota.h
include/linux/ratelimit.h
include/linux/rcupdate.h
include/linux/rcutiny.h [new file with mode: 0644]
include/linux/rcutree.h
include/linux/sched.h
include/linux/securebits.h
include/linux/security.h
include/linux/smp.h
include/linux/smp_lock.h
include/linux/spinlock.h
include/linux/spinlock_api_smp.h
include/linux/srcu.h
include/linux/swiotlb.h
include/linux/tpm.h
include/pcmcia/cs.h
include/pcmcia/cs_types.h
include/pcmcia/ds.h
include/pcmcia/ss.h
include/trace/events/bkl.h [new file with mode: 0644]
include/trace/events/syscalls.h
include/trace/ftrace.h
include/trace/power.h [deleted file]
include/trace/syscall.h
init/Kconfig
init/main.c
kernel/Kconfig.locks [new file with mode: 0644]
kernel/Makefile
kernel/capability.c
kernel/hung_task.c
kernel/irq/chip.c
kernel/irq/proc.c
kernel/irq/spurious.c
kernel/kmod.c
kernel/kprobes.c
kernel/module.c
kernel/mutex.c
kernel/printk.c
kernel/rcupdate.c
kernel/rcutiny.c [new file with mode: 0644]
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/sched.c
kernel/signal.c
kernel/smp.c
kernel/softirq.c
kernel/spinlock.c
kernel/srcu.c
kernel/sysctl.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/ring_buffer_benchmark.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_clock.c
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_export.c
kernel/trace/trace_syscalls.c
lib/Kconfig.debug
lib/kernel_lock.c
lib/ratelimit.c
lib/swiotlb.c
mm/bootmem.c
mm/mmap.c
net/core/sysctl_net_core.c
net/core/utils.c
scripts/recordmcount.pl
scripts/selinux/Makefile
scripts/selinux/genheaders/.gitignore [new file with mode: 0644]
scripts/selinux/genheaders/Makefile [new file with mode: 0644]
scripts/selinux/genheaders/genheaders.c [new file with mode: 0644]
scripts/selinux/mdp/mdp.c
security/Kconfig
security/Makefile
security/capability.c
security/commoncap.c
security/integrity/ima/Kconfig
security/lsm_audit.c
security/min_addr.c
security/root_plug.c [deleted file]
security/security.c
security/selinux/.gitignore [new file with mode: 0644]
security/selinux/Makefile
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/av_inherit.h [deleted file]
security/selinux/include/av_perm_to_string.h [deleted file]
security/selinux/include/av_permissions.h [deleted file]
security/selinux/include/avc_ss.h
security/selinux/include/class_to_string.h [deleted file]
security/selinux/include/classmap.h [new file with mode: 0644]
security/selinux/include/common_perm_to_string.h [deleted file]
security/selinux/include/flask.h [deleted file]
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/Makefile
security/selinux/ss/mls.c
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c
security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/realpath.c
sound/pcmcia/pdaudiocf/pdaudiocf.c
sound/pcmcia/vx/vxpocket.c

index 187bbf1..8608fd8 100644 (file)
 CONFIG_RCU_TRACE debugfs Files and Formats
 
 
-The rcupreempt and rcutree implementations of RCU provide debugfs trace
-output that summarizes counters and state.  This information is useful for
-debugging RCU itself, and can sometimes also help to debug abuses of RCU.
-Note that the rcuclassic implementation of RCU does not provide debugfs
-trace output.
-
-The following sections describe the debugfs files and formats for
-preemptable RCU (rcupreempt) and hierarchical RCU (rcutree).
-
-
-Preemptable RCU debugfs Files and Formats
-
-This implementation of RCU provides three debugfs files under the
-top-level directory RCU: rcu/rcuctrs (which displays the per-CPU
-counters used by preemptable RCU) rcu/rcugp (which displays grace-period
-counters), and rcu/rcustats (which internal counters for debugging RCU).
-
-The output of "cat rcu/rcuctrs" looks as follows:
-
-CPU last cur F M
-  0    5  -5 0 0
-  1   -1   0 0 0
-  2    0   1 0 0
-  3    0   1 0 0
-  4    0   1 0 0
-  5    0   1 0 0
-  6    0   2 0 0
-  7    0  -1 0 0
-  8    0   1 0 0
-ggp = 26226, state = waitzero
-
-The per-CPU fields are as follows:
-
-o      "CPU" gives the CPU number.  Offline CPUs are not displayed.
-
-o      "last" gives the value of the counter that is being decremented
-       for the current grace period phase.  In the example above,
-       the counters sum to 4, indicating that there are still four
-       RCU read-side critical sections still running that started
-       before the last counter flip.
-
-o      "cur" gives the value of the counter that is currently being
-       both incremented (by rcu_read_lock()) and decremented (by
-       rcu_read_unlock()).  In the example above, the counters sum to
-       1, indicating that there is only one RCU read-side critical section
-       still running that started after the last counter flip.
-
-o      "F" indicates whether RCU is waiting for this CPU to acknowledge
-       a counter flip.  In the above example, RCU is not waiting on any,
-       which is consistent with the state being "waitzero" rather than
-       "waitack".
-
-o      "M" indicates whether RCU is waiting for this CPU to execute a
-       memory barrier.  In the above example, RCU is not waiting on any,
-       which is consistent with the state being "waitzero" rather than
-       "waitmb".
-
-o      "ggp" is the global grace-period counter.
-
-o      "state" is the RCU state, which can be one of the following:
-
-       o       "idle": there is no grace period in progress.
-
-       o       "waitack": RCU just incremented the global grace-period
-               counter, which has the effect of reversing the roles of
-               the "last" and "cur" counters above, and is waiting for
-               all the CPUs to acknowledge the flip.  Once the flip has
-               been acknowledged, CPUs will no longer be incrementing
-               what are now the "last" counters, so that their sum will
-               decrease monotonically down to zero.
-
-       o       "waitzero": RCU is waiting for the sum of the "last" counters
-               to decrease to zero.
-
-       o       "waitmb": RCU is waiting for each CPU to execute a memory
-               barrier, which ensures that instructions from a given CPU's
-               last RCU read-side critical section cannot be reordered
-               with instructions following the memory-barrier instruction.
-
-The output of "cat rcu/rcugp" looks as follows:
-
-oldggp=48870  newggp=48873
-
-Note that reading from this file provokes a synchronize_rcu().  The
-"oldggp" value is that of "ggp" from rcu/rcuctrs above, taken before
-executing the synchronize_rcu(), and the "newggp" value is also the
-"ggp" value, but taken after the synchronize_rcu() command returns.
-
-
-The output of "cat rcu/rcugp" looks as follows:
-
-na=1337955 nl=40 wa=1337915 wl=44 da=1337871 dl=0 dr=1337871 di=1337871
-1=50989 e1=6138 i1=49722 ie1=82 g1=49640 a1=315203 ae1=265563 a2=49640
-z1=1401244 ze1=1351605 z2=49639 m1=5661253 me1=5611614 m2=49639
-
-These are counters tracking internal preemptable-RCU events, however,
-some of them may be useful for debugging algorithms using RCU.  In
-particular, the "nl", "wl", and "dl" values track the number of RCU
-callbacks in various states.  The fields are as follows:
-
-o      "na" is the total number of RCU callbacks that have been enqueued
-       since boot.
-
-o      "nl" is the number of RCU callbacks waiting for the previous
-       grace period to end so that they can start waiting on the next
-       grace period.
-
-o      "wa" is the total number of RCU callbacks that have started waiting
-       for a grace period since boot.  "na" should be roughly equal to
-       "nl" plus "wa".
-
-o      "wl" is the number of RCU callbacks currently waiting for their
-       grace period to end.
-
-o      "da" is the total number of RCU callbacks whose grace periods
-       have completed since boot.  "wa" should be roughly equal to
-       "wl" plus "da".
-
-o      "dr" is the total number of RCU callbacks that have been removed
-       from the list of callbacks ready to invoke.  "dr" should be roughly
-       equal to "da".
-
-o      "di" is the total number of RCU callbacks that have been invoked
-       since boot.  "di" should be roughly equal to "da", though some
-       early versions of preemptable RCU had a bug so that only the
-       last CPU's count of invocations was displayed, rather than the
-       sum of all CPU's counts.
-
-o      "1" is the number of calls to rcu_try_flip().  This should be
-       roughly equal to the sum of "e1", "i1", "a1", "z1", and "m1"
-       described below.  In other words, the number of times that
-       the state machine is visited should be equal to the sum of the
-       number of times that each state is visited plus the number of
-       times that the state-machine lock acquisition failed.
-
-o      "e1" is the number of times that rcu_try_flip() was unable to
-       acquire the fliplock.
-
-o      "i1" is the number of calls to rcu_try_flip_idle().
-
-o      "ie1" is the number of times rcu_try_flip_idle() exited early
-       due to the calling CPU having no work for RCU.
-
-o      "g1" is the number of times that rcu_try_flip_idle() decided
-       to start a new grace period.  "i1" should be roughly equal to
-       "ie1" plus "g1".
-
-o      "a1" is the number of calls to rcu_try_flip_waitack().
-
-o      "ae1" is the number of times that rcu_try_flip_waitack() found
-       that at least one CPU had not yet acknowledge the new grace period
-       (AKA "counter flip").
-
-o      "a2" is the number of time rcu_try_flip_waitack() found that
-       all CPUs had acknowledged.  "a1" should be roughly equal to
-       "ae1" plus "a2".  (This particular output was collected on
-       a 128-CPU machine, hence the smaller-than-usual fraction of
-       calls to rcu_try_flip_waitack() finding all CPUs having already
-       acknowledged.)
-
-o      "z1" is the number of calls to rcu_try_flip_waitzero().
-
-o      "ze1" is the number of times that rcu_try_flip_waitzero() found
-       that not all of the old RCU read-side critical sections had
-       completed.
-
-o      "z2" is the number of times that rcu_try_flip_waitzero() finds
-       the sum of the counters equal to zero, in other words, that
-       all of the old RCU read-side critical sections had completed.
-       The value of "z1" should be roughly equal to "ze1" plus
-       "z2".
-
-o      "m1" is the number of calls to rcu_try_flip_waitmb().
-
-o      "me1" is the number of times that rcu_try_flip_waitmb() finds
-       that at least one CPU has not yet executed a memory barrier.
-
-o      "m2" is the number of times that rcu_try_flip_waitmb() finds that
-       all CPUs have executed a memory barrier.
+The rcutree implementation of RCU provides debugfs trace output that
+summarizes counters and state.  This information is useful for debugging
+RCU itself, and can sometimes also help to debug abuses of RCU.
+The following sections describe the debugfs files and formats.
 
 
 Hierarchical RCU debugfs Files and Formats
@@ -210,9 +35,10 @@ rcu_bh:
   6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
   7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
 
-The first section lists the rcu_data structures for rcu, the second for
-rcu_bh.  Each section has one line per CPU, or eight for this 8-CPU system.
-The fields are as follows:
+The first section lists the rcu_data structures for rcu_sched, the second
+for rcu_bh.  Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
+additional section for rcu_preempt.  Each section has one line per CPU,
+or eight for this 8-CPU system.  The fields are as follows:
 
 o      The number at the beginning of each line is the CPU number.
        CPUs numbers followed by an exclamation mark are offline,
@@ -223,9 +49,9 @@ o    The number at the beginning of each line is the CPU number.
 
 o      "c" is the count of grace periods that this CPU believes have
        completed.  CPUs in dynticks idle mode may lag quite a ways
-       behind, for example, CPU 4 under "rcu" above, which has slept
-       through the past 25 RCU grace periods.  It is not unusual to
-       see CPUs lagging by thousands of grace periods.
+       behind, for example, CPU 4 under "rcu_sched" above, which has
+       slept through the past 25 RCU grace periods.  It is not unusual
+       to see CPUs lagging by thousands of grace periods.
 
 o      "g" is the count of grace periods that this CPU believes have
        started.  Again, CPUs in dynticks idle mode may lag behind.
@@ -308,8 +134,10 @@ The output of "cat rcu/rcugp" looks as follows:
 rcu_sched: completed=33062  gpnum=33063
 rcu_bh: completed=464  gpnum=464
 
-Again, this output is for both "rcu" and "rcu_bh".  The fields are
-taken from the rcu_state structure, and are as follows:
+Again, this output is for both "rcu_sched" and "rcu_bh".  Note that
+kernels built with CONFIG_TREE_PREEMPT_RCU will have an additional
+"rcu_preempt" line.  The fields are taken from the rcu_state structure,
+and are as follows:
 
 o      "completed" is the number of grace periods that have completed.
        It is comparable to the "c" field from rcu/rcudata in that a
@@ -324,23 +152,24 @@ o "gpnum" is the number of grace periods that have started.  It is
        If these two fields are equal (as they are for "rcu_bh" above),
        then there is no grace period in progress, in other words, RCU
        is idle.  On the other hand, if the two fields differ (as they
-       do for "rcu" above), then an RCU grace period is in progress.
+       do for "rcu_sched" above), then an RCU grace period is in progress.
 
 
 The output of "cat rcu/rcuhier" looks as follows, with very long lines:
 
-c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6
-1/1 0:127 ^0    
-3/3 0:35 ^0    0/0 36:71 ^1    0/0 72:107 ^2    0/0 108:127 ^3    
-3/3f 0:5 ^0    2/3 6:11 ^1    0/0 12:17 ^2    0/0 18:23 ^3    0/0 24:29 ^4    0/0 30:35 ^5    0/0 36:41 ^0    0/0 42:47 ^1    0/0 48:53 ^2    0/0 54:59 ^3    0/0 60:65 ^4    0/0 66:71 ^5    0/0 72:77 ^0    0/0 78:83 ^1    0/0 84:89 ^2    0/0 90:95 ^3    0/0 96:101 ^4    0/0 102:107 ^5    0/0 108:113 ^0    0/0 114:119 ^1    0/0 120:125 ^2    0/0 126:127 ^3    
+c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 oqlen=0
+1/1 .>. 0:127 ^0    
+3/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3    
+3/3f .>. 0:5 ^0    2/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3    
 rcu_bh:
-c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0
-0/1 0:127 ^0    
-0/3 0:35 ^0    0/0 36:71 ^1    0/0 72:107 ^2    0/0 108:127 ^3    
-0/3f 0:5 ^0    0/3 6:11 ^1    0/0 12:17 ^2    0/0 18:23 ^3    0/0 24:29 ^4    0/0 30:35 ^5    0/0 36:41 ^0    0/0 42:47 ^1    0/0 48:53 ^2    0/0 54:59 ^3    0/0 60:65 ^4    0/0 66:71 ^5    0/0 72:77 ^0    0/0 78:83 ^1    0/0 84:89 ^2    0/0 90:95 ^3    0/0 96:101 ^4    0/0 102:107 ^5    0/0 108:113 ^0    0/0 114:119 ^1    0/0 120:125 ^2    0/0 126:127 ^3
+c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 oqlen=0
+0/1 .>. 0:127 ^0    
+0/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3    
+0/3f .>. 0:5 ^0    0/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3
 
-This is once again split into "rcu" and "rcu_bh" portions.  The fields are
-as follows:
+This is once again split into "rcu_sched" and "rcu_bh" portions,
+and CONFIG_TREE_PREEMPT_RCU kernels will again have an additional
+"rcu_preempt" section.  The fields are as follows:
 
 o      "c" is exactly the same as "completed" under rcu/rcugp.
 
@@ -372,6 +201,11 @@ o  "fqlh" is the number of calls to force_quiescent_state() that
        exited immediately (without even being counted in nfqs above)
        due to contention on ->fqslock.
 
+o      "oqlen" is the number of callbacks on the "orphan" callback
+       list.  RCU callbacks are placed on this list by CPUs going
+       offline, and are "adopted" either by the CPU helping the outgoing
+       CPU or by the next rcu_barrier*() call, whichever comes first.
+
 o      Each element of the form "1/1 0:127 ^0" represents one struct
        rcu_node.  Each line represents one level of the hierarchy, from
        root to leaves.  It is best to think of the rcu_data structures
@@ -379,7 +213,7 @@ o   Each element of the form "1/1 0:127 ^0" represents one struct
        might be either one, two, or three levels of rcu_node structures,
        depending on the relationship between CONFIG_RCU_FANOUT and
        CONFIG_NR_CPUS.
-       
+
        o       The numbers separated by the "/" are the qsmask followed
                by the qsmaskinit.  The qsmask will have one bit
                set for each entity in the next lower level that
@@ -389,10 +223,19 @@ o Each element of the form "1/1 0:127 ^0" represents one struct
                The value of qsmaskinit is assigned to that of qsmask
                at the beginning of each grace period.
 
-               For example, for "rcu", the qsmask of the first entry
-               of the lowest level is 0x14, meaning that we are still
-               waiting for CPUs 2 and 4 to check in for the current
-               grace period.
+               For example, for "rcu_sched", the qsmask of the first
+               entry of the lowest level is 0x14, meaning that we
+               are still waiting for CPUs 2 and 4 to check in for the
+               current grace period.
+
+       o       The characters separated by the ">" indicate the state
+               of the blocked-tasks lists.  A "T" preceding the ">"
+               indicates that at least one task blocked in an RCU
+               read-side critical section blocks the current grace
+               period, while a "." preceding the ">" indicates otherwise.
+               The character following the ">" indicates similarly for
+               the next grace period.  A "T" should appear in this
+               field only for rcu-preempt.
 
        o       The numbers separated by the ":" are the range of CPUs
                served by this struct rcu_node.  This can be helpful
@@ -431,8 +274,9 @@ rcu_bh:
   6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
   7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
 
-As always, this is once again split into "rcu" and "rcu_bh" portions.
-The fields are as follows:
+As always, this is once again split into "rcu_sched" and "rcu_bh"
+portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional
+"rcu_preempt" section.  The fields are as follows:
 
 o      "np" is the number of times that __rcu_pending() has been invoked
        for the corresponding flavor of RCU.
index e41a7fe..d542ca2 100644 (file)
@@ -830,7 +830,7 @@ sched:      Critical sections       Grace period            Barrier
 SRCU:  Critical sections       Grace period            Barrier
 
        srcu_read_lock          synchronize_srcu        N/A
-       srcu_read_unlock
+       srcu_read_unlock        synchronize_srcu_expedited
 
 SRCU:  Initialization/cleanup
        init_srcu_struct
index e1efc40..e151b2a 100644 (file)
@@ -65,6 +65,7 @@ aicdb.h*
 asm-offsets.h
 asm_offsets.h
 autoconf.h*
+av_permissions.h
 bbootsect
 bin2c
 binkernel.spec
@@ -95,12 +96,14 @@ docproc
 elf2ecoff
 elfconfig.h*
 fixdep
+flask.h
 fore200e_mkfirm
 fore200e_pca_fw.c*
 gconf
 gen-devlist
 gen_crc32table
 gen_init_cpio
+genheaders
 genksyms
 *_gray256.c
 ihex2fw
index 52c34b4..d8ce217 100644 (file)
@@ -85,7 +85,6 @@ parameter is applicable:
        PPT     Parallel port support is enabled.
        PS2     Appropriate PS/2 support is enabled.
        RAM     RAM disk support is enabled.
-       ROOTPLUG The example Root Plug LSM is enabled.
        S390    S390 architecture is enabled.
        SCSI    Appropriate SCSI support is enabled.
                        A lot of drivers has their options described inside of
@@ -779,6 +778,13 @@ and is between 256 and 4096 characters. It is defined in the file
                        by the set_ftrace_notrace file in the debugfs
                        tracing directory.
 
+       ftrace_graph_filter=[function-list]
+                       [FTRACE] Limit the top level callers functions traced
+                       by the function graph tracer at boot up.
+                       function-list is a comma separated list of functions
+                       that can be changed at run time by the
+                       set_graph_function file in the debugfs tracing directory.
+
        gamecon.map[2|3]=
                        [HW,JOY] Multisystem joystick and NES/SNES/PSX pad
                        support via parallel port (up to 5 devices per port)
@@ -2032,8 +2038,15 @@ and is between 256 and 4096 characters. It is defined in the file
 
        print-fatal-signals=
                        [KNL] debug: print fatal signals
-                       print-fatal-signals=1: print segfault info to
-                       the kernel console.
+
+                       If enabled, warn about various signal handling
+                       related application anomalies: too many signals,
+                       too many POSIX.1 timers, fatal signals causing a
+                       coredump - etc.
+
+                       If you hit the warning due to signal overflow,
+                       you might want to try "ulimit -i unlimited".
+
                        default: off.
 
        printk.time=    Show timing data prefixed to each printk message line
@@ -2164,15 +2177,6 @@ and is between 256 and 4096 characters. It is defined in the file
                        Useful for devices that are detected asynchronously
                        (e.g. USB and MMC devices).
 
-       root_plug.vendor_id=
-                       [ROOTPLUG] Override the default vendor ID
-
-       root_plug.product_id=
-                       [ROOTPLUG] Override the default product ID
-
-       root_plug.debug=
-                       [ROOTPLUG] Enable debugging output
-
        rw              [KNL] Mount root device read-write on boot
 
        S               [KNL] Run init in single mode
index 0599343..446f43b 100644 (file)
@@ -1,5 +1,17 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* no cs_error / CS_CHECK / CONFIG_PCMCIA_DEBUG (as of 2.6.33)
+   Instead of the cs_error() callback or the CS_CHECK() macro, please use
+   Linux-style checking of return values, and -- if necessary -- debug
+   messages using "dev_dbg()" or "pr_debug()".
+
+* New CIS tuple access (as of 2.6.33)
+   Instead of pcmcia_get_{first,next}_tuple(), pcmcia_get_tuple_data() and
+   pcmcia_parse_tuple(), a driver shall use "pcmcia_get_tuple()" if it is
+   only interested in one (raw) tuple, or "pcmcia_loop_tuple()" if it is
+   interested in all tuples of one type. To decode the MAC from CISTPL_FUNCE,
+   a new helper "pcmcia_get_mac_from_cis()" was added.
+
 * New configuration loop helper (as of 2.6.28)
    By calling pcmcia_loop_config(), a driver can iterate over all available
    configuration options. During a driver's probe() phase, one doesn't need
index 7003e10..641a1ef 100644 (file)
@@ -213,10 +213,19 @@ If you can't trace NMI functions, then skip this option.
 <details to be filled>
 
 
-HAVE_FTRACE_SYSCALLS
+HAVE_SYSCALL_TRACEPOINTS
 ---------------------
 
-<details to be filled>
+You need very few things to get the syscalls tracing in an arch.
+
+- Have a NR_syscalls variable in <asm/unistd.h> that provides the number
+  of syscalls supported by the arch.
+- Implement arch_syscall_addr() that resolves a syscall address from a
+  syscall number.
+- Support the TIF_SYSCALL_TRACEPOINT thread flags
+- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
+  in the ptrace syscalls tracing path.
+- Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
 
 
 HAVE_FTRACE_MCOUNT_RECORD
index 1186b19..89ceb40 100644 (file)
@@ -3023,11 +3023,8 @@ S:       Maintained
 F:     fs/autofs4/
 
 KERNEL BUILD
-M:     Sam Ravnborg <sam@ravnborg.org>
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git
 L:     linux-kbuild@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     Documentation/kbuild/
 F:     Makefile
 F:     scripts/Makefile.*
index ad82601..33d4732 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 32
-EXTRAVERSION = -rc8
+EXTRAVERSION =
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
@@ -379,6 +379,7 @@ export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exc
 PHONY += scripts_basic
 scripts_basic:
        $(Q)$(MAKE) $(build)=scripts/basic
+       $(Q)rm -f .tmp_quiet_recordmcount
 
 # To avoid any implicit rule to kick in, define an empty command.
 scripts/basic/%: scripts_basic ;
index 331d45b..2aa373c 100644 (file)
@@ -52,7 +52,7 @@
 #define BUG()                                                          \
        do {                                                            \
                _BUG_OR_WARN(0);                                        \
-               for (;;);                                               \
+               unreachable();                                          \
        } while (0)
 
 #define WARN_ON(condition)                                                     \
index dcbaea7..f0acde6 100644 (file)
@@ -4,8 +4,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/swiotlb.h>
 
-extern int swiotlb_force;
-
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
 extern void pci_swiotlb_init(void);
index 285aae8..53292ab 100644 (file)
@@ -41,7 +41,7 @@ struct dma_map_ops swiotlb_dma_ops = {
 void __init swiotlb_dma_init(void)
 {
        dma_ops = &swiotlb_dma_ops;
-       swiotlb_init();
+       swiotlb_init(1);
 }
 
 void __init pci_swiotlb_init(void)
@@ -51,7 +51,7 @@ void __init pci_swiotlb_init(void)
                swiotlb = 1;
                printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
                machvec_init("dig");
-               swiotlb_init();
+               swiotlb_init(1);
                dma_ops = &swiotlb_dma_ops;
 #else
                panic("Unable to find Intel IOMMU");
index 6cf29c2..540c98a 100644 (file)
@@ -11,9 +11,7 @@
 static inline void __noreturn BUG(void)
 {
        __asm__ __volatile__("break %0" : : "i" (BRK_BUG));
-       /* Fool GCC into thinking the function doesn't return. */
-       while (1)
-               ;
+       unreachable();
 }
 
 #define HAVE_ARCH_BUG
index 3fe1fcf..fe0d798 100644 (file)
@@ -306,6 +306,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,
 
        if (cpu_has_llsc && R10000_LLSC_WAR) {
                __asm__ __volatile__ (
+               "       .set    mips3                                   \n"
                "       li      %[err], 0                               \n"
                "1:     ll      %[old], (%[addr])                       \n"
                "       move    %[tmp], %[new]                          \n"
@@ -320,6 +321,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,
                "       "STR(PTR)"      1b, 4b                          \n"
                "       "STR(PTR)"      2b, 4b                          \n"
                "       .previous                                       \n"
+               "       .set    mips0                                   \n"
                : [old] "=&r" (old),
                  [err] "=&r" (err),
                  [tmp] "=&r" (tmp)
@@ -329,6 +331,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,
                : "memory");
        } else if (cpu_has_llsc) {
                __asm__ __volatile__ (
+               "       .set    mips3                                   \n"
                "       li      %[err], 0                               \n"
                "1:     ll      %[old], (%[addr])                       \n"
                "       move    %[tmp], %[new]                          \n"
@@ -347,6 +350,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,
                "       "STR(PTR)"      1b, 5b                          \n"
                "       "STR(PTR)"      2b, 5b                          \n"
                "       .previous                                       \n"
+               "       .set    mips0                                   \n"
                : [old] "=&r" (old),
                  [err] "=&r" (err),
                  [tmp] "=&r" (tmp)
index 9f40e1f..041fc1a 100644 (file)
@@ -110,7 +110,6 @@ static struct korina_device korina_dev0_data = {
 static struct platform_device korina_dev0 = {
        .id = -1,
        .name = "korina",
-       .dev.driver_data = &korina_dev0_data,
        .resource = korina_dev0_res,
        .num_resources = ARRAY_SIZE(korina_dev0_res),
 };
@@ -332,6 +331,8 @@ static int __init plat_setup_devices(void)
        /* set the uart clock to the current cpu frequency */
        rb532_uart_res[0].uartclk = idt_cpu_freq;
 
+       dev_set_drvdata(&korina_dev0.dev, &korina_dev0_data);
+
        return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
 }
 
index 53bcf3d..b152de3 100644 (file)
@@ -345,7 +345,7 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_SWIOTLB
        if (ppc_swiotlb_enable)
-               swiotlb_init();
+               swiotlb_init(1);
 #endif
 
        paging_init();
index 04f638d..df2c9e9 100644 (file)
@@ -550,7 +550,7 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_SWIOTLB
        if (ppc_swiotlb_enable)
-               swiotlb_init();
+               swiotlb_init(1);
 #endif
 
        paging_init();
index 43c0aca..16c6730 100644 (file)
@@ -95,6 +95,34 @@ config S390
        select HAVE_ARCH_TRACEHOOK
        select INIT_ALL_POSSIBLE
        select HAVE_PERF_EVENTS
+       select ARCH_INLINE_SPIN_TRYLOCK
+       select ARCH_INLINE_SPIN_TRYLOCK_BH
+       select ARCH_INLINE_SPIN_LOCK
+       select ARCH_INLINE_SPIN_LOCK_BH
+       select ARCH_INLINE_SPIN_LOCK_IRQ
+       select ARCH_INLINE_SPIN_LOCK_IRQSAVE
+       select ARCH_INLINE_SPIN_UNLOCK
+       select ARCH_INLINE_SPIN_UNLOCK_BH
+       select ARCH_INLINE_SPIN_UNLOCK_IRQ
+       select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE
+       select ARCH_INLINE_READ_TRYLOCK
+       select ARCH_INLINE_READ_LOCK
+       select ARCH_INLINE_READ_LOCK_BH
+       select ARCH_INLINE_READ_LOCK_IRQ
+       select ARCH_INLINE_READ_LOCK_IRQSAVE
+       select ARCH_INLINE_READ_UNLOCK
+       select ARCH_INLINE_READ_UNLOCK_BH
+       select ARCH_INLINE_READ_UNLOCK_IRQ
+       select ARCH_INLINE_READ_UNLOCK_IRQRESTORE
+       select ARCH_INLINE_WRITE_TRYLOCK
+       select ARCH_INLINE_WRITE_LOCK
+       select ARCH_INLINE_WRITE_LOCK_BH
+       select ARCH_INLINE_WRITE_LOCK_IRQ
+       select ARCH_INLINE_WRITE_LOCK_IRQSAVE
+       select ARCH_INLINE_WRITE_UNLOCK
+       select ARCH_INLINE_WRITE_UNLOCK_BH
+       select ARCH_INLINE_WRITE_UNLOCK_IRQ
+       select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 
 config SCHED_OMIT_FRAME_POINTER
        bool
index 7efd0ab..efb74fd 100644 (file)
@@ -49,7 +49,7 @@
 
 #define BUG() do {                                     \
        __EMIT_BUG(0);                                  \
-       for (;;);                                       \
+       unreachable();                                  \
 } while (0)
 
 #define WARN_ON(x) ({                                  \
index 41ce686..c9af0d1 100644 (file)
@@ -191,33 +191,4 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
 #define _raw_read_relax(lock)  cpu_relax()
 #define _raw_write_relax(lock) cpu_relax()
 
-#define __always_inline__spin_lock
-#define __always_inline__read_lock
-#define __always_inline__write_lock
-#define __always_inline__spin_lock_bh
-#define __always_inline__read_lock_bh
-#define __always_inline__write_lock_bh
-#define __always_inline__spin_lock_irq
-#define __always_inline__read_lock_irq
-#define __always_inline__write_lock_irq
-#define __always_inline__spin_lock_irqsave
-#define __always_inline__read_lock_irqsave
-#define __always_inline__write_lock_irqsave
-#define __always_inline__spin_trylock
-#define __always_inline__read_trylock
-#define __always_inline__write_trylock
-#define __always_inline__spin_trylock_bh
-#define __always_inline__spin_unlock
-#define __always_inline__read_unlock
-#define __always_inline__write_unlock
-#define __always_inline__spin_unlock_bh
-#define __always_inline__read_unlock_bh
-#define __always_inline__write_unlock_bh
-#define __always_inline__spin_unlock_irq
-#define __always_inline__read_unlock_irq
-#define __always_inline__write_unlock_irq
-#define __always_inline__spin_unlock_irqrestore
-#define __always_inline__read_unlock_irqrestore
-#define __always_inline__write_unlock_irqrestore
-
 #endif /* __ASM_SPINLOCK_H */
index f5fe34d..5a82bc6 100644 (file)
@@ -203,73 +203,10 @@ out:
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 
-extern unsigned long __start_syscalls_metadata[];
-extern unsigned long __stop_syscalls_metadata[];
 extern unsigned int sys_call_table[];
 
-static struct syscall_metadata **syscalls_metadata;
-
-struct syscall_metadata *syscall_nr_to_meta(int nr)
-{
-       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
-               return NULL;
-
-       return syscalls_metadata[nr];
-}
-
-int syscall_name_to_nr(char *name)
-{
-       int i;
-
-       if (!syscalls_metadata)
-               return -1;
-       for (i = 0; i < NR_syscalls; i++)
-               if (syscalls_metadata[i])
-                       if (!strcmp(syscalls_metadata[i]->name, name))
-                               return i;
-       return -1;
-}
-
-void set_syscall_enter_id(int num, int id)
-{
-       syscalls_metadata[num]->enter_id = id;
-}
-
-void set_syscall_exit_id(int num, int id)
+unsigned long __init arch_syscall_addr(int nr)
 {
-       syscalls_metadata[num]->exit_id = id;
-}
-
-static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
-{
-       struct syscall_metadata *start;
-       struct syscall_metadata *stop;
-       char str[KSYM_SYMBOL_LEN];
-
-       start = (struct syscall_metadata *)__start_syscalls_metadata;
-       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
-       kallsyms_lookup(syscall, NULL, NULL, NULL, str);
-
-       for ( ; start < stop; start++) {
-               if (start->name && !strcmp(start->name + 3, str + 3))
-                       return start;
-       }
-       return NULL;
-}
-
-static int __init arch_init_ftrace_syscalls(void)
-{
-       struct syscall_metadata *meta;
-       int i;
-       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
-                                   GFP_KERNEL);
-       if (!syscalls_metadata)
-               return -ENOMEM;
-       for (i = 0; i < NR_syscalls; i++) {
-               meta = find_syscall_meta((unsigned long)sys_call_table[i]);
-               syscalls_metadata[i] = meta;
-       }
-       return 0;
+       return (unsigned long)sys_call_table[nr];
 }
-arch_initcall(arch_init_ftrace_syscalls);
 #endif
index 4b18089..5af2982 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
 #include <linux/irqreturn.h>
 
 #ifdef CONFIG_AMD_IOMMU
-extern int amd_iommu_init(void);
-extern int amd_iommu_init_dma_ops(void);
-extern int amd_iommu_init_passthrough(void);
+
 extern void amd_iommu_detect(void);
-extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
-extern void amd_iommu_flush_all_domains(void);
-extern void amd_iommu_flush_all_devices(void);
-extern void amd_iommu_shutdown(void);
-extern void amd_iommu_apply_erratum_63(u16 devid);
+
 #else
-static inline int amd_iommu_init(void) { return -ENODEV; }
+
 static inline void amd_iommu_detect(void) { }
-static inline void amd_iommu_shutdown(void) { }
+
 #endif
 
 #endif /* _ASM_X86_AMD_IOMMU_H */
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h
new file mode 100644 (file)
index 0000000..84786fb
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _ASM_X86_AMD_IOMMU_PROTO_H
+#define _ASM_X86_AMD_IOMMU_PROTO_H
+
+struct amd_iommu;
+
+extern int amd_iommu_init_dma_ops(void);
+extern int amd_iommu_init_passthrough(void);
+extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
+extern void amd_iommu_flush_all_domains(void);
+extern void amd_iommu_flush_all_devices(void);
+extern void amd_iommu_apply_erratum_63(u16 devid);
+extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
+
+#ifndef CONFIG_AMD_IOMMU_STATS
+
+static inline void amd_iommu_stats_init(void) { }
+
+#endif /* !CONFIG_AMD_IOMMU_STATS */
+
+#endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
index 2a2cc7a..ba19ad4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
 #include <linux/spinlock.h>
 
 /*
+ * Maximum number of IOMMUs supported
+ */
+#define MAX_IOMMUS     32
+
+/*
  * some size calculation constants
  */
 #define DEV_TABLE_ENTRY_SIZE           32
@@ -206,6 +211,9 @@ extern bool amd_iommu_dump;
                        printk(KERN_INFO "AMD-Vi: " format, ## arg);    \
        } while(0);
 
+/* global flag if IOMMUs cache non-present entries */
+extern bool amd_iommu_np_cache;
+
 /*
  * Make iterating over all IOMMUs easier
  */
@@ -226,6 +234,8 @@ extern bool amd_iommu_dump;
  * independent of their use.
  */
 struct protection_domain {
+       struct list_head list;  /* for list of all protection domains */
+       struct list_head dev_list; /* List of all devices in this domain */
        spinlock_t lock;        /* mostly used to lock the page table*/
        u16 id;                 /* the domain id written to the device table */
        int mode;               /* paging mode (0-6 levels) */
@@ -233,7 +243,20 @@ struct protection_domain {
        unsigned long flags;    /* flags to find out type of domain */
        bool updated;           /* complete domain flush required */
        unsigned dev_cnt;       /* devices assigned to this domain */
+       unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */
        void *priv;             /* private data */
+
+};
+
+/*
+ * This struct contains device specific data for the IOMMU
+ */
+struct iommu_dev_data {
+       struct list_head list;            /* For domain->dev_list */
+       struct device *dev;               /* Device this data belong to */
+       struct device *alias;             /* The Alias Device */
+       struct protection_domain *domain; /* Domain the device is bound to */
+       atomic_t bind;                    /* Domain attach reverent count */
 };
 
 /*
@@ -291,6 +314,9 @@ struct dma_ops_domain {
 struct amd_iommu {
        struct list_head list;
 
+       /* Index within the IOMMU array */
+       int index;
+
        /* locks the accesses to the hardware */
        spinlock_t lock;
 
@@ -357,6 +383,21 @@ struct amd_iommu {
 extern struct list_head amd_iommu_list;
 
 /*
+ * Array with pointers to each IOMMU struct
+ * The indices are referenced in the protection domains
+ */
+extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
+
+/* Number of IOMMUs present in the system */
+extern int amd_iommus_present;
+
+/*
+ * Declarations for the global list of all protection domains
+ */
+extern spinlock_t amd_iommu_pd_lock;
+extern struct list_head amd_iommu_pd_list;
+
+/*
  * Structure defining one entry in the device table
  */
 struct dev_table_entry {
@@ -416,15 +457,9 @@ extern unsigned amd_iommu_aperture_order;
 /* largest PCI device id we expect translation requests for */
 extern u16 amd_iommu_last_bdf;
 
-/* data structures for protection domain handling */
-extern struct protection_domain **amd_iommu_pd_table;
-
 /* allocation bitmap for domain ids */
 extern unsigned long *amd_iommu_pd_alloc_bitmap;
 
-/* will be 1 if device isolation is enabled */
-extern bool amd_iommu_isolate;
-
 /*
  * If true, the addresses will be flushed on unmap time, not when
  * they are reused
@@ -462,11 +497,6 @@ struct __iommu_counter {
 #define ADD_STATS_COUNTER(name, x)
 #define SUB_STATS_COUNTER(name, x)
 
-static inline void amd_iommu_stats_init(void) { }
-
 #endif /* CONFIG_AMD_IOMMU_STATS */
 
-/* some function prototypes */
-extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
-
 #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
index d9cf1cd..f654d1b 100644 (file)
@@ -22,14 +22,14 @@ do {                                                                \
                     ".popsection"                              \
                     : : "i" (__FILE__), "i" (__LINE__),        \
                     "i" (sizeof(struct bug_entry)));           \
-       for (;;) ;                                              \
+       unreachable();                                          \
 } while (0)
 
 #else
 #define BUG()                                                  \
 do {                                                           \
        asm volatile("ud2");                                    \
-       for (;;) ;                                              \
+       unreachable();                                          \
 } while (0)
 #endif
 
index b03bedb..0918654 100644 (file)
@@ -62,10 +62,8 @@ struct cal_chipset_ops {
 extern int use_calgary;
 
 #ifdef CONFIG_CALGARY_IOMMU
-extern int calgary_iommu_init(void);
 extern void detect_calgary(void);
 #else
-static inline int calgary_iommu_init(void) { return 1; }
 static inline void detect_calgary(void) { return; }
 #endif
 
index cee34e9..029f230 100644 (file)
@@ -8,7 +8,7 @@ struct dev_archdata {
 #ifdef CONFIG_X86_64
 struct dma_map_ops *dma_ops;
 #endif
-#ifdef CONFIG_DMAR
+#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
        void *iommu; /* hook for IOMMU specific extension */
 #endif
 };
index 6a25d5d..0f6c02f 100644 (file)
@@ -20,7 +20,8 @@
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(32)
 #endif
 
-extern dma_addr_t bad_dma_address;
+#define DMA_ERROR_CODE 0
+
 extern int iommu_merge;
 extern struct device x86_dma_fallback_dev;
 extern int panic_on_overflow;
@@ -48,7 +49,7 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
        if (ops->mapping_error)
                return ops->mapping_error(dev, dma_addr);
 
-       return (dma_addr == bad_dma_address);
+       return (dma_addr == DMA_ERROR_CODE);
 }
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
index 6cfdafa..4ac5b0f 100644 (file)
@@ -35,8 +35,7 @@ extern int gart_iommu_aperture_allowed;
 extern int gart_iommu_aperture_disabled;
 
 extern void early_gart_iommu_check(void);
-extern void gart_iommu_init(void);
-extern void gart_iommu_shutdown(void);
+extern int gart_iommu_init(void);
 extern void __init gart_parse_options(char *);
 extern void gart_iommu_hole_init(void);
 
@@ -48,12 +47,6 @@ extern void gart_iommu_hole_init(void);
 static inline void early_gart_iommu_check(void)
 {
 }
-static inline void gart_iommu_init(void)
-{
-}
-static inline void gart_iommu_shutdown(void)
-{
-}
 static inline void gart_parse_options(char *options)
 {
 }
index fd6d21b..345c99c 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _ASM_X86_IOMMU_H
 #define _ASM_X86_IOMMU_H
 
-extern void pci_iommu_shutdown(void);
-extern void no_iommu_init(void);
 extern struct dma_map_ops nommu_dma_ops;
 extern int force_iommu, no_iommu;
 extern int iommu_detected;
index b9e4e20..87ffcb1 100644 (file)
@@ -3,17 +3,14 @@
 
 #include <linux/swiotlb.h>
 
-/* SWIOTLB interface */
-
-extern int swiotlb_force;
-
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
-extern void pci_swiotlb_init(void);
+extern int pci_swiotlb_init(void);
 #else
 #define swiotlb 0
-static inline void pci_swiotlb_init(void)
+static inline int pci_swiotlb_init(void)
 {
+       return 0;
 }
 #endif
 
index 2c756fd..d8e7145 100644 (file)
@@ -91,6 +91,14 @@ struct x86_init_timers {
 };
 
 /**
+ * struct x86_init_iommu - platform specific iommu setup
+ * @iommu_init:                        platform specific iommu setup
+ */
+struct x86_init_iommu {
+       int (*iommu_init)(void);
+};
+
+/**
  * struct x86_init_ops - functions for platform specific setup
  *
  */
@@ -101,6 +109,7 @@ struct x86_init_ops {
        struct x86_init_oem             oem;
        struct x86_init_paging          paging;
        struct x86_init_timers          timers;
+       struct x86_init_iommu           iommu;
 };
 
 /**
@@ -121,6 +130,7 @@ struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
        unsigned long (*get_wallclock)(void);
        int (*set_wallclock)(unsigned long nowtime);
+       void (*iommu_shutdown)(void);
 };
 
 extern struct x86_init_ops x86_init;
index 0285521..32fb091 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
@@ -28,6 +28,7 @@
 #include <asm/proto.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
+#include <asm/amd_iommu_proto.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
 
@@ -56,20 +57,115 @@ struct iommu_cmd {
        u32 data[4];
 };
 
-static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
-                            struct unity_map_entry *e);
-static struct dma_ops_domain *find_protection_domain(u16 devid);
-static u64 *alloc_pte(struct protection_domain *domain,
-                     unsigned long address, int end_lvl,
-                     u64 **pte_page, gfp_t gfp);
-static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
-                                     unsigned long start_page,
-                                     unsigned int pages);
 static void reset_iommu_command_buffer(struct amd_iommu *iommu);
-static u64 *fetch_pte(struct protection_domain *domain,
-                     unsigned long address, int map_size);
 static void update_domain(struct protection_domain *domain);
 
+/****************************************************************************
+ *
+ * Helper functions
+ *
+ ****************************************************************************/
+
+static inline u16 get_device_id(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return calc_devid(pdev->bus->number, pdev->devfn);
+}
+
+static struct iommu_dev_data *get_dev_data(struct device *dev)
+{
+       return dev->archdata.iommu;
+}
+
+/*
+ * In this function the list of preallocated protection domains is traversed to
+ * find the domain for a specific device
+ */
+static struct dma_ops_domain *find_protection_domain(u16 devid)
+{
+       struct dma_ops_domain *entry, *ret = NULL;
+       unsigned long flags;
+       u16 alias = amd_iommu_alias_table[devid];
+
+       if (list_empty(&iommu_pd_list))
+               return NULL;
+
+       spin_lock_irqsave(&iommu_pd_list_lock, flags);
+
+       list_for_each_entry(entry, &iommu_pd_list, list) {
+               if (entry->target_dev == devid ||
+                   entry->target_dev == alias) {
+                       ret = entry;
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+       return ret;
+}
+
+/*
+ * This function checks if the driver got a valid device from the caller to
+ * avoid dereferencing invalid pointers.
+ */
+static bool check_device(struct device *dev)
+{
+       u16 devid;
+
+       if (!dev || !dev->dma_mask)
+               return false;
+
+       /* No device or no PCI device */
+       if (!dev || dev->bus != &pci_bus_type)
+               return false;
+
+       devid = get_device_id(dev);
+
+       /* Out of our scope? */
+       if (devid > amd_iommu_last_bdf)
+               return false;
+
+       if (amd_iommu_rlookup_table[devid] == NULL)
+               return false;
+
+       return true;
+}
+
+static int iommu_init_device(struct device *dev)
+{
+       struct iommu_dev_data *dev_data;
+       struct pci_dev *pdev;
+       u16 devid, alias;
+
+       if (dev->archdata.iommu)
+               return 0;
+
+       dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
+       if (!dev_data)
+               return -ENOMEM;
+
+       dev_data->dev = dev;
+
+       devid = get_device_id(dev);
+       alias = amd_iommu_alias_table[devid];
+       pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
+       if (pdev)
+               dev_data->alias = &pdev->dev;
+
+       atomic_set(&dev_data->bind, 0);
+
+       dev->archdata.iommu = dev_data;
+
+
+       return 0;
+}
+
+static void iommu_uninit_device(struct device *dev)
+{
+       kfree(dev->archdata.iommu);
+}
 #ifdef CONFIG_AMD_IOMMU_STATS
 
 /*
@@ -90,7 +186,6 @@ DECLARE_STATS_COUNTER(alloced_io_mem);
 DECLARE_STATS_COUNTER(total_map_requests);
 
 static struct dentry *stats_dir;
-static struct dentry *de_isolate;
 static struct dentry *de_fflush;
 
 static void amd_iommu_stats_add(struct __iommu_counter *cnt)
@@ -108,9 +203,6 @@ static void amd_iommu_stats_init(void)
        if (stats_dir == NULL)
                return;
 
-       de_isolate = debugfs_create_bool("isolation", 0444, stats_dir,
-                                        (u32 *)&amd_iommu_isolate);
-
        de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
                                         (u32 *)&amd_iommu_unmap_flush);
 
@@ -130,12 +222,6 @@ static void amd_iommu_stats_init(void)
 
 #endif
 
-/* returns !0 if the IOMMU is caching non-present entries in its TLB */
-static int iommu_has_npcache(struct amd_iommu *iommu)
-{
-       return iommu->cap & (1UL << IOMMU_CAP_NPCACHE);
-}
-
 /****************************************************************************
  *
  * Interrupt handling functions
@@ -199,6 +285,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
                break;
        case EVENT_TYPE_ILL_CMD:
                printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
+               iommu->reset_in_progress = true;
                reset_iommu_command_buffer(iommu);
                dump_command(address);
                break;
@@ -321,11 +408,8 @@ static void __iommu_wait_for_completion(struct amd_iommu *iommu)
        status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
        writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
 
-       if (unlikely(i == EXIT_LOOP_COUNT)) {
-               spin_unlock(&iommu->lock);
-               reset_iommu_command_buffer(iommu);
-               spin_lock(&iommu->lock);
-       }
+       if (unlikely(i == EXIT_LOOP_COUNT))
+               iommu->reset_in_progress = true;
 }
 
 /*
@@ -372,26 +456,46 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
 out:
        spin_unlock_irqrestore(&iommu->lock, flags);
 
+       if (iommu->reset_in_progress)
+               reset_iommu_command_buffer(iommu);
+
        return 0;
 }
 
+static void iommu_flush_complete(struct protection_domain *domain)
+{
+       int i;
+
+       for (i = 0; i < amd_iommus_present; ++i) {
+               if (!domain->dev_iommu[i])
+                       continue;
+
+               /*
+                * Devices of this domain are behind this IOMMU
+                * We need to wait for completion of all commands.
+                */
+               iommu_completion_wait(amd_iommus[i]);
+       }
+}
+
 /*
  * Command send function for invalidating a device table entry
  */
-static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
+static int iommu_flush_device(struct device *dev)
 {
+       struct amd_iommu *iommu;
        struct iommu_cmd cmd;
-       int ret;
+       u16 devid;
 
-       BUG_ON(iommu == NULL);
+       devid = get_device_id(dev);
+       iommu = amd_iommu_rlookup_table[devid];
 
+       /* Build command */
        memset(&cmd, 0, sizeof(cmd));
        CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY);
        cmd.data[0] = devid;
 
-       ret = iommu_queue_command(iommu, &cmd);
-
-       return ret;
+       return iommu_queue_command(iommu, &cmd);
 }
 
 static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
@@ -430,11 +534,11 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
  * It invalidates a single PTE if the range to flush is within a single
  * page. Otherwise it flushes the whole TLB of the IOMMU.
  */
-static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
-               u64 address, size_t size)
+static void __iommu_flush_pages(struct protection_domain *domain,
+                               u64 address, size_t size, int pde)
 {
-       int s = 0;
-       unsigned pages = iommu_num_pages(address, size, PAGE_SIZE);
+       int s = 0, i;
+       unsigned long pages = iommu_num_pages(address, size, PAGE_SIZE);
 
        address &= PAGE_MASK;
 
@@ -447,142 +551,212 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
                s = 1;
        }
 
-       iommu_queue_inv_iommu_pages(iommu, address, domid, 0, s);
 
-       return 0;
+       for (i = 0; i < amd_iommus_present; ++i) {
+               if (!domain->dev_iommu[i])
+                       continue;
+
+               /*
+                * Devices of this domain are behind this IOMMU
+                * We need a TLB flush
+                */
+               iommu_queue_inv_iommu_pages(amd_iommus[i], address,
+                                           domain->id, pde, s);
+       }
+
+       return;
 }
 
-/* Flush the whole IO/TLB for a given protection domain */
-static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
+static void iommu_flush_pages(struct protection_domain *domain,
+                            u64 address, size_t size)
 {
-       u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-
-       INC_STATS_COUNTER(domain_flush_single);
+       __iommu_flush_pages(domain, address, size, 0);
+}
 
-       iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
+/* Flush the whole IO/TLB for a given protection domain */
+static void iommu_flush_tlb(struct protection_domain *domain)
+{
+       __iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
 }
 
 /* Flush the whole IO/TLB for a given protection domain - including PDE */
-static void iommu_flush_tlb_pde(struct amd_iommu *iommu, u16 domid)
+static void iommu_flush_tlb_pde(struct protection_domain *domain)
 {
-       u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
-
-       INC_STATS_COUNTER(domain_flush_single);
-
-       iommu_queue_inv_iommu_pages(iommu, address, domid, 1, 1);
+       __iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
 }
 
+
 /*
- * This function flushes one domain on one IOMMU
+ * This function flushes the DTEs for all devices in domain
  */
-static void flush_domain_on_iommu(struct amd_iommu *iommu, u16 domid)
+static void iommu_flush_domain_devices(struct protection_domain *domain)
 {
-       struct iommu_cmd cmd;
+       struct iommu_dev_data *dev_data;
        unsigned long flags;
 
-       __iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
-                                     domid, 1, 1);
+       spin_lock_irqsave(&domain->lock, flags);
 
-       spin_lock_irqsave(&iommu->lock, flags);
-       __iommu_queue_command(iommu, &cmd);
-       __iommu_completion_wait(iommu);
-       __iommu_wait_for_completion(iommu);
-       spin_unlock_irqrestore(&iommu->lock, flags);
+       list_for_each_entry(dev_data, &domain->dev_list, list)
+               iommu_flush_device(dev_data->dev);
+
+       spin_unlock_irqrestore(&domain->lock, flags);
 }
 
-static void flush_all_domains_on_iommu(struct amd_iommu *iommu)
+static void iommu_flush_all_domain_devices(void)
 {
-       int i;
+       struct protection_domain *domain;
+       unsigned long flags;
 
-       for (i = 1; i < MAX_DOMAIN_ID; ++i) {
-               if (!test_bit(i, amd_iommu_pd_alloc_bitmap))
-                       continue;
-               flush_domain_on_iommu(iommu, i);
+       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+
+       list_for_each_entry(domain, &amd_iommu_pd_list, list) {
+               iommu_flush_domain_devices(domain);
+               iommu_flush_complete(domain);
        }
 
+       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
+void amd_iommu_flush_all_devices(void)
+{
+       iommu_flush_all_domain_devices();
 }
 
 /*
- * This function is used to flush the IO/TLB for a given protection domain
- * on every IOMMU in the system
+ * This function uses heavy locking and may disable irqs for some time. But
+ * this is no issue because it is only called during resume.
  */
-static void iommu_flush_domain(u16 domid)
+void amd_iommu_flush_all_domains(void)
 {
-       struct amd_iommu *iommu;
+       struct protection_domain *domain;
+       unsigned long flags;
 
-       INC_STATS_COUNTER(domain_flush_all);
+       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
 
-       for_each_iommu(iommu)
-               flush_domain_on_iommu(iommu, domid);
+       list_for_each_entry(domain, &amd_iommu_pd_list, list) {
+               spin_lock(&domain->lock);
+               iommu_flush_tlb_pde(domain);
+               iommu_flush_complete(domain);
+               spin_unlock(&domain->lock);
+       }
+
+       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
 }
 
-void amd_iommu_flush_all_domains(void)
+static void reset_iommu_command_buffer(struct amd_iommu *iommu)
 {
-       struct amd_iommu *iommu;
+       pr_err("AMD-Vi: Resetting IOMMU command buffer\n");
 
-       for_each_iommu(iommu)
-               flush_all_domains_on_iommu(iommu);
+       if (iommu->reset_in_progress)
+               panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n");
+
+       amd_iommu_reset_cmd_buffer(iommu);
+       amd_iommu_flush_all_devices();
+       amd_iommu_flush_all_domains();
+
+       iommu->reset_in_progress = false;
 }
 
-static void flush_all_devices_for_iommu(struct amd_iommu *iommu)
+/****************************************************************************
+ *
+ * The functions below are used the create the page table mappings for
+ * unity mapped regions.
+ *
+ ****************************************************************************/
+
+/*
+ * This function is used to add another level to an IO page table. Adding
+ * another level increases the size of the address space by 9 bits to a size up
+ * to 64 bits.
+ */
+static bool increase_address_space(struct protection_domain *domain,
+                                  gfp_t gfp)
 {
-       int i;
+       u64 *pte;
 
-       for (i = 0; i <= amd_iommu_last_bdf; ++i) {
-               if (iommu != amd_iommu_rlookup_table[i])
-                       continue;
+       if (domain->mode == PAGE_MODE_6_LEVEL)
+               /* address space already 64 bit large */
+               return false;
 
-               iommu_queue_inv_dev_entry(iommu, i);
-               iommu_completion_wait(iommu);
-       }
+       pte = (void *)get_zeroed_page(gfp);
+       if (!pte)
+               return false;
+
+       *pte             = PM_LEVEL_PDE(domain->mode,
+                                       virt_to_phys(domain->pt_root));
+       domain->pt_root  = pte;
+       domain->mode    += 1;
+       domain->updated  = true;
+
+       return true;
 }
 
-static void flush_devices_by_domain(struct protection_domain *domain)
+static u64 *alloc_pte(struct protection_domain *domain,
+                     unsigned long address,
+                     int end_lvl,
+                     u64 **pte_page,
+                     gfp_t gfp)
 {
-       struct amd_iommu *iommu;
-       int i;
+       u64 *pte, *page;
+       int level;
 
-       for (i = 0; i <= amd_iommu_last_bdf; ++i) {
-               if ((domain == NULL && amd_iommu_pd_table[i] == NULL) ||
-                   (amd_iommu_pd_table[i] != domain))
-                       continue;
+       while (address > PM_LEVEL_SIZE(domain->mode))
+               increase_address_space(domain, gfp);
 
-               iommu = amd_iommu_rlookup_table[i];
-               if (!iommu)
-                       continue;
+       level =  domain->mode - 1;
+       pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
 
-               iommu_queue_inv_dev_entry(iommu, i);
-               iommu_completion_wait(iommu);
+       while (level > end_lvl) {
+               if (!IOMMU_PTE_PRESENT(*pte)) {
+                       page = (u64 *)get_zeroed_page(gfp);
+                       if (!page)
+                               return NULL;
+                       *pte = PM_LEVEL_PDE(level, virt_to_phys(page));
+               }
+
+               level -= 1;
+
+               pte = IOMMU_PTE_PAGE(*pte);
+
+               if (pte_page && level == end_lvl)
+                       *pte_page = pte;
+
+               pte = &pte[PM_LEVEL_INDEX(level, address)];
        }
+
+       return pte;
 }
 
-static void reset_iommu_command_buffer(struct amd_iommu *iommu)
+/*
+ * This function checks if there is a PTE for a given dma address. If
+ * there is one, it returns the pointer to it.
+ */
+static u64 *fetch_pte(struct protection_domain *domain,
+                     unsigned long address, int map_size)
 {
-       pr_err("AMD-Vi: Resetting IOMMU command buffer\n");
+       int level;
+       u64 *pte;
 
-       if (iommu->reset_in_progress)
-               panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n");
+       level =  domain->mode - 1;
+       pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
 
-       iommu->reset_in_progress = true;
+       while (level > map_size) {
+               if (!IOMMU_PTE_PRESENT(*pte))
+                       return NULL;
 
-       amd_iommu_reset_cmd_buffer(iommu);
-       flush_all_devices_for_iommu(iommu);
-       flush_all_domains_on_iommu(iommu);
+               level -= 1;
 
-       iommu->reset_in_progress = false;
-}
+               pte = IOMMU_PTE_PAGE(*pte);
+               pte = &pte[PM_LEVEL_INDEX(level, address)];
 
-void amd_iommu_flush_all_devices(void)
-{
-       flush_devices_by_domain(NULL);
-}
+               if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) {
+                       pte = NULL;
+                       break;
+               }
+       }
 
-/****************************************************************************
- *
- * The functions below are used the create the page table mappings for
- * unity mapped regions.
- *
- ****************************************************************************/
+       return pte;
+}
 
 /*
  * Generic mapping functions. It maps a physical address into a DMA
@@ -654,28 +828,6 @@ static int iommu_for_unity_map(struct amd_iommu *iommu,
 }
 
 /*
- * Init the unity mappings for a specific IOMMU in the system
- *
- * Basically iterates over all unity mapping entries and applies them to
- * the default domain DMA of that IOMMU if necessary.
- */
-static int iommu_init_unity_mappings(struct amd_iommu *iommu)
-{
-       struct unity_map_entry *entry;
-       int ret;
-
-       list_for_each_entry(entry, &amd_iommu_unity_map, list) {
-               if (!iommu_for_unity_map(iommu, entry))
-                       continue;
-               ret = dma_ops_unity_map(iommu->default_dom, entry);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-/*
  * This function actually applies the mapping to the page table of the
  * dma_ops domain.
  */
@@ -704,6 +856,28 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 }
 
 /*
+ * Init the unity mappings for a specific IOMMU in the system
+ *
+ * Basically iterates over all unity mapping entries and applies them to
+ * the default domain DMA of that IOMMU if necessary.
+ */
+static int iommu_init_unity_mappings(struct amd_iommu *iommu)
+{
+       struct unity_map_entry *entry;
+       int ret;
+
+       list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+               if (!iommu_for_unity_map(iommu, entry))
+                       continue;
+               ret = dma_ops_unity_map(iommu->default_dom, entry);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/*
  * Inits the unity mappings required for a specific device
  */
 static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
@@ -740,34 +914,23 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
  */
 
 /*
- * This function checks if there is a PTE for a given dma address. If
- * there is one, it returns the pointer to it.
+ * Used to reserve address ranges in the aperture (e.g. for exclusion
+ * ranges.
  */
-static u64 *fetch_pte(struct protection_domain *domain,
-                     unsigned long address, int map_size)
+static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
+                                     unsigned long start_page,
+                                     unsigned int pages)
 {
-       int level;
-       u64 *pte;
-
-       level =  domain->mode - 1;
-       pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
-
-       while (level > map_size) {
-               if (!IOMMU_PTE_PRESENT(*pte))
-                       return NULL;
-
-               level -= 1;
+       unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
 
-               pte = IOMMU_PTE_PAGE(*pte);
-               pte = &pte[PM_LEVEL_INDEX(level, address)];
+       if (start_page + pages > last_page)
+               pages = last_page - start_page;
 
-               if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) {
-                       pte = NULL;
-                       break;
-               }
+       for (i = start_page; i < start_page + pages; ++i) {
+               int index = i / APERTURE_RANGE_PAGES;
+               int page  = i % APERTURE_RANGE_PAGES;
+               __set_bit(page, dom->aperture[index]->bitmap);
        }
-
-       return pte;
 }
 
 /*
@@ -775,11 +938,11 @@ static u64 *fetch_pte(struct protection_domain *domain,
  * aperture in case of dma_ops domain allocation or address allocation
  * failure.
  */
-static int alloc_new_range(struct amd_iommu *iommu,
-                          struct dma_ops_domain *dma_dom,
+static int alloc_new_range(struct dma_ops_domain *dma_dom,
                           bool populate, gfp_t gfp)
 {
        int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
+       struct amd_iommu *iommu;
        int i;
 
 #ifdef CONFIG_IOMMU_STRESS
@@ -819,14 +982,17 @@ static int alloc_new_range(struct amd_iommu *iommu,
        dma_dom->aperture_size += APERTURE_RANGE_SIZE;
 
        /* Intialize the exclusion range if necessary */
-       if (iommu->exclusion_start &&
-           iommu->exclusion_start >= dma_dom->aperture[index]->offset &&
-           iommu->exclusion_start < dma_dom->aperture_size) {
-               unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
-               int pages = iommu_num_pages(iommu->exclusion_start,
-                                           iommu->exclusion_length,
-                                           PAGE_SIZE);
-               dma_ops_reserve_addresses(dma_dom, startpage, pages);
+       for_each_iommu(iommu) {
+               if (iommu->exclusion_start &&
+                   iommu->exclusion_start >= dma_dom->aperture[index]->offset
+                   && iommu->exclusion_start < dma_dom->aperture_size) {
+                       unsigned long startpage;
+                       int pages = iommu_num_pages(iommu->exclusion_start,
+                                                   iommu->exclusion_length,
+                                                   PAGE_SIZE);
+                       startpage = iommu->exclusion_start >> PAGE_SHIFT;
+                       dma_ops_reserve_addresses(dma_dom, startpage, pages);
+               }
        }
 
        /*
@@ -928,7 +1094,7 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev,
        }
 
        if (unlikely(address == -1))
-               address = bad_dma_address;
+               address = DMA_ERROR_CODE;
 
        WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size);
 
@@ -973,6 +1139,31 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom,
  *
  ****************************************************************************/
 
+/*
+ * This function adds a protection domain to the global protection domain list
+ */
+static void add_domain_to_list(struct protection_domain *domain)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+       list_add(&domain->list, &amd_iommu_pd_list);
+       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
+/*
+ * This function removes a protection domain to the global
+ * protection domain list
+ */
+static void del_domain_from_list(struct protection_domain *domain)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&amd_iommu_pd_lock, flags);
+       list_del(&domain->list);
+       spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
+}
+
 static u16 domain_id_alloc(void)
 {
        unsigned long flags;
@@ -1000,26 +1191,6 @@ static void domain_id_free(int id)
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
 
-/*
- * Used to reserve address ranges in the aperture (e.g. for exclusion
- * ranges.
- */
-static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
-                                     unsigned long start_page,
-                                     unsigned int pages)
-{
-       unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
-
-       if (start_page + pages > last_page)
-               pages = last_page - start_page;
-
-       for (i = start_page; i < start_page + pages; ++i) {
-               int index = i / APERTURE_RANGE_PAGES;
-               int page  = i % APERTURE_RANGE_PAGES;
-               __set_bit(page, dom->aperture[index]->bitmap);
-       }
-}
-
 static void free_pagetable(struct protection_domain *domain)
 {
        int i, j;
@@ -1061,6 +1232,8 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
        if (!dom)
                return;
 
+       del_domain_from_list(&dom->domain);
+
        free_pagetable(&dom->domain);
 
        for (i = 0; i < APERTURE_MAX_RANGES; ++i) {
@@ -1078,7 +1251,7 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
  * It also intializes the page table and the address allocator data
  * structures required for the dma_ops interface
  */
-static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
+static struct dma_ops_domain *dma_ops_domain_alloc(void)
 {
        struct dma_ops_domain *dma_dom;
 
@@ -1091,6 +1264,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
        dma_dom->domain.id = domain_id_alloc();
        if (dma_dom->domain.id == 0)
                goto free_dma_dom;
+       INIT_LIST_HEAD(&dma_dom->domain.dev_list);
        dma_dom->domain.mode = PAGE_MODE_2_LEVEL;
        dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
        dma_dom->domain.flags = PD_DMA_OPS_MASK;
@@ -1101,7 +1275,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
        dma_dom->need_flush = false;
        dma_dom->target_dev = 0xffff;
 
-       if (alloc_new_range(iommu, dma_dom, true, GFP_KERNEL))
+       add_domain_to_list(&dma_dom->domain);
+
+       if (alloc_new_range(dma_dom, true, GFP_KERNEL))
                goto free_dma_dom;
 
        /*
@@ -1129,22 +1305,6 @@ static bool dma_ops_domain(struct protection_domain *domain)
        return domain->flags & PD_DMA_OPS_MASK;
 }
 
-/*
- * Find out the protection domain structure for a given PCI device. This
- * will give us the pointer to the page table root for example.
- */
-static struct protection_domain *domain_for_device(u16 devid)
-{
-       struct protection_domain *dom;
-       unsigned long flags;
-
-       read_lock_irqsave(&amd_iommu_devtable_lock, flags);
-       dom = amd_iommu_pd_table[devid];
-       read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
-
-       return dom;
-}
-
 static void set_dte_entry(u16 devid, struct protection_domain *domain)
 {
        u64 pte_root = virt_to_phys(domain->pt_root);
@@ -1156,42 +1316,123 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain)
        amd_iommu_dev_table[devid].data[2] = domain->id;
        amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root);
        amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root);
+}
+
+static void clear_dte_entry(u16 devid)
+{
+       /* remove entry from the device table seen by the hardware */
+       amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+       amd_iommu_dev_table[devid].data[1] = 0;
+       amd_iommu_dev_table[devid].data[2] = 0;
 
-       amd_iommu_pd_table[devid] = domain;
+       amd_iommu_apply_erratum_63(devid);
+}
+
+static void do_attach(struct device *dev, struct protection_domain *domain)
+{
+       struct iommu_dev_data *dev_data;
+       struct amd_iommu *iommu;
+       u16 devid;
+
+       devid    = get_device_id(dev);
+       iommu    = amd_iommu_rlookup_table[devid];
+       dev_data = get_dev_data(dev);
+
+       /* Update data structures */
+       dev_data->domain = domain;
+       list_add(&dev_data->list, &domain->dev_list);
+       set_dte_entry(devid, domain);
+
+       /* Do reference counting */
+       domain->dev_iommu[iommu->index] += 1;
+       domain->dev_cnt                 += 1;
+
+       /* Flush the DTE entry */
+       iommu_flush_device(dev);
+}
+
+static void do_detach(struct device *dev)
+{
+       struct iommu_dev_data *dev_data;
+       struct amd_iommu *iommu;
+       u16 devid;
+
+       devid    = get_device_id(dev);
+       iommu    = amd_iommu_rlookup_table[devid];
+       dev_data = get_dev_data(dev);
+
+       /* decrease reference counters */
+       dev_data->domain->dev_iommu[iommu->index] -= 1;
+       dev_data->domain->dev_cnt                 -= 1;
+
+       /* Update data structures */
+       dev_data->domain = NULL;
+       list_del(&dev_data->list);
+       clear_dte_entry(devid);
+
+       /* Flush the DTE entry */
+       iommu_flush_device(dev);
 }
 
 /*
  * If a device is not yet associated with a domain, this function does
  * assigns it visible for the hardware
  */
-static void __attach_device(struct amd_iommu *iommu,
-                           struct protection_domain *domain,
-                           u16 devid)
+static int __attach_device(struct device *dev,
+                          struct protection_domain *domain)
 {
+       struct iommu_dev_data *dev_data, *alias_data;
+
+       dev_data   = get_dev_data(dev);
+       alias_data = get_dev_data(dev_data->alias);
+
+       if (!alias_data)
+               return -EINVAL;
+
        /* lock domain */
        spin_lock(&domain->lock);
 
-       /* update DTE entry */
-       set_dte_entry(devid, domain);
+       /* Some sanity checks */
+       if (alias_data->domain != NULL &&
+           alias_data->domain != domain)
+               return -EBUSY;
 
-       domain->dev_cnt += 1;
+       if (dev_data->domain != NULL &&
+           dev_data->domain != domain)
+               return -EBUSY;
+
+       /* Do real assignment */
+       if (dev_data->alias != dev) {
+               alias_data = get_dev_data(dev_data->alias);
+               if (alias_data->domain == NULL)
+                       do_attach(dev_data->alias, domain);
+
+               atomic_inc(&alias_data->bind);
+       }
+
+       if (dev_data->domain == NULL)
+               do_attach(dev, domain);
+
+       atomic_inc(&dev_data->bind);
 
        /* ready */
        spin_unlock(&domain->lock);
+
+       return 0;
 }
 
 /*
  * If a device is not yet associated with a domain, this function does
  * assigns it visible for the hardware
  */
-static void attach_device(struct amd_iommu *iommu,
-                         struct protection_domain *domain,
-                         u16 devid)
+static int attach_device(struct device *dev,
+                        struct protection_domain *domain)
 {
        unsigned long flags;
+       int ret;
 
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-       __attach_device(iommu, domain, devid);
+       ret = __attach_device(dev, domain);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 
        /*
@@ -1199,98 +1440,125 @@ static void attach_device(struct amd_iommu *iommu,
         * left the caches in the IOMMU dirty. So we have to flush
         * here to evict all dirty stuff.
         */
-       iommu_queue_inv_dev_entry(iommu, devid);
-       iommu_flush_tlb_pde(iommu, domain->id);
+       iommu_flush_tlb_pde(domain);
+
+       return ret;
 }
 
 /*
  * Removes a device from a protection domain (unlocked)
  */
-static void __detach_device(struct protection_domain *domain, u16 devid)
+static void __detach_device(struct device *dev)
 {
+       struct iommu_dev_data *dev_data = get_dev_data(dev);
+       struct iommu_dev_data *alias_data;
+       unsigned long flags;
 
-       /* lock domain */
-       spin_lock(&domain->lock);
-
-       /* remove domain from the lookup table */
-       amd_iommu_pd_table[devid] = NULL;
+       BUG_ON(!dev_data->domain);
 
-       /* remove entry from the device table seen by the hardware */
-       amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
-       amd_iommu_dev_table[devid].data[1] = 0;
-       amd_iommu_dev_table[devid].data[2] = 0;
+       spin_lock_irqsave(&dev_data->domain->lock, flags);
 
-       amd_iommu_apply_erratum_63(devid);
+       if (dev_data->alias != dev) {
+               alias_data = get_dev_data(dev_data->alias);
+               if (atomic_dec_and_test(&alias_data->bind))
+                       do_detach(dev_data->alias);
+       }
 
-       /* decrease reference counter */
-       domain->dev_cnt -= 1;
+       if (atomic_dec_and_test(&dev_data->bind))
+               do_detach(dev);
 
-       /* ready */
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&dev_data->domain->lock, flags);
 
        /*
         * If we run in passthrough mode the device must be assigned to the
         * passthrough domain if it is detached from any other domain
         */
-       if (iommu_pass_through) {
-               struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
-               __attach_device(iommu, pt_domain, devid);
-       }
+       if (iommu_pass_through && dev_data->domain == NULL)
+               __attach_device(dev, pt_domain);
 }
 
 /*
  * Removes a device from a protection domain (with devtable_lock held)
  */
-static void detach_device(struct protection_domain *domain, u16 devid)
+static void detach_device(struct device *dev)
 {
        unsigned long flags;
 
        /* lock device table */
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-       __detach_device(domain, devid);
+       __detach_device(dev);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
 
+/*
+ * Find out the protection domain structure for a given PCI device. This
+ * will give us the pointer to the page table root for example.
+ */
+static struct protection_domain *domain_for_device(struct device *dev)
+{
+       struct protection_domain *dom;
+       struct iommu_dev_data *dev_data, *alias_data;
+       unsigned long flags;
+       u16 devid, alias;
+
+       devid      = get_device_id(dev);
+       alias      = amd_iommu_alias_table[devid];
+       dev_data   = get_dev_data(dev);
+       alias_data = get_dev_data(dev_data->alias);
+       if (!alias_data)
+               return NULL;
+
+       read_lock_irqsave(&amd_iommu_devtable_lock, flags);
+       dom = dev_data->domain;
+       if (dom == NULL &&
+           alias_data->domain != NULL) {
+               __attach_device(dev, alias_data->domain);
+               dom = alias_data->domain;
+       }
+
+       read_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+
+       return dom;
+}
+
 static int device_change_notifier(struct notifier_block *nb,
                                  unsigned long action, void *data)
 {
        struct device *dev = data;
-       struct pci_dev *pdev = to_pci_dev(dev);
-       u16 devid = calc_devid(pdev->bus->number, pdev->devfn);
+       u16 devid;
        struct protection_domain *domain;
        struct dma_ops_domain *dma_domain;
        struct amd_iommu *iommu;
        unsigned long flags;
 
-       if (devid > amd_iommu_last_bdf)
-               goto out;
-
-       devid = amd_iommu_alias_table[devid];
-
-       iommu = amd_iommu_rlookup_table[devid];
-       if (iommu == NULL)
-               goto out;
-
-       domain = domain_for_device(devid);
+       if (!check_device(dev))
+               return 0;
 
-       if (domain && !dma_ops_domain(domain))
-               WARN_ONCE(1, "AMD IOMMU WARNING: device %s already bound "
-                         "to a non-dma-ops domain\n", dev_name(dev));
+       devid  = get_device_id(dev);
+       iommu  = amd_iommu_rlookup_table[devid];
 
        switch (action) {
        case BUS_NOTIFY_UNBOUND_DRIVER:
+
+               domain = domain_for_device(dev);
+
                if (!domain)
                        goto out;
                if (iommu_pass_through)
                        break;
-               detach_device(domain, devid);
+               detach_device(dev);
                break;
        case BUS_NOTIFY_ADD_DEVICE:
+
+               iommu_init_device(dev);
+
+               domain = domain_for_device(dev);
+
                /* allocate a protection domain if a device is added */
                dma_domain = find_protection_domain(devid);
                if (dma_domain)
                        goto out;
-               dma_domain = dma_ops_domain_alloc(iommu);
+               dma_domain = dma_ops_domain_alloc();
                if (!dma_domain)
                        goto out;
                dma_domain->target_dev = devid;
@@ -1300,11 +1568,15 @@ static int device_change_notifier(struct notifier_block *nb,
                spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
 
                break;
+       case BUS_NOTIFY_DEL_DEVICE:
+
+               iommu_uninit_device(dev);
+
        default:
                goto out;
        }
 
-       iommu_queue_inv_dev_entry(iommu, devid);
+       iommu_flush_device(dev);
        iommu_completion_wait(iommu);
 
 out:
@@ -1322,106 +1594,46 @@ static struct notifier_block device_nb = {
  *****************************************************************************/
 
 /*
- * This function checks if the driver got a valid device from the caller to
- * avoid dereferencing invalid pointers.
- */
-static bool check_device(struct device *dev)
-{
-       if (!dev || !dev->dma_mask)
-               return false;
-
-       return true;
-}
-
-/*
- * In this function the list of preallocated protection domains is traversed to
- * find the domain for a specific device
- */
-static struct dma_ops_domain *find_protection_domain(u16 devid)
-{
-       struct dma_ops_domain *entry, *ret = NULL;
-       unsigned long flags;
-
-       if (list_empty(&iommu_pd_list))
-               return NULL;
-
-       spin_lock_irqsave(&iommu_pd_list_lock, flags);
-
-       list_for_each_entry(entry, &iommu_pd_list, list) {
-               if (entry->target_dev == devid) {
-                       ret = entry;
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
-
-       return ret;
-}
-
-/*
  * In the dma_ops path we only have the struct device. This function
  * finds the corresponding IOMMU, the protection domain and the
  * requestor id for a given device.
  * If the device is not yet associated with a domain this is also done
  * in this function.
  */
-static int get_device_resources(struct device *dev,
-                               struct amd_iommu **iommu,
-                               struct protection_domain **domain,
-                               u16 *bdf)
+static struct protection_domain *get_domain(struct device *dev)
 {
+       struct protection_domain *domain;
        struct dma_ops_domain *dma_dom;
-       struct pci_dev *pcidev;
-       u16 _bdf;
-
-       *iommu = NULL;
-       *domain = NULL;
-       *bdf = 0xffff;
-
-       if (dev->bus != &pci_bus_type)
-               return 0;
+       u16 devid = get_device_id(dev);
 
-       pcidev = to_pci_dev(dev);
-       _bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
+       if (!check_device(dev))
+               return ERR_PTR(-EINVAL);
 
-       /* device not translated by any IOMMU in the system? */
-       if (_bdf > amd_iommu_last_bdf)
-               return 0;
+       domain = domain_for_device(dev);
+       if (domain != NULL && !dma_ops_domain(domain))
+               return ERR_PTR(-EBUSY);
 
-       *bdf = amd_iommu_alias_table[_bdf];
+       if (domain != NULL)
+               return domain;
 
-       *iommu = amd_iommu_rlookup_table[*bdf];
-       if (*iommu == NULL)
-               return 0;
-       *domain = domain_for_device(*bdf);
-       if (*domain == NULL) {
-               dma_dom = find_protection_domain(*bdf);
-               if (!dma_dom)
-                       dma_dom = (*iommu)->default_dom;
-               *domain = &dma_dom->domain;
-               attach_device(*iommu, *domain, *bdf);
-               DUMP_printk("Using protection domain %d for device %s\n",
-                           (*domain)->id, dev_name(dev));
-       }
-
-       if (domain_for_device(_bdf) == NULL)
-               attach_device(*iommu, *domain, _bdf);
+       /* Device not bount yet - bind it */
+       dma_dom = find_protection_domain(devid);
+       if (!dma_dom)
+               dma_dom = amd_iommu_rlookup_table[devid]->default_dom;
+       attach_device(dev, &dma_dom->domain);
+       DUMP_printk("Using protection domain %d for device %s\n",
+                   dma_dom->domain.id, dev_name(dev));
 
-       return 1;
+       return &dma_dom->domain;
 }
 
 static void update_device_table(struct protection_domain *domain)
 {
-       unsigned long flags;
-       int i;
+       struct iommu_dev_data *dev_data;
 
-       for (i = 0; i <= amd_iommu_last_bdf; ++i) {
-               if (amd_iommu_pd_table[i] != domain)
-                       continue;
-               write_lock_irqsave(&amd_iommu_devtable_lock, flags);
-               set_dte_entry(i, domain);
-               write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+       list_for_each_entry(dev_data, &domain->dev_list, list) {
+               u16 devid = get_device_id(dev_data->dev);
+               set_dte_entry(devid, domain);
        }
 }
 
@@ -1431,76 +1643,13 @@ static void update_domain(struct protection_domain *domain)
                return;
 
        update_device_table(domain);
-       flush_devices_by_domain(domain);
-       iommu_flush_domain(domain->id);
+       iommu_flush_domain_devices(domain);
+       iommu_flush_tlb_pde(domain);
 
        domain->updated = false;
 }
 
 /*
- * This function is used to add another level to an IO page table. Adding
- * another level increases the size of the address space by 9 bits to a size up
- * to 64 bits.
- */
-static bool increase_address_space(struct protection_domain *domain,
-                                  gfp_t gfp)
-{
-       u64 *pte;
-
-       if (domain->mode == PAGE_MODE_6_LEVEL)
-               /* address space already 64 bit large */
-               return false;
-
-       pte = (void *)get_zeroed_page(gfp);
-       if (!pte)
-               return false;
-
-       *pte             = PM_LEVEL_PDE(domain->mode,
-                                       virt_to_phys(domain->pt_root));
-       domain->pt_root  = pte;
-       domain->mode    += 1;
-       domain->updated  = true;
-
-       return true;
-}
-
-static u64 *alloc_pte(struct protection_domain *domain,
-                     unsigned long address,
-                     int end_lvl,
-                     u64 **pte_page,
-                     gfp_t gfp)
-{
-       u64 *pte, *page;
-       int level;
-
-       while (address > PM_LEVEL_SIZE(domain->mode))
-               increase_address_space(domain, gfp);
-
-       level =  domain->mode - 1;
-       pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
-
-       while (level > end_lvl) {
-               if (!IOMMU_PTE_PRESENT(*pte)) {
-                       page = (u64 *)get_zeroed_page(gfp);
-                       if (!page)
-                               return NULL;
-                       *pte = PM_LEVEL_PDE(level, virt_to_phys(page));
-               }
-
-               level -= 1;
-
-               pte = IOMMU_PTE_PAGE(*pte);
-
-               if (pte_page && level == end_lvl)
-                       *pte_page = pte;
-
-               pte = &pte[PM_LEVEL_INDEX(level, address)];
-       }
-
-       return pte;
-}
-
-/*
  * This function fetches the PTE for a given address in the aperture
  */
 static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
@@ -1530,8 +1679,7 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
  * This is the generic map function. It maps one 4kb page at paddr to
  * the given address in the DMA address space for the domain.
  */
-static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
-                                    struct dma_ops_domain *dom,
+static dma_addr_t dma_ops_domain_map(struct dma_ops_domain *dom,
                                     unsigned long address,
                                     phys_addr_t paddr,
                                     int direction)
@@ -1544,7 +1692,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
 
        pte  = dma_ops_get_pte(dom, address);
        if (!pte)
-               return bad_dma_address;
+               return DMA_ERROR_CODE;
 
        __pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC;
 
@@ -1565,8 +1713,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
 /*
  * The generic unmapping function for on page in the DMA address space.
  */
-static void dma_ops_domain_unmap(struct amd_iommu *iommu,
-                                struct dma_ops_domain *dom,
+static void dma_ops_domain_unmap(struct dma_ops_domain *dom,
                                 unsigned long address)
 {
        struct aperture_range *aperture;
@@ -1597,7 +1744,6 @@ static void dma_ops_domain_unmap(struct amd_iommu *iommu,
  * Must be called with the domain lock held.
  */
 static dma_addr_t __map_single(struct device *dev,
-                              struct amd_iommu *iommu,
                               struct dma_ops_domain *dma_dom,
                               phys_addr_t paddr,
                               size_t size,
@@ -1625,7 +1771,7 @@ static dma_addr_t __map_single(struct device *dev,
 retry:
        address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask,
                                          dma_mask);
-       if (unlikely(address == bad_dma_address)) {
+       if (unlikely(address == DMA_ERROR_CODE)) {
                /*
                 * setting next_address here will let the address
                 * allocator only scan the new allocated range in the
@@ -1633,7 +1779,7 @@ retry:
                 */
                dma_dom->next_address = dma_dom->aperture_size;
 
-               if (alloc_new_range(iommu, dma_dom, false, GFP_ATOMIC))
+               if (alloc_new_range(dma_dom, false, GFP_ATOMIC))
                        goto out;
 
                /*
@@ -1645,8 +1791,8 @@ retry:
 
        start = address;
        for (i = 0; i < pages; ++i) {
-               ret = dma_ops_domain_map(iommu, dma_dom, start, paddr, dir);
-               if (ret == bad_dma_address)
+               ret = dma_ops_domain_map(dma_dom, start, paddr, dir);
+               if (ret == DMA_ERROR_CODE)
                        goto out_unmap;
 
                paddr += PAGE_SIZE;
@@ -1657,10 +1803,10 @@ retry:
        ADD_STATS_COUNTER(alloced_io_mem, size);
 
        if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
-               iommu_flush_tlb(iommu, dma_dom->domain.id);
+               iommu_flush_tlb(&dma_dom->domain);
                dma_dom->need_flush = false;
-       } else if (unlikely(iommu_has_npcache(iommu)))
-               iommu_flush_pages(iommu, dma_dom->domain.id, address, size);
+       } else if (unlikely(amd_iommu_np_cache))
+               iommu_flush_pages(&dma_dom->domain, address, size);
 
 out:
        return address;
@@ -1669,20 +1815,19 @@ out_unmap:
 
        for (--i; i >= 0; --i) {
                start -= PAGE_SIZE;
-               dma_ops_domain_unmap(iommu, dma_dom, start);
+               dma_ops_domain_unmap(dma_dom, start);
        }
 
        dma_ops_free_addresses(dma_dom, address, pages);
 
-       return bad_dma_address;
+       return DMA_ERROR_CODE;
 }
 
 /*
  * Does the reverse of the __map_single function. Must be called with
  * the domain lock held too
  */
-static void __unmap_single(struct amd_iommu *iommu,
-                          struct dma_ops_domain *dma_dom,
+static void __unmap_single(struct dma_ops_domain *dma_dom,
                           dma_addr_t dma_addr,
                           size_t size,
                           int dir)
@@ -1690,7 +1835,7 @@ static void __unmap_single(struct amd_iommu *iommu,
        dma_addr_t i, start;
        unsigned int pages;
 
-       if ((dma_addr == bad_dma_address) ||
+       if ((dma_addr == DMA_ERROR_CODE) ||
            (dma_addr + size > dma_dom->aperture_size))
                return;
 
@@ -1699,7 +1844,7 @@ static void __unmap_single(struct amd_iommu *iommu,
        start = dma_addr;
 
        for (i = 0; i < pages; ++i) {
-               dma_ops_domain_unmap(iommu, dma_dom, start);
+               dma_ops_domain_unmap(dma_dom, start);
                start += PAGE_SIZE;
        }
 
@@ -1708,7 +1853,7 @@ static void __unmap_single(struct amd_iommu *iommu,
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
        if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-               iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size);
+               iommu_flush_pages(&dma_dom->domain, dma_addr, size);
                dma_dom->need_flush = false;
        }
 }
@@ -1722,36 +1867,29 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
                           struct dma_attrs *attrs)
 {
        unsigned long flags;
-       struct amd_iommu *iommu;
        struct protection_domain *domain;
-       u16 devid;
        dma_addr_t addr;
        u64 dma_mask;
        phys_addr_t paddr = page_to_phys(page) + offset;
 
        INC_STATS_COUNTER(cnt_map_single);
 
-       if (!check_device(dev))
-               return bad_dma_address;
-
-       dma_mask = *dev->dma_mask;
-
-       get_device_resources(dev, &iommu, &domain, &devid);
-
-       if (iommu == NULL || domain == NULL)
-               /* device not handled by any AMD IOMMU */
+       domain = get_domain(dev);
+       if (PTR_ERR(domain) == -EINVAL)
                return (dma_addr_t)paddr;
+       else if (IS_ERR(domain))
+               return DMA_ERROR_CODE;
 
-       if (!dma_ops_domain(domain))
-               return bad_dma_address;
+       dma_mask = *dev->dma_mask;
 
        spin_lock_irqsave(&domain->lock, flags);
-       addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false,
+
+       addr = __map_single(dev, domain->priv, paddr, size, dir, false,
                            dma_mask);
-       if (addr == bad_dma_address)
+       if (addr == DMA_ERROR_CODE)
                goto out;
 
-       iommu_completion_wait(iommu);
+       iommu_flush_complete(domain);
 
 out:
        spin_unlock_irqrestore(&domain->lock, flags);
@@ -1766,25 +1904,19 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
                       enum dma_data_direction dir, struct dma_attrs *attrs)
 {
        unsigned long flags;
-       struct amd_iommu *iommu;
        struct protection_domain *domain;
-       u16 devid;
 
        INC_STATS_COUNTER(cnt_unmap_single);
 
-       if (!check_device(dev) ||
-           !get_device_resources(dev, &iommu, &domain, &devid))
-               /* device not handled by any AMD IOMMU */
-               return;
-
-       if (!dma_ops_domain(domain))
+       domain = get_domain(dev);
+       if (IS_ERR(domain))
                return;
 
        spin_lock_irqsave(&domain->lock, flags);
 
-       __unmap_single(iommu, domain->priv, dma_addr, size, dir);
+       __unmap_single(domain->priv, dma_addr, size, dir);
 
-       iommu_completion_wait(iommu);
+       iommu_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 }
@@ -1816,9 +1948,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
                  struct dma_attrs *attrs)
 {
        unsigned long flags;
-       struct amd_iommu *iommu;
        struct protection_domain *domain;
-       u16 devid;
        int i;
        struct scatterlist *s;
        phys_addr_t paddr;
@@ -1827,25 +1957,20 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 
        INC_STATS_COUNTER(cnt_map_sg);
 
-       if (!check_device(dev))
+       domain = get_domain(dev);
+       if (PTR_ERR(domain) == -EINVAL)
+               return map_sg_no_iommu(dev, sglist, nelems, dir);
+       else if (IS_ERR(domain))
                return 0;
 
        dma_mask = *dev->dma_mask;
 
-       get_device_resources(dev, &iommu, &domain, &devid);
-
-       if (!iommu || !domain)
-               return map_sg_no_iommu(dev, sglist, nelems, dir);
-
-       if (!dma_ops_domain(domain))
-               return 0;
-
        spin_lock_irqsave(&domain->lock, flags);
 
        for_each_sg(sglist, s, nelems, i) {
                paddr = sg_phys(s);
 
-               s->dma_address = __map_single(dev, iommu, domain->priv,
+               s->dma_address = __map_single(dev, domain->priv,
                                              paddr, s->length, dir, false,
                                              dma_mask);
 
@@ -1856,7 +1981,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
                        goto unmap;
        }
 
-       iommu_completion_wait(iommu);
+       iommu_flush_complete(domain);
 
 out:
        spin_unlock_irqrestore(&domain->lock, flags);
@@ -1865,7 +1990,7 @@ out:
 unmap:
        for_each_sg(sglist, s, mapped_elems, i) {
                if (s->dma_address)
-                       __unmap_single(iommu, domain->priv, s->dma_address,
+                       __unmap_single(domain->priv, s->dma_address,
                                       s->dma_length, dir);
                s->dma_address = s->dma_length = 0;
        }
@@ -1884,30 +2009,25 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
                     struct dma_attrs *attrs)
 {
        unsigned long flags;
-       struct amd_iommu *iommu;
        struct protection_domain *domain;
        struct scatterlist *s;
-       u16 devid;
        int i;
 
        INC_STATS_COUNTER(cnt_unmap_sg);
 
-       if (!check_device(dev) ||
-           !get_device_resources(dev, &iommu, &domain, &devid))
-               return;
-
-       if (!dma_ops_domain(domain))
+       domain = get_domain(dev);
+       if (IS_ERR(domain))
                return;
 
        spin_lock_irqsave(&domain->lock, flags);
 
        for_each_sg(sglist, s, nelems, i) {
-               __unmap_single(iommu, domain->priv, s->dma_address,
+               __unmap_single(domain->priv, s->dma_address,
                               s->dma_length, dir);
                s->dma_address = s->dma_length = 0;
        }
 
-       iommu_completion_wait(iommu);
+       iommu_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 }
@@ -1920,49 +2040,44 @@ static void *alloc_coherent(struct device *dev, size_t size,
 {
        unsigned long flags;
        void *virt_addr;
-       struct amd_iommu *iommu;
        struct protection_domain *domain;
-       u16 devid;
        phys_addr_t paddr;
        u64 dma_mask = dev->coherent_dma_mask;
 
        INC_STATS_COUNTER(cnt_alloc_coherent);
 
-       if (!check_device(dev))
+       domain = get_domain(dev);
+       if (PTR_ERR(domain) == -EINVAL) {
+               virt_addr = (void *)__get_free_pages(flag, get_order(size));
+               *dma_addr = __pa(virt_addr);
+               return virt_addr;
+       } else if (IS_ERR(domain))
                return NULL;
 
-       if (!get_device_resources(dev, &iommu, &domain, &devid))
-               flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+       dma_mask  = dev->coherent_dma_mask;
+       flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+       flag     |= __GFP_ZERO;
 
-       flag |= __GFP_ZERO;
        virt_addr = (void *)__get_free_pages(flag, get_order(size));
        if (!virt_addr)
                return NULL;
 
        paddr = virt_to_phys(virt_addr);
 
-       if (!iommu || !domain) {
-               *dma_addr = (dma_addr_t)paddr;
-               return virt_addr;
-       }
-
-       if (!dma_ops_domain(domain))
-               goto out_free;
-
        if (!dma_mask)
                dma_mask = *dev->dma_mask;
 
        spin_lock_irqsave(&domain->lock, flags);
 
-       *dma_addr = __map_single(dev, iommu, domain->priv, paddr,
+       *dma_addr = __map_single(dev, domain->priv, paddr,
                                 size, DMA_BIDIRECTIONAL, true, dma_mask);
 
-       if (*dma_addr == bad_dma_address) {
+       if (*dma_addr == DMA_ERROR_CODE) {
                spin_unlock_irqrestore(&domain->lock, flags);
                goto out_free;
        }
 
-       iommu_completion_wait(iommu);
+       iommu_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 
@@ -1982,28 +2097,19 @@ static void free_coherent(struct device *dev, size_t size,
                          void *virt_addr, dma_addr_t dma_addr)
 {
        unsigned long flags;
-       struct amd_iommu *iommu;
        struct protection_domain *domain;
-       u16 devid;
 
        INC_STATS_COUNTER(cnt_free_coherent);
 
-       if (!check_device(dev))
-               return;
-
-       get_device_resources(dev, &iommu, &domain, &devid);
-
-       if (!iommu || !domain)
-               goto free_mem;
-
-       if (!dma_ops_domain(domain))
+       domain = get_domain(dev);
+       if (IS_ERR(domain))
                goto free_mem;
 
        spin_lock_irqsave(&domain->lock, flags);
 
-       __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
+       __unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
 
-       iommu_completion_wait(iommu);
+       iommu_flush_complete(domain);
 
        spin_unlock_irqrestore(&domain->lock, flags);
 
@@ -2017,22 +2123,7 @@ free_mem:
  */
 static int amd_iommu_dma_supported(struct device *dev, u64 mask)
 {
-       u16 bdf;
-       struct pci_dev *pcidev;
-
-       /* No device or no PCI device */
-       if (!dev || dev->bus != &pci_bus_type)
-               return 0;
-
-       pcidev = to_pci_dev(dev);
-
-       bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
-
-       /* Out of our scope? */
-       if (bdf > amd_iommu_last_bdf)
-               return 0;
-
-       return 1;
+       return check_device(dev);
 }
 
 /*
@@ -2046,25 +2137,30 @@ static void prealloc_protection_domains(void)
 {
        struct pci_dev *dev = NULL;
        struct dma_ops_domain *dma_dom;
-       struct amd_iommu *iommu;
        u16 devid;
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               devid = calc_devid(dev->bus->number, dev->devfn);
-               if (devid > amd_iommu_last_bdf)
-                       continue;
-               devid = amd_iommu_alias_table[devid];
-               if (domain_for_device(devid))
+
+               /* Do we handle this device? */
+               if (!check_device(&dev->dev))
                        continue;
-               iommu = amd_iommu_rlookup_table[devid];
-               if (!iommu)
+
+               iommu_init_device(&dev->dev);
+
+               /* Is there already any domain for it? */
+               if (domain_for_device(&dev->dev))
                        continue;
-               dma_dom = dma_ops_domain_alloc(iommu);
+
+               devid = get_device_id(&dev->dev);
+
+               dma_dom = dma_ops_domain_alloc();
                if (!dma_dom)
                        continue;
                init_unity_mappings_for_device(dma_dom, devid);
                dma_dom->target_dev = devid;
 
+               attach_device(&dev->dev, &dma_dom->domain);
+
                list_add_tail(&dma_dom->list, &iommu_pd_list);
        }
 }
@@ -2093,7 +2189,7 @@ int __init amd_iommu_init_dma_ops(void)
         * protection domain will be assigned to the default one.
         */
        for_each_iommu(iommu) {
-               iommu->default_dom = dma_ops_domain_alloc(iommu);
+               iommu->default_dom = dma_ops_domain_alloc();
                if (iommu->default_dom == NULL)
                        return -ENOMEM;
                iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
@@ -2103,15 +2199,12 @@ int __init amd_iommu_init_dma_ops(void)
        }
 
        /*
-        * If device isolation is enabled, pre-allocate the protection
-        * domains for each device.
+        * Pre-allocate the protection domains for each device.
         */
-       if (amd_iommu_isolate)
-               prealloc_protection_domains();
+       prealloc_protection_domains();
 
        iommu_detected = 1;
-       force_iommu = 1;
-       bad_dma_address = 0;
+       swiotlb = 0;
 #ifdef CONFIG_GART_IOMMU
        gart_iommu_aperture_disabled = 1;
        gart_iommu_aperture = 0;
@@ -2150,14 +2243,17 @@ free_domains:
 
 static void cleanup_domain(struct protection_domain *domain)
 {
+       struct iommu_dev_data *dev_data, *next;
        unsigned long flags;
-       u16 devid;
 
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
 
-       for (devid = 0; devid <= amd_iommu_last_bdf; ++devid)
-               if (amd_iommu_pd_table[devid] == domain)
-                       __detach_device(domain, devid);
+       list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {
+               struct device *dev = dev_data->dev;
+
+               do_detach(dev);
+               atomic_set(&dev_data->bind, 0);
+       }
 
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 }
@@ -2167,6 +2263,8 @@ static void protection_domain_free(struct protection_domain *domain)
        if (!domain)
                return;
 
+       del_domain_from_list(domain);
+
        if (domain->id)
                domain_id_free(domain->id);
 
@@ -2185,6 +2283,9 @@ static struct protection_domain *protection_domain_alloc(void)
        domain->id = domain_id_alloc();
        if (!domain->id)
                goto out_err;
+       INIT_LIST_HEAD(&domain->dev_list);
+
+       add_domain_to_list(domain);
 
        return domain;
 
@@ -2241,26 +2342,23 @@ static void amd_iommu_domain_destroy(struct iommu_domain *dom)
 static void amd_iommu_detach_device(struct iommu_domain *dom,
                                    struct device *dev)
 {
-       struct protection_domain *domain = dom->priv;
+       struct iommu_dev_data *dev_data = dev->archdata.iommu;
        struct amd_iommu *iommu;
-       struct pci_dev *pdev;
        u16 devid;
 
-       if (dev->bus != &pci_bus_type)
+       if (!check_device(dev))
                return;
 
-       pdev = to_pci_dev(dev);
-
-       devid = calc_devid(pdev->bus->number, pdev->devfn);
+       devid = get_device_id(dev);
 
-       if (devid > 0)
-               detach_device(domain, devid);
+       if (dev_data->domain != NULL)
+               detach_device(dev);
 
        iommu = amd_iommu_rlookup_table[devid];
        if (!iommu)
                return;
 
-       iommu_queue_inv_dev_entry(iommu, devid);
+       iommu_flush_device(dev);
        iommu_completion_wait(iommu);
 }
 
@@ -2268,35 +2366,30 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
                                   struct device *dev)
 {
        struct protection_domain *domain = dom->priv;
-       struct protection_domain *old_domain;
+       struct iommu_dev_data *dev_data;
        struct amd_iommu *iommu;
-       struct pci_dev *pdev;
+       int ret;
        u16 devid;
 
-       if (dev->bus != &pci_bus_type)
+       if (!check_device(dev))
                return -EINVAL;
 
-       pdev = to_pci_dev(dev);
+       dev_data = dev->archdata.iommu;
 
-       devid = calc_devid(pdev->bus->number, pdev->devfn);
-
-       if (devid >= amd_iommu_last_bdf ||
-                       devid != amd_iommu_alias_table[devid])
-               return -EINVAL;
+       devid = get_device_id(dev);
 
        iommu = amd_iommu_rlookup_table[devid];
        if (!iommu)
                return -EINVAL;
 
-       old_domain = domain_for_device(devid);
-       if (old_domain)
-               detach_device(old_domain, devid);
+       if (dev_data->domain)
+               detach_device(dev);
 
-       attach_device(iommu, domain, devid);
+       ret = attach_device(dev, domain);
 
        iommu_completion_wait(iommu);
 
-       return 0;
+       return ret;
 }
 
 static int amd_iommu_map_range(struct iommu_domain *dom,
@@ -2342,7 +2435,7 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom,
                iova  += PAGE_SIZE;
        }
 
-       iommu_flush_domain(domain->id);
+       iommu_flush_tlb_pde(domain);
 }
 
 static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
@@ -2393,8 +2486,9 @@ static struct iommu_ops amd_iommu_ops = {
 
 int __init amd_iommu_init_passthrough(void)
 {
+       struct amd_iommu *iommu;
        struct pci_dev *dev = NULL;
-       u16 devid, devid2;
+       u16 devid;
 
        /* allocate passthroug domain */
        pt_domain = protection_domain_alloc();
@@ -2404,20 +2498,17 @@ int __init amd_iommu_init_passthrough(void)
        pt_domain->mode |= PAGE_MODE_NONE;
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               struct amd_iommu *iommu;
 
-               devid = calc_devid(dev->bus->number, dev->devfn);
-               if (devid > amd_iommu_last_bdf)
+               if (!check_device(&dev->dev))
                        continue;
 
-               devid2 = amd_iommu_alias_table[devid];
+               devid = get_device_id(&dev->dev);
 
-               iommu = amd_iommu_rlookup_table[devid2];
+               iommu = amd_iommu_rlookup_table[devid];
                if (!iommu)
                        continue;
 
-               __attach_device(iommu, pt_domain, devid);
-               __attach_device(iommu, pt_domain, devid2);
+               attach_device(&dev->dev, pt_domain);
        }
 
        pr_info("AMD-Vi: Initialized for Passthrough Mode\n");
index c20001e..7ffc399 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
  * Author: Joerg Roedel <joerg.roedel@amd.com>
  *         Leo Duran <leo.duran@amd.com>
  *
 #include <linux/interrupt.h>
 #include <linux/msi.h>
 #include <asm/pci-direct.h>
+#include <asm/amd_iommu_proto.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
+#include <asm/x86_init.h>
 
 /*
  * definitions for the ACPI scanning code
@@ -123,18 +125,24 @@ u16 amd_iommu_last_bdf;                   /* largest PCI device id we have
                                           to handle */
 LIST_HEAD(amd_iommu_unity_map);                /* a list of required unity mappings
                                           we find in ACPI */
-#ifdef CONFIG_IOMMU_STRESS
-bool amd_iommu_isolate = false;
-#else
-bool amd_iommu_isolate = true;         /* if true, device isolation is
-                                          enabled */
-#endif
-
 bool amd_iommu_unmap_flush;            /* if true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list);             /* list of all AMD IOMMUs in the
                                           system */
 
+/* Array to assign indices to IOMMUs*/
+struct amd_iommu *amd_iommus[MAX_IOMMUS];
+int amd_iommus_present;
+
+/* IOMMUs have a non-present cache? */
+bool amd_iommu_np_cache __read_mostly;
+
+/*
+ * List of protection domains - used during resume
+ */
+LIST_HEAD(amd_iommu_pd_list);
+spinlock_t amd_iommu_pd_lock;
+
 /*
  * Pointer to the device table which is shared by all AMD IOMMUs
  * it is indexed by the PCI device id or the HT unit id and contains
@@ -157,12 +165,6 @@ u16 *amd_iommu_alias_table;
 struct amd_iommu **amd_iommu_rlookup_table;
 
 /*
- * The pd table (protection domain table) is used to find the protection domain
- * data structure a device belongs to. Indexed with the PCI device id too.
- */
-struct protection_domain **amd_iommu_pd_table;
-
-/*
  * AMD IOMMU allows up to 2^16 differend protection domains. This is a bitmap
  * to know which ones are already in use.
  */
@@ -838,7 +840,18 @@ static void __init free_iommu_all(void)
 static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 {
        spin_lock_init(&iommu->lock);
+
+       /* Add IOMMU to internal data structures */
        list_add_tail(&iommu->list, &amd_iommu_list);
+       iommu->index             = amd_iommus_present++;
+
+       if (unlikely(iommu->index >= MAX_IOMMUS)) {
+               WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n");
+               return -ENOSYS;
+       }
+
+       /* Index is fine - add IOMMU to the array */
+       amd_iommus[iommu->index] = iommu;
 
        /*
         * Copy data from ACPI table entry to the iommu struct
@@ -868,6 +881,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
        init_iommu_from_acpi(iommu, h);
        init_iommu_devices(iommu);
 
+       if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
+               amd_iommu_np_cache = true;
+
        return pci_enable_device(iommu->dev);
 }
 
@@ -925,7 +941,7 @@ static int __init init_iommu_all(struct acpi_table_header *table)
  *
  ****************************************************************************/
 
-static int __init iommu_setup_msi(struct amd_iommu *iommu)
+static int iommu_setup_msi(struct amd_iommu *iommu)
 {
        int r;
 
@@ -1176,19 +1192,10 @@ static struct sys_device device_amd_iommu = {
  * functions. Finally it prints some information about AMD IOMMUs and
  * the driver state and enables the hardware.
  */
-int __init amd_iommu_init(void)
+static int __init amd_iommu_init(void)
 {
        int i, ret = 0;
 
-
-       if (no_iommu) {
-               printk(KERN_INFO "AMD-Vi disabled by kernel command line\n");
-               return 0;
-       }
-
-       if (!amd_iommu_detected)
-               return -ENODEV;
-
        /*
         * First parse ACPI tables to find the largest Bus/Dev/Func
         * we need to handle. Upon this information the shared data
@@ -1225,15 +1232,6 @@ int __init amd_iommu_init(void)
        if (amd_iommu_rlookup_table == NULL)
                goto free;
 
-       /*
-        * Protection Domain table - maps devices to protection domains
-        * This table has the same size as the rlookup_table
-        */
-       amd_iommu_pd_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                    get_order(rlookup_table_size));
-       if (amd_iommu_pd_table == NULL)
-               goto free;
-
        amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(
                                            GFP_KERNEL | __GFP_ZERO,
                                            get_order(MAX_DOMAIN_ID/8));
@@ -1255,6 +1253,8 @@ int __init amd_iommu_init(void)
         */
        amd_iommu_pd_alloc_bitmap[0] = 1;
 
+       spin_lock_init(&amd_iommu_pd_lock);
+
        /*
         * now the data structures are allocated and basically initialized
         * start the real acpi table scan
@@ -1286,17 +1286,12 @@ int __init amd_iommu_init(void)
        if (iommu_pass_through)
                goto out;
 
-       printk(KERN_INFO "AMD-Vi: device isolation ");
-       if (amd_iommu_isolate)
-               printk("enabled\n");
-       else
-               printk("disabled\n");
-
        if (amd_iommu_unmap_flush)
                printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n");
        else
                printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
 
+       x86_platform.iommu_shutdown = disable_iommus;
 out:
        return ret;
 
@@ -1304,9 +1299,6 @@ free:
        free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
                   get_order(MAX_DOMAIN_ID/8));
 
-       free_pages((unsigned long)amd_iommu_pd_table,
-                  get_order(rlookup_table_size));
-
        free_pages((unsigned long)amd_iommu_rlookup_table,
                   get_order(rlookup_table_size));
 
@@ -1323,11 +1315,6 @@ free:
        goto out;
 }
 
-void amd_iommu_shutdown(void)
-{
-       disable_iommus();
-}
-
 /****************************************************************************
  *
  * Early detect code. This code runs at IOMMU detection time in the DMA
@@ -1342,16 +1329,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)
 
 void __init amd_iommu_detect(void)
 {
-       if (swiotlb || no_iommu || (iommu_detected && !gart_iommu_aperture))
+       if (no_iommu || (iommu_detected && !gart_iommu_aperture))
                return;
 
        if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
                iommu_detected = 1;
                amd_iommu_detected = 1;
-#ifdef CONFIG_GART_IOMMU
-               gart_iommu_aperture_disabled = 1;
-               gart_iommu_aperture = 0;
-#endif
+               x86_init.iommu.iommu_init = amd_iommu_init;
        }
 }
 
@@ -1372,10 +1356,6 @@ static int __init parse_amd_iommu_dump(char *str)
 static int __init parse_amd_iommu_options(char *str)
 {
        for (; *str; ++str) {
-               if (strncmp(str, "isolate", 7) == 0)
-                       amd_iommu_isolate = true;
-               if (strncmp(str, "share", 5) == 0)
-                       amd_iommu_isolate = false;
                if (strncmp(str, "fullflush", 9) == 0)
                        amd_iommu_unmap_flush = true;
        }
index 128111d..e0dfb68 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
 #include <asm/k8.h>
+#include <asm/x86_init.h>
 
 int gart_iommu_aperture;
 int gart_iommu_aperture_disabled __initdata;
@@ -400,6 +401,7 @@ void __init gart_iommu_hole_init(void)
 
                        iommu_detected = 1;
                        gart_iommu_aperture = 1;
+                       x86_init.iommu.iommu_init = gart_iommu_init;
 
                        aper_order = (read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL) >> 1) & 7;
                        aper_size = (32 * 1024 * 1024) << aper_order;
@@ -456,7 +458,7 @@ out:
 
        if (aper_alloc) {
                /* Got the aperture from the AGP bridge */
-       } else if (swiotlb && !valid_agp) {
+       } else if (!valid_agp) {
                /* Do nothing */
        } else if ((!no_iommu && max_pfn > MAX_DMA32_PFN) ||
                   force_iommu ||
index 5e409dc..a4849c1 100644 (file)
@@ -27,8 +27,7 @@
 #include <asm/cpu.h>
 #include <asm/reboot.h>
 #include <asm/virtext.h>
-#include <asm/iommu.h>
-
+#include <asm/x86_init.h>
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 
@@ -106,7 +105,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
 #endif
 
 #ifdef CONFIG_X86_64
-       pci_iommu_shutdown();
+       x86_platform.iommu_shutdown();
 #endif
 
        crash_save_cpu(regs, safe_smp_processor_id());
index c097e7d..7d52e9d 100644 (file)
@@ -1185,17 +1185,14 @@ END(ftrace_graph_caller)
 
 .globl return_to_handler
 return_to_handler:
-       pushl $0
        pushl %eax
-       pushl %ecx
        pushl %edx
        movl %ebp, %eax
        call ftrace_return_to_handler
-       movl %eax, 0xc(%esp)
+       movl %eax, %ecx
        popl %edx
-       popl %ecx
        popl %eax
-       ret
+       jmp *%ecx
 #endif
 
 .section .rodata,"a"
index b5c061f..bd5bbdd 100644 (file)
@@ -155,11 +155,11 @@ GLOBAL(return_to_handler)
 
        call ftrace_return_to_handler
 
-       movq %rax, 16(%rsp)
+       movq %rax, %rdi
        movq 8(%rsp), %rdx
        movq (%rsp), %rax
-       addq $16, %rsp
-       retq
+       addq $24, %rsp
+       jmp *%rdi
 #endif
 
 
index 9dbb527..5a1b975 100644 (file)
@@ -9,6 +9,8 @@
  * the dangers of modifying code on the run.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/spinlock.h>
 #include <linux/hardirq.h>
 #include <linux/uaccess.h>
@@ -336,15 +338,15 @@ int __init ftrace_dyn_arch_init(void *data)
 
        switch (faulted) {
        case 0:
-               pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n");
+               pr_info("converting mcount calls to 0f 1f 44 00 00\n");
                memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
                break;
        case 1:
-               pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n");
+               pr_info("converting mcount calls to 66 66 66 66 90\n");
                memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
                break;
        case 2:
-               pr_info("ftrace: converting mcount calls to jmp . + 5\n");
+               pr_info("converting mcount calls to jmp . + 5\n");
                memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
                break;
        }
@@ -468,82 +470,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 
-extern unsigned long __start_syscalls_metadata[];
-extern unsigned long __stop_syscalls_metadata[];
 extern unsigned long *sys_call_table;
 
-static struct syscall_metadata **syscalls_metadata;
-
-static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
-{
-       struct syscall_metadata *start;
-       struct syscall_metadata *stop;
-       char str[KSYM_SYMBOL_LEN];
-
-
-       start = (struct syscall_metadata *)__start_syscalls_metadata;
-       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
-       kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
-
-       for ( ; start < stop; start++) {
-               if (start->name && !strcmp(start->name, str))
-                       return start;
-       }
-       return NULL;
-}
-
-struct syscall_metadata *syscall_nr_to_meta(int nr)
-{
-       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
-               return NULL;
-
-       return syscalls_metadata[nr];
-}
-
-int syscall_name_to_nr(char *name)
+unsigned long __init arch_syscall_addr(int nr)
 {
-       int i;
-
-       if (!syscalls_metadata)
-               return -1;
-
-       for (i = 0; i < NR_syscalls; i++) {
-               if (syscalls_metadata[i]) {
-                       if (!strcmp(syscalls_metadata[i]->name, name))
-                               return i;
-               }
-       }
-       return -1;
-}
-
-void set_syscall_enter_id(int num, int id)
-{
-       syscalls_metadata[num]->enter_id = id;
-}
-
-void set_syscall_exit_id(int num, int id)
-{
-       syscalls_metadata[num]->exit_id = id;
-}
-
-static int __init arch_init_ftrace_syscalls(void)
-{
-       int i;
-       struct syscall_metadata *meta;
-       unsigned long **psys_syscall_table = &sys_call_table;
-
-       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
-                                       NR_syscalls, GFP_KERNEL);
-       if (!syscalls_metadata) {
-               WARN_ON(1);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < NR_syscalls; i++) {
-               meta = find_syscall_meta(psys_syscall_table[i]);
-               syscalls_metadata[i] = meta;
-       }
-       return 0;
+       return (unsigned long)(&sys_call_table)[nr];
 }
-arch_initcall(arch_init_ftrace_syscalls);
 #endif
index 971a3be..c563e4c 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/dma.h>
 #include <asm/rio.h>
 #include <asm/bios_ebda.h>
+#include <asm/x86_init.h>
 
 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
 int use_calgary __read_mostly = 1;
@@ -244,7 +245,7 @@ static unsigned long iommu_range_alloc(struct device *dev,
                        if (panic_on_overflow)
                                panic("Calgary: fix the allocator.\n");
                        else
-                               return bad_dma_address;
+                               return DMA_ERROR_CODE;
                }
        }
 
@@ -260,12 +261,15 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
                              void *vaddr, unsigned int npages, int direction)
 {
        unsigned long entry;
-       dma_addr_t ret = bad_dma_address;
+       dma_addr_t ret;
 
        entry = iommu_range_alloc(dev, tbl, npages);
 
-       if (unlikely(entry == bad_dma_address))
-               goto error;
+       if (unlikely(entry == DMA_ERROR_CODE)) {
+               printk(KERN_WARNING "Calgary: failed to allocate %u pages in "
+                      "iommu %p\n", npages, tbl);
+               return DMA_ERROR_CODE;
+       }
 
        /* set the return dma address */
        ret = (entry << PAGE_SHIFT) | ((unsigned long)vaddr & ~PAGE_MASK);
@@ -273,13 +277,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
        /* put the TCEs in the HW table */
        tce_build(tbl, entry, npages, (unsigned long)vaddr & PAGE_MASK,
                  direction);
-
        return ret;
-
-error:
-       printk(KERN_WARNING "Calgary: failed to allocate %u pages in "
-              "iommu %p\n", npages, tbl);
-       return bad_dma_address;
 }
 
 static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -290,8 +288,8 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
        unsigned long flags;
 
        /* were we called with bad_dma_address? */
-       badend = bad_dma_address + (EMERGENCY_PAGES * PAGE_SIZE);
-       if (unlikely((dma_addr >= bad_dma_address) && (dma_addr < badend))) {
+       badend = DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE);
+       if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) {
                WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "
                       "address 0x%Lx\n", dma_addr);
                return;
@@ -318,13 +316,15 @@ static inline struct iommu_table *find_iommu_table(struct device *dev)
 
        pdev = to_pci_dev(dev);
 
+       /* search up the device tree for an iommu */
        pbus = pdev->bus;
-
-       /* is the device behind a bridge? Look for the root bus */
-       while (pbus->parent)
+       do {
+               tbl = pci_iommu(pbus);
+               if (tbl && tbl->it_busno == pbus->number)
+                       break;
+               tbl = NULL;
                pbus = pbus->parent;
-
-       tbl = pci_iommu(pbus);
+       } while (pbus);
 
        BUG_ON(tbl && (tbl->it_busno != pbus->number));
 
@@ -373,7 +373,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
                npages = iommu_num_pages(vaddr, s->length, PAGE_SIZE);
 
                entry = iommu_range_alloc(dev, tbl, npages);
-               if (entry == bad_dma_address) {
+               if (entry == DMA_ERROR_CODE) {
                        /* makes sure unmap knows to stop */
                        s->dma_length = 0;
                        goto error;
@@ -391,7 +391,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
 error:
        calgary_unmap_sg(dev, sg, nelems, dir, NULL);
        for_each_sg(sg, s, nelems, i) {
-               sg->dma_address = bad_dma_address;
+               sg->dma_address = DMA_ERROR_CODE;
                sg->dma_length = 0;
        }
        return 0;
@@ -446,7 +446,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
 
        /* set up tces to cover the allocated range */
        mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
-       if (mapping == bad_dma_address)
+       if (mapping == DMA_ERROR_CODE)
                goto free;
        *dma_handle = mapping;
        return ret;
@@ -727,7 +727,7 @@ static void __init calgary_reserve_regions(struct pci_dev *dev)
        struct iommu_table *tbl = pci_iommu(dev->bus);
 
        /* reserve EMERGENCY_PAGES from bad_dma_address and up */
-       iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES);
+       iommu_range_reserve(tbl, DMA_ERROR_CODE, EMERGENCY_PAGES);
 
        /* avoid the BIOS/VGA first 640KB-1MB region */
        /* for CalIOC2 - avoid the entire first MB */
@@ -1344,6 +1344,23 @@ static void __init get_tce_space_from_tar(void)
        return;
 }
 
+static int __init calgary_iommu_init(void)
+{
+       int ret;
+
+       /* ok, we're trying to use Calgary - let's roll */
+       printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n");
+
+       ret = calgary_init();
+       if (ret) {
+               printk(KERN_ERR "PCI-DMA: Calgary init failed %d, "
+                      "falling back to no_iommu\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 void __init detect_calgary(void)
 {
        int bus;
@@ -1357,7 +1374,7 @@ void __init detect_calgary(void)
         * if the user specified iommu=off or iommu=soft or we found
         * another HW IOMMU already, bail out.
         */
-       if (swiotlb || no_iommu || iommu_detected)
+       if (no_iommu || iommu_detected)
                return;
 
        if (!use_calgary)
@@ -1442,9 +1459,7 @@ void __init detect_calgary(void)
                printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d\n",
                       specified_table_size);
 
-               /* swiotlb for devices that aren't behind the Calgary. */
-               if (max_pfn > MAX_DMA32_PFN)
-                       swiotlb = 1;
+               x86_init.iommu.iommu_init = calgary_iommu_init;
        }
        return;
 
@@ -1457,35 +1472,6 @@ cleanup:
        }
 }
 
-int __init calgary_iommu_init(void)
-{
-       int ret;
-
-       if (no_iommu || (swiotlb && !calgary_detected))
-               return -ENODEV;
-
-       if (!calgary_detected)
-               return -ENODEV;
-
-       /* ok, we're trying to use Calgary - let's roll */
-       printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n");
-
-       ret = calgary_init();
-       if (ret) {
-               printk(KERN_ERR "PCI-DMA: Calgary init failed %d, "
-                      "falling back to no_iommu\n", ret);
-               return ret;
-       }
-
-       force_iommu = 1;
-       bad_dma_address = 0x0;
-       /* dma_ops is set to swiotlb or nommu */
-       if (!dma_ops)
-               dma_ops = &nommu_dma_ops;
-
-       return 0;
-}
-
 static int __init calgary_parse_options(char *p)
 {
        unsigned int bridge;
index a6e804d..afcc58b 100644 (file)
 #include <asm/gart.h>
 #include <asm/calgary.h>
 #include <asm/amd_iommu.h>
+#include <asm/x86_init.h>
 
 static int forbid_dac __read_mostly;
 
-struct dma_map_ops *dma_ops;
+struct dma_map_ops *dma_ops = &nommu_dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
 static int iommu_sac_force __read_mostly;
@@ -42,9 +43,6 @@ int iommu_detected __read_mostly = 0;
  */
 int iommu_pass_through __read_mostly;
 
-dma_addr_t bad_dma_address __read_mostly = 0;
-EXPORT_SYMBOL(bad_dma_address);
-
 /* Dummy device used for NULL arguments (normally ISA). */
 struct device x86_dma_fallback_dev = {
        .init_name = "fallback device",
@@ -126,20 +124,17 @@ void __init pci_iommu_alloc(void)
        /* free the range so iommu could get some range less than 4G */
        dma32_free_bootmem();
 #endif
+       if (pci_swiotlb_init())
+               return;
 
-       /*
-        * The order of these functions is important for
-        * fall-back/fail-over reasons
-        */
        gart_iommu_hole_init();
 
        detect_calgary();
 
        detect_intel_iommu();
 
+       /* needs to be called after gart_iommu_hole_init */
        amd_iommu_detect();
-
-       pci_swiotlb_init();
 }
 
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
@@ -214,7 +209,7 @@ static __init int iommu_setup(char *p)
                if (!strncmp(p, "allowdac", 8))
                        forbid_dac = 0;
                if (!strncmp(p, "nodac", 5))
-                       forbid_dac = -1;
+                       forbid_dac = 1;
                if (!strncmp(p, "usedac", 6)) {
                        forbid_dac = -1;
                        return 1;
@@ -289,25 +284,17 @@ static int __init pci_iommu_init(void)
 #ifdef CONFIG_PCI
        dma_debug_add_bus(&pci_bus_type);
 #endif
+       x86_init.iommu.iommu_init();
 
-       calgary_iommu_init();
-
-       intel_iommu_init();
+       if (swiotlb) {
+               printk(KERN_INFO "PCI-DMA: "
+                      "Using software bounce buffering for IO (SWIOTLB)\n");
+               swiotlb_print_info();
+       } else
+               swiotlb_free();
 
-       amd_iommu_init();
-
-       gart_iommu_init();
-
-       no_iommu_init();
        return 0;
 }
-
-void pci_iommu_shutdown(void)
-{
-       gart_iommu_shutdown();
-
-       amd_iommu_shutdown();
-}
 /* Must execute after PCI subsystem */
 rootfs_initcall(pci_iommu_init);
 
index a7f1b64..e6a0d40 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
 #include <asm/k8.h>
+#include <asm/x86_init.h>
 
 static unsigned long iommu_bus_base;   /* GART remapping area (physical) */
 static unsigned long iommu_size;       /* size of remapping area bytes */
@@ -46,6 +47,8 @@ static unsigned long iommu_pages;     /* .. and in pages */
 
 static u32 *iommu_gatt_base;           /* Remapping table */
 
+static dma_addr_t bad_dma_addr;
+
 /*
  * If this is disabled the IOMMU will use an optimized flushing strategy
  * of only flushing when an mapping is reused. With it true the GART is
@@ -92,7 +95,7 @@ static unsigned long alloc_iommu(struct device *dev, int size,
 
        base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
                           PAGE_SIZE) >> PAGE_SHIFT;
-       boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
+       boundary_size = ALIGN((u64)dma_get_seg_boundary(dev) + 1,
                              PAGE_SIZE) >> PAGE_SHIFT;
 
        spin_lock_irqsave(&iommu_bitmap_lock, flags);
@@ -216,7 +219,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
                if (panic_on_overflow)
                        panic("dma_map_area overflow %lu bytes\n", size);
                iommu_full(dev, size, dir);
-               return bad_dma_address;
+               return bad_dma_addr;
        }
 
        for (i = 0; i < npages; i++) {
@@ -294,7 +297,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
        int i;
 
 #ifdef CONFIG_IOMMU_DEBUG
-       printk(KERN_DEBUG "dma_map_sg overflow\n");
+       pr_debug("dma_map_sg overflow\n");
 #endif
 
        for_each_sg(sg, s, nents, i) {
@@ -302,7 +305,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
 
                if (nonforced_iommu(dev, addr, s->length)) {
                        addr = dma_map_area(dev, addr, s->length, dir, 0);
-                       if (addr == bad_dma_address) {
+                       if (addr == bad_dma_addr) {
                                if (i > 0)
                                        gart_unmap_sg(dev, sg, i, dir, NULL);
                                nents = 0;
@@ -389,12 +392,14 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
        if (!dev)
                dev = &x86_dma_fallback_dev;
 
-       out = 0;
-       start = 0;
-       start_sg = sgmap = sg;
-       seg_size = 0;
-       max_seg_size = dma_get_max_seg_size(dev);
-       ps = NULL; /* shut up gcc */
+       out             = 0;
+       start           = 0;
+       start_sg        = sg;
+       sgmap           = sg;
+       seg_size        = 0;
+       max_seg_size    = dma_get_max_seg_size(dev);
+       ps              = NULL; /* shut up gcc */
+
        for_each_sg(sg, s, nents, i) {
                dma_addr_t addr = sg_phys(s);
 
@@ -417,11 +422,12 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
                                                 sgmap, pages, need) < 0)
                                        goto error;
                                out++;
-                               seg_size = 0;
-                               sgmap = sg_next(sgmap);
-                               pages = 0;
-                               start = i;
-                               start_sg = s;
+
+                               seg_size        = 0;
+                               sgmap           = sg_next(sgmap);
+                               pages           = 0;
+                               start           = i;
+                               start_sg        = s;
                        }
                }
 
@@ -455,7 +461,7 @@ error:
 
        iommu_full(dev, pages << PAGE_SHIFT, dir);
        for_each_sg(sg, s, nents, i)
-               s->dma_address = bad_dma_address;
+               s->dma_address = bad_dma_addr;
        return 0;
 }
 
@@ -479,7 +485,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
                                     DMA_BIDIRECTIONAL, align_mask);
 
                flush_gart();
-               if (paddr != bad_dma_address) {
+               if (paddr != bad_dma_addr) {
                        *dma_addr = paddr;
                        return page_address(page);
                }
@@ -499,6 +505,11 @@ gart_free_coherent(struct device *dev, size_t size, void *vaddr,
        free_pages((unsigned long)vaddr, get_order(size));
 }
 
+static int gart_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       return (dma_addr == bad_dma_addr);
+}
+
 static int no_agp;
 
 static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
@@ -515,7 +526,7 @@ static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
        iommu_size -= round_up(a, PMD_PAGE_SIZE) - a;
 
        if (iommu_size < 64*1024*1024) {
-               printk(KERN_WARNING
+               pr_warning(
                        "PCI-DMA: Warning: Small IOMMU %luMB."
                        " Consider increasing the AGP aperture in BIOS\n",
                                iommu_size >> 20);
@@ -570,28 +581,32 @@ void set_up_gart_resume(u32 aper_order, u32 aper_alloc)
        aperture_alloc = aper_alloc;
 }
 
-static int gart_resume(struct sys_device *dev)
+static void gart_fixup_northbridges(struct sys_device *dev)
 {
-       printk(KERN_INFO "PCI-DMA: Resuming GART IOMMU\n");
+       int i;
 
-       if (fix_up_north_bridges) {
-               int i;
+       if (!fix_up_north_bridges)
+               return;
 
-               printk(KERN_INFO "PCI-DMA: Restoring GART aperture settings\n");
+       pr_info("PCI-DMA: Restoring GART aperture settings\n");
 
-               for (i = 0; i < num_k8_northbridges; i++) {
-                       struct pci_dev *dev = k8_northbridges[i];
+       for (i = 0; i < num_k8_northbridges; i++) {
+               struct pci_dev *dev = k8_northbridges[i];
 
-                       /*
-                        * Don't enable translations just yet.  That is the next
-                        * step.  Restore the pre-suspend aperture settings.
-                        */
-                       pci_write_config_dword(dev, AMD64_GARTAPERTURECTL,
-                                               aperture_order << 1);
-                       pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE,
-                                               aperture_alloc >> 25);
-               }
+               /*
+                * Don't enable translations just yet.  That is the next
+                * step.  Restore the pre-suspend aperture settings.
+                */
+               pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, aperture_order << 1);
+               pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, aperture_alloc >> 25);
        }
+}
+
+static int gart_resume(struct sys_device *dev)
+{
+       pr_info("PCI-DMA: Resuming GART IOMMU\n");
+
+       gart_fixup_northbridges(dev);
 
        enable_gart_translations();
 
@@ -604,15 +619,14 @@ static int gart_suspend(struct sys_device *dev, pm_message_t state)
 }
 
 static struct sysdev_class gart_sysdev_class = {
-       .name = "gart",
-       .suspend = gart_suspend,
-       .resume = gart_resume,
+       .name           = "gart",
+       .suspend        = gart_suspend,
+       .resume         = gart_resume,
 
 };
 
 static struct sys_device device_gart = {
-       .id     = 0,
-       .cls    = &gart_sysdev_class,
+       .cls            = &gart_sysdev_class,
 };
 
 /*
@@ -627,7 +641,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
        void *gatt;
        int i, error;
 
-       printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
+       pr_info("PCI-DMA: Disabling AGP.\n");
+
        aper_size = aper_base = info->aper_size = 0;
        dev = NULL;
        for (i = 0; i < num_k8_northbridges; i++) {
@@ -645,6 +660,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
        }
        if (!aper_base)
                goto nommu;
+
        info->aper_base = aper_base;
        info->aper_size = aper_size >> 20;
 
@@ -667,14 +683,14 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
 
        flush_gart();
 
-       printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n",
+       pr_info("PCI-DMA: aperture base @ %x size %u KB\n",
               aper_base, aper_size>>10);
 
        return 0;
 
  nommu:
        /* Should not happen anymore */
-       printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n"
+       pr_warning("PCI-DMA: More than 4GB of RAM and no IOMMU\n"
               "falling back to iommu=soft.\n");
        return -1;
 }
@@ -686,14 +702,15 @@ static struct dma_map_ops gart_dma_ops = {
        .unmap_page                     = gart_unmap_page,
        .alloc_coherent                 = gart_alloc_coherent,
        .free_coherent                  = gart_free_coherent,
+       .mapping_error                  = gart_mapping_error,
 };
 
-void gart_iommu_shutdown(void)
+static void gart_iommu_shutdown(void)
 {
        struct pci_dev *dev;
        int i;
 
-       if (no_agp && (dma_ops != &gart_dma_ops))
+       if (no_agp)
                return;
 
        for (i = 0; i < num_k8_northbridges; i++) {
@@ -708,7 +725,7 @@ void gart_iommu_shutdown(void)
        }
 }
 
-void __init gart_iommu_init(void)
+int __init gart_iommu_init(void)
 {
        struct agp_kern_info info;
        unsigned long iommu_start;
@@ -718,7 +735,7 @@ void __init gart_iommu_init(void)
        long i;
 
        if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0)
-               return;
+               return 0;
 
 #ifndef CONFIG_AGP_AMD64
        no_agp = 1;
@@ -730,35 +747,28 @@ void __init gart_iommu_init(void)
                (agp_copy_info(agp_bridge, &info) < 0);
 #endif
 
-       if (swiotlb)
-               return;
-
-       /* Did we detect a different HW IOMMU? */
-       if (iommu_detected && !gart_iommu_aperture)
-               return;
-
        if (no_iommu ||
            (!force_iommu && max_pfn <= MAX_DMA32_PFN) ||
            !gart_iommu_aperture ||
            (no_agp && init_k8_gatt(&info) < 0)) {
                if (max_pfn > MAX_DMA32_PFN) {
-                       printk(KERN_WARNING "More than 4GB of memory "
-                              "but GART IOMMU not available.\n");
-                       printk(KERN_WARNING "falling back to iommu=soft.\n");
+                       pr_warning("More than 4GB of memory but GART IOMMU not available.\n");
+                       pr_warning("falling back to iommu=soft.\n");
                }
-               return;
+               return 0;
        }
 
        /* need to map that range */
-       aper_size = info.aper_size << 20;
-       aper_base = info.aper_base;
-       end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT);
+       aper_size       = info.aper_size << 20;
+       aper_base       = info.aper_base;
+       end_pfn         = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT);
+
        if (end_pfn > max_low_pfn_mapped) {
                start_pfn = (aper_base>>PAGE_SHIFT);
                init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
        }
 
-       printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
+       pr_info("PCI-DMA: using GART IOMMU.\n");
        iommu_size = check_iommu_size(info.aper_base, aper_size);
        iommu_pages = iommu_size >> PAGE_SHIFT;
 
@@ -773,8 +783,7 @@ void __init gart_iommu_init(void)
 
                ret = dma_debug_resize_entries(iommu_pages);
                if (ret)
-                       printk(KERN_DEBUG
-                              "PCI-DMA: Cannot trace all the entries\n");
+                       pr_debug("PCI-DMA: Cannot trace all the entries\n");
        }
 #endif
 
@@ -784,15 +793,14 @@ void __init gart_iommu_init(void)
         */
        iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES);
 
-       agp_memory_reserved = iommu_size;
-       printk(KERN_INFO
-              "PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n",
+       pr_info("PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n",
               iommu_size >> 20);
 
-       iommu_start = aper_size - iommu_size;
-       iommu_bus_base = info.aper_base + iommu_start;
-       bad_dma_address = iommu_bus_base;
-       iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT);
+       agp_memory_reserved     = iommu_size;
+       iommu_start             = aper_size - iommu_size;
+       iommu_bus_base          = info.aper_base + iommu_start;
+       bad_dma_addr            = iommu_bus_base;
+       iommu_gatt_base         = agp_gatt_table + (iommu_start>>PAGE_SHIFT);
 
        /*
         * Unmap the IOMMU part of the GART. The alias of the page is
@@ -814,7 +822,7 @@ void __init gart_iommu_init(void)
         * the pages as Not-Present:
         */
        wbinvd();
-       
+
        /*
         * Now all caches are flushed and we can safely enable
         * GART hardware.  Doing it early leaves the possibility
@@ -838,6 +846,10 @@ void __init gart_iommu_init(void)
 
        flush_gart();
        dma_ops = &gart_dma_ops;
+       x86_platform.iommu_shutdown = gart_iommu_shutdown;
+       swiotlb = 0;
+
+       return 0;
 }
 
 void __init gart_parse_options(char *p)
@@ -856,7 +868,7 @@ void __init gart_parse_options(char *p)
 #endif
        if (isdigit(*p) && get_option(&p, &arg))
                iommu_size = arg;
-       if (!strncmp(p, "fullflush", 8))
+       if (!strncmp(p, "fullflush", 9))
                iommu_fullflush = 1;
        if (!strncmp(p, "nofullflush", 11))
                iommu_fullflush = 0;
index a3933d4..22be12b 100644 (file)
@@ -33,7 +33,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
        dma_addr_t bus = page_to_phys(page) + offset;
        WARN_ON(size == 0);
        if (!check_addr("map_single", dev, bus, size))
-               return bad_dma_address;
+               return DMA_ERROR_CODE;
        flush_write_buffers();
        return bus;
 }
@@ -103,12 +103,3 @@ struct dma_map_ops nommu_dma_ops = {
        .sync_sg_for_device     = nommu_sync_sg_for_device,
        .is_phys                = 1,
 };
-
-void __init no_iommu_init(void)
-{
-       if (dma_ops)
-               return;
-
-       force_iommu = 0; /* no HW IOMMU */
-       dma_ops = &nommu_dma_ops;
-}
index aaa6b78..e3c0a66 100644 (file)
@@ -42,18 +42,28 @@ static struct dma_map_ops swiotlb_dma_ops = {
        .dma_supported = NULL,
 };
 
-void __init pci_swiotlb_init(void)
+/*
+ * pci_swiotlb_init - initialize swiotlb if necessary
+ *
+ * This returns non-zero if we are forced to use swiotlb (by the boot
+ * option).
+ */
+int __init pci_swiotlb_init(void)
 {
+       int use_swiotlb = swiotlb | swiotlb_force;
+
        /* don't initialize swiotlb if iommu=off (no_iommu=1) */
 #ifdef CONFIG_X86_64
-       if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN))
+       if (!no_iommu && max_pfn > MAX_DMA32_PFN)
                swiotlb = 1;
 #endif
        if (swiotlb_force)
                swiotlb = 1;
+
        if (swiotlb) {
-               printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
-               swiotlb_init();
+               swiotlb_init(0);
                dma_ops = &swiotlb_dma_ops;
        }
+
+       return use_swiotlb;
 }
index f930787..2b97fc5 100644 (file)
@@ -23,7 +23,7 @@
 # include <linux/ctype.h>
 # include <linux/mc146818rtc.h>
 #else
-# include <asm/iommu.h>
+# include <asm/x86_init.h>
 #endif
 
 /*
@@ -622,7 +622,7 @@ void native_machine_shutdown(void)
 #endif
 
 #ifdef CONFIG_X86_64
-       pci_iommu_shutdown();
+       x86_platform.iommu_shutdown();
 #endif
 }
 
index 4449a4a..d11c5ff 100644 (file)
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/tsc.h>
+#include <asm/iommu.h>
 
 void __cpuinit x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
+int __init iommu_init_noop(void) { return 0; }
+void iommu_shutdown_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -62,6 +65,10 @@ struct x86_init_ops x86_init __initdata = {
                .tsc_pre_init           = x86_init_noop,
                .timer_init             = hpet_time_init,
        },
+
+       .iommu = {
+               .iommu_init             = iommu_init_noop,
+       },
 };
 
 struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
@@ -72,4 +79,5 @@ struct x86_platform_ops x86_platform = {
        .calibrate_tsc                  = native_calibrate_tsc,
        .get_wallclock                  = mach_get_cmos_time,
        .set_wallclock                  = mach_set_rtc_mmss,
+       .iommu_shutdown                 = iommu_shutdown_noop,
 };
index 427fd1b..8565d94 100644 (file)
@@ -1,12 +1,13 @@
 /*
  * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/mmiotrace.h>
 
-#define MODULE_NAME "testmmiotrace"
-
 static unsigned long mmio_address;
 module_param(mmio_address, ulong, 0);
 MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
@@ -30,7 +31,7 @@ static unsigned v32(unsigned i)
 static void do_write_test(void __iomem *p)
 {
        unsigned int i;
-       pr_info(MODULE_NAME ": write test.\n");
+       pr_info("write test.\n");
        mmiotrace_printk("Write test.\n");
 
        for (i = 0; i < 256; i++)
@@ -47,7 +48,7 @@ static void do_read_test(void __iomem *p)
 {
        unsigned int i;
        unsigned errs[3] = { 0 };
-       pr_info(MODULE_NAME ": read test.\n");
+       pr_info("read test.\n");
        mmiotrace_printk("Read test.\n");
 
        for (i = 0; i < 256; i++)
@@ -68,7 +69,7 @@ static void do_read_test(void __iomem *p)
 
 static void do_read_far_test(void __iomem *p)
 {
-       pr_info(MODULE_NAME ": read far test.\n");
+       pr_info("read far test.\n");
        mmiotrace_printk("Read far test.\n");
 
        ioread32(p + read_far);
@@ -78,7 +79,7 @@ static void do_test(unsigned long size)
 {
        void __iomem *p = ioremap_nocache(mmio_address, size);
        if (!p) {
-               pr_err(MODULE_NAME ": could not ioremap, aborting.\n");
+               pr_err("could not ioremap, aborting.\n");
                return;
        }
        mmiotrace_printk("ioremap returned %p.\n", p);
@@ -94,24 +95,22 @@ static int __init init(void)
        unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
 
        if (mmio_address == 0) {
-               pr_err(MODULE_NAME ": you have to use the module argument "
-                                                       "mmio_address.\n");
-               pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS"
-                               " YOU REALLY KNOW WHAT YOU ARE DOING!\n");
+               pr_err("you have to use the module argument mmio_address.\n");
+               pr_err("DO NOT LOAD THIS MODULE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!\n");
                return -ENXIO;
        }
 
-       pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI "
-               "address space, and writing 16 kB of rubbish in there.\n",
-                size >> 10, mmio_address);
+       pr_warning("WARNING: mapping %lu kB @ 0x%08lx in PCI address space, "
+                  "and writing 16 kB of rubbish in there.\n",
+                  size >> 10, mmio_address);
        do_test(size);
-       pr_info(MODULE_NAME ": All done.\n");
+       pr_info("All done.\n");
        return 0;
 }
 
 static void __exit cleanup(void)
 {
-       pr_debug(MODULE_NAME ": unloaded.\n");
+       pr_debug("unloaded.\n");
 }
 
 module_init(init);
index dc99e26..1b392c9 100644 (file)
@@ -177,9 +177,6 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
        .drain_fifo     = pcmcia_8bit_drain_fifo,
 };
 
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-
 
 struct pcmcia_config_check {
        unsigned long ctl_base;
@@ -252,7 +249,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        struct ata_port *ap;
        struct ata_pcmcia_info *info;
        struct pcmcia_config_check *stk = NULL;
-       int last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
+       int is_kme = 0, ret = -ENOMEM, p;
        unsigned long io_base, ctl_base;
        void __iomem *io_addr, *ctl_addr;
        int n_ports = 1;
@@ -271,7 +268,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
        pdev->io.IOAddrLines = 3;
        pdev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
-       pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;
        pdev->conf.Attributes = CONF_ENABLE_IRQ;
        pdev->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -296,8 +292,13 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        }
        io_base = pdev->io.BasePort1;
        ctl_base = stk->ctl_base;
-       CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
+       ret = pcmcia_request_irq(pdev, &pdev->irq);
+       if (ret)
+               goto failed;
+
+       ret = pcmcia_request_configuration(pdev, &pdev->conf);
+       if (ret)
+               goto failed;
 
        /* iomap */
        ret = -ENOMEM;
@@ -351,8 +352,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        kfree(stk);
        return 0;
 
-cs_failed:
-       cs_error(pdev, last_fn, last_ret);
 failed:
        kfree(stk);
        info->ndev = 0;
index 965ece2..13bb69d 100644 (file)
@@ -735,6 +735,21 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector
        part_stat_unlock();
 }
 
+/*
+ * Ensure we don't create aliases in VI caches
+ */
+static inline void
+killalias(struct bio *bio)
+{
+       struct bio_vec *bv;
+       int i;
+
+       if (bio_data_dir(bio) == READ)
+               __bio_for_each_segment(bv, bio, i, 0) {
+                       flush_dcache_page(bv->bv_page);
+               }
+}
+
 void
 aoecmd_ata_rsp(struct sk_buff *skb)
 {
@@ -853,8 +868,12 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 
        if (buf && --buf->nframesout == 0 && buf->resid == 0) {
                diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector);
-               n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
-               bio_endio(buf->bio, n);
+               if (buf->flags & BUFFL_FAIL)
+                       bio_endio(buf->bio, -EIO);
+               else {
+                       killalias(buf->bio);
+                       bio_endio(buf->bio, 0);
+               }
                mempool_free(buf, d->bufpool);
        }
 
index b0e569b..2acdc60 100644 (file)
@@ -867,11 +867,9 @@ static int bluecard_probe(struct pcmcia_device *link)
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
        link->io.NumPorts1 = 8;
-       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
-       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 
        link->irq.Handler = bluecard_interrupt;
-       link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.IntType = INT_MEMORY_AND_IO;
@@ -905,22 +903,16 @@ static int bluecard_config(struct pcmcia_device *link)
                        break;
        }
 
-       if (i != 0) {
-               cs_error(link, RequestIO, i);
+       if (i != 0)
                goto failed;
-       }
 
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != 0) {
-               cs_error(link, RequestIRQ, i);
+       if (i != 0)
                link->irq.AssignedIRQ = 0;
-       }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != 0) {
-               cs_error(link, RequestConfiguration, i);
+       if (i != 0)
                goto failed;
-       }
 
        if (bluecard_open(info) != 0)
                goto failed;
index d58e22b..d814a27 100644 (file)
@@ -659,11 +659,9 @@ static int bt3c_probe(struct pcmcia_device *link)
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
        link->io.NumPorts1 = 8;
-       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
-       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 
        link->irq.Handler = bt3c_interrupt;
-       link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.IntType = INT_MEMORY_AND_IO;
@@ -740,21 +738,16 @@ static int bt3c_config(struct pcmcia_device *link)
                goto found_port;
 
        BT_ERR("No usable port range found");
-       cs_error(link, RequestIO, -ENODEV);
        goto failed;
 
 found_port:
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != 0) {
-               cs_error(link, RequestIRQ, i);
+       if (i != 0)
                link->irq.AssignedIRQ = 0;
-       }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != 0) {
-               cs_error(link, RequestConfiguration, i);
+       if (i != 0)
                goto failed;
-       }
 
        if (bt3c_open(info) != 0)
                goto failed;
index efd689a..d339464 100644 (file)
@@ -588,11 +588,9 @@ static int btuart_probe(struct pcmcia_device *link)
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
        link->io.NumPorts1 = 8;
-       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
-       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 
        link->irq.Handler = btuart_interrupt;
-       link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.IntType = INT_MEMORY_AND_IO;
@@ -669,21 +667,16 @@ static int btuart_config(struct pcmcia_device *link)
                goto found_port;
 
        BT_ERR("No usable port range found");
-       cs_error(link, RequestIO, -ENODEV);
        goto failed;
 
 found_port:
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != 0) {
-               cs_error(link, RequestIRQ, i);
+       if (i != 0)
                link->irq.AssignedIRQ = 0;
-       }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != 0) {
-               cs_error(link, RequestConfiguration, i);
+       if (i != 0)
                goto failed;
-       }
 
        if (btuart_open(info) != 0)
                goto failed;
index b881a9c..4f02a6f 100644 (file)
@@ -573,11 +573,9 @@ static int dtl1_probe(struct pcmcia_device *link)
 
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
        link->io.NumPorts1 = 8;
-       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
-       link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 
        link->irq.Handler = dtl1_interrupt;
-       link->irq.Instance = info;
 
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.IntType = INT_MEMORY_AND_IO;
@@ -622,16 +620,12 @@ static int dtl1_config(struct pcmcia_device *link)
                goto failed;
 
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != 0) {
-               cs_error(link, RequestIRQ, i);
+       if (i != 0)
                link->irq.AssignedIRQ = 0;
-       }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != 0) {
-               cs_error(link, RequestConfiguration, i);
+       if (i != 0)
                goto failed;
-       }
 
        if (dtl1_open(info) != 0)
                goto failed;
index ccb1fa8..2fb3a48 100644 (file)
@@ -56,9 +56,8 @@ config AGP_AMD
          X on AMD Irongate, 761, and 762 chipsets.
 
 config AGP_AMD64
-       tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
+       tristate "AMD Opteron/Athlon64 on-CPU GART support"
        depends on AGP && X86
-       default y if GART_IOMMU
        help
          This option gives you AGP support for the GLX component of
          X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
index c250a31..2db4c0a 100644 (file)
@@ -23,8 +23,6 @@
   * All rights reserved. Licensed under dual BSD/GPL license.
   */
 
-/* #define PCMCIA_DEBUG 6 */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 
 /* #define ATR_CSUM */
 
-#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)       (&handle_to_dev(x->p_dev))
-static int pc_debug = PCMCIA_DEBUG;
-module_param(pc_debug, int, 0600);
-#define DEBUGP(n, rdr, x, args...) do {                                \
-       if (pc_debug >= (n))                                            \
-               dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x,     \
-                          __func__ , ## args);                 \
+#define reader_to_dev(x)       (&x->p_dev->dev)
+
+/* n (debug level) is ignored */
+/* additional debug output may be enabled by re-compiling with
+ * CM4000_DEBUG set */
+/* #define CM4000_DEBUG */
+#define DEBUGP(n, rdr, x, args...) do {                \
+               dev_dbg(reader_to_dev(rdr), "%s:" x,    \
+                          __func__ , ## args);         \
        } while (0)
-#else
-#define DEBUGP(n, rdr, x, args...)
-#endif
+
 static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
 
 #define        T_1SEC          (HZ)
@@ -174,14 +171,13 @@ static unsigned char fi_di_table[10][14] = {
 /* 9 */ {0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x11,0x11,0x99,0xA9,0xB9,0xC9,0xD9}
 };
 
-#ifndef PCMCIA_DEBUG
+#ifndef CM4000_DEBUG
 #define        xoutb   outb
 #define        xinb    inb
 #else
 static inline void xoutb(unsigned char val, unsigned short port)
 {
-       if (pc_debug >= 7)
-               printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port);
+       pr_debug("outb(val=%.2x,port=%.4x)\n", val, port);
        outb(val, port);
 }
 static inline unsigned char xinb(unsigned short port)
@@ -189,8 +185,7 @@ static inline unsigned char xinb(unsigned short port)
        unsigned char val;
 
        val = inb(port);
-       if (pc_debug >= 7)
-               printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port);
+       pr_debug("%.2x=inb(%.4x)\n", val, port);
 
        return val;
 }
@@ -514,12 +509,10 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
        for (i = 0; i < 4; i++) {
                xoutb(i, REG_BUF_ADDR(iobase));
                xoutb(dev->pts[i], REG_BUF_DATA(iobase));       /* buf data */
-#ifdef PCMCIA_DEBUG
-               if (pc_debug >= 5)
-                       printk("0x%.2x ", dev->pts[i]);
+#ifdef CM4000_DEBUG
+               pr_debug("0x%.2x ", dev->pts[i]);
        }
-       if (pc_debug >= 5)
-               printk("\n");
+       pr_debug("\n");
 #else
        }
 #endif
@@ -579,14 +572,13 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
                pts_reply[i] = inb(REG_BUF_DATA(iobase));
        }
 
-#ifdef PCMCIA_DEBUG
+#ifdef CM4000_DEBUG
        DEBUGP(2, dev, "PTSreply: ");
        for (i = 0; i < num_bytes_read; i++) {
-               if (pc_debug >= 5)
-                       printk("0x%.2x ", pts_reply[i]);
+               pr_debug("0x%.2x ", pts_reply[i]);
        }
-       printk("\n");
-#endif /* PCMCIA_DEBUG */
+       pr_debug("\n");
+#endif /* CM4000_DEBUG */
 
        DEBUGP(5, dev, "Clear Tactive in Flags1\n");
        xoutb(0x20, REG_FLAGS1(iobase));
@@ -655,7 +647,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
 
        DEBUGP(5, dev, "Delete timer\n");
        del_timer_sync(&dev->timer);
-#ifdef PCMCIA_DEBUG
+#ifdef CM4000_DEBUG
        dev->monitor_running = 0;
 #endif
 
@@ -898,7 +890,7 @@ static void monitor_card(unsigned long p)
                                DEBUGP(4, dev, "ATR checksum (0x%.2x, should "
                                       "be zero) failed\n", dev->atr_csum);
                        }
-#ifdef PCMCIA_DEBUG
+#ifdef CM4000_DEBUG
                        else if (test_bit(IS_BAD_LENGTH, &dev->flags)) {
                                DEBUGP(4, dev, "ATR length error\n");
                        } else {
@@ -1415,7 +1407,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int size;
        int rc;
        void __user *argp = (void __user *)arg;
-#ifdef PCMCIA_DEBUG
+#ifdef CM4000_DEBUG
        char *ioctl_names[CM_IOC_MAXNR + 1] = {
                [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS",
                [_IOC_NR(CM_IOCGATR)] "CM_IOCGATR",
@@ -1423,9 +1415,9 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                [_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS",
                [_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL",
        };
-#endif
        DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode),
               iminor(inode), ioctl_names[_IOC_NR(cmd)]);
+#endif
 
        lock_kernel();
        rc = -ENODEV;
@@ -1523,7 +1515,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                }
        case CM_IOCARDOFF:
 
-#ifdef PCMCIA_DEBUG
+#ifdef CM4000_DEBUG
                DEBUGP(4, dev, "... in CM_IOCARDOFF\n");
                if (dev->flags0 & 0x01) {
                        DEBUGP(4, dev, "    Card inserted\n");
@@ -1625,18 +1617,9 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
                }
                break;
-#ifdef PCMCIA_DEBUG
-       case CM_IOSDBGLVL:      /* set debug log level */
-               {
-                       int old_pc_debug = 0;
-
-                       old_pc_debug = pc_debug;
-                       if (copy_from_user(&pc_debug, argp, sizeof(int)))
-                               rc = -EFAULT;
-                       else if (old_pc_debug != pc_debug)
-                               DEBUGP(0, dev, "Changed debug log level "
-                                      "to %i\n", pc_debug);
-               }
+#ifdef CM4000_DEBUG
+       case CM_IOSDBGLVL:
+               rc = -ENOTTY;
                break;
 #endif
        default:
index 4f0723b..a6a70e4 100644 (file)
@@ -17,8 +17,6 @@
  * All rights reserved, Dual BSD/GPL Licensed.
  */
 
-/* #define PCMCIA_DEBUG 6 */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include "cm4040_cs.h"
 
 
-#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)       (&handle_to_dev(x->p_dev))
-static int pc_debug = PCMCIA_DEBUG;
-module_param(pc_debug, int, 0600);
-#define DEBUGP(n, rdr, x, args...) do {                                \
-       if (pc_debug >= (n))                                            \
-               dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x,     \
-                          __func__ , ##args);                  \
+#define reader_to_dev(x)       (&x->p_dev->dev)
+
+/* n (debug level) is ignored */
+/* additional debug output may be enabled by re-compiling with
+ * CM4040_DEBUG set */
+/* #define CM4040_DEBUG */
+#define DEBUGP(n, rdr, x, args...) do {                \
+               dev_dbg(reader_to_dev(rdr), "%s:" x,    \
+                          __func__ , ## args);         \
        } while (0)
-#else
-#define DEBUGP(n, rdr, x, args...)
-#endif
 
 static char *version =
 "OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte";
@@ -90,14 +86,13 @@ struct reader_dev {
 
 static struct pcmcia_device *dev_table[CM_MAX_DEV];
 
-#ifndef PCMCIA_DEBUG
+#ifndef CM4040_DEBUG
 #define        xoutb   outb
 #define        xinb    inb
 #else
 static inline void xoutb(unsigned char val, unsigned short port)
 {
-       if (pc_debug >= 7)
-               printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port);
+       pr_debug("outb(val=%.2x,port=%.4x)\n", val, port);
        outb(val, port);
 }
 
@@ -106,8 +101,7 @@ static inline unsigned char xinb(unsigned short port)
        unsigned char val;
 
        val = inb(port);
-       if (pc_debug >= 7)
-               printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port);
+       pr_debug("%.2x=inb(%.4x)\n", val, port);
        return val;
 }
 #endif
@@ -260,23 +254,22 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
                        return -EIO;
                }
                dev->r_buf[i] = xinb(iobase + REG_OFFSET_BULK_IN);
-#ifdef PCMCIA_DEBUG
-               if (pc_debug >= 6)
-                       printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]);
+#ifdef CM4040_DEBUG
+               pr_debug("%lu:%2x ", i, dev->r_buf[i]);
        }
-       printk("\n");
+       pr_debug("\n");
 #else
        }
 #endif
 
        bytes_to_read = 5 + le32_to_cpu(*(__le32 *)&dev->r_buf[1]);
 
-       DEBUGP(6, dev, "BytesToRead=%lu\n", bytes_to_read);
+       DEBUGP(6, dev, "BytesToRead=%zu\n", bytes_to_read);
 
        min_bytes_to_read = min(count, bytes_to_read + 5);
        min_bytes_to_read = min_t(size_t, min_bytes_to_read, READ_WRITE_BUFFER_SIZE);
 
-       DEBUGP(6, dev, "Min=%lu\n", min_bytes_to_read);
+       DEBUGP(6, dev, "Min=%zu\n", min_bytes_to_read);
 
        for (i = 0; i < (min_bytes_to_read-5); i++) {
                rc = wait_for_bulk_in_ready(dev);
@@ -288,11 +281,10 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
                        return -EIO;
                }
                dev->r_buf[i+5] = xinb(iobase + REG_OFFSET_BULK_IN);
-#ifdef PCMCIA_DEBUG
-               if (pc_debug >= 6)
-                       printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]);
+#ifdef CM4040_DEBUG
+               pr_debug("%lu:%2x ", i, dev->r_buf[i]);
        }
-       printk("\n");
+       pr_debug("\n");
 #else
        }
 #endif
@@ -547,7 +539,7 @@ static int cm4040_config_check(struct pcmcia_device *p_dev,
        p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
 
        rc = pcmcia_request_io(p_dev, &p_dev->io);
-       dev_printk(KERN_INFO, &handle_to_dev(p_dev),
+       dev_printk(KERN_INFO, &p_dev->dev,
                   "pcmcia_request_io returned 0x%x\n", rc);
        return rc;
 }
@@ -569,7 +561,7 @@ static int reader_config(struct pcmcia_device *link, int devno)
 
        fail_rc = pcmcia_request_configuration(link, &link->conf);
        if (fail_rc != 0) {
-               dev_printk(KERN_INFO, &handle_to_dev(link),
+               dev_printk(KERN_INFO, &link->dev,
                           "pcmcia_request_configuration failed 0x%x\n",
                           fail_rc);
                goto cs_release;
index 4c1820c..99cffda 100644 (file)
@@ -1213,12 +1213,12 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
 
 irqreturn_t ipwireless_interrupt(int irq, void *dev_id)
 {
-       struct ipw_hardware *hw = dev_id;
+       struct ipw_dev *ipw = dev_id;
 
-       if (hw->hw_version == HW_VERSION_1)
-               return ipwireless_handle_v1_interrupt(irq, hw);
+       if (ipw->hardware->hw_version == HW_VERSION_1)
+               return ipwireless_handle_v1_interrupt(irq, ipw->hardware);
        else
-               return ipwireless_handle_v2_v3_interrupt(irq, hw);
+               return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware);
 }
 
 static void flush_packets_to_hw(struct ipw_hardware *hw)
index 5216fce..dff24da 100644 (file)
@@ -65,10 +65,7 @@ static void signalled_reboot_work(struct work_struct *work_reboot)
        struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
                        work_reboot);
        struct pcmcia_device *link = ipw->link;
-       int ret = pcmcia_reset_card(link->socket);
-
-       if (ret != 0)
-               cs_error(link, ResetCard, ret);
+       pcmcia_reset_card(link->socket);
 }
 
 static void signalled_reboot_callback(void *callback_data)
@@ -79,208 +76,127 @@ static void signalled_reboot_callback(void *callback_data)
        schedule_work(&ipw->work_reboot);
 }
 
-static int config_ipwireless(struct ipw_dev *ipw)
+static int ipwireless_probe(struct pcmcia_device *p_dev,
+                           cistpl_cftable_entry_t *cfg,
+                           cistpl_cftable_entry_t *dflt,
+                           unsigned int vcc,
+                           void *priv_data)
 {
-       struct pcmcia_device *link = ipw->link;
-       int ret;
-       tuple_t tuple;
-       unsigned short buf[64];
-       cisparse_t parse;
-       unsigned short cor_value;
+       struct ipw_dev *ipw = priv_data;
+       struct resource *io_resource;
        memreq_t memreq_attr_memory;
        memreq_t memreq_common_memory;
+       int ret;
 
-       ipw->is_v2_card = 0;
-
-       tuple.Attributes = 0;
-       tuple.TupleData = (cisdata_t *) buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-
-       tuple.DesiredTuple = RETURN_FIRST_TUPLE;
-
-       ret = pcmcia_get_first_tuple(link, &tuple);
-
-       while (ret == 0) {
-               ret = pcmcia_get_tuple_data(link, &tuple);
-
-               if (ret != 0) {
-                       cs_error(link, GetTupleData, ret);
-                       goto exit0;
-               }
-               ret = pcmcia_get_next_tuple(link, &tuple);
-       }
-
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
-       ret = pcmcia_get_first_tuple(link, &tuple);
-
-       if (ret != 0) {
-               cs_error(link, GetFirstTuple, ret);
-               goto exit0;
-       }
-
-       ret = pcmcia_get_tuple_data(link, &tuple);
-
-       if (ret != 0) {
-               cs_error(link, GetTupleData, ret);
-               goto exit0;
-       }
-
-       ret = pcmcia_parse_tuple(&tuple, &parse);
-
-       if (ret != 0) {
-               cs_error(link, ParseTuple, ret);
-               goto exit0;
-       }
-
-       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-       link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-       link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
-       link->io.IOAddrLines = 16;
-
-       link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1;
+       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+       p_dev->io.BasePort1 = cfg->io.win[0].base;
+       p_dev->io.NumPorts1 = cfg->io.win[0].len;
+       p_dev->io.IOAddrLines = 16;
 
        /* 0x40 causes it to generate level mode interrupts. */
        /* 0x04 enables IREQ pin. */
-       cor_value = parse.cftable_entry.index | 0x44;
-       link->conf.ConfigIndex = cor_value;
+       p_dev->conf.ConfigIndex = cfg->index | 0x44;
+       ret = pcmcia_request_io(p_dev, &p_dev->io);
+       if (ret)
+               return ret;
 
-       /* IRQ and I/O settings */
-       tuple.DesiredTuple = CISTPL_CONFIG;
+       io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1,
+                               IPWIRELESS_PCCARD_NAME);
 
-       ret = pcmcia_get_first_tuple(link, &tuple);
+       if (cfg->mem.nwin == 0)
+               return 0;
 
-       if (ret != 0) {
-               cs_error(link, GetFirstTuple, ret);
-               goto exit0;
-       }
+       ipw->request_common_memory.Attributes =
+               WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+       ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
+       ipw->request_common_memory.Size = cfg->mem.win[0].len;
+       if (ipw->request_common_memory.Size < 0x1000)
+               ipw->request_common_memory.Size = 0x1000;
+       ipw->request_common_memory.AccessSpeed = 0;
 
-       ret = pcmcia_get_tuple_data(link, &tuple);
-
-       if (ret != 0) {
-               cs_error(link, GetTupleData, ret);
-               goto exit0;
-       }
+       ret = pcmcia_request_window(p_dev, &ipw->request_common_memory,
+                               &ipw->handle_common_memory);
 
-       ret = pcmcia_parse_tuple(&tuple, &parse);
+       if (ret != 0)
+               goto exit1;
 
-       if (ret != 0) {
-               cs_error(link, GetTupleData, ret);
-               goto exit0;
-       }
-       link->conf.Attributes = CONF_ENABLE_IRQ;
-       link->conf.ConfigBase = parse.config.base;
-       link->conf.Present = parse.config.rmask[0];
-       link->conf.IntType = INT_MEMORY_AND_IO;
+       memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr;
+       memreq_common_memory.Page = 0;
 
-       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
-       link->irq.Handler = ipwireless_interrupt;
-       link->irq.Instance = ipw->hardware;
+       ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
+                               &memreq_common_memory);
 
-       ret = pcmcia_request_io(link, &link->io);
+       if (ret != 0)
+               goto exit2;
 
-       if (ret != 0) {
-               cs_error(link, RequestIO, ret);
-               goto exit0;
-       }
+       ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
 
-       request_region(link->io.BasePort1, link->io.NumPorts1,
+       ipw->common_memory = ioremap(ipw->request_common_memory.Base,
+                               ipw->request_common_memory.Size);
+       request_mem_region(ipw->request_common_memory.Base,
+                       ipw->request_common_memory.Size,
                        IPWIRELESS_PCCARD_NAME);
 
-       /* memory settings */
-
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
-       ret = pcmcia_get_first_tuple(link, &tuple);
-
-       if (ret != 0) {
-               cs_error(link, GetFirstTuple, ret);
-               goto exit1;
-       }
-
-       ret = pcmcia_get_tuple_data(link, &tuple);
+       ipw->request_attr_memory.Attributes =
+               WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
+       ipw->request_attr_memory.Base = 0;
+       ipw->request_attr_memory.Size = 0;      /* this used to be 0x1000 */
+       ipw->request_attr_memory.AccessSpeed = 0;
 
-       if (ret != 0) {
-               cs_error(link, GetTupleData, ret);
-               goto exit1;
-       }
-
-       ret = pcmcia_parse_tuple(&tuple, &parse);
-
-       if (ret != 0) {
-               cs_error(link, ParseTuple, ret);
-               goto exit1;
-       }
+       ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory,
+                               &ipw->handle_attr_memory);
 
-       if (parse.cftable_entry.mem.nwin > 0) {
-               ipw->request_common_memory.Attributes =
-                       WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-               ipw->request_common_memory.Base =
-                       parse.cftable_entry.mem.win[0].host_addr;
-               ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
-               if (ipw->request_common_memory.Size < 0x1000)
-                       ipw->request_common_memory.Size = 0x1000;
-               ipw->request_common_memory.AccessSpeed = 0;
-
-               ret = pcmcia_request_window(&link, &ipw->request_common_memory,
-                               &ipw->handle_common_memory);
+       if (ret != 0)
+               goto exit2;
 
-               if (ret != 0) {
-                       cs_error(link, RequestWindow, ret);
-                       goto exit1;
-               }
+       memreq_attr_memory.CardOffset = 0;
+       memreq_attr_memory.Page = 0;
 
-               memreq_common_memory.CardOffset =
-                       parse.cftable_entry.mem.win[0].card_addr;
-               memreq_common_memory.Page = 0;
+       ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory,
+                               &memreq_attr_memory);
 
-               ret = pcmcia_map_mem_page(ipw->handle_common_memory,
-                               &memreq_common_memory);
+       if (ret != 0)
+               goto exit3;
 
-               if (ret != 0) {
-                       cs_error(link, MapMemPage, ret);
-                       goto exit1;
-               }
+       ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
+                               ipw->request_attr_memory.Size);
+       request_mem_region(ipw->request_attr_memory.Base,
+                       ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME);
 
-               ipw->is_v2_card =
-                       parse.cftable_entry.mem.win[0].len == 0x100;
+       return 0;
 
-               ipw->common_memory = ioremap(ipw->request_common_memory.Base,
+exit3:
+       pcmcia_release_window(p_dev, ipw->handle_attr_memory);
+exit2:
+       if (ipw->common_memory) {
+               release_mem_region(ipw->request_common_memory.Base,
                                ipw->request_common_memory.Size);
-               request_mem_region(ipw->request_common_memory.Base,
-                               ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME);
-
-               ipw->request_attr_memory.Attributes =
-                       WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
-               ipw->request_attr_memory.Base = 0;
-               ipw->request_attr_memory.Size = 0;      /* this used to be 0x1000 */
-               ipw->request_attr_memory.AccessSpeed = 0;
-
-               ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
-                               &ipw->handle_attr_memory);
+               iounmap(ipw->common_memory);
+               pcmcia_release_window(p_dev, ipw->handle_common_memory);
+       } else
+               pcmcia_release_window(p_dev, ipw->handle_common_memory);
+exit1:
+       release_resource(io_resource);
+       pcmcia_disable_device(p_dev);
+       return -1;
+}
 
-               if (ret != 0) {
-                       cs_error(link, RequestWindow, ret);
-                       goto exit2;
-               }
+static int config_ipwireless(struct ipw_dev *ipw)
+{
+       struct pcmcia_device *link = ipw->link;
+       int ret = 0;
 
-               memreq_attr_memory.CardOffset = 0;
-               memreq_attr_memory.Page = 0;
+       ipw->is_v2_card = 0;
 
-               ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
-                               &memreq_attr_memory);
+       ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
+       if (ret != 0)
+               return ret;
 
-               if (ret != 0) {
-                       cs_error(link, MapMemPage, ret);
-                       goto exit2;
-               }
+       link->conf.Attributes = CONF_ENABLE_IRQ;
+       link->conf.IntType = INT_MEMORY_AND_IO;
 
-               ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
-                               ipw->request_attr_memory.Size);
-               request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size,
-                               IPWIRELESS_PCCARD_NAME);
-       }
+       link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
+       link->irq.Handler = ipwireless_interrupt;
 
        INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
@@ -291,10 +207,8 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ret = pcmcia_request_irq(link, &link->irq);
 
-       if (ret != 0) {
-               cs_error(link, RequestIRQ, ret);
-               goto exit3;
-       }
+       if (ret != 0)
+               goto exit;
 
        printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
                        ipw->is_v2_card ? "V2/V3" : "V1");
@@ -316,12 +230,12 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ipw->network = ipwireless_network_create(ipw->hardware);
        if (!ipw->network)
-               goto exit3;
+               goto exit;
 
        ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,
                        ipw->nodes);
        if (!ipw->tty)
-               goto exit3;
+               goto exit;
 
        ipwireless_init_hardware_v2_v3(ipw->hardware);
 
@@ -331,35 +245,27 @@ static int config_ipwireless(struct ipw_dev *ipw)
         */
        ret = pcmcia_request_configuration(link, &link->conf);
 
-       if (ret != 0) {
-               cs_error(link, RequestConfiguration, ret);
-               goto exit4;
-       }
+       if (ret != 0)
+               goto exit;
 
        link->dev_node = &ipw->nodes[0];
 
        return 0;
 
-exit4:
-       pcmcia_disable_device(link);
-exit3:
+exit:
        if (ipw->attr_memory) {
                release_mem_region(ipw->request_attr_memory.Base,
                                ipw->request_attr_memory.Size);
                iounmap(ipw->attr_memory);
-               pcmcia_release_window(ipw->handle_attr_memory);
-               pcmcia_disable_device(link);
+               pcmcia_release_window(link, ipw->handle_attr_memory);
        }
-exit2:
        if (ipw->common_memory) {
                release_mem_region(ipw->request_common_memory.Base,
                                ipw->request_common_memory.Size);
                iounmap(ipw->common_memory);
-               pcmcia_release_window(ipw->handle_common_memory);
+               pcmcia_release_window(link, ipw->handle_common_memory);
        }
-exit1:
        pcmcia_disable_device(link);
-exit0:
        return -1;
 }
 
@@ -378,9 +284,9 @@ static void release_ipwireless(struct ipw_dev *ipw)
                iounmap(ipw->attr_memory);
        }
        if (ipw->common_memory)
-               pcmcia_release_window(ipw->handle_common_memory);
+               pcmcia_release_window(ipw->link, ipw->handle_common_memory);
        if (ipw->attr_memory)
-               pcmcia_release_window(ipw->handle_attr_memory);
+               pcmcia_release_window(ipw->link, ipw->handle_attr_memory);
 
        /* Break the link with Card Services */
        pcmcia_disable_device(ipw->link);
@@ -406,7 +312,6 @@ static int ipwireless_attach(struct pcmcia_device *link)
 
        ipw->link = link;
        link->priv = ipw;
-       link->irq.Instance = ipw;
 
        /* Link this device into our device list. */
        link->dev_node = &ipw->nodes[0];
@@ -421,7 +326,6 @@ static int ipwireless_attach(struct pcmcia_device *link)
        ret = config_ipwireless(ipw);
 
        if (ret != 0) {
-               cs_error(link, RegisterClient, ret);
                ipwireless_detach(link);
                return ret;
        }
index caf6e4d..c31a0d9 100644 (file)
@@ -554,7 +554,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
-    link->irq.IRQInfo1   = IRQ_LEVEL_ID;
     link->irq.Handler = NULL;
 
     link->conf.Attributes = 0;
@@ -572,69 +571,51 @@ static int mgslpc_probe(struct pcmcia_device *link)
 /* Card has been inserted.
  */
 
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
+                         cistpl_cftable_entry_t *cfg,
+                         cistpl_cftable_entry_t *dflt,
+                         unsigned int vcc,
+                         void *priv_data)
+{
+       if (cfg->io.nwin > 0) {
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               if (!(cfg->io.flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(cfg->io.flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+               p_dev->io.BasePort1 = cfg->io.win[0].base;
+               p_dev->io.NumPorts1 = cfg->io.win[0].len;
+               return pcmcia_request_io(p_dev, &p_dev->io);
+       }
+       return -ENODEV;
+}
 
 static int mgslpc_config(struct pcmcia_device *link)
 {
     MGSLPC_INFO *info = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
-    int last_fn, last_ret;
-    u_char buf[64];
-    cistpl_cftable_entry_t dflt = { 0 };
-    cistpl_cftable_entry_t *cfg;
+    int ret;
 
     if (debug_level >= DEBUG_LEVEL_INFO)
            printk("mgslpc_config(0x%p)\n", link);
 
-    tuple.Attributes = 0;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
-
-    /* get CIS configuration entry */
-
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-
-    cfg = &(parse.cftable_entry);
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
-
-    if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-    if (cfg->index == 0)
-           goto cs_failed;
-
-    link->conf.ConfigIndex = cfg->index;
-    link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-    /* IO window settings */
-    link->io.NumPorts1 = 0;
-    if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-           cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-           link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-           if (!(io->flags & CISTPL_IO_8BIT))
-                   link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-           if (!(io->flags & CISTPL_IO_16BIT))
-                   link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-           link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-           link->io.BasePort1 = io->win[0].base;
-           link->io.NumPorts1 = io->win[0].len;
-           CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
-    }
+    ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
+    if (ret != 0)
+           goto failed;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 8;
     link->conf.Present = PRESENT_OPTION;
 
-    link->irq.Attributes |= IRQ_HANDLE_PRESENT;
     link->irq.Handler     = mgslpc_isr;
-    link->irq.Instance    = info;
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+    ret = pcmcia_request_irq(link, &link->irq);
+    if (ret)
+           goto failed;
+    ret = pcmcia_request_configuration(link, &link->conf);
+    if (ret)
+           goto failed;
 
     info->io_base = link->io.BasePort1;
     info->irq_level = link->irq.AssignedIRQ;
@@ -654,8 +635,7 @@ static int mgslpc_config(struct pcmcia_device *link)
     printk("\n");
     return 0;
 
-cs_failed:
-    cs_error(link, last_fn, last_ret);
+failed:
     mgslpc_release((u_long)link);
     return -ENODEV;
 }
index 47c2d27..f06bb37 100644 (file)
@@ -31,7 +31,7 @@
 
 enum tpm_const {
        TPM_MINOR = 224,        /* officially assigned */
-       TPM_BUFSIZE = 2048,
+       TPM_BUFSIZE = 4096,
        TPM_NUM_DEVICES = 256,
 };
 
index 0b73e4e..2405f17 100644 (file)
@@ -257,6 +257,10 @@ out:
        return size;
 }
 
+static int itpm;
+module_param(itpm, bool, 0444);
+MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
+
 /*
  * If interrupts are used (signaled by an irq set in the vendor structure)
  * tpm.c can skip polling for the data to be available as the interrupt is
@@ -293,7 +297,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
                wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
                              &chip->vendor.int_queue);
                status = tpm_tis_status(chip);
-               if ((status & TPM_STS_DATA_EXPECT) == 0) {
+               if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
                        rc = -EIO;
                        goto out_err;
                }
@@ -467,6 +471,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
                 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
                 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
+       if (itpm)
+               dev_info(dev, "Intel iTPM workaround enabled\n");
+
+
        /* Figure out the capabilities */
        intfcaps =
            ioread32(chip->vendor.iobase +
@@ -629,6 +637,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
        {"", 0},                /* User Specified */
        {"", 0}                 /* Terminator */
 };
+MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
 
 static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
 {
index 5711ce5..4baf3d7 100644 (file)
@@ -144,13 +144,6 @@ static int lnw_irq_type(unsigned irq, unsigned type)
 
 static void lnw_irq_unmask(unsigned irq)
 {
-       struct lnw_gpio *lnw = get_irq_chip_data(irq);
-       u32 gpio = irq - lnw->irq_base;
-       u8 reg = gpio / 32;
-       void __iomem *gedr;
-
-       gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]);
-       writel(BIT(gpio % 32), gedr);
 };
 
 static void lnw_irq_mask(unsigned irq)
@@ -183,13 +176,11 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
                gedr_v = readl(gedr);
                if (!gedr_v)
                        continue;
-               for (gpio = reg*32; gpio < reg*32+32; gpio++) {
-                       gedr_v = readl(gedr);
+               for (gpio = reg*32; gpio < reg*32+32; gpio++)
                        if (gedr_v & BIT(gpio % 32)) {
                                pr_debug("pin %d triggered\n", gpio);
                                generic_handle_irq(lnw->irq_base + gpio);
                        }
-               }
                /* clear the edge detect status bit */
                writel(gedr_v, gedr);
        }
index 063b933..dd63963 100644 (file)
@@ -60,15 +60,6 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
 MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
 MODULE_LICENSE("Dual MPL/GPL");
 
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
-
-#ifdef CONFIG_PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, 0);
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-#else
-#define DEBUG(n, args...)
-#endif
-
 /*====================================================================*/
 
 typedef struct ide_info_t {
@@ -98,7 +89,7 @@ static int ide_probe(struct pcmcia_device *link)
 {
     ide_info_t *info;
 
-    DEBUG(0, "ide_attach()\n");
+    dev_dbg(&link->dev, "ide_attach()\n");
 
     /* Create new ide device */
     info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -112,7 +103,6 @@ static int ide_probe(struct pcmcia_device *link)
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->io.IOAddrLines = 3;
     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -134,7 +124,7 @@ static void ide_detach(struct pcmcia_device *link)
     ide_hwif_t *hwif = info->host->ports[0];
     unsigned long data_addr, ctl_addr;
 
-    DEBUG(0, "ide_detach(0x%p)\n", link);
+    dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
 
     data_addr = hwif->io_ports.data_addr;
     ctl_addr  = hwif->io_ports.ctl_addr;
@@ -217,9 +207,6 @@ out_release:
 
 ======================================================================*/
 
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-
 struct pcmcia_config_check {
        unsigned long ctl_base;
        int skip_vcc;
@@ -282,11 +269,11 @@ static int ide_config(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
     struct pcmcia_config_check *stk = NULL;
-    int last_ret = 0, last_fn = 0, is_kme = 0;
+    int ret = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
     struct ide_host *host;
 
-    DEBUG(0, "ide_config(0x%p)\n", link);
+    dev_dbg(&link->dev, "ide_config(0x%p)\n", link);
 
     is_kme = ((link->manf_id == MANFID_KME) &&
              ((link->card_id == PRODID_KME_KXLC005_A) ||
@@ -306,8 +293,12 @@ static int ide_config(struct pcmcia_device *link)
     io_base = link->io.BasePort1;
     ctl_base = stk->ctl_base;
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+    ret = pcmcia_request_irq(link, &link->irq);
+    if (ret)
+           goto failed;
+    ret = pcmcia_request_configuration(link, &link->conf);
+    if (ret)
+           goto failed;
 
     /* disable drive interrupts during IDE probe */
     outb(0x02, ctl_base);
@@ -342,8 +333,6 @@ err_mem:
     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
     goto failed;
 
-cs_failed:
-    cs_error(link, last_fn, last_ret);
 failed:
     kfree(stk);
     ide_release(link);
@@ -363,7 +352,7 @@ static void ide_release(struct pcmcia_device *link)
     ide_info_t *info = link->priv;
     struct ide_host *host = info->host;
 
-    DEBUG(0, "ide_release(0x%p)\n", link);
+    dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
 
     if (info->ndev)
        /* FIXME: if this fails we need to queue the cleanup somehow
index a537925..2bcf1ac 100644 (file)
@@ -447,6 +447,27 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
                },
        },
+       {
+               .ident = "Dell Vostro 1320",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),
+               },
+       },
+       {
+               .ident = "Dell Vostro 1520",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),
+               },
+       },
+       {
+               .ident = "Dell Vostro 1720",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
+               },
+       },
        { }
 };
 
index c725655..5a6ae64 100644 (file)
@@ -111,8 +111,6 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
     p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 
-    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
-
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
     p_dev->conf.IntType = INT_MEMORY_AND_IO;
@@ -198,7 +196,6 @@ static int avmcs_config(struct pcmcia_device *link)
         */
        i = pcmcia_request_irq(link, &link->irq);
        if (i != 0) {
-           cs_error(link, RequestIRQ, i);
            /* undo */
            pcmcia_disable_device(link);
            break;
@@ -209,7 +206,6 @@ static int avmcs_config(struct pcmcia_device *link)
          */
        i = pcmcia_request_configuration(link, &link->conf);
        if (i != 0) {
-           cs_error(link, RequestConfiguration, i);
            pcmcia_disable_device(link);
            break;
        }
index 23560c8..f9bdff3 100644 (file)
@@ -30,22 +30,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA car
 MODULE_AUTHOR("Carsten Paeth");
 MODULE_LICENSE("GPL");
 
-/*
-   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
-   you do not define PCMCIA_DEBUG at all, all the debug code will be
-   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
-   be present but disabled -- but it can then be enabled for specific
-   modules at load time with a 'pc_debug=#' option to insmod.
-*/
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-module_param(pc_debug, int, 0);
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
-static char *version =
-"avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)";
-#else
-#define DEBUG(n, args...)
-#endif
 
 /*====================================================================*/
 
@@ -119,7 +103,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)
 {
     local_info_t *local;
 
-    DEBUG(0, "avma1cs_attach()\n");
+    dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
 
     /* Allocate space for private device-specific data */
     local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
@@ -139,8 +123,6 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)
     p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 
-    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
-
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
     p_dev->conf.IntType = INT_MEMORY_AND_IO;
@@ -161,7 +143,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)
 
 static void avma1cs_detach(struct pcmcia_device *link)
 {
-       DEBUG(0, "avma1cs_detach(0x%p)\n", link);
+       dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
        avma1cs_release(link);
        kfree(link->priv);
 } /* avma1cs_detach */
@@ -203,7 +185,7 @@ static int avma1cs_config(struct pcmcia_device *link)
 
     dev = link->priv;
 
-    DEBUG(0, "avma1cs_config(0x%p)\n", link);
+    dev_dbg(&link->dev, "avma1cs_config(0x%p)\n", link);
 
     devname[0] = 0;
     if (link->prod_id[1])
@@ -218,7 +200,6 @@ static int avma1cs_config(struct pcmcia_device *link)
         */
        i = pcmcia_request_irq(link, &link->irq);
        if (i != 0) {
-           cs_error(link, RequestIRQ, i);
            /* undo */
            pcmcia_disable_device(link);
            break;
@@ -229,7 +210,6 @@ static int avma1cs_config(struct pcmcia_device *link)
         */
        i = pcmcia_request_configuration(link, &link->conf);
        if (i != 0) {
-           cs_error(link, RequestConfiguration, i);
            pcmcia_disable_device(link);
            break;
        }
@@ -281,7 +261,7 @@ static void avma1cs_release(struct pcmcia_device *link)
 {
        local_info_t *local = link->priv;
 
-       DEBUG(0, "avma1cs_release(0x%p)\n", link);
+       dev_dbg(&link->dev, "avma1cs_release(0x%p)\n", link);
 
        /* now unregister function with hisax */
        HiSax_closecard(local->node.minor);
index f4d0fe2..a2f709f 100644 (file)
@@ -57,23 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards");
 MODULE_AUTHOR("Klaus Lichtenwalder");
 MODULE_LICENSE("Dual MPL/GPL");
 
-/*
-   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
-   you do not define PCMCIA_DEBUG at all, all the debug code will be
-   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
-   be present but disabled -- but it can then be enabled for specific
-   modules at load time with a 'pc_debug=#' option to insmod.
-*/
-
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-module_param(pc_debug, int, 0);
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
-static char *version =
-"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)";
-#else
-#define DEBUG(n, args...)
-#endif
 
 /*====================================================================*/<