]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Automatic merge of 'misc-fixes' branch from
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Sat, 4 Jun 2005 15:18:39 +0000 (08:18 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sat, 4 Jun 2005 15:18:39 +0000 (08:18 -0700)
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

233 files changed:
Documentation/DocBook/libata.tmpl
Documentation/cpu-freq/cpufreq-stats.txt [new file with mode: 0644]
MAINTAINERS
arch/h8300/kernel/process.c
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/Makefile
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/sc520_freq.c [new file with mode: 0644]
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
arch/i386/kernel/cpu/intel_cacheinfo.c
arch/i386/kernel/setup.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/timers/common.c
arch/i386/kernel/timers/timer_tsc.c
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/mca.c
arch/ia64/kernel/minstate.h
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/sys_ia64.c
arch/ia64/sn/kernel/setup.c
arch/m68knommu/kernel/process.c
arch/ppc/Kconfig
arch/ppc/boot/images/Makefile
arch/ppc/configs/mpc8555_cds_defconfig
arch/ppc/kernel/head_fsl_booke.S
arch/ppc/kernel/traps.c
arch/ppc/platforms/83xx/mpc834x_sys.c
arch/ppc/platforms/83xx/mpc834x_sys.h
arch/ppc/platforms/85xx/mpc8540_ads.c
arch/ppc/platforms/85xx/mpc85xx_cds_common.c
arch/ppc/platforms/85xx/mpc85xx_cds_common.h
arch/ppc/platforms/85xx/sbc8560.c
arch/ppc/platforms/pmac_cpufreq.c
arch/ppc/platforms/pq2ads.h
arch/ppc/syslib/Makefile
arch/ppc/syslib/m8260_pci.c [deleted file]
arch/ppc/syslib/m8260_pci.h [deleted file]
arch/ppc/syslib/m8260_pci_erratum9.c
arch/ppc/syslib/m8260_setup.c
arch/ppc/syslib/m82xx_pci.c [new file with mode: 0644]
arch/ppc/syslib/m82xx_pci.h [new file with mode: 0644]
arch/ppc/syslib/open_pic.c
arch/ppc/syslib/ppc83xx_setup.c
arch/ppc/syslib/ppc85xx_setup.c
arch/ppc/syslib/prom_init.c
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/head.S
arch/ppc64/kernel/iSeries_setup.c
arch/ppc64/kernel/idle.c
arch/ppc64/kernel/pSeries_reconfig.c
arch/ppc64/kernel/process.c
arch/ppc64/kernel/prom_init.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/smp.c
arch/ppc64/kernel/sysfs.c
arch/ppc64/kernel/time.c
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/pci_psycho.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/sbus.c
arch/um/Kconfig.debug
arch/um/drivers/random.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/drivers/ubd_kern.c
arch/um/include/2_5compat.h [deleted file]
arch/um/include/sysrq.h
arch/um/kernel/exec_kern.c
arch/um/kernel/initrd_kern.c [deleted file]
arch/um/kernel/initrd_user.c [deleted file]
arch/um/kernel/main.c
arch/um/kernel/process_kern.c
arch/um/kernel/ptrace.c
arch/um/kernel/sysrq.c
arch/um/kernel/trap_kern.c
arch/um/kernel/tt/process_kern.c
arch/um/kernel/um_arch.c
arch/um/sys-i386/sysrq.c
arch/um/sys-ppc/sysrq.c
arch/um/sys-x86_64/syscalls.c
arch/um/sys-x86_64/sysrq.c
arch/x86_64/Kconfig
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/signal.c
arch/x86_64/kernel/time.c
drivers/atm/Makefile
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/nicstar.c
drivers/atm/zatm.c
drivers/block/ub.c
drivers/cdrom/viocd.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Makefile
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c [new file with mode: 0644]
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_stats.c
drivers/firmware/pcdp.c
drivers/i2c/busses/i2c-ali1563.c
drivers/ide/ide-cd.c
drivers/ide/pci/amd74xx.c
drivers/input/gameport/Kconfig
drivers/input/joydev.c
drivers/input/keyboard/atkbd.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mousedev.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/touchscreen/gunze.c
drivers/macintosh/via-pmu.c
drivers/media/dvb/bt8xx/dst.c
drivers/net/hamradio/baycom_epp.c
drivers/net/shaper.c
drivers/net/tg3.c
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/shpchprm_acpi.c
drivers/scsi/ahci.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/sata_nv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_qstor.c
drivers/scsi/sata_sil.c
drivers/scsi/sata_sis.c
drivers/scsi/sata_svw.c
drivers/scsi/sata_sx4.c
drivers/scsi/sata_uli.c
drivers/scsi/sata_via.c
drivers/scsi/sata_vsc.c
drivers/scsi/scsi_scan.c
drivers/usb/core/sysfs.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/sl811-hcd.c
drivers/usb/host/sl811_cs.c [new file with mode: 0644]
drivers/usb/input/hid-core.c
drivers/usb/media/pwc/ChangeLog [deleted file]
drivers/usb/media/pwc/pwc-ctrl.c
drivers/usb/media/pwc/pwc-uncompress.c
drivers/usb/net/usbnet.c
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/cp2101.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/option.c [new file with mode: 0644]
drivers/usb/serial/usb-serial.c
drivers/usb/storage/unusual_devs.h
drivers/video/intelfb/intelfbdrv.c
fs/cifs/README
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/hostfs/hostfs_kern.c
fs/jbd/checkpoint.c
fs/proc/proc_devtree.c
fs/udf/udftime.c
include/asm-i386/timer.h
include/asm-ia64/perfmon.h
include/asm-ia64/sn/sn_sal.h
include/asm-ppc/cpm2.h
include/asm-ppc/m8260_pci.h
include/asm-ppc/mpc8260.h
include/asm-ppc64/processor.h
include/asm-ppc64/prom.h
include/asm-ppc64/thread_info.h
include/asm-sh/thread_info.h
include/asm-sh64/thread_info.h
include/asm-sparc64/iommu.h
include/asm-sparc64/pbm.h
include/asm-um/page.h
include/asm-um/pgtable.h
include/asm-um/thread_info.h
include/linux/cpufreq.h
include/linux/etherdevice.h
include/linux/ethtool.h
include/linux/gameport.h
include/linux/hardirq.h
include/linux/if_shaper.h
include/linux/inetdevice.h
include/linux/libata.h
include/linux/netdevice.h
include/linux/notifier.h
include/linux/pci_ids.h
include/linux/sysctl.h
include/linux/usb.h
include/net/route.h
init/Kconfig
kernel/irq/handle.c
kernel/module.c
lib/Kconfig.debug
net/bridge/br_device.c
net/bridge/br_if.c
net/bridge/br_input.c
net/bridge/br_notify.c
net/bridge/br_private.h
net/bridge/br_stp_bpdu.c
net/core/dev.c
net/core/ethtool.c
net/core/net-sysfs.c
net/ipv4/devinet.c
net/ipv4/esp4.c
net/ipv4/ipvs/Makefile
net/ipv4/ipvs/ip_vs_proto.c
net/ipv4/ipvs/ip_vs_proto_icmp.c [deleted file]
net/ipv4/multipath_drr.c
net/ipv4/multipath_rr.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/udp.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ipv6_syms.c
net/sched/sch_dsmark.c
sound/oss/Kconfig
sound/ppc/pmac.c

index cf2fce7707da202e7f408f40929dde7255cf742e..6df1dfd18b651fce1224fe0e127cf7e777981d34 100644 (file)
@@ -14,7 +14,7 @@
   </authorgroup>
 
   <copyright>
-   <year>2003</year>
+   <year>2003-2005</year>
    <holder>Jeff Garzik</holder>
   </copyright>
 
 
 <toc></toc>
 
-  <chapter id="libataThanks">
-     <title>Thanks</title>
+  <chapter id="libataIntroduction">
+     <title>Introduction</title>
   <para>
-  The bulk of the ATA knowledge comes thanks to long conversations with
-  Andre Hedrick (www.linux-ide.org).
+  libATA is a library used inside the Linux kernel to support ATA host
+  controllers and devices.  libATA provides an ATA driver API, class
+  transports for ATA and ATAPI devices, and SCSI&lt;-&gt;ATA translation
+  for ATA devices according to the T10 SAT specification.
   </para>
   <para>
-  Thanks to Alan Cox for pointing out similarities 
-  between SATA and SCSI, and in general for motivation to hack on
-  libata.
-  </para>
-  <para>
-  libata's device detection
-  method, ata_pio_devchk, and in general all the early probing was
-  based on extensive study of Hale Landis's probe/reset code in his
-  ATADRVR driver (www.ata-atapi.com).
+  This Guide documents the libATA driver API, library functions, library
+  internals, and a couple sample ATA low-level drivers.
   </para>
   </chapter>
 
   <chapter id="libataDriverApi">
      <title>libata Driver API</title>
+     <para>
+     struct ata_port_operations is defined for every low-level libata
+     hardware driver, and it controls how the low-level driver
+     interfaces with the ATA and SCSI layers.
+     </para>
+     <para>
+     FIS-based drivers will hook into the system with ->qc_prep() and
+     ->qc_issue() high-level hooks.  Hardware which behaves in a manner
+     similar to PCI IDE hardware may utilize several generic helpers,
+     defining at a bare minimum the bus I/O addresses of the ATA shadow
+     register blocks.
+     </para>
      <sect1>
         <title>struct ata_port_operations</title>
 
+       <sect2><title>Disable ATA port</title>
        <programlisting>
 void (*port_disable) (struct ata_port *);
        </programlisting>
@@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
        unplug).
        </para>
 
+       </sect2>
+
+       <sect2><title>Post-IDENTIFY device configuration</title>
        <programlisting>
 void (*dev_config) (struct ata_port *, struct ata_device *);
        </programlisting>
@@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
        issue of SET FEATURES - XFER MODE, and prior to operation.
        </para>
 
+       </sect2>
+
+       <sect2><title>Set PIO/DMA mode</title>
        <programlisting>
 void (*set_piomode) (struct ata_port *, struct ata_device *);
 void (*set_dmamode) (struct ata_port *, struct ata_device *);
@@ -108,6 +122,9 @@ void (*post_set_mode) (struct ata_port *ap);
        ->set_dma_mode() is only called if DMA is possible.
        </para>
 
+       </sect2>
+
+       <sect2><title>Taskfile read/write</title>
        <programlisting>
 void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
 void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -120,6 +137,9 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
        taskfile register values.
        </para>
 
+       </sect2>
+
+       <sect2><title>ATA command execute</title>
        <programlisting>
 void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
        </programlisting>
@@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
        ->tf_load(), to be initiated in hardware.
        </para>
 
+       </sect2>
+
+       <sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
+       <programlisting>
+int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+       </programlisting>
+
+       <para>
+Allow low-level driver to filter ATA PACKET commands, returning a status
+indicating whether or not it is OK to use DMA for the supplied PACKET
+command.
+       </para>
+
+       </sect2>
+
+       <sect2><title>Read specific ATA shadow registers</title>
        <programlisting>
 u8   (*check_status)(struct ata_port *ap);
-void (*dev_select)(struct ata_port *ap, unsigned int device);
+u8   (*check_altstatus)(struct ata_port *ap);
+u8   (*check_err)(struct ata_port *ap);
        </programlisting>
 
        <para>
-       Reads the Status ATA shadow register from hardware.  On some
-       hardware, this has the side effect of clearing the interrupt
-       condition.
+       Reads the Status/AltStatus/Error ATA shadow register from
+       hardware.  On some hardware, reading the Status register has
+       the side effect of clearing the interrupt condition.
        </para>
 
+       </sect2>
+
+       <sect2><title>Select ATA device on bus</title>
        <programlisting>
 void (*dev_select)(struct ata_port *ap, unsigned int device);
        </programlisting>
@@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
        <para>
        Issues the low-level hardware command(s) that causes one of N
        hardware devices to be considered 'selected' (active and
-       available for use) on the ATA bus.
+       available for use) on the ATA bus.  This generally has no
+meaning on FIS-based devices.
        </para>
 
+       </sect2>
+
+       <sect2><title>Reset ATA bus</title>
        <programlisting>
 void (*phy_reset) (struct ata_port *ap);
        </programlisting>
@@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
        functions ata_bus_reset() or sata_phy_reset() for this hook.
        </para>
 
+       </sect2>
+
+       <sect2><title>Control PCI IDE BMDMA engine</title>
        <programlisting>
 void (*bmdma_setup) (struct ata_queued_cmd *qc);
 void (*bmdma_start) (struct ata_queued_cmd *qc);
+void (*bmdma_stop) (struct ata_port *ap);
+u8   (*bmdma_status) (struct ata_port *ap);
        </programlisting>
 
        <para>
-       When setting up an IDE BMDMA transaction, these hooks arm
-       (->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
-       engine.
+When setting up an IDE BMDMA transaction, these hooks arm
+(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
+the hardware's DMA engine.  ->bmdma_status is used to read the standard
+PCI IDE DMA Status register.
        </para>
 
+       <para>
+These hooks are typically either no-ops, or simply not implemented, in
+FIS-based drivers.
+       </para>
+
+       </sect2>
+
+       <sect2><title>High-level taskfile hooks</title>
        <programlisting>
 void (*qc_prep) (struct ata_queued_cmd *qc);
 int (*qc_issue) (struct ata_queued_cmd *qc);
@@ -190,20 +248,26 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
        ->qc_issue is used to make a command active, once the hardware
        and S/G tables have been prepared.  IDE BMDMA drivers use the
        helper function ata_qc_issue_prot() for taskfile protocol-based
-       dispatch.  More advanced drivers roll their own ->qc_issue
-       implementation, using this as the "issue new ATA command to
-       hardware" hook.
+       dispatch.  More advanced drivers implement their own ->qc_issue.
        </para>
 
+       </sect2>
+
+       <sect2><title>Timeout (error) handling</title>
        <programlisting>
 void (*eng_timeout) (struct ata_port *ap);
        </programlisting>
 
        <para>
-       This is a high level error handling function, called from the
-       error handling thread, when a command times out.
+This is a high level error handling function, called from the
+error handling thread, when a command times out.  Most newer
+hardware will implement its own error handling code here.  IDE BMDMA
+drivers may use the helper function ata_eng_timeout().
        </para>
 
+       </sect2>
+
+       <sect2><title>Hardware interrupt handling</title>
        <programlisting>
 irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
 void (*irq_clear) (struct ata_port *);
@@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
        is quiet.
        </para>
 
+       </sect2>
+
+       <sect2><title>SATA phy read/write</title>
        <programlisting>
 u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
 void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -227,6 +294,9 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
        if ->phy_reset hook called the sata_phy_reset() helper function.
        </para>
 
+       </sect2>
+
+       <sect2><title>Init and shutdown</title>
        <programlisting>
 int (*port_start) (struct ata_port *ap);
 void (*port_stop) (struct ata_port *ap);
@@ -240,15 +310,17 @@ void (*host_stop) (struct ata_host_set *host_set);
        tasks.  
        </para>
        <para>
-       ->host_stop() is called when the rmmod or hot unplug process
-       begins.  The hook must stop all hardware interrupts, DMA
-       engines, etc.
-       </para>
-       <para>
        ->port_stop() is called after ->host_stop().  It's sole function
        is to release DMA/memory resources, now that they are no longer
        actively being used.
        </para>
+       <para>
+       ->host_stop() is called after all ->port_stop() calls
+have completed.  The hook must finalize hardware shutdown, release DMA
+and other resources, etc.
+       </para>
+
+       </sect2>
 
      </sect1>
   </chapter>
@@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
 !Idrivers/scsi/sata_sil.c
   </chapter>
 
+  <chapter id="libataThanks">
+     <title>Thanks</title>
+  <para>
+  The bulk of the ATA knowledge comes thanks to long conversations with
+  Andre Hedrick (www.linux-ide.org), and long hours pondering the ATA
+  and SCSI specifications.
+  </para>
+  <para>
+  Thanks to Alan Cox for pointing out similarities 
+  between SATA and SCSI, and in general for motivation to hack on
+  libata.
+  </para>
+  <para>
+  libata's device detection
+  method, ata_pio_devchk, and in general all the early probing was
+  based on extensive study of Hale Landis's probe/reset code in his
+  ATADRVR driver (www.ata-atapi.com).
+  </para>
+  </chapter>
+
 </book>
diff --git a/Documentation/cpu-freq/cpufreq-stats.txt b/Documentation/cpu-freq/cpufreq-stats.txt
new file mode 100644 (file)
index 0000000..e2d1e76
--- /dev/null
@@ -0,0 +1,128 @@
+
+     CPU frequency and voltage scaling statictics in the Linux(TM) kernel
+
+
+             L i n u x    c p u f r e q - s t a t s   d r i v e r
+
+                       - information for users -
+
+
+             Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+Contents
+1. Introduction
+2. Statistics Provided (with example)
+3. Configuring cpufreq-stats
+
+
+1. Introduction
+
+cpufreq-stats is a driver that provices CPU frequency statistics for each CPU.
+This statistics is provided in /sysfs as a bunch of read_only interfaces. This
+interface (when configured) will appear in a seperate directory under cpufreq
+in /sysfs (<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU.
+Various statistics will form read_only files under this directory.
+
+This driver is designed to be independent of any particular cpufreq_driver
+that may be running on your CPU. So, it will work with any cpufreq_driver.
+
+
+2. Statistics Provided (with example)
+
+cpufreq stats provides following statistics (explained in detail below).
+-  time_in_state
+-  total_trans
+-  trans_table
+
+All the statistics will be from the time the stats driver has been inserted 
+to the time when a read of a particular statistic is done. Obviously, stats 
+driver will not have any information about the the frequcny transitions before
+the stats driver insertion.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # ls -l
+total 0
+drwxr-xr-x  2 root root    0 May 14 16:06 .
+drwxr-xr-x  3 root root    0 May 14 15:58 ..
+-r--r--r--  1 root root 4096 May 14 16:06 time_in_state
+-r--r--r--  1 root root 4096 May 14 16:06 total_trans
+-r--r--r--  1 root root 4096 May 14 16:06 trans_table
+--------------------------------------------------------------------------------
+
+-  time_in_state
+This gives the amount of time spent in each of the frequencies supported by
+this CPU. The cat output will have "<frequency> <time>" pair in each line, which
+will mean this CPU spent <time> usertime units of time at <frequency>. Output
+will have one line for each of the supported freuencies. usertime units here 
+is 10mS (similar to other time exported in /proc).
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat time_in_state 
+3600000 2089
+3400000 136
+3200000 34
+3000000 67
+2800000 172488
+--------------------------------------------------------------------------------
+
+
+-  total_trans
+This gives the total number of frequency transitions on this CPU. The cat 
+output will have a single count which is the total number of frequency
+transitions.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat total_trans
+20
+--------------------------------------------------------------------------------
+
+-  trans_table
+This will give a fine grained information about all the CPU frequency
+transitions. The cat output here is a two dimensional matrix, where an entry
+<i,j> (row i, column j) represents the count of number of transitions from 
+Freq_i to Freq_j. Freq_i is in descending order with increasing rows and 
+Freq_j is in descending order with increasing columns. The output here also 
+contains the actual freq values for each row and column for better readability.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat trans_table
+   From  :    To
+         :   3600000   3400000   3200000   3000000   2800000 
+  3600000:         0         5         0         0         0 
+  3400000:         4         0         2         0         0 
+  3200000:         0         1         0         2         0 
+  3000000:         0         0         1         0         3 
+  2800000:         0         0         0         2         0 
+--------------------------------------------------------------------------------
+
+
+3. Configuring cpufreq-stats
+
+To configure cpufreq-stats in your kernel
+Config Main Menu
+       Power management options (ACPI, APM)  --->
+               CPU Frequency scaling  --->
+                       [*] CPU Frequency scaling
+                       <*>   CPU frequency translation statistics 
+                       [*]     CPU frequency translation statistics details
+
+
+"CPU Frequency scaling" (CONFIG_CPU_FREQ) should be enabled to configure
+cpufreq-stats.
+
+"CPU frequency translation statistics" (CONFIG_CPU_FREQ_STAT) provides the
+basic statistics which includes time_in_state and total_trans.
+
+"CPU frequency translation statistics details" (CONFIG_CPU_FREQ_STAT_DETAILS)
+provides fine grained cpufreq stats by trans_table. The reason for having a
+seperate config option for trans_table is:
+- trans_table goes against the traditional /sysfs rule of one value per
+  interface. It provides a whole bunch of value in a 2 dimensional matrix
+  form.
+
+Once these two options are enabled and your CPU supports cpufrequency, you
+will be able to see the CPU frequency statistics in /sysfs.
+
+
+
+
index 5b8483334de1eb0e30b83dc825f8867294bc4e0c..65ad8251e4bc51a19acd189f425a346c31218296 100644 (file)
@@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
 W:     http://www.linux-usb.org/SpeedTouch/
 S:     Maintained
 
+ALI1563 I2C DRIVER
+P:     Rudolf Marek
+M:     r.marek@sh.cvut.cz
+L:     sensors@stimpy.netroedge.com
+S:     Maintained
+
 ALPHA PORT
 P:     Richard Henderson
 M:     rth@twiddle.net
@@ -1023,8 +1029,8 @@ W:        http://www.ia64-linux.org/
 S:     Maintained
 
 SN-IA64 (Itanium) SUB-PLATFORM
-P:     Jesse Barnes
-M:     jbarnes@sgi.com
+P:     Greg Edwards
+M:     edwardsg@sgi.com
 L:     linux-altix@sgi.com
 L:     linux-ia64@vger.kernel.org
 W:     http://www.sgi.com/altix
index 134aec1c6d199d259a5207a2c0ea427bc487843a..b5f83e9f04db63eb1013267b65f94a891432e375 100644 (file)
@@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void);
 void default_idle(void)
 {
        while(1) {
-               if (need_resched()) {
+               if (!need_resched()) {
                        local_irq_enable();
                        __asm__("sleep");
                        local_irq_disable();
index f25ffd74235caa330985b4cbaa6d5ece01b78b67..0f1eb507233b701c6bb7b158104e0e5cfd9e4d85 100644 (file)
@@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
          If in doubt, say N.
 
 config ELAN_CPUFREQ
-       tristate "AMD Elan"
+       tristate "AMD Elan SC400 and SC410"
        select CPU_FREQ_TABLE
        depends on X86_ELAN
        ---help---
@@ -38,6 +38,18 @@ config ELAN_CPUFREQ
 
          If in doubt, say N.
 
+config SC520_CPUFREQ
+       tristate "AMD Elan SC520"
+       select CPU_FREQ_TABLE
+       depends on X86_ELAN
+       ---help---
+         This adds the CPUFreq driver for AMD Elan SC520 processor.
+
+         For details, take a look at <file:Documentation/cpu-freq/>.
+
+         If in doubt, say N.
+
+
 config X86_POWERNOW_K6
        tristate "AMD Mobile K6-2/K6-3 PowerNow!"
        select CPU_FREQ_TABLE
index a922e97aeedd5ee7283441a72e613504ef566086..2e894f1c89103f69f51e9c7da8748060d3019790 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7)           += powernow-k7.o
 obj-$(CONFIG_X86_POWERNOW_K8)          += powernow-k8.o
 obj-$(CONFIG_X86_LONGHAUL)             += longhaul.o
 obj-$(CONFIG_ELAN_CPUFREQ)             += elanfreq.o
+obj-$(CONFIG_SC520_CPUFREQ)            += sc520_freq.o
 obj-$(CONFIG_X86_LONGRUN)              += longrun.o  
 obj-$(CONFIG_X86_GX_SUSPMOD)           += gx-suspmod.o
 obj-$(CONFIG_X86_SPEEDSTEP_ICH)                += speedstep-ich.o
index ab0f9f5aac1168075b02b36cf2fdeda1dc23cf2f..04e3563da4fea19e2a7f0c2c0e0053855cda67f1 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/pci.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
@@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
 static void do_powersaver(union msr_longhaul *longhaul,
                        unsigned int clock_ratio_index)
 {
+       struct pci_dev *dev;
+       unsigned long flags;
+       unsigned int tmp_mask;
        int version;
+       int i;
+       u16 pci_cmd;
+       u16 cmd_state[64];
 
        switch (cpu_model) {
        case CPU_EZRA_T:
@@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul,
        longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
        longhaul->bits.EnableSoftBusRatio = 1;
        longhaul->bits.RevisionKey = 0;
-       local_irq_disable();
-       wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+
+       preempt_disable();
+       local_irq_save(flags);
+
+       /*
+        * get current pci bus master state for all devices
+        * and clear bus master bit
+        */
+       dev = NULL;
+       i = 0;
+       do {
+               dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+               if (dev != NULL) {
+                       pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+                       cmd_state[i++] = pci_cmd;
+                       pci_cmd &= ~PCI_COMMAND_MASTER;
+                       pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+               }
+       } while (dev != NULL);
+
+       tmp_mask=inb(0x21);     /* works on C3. save mask. */
+       outb(0xFE,0x21);        /* TMR0 only */
+       outb(0xFF,0x80);        /* delay */
+
        local_irq_enable();
+
+       __hlt();
+       wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
        __hlt();
 
+       local_irq_disable();
+
+       outb(tmp_mask,0x21);    /* restore mask */
+
+       /* restore pci bus master state for all devices */
+       dev = NULL;
+       i = 0;
+       do {
+               dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+               if (dev != NULL) {
+                       pci_cmd = cmd_state[i++];
+                       pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
+               }
+       } while (dev != NULL);
+       local_irq_restore(flags);
+       preempt_enable();
+
+       /* disable bus ratio bit */
        rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
        longhaul->bits.EnableSoftBusRatio = 0;
        longhaul->bits.RevisionKey = version;
-       local_irq_disable();
        wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-       local_irq_enable();
 }
 
 /**
@@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                longhaul_setup_voltagescaling();
 
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+       policy->cpuinfo.transition_latency = 200000;    /* nsec */
        policy->cur = calc_speed(longhaul_get_cpu_mult());
 
        ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
index 913f652623d91f780d0c4a5492f57c6e3afebaee..5c530064eb74bf963a8f43ea4265b96d6042ac65 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/dmi.h>
 
 #include <asm/msr.h>
+#include <asm/timer.h>
 #include <asm/timex.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -586,13 +587,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
 
        rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 
-       /* A K7 with powernow technology is set to max frequency by BIOS */
-       fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
+       /* recalibrate cpu_khz */
+       result = recalibrate_cpu_khz();
+       if (result)
+               return result;
+
+       fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
        if (!fsb) {
                printk(KERN_WARNING PFX "can not determine bus frequency\n");
                return -EINVAL;
        }
-       dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
+       dprintk("FSB: %3dMHz\n", fsb/1000);
 
        if (dmi_check_system(powernow_dmi_table) || acpi_force) {
                printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");
index a65ff7e32e5d09417279a06de1db0f003c77671a..10cc096c0adead9961f48bd79a865f317ce8f27a 100644 (file)
@@ -4,7 +4,7 @@
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
  *
- *  Support : paul.devriendt@amd.com
+ *  Support : mark.langsdorf@amd.com
  *
  *  Based on the powernow-k7.c module written by Dave Jones.
  *  (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
  *
  *  Valuable input gratefully received from Dave Jones, Pavel Machek,
  *  Dominik Brodowski, and others.
+ *  Originally developed by Paul Devriendt.
  *  Processor information obtained from Chapter 9 (Power and Thermal Management)
  *  of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
  *  Opteron Processors" available for download from www.amd.com
  *
  *  Tables for specific CPUs can be infrerred from
- *     http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
+ *     http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
  */
 
 #include <linux/kernel.h>
@@ -30,6 +31,7 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cpumask.h>
 
 #include <asm/msr.h>
 #include <asm/io.h>
@@ -42,7 +44,7 @@
 
 #define PFX "powernow-k8: "
 #define BFX PFX "BIOS error: "
-#define VERSION "version 1.00.09e"
+#define VERSION "version 1.40.2"
 #include "powernow-k8.h"
 
 /* serialize freq changes  */
@@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem);
 
 static struct powernow_k8_data *powernow_data[NR_CPUS];
 
+#ifndef CONFIG_SMP
+static cpumask_t cpu_core_map[1];
+#endif
+
 /* Return a frequency in MHz, given an input fid */
 static u32 find_freq_from_fid(u32 fid)
 {
@@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
 {
        u32 rvosteps = data->rvo;
        u32 savefid = data->currfid;
+       u32 maxvid, lo;
 
        dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
                smp_processor_id(),
                data->currfid, data->currvid, reqvid, data->rvo);
 
+       rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
+       maxvid = 0x1f & (maxvid >> 16);
+       dprintk("ph1 maxvid=0x%x\n", maxvid);
+       if (reqvid < maxvid) /* lower numbers are higher voltages */
+               reqvid = maxvid;
+
        while (data->currvid > reqvid) {
                dprintk("ph1: curr 0x%x, req vid 0x%x\n",
                        data->currvid, reqvid);
@@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
                        return 1;
        }
 
-       while ((rvosteps > 0)  && ((data->rvo + data->currvid) > reqvid)) {
-               if (data->currvid == 0) {
+       while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
+               if (data->currvid == maxvid) {
                        rvosteps = 0;
                } else {
                        dprintk("ph1: changing vid for rvo, req 0x%x\n",
@@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data)
         * BIOS and Kernel Developer's Guide, which is available on
         * www.amd.com
         */
-       printk(KERN_ERR PFX "BIOS error - no PSB\n");
+       printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
        return -ENODEV;
 }
 
@@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
        struct cpufreq_frequency_table *powernow_table;
 
        if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
-               dprintk("register performance failed\n");
+               dprintk("register performance failed: bad ACPI data\n");
                return -EIO;
        }
 
@@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
                        continue;
                }
 
-               if (fid < HI_FID_TABLE_BOTTOM) {
-                       if (cntlofreq) {
-                               /* if both entries are the same, ignore this
-                                * one... 
-                                */
-                               if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
-                                   (powernow_table[i].index != powernow_table[cntlofreq].index)) {
-                                       printk(KERN_ERR PFX "Too many lo freq table entries\n");
-                                       goto err_out_mem;
-                               }
-                               
-                               dprintk("double low frequency table entry, ignoring it.\n");
-                               powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
-                               continue;
-                       } else
-                               cntlofreq = i;
+               /* verify only 1 entry from the lo frequency table */
+               if (fid < HI_FID_TABLE_BOTTOM) {
+                       if (cntlofreq) {
+                               /* if both entries are the same, ignore this
+                                * one... 
+                                */
+                               if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
+                                   (powernow_table[i].index != powernow_table[cntlofreq].index)) {
+                                       printk(KERN_ERR PFX "Too many lo freq table entries\n");
+                                       goto err_out_mem;
+                               }
+
+                               dprintk("double low frequency table entry, ignoring it.\n");
+                               powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+                               continue;
+                       } else
+                               cntlofreq = i;
                }
 
                if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
@@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
 {
        u32 fid;
        u32 vid;
-       int res;
+       int res, i;
        struct cpufreq_freqs freqs;
 
        dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
@@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
        }
 
        if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
-               printk("ignoring illegal change in lo freq table-%x to 0x%x\n",
+               printk(KERN_ERR PFX
+                      "ignoring illegal change in lo freq table-%x to 0x%x\n",
                       data->currfid, fid);
                return 1;
        }
@@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
                smp_processor_id(), fid, vid);
 
        freqs.cpu = data->cpu;
-
        freqs.old = find_khz_freq_from_fid(data->currfid);
        freqs.new = find_khz_freq_from_fid(fid);
-       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+               freqs.cpu = i;
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       }
 
-       down(&fidvid_sem);
        res = transition_fid_vid(data, fid, vid);
-       up(&fidvid_sem);
 
        freqs.new = find_khz_freq_from_fid(data->currfid);
-       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
+       for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+               freqs.cpu = i;
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+        }
        return res;
 }
 
@@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
        u32 checkvid = data->currvid;
        unsigned int newstate;
        int ret = -EIO;
+       int i;
 
        /* only run on specific CPU from here on */
        oldmask = current->cpus_allowed;
@@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
                data->currfid, data->currvid);
 
        if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
-               printk(KERN_ERR PFX
-                      "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
-                      checkfid, data->currfid, checkvid, data->currvid);
+               printk(KERN_INFO PFX
+                       "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
+                       checkfid, data->currfid, checkvid, data->currvid);
        }
 
        if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
                goto err_out;
 
+       down(&fidvid_sem);
+
+       for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+               /* make sure the sibling is initialized */
+               if (!powernow_data[i]) {
+                        ret = 0;
+                        up(&fidvid_sem);
+                        goto err_out;
+                }
+       }
+
        powernow_k8_acpi_pst_values(data, newstate);
 
        if (transition_frequency(data, newstate)) {
                printk(KERN_ERR PFX "transition frequency failed\n");
                ret = 1;
+               up(&fidvid_sem);
                goto err_out;
        }
 
+       /* Update all the fid/vids of our siblings */
+       for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+               powernow_data[i]->currvid = data->currvid;
+               powernow_data[i]->currfid = data->currfid;
+       }       
+       up(&fidvid_sem);
+
        pol->cur = find_khz_freq_from_fid(data->currfid);
        ret = 0;
 
@@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
                 */
 
                if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
-                       printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
+                       printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
                        kfree(data);
                        return -ENODEV;
                }
@@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
        schedule();
 
        pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
+       pol->cpus = cpu_core_map[pol->cpu];
 
        /* Take a crude guess here. 
         * That guess was in microseconds, so multiply with 1000 */
@@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
                return 0;
        }
        preempt_disable();
-
+       
        if (query_current_values_with_pending_wait(data))
                goto out;
 
@@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void)
        cpufreq_unregister_driver(&cpufreq_amd64_driver);
 }
 
-MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
+MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
 MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
 MODULE_LICENSE("GPL");
 
 late_initcall(powernowk8_init);
 module_exit(powernowk8_exit);
+
index 63ebc8470f5249e29b64731851a0fcf932e13629..9ed5bf221cb7971fc365de5cde7c50d53024f08d 100644 (file)
@@ -174,3 +174,18 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
 static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
+
+#ifndef for_each_cpu_mask
+#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
+#endif
+                                                                                
+#ifdef CONFIG_SMP
+static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
+{
+}
+#else
+static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
+{
+       cpu_set(0, cpu_sharedcore_mask[0]);
+}
+#endif
diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
new file mode 100644 (file)
index 0000000..ef457d5
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *     sc520_freq.c: cpufreq driver for the AMD Elan sc520
+ *
+ *     Copyright (C) 2005 Sean Young <sean@mess.org>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Based on elanfreq.c
+ *
+ *     2005-03-30: - initial revision
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/delay.h>
+#include <linux/cpufreq.h>
+
+#include <asm/msr.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+
+#define MMCR_BASE      0xfffef000      /* The default base address */
+#define OFFS_CPUCTL    0x2   /* CPU Control Register */
+
+static __u8 __iomem *cpuctl;
+
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg)
+
+static struct cpufreq_frequency_table sc520_freq_table[] = {
+       {0x01,  100000},
+       {0x02,  133000},
+       {0,     CPUFREQ_TABLE_END},
+};
+
+static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
+{
+       u8 clockspeed_reg = *cpuctl;
+
+       switch (clockspeed_reg & 0x03) {
+       default:
+               printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg);
+       case 0x01:
+               return 100000;
+       case 0x02:
+               return 133000;
+       }
+}
+
+static void sc520_freq_set_cpu_state (unsigned int state)
+{
+
+       struct cpufreq_freqs    freqs;
+       u8 clockspeed_reg;
+
+       freqs.old = sc520_freq_get_cpu_frequency(0);
+       freqs.new = sc520_freq_table[state].frequency;
+       freqs.cpu = 0; /* AMD Elan is UP */
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+       dprintk("attempting to set frequency to %i kHz\n",
+                       sc520_freq_table[state].frequency);
+
+       local_irq_disable();
+
+       clockspeed_reg = *cpuctl & ~0x03;
+       *cpuctl = clockspeed_reg | sc520_freq_table[state].index;
+
+       local_irq_enable();
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+};
+
+static int sc520_freq_verify (struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
+}
+
+static int sc520_freq_target (struct cpufreq_policy *policy,
+                           unsigned int target_freq,
+                           unsigned int relation)
+{
+       unsigned int newstate = 0;
+
+       if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate))
+               return -EINVAL;
+
+       sc520_freq_set_cpu_state(newstate);
+
+       return 0;
+}
+
+
+/*
+ *     Module init and exit code
+ */
+
+static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
+{
+       struct cpuinfo_x86 *c = cpu_data;
+       int result;
+
+       /* capability check */
+       if (c->x86_vendor != X86_VENDOR_AMD ||
+           c->x86 != 4 || c->x86_model != 9)
+               return -ENODEV;
+
+       /* cpuinfo and default policy values */
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+       policy->cpuinfo.transition_latency = 1000000; /* 1ms */
+       policy->cur = sc520_freq_get_cpu_frequency(0);
+
+       result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
+       if (result)
+               return (result);
+
+       cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
+
+       return 0;
+}
+
+
+static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
+
+
+static struct freq_attr* sc520_freq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+
+static struct cpufreq_driver sc520_freq_driver = {
+       .get    = sc520_freq_get_cpu_frequency,
+       .verify = sc520_freq_verify,
+       .target = sc520_freq_target,
+       .init   = sc520_freq_cpu_init,
+       .exit   = sc520_freq_cpu_exit,
+       .name   = "sc520_freq",
+       .owner  = THIS_MODULE,
+       .attr   = sc520_freq_attr,
+};
+
+
+static int __init sc520_freq_init(void)
+{
+       struct cpuinfo_x86 *c = cpu_data;
+
+       /* Test if we have the right hardware */
+       if(c->x86_vendor != X86_VENDOR_AMD ||
+                               c->x86 != 4 || c->x86_model != 9) {
+               dprintk("no Elan SC520 processor found!\n");
+               return -ENODEV;
+       }
+       cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
+       if(!cpuctl) {
+               printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
+               return -ENOMEM;
+       }
+
+       return cpufreq_register_driver(&sc520_freq_driver);
+}
+
+
+static void __exit sc520_freq_exit(void)
+{
+       cpufreq_unregister_driver(&sc520_freq_driver);
+       iounmap(cpuctl);
+}
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
+
+module_init(sc520_freq_init);
+module_exit(sc520_freq_exit);
+
index 07d5612dc00f4f534e8926f669ca45bae2995609..7dcbf70fc16f52afaaf355aa1f4f1c7aae0ca1d5 100644 (file)
@@ -54,6 +54,8 @@ enum {
        CPU_DOTHAN_A1,
        CPU_DOTHAN_A2,
        CPU_DOTHAN_B0,
+       CPU_MP4HT_D0,
+       CPU_MP4HT_E0,
 };
 
 static const struct cpu_id cpu_ids[] = {
@@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = {
        [CPU_DOTHAN_A1] = { 6, 13, 1 },
        [CPU_DOTHAN_A2] = { 6, 13, 2 },
        [CPU_DOTHAN_B0] = { 6, 13, 6 },
+       [CPU_MP4HT_D0]  = {15,  3, 4 },
+       [CPU_MP4HT_E0]  = {15,  4, 1 },
 };
 #define N_IDS  (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
 
@@ -226,6 +230,8 @@ static struct cpu_model models[] =
        { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
        { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
        { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
+       { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },
+       { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },
 
        { NULL, }
 };
index 8ba430a9c3a21a0db5d6522128d5e5e6b2406c0c..d368b3f5fce85397e9e139eb4f5b0314ac15c178 100644 (file)
@@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
        if (!prev_speed)
                return -EIO;
 
-       dprintk("previous seped is %u\n", prev_speed);
+       dprintk("previous speed is %u\n", prev_speed);
        
        local_irq_save(flags);
 
@@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
                goto out;
        }
 
-       dprintk("low seped is %u\n", *low_speed);
+       dprintk("low speed is %u\n", *low_speed);
 
        /* switch to high state */
        set_state(SPEEDSTEP_HIGH);
@@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
                goto out;
        }
 
-       dprintk("high seped is %u\n", *high_speed);
+       dprintk("high speed is %u\n", *high_speed);
 
        if (*low_speed == *high_speed) {
                ret = -ENODEV;
index 79440b3f087ec9beeca123de97b9da6b572bd171..b25fb6b635ae85e8595454e7c304a864d10c353c 100644 (file)
@@ -357,6 +357,9 @@ static int __init speedstep_init(void)
        case SPEEDSTEP_PROCESSOR_PIII_C:
        case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
                break;
+       case SPEEDSTEP_PROCESSOR_P4M:
+               printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n");
+               break;
        default:
                speedstep_processor = 0;
        }
index aeb5b4ef8c8b52e095159551bcaaaded2442aaee..a710dc4eb20e33354cc446f6a74549f0e6a6e895 100644 (file)
@@ -118,7 +118,7 @@ struct _cpuid4_info {
 };
 
 #define MAX_CACHE_LEAVES               4
-static unsigned short __devinitdata    num_cache_leaves;
+static unsigned short                  num_cache_leaves;
 
 static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
 {
index 945ec73163c8c7ed1ff3297fe4530d4316293e6e..2bfbddebdbf80b65642f47663dba8f5042876a05 100644 (file)
@@ -1502,11 +1502,13 @@ void __init setup_arch(char **cmdline_p)
        if (efi_enabled)
                efi_map_memmap();
 
+#ifdef CONFIG_ACPI_BOOT
        /*
         * Parse the ACPI tables for possible boot-time SMP configuration.
         */
        acpi_boot_table_init();
        acpi_boot_init();
+#endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
        if (smp_found_config)
index 35bfe138cb1a408a165c08de7c456a546118cf94..bc1bb6919e6ae68e56d0f2dea2b963cd7f99410d 100644 (file)
@@ -1074,8 +1074,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
                        cpu_set(cpu, cpu_sibling_map[cpu]);
                }
 
-               if (siblings != smp_num_siblings)
+               if (siblings != smp_num_siblings) {
                        printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
+                       smp_num_siblings = siblings;
+               }
 
                if (c->x86_num_cores > 1) {
                        for (i = 0; i < NR_CPUS; i++) {
index f7f90005e22e352ffedf7a19347ae0da92fe728b..8e201219f5253f53a84d1254b922ab7a7ff1a519 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/jiffies.h>
+#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/timer.h>
@@ -24,7 +25,7 @@
 
 #define CALIBRATE_TIME (5 * 1000020/HZ)
 
-unsigned long __init calibrate_tsc(void)
+unsigned long calibrate_tsc(void)
 {
        mach_prepare_counter();
 
@@ -139,7 +140,7 @@ bad_calibration:
 #endif
 
 /* calculate cpu_khz */
-void __init init_cpu_khz(void)
+void init_cpu_khz(void)
 {
        if (cpu_has_tsc) {
                unsigned long tsc_quotient = calibrate_tsc();
@@ -158,3 +159,4 @@ void __init init_cpu_khz(void)
                }
        }
 }
+
index 7926d967be00ddf89718a4c43c4e866b17f09cfc..180444d87824e4299979a68b8f726da94ec50725 100644 (file)
@@ -320,6 +320,26 @@ core_initcall(cpufreq_tsc);
 static inline void cpufreq_delayed_get(void) { return; }
 #endif 
 
+int recalibrate_cpu_khz(void)
+{
+#ifndef CONFIG_SMP
+       unsigned long cpu_khz_old = cpu_khz;
+
+       if (cpu_has_tsc) {
+               init_cpu_khz();
+               cpu_data[0].loops_per_jiffy =
+                   cpufreq_scale(cpu_data[0].loops_per_jiffy,
+                                 cpu_khz_old,
+                                 cpu_khz);
+               return 0;
+       } else
+               return -ENODEV;
+#else
+       return -ENODEV;
+#endif
+}
+EXPORT_SYMBOL(recalibrate_cpu_khz);
+
 static void mark_offset_tsc(void)
 {
        unsigned long lost,delay;
index 247a21c64aea33bb41ad5aa591323abcfb81aaaf..c1e20d65dd6cb4688391f928f43445aea644b66b 100644 (file)
@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
 {
        struct epoll_event *events64 = NULL;
        mm_segment_t old_fs = get_fs();
-       int error, numevents, size;
+       int numevents, size;
        int evt_idx;
        int do_free_pages = 0;
 
index 81c45d44739430f5754b89117a15333f2ffa4d1f..d99316c9be28977f4a814970d42f629c958cd54b 100644 (file)
@@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user)
        ;;
 (pNonSys) mov out2=0                           // out2==0 => not a syscall
        .fframe 16
-       .spillpsp ar.unat, 16                   // (note that offset is relative to psp+0x10!)
+       .spillsp ar.unat, 16
        st8 [sp]=r9,-16                         // allocate space for ar.unat and save it
        st8 [out1]=loc1,-8                      // save ar.pfs, out1=&sigscratch
        .body
@@ -1208,7 +1208,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend)
        adds out2=8,sp                          // out2=&sigscratch->ar_pfs
        ;;
        .fframe 16
-       .spillpsp ar.unat, 16                   // (note that offset is relative to psp+0x10!)
+       .spillsp ar.unat, 16
        st8 [sp]=r9,-16                         // allocate space for ar.unat and save it
        st8 [out2]=loc1,-8                      // save ar.pfs, out2=&sigscratch
        .body
index 4d6c7b8f667bc6207dc20230c453560e276da516..736e328b5e612865d1173d84ff054dc21bbbfde9 100644 (file)
@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
        return IRQ_HANDLED;
 }
 
-#endif /* CONFIG_ACPI */
-
 /*
  *  ia64_mca_cpe_poll
  *
@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy)
        platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
+#endif /* CONFIG_ACPI */
+
 /*
  * C portion of the OS INIT handler
  *
@@ -1390,8 +1390,7 @@ ia64_mca_init(void)
        register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
 
 #ifdef CONFIG_ACPI
-       /* Setup the CPEI/P vector and handler */
-       cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
+       /* Setup the CPEI/P handler */
        register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
 #endif
 
@@ -1436,6 +1435,7 @@ ia64_mca_late_init(void)
 
 #ifdef CONFIG_ACPI
        /* Setup the CPEI/P vector and handler */
+       cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
        init_timer(&cpe_poll_timer);
        cpe_poll_timer.function = ia64_mca_cpe_poll;
 
index 1dbc7b2497c90d4b3c0a8cef4c7afb94e7abc315..f6d8a010d99beacb04dc2d3a9cf8af2e14237a3e 100644 (file)
@@ -41,7 +41,7 @@
 (pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;;                                                   \
 (pKStk) ld8 r3 = [r3];;                                                                                \
 (pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;;                                            \
-(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3;                                          \
+(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3;                                          \
 (pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
 (pUStk)        addl r22=IA64_RBS_OFFSET,r1;            /* compute base of register backing store */    \
        ;;                                                                                      \
@@ -50,7 +50,6 @@
 (pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
 (pUStk)        dep r22=-1,r22,61,3;                    /* compute kernel virtual addr of RBS */        \
        ;;                                                                                      \
-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1;         /* if in kernel mode, use sp (r12) */           \
 (pUStk)        mov ar.bspstore=r22;                    /* switch to kernel RBS */                      \
        ;;                                                                                      \
 (pUStk)        mov r18=ar.bsp;                                                                         \
index 71c101601e3ef060a33d416904c57021d1501c01..6407bff6bfd7540cb02322b093b7bf860a7e2321 100644 (file)
@@ -11,7 +11,7 @@
  * Version Perfmon-2.x is a rewrite of perfmon-1.x
  * by Stephane Eranian, Hewlett Packard Co.
  *
- * Copyright (C) 1999-2003, 2005  Hewlett Packard Co
+ * Copyright (C) 1999-2005  Hewlett Packard Co
  *               Stephane Eranian <eranian@hpl.hp.com>
  *               David Mosberger-Tang <davidm@hpl.hp.com>
  *
@@ -497,6 +497,9 @@ typedef struct {
 static pfm_stats_t             pfm_stats[NR_CPUS];
 static pfm_session_t           pfm_sessions;   /* global sessions information */
 
+static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED;
+static pfm_intr_handler_desc_t  *pfm_alt_intr_handler;
+
 static struct proc_dir_entry   *perfmon_dir;
 static pfm_uuid_t              pfm_null_uuid = {0,};
 
@@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info);
 DEFINE_PER_CPU(struct task_struct *, pmu_owner);
 DEFINE_PER_CPU(pfm_context_t  *, pmu_ctx);
 DEFINE_PER_CPU(unsigned long, pmu_activation_number);
+EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info);
 
 
 /* forward declaration */
@@ -1325,7 +1329,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
 error_conflict:
        DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",
                pfm_sessions.pfs_sys_session[cpu]->pid,
-               smp_processor_id()));
+               cpu));
 abort:
        UNLOCK_PFS(flags);
 
@@ -5555,26 +5559,32 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
        int ret;
 
        this_cpu = get_cpu();
-       min      = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
-       max      = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
+       if (likely(!pfm_alt_intr_handler)) {
+               min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
+               max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
 
-       start_cycles = ia64_get_itc();
+               start_cycles = ia64_get_itc();
 
-       ret = pfm_do_interrupt_handler(irq, arg, regs);
+               ret = pfm_do_interrupt_handler(irq, arg, regs);
 
-       total_cycles = ia64_get_itc();
+               total_cycles = ia64_get_itc();
 
-       /*
-        * don't measure spurious interrupts
-        */
-       if (likely(ret == 0)) {
-               total_cycles -= start_cycles;
+               /*
+                * don't measure spurious interrupts
+                */
+               if (likely(ret == 0)) {
+                       total_cycles -= start_cycles;
 
-               if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
-               if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
+                       if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
+                       if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
 
-               pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
+                       pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
+               }
+       }
+       else {
+               (*pfm_alt_intr_handler->handler)(irq, arg, regs);
        }
+
        put_cpu_no_resched();
        return IRQ_HANDLED;
 }
@@ -6425,6 +6435,141 @@ static struct irqaction perfmon_irqaction = {
        .name    = "perfmon"
 };
 
+static void
+pfm_alt_save_pmu_state(void *data)
+{
+       struct pt_regs *regs;
+
+       regs = ia64_task_regs(current);
+
+       DPRINT(("called\n"));
+
+       /*
+        * should not be necessary but
+        * let's take not risk
+        */
+       pfm_clear_psr_up();
+       pfm_clear_psr_pp();
+       ia64_psr(regs)->pp = 0;
+
+       /*
+        * This call is required
+        * May cause a spurious interrupt on some processors
+        */
+       pfm_freeze_pmu();
+
+       ia64_srlz_d();
+}
+
+void
+pfm_alt_restore_pmu_state(void *data)
+{
+       struct pt_regs *regs;
+
+       regs = ia64_task_regs(current);
+
+       DPRINT(("called\n"));
+
+       /*
+        * put PMU back in state expected
+        * by perfmon
+        */
+       pfm_clear_psr_up();
+       pfm_clear_psr_pp();
+       ia64_psr(regs)->pp = 0;
+
+       /*
+        * perfmon runs with PMU unfrozen at all times
+        */
+       pfm_unfreeze_pmu();
+
+       ia64_srlz_d();
+}
+
+int
+pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
+{
+       int ret, i;
+       int reserve_cpu;
+
+       /* some sanity checks */
+       if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
+
+       /* do the easy test first */
+       if (pfm_alt_intr_handler) return -EBUSY;
+
+       /* one at a time in the install or remove, just fail the others */
+       if (!spin_trylock(&pfm_alt_install_check)) {
+               return -EBUSY;
+       }
+
+       /* reserve our session */
+       for_each_online_cpu(reserve_cpu) {
+               ret = pfm_reserve_session(NULL, 1, reserve_cpu);
+               if (ret) goto cleanup_reserve;
+       }
+
+       /* save the current system wide pmu states */
+       ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1);
+       if (ret) {
+               DPRINT(("on_each_cpu() failed: %d\n", ret));
+               goto cleanup_reserve;
+       }
+
+       /* officially change to the alternate interrupt handler */
+       pfm_alt_intr_handler = hdl;
+
+       spin_unlock(&pfm_alt_install_check);
+
+       return 0;
+
+cleanup_reserve:
+       for_each_online_cpu(i) {
+               /* don't unreserve more than we reserved */
+               if (i >= reserve_cpu) break;
+
+               pfm_unreserve_session(NULL, 1, i);
+       }
+
+       spin_unlock(&pfm_alt_install_check);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt);
+
+int
+pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
+{
+       int i;
+       int ret;
+
+       if (hdl == NULL) return -EINVAL;
+
+       /* cannot remove someone else's handler! */
+       if (pfm_alt_intr_handler != hdl) return -EINVAL;
+
+       /* one at a time in the install or remove, just fail the others */
+       if (!spin_trylock(&pfm_alt_install_check)) {
+               return -EBUSY;
+       }
+
+       pfm_alt_intr_handler = NULL;
+
+       ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1);
+       if (ret) {
+               DPRINT(("on_each_cpu() failed: %d\n", ret));
+       }
+
+       for_each_online_cpu(i) {
+               pfm_unreserve_session(NULL, 1, i);
+       }
+
+       spin_unlock(&pfm_alt_install_check);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pfm_remove_alt_pmu_interrupt);
+
 /*
  * perfmon initialization routine, called from the initcall() table
  */
index 907464ee7273221468afa4c59cc811042ed2fd11..08c8a5eb25abc307c49bbc01ac34d6ad6e8e7bdb 100644 (file)
@@ -692,16 +692,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs  *pt,
                        unsigned long cfm)
 {
        struct unw_frame_info info, prev_info;
-       unsigned long ip, pr;
+       unsigned long ip, sp, pr;
 
        unw_init_from_blocked_task(&info, child);
        while (1) {
                prev_info = info;
                if (unw_unwind(&info) < 0)
                        return;
-               if (unw_get_rp(&info, &ip) < 0)
+
+               unw_get_sp(&info, &sp);
+               if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
+                   < IA64_PT_REGS_SIZE) {
+                       dprintk("ptrace.%s: ran off the top of the kernel "
+                               "stack\n", __FUNCTION__);
+                       return;
+               }
+               if (unw_get_pr (&prev_info, &pr) < 0) {
+                       unw_get_rp(&prev_info, &ip);
+                       dprintk("ptrace.%s: failed to read "
+                               "predicate register (ip=0x%lx)\n",
+                               __FUNCTION__, ip);
                        return;
-               if (ip < FIXADDR_USER_END)
+               }
+               if (unw_is_intr_frame(&info)
+                   && (pr & (1UL << PRED_USER_STACK)))
                        break;
        }
 
index 0d5ee57c9865ce10128cdf89a05d0af48d8d7020..3865f088ffa26d9c7db30c932098a09db0762ba0 100644 (file)
@@ -624,7 +624,7 @@ static struct {
        __u16   thread_id;
        __u16   proc_fixed_addr;
        __u8    valid;
-}mt_info[NR_CPUS] __devinit;
+} mt_info[NR_CPUS] __devinitdata;
 
 #ifdef CONFIG_HOTPLUG_CPU
 static inline void
index a8cf6d8a509cb07c780ccde59b8a71a30c437b46..770fab37928ee9e4c3870b8875473f7a53d1213b 100644 (file)
@@ -182,13 +182,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
                }
        }
 
-       /*
-        * A zero mmap always succeeds in Linux, independent of whether or not the
-        * remaining arguments are valid.
-        */
-       if (len == 0)
-               goto out;
-
        /* Careful about overflows.. */
        len = PAGE_ALIGN(len);
        if (!len || len > TASK_SIZE) {
index 4fb44984afe61198a5f3c4c62795a6ced91eb265..e64cb8175f7a7450becd3ff9962ab348b80780d1 100644 (file)
@@ -271,6 +271,8 @@ void __init sn_setup(char **cmdline_p)
        int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
        extern void sn_cpu_init(void);
 
+       ia64_sn_plat_set_error_handling_features();
+
        /*
         * If the generic code has enabled vga console support - lets
         * get rid of it again. This is a kludge for the fact that ACPI
index 2b6c9d32b7a6267754ab11b202317755a825a0b5..c4a33f265dc07e53577350d5366b3a936c8bc665 100644 (file)
@@ -45,11 +45,13 @@ asmlinkage void ret_from_fork(void);
  */
 void default_idle(void)
 {
-       while(1) {
-               if (need_resched())
-                       __asm__("stop #0x2000" : : : "cc");
-               schedule();
+       local_irq_disable();
+       while (!need_resched()) {
+               /* This stop will re-enable interrupts */
+               __asm__("stop #0x2000" : : : "cc");
+               local_irq_disable();
        }
+       local_irq_enable();
 }
 
 void (*idle)(void) = default_idle;
@@ -63,7 +65,12 @@ void (*idle)(void) = default_idle;
 void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
-       idle();
+       while (1) {
+               idle();
+               preempt_enable_no_resched();
+               schedule();
+               preempt_disable();
+       }
 }
 
 void machine_restart(char * __unused)
index 600f23d7fd33aae9e5115875ada43a289e075b5d..6e6377a69d5bc58c16de9f12013b377b3af7d17e 100644 (file)
@@ -1143,12 +1143,12 @@ config PCI_QSPAN
 
 config PCI_8260
        bool
-       depends on PCI && 8260 && !8272
+       depends on PCI && 8260
        default y
 
 config 8260_PCI9
        bool "  Enable workaround for MPC826x erratum PCI 9"
-       depends on PCI_8260
+       depends on PCI_8260 && !ADS8272
        default y
 
 choice
index f850fb0fb5118be47d976291ee028697fbdeb688..c9ac5f5fa9e483d205172b4835c7a361ade172a1 100644 (file)
@@ -22,7 +22,8 @@ targets += uImage
 $(obj)/uImage: $(obj)/vmlinux.gz
        $(Q)rm -f $@
        $(call if_changed,uimage)
-       @echo '  Image: $@' $(if $(wildcard $@),'is ready','not made')
+       @echo -n '  Image: $@ '
+       @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
 
 # Files generated that shall be removed upon make clean
 clean-files    := sImage vmapus vmlinux* miboot* zImage* uImage
index 728bd9e1a8fabf3982d5bc52b0147cd5637e9219..15abebf46b96f8344c634831099794f4e429305e 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc1
-# Thu Jan 20 01:25:35 2005
+# Linux kernel version: 2.6.12-rc4
+# Tue May 17 11:56:01 2005
 #
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y
 CONFIG_PPC=y
 CONFIG_PPC32=y
 CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 
 #
 # Code maturity level options
@@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -29,12 +31,14 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -62,10 +67,12 @@ CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_E500=y
 CONFIG_BOOKE=y
 CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
 CONFIG_SPE=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_CPU_FREQ is not set
 CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
 CONFIG_85xx=y
 CONFIG_PPC_INDIRECT_PCI_BE=y
 
@@ -76,6 +83,7 @@ CONFIG_PPC_INDIRECT_PCI_BE=y
 CONFIG_MPC8555_CDS=y
 # CONFIG_MPC8560_ADS is not set
 # CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
 CONFIG_MPC8555=y
 CONFIG_85xx_PCI2=y
 
@@ -90,6 +98,7 @@ CONFIG_CPM2=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
@@ -104,10 +113,6 @@ CONFIG_PCI_NAMES=y
 #
 # CONFIG_PCCARD is not set
 
-#
-# PC-card bridges
-#
-
 #
 # Advanced setup
 #
@@ -180,7 +185,59 @@ CONFIG_IOSCHED_CFQ=y
 #
 # ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -220,7 +277,6 @@ CONFIG_NET=y
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -369,14 +425,6 @@ CONFIG_INPUT=y
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
 #
 # Input Device Drivers
 #
@@ -386,6 +434,13 @@ CONFIG_SOUND_GAMEPORT=y
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
 #
 # Character devices
 #
@@ -406,6 +461,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_CPM is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -433,6 +489,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
 #
 # I2C support
 #
@@ -456,11 +517,11 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_SCx200_ACB is not set
@@ -483,7 +544,9 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
@@ -494,9 +557,11 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -506,10 +571,12 @@ CONFIG_I2C_MPC=y
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -538,7 +605,6 @@ CONFIG_I2C_MPC=y
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -548,13 +614,9 @@ CONFIG_I2C_MPC=y
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -585,6 +647,10 @@ CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -646,7 +712,6 @@ CONFIG_NFS_FS=y
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -698,7 +763,9 @@ CONFIG_CRC32=y
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_KGDB_CONSOLE is not set
 # CONFIG_SERIAL_TEXT_DEBUG is not set
 
index f22ddce36135fddce922d21e2b033d642f5fe946..ce36e88ba6277ea68631ddd0fc8fb13623e94fe6 100644 (file)
@@ -232,7 +232,8 @@ skpinv:     addi    r6,r6,1                         /* Increment */
        tlbwe
 
 /* 7. Jump to KERNELBASE mapping */
-       li      r7,0
+       lis     r7,MSR_KERNEL@h
+       ori     r7,r7,MSR_KERNEL@l
        bl      1f                      /* Find our address */
 1:     mflr    r9
        rlwimi  r6,r9,0,20,31
@@ -293,6 +294,18 @@ skpinv:    addi    r6,r6,1                         /* Increment */
        mtspr   SPRN_HID0, r2
 #endif
 
+#if !defined(CONFIG_BDI_SWITCH)
+       /*
+        * The Abatron BDI JTAG debugger does not tolerate others
+        * mucking with the debug registers.
+        */
+       lis     r2,DBCR0_IDM@h
+       mtspr   SPRN_DBCR0,r2
+       /* clear any residual debug events */
+       li      r2,-1
+       mtspr   SPRN_DBSR,r2
+#endif
+
        /*
         * This is where the main kernel code starts.
         */
index f8e7e324a17396fc81e64a3afbcc2cb77eaa6702..c65731e8bc657cb2edbcec90b8050ef813846803 100644 (file)
@@ -408,12 +408,7 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 
        /* Early out if we are an invalid form of lswx */
        if ((instword & INST_STRING_MASK) == INST_LSWX)
-               if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB))
-                       return -EINVAL;
-
-       /* Early out if we are an invalid form of lswi */
-       if ((instword & INST_STRING_MASK) == INST_LSWI)
-               if ((rA >= rT) || (rT == rA))
+               if ((rT == rA) || (rT == NB_RB))
                        return -EINVAL;
 
        EA = (rA == 0) ? 0 : regs->gpr[rA];
index b3b0f51979d2b2c6ef6b316c392567e8d4a67765..e6348b5a1ddc6a56e81908fbd8a8e8434f471e44 100644 (file)
@@ -127,7 +127,6 @@ mpc834x_sys_map_io(void)
 {
        /* we steal the lowest ioremap addr for virt space */
        io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
-       io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
 }
 
 int
index f4d055ae19c14b6eecf94e6be35bd05d6afc3f19..a2f6e49d71512946ca5e89e2b7d7ca80fec0f8de 100644 (file)
 #define VIRT_IMMRBAR           ((uint)0xfe000000)
 
 #define BCSR_PHYS_ADDR         ((uint)0xf8000000)
-#define BCSR_VIRT_ADDR         ((uint)0xfe100000)
 #define BCSR_SIZE              ((uint)(32 * 1024))
 
+#define BCSR_MISC_REG2_OFF     0x07
+#define BCSR_MISC_REG2_PORESET 0x01
+
+#define BCSR_MISC_REG3_OFF     0x08
+#define BCSR_MISC_REG3_CNFLOCK 0x80
+
 #ifdef CONFIG_PCI
 /* PCI interrupt controller */
 #define PIRQA        MPC83xx_IRQ_IRQ4
index 4d857d6d633d757c7818356c24a12219f99c341d..583838ab02d8370a97d22640915a3fed84d1eaf6 100644 (file)
@@ -210,6 +210,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
        ppc_md.progress = gen550_progress;
 #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+       ppc_md.early_serial_map = mpc85xx_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
 
        if (ppc_md.progress)
                ppc_md.progress("mpc8540ads_init(): exit", 0);
index 6c020d67ad704457a1341d2295907d5c52733928..e7cfa498568c25b03f891bd809a3342010c32f58 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/open_pic.h>
+#include <asm/i8259.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
 #include <asm/mpc85xx.h>
@@ -181,6 +182,7 @@ void __init
 mpc85xx_cds_init_IRQ(void)
 {
        bd_t *binfo = (bd_t *) __res;
+       int i;
 
        /* Determine the Physical Address of the OpenPIC regs */
        phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
@@ -198,6 +200,15 @@ mpc85xx_cds_init_IRQ(void)
         */
        openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
 
+#ifdef CONFIG_PCI
+       openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
+
+       for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+               irq_desc[i].handler = &i8259_pic;
+
+       i8259_init(0);
+#endif
+
 #ifdef CONFIG_CPM2
        /* Setup CPM2 PIC */
         cpm2_init_IRQ();
@@ -231,7 +242,7 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
                         * interrupt on slot */
                {
                        { 0, 1, 2, 3 }, /* 16 - PMC */
-                       { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */
+                       { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
                        { 0, 1, 2, 3 }, /* 18 - Slot 1 */
                        { 1, 2, 3, 0 }, /* 19 - Slot 2 */
                        { 2, 3, 0, 1 }, /* 20 - Slot 3 */
@@ -280,13 +291,135 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
                        return PCIBIOS_DEVICE_NOT_FOUND;
 #endif
        /* We explicitly do not go past the Tundra 320 Bridge */
-       if (bus == 1)
+       if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
                return PCIBIOS_DEVICE_NOT_FOUND;
        if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
                return PCIBIOS_DEVICE_NOT_FOUND;
        else
                return PCIBIOS_SUCCESSFUL;
 }
+
+void __init
+mpc85xx_cds_enable_via(struct pci_controller *hose)
+{
+       u32 pci_class;
+       u16 vid, did;
+
+       early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
+       if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
+               return;
+
+       /* Configure P2P so that we can reach bus 1 */
+       early_write_config_byte(hose, 0, 0x88, PCI_PRIMARY_BUS, 0);
+       early_write_config_byte(hose, 0, 0x88, PCI_SECONDARY_BUS, 1);
+       early_write_config_byte(hose, 0, 0x88, PCI_SUBORDINATE_BUS, 0xff);
+
+       early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
+       early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
+
+       if ((vid != PCI_VENDOR_ID_VIA) ||
+                       (did != PCI_DEVICE_ID_VIA_82C686))
+               return;
+
+       /* Enable USB and IDE functions */
+       early_write_config_byte(hose, 1, 0x10, 0x48, 0x08);
+}
+
+void __init
+mpc85xx_cds_fixup_via(struct pci_controller *hose)
+{
+       u32 pci_class;
+       u16 vid, did;
+
+       early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
+       if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
+               return;
+
+       /*
+        * Force the backplane P2P bridge to have a window
+        * open from 0x00000000-0x00001fff in PCI I/O space.
+        * This allows legacy I/O (i8259, etc) on the VIA
+        * southbridge to be accessed.
+        */
+       early_write_config_byte(hose, 0, 0x88, PCI_IO_BASE, 0x00);
+       early_write_config_word(hose, 0, 0x88, PCI_IO_BASE_UPPER16, 0x0000);
+       early_write_config_byte(hose, 0, 0x88, PCI_IO_LIMIT, 0x10);
+       early_write_config_word(hose, 0, 0x88, PCI_IO_LIMIT_UPPER16, 0x0000);
+
+       early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
+       early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
+       if ((vid != PCI_VENDOR_ID_VIA) ||
+                       (did != PCI_DEVICE_ID_VIA_82C686))
+               return;
+
+       /*
+        * Since the P2P window was forced to cover the fixed
+        * legacy I/O addresses, it is necessary to manually
+        * place the base addresses for the IDE and USB functions
+        * within this window.
+        */
+       /* Function 1, IDE */
+       early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_0, 0x1ff8);
+       early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_1, 0x1ff4);
+       early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_2, 0x1fe8);
+       early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_3, 0x1fe4);
+       early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_4, 0x1fd0);
+
+       /* Function 2, USB ports 0-1 */
+       early_write_config_dword(hose, 1, 0x12, PCI_BASE_ADDRESS_4, 0x1fa0);
+
+       /* Function 3, USB ports 2-3 */
+       early_write_config_dword(hose, 1, 0x13, PCI_BASE_ADDRESS_4, 0x1f80);
+
+       /* Function 5, Power Management */
+       early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_0, 0x1e00);
+       early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_1, 0x1dfc);
+       early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_2, 0x1df8);
+
+       /* Function 6, AC97 Interface */
+       early_write_config_dword(hose, 1, 0x16, PCI_BASE_ADDRESS_0, 0x1c00);
+}
+
+void __init
+mpc85xx_cds_pcibios_fixup(void)
+{
+        struct pci_dev *dev = NULL;
+       u_char          c;
+
+        if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+                                        PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+                /*
+                 * U-Boot does not set the enable bits
+                 * for the IDE device. Force them on here.
+                 */
+                pci_read_config_byte(dev, 0x40, &c);
+                c |= 0x03; /* IDE: Chip Enable Bits */
+                pci_write_config_byte(dev, 0x40, c);
+
+               /*
+                * Since only primary interface works, force the
+                * IDE function to standard primary IDE interrupt
+                * w/ 8259 offset
+                */
+                dev->irq = 14;
+                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+        }
+
+       /*
+        * Force legacy USB interrupt routing
+        */
+        if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+                                        PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
+                dev->irq = 10;
+                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+        }
+
+        if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+                                        PCI_DEVICE_ID_VIA_82C586_2, dev))) {
+                dev->irq = 11;
+                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+        }
+}
 #endif /* CONFIG_PCI */
 
 TODC_ALLOC();
@@ -328,6 +461,9 @@ mpc85xx_cds_setup_arch(void)
        loops_per_jiffy = freq / HZ;
 
 #ifdef CONFIG_PCI
+       /* VIA IDE configuration */
+        ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+
        /* setup PCI host bridges */
        mpc85xx_setup_hose();
 #endif
@@ -459,6 +595,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
        ppc_md.progress = gen550_progress;
 #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+       ppc_md.early_serial_map = mpc85xx_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
 
        if (ppc_md.progress)
                ppc_md.progress("mpc85xx_cds_init(): exit", 0);
index 7627d77504bd07a8da615ccff57662ca44f4421e..12b292c6ae3225bb41eeea720de35a8770bdca0a 100644 (file)
@@ -77,4 +77,7 @@
 
 #define MPC85XX_PCI2_IO_SIZE         0x01000000
 
+#define NR_8259_INTS                16
+#define CPM_IRQ_OFFSET              NR_8259_INTS
+
 #endif /* __MACH_MPC85XX_CDS_H__ */
index 9ab05e590c3e0a60537052f7880fc5f8e4033aba..7b9e1543e17524e6301e4c45cd9d77b4a6b8967e 100644 (file)
@@ -221,6 +221,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
        ppc_md.progress = gen550_progress;
 #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+       ppc_md.early_serial_map = sbc8560_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
 
        if (ppc_md.progress)
                ppc_md.progress("sbc8560_init(): exit", 0);
index f7fb2786cd505a7701fe2322c73b169af4ff2133..937f46df711eeda3dc94db367bb7a0e2e0c7c387 100644 (file)
@@ -85,14 +85,11 @@ static int no_schedule;
 static int has_cpu_l2lve;
 
 
-#define PMAC_CPU_LOW_SPEED     1
-#define PMAC_CPU_HIGH_SPEED    0
-
 /* There are only two frequency states for each processor. Values
  * are in kHz for the time being.
  */
-#define CPUFREQ_HIGH                  PMAC_CPU_HIGH_SPEED
-#define CPUFREQ_LOW                   PMAC_CPU_LOW_SPEED
+#define CPUFREQ_HIGH                  0
+#define CPUFREQ_LOW                   1
 
 static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
        {CPUFREQ_HIGH,          0},
@@ -100,6 +97,11 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
+static struct freq_attr* pmac_cpu_freqs_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
 static inline void local_delay(unsigned long ms)
 {
        if (no_schedule)
@@ -269,6 +271,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
 #ifdef DEBUG_FREQ
        printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
 #endif
+       pmu_suspend();
+
        /* Disable all interrupt sources on openpic */
        pic_prio = openpic_get_priority();
        openpic_set_priority(0xf);
@@ -343,6 +347,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
        debug_calc_bogomips();
 #endif
 
+       pmu_resume();
+
        preempt_enable();
 
        return 0;
@@ -355,7 +361,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
        static unsigned long prev_l3cr;
 
        freqs.old = cur_freq;
-       freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+       freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
        freqs.cpu = smp_processor_id();
 
        if (freqs.old == freqs.new)
@@ -363,7 +369,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
 
        if (notify)
                cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-       if (speed_mode == PMAC_CPU_LOW_SPEED &&
+       if (speed_mode == CPUFREQ_LOW &&
            cpu_has_feature(CPU_FTR_L3CR)) {
                l3cr = _get_L3CR();
                if (l3cr & L3CR_L3E) {
@@ -371,8 +377,8 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
                        _set_L3CR(0);
                }
        }
-       set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
-       if (speed_mode == PMAC_CPU_HIGH_SPEED &&
+       set_speed_proc(speed_mode == CPUFREQ_LOW);
+       if (speed_mode == CPUFREQ_HIGH &&
            cpu_has_feature(CPU_FTR_L3CR)) {
                l3cr = _get_L3CR();
                if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
@@ -380,7 +386,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
        }
        if (notify)
                cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-       cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+       cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
 
        return 0;
 }
@@ -423,7 +429,8 @@ static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency      = CPUFREQ_ETERNAL;
        policy->cur = cur_freq;
 
-       return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]);
+       cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
+       return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
 }
 
 static u32 __pmac read_gpio(struct device_node *np)
@@ -457,7 +464,7 @@ static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
        no_schedule = 1;
        sleep_freq = cur_freq;
        if (cur_freq == low_freq)
-               do_set_cpu_speed(PMAC_CPU_HIGH_SPEED, 0);
+               do_set_cpu_speed(CPUFREQ_HIGH, 0);
        return 0;
 }
 
@@ -473,8 +480,8 @@ static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy)
         * is that we force a switch to whatever it was, which is
         * probably high speed due to our suspend() routine
         */
-       do_set_cpu_speed(sleep_freq == low_freq ? PMAC_CPU_LOW_SPEED
-                        : PMAC_CPU_HIGH_SPEED, 0);
+       do_set_cpu_speed(sleep_freq == low_freq ?
+                        CPUFREQ_LOW : CPUFREQ_HIGH, 0);
 
        no_schedule = 0;
        return 0;
@@ -488,6 +495,7 @@ static struct cpufreq_driver pmac_cpufreq_driver = {
        .suspend        = pmac_cpufreq_suspend,
        .resume         = pmac_cpufreq_resume,
        .flags          = CPUFREQ_PM_NO_WARN,
+       .attr           = pmac_cpu_freqs_attr,
        .name           = "powermac",
        .owner          = THIS_MODULE,
 };
index cf5e5dd06d6300d7733b20f4e5b21c31a1bdda48..067d9a5aebc108f7301913e74d3d218161c23ea7 100644 (file)
 /* PCI interrupt controller */
 #define PCI_INT_STAT_REG       0xF8200000
 #define PCI_INT_MASK_REG       0xF8200004
-#define PIRQA                  (NR_SIU_INTS + 0)
-#define PIRQB                  (NR_SIU_INTS + 1)
-#define PIRQC                  (NR_SIU_INTS + 2)
-#define PIRQD                  (NR_SIU_INTS + 3)
+#define PIRQA                  (NR_CPM_INTS + 0)
+#define PIRQB                  (NR_CPM_INTS + 1)
+#define PIRQC                  (NR_CPM_INTS + 2)
+#define PIRQD                  (NR_CPM_INTS + 3)
 
 /*
  * PCI memory map definitions for MPC8266ADS-PCI.
  *     0x00000000-0x1FFFFFFF   0x00000000-0x1FFFFFFF   MPC8266 local memory
  */
 
-/* window for a PCI master to access MPC8266 memory */
-#define PCI_SLV_MEM_LOCAL      0x00000000      /* Local base */
-#define PCI_SLV_MEM_BUS                0x00000000      /* PCI base */
+/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
+   Here we should redefine what is unique for this board */
+#define M82xx_PCI_SLAVE_MEM_LOCAL      0x00000000      /* Local base */
+#define M82xx_PCI_SLAVE_MEM_BUS                0x00000000      /* PCI base */
+#define M82xx_PCI_SLAVE_MEM_SIZE       0x10000000      /* 256 Mb */
 
-/* window for the processor to access PCI memory with prefetching */
-#define PCI_MSTR_MEM_LOCAL     0x80000000      /* Local base */
-#define PCI_MSTR_MEM_BUS       0x80000000      /* PCI base   */
-#define PCI_MSTR_MEM_SIZE      0x20000000      /* 512MB */
+#define M82xx_PCI_SLAVE_SEC_WND_SIZE   ~(0x40000000 - 1U)      /* 2 x 512Mb  */
+#define M82xx_PCI_SLAVE_SEC_WND_BASE   0x80000000              /* PCI Memory base */
 
-/* window for the processor to access PCI memory without prefetching */
-#define PCI_MSTR_MEMIO_LOCAL   0xA0000000      /* Local base */
-#define PCI_MSTR_MEMIO_BUS     0xA0000000      /* PCI base   */
-#define PCI_MSTR_MEMIO_SIZE    0x20000000      /* 512MB */
+#if defined(CONFIG_ADS8272)
+#define PCI_INT_TO_SIU         SIU_INT_IRQ2
+#elif defined(CONFIG_PQ2FADS)
+#define PCI_INT_TO_SIU         SIU_INT_IRQ6
+#else
+#warning PCI Bridge will be without interrupts support
+#endif
 
-/* window for the processor to access PCI I/O */
-#define PCI_MSTR_IO_LOCAL      0xF4000000      /* Local base */
-#define PCI_MSTR_IO_BUS         0x00000000     /* PCI base   */
-#define PCI_MSTR_IO_SIZE        0x04000000     /* 64MB */
-
-#define _IO_BASE               PCI_MSTR_IO_LOCAL
-#define _ISA_MEM_BASE          PCI_MSTR_MEMIO_LOCAL
-#define PCI_DRAM_OFFSET                PCI_SLV_MEM_BUS
 #endif /* CONFIG_PCI */
 
 #endif /* __MACH_ADS8260_DEFS */
index dd418ea3426c70a4ed065986e464967fce8122fb..96acf85800d47a493ca924ded205dcfb70af8779 100644 (file)
@@ -81,7 +81,7 @@ obj-$(CONFIG_SBC82xx)         += todc_time.o
 obj-$(CONFIG_SPRUCE)           += cpc700_pic.o indirect_pci.o pci_auto.o \
                                   todc_time.o
 obj-$(CONFIG_8260)             += m8260_setup.o
-obj-$(CONFIG_PCI_8260)         += m8260_pci.o indirect_pci.o
+obj-$(CONFIG_PCI_8260)         += m82xx_pci.o indirect_pci.o pci_auto.o
 obj-$(CONFIG_8260_PCI9)                += m8260_pci_erratum9.o
 obj-$(CONFIG_CPM2)             += cpm2_common.o cpm2_pic.o
 ifeq ($(CONFIG_PPC_GEN550),y)
@@ -97,7 +97,7 @@ obj-$(CONFIG_MPC10X_OPENPIC)  += open_pic.o
 obj-$(CONFIG_40x)              += dcr.o
 obj-$(CONFIG_BOOKE)            += dcr.o
 obj-$(CONFIG_85xx)             += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
-                                       ppc_sys.o mpc85xx_sys.o \
+                                       ppc_sys.o i8259.o mpc85xx_sys.o \
                                        mpc85xx_devices.o
 ifeq ($(CONFIG_85xx),y)
 obj-$(CONFIG_PCI)              += indirect_pci.o pci_auto.o
diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c
deleted file mode 100644 (file)
index 057cc3f..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2004 Red Hat, Inc.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/immap_cpm2.h>
-#include <asm/mpc8260.h>
-
-#include "m8260_pci.h"
-
-
-/* PCI bus configuration registers.
- */
-
-static void __init m8260_setup_pci(struct pci_controller *hose)
-{
-       volatile cpm2_map_t *immap = cpm2_immr;
-       unsigned long pocmr;
-       u16 tempShort;
-
-#ifndef CONFIG_ATC     /* already done in U-Boot */
-       /* 
-        * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]), 
-        * and local bus for PCI (SIUMCR [LBPC]).
-        */
-       immap->im_siu_conf.siu_82xx.sc_siumcr = 0x00640000;
-#endif
-
-       /* Make PCI lowest priority */
-       /* Each 4 bits is a device bus request  and the MS 4bits 
-          is highest priority */
-       /* Bus               4bit value 
-          ---               ----------
-          CPM high          0b0000
-          CPM middle        0b0001
-          CPM low           0b0010
-          PCI reguest       0b0011
-          Reserved          0b0100
-          Reserved          0b0101
-          Internal Core     0b0110
-          External Master 1 0b0111
-          External Master 2 0b1000
-          External Master 3 0b1001
-          The rest are reserved */
-       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
-
-       /* Park bus on core while modifying PCI Bus accesses */
-       immap->im_siu_conf.siu_82xx.sc_ppc_acr = 0x6;
-
-       /* 
-        * Set up master window that allows the CPU to access PCI space. This 
-        * window is set up using the first SIU PCIBR registers.
-        */
-       immap->im_memctl.memc_pcimsk0 = MPC826x_PCI_MASK;
-       immap->im_memctl.memc_pcibr0 =  MPC826x_PCI_BASE | PCIBR_ENABLE;
-
-       /* Disable machine check on no response or target abort */
-       immap->im_pci.pci_emr = cpu_to_le32(0x1fe7);
-       /* Release PCI RST (by default the PCI RST signal is held low)  */
-       immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
-
-       /* give it some time */
-       mdelay(1);
-
-       /* 
-        * Set up master window that allows the CPU to access PCI Memory (prefetch) 
-        * space. This window is set up using the first set of Outbound ATU registers.
-        */
-       immap->im_pci.pci_potar0 = cpu_to_le32(MPC826x_PCI_LOWER_MEM >> 12);
-       immap->im_pci.pci_pobar0 = cpu_to_le32((MPC826x_PCI_LOWER_MEM - MPC826x_PCI_MEM_OFFSET) >> 12);
-       pocmr = ((MPC826x_PCI_UPPER_MEM - MPC826x_PCI_LOWER_MEM) >> 12) ^ 0xfffff;
-       immap->im_pci.pci_pocmr0 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PREFETCH_EN);
-
-       /* 
-        * Set up master window that allows the CPU to access PCI Memory (non-prefetch) 
-        * space. This window is set up using the second set of Outbound ATU registers.
-        */
-       immap->im_pci.pci_potar1 = cpu_to_le32(MPC826x_PCI_LOWER_MMIO >> 12);
-       immap->im_pci.pci_pobar1 = cpu_to_le32((MPC826x_PCI_LOWER_MMIO - MPC826x_PCI_MMIO_OFFSET) >> 12);
-       pocmr = ((MPC826x_PCI_UPPER_MMIO - MPC826x_PCI_LOWER_MMIO) >> 12) ^ 0xfffff;
-       immap->im_pci.pci_pocmr1 = cpu_to_le32(pocmr | POCMR_ENABLE);
-
-       /* 
-        * Set up master window that allows the CPU to access PCI IO space. This window
-        * is set up using the third set of Outbound ATU registers.
-        */
-       immap->im_pci.pci_potar2 = cpu_to_le32(MPC826x_PCI_IO_BASE >> 12);
-       immap->im_pci.pci_pobar2 = cpu_to_le32(MPC826x_PCI_LOWER_IO >> 12);
-       pocmr = ((MPC826x_PCI_UPPER_IO - MPC826x_PCI_LOWER_IO) >> 12) ^ 0xfffff;
-       immap->im_pci.pci_pocmr2 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PCI_IO);
-
-       /* 
-        * Set up slave window that allows PCI masters to access MPC826x local memory. 
-        * This window is set up using the first set of Inbound ATU registers
-        */
-
-       immap->im_pci.pci_pitar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_LOCAL >> 12);
-       immap->im_pci.pci_pibar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_BUS >> 12);
-       pocmr = ((MPC826x_PCI_SLAVE_MEM_SIZE-1) >> 12) ^ 0xfffff;
-       immap->im_pci.pci_picmr0 = cpu_to_le32(pocmr | PICMR_ENABLE | PICMR_PREFETCH_EN);
-
-       /* See above for description - puts PCI request as highest priority */
-       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
-
-       /* Park the bus on the PCI */
-       immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
-
-       /* Host mode - specify the bridge as a host-PCI bridge */
-       early_write_config_word(hose, 0, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST);
-
-       /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
-       early_read_config_word(hose, 0, 0, PCI_COMMAND, &tempShort);
-       early_write_config_word(hose, 0, 0, PCI_COMMAND,
-                               tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-}
-
-void __init m8260_find_bridges(void)
-{
-       extern int pci_assign_all_busses;
-       struct pci_controller * hose;
-
-       pci_assign_all_busses = 1;
-
-       hose = pcibios_alloc_controller();
-
-       if (!hose)
-               return;
-
-       ppc_md.pci_swizzle = common_swizzle;
-
-       hose->first_busno = 0;
-       hose->bus_offset = 0;
-       hose->last_busno = 0xff;
-
-       setup_m8260_indirect_pci(hose, 
-                                (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
-                                (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
-
-       m8260_setup_pci(hose);
-        hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
-
-        hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE,
-                                        MPC826x_PCI_IO_SIZE);
-        isa_io_base = (unsigned long) hose->io_base_virt;
-        /* setup resources */
-        pci_init_resource(&hose->mem_resources[0],
-                         MPC826x_PCI_LOWER_MEM,
-                         MPC826x_PCI_UPPER_MEM,
-                         IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
-
-        pci_init_resource(&hose->mem_resources[1],
-                         MPC826x_PCI_LOWER_MMIO,
-                         MPC826x_PCI_UPPER_MMIO,
-                         IORESOURCE_MEM, "PCI memory");
-
-        pci_init_resource(&hose->io_resource,
-                         MPC826x_PCI_LOWER_IO,
-                         MPC826x_PCI_UPPER_IO,
-                         IORESOURCE_IO, "PCI I/O");
-}
diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
deleted file mode 100644 (file)
index d135212..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#ifndef _PPC_KERNEL_M8260_PCI_H
-#define _PPC_KERNEL_M8260_PCI_H
-
-#include <asm/m8260_pci.h>
-
-/*
- *   Local->PCI map (from CPU)                             controlled by
- *   MPC826x master window
- *
- *   0x80000000 - 0xBFFFFFFF    Total CPU2PCI space        PCIBR0
- *                       
- *   0x80000000 - 0x9FFFFFFF    PCI Mem with prefetch      (Outbound ATU #1)
- *   0xA0000000 - 0xAFFFFFFF    PCI Mem w/o  prefetch      (Outbound ATU #2)
- *   0xB0000000 - 0xB0FFFFFF    32-bit PCI IO              (Outbound ATU #3)
- *                      
- *   PCI->Local map (from PCI)
- *   MPC826x slave window                                  controlled by
- *
- *   0x00000000 - 0x07FFFFFF    MPC826x local memory       (Inbound ATU #1)
- */
-
-/* 
- * Slave window that allows PCI masters to access MPC826x local memory. 
- * This window is set up using the first set of Inbound ATU registers
- */
-
-#ifndef MPC826x_PCI_SLAVE_MEM_LOCAL
-#define MPC826x_PCI_SLAVE_MEM_LOCAL    (((struct bd_info *)__res)->bi_memstart)
-#define MPC826x_PCI_SLAVE_MEM_BUS      (((struct bd_info *)__res)->bi_memstart)
-#define MPC826x_PCI_SLAVE_MEM_SIZE     (((struct bd_info *)__res)->bi_memsize)
-#endif
-
-/* 
- * This is the window that allows the CPU to access PCI address space.
- * It will be setup with the SIU PCIBR0 register. All three PCI master
- * windows, which allow the CPU to access PCI prefetch, non prefetch,
- * and IO space (see below), must all fit within this window. 
- */
-#ifndef MPC826x_PCI_BASE
-#define MPC826x_PCI_BASE       0x80000000
-#define MPC826x_PCI_MASK       0xc0000000
-#endif
-
-#ifndef MPC826x_PCI_LOWER_MEM
-#define MPC826x_PCI_LOWER_MEM  0x80000000
-#define MPC826x_PCI_UPPER_MEM  0x9fffffff
-#define MPC826x_PCI_MEM_OFFSET 0x00000000
-#endif
-
-#ifndef MPC826x_PCI_LOWER_MMIO
-#define MPC826x_PCI_LOWER_MMIO  0xa0000000
-#define MPC826x_PCI_UPPER_MMIO  0xafffffff
-#define MPC826x_PCI_MMIO_OFFSET 0x00000000
-#endif
-
-#ifndef MPC826x_PCI_LOWER_IO
-#define MPC826x_PCI_LOWER_IO   0x00000000
-#define MPC826x_PCI_UPPER_IO   0x00ffffff
-#define MPC826x_PCI_IO_BASE    0xb0000000
-#define MPC826x_PCI_IO_SIZE    0x01000000
-#endif
-
-#ifndef _IO_BASE
-#define _IO_BASE isa_io_base
-#endif
-
-#ifdef CONFIG_8260_PCI9
-struct pci_controller;
-extern void setup_m8260_indirect_pci(struct pci_controller* hose,
-                                    u32 cfg_addr, u32 cfg_data);
-#else
-#define setup_m8260_indirect_pci setup_indirect_pci
-#endif
-
-#endif /* _PPC_KERNEL_M8260_PCI_H */
index 9c0582d639e051ccba4d213044045bf99211550c..1dc7e4e1d4914ed5d11f583b944de475092436d7 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/immap_cpm2.h>
 #include <asm/cpm2.h>
 
-#include "m8260_pci.h"
+#include "m82xx_pci.h"
 
 #ifdef CONFIG_8260_PCI9
 /*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */
@@ -248,11 +248,11 @@ EXPORT_SYMBOL(idma_pci9_read_le);
 
 static inline int is_pci_mem(unsigned long addr)
 {
-       if (addr >= MPC826x_PCI_LOWER_MMIO &&
-           addr <= MPC826x_PCI_UPPER_MMIO)
+       if (addr >= M82xx_PCI_LOWER_MMIO &&
+               addr <= M82xx_PCI_UPPER_MMIO)
                return 1;
-       if (addr >= MPC826x_PCI_LOWER_MEM &&
-           addr <= MPC826x_PCI_UPPER_MEM)
+       if (addr >= M82xx_PCI_LOWER_MEM &&
+               addr <= M82xx_PCI_UPPER_MEM)
                return 1;
        return 0;
 }
index 23ea3f694de2066ec5b324ebedb38b1c027415ce..fda75d79050c3e9201ce7033193645bd74609aec 100644 (file)
@@ -34,7 +34,8 @@
 unsigned char __res[sizeof(bd_t)];
 
 extern void cpm2_reset(void);
-extern void m8260_find_bridges(void);
+extern void pq2_find_bridges(void);
+extern void pq2pci_init_irq(void);
 extern void idma_pci9_init(void);
 
 /* Place-holder for board-specific init */
@@ -56,7 +57,7 @@ m8260_setup_arch(void)
        idma_pci9_init();
 #endif
 #ifdef CONFIG_PCI_8260
-       m8260_find_bridges();
+       pq2_find_bridges();
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start)
@@ -173,6 +174,12 @@ m8260_init_IRQ(void)
         * in case the boot rom changed something on us.
         */
        cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+
+#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
+       /* Initialize stuff for the 82xx CPLD IC and install demux  */
+       pq2pci_init_irq();
+#endif
+
 }
 
 /*
diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
new file mode 100644 (file)
index 0000000..5e7a7ed
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004 Red Hat, Inc.
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+
+#include "m82xx_pci.h"
+
+/*
+ * Interrupt routing
+ */
+
+static inline int
+pq2pci_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+       static char pci_irq_table[][4] =
+       /*
+        *      PCI IDSEL/INTPIN->INTLINE
+        *        A      B      C      D
+        */
+       {
+               { PIRQA, PIRQB, PIRQC, PIRQD }, /* IDSEL 22 - PCI slot 0 */
+               { PIRQD, PIRQA, PIRQB, PIRQC }, /* IDSEL 23 - PCI slot 1 */
+               { PIRQC, PIRQD, PIRQA, PIRQB }, /* IDSEL 24 - PCI slot 2 */
+       };
+
+       const long min_idsel = 22, max_idsel = 24, irqs_per_slot = 4;
+       return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void
+pq2pci_mask_irq(unsigned int irq)
+{
+       int bit = irq - NR_CPM_INTS;
+
+       *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
+       return;
+}
+
+static void
+pq2pci_unmask_irq(unsigned int irq)
+{
+       int bit = irq - NR_CPM_INTS;
+
+       *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
+       return;
+}
+
+static void
+pq2pci_mask_and_ack(unsigned int irq)
+{
+       int bit = irq - NR_CPM_INTS;
+
+       *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
+       return;
+}
+
+static void
+pq2pci_end_irq(unsigned int irq)
+{
+       int bit = irq - NR_CPM_INTS;
+
+       *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
+       return;
+}
+
+struct hw_interrupt_type pq2pci_ic = {
+       "PQ2 PCI",
+       NULL,
+       NULL,
+       pq2pci_unmask_irq,
+       pq2pci_mask_irq,
+       pq2pci_mask_and_ack,
+       pq2pci_end_irq,
+       0
+};
+
+static irqreturn_t
+pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned long stat, mask, pend;
+       int bit;
+
+       for(;;) {
+               stat = *(volatile unsigned long *) PCI_INT_STAT_REG;
+               mask = *(volatile unsigned long *) PCI_INT_MASK_REG;
+               pend = stat & ~mask & 0xf0000000;
+               if (!pend)
+                       break;
+               for (bit = 0; pend != 0; ++bit, pend <<= 1) {
+                       if (pend & 0x80000000)
+                               __do_IRQ(NR_CPM_INTS + bit, regs);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction pq2pci_irqaction = {
+       .handler = pq2pci_irq_demux,
+       .flags   = SA_INTERRUPT,
+       .mask    = CPU_MASK_NONE,
+       .name    = "PQ2 PCI cascade",
+};
+
+
+void
+pq2pci_init_irq(void)
+{
+       int irq;
+       volatile cpm2_map_t *immap = cpm2_immr;
+#if defined CONFIG_ADS8272
+       /* configure chip select for PCI interrupt controller */
+       immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
+       immap->im_memctl.memc_or3 = 0xffff8010;
+#elif defined CONFIG_PQ2FADS
+       immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
+       immap->im_memctl.memc_or8 = 0xffff8010;
+#endif
+       for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
+               irq_desc[irq].handler = &pq2pci_ic;
+
+       /* make PCI IRQ level sensitive */
+       immap->im_intctl.ic_siexr &=
+               ~(1 << (14 - (PCI_INT_TO_SIU - SIU_INT_IRQ1)));
+
+       /* mask all PCI interrupts */
+       *(volatile unsigned long *) PCI_INT_MASK_REG |= 0xfff00000;
+
+       /* install the demultiplexer for the PCI cascade interrupt */
+       setup_irq(PCI_INT_TO_SIU, &pq2pci_irqaction);
+       return;
+}
+
+static int
+pq2pci_exclude_device(u_char bus, u_char devfn)
+{
+       return PCIBIOS_SUCCESSFUL;
+}
+
+/* PCI bus configuration registers.
+ */
+static void
+pq2ads_setup_pci(struct pci_controller *hose)
+{
+       __u32 val;
+       volatile cpm2_map_t *immap = cpm2_immr;
+       bd_t* binfo = (bd_t*) __res;
+       u32 sccr = immap->im_clkrst.car_sccr;
+       uint pci_div,freq,time;
+               /* PCI int lowest prio */
+       /* Each 4 bits is a device bus request  and the MS 4bits
+        is highest priority */
+       /* Bus                4bit value
+          ---                ----------
+          CPM high             0b0000
+          CPM middle           0b0001
+          CPM low              0b0010
+          PCI reguest          0b0011
+          Reserved             0b0100
+          Reserved             0b0101
+          Internal Core        0b0110
+          External Master 1    0b0111
+          External Master 2    0b1000
+          External Master 3    0b1001
+          The rest are reserved
+        */
+       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
+       /* park bus on core */
+       immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_CORE;
+       /*
+        * Set up master windows that allow the CPU to access PCI space. These
+        * windows are set up using the two SIU PCIBR registers.
+        */
+
+       immap->im_memctl.memc_pcimsk0 = M82xx_PCI_PRIM_WND_SIZE;
+       immap->im_memctl.memc_pcibr0  = M82xx_PCI_PRIM_WND_BASE | PCIBR_ENABLE;
+
+#ifdef M82xx_PCI_SEC_WND_SIZE
+       immap->im_memctl.memc_pcimsk1 = M82xx_PCI_SEC_WND_SIZE;
+       immap->im_memctl.memc_pcibr1  = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
+#endif
+
+#if defined CONFIG_ADS8272
+       immap->im_siu_conf.siu_82xx.sc_siumcr =
+               (immap->im_siu_conf.siu_82xx.sc_siumcr &
+               ~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
+               SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
+               SIUMCR_LBPC11 | SIUMCR_APPC11 |
+               SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
+               SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
+               SIUMCR_APPC10 | SIUMCR_CS10PC00 |
+               SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
+
+#elif defined CONFIG_PQ2FADS
+       /*
+        * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+        * and local bus for PCI (SIUMCR [LBPC]).
+        */
+       immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+                               ~(SIUMCR_L2PC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
+                               SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10;
+#endif
+       /* Enable PCI  */
+       immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+
+       pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) *
+                       ( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1);
+       freq = (uint)((2*binfo->bi_cpmfreq)/(pci_div));
+       time = (int)666666/freq;
+       /* due to PCI Local Bus spec, some devices needs to wait such a long
+       time after RST  deassertion. More specifically, 0.508s for 66MHz & twice more for 33 */
+       printk("%s: The PCI bus is %d Mhz.\nWaiting %s after deasserting RST...\n",__FILE__,freq,
+       (time==1) ? "0.5 seconds":"1 second" );
+
+       {
+               int i;
+               for(i=0;i<(500*time);i++)
+                       udelay(1000);
+       }
+
+       /* setup ATU registers */
+       immap->im_pci.pci_pocmr0 = cpu_to_le32(POCMR_ENABLE | POCMR_PCI_IO |
+                               ((~(M82xx_PCI_IO_SIZE - 1U)) >> POTA_ADDR_SHIFT));
+       immap->im_pci.pci_potar0 = cpu_to_le32(M82xx_PCI_LOWER_IO >> POTA_ADDR_SHIFT);
+       immap->im_pci.pci_pobar0 = cpu_to_le32(M82xx_PCI_IO_BASE >> POTA_ADDR_SHIFT);
+
+       /* Set-up non-prefetchable window */
+       immap->im_pci.pci_pocmr1 = cpu_to_le32(POCMR_ENABLE | ((~(M82xx_PCI_MMIO_SIZE-1U)) >> POTA_ADDR_SHIFT));
+       immap->im_pci.pci_potar1 = cpu_to_le32(M82xx_PCI_LOWER_MMIO >> POTA_ADDR_SHIFT);
+       immap->im_pci.pci_pobar1 = cpu_to_le32((M82xx_PCI_LOWER_MMIO - M82xx_PCI_MMIO_OFFSET) >> POTA_ADDR_SHIFT);
+
+       /* Set-up prefetchable window */
+       immap->im_pci.pci_pocmr2 = cpu_to_le32(POCMR_ENABLE |POCMR_PREFETCH_EN |
+               (~(M82xx_PCI_MEM_SIZE-1U) >> POTA_ADDR_SHIFT));
+       immap->im_pci.pci_potar2 = cpu_to_le32(M82xx_PCI_LOWER_MEM >> POTA_ADDR_SHIFT);
+       immap->im_pci.pci_pobar2 = cpu_to_le32((M82xx_PCI_LOWER_MEM - M82xx_PCI_MEM_OFFSET) >> POTA_ADDR_SHIFT);
+
+       /* Inbound transactions from PCI memory space */
+       immap->im_pci.pci_picmr0 = cpu_to_le32(PICMR_ENABLE | PICMR_PREFETCH_EN |
+                                       ((~(M82xx_PCI_SLAVE_MEM_SIZE-1U)) >> PITA_ADDR_SHIFT));
+       immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS  >> PITA_ADDR_SHIFT);
+       immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
+
+#if defined CONFIG_ADS8272
+       /* PCI int highest prio */
+       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
+#elif defined CONFIG_PQ2FADS
+       immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
+#endif
+       /* park bus on PCI */
+       immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+       /* Enable bus mastering and inbound memory transactions */
+       early_read_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, &val);
+       val &= 0xffff0000;
+       val |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
+       early_write_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, val);
+
+}
+
+void __init pq2_find_bridges(void)
+{
+       extern int pci_assign_all_busses;
+       struct pci_controller * hose;
+       int host_bridge;
+
+       pci_assign_all_busses = 1;
+
+       hose = pcibios_alloc_controller();
+
+       if (!hose)
+               return;
+
+       ppc_md.pci_swizzle = common_swizzle;
+
+       hose->first_busno = 0;
+       hose->bus_offset = 0;
+       hose->last_busno = 0xff;
+
+#ifdef CONFIG_ADS8272
+       hose->set_cfg_type = 1;
+#endif
+
+       setup_m8260_indirect_pci(hose,
+                                (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
+                                (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
+
+       /* Make sure it is a supported bridge */
+       early_read_config_dword(hose,
+                               0,
+                               PCI_DEVFN(0,0),
+                               PCI_VENDOR_ID,
+                               &host_bridge);
+       switch (host_bridge) {
+               case PCI_DEVICE_ID_MPC8265:
+                       break;
+               case PCI_DEVICE_ID_MPC8272:
+                       break;
+               default:
+                       printk("Attempting to use unrecognized host bridge ID"
+                               " 0x%08x.\n", host_bridge);
+                       break;
+       }
+
+       pq2ads_setup_pci(hose);
+
+       hose->io_space.start =  M82xx_PCI_LOWER_IO;
+       hose->io_space.end = M82xx_PCI_UPPER_IO;
+       hose->mem_space.start = M82xx_PCI_LOWER_MEM;
+       hose->mem_space.end = M82xx_PCI_UPPER_MMIO;
+       hose->pci_mem_offset = M82xx_PCI_MEM_OFFSET;
+
+       isa_io_base =
+       (unsigned long) ioremap(M82xx_PCI_IO_BASE,
+                                       M82xx_PCI_IO_SIZE);
+       hose->io_base_virt = (void *) isa_io_base;
+
+       /* setup resources */
+       pci_init_resource(&hose->mem_resources[0],
+                       M82xx_PCI_LOWER_MEM,
+                       M82xx_PCI_UPPER_MEM,
+                       IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
+
+       pci_init_resource(&hose->mem_resources[1],
+                       M82xx_PCI_LOWER_MMIO,
+                       M82xx_PCI_UPPER_MMIO,
+                       IORESOURCE_MEM, "PCI memory");
+
+       pci_init_resource(&hose->io_resource,
+                       M82xx_PCI_LOWER_IO,
+                       M82xx_PCI_UPPER_IO,
+                       IORESOURCE_IO | 1, "PCI I/O");
+
+       ppc_md.pci_exclude_device = pq2pci_exclude_device;
+       hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+       ppc_md.pci_map_irq = pq2pci_map_irq;
+       ppc_md.pcibios_fixup = NULL;
+       ppc_md.pcibios_fixup_bus = NULL;
+
+}
diff --git a/arch/ppc/syslib/m82xx_pci.h b/arch/ppc/syslib/m82xx_pci.h
new file mode 100644 (file)
index 0000000..924f73f
--- /dev/null
@@ -0,0 +1,92 @@
+
+#ifndef _PPC_KERNEL_M82XX_PCI_H
+#define _PPC_KERNEL_M82XX_PCI_H
+
+#include <asm/m8260_pci.h>
+/*
+ *   Local->PCI map (from CPU)                             controlled by
+ *   MPC826x master window
+ *
+ *   0xF6000000 - 0xF7FFFFFF    IO space
+ *   0x80000000 - 0xBFFFFFFF    CPU2PCI memory space       PCIBR0
+ *
+ *   0x80000000 - 0x9FFFFFFF    PCI Mem with prefetch      (Outbound ATU #1)
+ *   0xA0000000 - 0xBFFFFFFF    PCI Mem w/o  prefetch      (Outbound ATU #2)
+ *   0xF6000000 - 0xF7FFFFFF    32-bit PCI IO              (Outbound ATU #3)
+ *
+ *   PCI->Local map (from PCI)
+ *   MPC826x slave window                                  controlled by
+ *
+ *   0x00000000 - 0x07FFFFFF    MPC826x local memory       (Inbound ATU #1)
+ */
+
+/*
+ * Slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+#ifndef M82xx_PCI_SLAVE_MEM_LOCAL
+#define M82xx_PCI_SLAVE_MEM_LOCAL      (((struct bd_info *)__res)->bi_memstart)
+#define M82xx_PCI_SLAVE_MEM_BUS                (((struct bd_info *)__res)->bi_memstart)
+#define M82xx_PCI_SLAVE_MEM_SIZE       (((struct bd_info *)__res)->bi_memsize)
+#endif
+
+/*
+ * This is the window that allows the CPU to access PCI address space.
+ * It will be setup with the SIU PCIBR0 register. All three PCI master
+ * windows, which allow the CPU to access PCI prefetch, non prefetch,
+ * and IO space (see below), must all fit within this window.
+ */
+
+#ifndef M82xx_PCI_LOWER_MEM
+#define M82xx_PCI_LOWER_MEM            0x80000000
+#define M82xx_PCI_UPPER_MEM            0x9fffffff
+#define M82xx_PCI_MEM_OFFSET           0x00000000
+#define M82xx_PCI_MEM_SIZE             0x20000000
+#endif
+
+#ifndef M82xx_PCI_LOWER_MMIO
+#define M82xx_PCI_LOWER_MMIO           0xa0000000
+#define M82xx_PCI_UPPER_MMIO           0xafffffff
+#define M82xx_PCI_MMIO_OFFSET          0x00000000
+#define M82xx_PCI_MMIO_SIZE            0x20000000
+#endif
+
+#ifndef M82xx_PCI_LOWER_IO
+#define M82xx_PCI_LOWER_IO             0x00000000
+#define M82xx_PCI_UPPER_IO             0x01ffffff
+#define M82xx_PCI_IO_BASE              0xf6000000
+#define M82xx_PCI_IO_SIZE              0x02000000
+#endif
+
+#ifndef M82xx_PCI_PRIM_WND_SIZE
+#define M82xx_PCI_PRIM_WND_SIZE        ~(M82xx_PCI_IO_SIZE - 1U)
+#define M82xx_PCI_PRIM_WND_BASE                (M82xx_PCI_IO_BASE)
+#endif
+
+#ifndef M82xx_PCI_SEC_WND_SIZE
+#define M82xx_PCI_SEC_WND_SIZE                 ~(M82xx_PCI_MEM_SIZE + M82xx_PCI_MMIO_SIZE - 1U)
+#define M82xx_PCI_SEC_WND_BASE                 (M82xx_PCI_LOWER_MEM)
+#endif
+
+#ifndef POTA_ADDR_SHIFT
+#define POTA_ADDR_SHIFT                12
+#endif
+
+#ifndef PITA_ADDR_SHIFT
+#define PITA_ADDR_SHIFT                12
+#endif
+
+#ifndef _IO_BASE
+#define _IO_BASE isa_io_base
+#endif
+
+#ifdef CONFIG_8260_PCI9
+struct pci_controller;
+extern void setup_m8260_indirect_pci(struct pci_controller* hose,
+                                       u32 cfg_addr, u32 cfg_data);
+#else
+#define setup_m8260_indirect_pci setup_indirect_pci
+#endif
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
index 9d4ed68b580419c5c7e1e0e02509a58e9e29ca60..000ba47c67cbacd5b1bde36148c2fe0328e9db04 100644 (file)
@@ -275,7 +275,7 @@ static void __init openpic_enable_sie(void)
 }
 #endif
 
-#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM)
+#if defined(CONFIG_EPIC_SERIAL_MODE)
 static void openpic_reset(void)
 {
        openpic_setfield(&OpenPIC->Global.Global_Configuration0,
@@ -993,8 +993,6 @@ int openpic_resume(struct sys_device *sysdev)
                return 0;
        }
 
-       openpic_reset();
-
        /* OpenPIC sometimes seem to need some time to be fully back up... */
        do {
                openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
index c28f9d679484f348e18c5409141983be5a7fcfe6..843cf8873e60f35376b80e2cda72839ee99fb35a 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mmu.h>
 #include <asm/ppc_sys.h>
 #include <asm/kgdb.h>
+#include <asm/delay.h>
 
 #include <syslib/ppc83xx_setup.h>
 
@@ -117,7 +118,34 @@ mpc83xx_early_serial_map(void)
 void
 mpc83xx_restart(char *cmd)
 {
+       volatile unsigned char __iomem *reg;
+       unsigned char tmp;
+
+       reg = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+
        local_irq_disable();
+
+       /*
+        * Unlock the BCSR bits so a PRST will update the contents.
+        * Otherwise the reset asserts but doesn't clear.
+        */
+       tmp = in_8(reg + BCSR_MISC_REG3_OFF);
+       tmp |= BCSR_MISC_REG3_CNFLOCK; /* low true, high false */
+       out_8(reg + BCSR_MISC_REG3_OFF, tmp);
+
+       /*
+        * Trigger a reset via a low->high transition of the
+        * PORESET bit.
+        */
+       tmp = in_8(reg + BCSR_MISC_REG2_OFF);
+       tmp &= ~BCSR_MISC_REG2_PORESET;
+       out_8(reg + BCSR_MISC_REG2_OFF, tmp);
+
+       udelay(1);
+
+       tmp |= BCSR_MISC_REG2_PORESET;
+       out_8(reg + BCSR_MISC_REG2_OFF, tmp);
+
        for(;;);
 }
 
index 152c3ef1312aa052072b25d86db7334583c74280..f3277f469e78a2695422189e4a28ba5124878ccd 100644 (file)
@@ -132,6 +132,12 @@ mpc85xx_halt(void)
 }
 
 #ifdef CONFIG_PCI
+
+#if defined(CONFIG_MPC8555_CDS)
+extern void mpc85xx_cds_enable_via(struct pci_controller *hose);
+extern void mpc85xx_cds_fixup_via(struct pci_controller *hose);
+#endif
+
 static void __init
 mpc85xx_setup_pci1(struct pci_controller *hose)
 {
@@ -302,8 +308,18 @@ mpc85xx_setup_hose(void)
 
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 
+#if defined(CONFIG_MPC8555_CDS)
+       /* Pre pciauto_bus_scan VIA init */
+       mpc85xx_cds_enable_via(hose_a);
+#endif
+
        hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
 
+#if defined(CONFIG_MPC8555_CDS)
+       /* Post pciauto_bus_scan VIA fixup */
+       mpc85xx_cds_fixup_via(hose_a);
+#endif
+
 #ifdef CONFIG_85xx_PCI2
        hose_b = pcibios_alloc_controller();
 
index 2cee87137f2efa9b6efff2d25aff5c1915061464..7f15136830f4fbf38fe38e3a5418e85e51e47b96 100644 (file)
@@ -626,8 +626,18 @@ inspect_node(phandle node, struct device_node *dad,
        l = call_prom("package-to-path", 3, 1, node,
                      mem_start, mem_end - mem_start);
        if (l >= 0) {
+               char *p, *ep;
+
                np->full_name = PTRUNRELOC((char *) mem_start);
                *(char *)(mem_start + l) = 0;
+               /* Fixup an Apple bug where they have bogus \0 chars in the
+                * middle of the path in some properties
+                */
+               for (p = (char *)mem_start, ep = p + l; p < ep; p++)
+                       if ((*p) == '\0') {
+                               memmove(p, p+1, ep - p);
+                               ep--;
+                       }
                mem_start = ALIGNUL(mem_start + l + 1);
        }
 
index d3604056e1a9c53d2407243ecb44aa282609363c..b61572eb2a7130d7a46924f8412024b9879286e7 100644 (file)
@@ -436,15 +436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        REST_8GPRS(14, r1)
        REST_10GPRS(22, r1)
 
-#ifdef CONFIG_PPC_ISERIES
-       clrrdi  r7,r1,THREAD_SHIFT      /* get current_thread_info() */
-       ld      r7,TI_FLAGS(r7)         /* Get run light flag */
-       mfspr   r9,CTRLF
-       srdi    r7,r7,TIF_RUN_LIGHT
-       insrdi  r9,r7,1,63              /* Insert run light into CTRL */
-       mtspr   CTRLT,r9
-#endif
-
        /* convert old thread to its task_struct for return value */
        addi    r3,r3,-THREAD
        ld      r7,_NIP(r1)     /* Return to _switch caller in new task */
index 92a744c31ab183b2aec6e4532a593cef614bba13..346dbf606b5dd910e1a3609d315d96a1a830fa00 100644 (file)
@@ -626,10 +626,10 @@ system_reset_iSeries:
        lhz     r24,PACAPACAINDEX(r13)  /* Get processor # */
        cmpwi   0,r24,0                 /* Are we processor 0? */
        beq     .__start_initialization_iSeries /* Start up the first processor */
-       mfspr   r4,CTRLF
-       li      r5,RUNLATCH             /* Turn off the run light */
+       mfspr   r4,SPRN_CTRLF
+       li      r5,CTRL_RUNLATCH        /* Turn off the run light */
        andc    r4,r4,r5
-       mtspr   CTRLT,r4
+       mtspr   SPRN_CTRLT,r4
 
 1:
        HMT_LOW
@@ -2082,9 +2082,9 @@ _GLOBAL(hmt_start_secondary)
        mfspr   r4, HID0
        ori     r4, r4, 0x1
        mtspr   HID0, r4
-       mfspr   r4, CTRLF
+       mfspr   r4, SPRN_CTRLF
        oris    r4, r4, 0x40
-       mtspr   CTRLT, r4
+       mtspr   SPRN_CTRLT, r4
        blr
 #endif
 
index da20120f22617515f554e405d9eaa744288aca57..6d06eb550a3fb839077953caab8d6f82d96afe8a 100644 (file)
@@ -852,6 +852,28 @@ static int __init iSeries_src_init(void)
 
 late_initcall(iSeries_src_init);
 
+static int set_spread_lpevents(char *str)
+{
+       unsigned long i;
+       unsigned long val = simple_strtoul(str, NULL, 0);
+
+       /*
+        * The parameter is the number of processors to share in processing
+        * lp events.
+        */
+       if (( val > 0) && (val <= NR_CPUS)) {
+               for (i = 1; i < val; ++i)
+                       paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
+
+               printk("lpevent processing spread over %ld processors\n", val);
+       } else {
+               printk("invalid spread_lpevents %ld\n", val);
+       }
+
+       return 1;
+}
+__setup("spread_lpevents=", set_spread_lpevents);
+
 void __init iSeries_early_setup(void)
 {
        iSeries_fixup_klimit();
index 6abc621d3ba0ca1fd2f52b934d83faaae4d8d81e..f24ce2b872004ae4feb1f419eddb3c0866c1c440 100644 (file)
@@ -75,13 +75,9 @@ static int iSeries_idle(void)
 {
        struct paca_struct *lpaca;
        long oldval;
-       unsigned long CTRL;
 
        /* ensure iSeries run light will be out when idle */
-       clear_thread_flag(TIF_RUN_LIGHT);
-       CTRL = mfspr(CTRLF);
-       CTRL &= ~RUNLATCH;
-       mtspr(CTRLT, CTRL);
+       ppc64_runlatch_off();
 
        lpaca = get_paca();
 
@@ -111,7 +107,9 @@ static int iSeries_idle(void)
                        }
                }
 
+               ppc64_runlatch_on();
                schedule();
+               ppc64_runlatch_off();
        }
 
        return 0;
index cb5443f2e49b81ba09b70966acf92fd5edcd6aa6..dc2a69d412a204820546107a47ab7c676036a7de 100644 (file)
@@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np)
                remove_proc_entry(pp->name, np->pde);
                pp = pp->next;
        }
-
-       /* Assuming that symlinks have the same parent directory as
-        * np->pde.
-        */
-       if (np->name_link)
-               remove_proc_entry(np->name_link->name, parent->pde);
-       if (np->addr_link)
-               remove_proc_entry(np->addr_link->name, parent->pde);
        if (np->pde)
                remove_proc_entry(np->pde->name, parent->pde);
 }
index 8b06861227385709431ace73498417c448b10e5d..cdfecbeb331f58d586edd4b85aa58212f859d872 100644 (file)
@@ -378,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                childregs->gpr[1] = sp + sizeof(struct pt_regs);
                p->thread.regs = NULL;  /* no user register state */
                clear_ti_thread_flag(p->thread_info, TIF_32BIT);
-#ifdef CONFIG_PPC_ISERIES
-               set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT);
-#endif
        } else {
                childregs->gpr[1] = usp;
                p->thread.regs = childregs;
index 6f79b7b9b445e8669411e34b48c1ea8ce5135965..b7683abfbe6a5f71e8031610ef8cb67dd14a07bd 100644 (file)
@@ -211,13 +211,23 @@ struct {
  */
 #define ADDR(x)                (u32) ((unsigned long)(x) - offset)
 
+/*
+ * Error results ... some OF calls will return "-1" on error, some
+ * will return 0, some will return either. To simplify, here are
+ * macros to use with any ihandle or phandle return value to check if
+ * it is valid
+ */
+
+#define PROM_ERROR             (-1u)
+#define PHANDLE_VALID(p)       ((p) != 0 && (p) != PROM_ERROR)
+#define IHANDLE_VALID(i)       ((i) != 0 && (i) != PROM_ERROR)
+
+
 /* This is the one and *ONLY* place where we actually call open
  * firmware from, since we need to make sure we're running in 32b
  * mode when we do.  We switch back to 64b mode upon return.
  */
 
-#define PROM_ERROR     (-1)
-
 static int __init call_prom(const char *service, int nargs, int nret, ...)
 {
        int i;
@@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void)
 {
        unsigned long offset = reloc_offset();
        ihandle elfloader;
-       int ret;
 
        elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
        if (elfloader == 0) {
                prom_printf("couldn't open /packages/elf-loader\n");
                return;
        }
-       ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
+       call_prom("call-method", 3, 1, ADDR("process-elf-header"),
                        elfloader, ADDR(&fake_elf));
        call_prom("close", 1, 0, elfloader);
 }
@@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
            base = _ALIGN_UP(base + 0x100000, align)) {
                prom_debug("    trying: 0x%x\n\r", base);
                addr = (unsigned long)prom_claim(base, size, 0);
-               if ((int)addr != PROM_ERROR)
+               if (addr != PROM_ERROR)
                        break;
                addr = 0;
                if (align == 0)
@@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align,
        for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align))  {
                prom_debug("    trying: 0x%x\n\r", base);
                addr = (unsigned long)prom_claim(base, size, 0);
-               if ((int)addr != PROM_ERROR)
+               if (addr != PROM_ERROR)
                        break;
                addr = 0;
        }
@@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void)
 {
        unsigned long offset = reloc_offset();
        struct prom_t *_prom = PTRRELOC(&prom);
-       phandle prom_rtas, rtas_node;
+       phandle rtas_node;
+       ihandle rtas_inst;
        u32 base, entry = 0;
        u32 size = 0;
 
        prom_debug("prom_instantiate_rtas: start...\n");
 
-       prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-       prom_debug("prom_rtas: %x\n", prom_rtas);
-       if (prom_rtas == (phandle) -1)
+       rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+       prom_debug("rtas_node: %x\n", rtas_node);
+       if (!PHANDLE_VALID(rtas_node))
                return;
 
-       prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
+       prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
        if (size == 0)
                return;
 
@@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void)
                prom_printf("RTAS allocation failed !\n");
                return;
        }
-       prom_printf("instantiating rtas at 0x%x", base);
 
-       rtas_node = call_prom("open", 1, 1, ADDR("/rtas"));
-       prom_printf("...");
+       rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
+       if (!IHANDLE_VALID(rtas_inst)) {
+               prom_printf("opening rtas package failed");
+               return;
+       }
+
+       prom_printf("instantiating rtas at 0x%x ...", base);
 
        if (call_prom("call-method", 3, 2,
                      ADDR("instantiate-rtas"),
-                     rtas_node, base) != PROM_ERROR) {
+                     rtas_inst, base) != PROM_ERROR) {
                entry = (long)_prom->args.rets[1];
        }
        if (entry == 0) {
@@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void)
 
        reserve_mem(base, size);
 
-       prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base));
-       prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry));
+       prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
+       prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
 
        prom_debug("rtas base     = 0x%x\n", base);
        prom_debug("rtas entry    = 0x%x\n", entry);
@@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void)
 
                prom_printf("opening PHB %s", path);
                phb_node = call_prom("open", 1, 1, path);
-               if ( (long)phb_node <= 0)
+               if (phb_node == 0)
                        prom_printf("... failed\n");
                else
                        prom_printf("... done\n");
@@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp)
 
        /* get a handle for the stdout device */
        _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
-       if ((long)_prom->chosen <= 0)
+       if (!PHANDLE_VALID(_prom->chosen))
                prom_panic("cannot find chosen"); /* msg won't be printed :( */
 
        /* get device tree root */
        _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
-       if ((long)_prom->root <= 0)
+       if (!PHANDLE_VALID(_prom->root))
                prom_panic("cannot find device tree root"); /* msg won't be printed :( */
 }
 
@@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void)
        }
        /* Default to pSeries. We need to know if we are running LPAR */
        rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-       if (rtas != (phandle) -1) {
-               unsigned long x;
-               x = prom_getproplen(rtas, "ibm,hypertas-functions");
+       if (PHANDLE_VALID(rtas)) {
+               int x = prom_getproplen(rtas, "ibm,hypertas-functions");
                if (x != PROM_ERROR) {
                        prom_printf("Hypertas detected, assuming LPAR !\n");
                        return PLATFORM_PSERIES_LPAR;
@@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void)
                 * leave some room at the end of the path for appending extra
                 * arguments
                 */
-               if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
+               if (call_prom("package-to-path", 3, 1, node, path,
+                             PROM_SCRATCH_SIZE-10) == PROM_ERROR)
                        continue;
                prom_printf("found display   : %s, opening ... ", path);
                
                ih = call_prom("open", 1, 1, path);
-               if (ih == (ihandle)0 || ih == (ihandle)-1) {
+               if (ih == 0) {
                        prom_printf("failed\n");
                        continue;
                }
@@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str)
        return 0;
 }
 
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
 static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
                                         unsigned long *mem_end)
 {
@@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
        /* get and store all property names */
        prev_name = RELOC("");
        for (;;) {
-               
-               /* 32 is max len of name including nul. */
-               namep = make_room(mem_start, mem_end, 32, 1);
-               if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
+               int rc;
+
+               /* 64 is max len of name including nul. */
+               namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
+               rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
+               if (rc != 1) {
                        /* No more nodes: unwind alloc */
                        *mem_start = (unsigned long)namep;
                        break;
@@ -1555,18 +1577,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
        }
 }
 
-/*
- * The Open Firmware 1275 specification states properties must be 31 bytes or
- * less, however not all firmwares obey this. Make it 64 bytes to be safe.
- */
-#define MAX_PROPERTY_NAME 64
-
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                                        unsigned long *mem_end)
 {
        int l, align;
        phandle child;
-       char *namep, *prev_name, *sstart;
+       char *namep, *prev_name, *sstart, *p, *ep;
        unsigned long soff;
        unsigned char *valp;
        unsigned long offset = reloc_offset();
@@ -1588,6 +1604,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                        call_prom("package-to-path", 3, 1, node, namep, l);
                }
                namep[l] = '\0';
+               /* Fixup an Apple bug where they have bogus \0 chars in the
+                * middle of the path in some properties
+                */
+               for (p = namep, ep = namep + l; p < ep; p++)
+                       if (*p == '\0') {
+                               memmove(p, p+1, ep - p);
+                               ep--; l--;
+                       }
                *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
        }
 
@@ -1599,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
        prev_name = RELOC("");
        sstart = (char *)RELOC(dt_string_start);
        for (;;) {
-               if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
+               int rc;
+
+               rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
+               if (rc != 1)
                        break;
 
                /* find string offset */
@@ -1615,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                l = call_prom("getproplen", 2, 1, node, pname);
 
                /* sanity checks */
-               if (l < 0)
+               if (l == PROM_ERROR)
                        continue;
                if (l > MAX_PROPERTY_LENGTH) {
                        prom_printf("WARNING: ignoring large property ");
@@ -1763,17 +1790,18 @@ static void __init fixup_device_tree(void)
 
        /* Some G5s have a missing interrupt definition, fix it up here */
        u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
-       if ((long)u3 <= 0)
+       if (!PHANDLE_VALID(u3))
                return;
        i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
-       if ((long)i2c <= 0)
+       if (!PHANDLE_VALID(i2c))
                return;
        mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
-       if ((long)mpic <= 0)
+       if (!PHANDLE_VALID(mpic))
                return;
 
        /* check if proper rev of u3 */
-       if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+       if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
+           == PROM_ERROR)
                return;
        if (u3_rev != 0x35)
                return;
@@ -1880,6 +1908,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
        prom_setprop(_prom->chosen, "linux,platform",
                     &getprop_rval, sizeof(getprop_rval));
 
+       /*
+        * On pSeries, inform the firmware about our capabilities
+        */
+       if (RELOC(of_platform) & PLATFORM_PSERIES)
+               prom_send_capabilities();
+
        /*
         * On pSeries, copy the CPU hold code
         */
index 21c57f539c29305b1bf7ecef8c8a7a5b72a33046..dce198d39328aefd6541efef430f6a6e71d9ca4f 100644 (file)
@@ -103,11 +103,6 @@ extern void unflatten_device_tree(void);
 
 extern void smp_release_cpus(void);
 
-unsigned long decr_overclock = 1;
-unsigned long decr_overclock_proc0 = 1;
-unsigned long decr_overclock_set = 0;
-unsigned long decr_overclock_proc0_set = 0;
-
 int have_of = 1;
 int boot_cpuid = 0;
 int boot_cpuid_phys = 0;
@@ -1120,64 +1115,15 @@ void ppc64_dump_msg(unsigned int src, const char *msg)
        printk("[dump]%04x %s\n", src, msg);
 }
 
-int set_spread_lpevents( char * str )
-{
-       /* The parameter is the number of processors to share in processing lp events */
-       unsigned long i;
-       unsigned long val = simple_strtoul( str, NULL, 0 );
-       if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
-               for ( i=1; i<val; ++i )
-                       paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
-               printk("lpevent processing spread over %ld processors\n", val);
-       }
-       else
-               printk("invalid spreaqd_lpevents %ld\n", val);
-       return 1;
-}      
-
 /* This should only be called on processor 0 during calibrate decr */
 void setup_default_decr(void)
 {
        struct paca_struct *lpaca = get_paca();
 
-       if ( decr_overclock_set && !decr_overclock_proc0_set )
-               decr_overclock_proc0 = decr_overclock;
-
-       lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;        
+       lpaca->default_decr = tb_ticks_per_jiffy;
        lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
 }
 
-int set_decr_overclock_proc0( char * str )
-{
-       unsigned long val = simple_strtoul( str, NULL, 0 );
-       if ( ( val >= 1 ) && ( val <= 48 ) ) {
-               decr_overclock_proc0_set = 1;
-               decr_overclock_proc0 = val;
-               printk("proc 0 decrementer overclock factor of %ld\n", val);
-       }
-       else
-               printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
-       return 1;
-}
-
-int set_decr_overclock( char * str )
-{
-       unsigned long val = simple_strtoul( str, NULL, 0 );
-       if ( ( val >= 1 ) && ( val <= 48 ) ) {
-               decr_overclock_set = 1;
-               decr_overclock = val;
-               printk("decrementer overclock factor of %ld\n", val);
-       }
-       else
-               printk("invalid decrementer overclock factor of %ld\n", val);
-       return 1;
-
-}
-
-__setup("spread_lpevents=", set_spread_lpevents );
-__setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
-__setup("decr_overclock=", set_decr_overclock );
-
 #ifndef CONFIG_PPC_ISERIES
 /*
  * This function can be used by platforms to "find" legacy serial ports.
index 3b906cd940378086b84d18f2d0b71c70a33308cc..9ef5d36d6b253d38127cc026554e2d0e698f87d5 100644 (file)
@@ -334,7 +334,6 @@ void smp_call_function_interrupt(void)
        }
 }
 
-extern unsigned long decr_overclock;
 extern struct gettimeofday_struct do_gtod;
 
 struct thread_info *current_set[NR_CPUS];
@@ -491,7 +490,7 @@ int __devinit __cpu_up(unsigned int cpu)
        if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
                return -EINVAL;
 
-       paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
+       paca[cpu].default_decr = tb_ticks_per_jiffy;
 
        if (!cpu_has_feature(CPU_FTR_SLB)) {
                void *tmp;
index 0925694c3ce5e7873438ae300075a80d648e7657..c8fa6569b2fd789fc3476a3c5ab86c3bf6b3c203 100644 (file)
@@ -113,7 +113,6 @@ void ppc64_enable_pmcs(void)
 #ifdef CONFIG_PPC_PSERIES
        unsigned long set, reset;
        int ret;
-       unsigned int ctrl;
 #endif /* CONFIG_PPC_PSERIES */
 
        /* Only need to enable them once */
@@ -167,11 +166,8 @@ void ppc64_enable_pmcs(void)
         * On SMT machines we have to set the run latch in the ctrl register
         * in order to make PMC6 spin.
         */
-       if (cpu_has_feature(CPU_FTR_SMT)) {
-               ctrl = mfspr(CTRLF);
-               ctrl |= RUNLATCH;
-               mtspr(CTRLT, ctrl);
-       }
+       if (cpu_has_feature(CPU_FTR_SMT))
+               ppc64_runlatch_on();
 #endif /* CONFIG_PPC_PSERIES */
 }
 
index 3d54745108c788a12099ddeaef929d9985060948..33364a7d2cd2e07dbcdd8567d669da11439b5038 100644 (file)
@@ -325,9 +325,7 @@ int timer_interrupt(struct pt_regs * regs)
 
        irq_enter();
 
-#ifndef CONFIG_PPC_ISERIES
        profile_tick(CPU_PROFILING, regs);
-#endif
 
        lpaca->lppaca.int_dword.fields.decr_int = 0;
 
index 33ca56c90da2637a6e233535239d74131c1b5455..2803bc7c2c798af12fc0d57b701991bc51727995 100644 (file)
@@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
        return NULL;
 }
 
+static int iommu_alloc_ctx(struct pci_iommu *iommu)
+{
+       int lowest = iommu->ctx_lowest_free;
+       int sz = IOMMU_NUM_CTXS - lowest;
+       int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest);
+
+       if (unlikely(n == sz)) {
+               n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1);
+               if (unlikely(n == lowest)) {
+                       printk(KERN_WARNING "IOMMU: Ran out of contexts.\n");
+                       n = 0;
+               }
+       }
+       if (n)
+               __set_bit(n, iommu->ctx_bitmap);
+
+       return n;
+}
+
+static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
+{
+       if (likely(ctx)) {
+               __clear_bit(ctx, iommu->ctx_bitmap);
+               if (ctx < iommu->ctx_lowest_free)
+                       iommu->ctx_lowest_free = ctx;
+       }
+}
+
 /* Allocate and map kernel buffer of size SIZE using consistent mode
  * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
  * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -236,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
        npages = size >> IO_PAGE_SHIFT;
        ctx = 0;
        if (iommu->iommu_ctxflush)
-               ctx = iommu->iommu_cur_ctx++;
+               ctx = iommu_alloc_ctx(iommu);
        first_page = __pa(first_page);
        while (npages--) {
                iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
@@ -317,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
                }
        }
 
+       iommu_free_ctx(iommu, ctx);
+
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        order = get_order(size);
@@ -360,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
        base_paddr = __pa(oaddr & IO_PAGE_MASK);
        ctx = 0;
        if (iommu->iommu_ctxflush)
-               ctx = iommu->iommu_cur_ctx++;
+               ctx = iommu_alloc_ctx(iommu);
        if (strbuf->strbuf_enabled)
                iopte_protection = IOPTE_STREAMING(ctx);
        else
@@ -380,39 +410,53 @@ bad:
        return PCI_DMA_ERROR_CODE;
 }
 
-static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages)
+static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
 {
        int limit;
 
-       PCI_STC_FLUSHFLAG_INIT(strbuf);
        if (strbuf->strbuf_ctxflush &&
            iommu->iommu_ctxflush) {
                unsigned long matchreg, flushreg;
+               u64 val;
 
                flushreg = strbuf->strbuf_ctxflush;
                matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
 
-               limit = 100000;
                pci_iommu_write(flushreg, ctx);
-               for(;;) {
-                       if (((long)pci_iommu_read(matchreg)) >= 0L)
-                               break;
-                       limit--;
-                       if (!limit)
-                               break;
-                       udelay(1);
+               val = pci_iommu_read(matchreg);
+               val &= 0xffff;
+               if (!val)
+                       goto do_flush_sync;
+
+               while (val) {
+                       if (val & 0x1)
+                               pci_iommu_write(flushreg, ctx);
+                       val >>= 1;
                }
-               if (!limit)
+               val = pci_iommu_read(matchreg);
+               if (unlikely(val)) {
                        printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
-                              "timeout vaddr[%08x] ctx[%lx]\n",
-                              vaddr, ctx);
+                              "timeout matchreg[%lx] ctx[%lx]\n",
+                              val, ctx);
+                       goto do_page_flush;
+               }
        } else {
                unsigned long i;
 
+       do_page_flush:
                for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
                        pci_iommu_write(strbuf->strbuf_pflush, vaddr);
        }
 
+do_flush_sync:
+       /* If the device could not have possibly put dirty data into
+        * the streaming cache, no flush-flag synchronization needs
+        * to be performed.
+        */
+       if (direction == PCI_DMA_TODEVICE)
+               return;
+
+       PCI_STC_FLUSHFLAG_INIT(strbuf);
        pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
        (void) pci_iommu_read(iommu->write_complete_reg);
 
@@ -466,7 +510,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
        if (strbuf->strbuf_enabled)
-               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -474,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
        free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
                               npages, ctx);
 
+       iommu_free_ctx(iommu, ctx);
+
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -613,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
        /* Step 4: Choose a context if necessary. */
        ctx = 0;
        if (iommu->iommu_ctxflush)
-               ctx = iommu->iommu_cur_ctx++;
+               ctx = iommu_alloc_ctx(iommu);
 
        /* Step 5: Create the mappings. */
        if (strbuf->strbuf_enabled)
@@ -678,7 +724,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
        if (strbuf->strbuf_enabled)
-               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -686,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
        free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
                               npages, ctx);
 
+       iommu_free_ctx(iommu, ctx);
+
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -724,7 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size
        }
 
        /* Step 2: Kick data out of streaming buffers. */
-       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
@@ -768,7 +816,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
        i--;
        npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
                  - bus_addr) >> IO_PAGE_SHIFT;
-       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
index 3567fa879e1fe7a900e545704ad97593d01cc820..534320ef0db2a43992ac6341df4c444d9ccc2182 100644 (file)
@@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
 
        /* Setup initial software IOMMU state. */
        spin_lock_init(&iommu->lock);
-       iommu->iommu_cur_ctx = 0;
+       iommu->ctx_lowest_free = 1;
 
        /* Register addresses. */
        iommu->iommu_control  = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
index 5525d1ec4af883884404d13b17ddc6deda8379f5..53d333b4a4e809f7ebf48231c46bb5e65af86ec3 100644 (file)
@@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
 
        /* Setup initial software IOMMU state. */
        spin_lock_init(&iommu->lock);
-       iommu->iommu_cur_ctx = 0;
+       iommu->ctx_lowest_free = 1;
 
        /* Register addresses. */
        iommu->iommu_control  = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
index e93fcadc37229f99221d1e7781941e5f00ddf0b1..5753175b94e6c91da7eb7ad91fcf197585bf3c98 100644 (file)
@@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 
        /* Setup initial software IOMMU state. */
        spin_lock_init(&iommu->lock);
-       iommu->iommu_cur_ctx = 0;
+       iommu->ctx_lowest_free = 1;
 
        /* Register addresses, SCHIZO has iommu ctx flushing. */
        iommu->iommu_control  = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
index 76ea6455433f1a7aa89005190b4fe60d56d3aea3..89f5e019f24c02ade1ed11ab0c6ed721de1b4bfd 100644 (file)
@@ -117,17 +117,25 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
 
 #define STRBUF_TAG_VALID       0x02UL
 
-static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction)
 {
        unsigned long n;
        int limit;
 
-       iommu->strbuf_flushflag = 0UL;
        n = npages;
        while (n--)
                upa_writeq(base + (n << IO_PAGE_SHIFT),
                           iommu->strbuf_regs + STRBUF_PFLUSH);
 
+       /* If the device could not have possibly put dirty data into
+        * the streaming cache, no flush-flag synchronization needs
+        * to be performed.
+        */
+       if (direction == SBUS_DMA_TODEVICE)
+               return;
+
+       iommu->strbuf_flushflag = 0UL;
+
        /* Whoopee cushion! */
        upa_writeq(__pa(&iommu->strbuf_flushflag),
                   iommu->strbuf_regs + STRBUF_FSYNC);
@@ -421,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
 
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
-       sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -584,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
        iommu = sdev->bus->iommu;
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
-       sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -596,7 +604,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
        size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
 
        spin_lock_irqsave(&iommu->lock, flags);
-       sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -620,7 +628,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
        size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
index b89989de364d1dbe650e988c5ec009b73acc5ba0..bd41e4286d0d4b743fafc74a993f167c7cac0955 100644 (file)
@@ -2,10 +2,6 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
-config FRAME_POINTER
-       bool
-       default y if DEBUG_INFO
-
 config PT_PROXY
        bool "Enable ptrace proxy"
        depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
index d43e9fab05a769db0dfa53f84aa93527732a6155..f9e22198e011c911c7c2f1d36a1b8da742c2325e 100644 (file)
@@ -1,5 +1,10 @@
-/* Much of this ripped from hw_random.c */
-
+/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
+/* Much of this ripped from drivers/char/hw_random.c, see there for other
+ * copyright.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
@@ -12,8 +17,6 @@
  */
 #define RNG_VERSION "1.0.0"
 #define RNG_MODULE_NAME "random"
-#define RNG_DRIVER_NAME   RNG_MODULE_NAME " virtual driver " RNG_VERSION
-#define PFX RNG_MODULE_NAME ": "
 
 #define RNG_MISCDEV_MINOR              183 /* official */
 
@@ -98,7 +101,7 @@ static int __init rng_init (void)
 
        err = misc_register (&rng_miscdev);
        if (err) {
-               printk (KERN_ERR PFX "misc device register failed\n");
+               printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
                goto err_out_cleanup_hw;
        }
 
@@ -120,3 +123,6 @@ static void __exit rng_cleanup (void)
 
 module_init (rng_init);
 module_exit (rng_cleanup);
+
+MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL");
index a2bac429f3d41d8b1941969318b2831fc3750567..b32a77010fbe5743aace38839dcf21f477c7da25 100644 (file)
@@ -22,7 +22,6 @@
 #include "init.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
-#include "2_5compat.h"
 
 static int ssl_version = 1;
 
index 361d0be342b3e68c717802ac0b3fa2dae4d10c0d..afbe1e71ed8310f36b2be4f8f633b61ca84af0a2 100644 (file)
@@ -28,7 +28,6 @@
 #include "irq_user.h"
 #include "mconsole_kern.h"
 #include "init.h"
-#include "2_5compat.h"
 
 #define MAX_TTYS (16)
 
index 88f956c34fedb0cf9b58e618ccb4b8c0e427a8c3..2a7f6892c55c203d66c03640acdccb8a3655b8e3 100644 (file)
@@ -49,7 +49,6 @@
 #include "irq_user.h"
 #include "irq_kern.h"
 #include "ubd_user.h"
-#include "2_5compat.h"
 #include "os.h"
 #include "mem.h"
 #include "mem_kern.h"
@@ -440,9 +439,9 @@ static int udb_setup(char *str)
 __setup("udb", udb_setup);
 __uml_help(udb_setup,
 "udb\n"
-"    This option is here solely to catch ubd -> udb typos, which can be\n\n"
-"    to impossible to catch visually unless you specifically look for\n\n"
-"    them.  The only result of any option starting with 'udb' is an error\n\n"
+"    This option is here solely to catch ubd -> udb typos, which can be\n"
+"    to impossible to catch visually unless you specifically look for\n"
+"    them.  The only result of any option starting with 'udb' is an error\n"
 "    in the boot output.\n\n"
 );
 
diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h
deleted file mode 100644 (file)
index abdb015..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* 
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __2_5_COMPAT_H__
-#define __2_5_COMPAT_H__
-
-#define INIT_HARDSECT(arr, maj, sizes)
-
-#define SET_PRI(task) do ; while(0)
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 2ce9423460b3858f5fc68db67d2fc1d85b90d865..c8d332b56b98b636adb113eef91ec1372cef2a92 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __UM_SYSRQ_H
 #define __UM_SYSRQ_H
 
-extern void show_trace(unsigned long *stack);
+struct task_struct;
+extern void show_trace(struct task_struct* task, unsigned long *stack);
 
 #endif
index 49ddabe69be74e3db30641cad223f90610896b10..efd222ffe20e1df22fa2e04a4c61cdd5d6a3a419 100644 (file)
@@ -16,7 +16,6 @@
 #include "kern.h"
 #include "irq_user.h"
 #include "tlb.h"
-#include "2_5compat.h"
 #include "os.h"
 #include "time_user.h"
 #include "choose-mode.h"
diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd_kern.c
deleted file mode 100644 (file)
index fc568af..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/init.h"
-#include "linux/bootmem.h"
-#include "linux/initrd.h"
-#include "asm/types.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "initrd.h"
-#include "init.h"
-#include "os.h"
-
-/* Changed by uml_initrd_setup, which is a setup */
-static char *initrd __initdata = NULL;
-
-static int __init read_initrd(void)
-{
-       void *area;
-       long long size;
-       int err;
-
-       if(initrd == NULL) return 0;
-       err = os_file_size(initrd, &size);
-       if(err) return 0;
-       area = alloc_bootmem(size);
-       if(area == NULL) return 0;
-       if(load_initrd(initrd, area, size) == -1) return 0;
-       initrd_start = (unsigned long) area;
-       initrd_end = initrd_start + size;
-       return 0;
-}
-
-__uml_postsetup(read_initrd);
-
-static int __init uml_initrd_setup(char *line, int *add)
-{
-       initrd = line;
-       return 0;
-}
-
-__uml_setup("initrd=", uml_initrd_setup, 
-"initrd=<initrd image>\n"
-"    This is used to boot UML from an initrd image.  The argument is the\n"
-"    name of the file containing the image.\n\n"
-);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c
deleted file mode 100644 (file)
index cb90681..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "initrd.h"
-#include "os.h"
-
-int load_initrd(char *filename, void *buf, int size)
-{
-       int fd, n;
-
-       fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
-       if(fd < 0){
-               printk("Opening '%s' failed - err = %d\n", filename, -fd);
-               return(-1);
-       }
-       n = os_read_file(fd, buf, size);
-       if(n != size){
-               printk("Read of %d bytes from '%s' failed, err = %d\n", size,
-                      filename, -n);
-               return(-1);
-       }
-
-       os_close_file(fd);
-       return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index a17c49703f9bd2513af8eef1eae001dc4fd11a52..e42e6364ca130a957c67f066f1779d1d040571a2 100644 (file)
@@ -71,7 +71,7 @@ static __init void do_uml_initcalls(void)
 
 static void last_ditch_exit(int sig)
 {
-       CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
+        kmalloc_ok = 0;
        signal(SIGINT, SIG_DFL);
        signal(SIGTERM, SIG_DFL);
        signal(SIGHUP, SIG_DFL);
@@ -87,7 +87,7 @@ int main(int argc, char **argv, char **envp)
 {
        char **new_argv;
        sigset_t mask;
-       int ret, i;
+       int ret, i, err;
 
        /* Enable all signals except SIGIO - in some environments, we can
         * enter with some signals blocked
@@ -160,27 +160,29 @@ int main(int argc, char **argv, char **envp)
         */
        change_sig(SIGPROF, 0);
 
-       /* Reboot */
-       if(ret){
-               int err;
-
-               printf("\n");
+        /* This signal stuff used to be in the reboot case.  However,
+         * sometimes a SIGVTALRM can come in when we're halting (reproducably
+         * when writing out gcov information, presumably because that takes
+         * some time) and cause a segfault.
+         */
 
-               /* stop timers and set SIG*ALRM to be ignored */
-               disable_timer();
+        /* stop timers and set SIG*ALRM to be ignored */
+        disable_timer();
 
-               /* disable SIGIO for the fds and set SIGIO to be ignored */
-               err = deactivate_all_fds();
-               if(err)
-                       printf("deactivate_all_fds failed, errno = %d\n",
-                              -err);
+        /* disable SIGIO for the fds and set SIGIO to be ignored */
+        err = deactivate_all_fds();
+        if(err)
+                printf("deactivate_all_fds failed, errno = %d\n", -err);
 
-               /* Let any pending signals fire now.  This ensures
-                * that they won't be delivered after the exec, when
-                * they are definitely not expected.
-                */
-               unblock_signals();
+        /* Let any pending signals fire now.  This ensures
+         * that they won't be delivered after the exec, when
+         * they are definitely not expected.
+         */
+        unblock_signals();
 
+       /* Reboot */
+       if(ret){
+               printf("\n");
                execvp(new_argv[0], new_argv);
                perror("Failed to exec kernel");
                ret = 1;
index c1adf7ba3fd16aaece7fc79a4b7afde720786316..804c6bbdf67c157e5e28b6a9be9a76c9d8c0ce04 100644 (file)
@@ -43,7 +43,6 @@
 #include "tlb.h"
 #include "frame_kern.h"
 #include "sigcontext.h"
-#include "2_5compat.h"
 #include "os.h"
 #include "mode.h"
 #include "mode_kern.h"
  */
 struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
 
-struct task_struct *get_task(int pid, int require)
-{
-        struct task_struct *ret;
-
-        read_lock(&tasklist_lock);
-       ret = find_task_by_pid(pid);
-        read_unlock(&tasklist_lock);
-
-        if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
-        return(ret);
-}
-
 int external_pid(void *t)
 {
        struct task_struct *task = t ? t : current;
@@ -189,7 +176,6 @@ void default_idle(void)
 
        while(1){
                /* endless idle loop with no priority at all */
-               SET_PRI(current);
 
                /*
                 * although we are an idle CPU, we do not want to
@@ -212,11 +198,6 @@ int page_size(void)
        return(PAGE_SIZE);
 }
 
-unsigned long page_mask(void)
-{
-       return(PAGE_MASK);
-}
-
 void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 
                      pte_t *pte_out)
 {
@@ -349,11 +330,6 @@ char *uml_strdup(char *string)
        return(new);
 }
 
-void *get_init_task(void)
-{
-       return(&init_thread_union.thread_info.task);
-}
-
 int copy_to_user_proc(void __user *to, void *from, int size)
 {
        return(copy_to_user(to, from, size));
@@ -480,15 +456,3 @@ unsigned long arch_align_stack(unsigned long sp)
        return sp & ~0xf;
 }
 #endif
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 2925e15324de370b29689b9587cc6311d95f935a..71af4d5038994014f12e5030dd3187bcbaae9450 100644 (file)
@@ -322,11 +322,9 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
                                            UPT_SYSCALL_ARG2(regs),
                                            UPT_SYSCALL_ARG3(regs),
                                            UPT_SYSCALL_ARG4(regs));
-               else {
-                        int res = UPT_SYSCALL_RET(regs);
-                       audit_syscall_exit(current, AUDITSC_RESULT(res),
-                                           res);
-                }
+               else audit_syscall_exit(current,
+                                        AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
+                                        UPT_SYSCALL_RET(regs));
        }
 
        /* Fake a debug trap */
@@ -356,14 +354,3 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
                current->exit_code = 0;
        }
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index e630438f9e73ee7d28c9101037a56a0c0a48bc9e..f80850091e798c1eab0ad3f820cdf21350cf22b3 100644 (file)
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/config.h"
 #include "linux/sched.h"
 #include "linux/kernel.h"
 #include "linux/module.h"
 #include "sysrq.h"
 #include "user_util.h"
 
-void show_trace(unsigned long * stack)
+/* Catch non-i386 SUBARCH's. */
+#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
+void show_trace(struct task_struct *task, unsigned long * stack)
 {
-       /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from
-        * arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/
         unsigned long addr;
 
         if (!stack) {
-                stack = (unsigned long*) &stack;
+               stack = (unsigned long*) &stack;
                WARN_ON(1);
        }
 
@@ -35,6 +36,7 @@ void show_trace(unsigned long * stack)
         }
         printk("\n");
 }
+#endif
 
 /*
  * stack dumps generator - this is used by arch-independent code.
@@ -44,7 +46,7 @@ void dump_stack(void)
 {
        unsigned long stack;
 
-       show_trace(&stack);
+       show_trace(current, &stack);
 }
 EXPORT_SYMBOL(dump_stack);
 
@@ -59,7 +61,11 @@ void show_stack(struct task_struct *task, unsigned long *esp)
        int i;
 
        if (esp == NULL) {
-               if (task != current) {
+               if (task != current && task != NULL) {
+                       /* XXX: Isn't this bogus? I.e. isn't this the
+                        * *userspace* stack of this task? If not so, use this
+                        * even when task == current (as in i386).
+                        */
                        esp = (unsigned long *) KSTK_ESP(task);
                        /* Which one? No actual difference - just coding style.*/
                        //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs);
@@ -77,5 +83,6 @@ void show_stack(struct task_struct *task, unsigned long *esp)
                printk("%08lx ", *stack++);
        }
 
-       show_trace(esp);
+       printk("Call Trace: \n");
+       show_trace(current, esp);
 }
index 1de22d8a313a0d7ad158952ca2077fd15e5a305f..c20aef120598ddb071f6362ca8868ecdc8373eca 100644 (file)
@@ -23,7 +23,6 @@
 #include "kern.h"
 #include "chan_kern.h"
 #include "mconsole_kern.h"
-#include "2_5compat.h"
 #include "mem.h"
 #include "mem_kern.h"
 
index df810ca8fc1204a1c48c1c05e6f3c93d945fbb9c..776310fd5b8b7e34d4b651b5fd2216a27b0a8935 100644 (file)
@@ -32,10 +32,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
        unsigned long flags;
        int err, vtalrm, alrm, prof, cpu;
        char c;
-       /* jailing and SMP are incompatible, so this doesn't need to be 
-        * made per-cpu 
-        */
-       static int reading;
 
        from = prev;
        to = next;
@@ -59,13 +55,11 @@ void *switch_to_tt(void *prev, void *next, void *last)
        c = 0;
        set_current(to);
 
-       reading = 0;
        err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
        if(err != sizeof(c))
                panic("write of switch_pipe failed, err = %d", -err);
 
-       reading = 1;
-        if(from->thread.mode.tt.switch_pipe[0] == -1)
+       if(from->thread.mode.tt.switch_pipe[0] == -1)
                os_kill_process(os_getpid(), 0);
 
        err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
index 4d10ec372a678a28124428f128d7b3b822b84d9f..418427107b2936b5cdc880aa113fb8f640367d0f 100644 (file)
@@ -111,12 +111,6 @@ struct seq_operations cpuinfo_op = {
        .show   = show_cpuinfo,
 };
 
-pte_t * __bad_pagetable(void)
-{
-       panic("Someone should implement __bad_pagetable");
-       return(NULL);
-}
-
 /* Set in linux_main */
 unsigned long host_task_size;
 unsigned long task_size;
index 281fc7b8ca00bbdfa9a9a892803e0365c600c3ec..e3706d15c4f51bfefe364ee37c45c5fe99375c12 100644 (file)
@@ -3,12 +3,15 @@
  * Licensed under the GPL
  */
 
+#include "linux/config.h"
 #include "linux/kernel.h"
 #include "linux/smp.h"
 #include "linux/sched.h"
+#include "linux/kallsyms.h"
 #include "asm/ptrace.h"
 #include "sysrq.h"
 
+/* This is declared by <linux/sched.h> */
 void show_regs(struct pt_regs *regs)
 {
         printk("\n");
@@ -31,5 +34,80 @@ void show_regs(struct pt_regs *regs)
               0xffff & PT_REGS_DS(regs), 
               0xffff & PT_REGS_ES(regs));
 
-        show_trace((unsigned long *) &regs);
+        show_trace(NULL, (unsigned long *) &regs);
 }
+
+/* Copied from i386. */
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+       return  p > (void *)tinfo &&
+               p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+/* Adapted from i386 (we also print the address we read from). */
+static inline unsigned long print_context_stack(struct thread_info *tinfo,
+                               unsigned long *stack, unsigned long ebp)
+{
+       unsigned long addr;
+
+#ifdef CONFIG_FRAME_POINTER
+       while (valid_stack_ptr(tinfo, (void *)ebp)) {
+               addr = *(unsigned long *)(ebp + 4);
+               printk("%08lx:  [<%08lx>]", ebp + 4, addr);
+               print_symbol(" %s", addr);
+               printk("\n");
+               ebp = *(unsigned long *)ebp;
+       }
+#else
+       while (valid_stack_ptr(tinfo, stack)) {
+               addr = *stack;
+               if (__kernel_text_address(addr)) {
+                       printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
+                       print_symbol(" %s", addr);
+                       printk("\n");
+               }
+               stack++;
+       }
+#endif
+       return ebp;
+}
+
+void show_trace(struct task_struct* task, unsigned long * stack)
+{
+       unsigned long ebp;
+       struct thread_info *context;
+
+       /* Turn this into BUG_ON if possible. */
+       if (!stack) {
+               stack = (unsigned long*) &stack;
+               printk("show_trace: got NULL stack, implicit assumption task == current");
+               WARN_ON(1);
+       }
+
+       if (!task)
+               task = current;
+
+       if (task != current) {
+               //ebp = (unsigned long) KSTK_EBP(task);
+               /* Which one? No actual difference - just coding style.*/
+               ebp = (unsigned long) PT_REGS_EBP(&task->thread.regs);
+       } else {
+               asm ("movl %%ebp, %0" : "=r" (ebp) : );
+       }
+
+       context = (struct thread_info *)
+               ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+       print_context_stack(context, stack, ebp);
+
+       /*while (((long) stack & (THREAD_SIZE-1)) != 0) {
+               addr = *stack;
+               if (__kernel_text_address(addr)) {
+                       printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
+                       print_symbol(" %s", addr);
+                       printk("\n");
+               }
+               stack++;
+       }*/
+       printk("\n");
+}
+
index 82d6e9335bb6bc9c8614c3e10c55e95e68516efa..2f816f1a0ff4d3ceae814f81e8aedd107b955430 100644 (file)
@@ -27,17 +27,5 @@ void show_regs(struct pt_regs_subarch *regs)
                 0xffff & regs->xds, 0xffff & regs->xes);
 #endif
 
-        show_trace(&regs->gpr[1]);
+        show_trace(current, &regs->gpr[1]);
 }
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index d4a59657fb99c4601a40ff61b455e81d9e5afc2d..6f44f40204ed0947ffe93f6358a0a517649b6fd8 100644 (file)
@@ -133,23 +133,27 @@ static long arch_prctl_tt(int code, unsigned long addr)
 
 #ifdef CONFIG_MODE_SKAS
 
+/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
 static long arch_prctl_skas(int code, unsigned long addr)
 {
        long ret = 0;
 
        switch(code){
-       case ARCH_SET_GS:
-               current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
-               break;
        case ARCH_SET_FS:
                current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
                break;
+       case ARCH_SET_GS:
+               current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
+               break;
        case ARCH_GET_FS:
-               ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr);
+               ret = put_user(current->thread.regs.regs.skas.
+                               regs[FS_BASE / sizeof(unsigned long)],
+                               (unsigned long __user *)addr);
                break;
        case ARCH_GET_GS:
-               ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \
-long)], &addr);
+               ret = put_user(current->thread.regs.regs.skas.
+                               regs[GS_BASE / sizeof(unsigned long)],
+                               (unsigned long __user *)addr);
                break;
        default:
                ret = -EINVAL;
index ddf74691a6109cfb406123c01354cf6b20cd9a15..d0a25af19a5bd216dc2995807fb0ed410238b44e 100644 (file)
@@ -36,14 +36,5 @@ void __show_regs(struct pt_regs * regs)
 void show_regs(struct pt_regs *regs)
 {
        __show_regs(regs);
-       show_trace((unsigned long *) &regs);
+       show_trace(current, (unsigned long *) &regs);
 }
-
-/* Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 0f430d9d363220232a0980de9e936294963c770d..289f448ac89cc426dcb5fdb4d23aaf8bef7988bb 100644 (file)
@@ -305,6 +305,7 @@ config HPET_TIMER
 
 config X86_PM_TIMER
        bool "PM timer"
+       depends on ACPI
        default y
        help
          Support the ACPI PM timer for time keeping. This is slow,
index 80e9b498c44343b4683e3cc0d79e4f2b42e8f727..afd87e64d0a870c43eaab0a6a99882c9d1c12281 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/desc.h>
 #include <asm/proto.h>
 #include <asm/mach_apic.h>
+#include <asm/acpi.h>
 
 #define __apicdebuginit  __init
 
index f86d9db94bfcc437b378fc32024d603c449cfdf1..61a63be6b294adf3f0716ad8bcd27c13b7028c36 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/pgalloc.h>
 #include <asm/io_apic.h>
 #include <asm/proto.h>
+#include <asm/acpi.h>
 
 /* Have we found an MP table */
 int smp_found_config;
index 3fdcdba0fec5f8ebf758170f4a62b1d3f41135e8..429c0269dc4e300abcf8efcb3c7a806c7ffb86a6 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/i387.h>
 #include <asm/proto.h>
+#include <asm/ia32_unistd.h>
 
 /* #define DEBUG_SIG 1 */
 
index 735b6767c8ed78eda64acda6cba265cbfc8df44e..fb8c809b4cd94fb817b7d04b6db140423e80cf30 100644 (file)
@@ -27,7 +27,9 @@
 #include <linux/bcd.h>
 #include <linux/kallsyms.h>
 #include <linux/acpi.h>
+#ifdef CONFIG_ACPI
 #include <acpi/achware.h>      /* for PM timer frequency */
+#endif
 #include <asm/8253pit.h>
 #include <asm/pgtable.h>
 #include <asm/vsyscall.h>
index d1dcd8eae3c901c3bacb00f08875ebb770141e44..5b77188527a9ad91f8d3f70691ba9c2d4393f4a1 100644 (file)
@@ -39,7 +39,8 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
   fore_200e-objs               += fore200e_pca_fw.o
   # guess the target endianess to choose the right PCA-200E firmware image
   ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
-    CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo $(obj)/pca200e.bin; else echo $(obj)/pca200e_ecd.bin2; fi)
+    byteorder.h                        := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
+    CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
   endif
 endif
 
index 9e65bfb85ba325285f299dcaf82388146bcafebb..5f702199543ac043eec3905b6231e119e421ba7c 100644 (file)
@@ -383,8 +383,7 @@ fore200e_shutdown(struct fore200e* fore200e)
     switch(fore200e->state) {
 
     case FORE200E_STATE_COMPLETE:
-       if (fore200e->stats)
-           kfree(fore200e->stats);
+       kfree(fore200e->stats);
 
     case FORE200E_STATE_IRQ:
        free_irq(fore200e->irq, fore200e->atm_dev);
@@ -963,8 +962,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
                entry, txq->tail, entry->vc_map, entry->skb);
 
        /* free copy of misaligned data */
-       if (entry->data)
-           kfree(entry->data);
+       kfree(entry->data);
        
        /* remove DMA mapping */
        fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
index 3022c548a132317e4b8c9334b0cd520b63bde32e..df2c83fd5496015ac64025ea9762e90e80c5093f 100644 (file)
@@ -412,8 +412,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
 init_one_failure:
        if (atm_dev)
                atm_dev_deregister(atm_dev);
-       if (he_dev)
-               kfree(he_dev);
+       kfree(he_dev);
        pci_disable_device(pci_dev);
        return err;
 }
@@ -2534,8 +2533,7 @@ he_open(struct atm_vcc *vcc)
 open_failed:
 
        if (err) {
-               if (he_vcc)
-                       kfree(he_vcc);
+               kfree(he_vcc);
                clear_bit(ATM_VF_ADDR, &vcc->flags);
        }
        else
index 85bf5c8442b000917465b56fb9ce12d2b0e68a14..b2a7b754fd1403a4c7dbd4ffe5ab47cd3de70b5e 100644 (file)
@@ -676,10 +676,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
    PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base);
       
    /* Initialize SCQ0, the only VBR SCQ used */
-   card->scq1 = (scq_info *) NULL;
-   card->scq2 = (scq_info *) NULL;
+   card->scq1 = NULL;
+   card->scq2 = NULL;
    card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);
-   if (card->scq0 == (scq_info *) NULL)
+   if (card->scq0 == NULL)
    {
       printk("nicstar%d: can't get SCQ0.\n", i);
       error = 12;
@@ -993,24 +993,24 @@ static scq_info *get_scq(int size, u32 scd)
    int i;
 
    if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
-      return (scq_info *) NULL;
+      return NULL;
 
    scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
-   if (scq == (scq_info *) NULL)
-      return (scq_info *) NULL;
+   if (scq == NULL)
+      return NULL;
    scq->org = kmalloc(2 * size, GFP_KERNEL);
    if (scq->org == NULL)
    {
       kfree(scq);
-      return (scq_info *) NULL;
+      return NULL;
    }
    scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
                                           (size / NS_SCQE_SIZE), GFP_KERNEL);
-   if (scq->skb == (struct sk_buff **) NULL)
+   if (scq->skb == NULL)
    {
       kfree(scq->org);
       kfree(scq);
-      return (scq_info *) NULL;
+      return NULL;
    }
    scq->num_entries = size / NS_SCQE_SIZE;
    scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size);
@@ -1498,7 +1498,7 @@ static int ns_open(struct atm_vcc *vcc)
          vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
 
          scq = get_scq(CBR_SCQSIZE, vc->cbr_scd);
-         if (scq == (scq_info *) NULL)
+         if (scq == NULL)
          {
             PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);
             card->scd2vc[frscdi] = NULL;
index 47a800519ad01ed87638b329f1fd4a1213c6a641..8d5e65cb975528203ebb5b951044d9eaf73c91ad 100644 (file)
@@ -902,7 +902,7 @@ static void close_tx(struct atm_vcc *vcc)
                zatm_dev->tx_bw += vcc->qos.txtp.min_pcr;
                dealloc_shaper(vcc->dev,zatm_vcc->shaper);
        }
-       if (zatm_vcc->ring) kfree(zatm_vcc->ring);
+       kfree(zatm_vcc->ring);
 }
 
 
@@ -1339,12 +1339,9 @@ static int __init zatm_start(struct atm_dev *dev)
        return 0;
     out:
        for (i = 0; i < NR_MBX; i++)
-               if (zatm_dev->mbx_start[i] != 0)
-                       kfree((void *) zatm_dev->mbx_start[i]);
-       if (zatm_dev->rx_map != NULL)
-               kfree(zatm_dev->rx_map);
-       if (zatm_dev->tx_map != NULL)
-               kfree(zatm_dev->tx_map);
+               kfree(zatm_dev->mbx_start[i]);
+       kfree(zatm_dev->rx_map);
+       kfree(zatm_dev->tx_map);
        free_irq(zatm_dev->irq, dev);
        return error;
 }
index ce42889f98fbdac287a2af1d50a8c66346a5433a..adc4dcc306f4225f850c24cfe4916e60b2b6f372 100644 (file)
@@ -8,13 +8,12 @@
  * and is not licensed separately. See file COPYING for details.
  *
  * TODO (sorted by decreasing priority)
+ *  -- Kill first_open (Al Viro fixed the block layer now)
  *  -- Do resets with usb_device_reset (needs a thread context, use khubd)
  *  -- set readonly flag for CDs, set removable flag for CF readers
  *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
- *  -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...)
  *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
  *  -- verify the 13 conditions and do bulk resets
- *  -- normal pool of commands instead of cmdv[]?
  *  -- kill last_pipe and simply do two-state clearing on both pipes
  *  -- verify protocol (bulk) from USB descriptors (maybe...)
  *  -- highmem and sg
 #define US_SC_SCSI     0x06            /* Transparent */
 
 /*
+ * This many LUNs per USB device.
+ * Every one of them takes a host, see UB_MAX_HOSTS.
  */
+#define UB_MAX_LUNS   4
+
+/*
+ */
+
 #define UB_MINORS_PER_MAJOR    8
 
 #define UB_MAX_CDB_SIZE      16                /* Corresponds to Bulk */
@@ -65,7 +71,7 @@ struct bulk_cb_wrap {
        u32     Tag;                    /* unique per command id */
        __le32  DataTransferLength;     /* size of data */
        u8      Flags;                  /* direction in bit 0 */
-       u8      Lun;                    /* LUN normally 0 */
+       u8      Lun;                    /* LUN */
        u8      Length;                 /* of of the CDB */
        u8      CDB[UB_MAX_CDB_SIZE];   /* max command */
 };
@@ -168,6 +174,7 @@ struct ub_scsi_cmd {
        unsigned int len;               /* Requested length */
        // struct scatterlist sgv[UB_MAX_REQ_SG];
 
+       struct ub_lun *lun;
        void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
        void *back;
 };
@@ -252,25 +259,47 @@ struct ub_scsi_cmd_queue {
 };
 
 /*
- * The UB device instance.
+ * The block device instance (one per LUN).
+ */
+struct ub_lun {
+       struct ub_dev *udev;
+       struct list_head link;
+       struct gendisk *disk;
+       int id;                         /* Host index */
+       int num;                        /* LUN number */
+       char name[16];
+
+       int changed;                    /* Media was changed */
+       int removable;
+       int readonly;
+       int first_open;                 /* Kludge. See ub_bd_open. */
+
+       /* Use Ingo's mempool if or when we have more than one command. */
+       /*
+        * Currently we never need more than one command for the whole device.
+        * However, giving every LUN a command is a cheap and automatic way
+        * to enforce fairness between them.
+        */
+       int cmda[1];
+       struct ub_scsi_cmd cmdv[1];
+
+       struct ub_capacity capacity; 
+};
+
+/*
+ * The USB device instance.
  */
 struct ub_dev {
        spinlock_t lock;
-       int id;                         /* Number among ub's */
        atomic_t poison;                /* The USB device is disconnected */
        int openc;                      /* protected by ub_lock! */
                                        /* kref is too implicit for our taste */
        unsigned int tagcnt;
-       int changed;                    /* Media was changed */
-       int removable;
-       int readonly;
-       int first_open;                 /* Kludge. See ub_bd_open. */
-       char name[8];
+       char name[12];
        struct usb_device *dev;
        struct usb_interface *intf;
 
-       struct ub_capacity capacity; 
-       struct gendisk *disk;
+       struct list_head luns;
 
        unsigned int send_bulk_pipe;    /* cached pipe values */
        unsigned int recv_bulk_pipe;
@@ -279,10 +308,6 @@ struct ub_dev {
 
        struct tasklet_struct tasklet;
 
-       /* XXX Use Ingo's mempool (once we have more than one) */
-       int cmda[1];
-       struct ub_scsi_cmd cmdv[1];
-
        struct ub_scsi_cmd_queue cmd_queue;
        struct ub_scsi_cmd top_rqs_cmd; /* REQUEST SENSE */
        unsigned char top_sense[UB_SENSE_SIZE];
@@ -301,9 +326,9 @@ struct ub_dev {
 /*
  */
 static void ub_cleanup(struct ub_dev *sc);
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
-    struct request *rq);
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq);
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct request *rq);
 static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     struct request *rq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -320,8 +345,10 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     int stalled_pipe);
 static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static int ub_sync_tur(struct ub_dev *sc);
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_capacity *ret);
+static int ub_probe_lun(struct ub_dev *sc, int lnum);
 
 /*
  */
@@ -342,6 +369,7 @@ MODULE_DEVICE_TABLE(usb, ub_usb_ids);
  */
 #define UB_MAX_HOSTS  26
 static char ub_hostv[UB_MAX_HOSTS];
+
 static DEFINE_SPINLOCK(ub_lock);       /* Locks globals and ->openc */
 
 /*
@@ -406,6 +434,8 @@ static ssize_t ub_diag_show(struct device *dev, char *page)
 {
        struct usb_interface *intf;
        struct ub_dev *sc;
+       struct list_head *p;
+       struct ub_lun *lun;
        int cnt;
        unsigned long flags;
        int nc, nh;
@@ -421,9 +451,15 @@ static ssize_t ub_diag_show(struct device *dev, char *page)
        spin_lock_irqsave(&sc->lock, flags);
 
        cnt += sprintf(page + cnt,
-           "qlen %d qmax %d changed %d removable %d readonly %d\n",
-           sc->cmd_queue.qlen, sc->cmd_queue.qmax,
-           sc->changed, sc->removable, sc->readonly);
+           "qlen %d qmax %d\n",
+           sc->cmd_queue.qlen, sc->cmd_queue.qmax);
+
+       list_for_each (p, &sc->luns) {
+               lun = list_entry(p, struct ub_lun, link);
+               cnt += sprintf(page + cnt,
+                   "lun %u changed %d removable %d readonly %d\n",
+                   lun->num, lun->changed, lun->removable, lun->readonly);
+       }
 
        if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
        for (j = 0; j < SCMD_TRACE_SZ; j++) {
@@ -523,53 +559,63 @@ static void ub_put(struct ub_dev *sc)
  */
 static void ub_cleanup(struct ub_dev *sc)
 {
+       struct list_head *p;
+       struct ub_lun *lun;
        request_queue_t *q;
 
-       /* I don't think queue can be NULL. But... Stolen from sx8.c */
-       if ((q = sc->disk->queue) != NULL)
-               blk_cleanup_queue(q);
+       while (!list_empty(&sc->luns)) {
+               p = sc->luns.next;
+               lun = list_entry(p, struct ub_lun, link);
+               list_del(p);
 
-       /*
-        * If we zero disk->private_data BEFORE put_disk, we have to check
-        * for NULL all over the place in open, release, check_media and
-        * revalidate, because the block level semaphore is well inside the
-        * put_disk. But we cannot zero after the call, because *disk is gone.
-        * The sd.c is blatantly racy in this area.
-        */
-       /* disk->private_data = NULL; */
-       put_disk(sc->disk);
-       sc->disk = NULL;
+               /* I don't think queue can be NULL. But... Stolen from sx8.c */
+               if ((q = lun->disk->queue) != NULL)
+                       blk_cleanup_queue(q);
+               /*
+                * If we zero disk->private_data BEFORE put_disk, we have
+                * to check for NULL all over the place in open, release,
+                * check_media and revalidate, because the block level
+                * semaphore is well inside the put_disk.
+                * But we cannot zero after the call, because *disk is gone.
+                * The sd.c is blatantly racy in this area.
+                */
+               /* disk->private_data = NULL; */
+               put_disk(lun->disk);
+               lun->disk = NULL;
+
+               ub_id_put(lun->id);
+               kfree(lun);
+       }
 
-       ub_id_put(sc->id);
        kfree(sc);
 }
 
 /*
  * The "command allocator".
  */
-static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun)
 {
        struct ub_scsi_cmd *ret;
 
-       if (sc->cmda[0])
+       if (lun->cmda[0])
                return NULL;
-       ret = &sc->cmdv[0];
-       sc->cmda[0] = 1;
+       ret = &lun->cmdv[0];
+       lun->cmda[0] = 1;
        return ret;
 }
 
-static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd)
 {
-       if (cmd != &sc->cmdv[0]) {
+       if (cmd != &lun->cmdv[0]) {
                printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
-                   sc->name, cmd);
+                   lun->name, cmd);
                return;
        }
-       if (!sc->cmda[0]) {
-               printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
+       if (!lun->cmda[0]) {
+               printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name);
                return;
        }
-       sc->cmda[0] = 0;
+       lun->cmda[0] = 0;
 }
 
 /*
@@ -630,29 +676,30 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
 
 static void ub_bd_rq_fn(request_queue_t *q)
 {
-       struct ub_dev *sc = q->queuedata;
+       struct ub_lun *lun = q->queuedata;
        struct request *rq;
 
        while ((rq = elv_next_request(q)) != NULL) {
-               if (ub_bd_rq_fn_1(sc, rq) != 0) {
+               if (ub_bd_rq_fn_1(lun, rq) != 0) {
                        blk_stop_queue(q);
                        break;
                }
        }
 }
 
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
 {
+       struct ub_dev *sc = lun->udev;
        struct ub_scsi_cmd *cmd;
        int rc;
 
-       if (atomic_read(&sc->poison) || sc->changed) {
+       if (atomic_read(&sc->poison) || lun->changed) {
                blkdev_dequeue_request(rq);
                ub_end_rq(rq, 0);
                return 0;
        }
 
-       if ((cmd = ub_get_cmd(sc)) == NULL)
+       if ((cmd = ub_get_cmd(lun)) == NULL)
                return -1;
        memset(cmd, 0, sizeof(struct ub_scsi_cmd));
 
@@ -661,32 +708,30 @@ static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
        if (blk_pc_request(rq)) {
                rc = ub_cmd_build_packet(sc, cmd, rq);
        } else {
-               rc = ub_cmd_build_block(sc, cmd, rq);
+               rc = ub_cmd_build_block(sc, lun, cmd, rq);
        }
        if (rc != 0) {
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
-               blk_start_queue(sc->disk->queue);
                return 0;
        }
-
        cmd->state = UB_CMDST_INIT;
+       cmd->lun = lun;
        cmd->done = ub_rw_cmd_done;
        cmd->back = rq;
 
        cmd->tag = sc->tagcnt++;
        if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
-               blk_start_queue(sc->disk->queue);
                return 0;
        }
 
        return 0;
 }
 
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
-    struct request *rq)
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct request *rq)
 {
        int ub_dir;
 #if 0 /* We use rq->buffer for now */
@@ -707,7 +752,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
        sg = &cmd->sgv[0];
        n_elem = blk_rq_map_sg(q, rq, sg);
        if (n_elem <= 0) {
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
                blk_start_queue(q);
                return 0;               /* request with no s/g entries? */
@@ -716,7 +761,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
        if (n_elem != 1) {              /* Paranoia */
                printk(KERN_WARNING "%s: request with %d segments\n",
                    sc->name, n_elem);
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
                blk_start_queue(q);
                return 0;
@@ -748,8 +793,8 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
         * The call to blk_queue_hardsect_size() guarantees that request
         * is aligned, but it is given in terms of 512 byte units, always.
         */
-       block = rq->sector >> sc->capacity.bshift;
-       nblks = rq->nr_sectors >> sc->capacity.bshift;
+       block = rq->sector >> lun->capacity.bshift;
+       nblks = rq->nr_sectors >> lun->capacity.bshift;
 
        cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
        /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
@@ -803,7 +848,8 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
        struct request *rq = cmd->back;
-       struct gendisk *disk = sc->disk;
+       struct ub_lun *lun = cmd->lun;
+       struct gendisk *disk = lun->disk;
        request_queue_t *q = disk->queue;
        int uptodate;
 
@@ -818,7 +864,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        else
                uptodate = 0;
 
-       ub_put_cmd(sc, cmd);
+       ub_put_cmd(lun, cmd);
        ub_end_rq(rq, uptodate);
        blk_start_queue(q);
 }
@@ -887,7 +933,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        bcb->Tag = cmd->tag;            /* Endianness is not important */
        bcb->DataTransferLength = cpu_to_le32(cmd->len);
        bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
-       bcb->Lun = 0;                   /* No multi-LUN yet */
+       bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0;
        bcb->Length = cmd->cdb_len;
 
        /* copy the command payload */
@@ -1002,9 +1048,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         * The control pipe clears itself - nothing to do.
                         * XXX Might try to reset the device here and retry.
                         */
-                       printk(KERN_NOTICE "%s: "
-                           "stall on control pipe for device %u\n",
-                           sc->name, sc->dev->devnum);
+                       printk(KERN_NOTICE "%s: stall on control pipe\n",
+                           sc->name);
                        goto Bad_End;
                }
 
@@ -1025,9 +1070,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         * The control pipe clears itself - nothing to do.
                         * XXX Might try to reset the device here and retry.
                         */
-                       printk(KERN_NOTICE "%s: "
-                           "stall on control pipe for device %u\n",
-                           sc->name, sc->dev->devnum);
+                       printk(KERN_NOTICE "%s: stall on control pipe\n",
+                           sc->name);
                        goto Bad_End;
                }
 
@@ -1046,9 +1090,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
                        if (rc != 0) {
                                printk(KERN_NOTICE "%s: "
-                                   "unable to submit clear for device %u"
-                                   " (code %d)\n",
-                                   sc->name, sc->dev->devnum, rc);
+                                   "unable to submit clear (%d)\n",
+                                   sc->name, rc);
                                /*
                                 * This is typically ENOMEM or some other such shit.
                                 * Retrying is pointless. Just do Bad End on it...
@@ -1107,9 +1150,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
                        if (rc != 0) {
                                printk(KERN_NOTICE "%s: "
-                                   "unable to submit clear for device %u"
-                                   " (code %d)\n",
-                                   sc->name, sc->dev->devnum, rc);
+                                   "unable to submit clear (%d)\n",
+                                   sc->name, rc);
                                /*
                                 * This is typically ENOMEM or some other such shit.
                                 * Retrying is pointless. Just do Bad End on it...
@@ -1140,9 +1182,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
                        if (rc != 0) {
                                printk(KERN_NOTICE "%s: "
-                                   "unable to submit clear for device %u"
-                                   " (code %d)\n",
-                                   sc->name, sc->dev->devnum, rc);
+                                   "unable to submit clear (%d)\n",
+                                   sc->name, rc);
                                /*
                                 * This is typically ENOMEM or some other such shit.
                                 * Retrying is pointless. Just do Bad End on it...
@@ -1164,9 +1205,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         * encounter such a thing, try to read the CSW again.
                         */
                        if (++cmd->stat_count >= 4) {
-                               printk(KERN_NOTICE "%s: "
-                                   "unable to get CSW on device %u\n",
-                                   sc->name, sc->dev->devnum);
+                               printk(KERN_NOTICE "%s: unable to get CSW\n",
+                                   sc->name);
                                goto Bad_End;
                        }
                        __ub_state_stat(sc, cmd);
@@ -1207,10 +1247,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         */
                        if (++cmd->stat_count >= 4) {
                                printk(KERN_NOTICE "%s: "
-                                   "tag mismatch orig 0x%x reply 0x%x "
-                                   "on device %u\n",
-                                   sc->name, cmd->tag, bcs->Tag,
-                                   sc->dev->devnum);
+                                   "tag mismatch orig 0x%x reply 0x%x\n",
+                                   sc->name, cmd->tag, bcs->Tag);
                                goto Bad_End;
                        }
                        __ub_state_stat(sc, cmd);
@@ -1244,8 +1282,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
        } else {
                printk(KERN_WARNING "%s: "
-                   "wrong command state %d on device %u\n",
-                   sc->name, cmd->state, sc->dev->devnum);
+                   "wrong command state %d\n",
+                   sc->name, cmd->state);
                goto Bad_End;
        }
        return;
@@ -1288,7 +1326,6 @@ static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
-               printk("%s: CSW #%d submit failed (%d)\n", sc->name, cmd->tag, rc); /* P3 */
                ub_complete(&sc->work_done);
                ub_state_done(sc, cmd, rc);
                return;
@@ -1333,6 +1370,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        scmd->state = UB_CMDST_INIT;
        scmd->data = sc->top_sense;
        scmd->len = UB_SENSE_SIZE;
+       scmd->lun = cmd->lun;
        scmd->done = ub_top_sense_done;
        scmd->back = cmd;
 
@@ -1411,14 +1449,14 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
        }
        if (cmd != scmd->back) {
                printk(KERN_WARNING "%s: "
-                   "sense done for wrong command 0x%x on device %u\n",
-                   sc->name, cmd->tag, sc->dev->devnum);
+                   "sense done for wrong command 0x%x\n",
+                   sc->name, cmd->tag);
                return;
        }
        if (cmd->state != UB_CMDST_SENSE) {
                printk(KERN_WARNING "%s: "
-                   "sense done with bad cmd state %d on device %u\n",
-                   sc->name, cmd->state, sc->dev->devnum);
+                   "sense done with bad cmd state %d\n",
+                   sc->name, cmd->state);
                return;
        }
 
@@ -1429,68 +1467,32 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
        ub_scsi_urb_compl(sc, cmd);
 }
 
-#if 0
-/* Determine what the maximum LUN supported is */
-int usb_stor_Bulk_max_lun(struct us_data *us)
-{
-       int result;
-
-       /* issue the command */
-       result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
-                                US_BULK_GET_MAX_LUN, 
-                                USB_DIR_IN | USB_TYPE_CLASS | 
-                                USB_RECIP_INTERFACE,
-                                0, us->ifnum, us->iobuf, 1, HZ);
-
-       /* 
-        * Some devices (i.e. Iomega Zip100) need this -- apparently
-        * the bulk pipes get STALLed when the GetMaxLUN request is
-        * processed.   This is, in theory, harmless to all other devices
-        * (regardless of if they stall or not).
-        */
-       if (result <&