diff --git a/[refs] b/[refs]
index b87f655e864c..d7242b3172f9 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: d3c39d14d1369c520916ff7a77b2b063e7a75557
+refs/heads/master: f497ba735fc9ff4e35a19641143708b3be1c7061
diff --git a/trunk/CREDITS b/trunk/CREDITS
index 9bd099d960f3..3b9e160d6f7e 100644
--- a/trunk/CREDITS
+++ b/trunk/CREDITS
@@ -882,12 +882,13 @@ S: Blacksburg, Virginia 24061
S: USA
N: Randy Dunlap
-E: rdunlap@xenotime.net
+E: rddunlap@osdl.org
W: http://www.xenotime.net/linux/linux.html
W: http://www.linux-usb.org
D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
D: x86 SMP, ACPI, bootflag hacking
-S: (ask for current address)
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
S: USA
N: Bob Dunlop
diff --git a/trunk/Documentation/DocBook/libata.tmpl b/trunk/Documentation/DocBook/libata.tmpl
index 6df1dfd18b65..cf2fce7707da 100644
--- a/trunk/Documentation/DocBook/libata.tmpl
+++ b/trunk/Documentation/DocBook/libata.tmpl
@@ -14,7 +14,7 @@
- 2003-2005
+ 2003
Jeff Garzik
@@ -44,38 +44,30 @@
-
- Introduction
+
+ Thanks
- 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<->ATA translation
- for ATA devices according to the T10 SAT specification.
+ The bulk of the ATA knowledge comes thanks to long conversations with
+ Andre Hedrick (www.linux-ide.org).
- This Guide documents the libATA driver API, library functions, library
- internals, and a couple sample ATA low-level drivers.
+ Thanks to Alan Cox for pointing out similarities
+ between SATA and SCSI, and in general for motivation to hack on
+ libata.
+
+
+ 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).
libata Driver API
-
- 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.
-
-
- 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.
-
struct ata_port_operations
- Disable ATA port
void (*port_disable) (struct ata_port *);
@@ -86,9 +78,6 @@ void (*port_disable) (struct ata_port *);
unplug).
-
-
- Post-IDENTIFY device configuration
void (*dev_config) (struct ata_port *, struct ata_device *);
@@ -99,9 +88,6 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
issue of SET FEATURES - XFER MODE, and prior to operation.
-
-
- Set PIO/DMA mode
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
@@ -122,9 +108,6 @@ void (*post_set_mode) (struct ata_port *ap);
->set_dma_mode() is only called if DMA is possible.
-
-
- Taskfile read/write
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -137,9 +120,6 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
taskfile register values.
-
-
- ATA command execute
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
@@ -149,37 +129,17 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
->tf_load(), to be initiated in hardware.
-
-
- Per-cmd ATAPI DMA capabilities filter
-
-int (*check_atapi_dma) (struct ata_queued_cmd *qc);
-
-
-
-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.
-
-
-
-
- Read specific ATA shadow registers
u8 (*check_status)(struct ata_port *ap);
-u8 (*check_altstatus)(struct ata_port *ap);
-u8 (*check_err)(struct ata_port *ap);
+void (*dev_select)(struct ata_port *ap, unsigned int device);
- 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.
+ Reads the Status ATA shadow register from hardware. On some
+ hardware, this has the side effect of clearing the interrupt
+ condition.
-
-
- Select ATA device on bus
void (*dev_select)(struct ata_port *ap, unsigned int device);
@@ -187,13 +147,9 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
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. This generally has no
-meaning on FIS-based devices.
+ available for use) on the ATA bus.
-
-
- Reset ATA bus
void (*phy_reset) (struct ata_port *ap);
@@ -206,31 +162,17 @@ void (*phy_reset) (struct ata_port *ap);
functions ata_bus_reset() or sata_phy_reset() for this hook.
-
-
- Control PCI IDE BMDMA engine
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);
-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.
+ When setting up an IDE BMDMA transaction, these hooks arm
+ (->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
+ engine.
-
-These hooks are typically either no-ops, or simply not implemented, in
-FIS-based drivers.
-
-
-
-
- High-level taskfile hooks
void (*qc_prep) (struct ata_queued_cmd *qc);
int (*qc_issue) (struct ata_queued_cmd *qc);
@@ -248,26 +190,20 @@ 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 implement their own ->qc_issue.
+ dispatch. More advanced drivers roll their own ->qc_issue
+ implementation, using this as the "issue new ATA command to
+ hardware" hook.
-
-
- Timeout (error) handling
void (*eng_timeout) (struct ata_port *ap);
-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().
+ This is a high level error handling function, called from the
+ error handling thread, when a command times out.
-
-
- Hardware interrupt handling
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *);
@@ -280,9 +216,6 @@ void (*irq_clear) (struct ata_port *);
is quiet.
-
-
- SATA phy read/write
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -294,9 +227,6 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
if ->phy_reset hook called the sata_phy_reset() helper function.
-
-
- Init and shutdown
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
@@ -310,17 +240,15 @@ void (*host_stop) (struct ata_host_set *host_set);
tasks.
+ ->host_stop() is called when the rmmod or hot unplug process
+ begins. The hook must stop all hardware interrupts, DMA
+ engines, etc.
+
+
->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.
-
- ->host_stop() is called after all ->port_stop() calls
-have completed. The hook must finalize hardware shutdown, release DMA
-and other resources, etc.
-
-
-
@@ -351,24 +279,4 @@ and other resources, etc.
!Idrivers/scsi/sata_sil.c
-
- Thanks
-
- 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.
-
-
- Thanks to Alan Cox for pointing out similarities
- between SATA and SCSI, and in general for motivation to hack on
- libata.
-
-
- 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).
-
-
-
diff --git a/trunk/Documentation/cpu-freq/cpufreq-stats.txt b/trunk/Documentation/cpu-freq/cpufreq-stats.txt
deleted file mode 100644
index e2d1e760b4ba..000000000000
--- a/trunk/Documentation/cpu-freq/cpufreq-stats.txt
+++ /dev/null
@@ -1,128 +0,0 @@
-
- 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
-
-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 (/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.
-
---------------------------------------------------------------------------------
-:/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 " " pair in each line, which
-will mean this CPU spent usertime units of time at . Output
-will have one line for each of the supported freuencies. usertime units here
-is 10mS (similar to other time exported in /proc).
-
---------------------------------------------------------------------------------
-:/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.
-
---------------------------------------------------------------------------------
-:/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
- (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.
-
---------------------------------------------------------------------------------
-:/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.
-
-
-
-
diff --git a/trunk/Documentation/cpusets.txt b/trunk/Documentation/cpusets.txt
index 2f8f24eaefd9..1ad26d2c20ae 100644
--- a/trunk/Documentation/cpusets.txt
+++ b/trunk/Documentation/cpusets.txt
@@ -252,7 +252,8 @@ in a tasks processor placement.
There is an exception to the above. If hotplug funtionality is used
to remove all the CPUs that are currently assigned to a cpuset,
then the kernel will automatically update the cpus_allowed of all
-tasks attached to CPUs in that cpuset to allow all CPUs. When memory
+tasks attached to CPUs in that cpuset with the online CPUs of the
+nearest parent cpuset that still has some CPUs online. When memory
hotplug functionality for removing Memory Nodes is available, a
similar exception is expected to apply there as well. In general,
the kernel prefers to violate cpuset placement, over starving a task
diff --git a/trunk/Documentation/dvb/README.flexcop b/trunk/Documentation/dvb/README.flexcop
deleted file mode 100644
index a50c70f9ca72..000000000000
--- a/trunk/Documentation/dvb/README.flexcop
+++ /dev/null
@@ -1,205 +0,0 @@
-This README escorted the skystar2-driver rewriting procedure. It describes the
-state of the new flexcop-driver set and some internals are written down here
-too.
-
-This document hopefully describes things about the flexcop and its
-device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
-drivers based on the skystar2.c and other information.
-
-Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
-touched and rewritten.
-
-History & News
-==============
- 2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
-
-
-
-
-General coding processing
-=========================
-
-We should proceed as follows (as long as no one complains):
-
-0) Think before start writing code!
-
-1) rewriting the skystar2.c with the help of the flexcop register descriptions
-and splitting up the files to a pci-bus-part and a flexcop-part.
-The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
-device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
-
-2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
-and other pci drivers)
-
-3) make some beautification (see 'Improvements when rewriting (refactoring) is
-done')
-
-4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
-a wider tester audience.
-
-5) creating an usb-bus-part using the already written flexcop code for the pci
-card.
-
-Idea: create a kernel-object for the flexcop and export all important
-functions. This option saves kernel-memory, but maybe a lot of functions have
-to be exported to kernel namespace.
-
-
-Current situation
-=================
-
-0) Done :)
-1) Done (some minor issues left)
-2) Done
-3) Not ready yet, more information is necessary
-4) next to be done (see the table below)
-5) USB driver is working (yes, there are some minor issues)
-
-What seems to be ready?
------------------------
-
-1) Rewriting
-1a) i2c is cut off from the flexcop-pci.c and seems to work
-1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
-1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
-1e) eeprom (reading MAC address)
-1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me))
-1f) misc. register accesses for reading parameters (e.g. resetting, revision)
-1g) pid/mac filter (flexcop-hw-filter.c)
-1i) dvb-stuff initialization in flexcop.c (done)
-1h) dma stuff (now just using the size-irq, instead of all-together, to be done)
-1j) remove flexcop initialization from flexcop-pci.c completely (done)
-1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO')
-1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
-non-static where possible, moved code to proper places)
-
-2) Search for errors in the leftover of flexcop-pci.c (partially done)
-5a) add MAC address reading
-5c) feeding of ISOC data to the software demux (format of the isochronous data
-and speed optimization, no real error) (thanks to Vadim Catana)
-
-What to do in the near future?
---------------------------------------
-(no special order here)
-
-5) USB driver
-5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting)
-
-Testing changes
----------------
-
-O = item is working
-P = item is partially working
-X = item is not working
-N = item does not apply here
- = item need to be examined
-
- | PCI | USB
-item | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
--------+-------+---------+---------+-------+-------+---------+---------+-------
-1a) | O | | | | N | N | N | N
-1b) | O | | | | | | O |
-1c) | N | N | | | N | N | O |
-1d) | O | O
-1e) | O | O
-1f) | P
-1g) | O
-1h) | P |
-1i) | O | N
-1j) | O | N
-1l) | O | N
-2) | O | N
-5a) | N | O
-5b)* | N |
-5c) | N | O
-
-* - not done yet
-
-Known bugs and problems and TODO
---------------------------------
-
-1g/h/l) when pid filtering is enabled on the pci card
-
-DMA usage currently:
- The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
- address and triggers an IRQ when it's full and starts writing to the second
- address. When the second address is full, the IRQ is triggered again, and
- the flexcop writes to first address again, and so on.
- The buffersize of each address is currently 640*188 bytes.
-
- Problem is, when using hw-pid-filtering and doing some low-bandwidth
- operation (like scanning) the buffers won't be filled enough to trigger
- the IRQ. That's why:
-
- When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
- is triggered. Is the current write address of DMA1 different to the one
- during the last IRQ, then the data is passed to the demuxer.
-
- There is an additional DMA-IRQ-method: packet count IRQ. This isn't
- implemented correctly yet.
-
- The solution is to disable HW PID filtering, but I don't know how the DVB
- API software demux behaves on slow systems with 45MBit/s TS.
-
-Solved bugs :)
---------------
-1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
-working)
-SOLUTION: also index 0 was affected, because net_translation is done for
-these indexes by default
-
-5b) isochronous transfer does only work in the first attempt (for the Sky2PC
-USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
-woke up again (don't know if this need fixes, see
-flexcop-fe-tuner.c:flexcop_sleep)
-
-NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
-anything in the while the driver is loaded the first time), no transfers take
-place anymore.
-
-Improvements when rewriting (refactoring) is done
-=================================================
-
-- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
- (enable sleeping for other demods than dvb-s)
-- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA)
-
-Debugging
----------
-- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
- with this flexcop, this is important, because i2c is now using the
- flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
- that, please tell us so).
-
-Everything which is identical in the following table, can be put into a common
-flexcop-module.
-
- PCI USB
--------------------------------------------------------------------------------
-Different:
-Register access: accessing IO memory USB control message
-I2C bus: I2C bus of the FC USB control message
-Data transfer: DMA isochronous transfer
-EEPROM transfer: through i2c bus not clear yet
-
-Identical:
-Streaming: accessing registers
-PID Filtering: accessing registers
-Sram destinations: accessing registers
-Tuner/Demod: I2C bus
-DVB-stuff: can be written for common use
-
-Acknowledgements (just for the rewriting part)
-================
-
-Bjarne Steinsbo thought a lot in the first place of the pci part for this code
-sharing idea.
-
-Andreas Oberritter for providing a recent PCI initialization template
-(pluto2.c).
-
-Boleslaw Ciesielski for pointing out a problem with firmware loader.
-
-Vadim Catana for correcting the USB transfer.
-
-comments, critics and ideas to linux-dvb@linuxtv.org.
diff --git a/trunk/Documentation/dvb/bt8xx.txt b/trunk/Documentation/dvb/bt8xx.txt
index d64430bf4bb6..e3cacf4f2345 100644
--- a/trunk/Documentation/dvb/bt8xx.txt
+++ b/trunk/Documentation/dvb/bt8xx.txt
@@ -17,53 +17,74 @@ Because of this, you need to enable
"Device drivers" => "Multimedia devices"
=> "Video For Linux" => "BT848 Video For Linux"
-Furthermore you need to enable
-"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
- => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
-
2) Loading Modules
==================
In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us, plus the common dvb-bt8xx device driver.
-The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
-TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
+i2c communication for us. Next you need the common dvb-bt8xx device driver
+and one frontend driver.
+
+The bttv driver will HANG YOUR SYSTEM IF YOU DO NOT SPECIFY THE CORRECT
+CARD ID!
+
+(If you don't get your card running and you suspect that the card id you're
+using is wrong, have a look at "bttv-cards.c" for a list of possible card
+ids.)
+
+Pay attention to failures when you load the frontend drivers
+(e.g. dmesg, /var/log/messages).
3a) Nebula / Pinnacle PCTV
--------------------------
- $ modprobe bttv (normally bttv is being loaded automatically by kmod)
- $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
+ $ modprobe bttv i2c_hw=1 card=0x68
+ $ modprobe dvb-bt8xx
+
+For Nebula cards use the "nxt6000" frontend driver:
+ $ modprobe nxt6000
+For Pinnacle PCTV cards use the "cx24110" frontend driver:
+ $ modprobe cx24110
-3b) TwinHan and Clones
---------------------------
+3b) TwinHan
+-----------
$ modprobe bttv i2c_hw=1 card=0x71
$ modprobe dvb-bt8xx
$ modprobe dst
-The value 0x71 will override the PCI type detection for dvb-bt8xx,
-which is necessary for TwinHan cards.
+The value 0x71 will override the PCI type detection for dvb-bt8xx, which
+is necessary for TwinHan cards.#
-If you're having an older card (blue color circuit) and card=0x71 locks
-your machine, try using 0x68, too. If that does not work, ask on the
-mailing list.
+If you're having an older card (blue color circuit) and card=0x71 locks your
+machine, try using 0x68, too. If that does not work, ask on the DVB mailing list.
-The DST module takes a couple of useful parameters.
+The DST module takes a couple of useful parameters, in case the
+dst drivers fails to detect your type of card correctly.
-verbose takes values 0 to 5. These values control the verbosity level.
+dst_type takes values 0 (satellite), 1 (terrestial TV), 2 (cable).
-debug takes values 0 and 1. You can either disable or enable debugging.
+dst_type_flags takes bit combined values:
+1 = new tuner type packets. You can use this if your card is detected
+ and you have debug and you continually see the tuner packets not
+ working (make sure not a basic problem like dish alignment etc.)
-dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card.
-0x20 means it has a Conditional Access slot.
+2 = TS 204. If your card tunes OK, but the picture is terrible, seemingly
+ breaking up in one half continually, and crc fails a lot, then
+ this is worth a try (or trying to turn off)
-The autodected values are determined bythe cards 'response
+4 = has symdiv. Some cards, mostly without new tuner packets, require
+ a symbol division algorithm. Doesn't apply to terrestial TV.
+
+You can also specify a value to have the autodetected values turned off
+(e.g. 0). The autodected values are determined bythe cards 'response
string' which you can see in your logs e.g.
-dst_get_device_id: Recognise [DSTMCI]
+dst_check_ci: recognize DST-MOT
+
+or
+dst_check_ci: unable to recognize DSTXCI or STXCI
--
-Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
+Authors: Richard Walker, Jamie Honan, Michael Hunold
diff --git a/trunk/Documentation/dvb/ci.txt b/trunk/Documentation/dvb/ci.txt
deleted file mode 100644
index 62e0701b542a..000000000000
--- a/trunk/Documentation/dvb/ci.txt
+++ /dev/null
@@ -1,219 +0,0 @@
-* For the user
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-NOTE: This document describes the usage of the high level CI API as
-in accordance to the Linux DVB API. This is a not a documentation for the,
-existing low level CI API.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To utilize the High Level CI capabilities,
-
-(1*) This point is valid only for the Twinhan/clones
- For the Twinhan/Twinhan clones, the dst_ca module handles the CI
- hardware handling.This module is loaded automatically if a CI
- (Common Interface, that holds the CAM (Conditional Access Module)
- is detected.
-
-(2) one requires a userspace application, ca_zap. This small userland
- application is in charge of sending the descrambling related information
- to the CAM.
-
-This application requires the following to function properly as of now.
-
- (a) Tune to a valid channel, with szap.
- eg: $ szap -c channels.conf -r "TMC" -x
-
- (b) a channels.conf containing a valid PMT PID
-
- eg: TMC:11996:h:0:27500:278:512:650:321
-
- here 278 is a valid PMT PID. the rest of the values are the
- same ones that szap uses.
-
- (c) after running a szap, you have to run ca_zap, for the
- descrambler to function,
-
- eg: $ ca_zap patched_channels.conf "TMC"
-
- The patched means a patch to apply to scan, such that scan can
- generate a channels.conf_with pmt, which has this PMT PID info
- (NOTE: szap cannot use this channels.conf with the PMT_PID)
-
-
- (d) Hopeflly Enjoy your favourite subscribed channel as you do with
- a FTA card.
-
-(3) Currently ca_zap, and dst_test, both are meant for demonstration
- purposes only, they can become full fledged applications if necessary.
-
-
-* Cards that fall in this category
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-At present the cards that fall in this category are the Twinhan and it's
-clones, these cards are available as VVMER, Tomato, Hercules, Orange and
-so on.
-
-* CI modules that are supported
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The CI module support is largely dependant upon the firmware on the cards
-Some cards do support almost all of the available CI modules. There is
-nothing much that can be done in order to make additional CI modules
-working with these cards.
-
-Modules that have been tested by this driver at present are
-
-(1) Irdeto 1 and 2 from SCM
-(2) Viaccess from SCM
-(3) Dragoncam
-
-* The High level CI API
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* For the programmer
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-With the High Level CI approach any new card with almost any random
-architecture can be implemented with this style, the definitions
-insidethe switch statement can be easily adapted for any card, thereby
-eliminating the need for any additional ioctls.
-
-The disadvantage is that the driver/hardware has to manage the rest. For
-the application programmer it would be as simple as sending/receiving an
-array to/from the CI ioctls as defined in the Linux DVB API. No changes
-have been made in the API to accomodate this feature.
-
-
-* Why the need for another CI interface ?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This is one of the most commonly asked question. Well a nice question.
-Strictly speaking this is not a new interface.
-
-The CI interface is defined in the DVB API in ca.h as
-
-typedef struct ca_slot_info {
- int num; /* slot number */
-
- int type; /* CA interface this slot supports */
-#define CA_CI 1 /* CI high level interface */
-#define CA_CI_LINK 2 /* CI link layer level interface */
-#define CA_CI_PHYS 4 /* CI physical layer level interface */
-#define CA_DESCR 8 /* built-in descrambler */
-#define CA_SC 128 /* simple smart card interface */
-
- unsigned int flags;
-#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
-#define CA_CI_MODULE_READY 2
-} ca_slot_info_t;
-
-
-
-This CI interface follows the CI high level interface, which is not
-implemented by most applications. Hence this area is revisited.
-
-This CI interface is quite different in the case that it tries to
-accomodate all other CI based devices, that fall into the other categories
-
-This means that this CI interface handles the EN50221 style tags in the
-Application layer only and no session management is taken care of by the
-application. The driver/hardware will take care of all that.
-
-This interface is purely an EN50221 interface exchanging APDU's. This
-means that no session management, link layer or a transport layer do
-exist in this case in the application to driver communication. It is
-as simple as that. The driver/hardware has to take care of that.
-
-
-With this High Level CI interface, the interface can be defined with the
-regular ioctls.
-
-All these ioctls are also valid for the High level CI interface
-
-#define CA_RESET _IO('o', 128)
-#define CA_GET_CAP _IOR('o', 129, ca_caps_t)
-#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t)
-#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
-#define CA_GET_MSG _IOR('o', 132, ca_msg_t)
-#define CA_SEND_MSG _IOW('o', 133, ca_msg_t)
-#define CA_SET_DESCR _IOW('o', 134, ca_descr_t)
-#define CA_SET_PID _IOW('o', 135, ca_pid_t)
-
-
-On querying the device, the device yields information thus
-
-CA_GET_SLOT_INFO
-----------------------------
-Command = [info]
-APP: Number=[1]
-APP: Type=[1]
-APP: flags=[1]
-APP: CI High level interface
-APP: CA/CI Module Present
-
-CA_GET_CAP
-----------------------------
-Command = [caps]
-APP: Slots=[1]
-APP: Type=[1]
-APP: Descrambler keys=[16]
-APP: Type=[1]
-
-CA_SEND_MSG
-----------------------------
-Descriptors(Program Level)=[ 09 06 06 04 05 50 ff f1]
-Found CA descriptor @ program level
-
-(20) ES type=[2] ES pid=[201] ES length =[0 (0x0)]
-(25) ES type=[4] ES pid=[301] ES length =[0 (0x0)]
-ca_message length is 25 (0x19) bytes
-EN50221 CA MSG=[ 9f 80 32 19 03 01 2d d1 f0 08 01 09 06 06 04 05 50 ff f1 02 e0 c9 00 00 04 e1 2d 00 00]
-
-
-Not all ioctl's are implemented in the driver from the API, the other
-features of the hardware that cannot be implemented by the API are achieved
-using the CA_GET_MSG and CA_SEND_MSG ioctls. An EN50221 style wrapper is
-used to exchange the data to maintain compatibility with other hardware.
-
-
-/* a message to/from a CI-CAM */
-typedef struct ca_msg {
- unsigned int index;
- unsigned int type;
- unsigned int length;
- unsigned char msg[256];
-} ca_msg_t;
-
-
-The flow of data can be described thus,
-
-
-
-
-
- App (User)
- -----
- parse
- |
- |
- v
- en50221 APDU (package)
- --------------------------------------
- | | | High Level CI driver
- | | |
- | v |
- | en50221 APDU (unpackage) |
- | | |
- | | |
- | v |
- | sanity checks |
- | | |
- | | |
- | v |
- | do (H/W dep) |
- --------------------------------------
- | Hardware
- |
- v
-
-
-
-
-The High Level CI interface uses the EN50221 DVB standard, following a
-standard ensures futureproofness.
diff --git a/trunk/Documentation/dvb/get_dvb_firmware b/trunk/Documentation/dvb/get_dvb_firmware
index a750f0101d9d..3ffdcb394299 100644
--- a/trunk/Documentation/dvb/get_dvb_firmware
+++ b/trunk/Documentation/dvb/get_dvb_firmware
@@ -107,7 +107,7 @@ sub tda10045 {
sub tda10046 {
my $sourcefile = "tt_budget_217g.zip";
my $url = "http://www.technotrend.de/new/217g/$sourcefile";
- my $hash = "6a7e1e2f2644b162ff0502367553c72d";
+ my $hash = "a25b579e37109af60f4a36c37893957c";
my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
@@ -115,7 +115,7 @@ sub tda10046 {
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
- extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp");
+ extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, "$tmpdir/fwtmp");
verify("$tmpdir/fwtmp", $hash);
copy("$tmpdir/fwtmp", $outfile);
diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt
index b9eb209318ab..d3c52dd24a2a 100644
--- a/trunk/Documentation/feature-removal-schedule.txt
+++ b/trunk/Documentation/feature-removal-schedule.txt
@@ -63,23 +63,3 @@ Why: Outside of Linux, the only implementations of anything even
people, who might be using implementations that I am not aware
of, to adjust to this upcoming change.
Who: Paul E. McKenney
-
----------------------------
-
-What: IEEE1394 Audio and Music Data Transmission Protocol driver,
- Connection Management Procedures driver
-When: November 2005
-Files: drivers/ieee1394/{amdtp,cmp}*
-Why: These are incomplete, have never worked, and are better implemented
- in userland via raw1394 (see http://freebob.sourceforge.net/ for
- example.)
-Who: Jody McIntyre
-
----------------------------
-
-What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When: November 2005
-Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
- more efficient. You should really be using libraw1394 for raw1394
- access anyway.
-Who: Jody McIntyre
diff --git a/trunk/Documentation/filesystems/sysfs-pci.txt b/trunk/Documentation/filesystems/sysfs-pci.txt
index 988a62fae11f..e97d024eae77 100644
--- a/trunk/Documentation/filesystems/sysfs-pci.txt
+++ b/trunk/Documentation/filesystems/sysfs-pci.txt
@@ -7,6 +7,7 @@ that support it. For example, a given bus might look like this:
|-- 0000:17:00.0
| |-- class
| |-- config
+ | |-- detach_state
| |-- device
| |-- irq
| |-- local_cpus
@@ -18,7 +19,7 @@ that support it. For example, a given bus might look like this:
| |-- subsystem_device
| |-- subsystem_vendor
| `-- vendor
- `-- ...
+ `-- detach_state
The topmost element describes the PCI domain and bus number. In this case,
the domain number is 0000 and the bus number is 17 (both values are in hex).
@@ -30,6 +31,7 @@ files, each with their own function.
---- --------
class PCI class (ascii, ro)
config PCI config space (binary, rw)
+ detach_state connection status (bool, rw)
device PCI device (ascii, ro)
irq IRQ number (ascii, ro)
local_cpus nearby CPU mask (cpumask, ro)
@@ -83,4 +85,4 @@ useful return codes should be provided.
Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms
wishing to support legacy functionality should define it and provide
-pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
+pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
\ No newline at end of file
diff --git a/trunk/Documentation/power/devices.txt b/trunk/Documentation/power/devices.txt
index f987afe43e28..5d4ae9a39f1d 100644
--- a/trunk/Documentation/power/devices.txt
+++ b/trunk/Documentation/power/devices.txt
@@ -207,6 +207,27 @@ SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
#READY_AFTER_RESUME
#
+Driver Detach Power Management
+
+The kernel now supports the ability to place a device in a low-power
+state when it is detached from its driver, which happens when its
+module is removed.
+
+Each device contains a 'detach_state' file in its sysfs directory
+which can be used to control this state. Reading from this file
+displays what the current detach state is set to. This is 0 (On) by
+default. A user may write a positive integer value to this file in the
+range of 1-4 inclusive.
+
+A value of 1-3 will indicate the device should be placed in that
+low-power state, which will cause ->suspend() to be called for that
+device. A value of 4 indicates that the device should be shutdown, so
+->shutdown() will be called for that device.
+
+The driver is responsible for reinitializing the device when the
+module is re-inserted during it's ->probe() (or equivalent) method.
+The driver core will not call any extra functions when binding the
+device to the driver.
pm_message_t meaning
diff --git a/trunk/Documentation/powerpc/hvcs.txt b/trunk/Documentation/powerpc/hvcs.txt
index dca75cbda6f8..c0a62e116e6e 100644
--- a/trunk/Documentation/powerpc/hvcs.txt
+++ b/trunk/Documentation/powerpc/hvcs.txt
@@ -347,8 +347,8 @@ address that is created by firmware. An example vty-server sysfs entry
looks like the following:
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
- . current_vty devspec name partner_vtys
- .. index partner_clcs vterm_state
+ . current_vty devspec name partner_vtys
+ .. detach_state index partner_clcs vterm_state
Each entry is provided, by default with a "name" attribute. Reading the
"name" attribute will reveal the device type as shown in the following
diff --git a/trunk/Documentation/x86_64/boot-options.txt b/trunk/Documentation/x86_64/boot-options.txt
index b9e6be00cadf..44b6eea60ece 100644
--- a/trunk/Documentation/x86_64/boot-options.txt
+++ b/trunk/Documentation/x86_64/boot-options.txt
@@ -25,9 +25,6 @@ APICs
noapictimer Don't set up the APIC timer
- no_timer_check Don't check the IO-APIC timer. This can work around
- problems with incorrect timer initialization on some boards.
-
Early Console
syntax: earlyprintk=vga
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index 65ad8251e4bc..5b8483334de1 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -239,12 +239,6 @@ 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
@@ -1029,8 +1023,8 @@ W: http://www.ia64-linux.org/
S: Maintained
SN-IA64 (Itanium) SUB-PLATFORM
-P: Greg Edwards
-M: edwardsg@sgi.com
+P: Jesse Barnes
+M: jbarnes@sgi.com
L: linux-altix@sgi.com
L: linux-ia64@vger.kernel.org
W: http://www.sgi.com/altix
diff --git a/trunk/Makefile b/trunk/Makefile
index c11a317ea910..bddcb861b49b 100644
--- a/trunk/Makefile
+++ b/trunk/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 12
-EXTRAVERSION =-rc5
+EXTRAVERSION =-rc4
NAME=Woozy Numbat
# *DOCUMENTATION*
@@ -530,7 +530,7 @@ endif
include $(srctree)/arch/$(ARCH)/Makefile
# arch Makefile may override CC so keep this after arch Makefile is included
-NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+NOSTDINC_FLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
# warn about C99 declaration after statement
diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c
index 167fd89f8707..64e450dddb49 100644
--- a/trunk/arch/alpha/kernel/osf_sys.c
+++ b/trunk/arch/alpha/kernel/osf_sys.c
@@ -1150,13 +1150,16 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
if (get_tv32(&tmp, sleep))
goto fault;
- ticks = timeval_to_jiffies(&tmp);
+ ticks = tmp.tv_usec;
+ ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
+ ticks += tmp.tv_sec * HZ;
current->state = TASK_INTERRUPTIBLE;
ticks = schedule_timeout(ticks);
if (remain) {
- jiffies_to_timeval(ticks, &tmp);
+ tmp.tv_sec = ticks / HZ;
+ tmp.tv_usec = ticks % HZ;
if (put_tv32(remain, &tmp))
goto fault;
}
diff --git a/trunk/arch/arm/mach-s3c2410/clock.c b/trunk/arch/arm/mach-s3c2410/clock.c
index 8d986b8401c2..e23f534d4e1d 100644
--- a/trunk/arch/arm/mach-s3c2410/clock.c
+++ b/trunk/arch/arm/mach-s3c2410/clock.c
@@ -478,7 +478,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
{
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
- s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
+ s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
print_mhz(s3c2440_clk_upll.rate));
diff --git a/trunk/arch/arm/mach-s3c2410/s3c2440.c b/trunk/arch/arm/mach-s3c2410/s3c2440.c
index d4c8281b55f6..9a8cc5ae2255 100644
--- a/trunk/arch/arm/mach-s3c2410/s3c2440.c
+++ b/trunk/arch/arm/mach-s3c2410/s3c2440.c
@@ -192,11 +192,9 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
iotable_init(mach_desc, size);
-
/* rename any peripherals used differing from the s3c2410 */
- s3c_device_i2c.name = "s3c2440-i2c";
- s3c_device_nand.name = "s3c2440-nand";
+ s3c_device_i2c.name = "s3c2440-i2c";
/* change irq for watchdog */
@@ -227,7 +225,7 @@ void __init s3c2440_init_clocks(int xtal)
break;
case S3C2440_CLKDIVN_HDIVN_2:
- hdiv = 2;
+ hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig
index 48bac7da8c70..c4fc6be629de 100644
--- a/trunk/arch/arm/mm/Kconfig
+++ b/trunk/arch/arm/mm/Kconfig
@@ -412,20 +412,21 @@ config CPU_BPREDICT_DISABLE
config TLS_REG_EMUL
bool
- default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+ default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
help
- An SMP system using a pre-ARMv6 processor (there are apparently
- a few prototypes like that in existence) and therefore access to
- that required register must be emulated.
+ We might be running on an ARMv6+ processor which should have the TLS
+ register but for some reason we can't use it, or maybe an SMP system
+ using a pre-ARMv6 processor (there are apparently a few prototypes
+ like that in existence) and therefore access to that register must
+ be emulated.
config HAS_TLS_REG
bool
- depends on !TLS_REG_EMUL
- default y if SMP || CPU_32v7
+ depends on CPU_32v6
+ default y if !TLS_REG_EMUL
help
This selects support for the CP15 thread register.
- It is defined to be available on some ARMv6 processors (including
- all SMP capable ARMv6's) or later processors. User space may
- assume directly accessing that register and always obtain the
- expected value only on ARMv7 and above.
+ It is defined to be available on ARMv6 or later. If a particular
+ ARMv6 or later CPU doesn't support it then it must omc;ide "select
+ TLS_REG_EMUL" along with its other caracteristics.
diff --git a/trunk/arch/arm/mm/copypage-v4mc.S b/trunk/arch/arm/mm/copypage-v4mc.S
new file mode 100644
index 000000000000..305af3dab3d8
--- /dev/null
+++ b/trunk/arch/arm/mm/copypage-v4mc.S
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/lib/copy_page-armv4mc.S
+ *
+ * Copyright (C) 1995-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ASM optimised string functions
+ */
+#include
+#include
+#include
+
+ .text
+ .align 5
+/*
+ * ARMv4 mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address. Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue. The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction. If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ */
+ENTRY(v4_mc_copy_user_page)
+ stmfd sp!, {r4, lr} @ 2
+ mov r4, r0
+ mov r0, r1
+ bl map_page_minicache
+ mov r1, #PAGE_SZ/64 @ 1
+ ldmia r0!, {r2, r3, ip, lr} @ 4
+1: mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmia r0!, {r2, r3, ip, lr} @ 4+1
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmia r0!, {r2, r3, ip, lr} @ 4
+ mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmia r0!, {r2, r3, ip, lr} @ 4
+ subs r1, r1, #1 @ 1
+ stmia r4!, {r2, r3, ip, lr} @ 4
+ ldmneia r0!, {r2, r3, ip, lr} @ 4
+ bne 1b @ 1
+ ldmfd sp!, {r4, pc} @ 3
+
+ .align 5
+/*
+ * ARMv4 optimised clear_user_page
+ *
+ * Same story as above.
+ */
+ENTRY(v4_mc_clear_user_page)
+ str lr, [sp, #-4]!
+ mov r1, #PAGE_SZ/64 @ 1
+ mov r2, #0 @ 1
+ mov r3, #0 @ 1
+ mov ip, #0 @ 1
+ mov lr, #0 @ 1
+1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ stmia r0!, {r2, r3, ip, lr} @ 4
+ subs r1, r1, #1 @ 1
+ bne 1b @ 1
+ ldr pc, [sp], #4
+
+ __INITDATA
+
+ .type v4_mc_user_fns, #object
+ENTRY(v4_mc_user_fns)
+ .long v4_mc_clear_user_page
+ .long v4_mc_copy_user_page
+ .size v4_mc_user_fns, . - v4_mc_user_fns
diff --git a/trunk/arch/arm/mm/copypage-v4mc.c b/trunk/arch/arm/mm/copypage-v4mc.c
deleted file mode 100644
index fc69dccdace1..000000000000
--- a/trunk/arch/arm/mm/copypage-v4mc.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * linux/arch/arm/lib/copypage-armv4mc.S
- *
- * Copyright (C) 1995-2005 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This handles the mini data cache, as found on SA11x0 and XScale
- * processors. When we copy a user page page, we map it in such a way
- * that accesses to this page will not touch the main data cache, but
- * will be cached in the mini data cache. This prevents us thrashing
- * the main data cache on page faults.
- */
-#include
-#include
-
-#include
-#include
-#include
-
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
-#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
- L_PTE_CACHEABLE)
-
-#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
-
-static DEFINE_SPINLOCK(minicache_lock);
-
-/*
- * ARMv4 mini-dcache optimised copy_user_page
- *
- * We flush the destination cache lines just before we write the data into the
- * corresponding address. Since the Dcache is read-allocate, this removes the
- * Dcache aliasing issue. The writes will be forwarded to the write buffer,
- * and merged as appropriate.
- *
- * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
- * instruction. If your processor does not supply this, you have to write your
- * own copy_user_page that does the right thing.
- */
-static void __attribute__((naked))
-mc_copy_user_page(void *from, void *to)
-{
- asm volatile(
- "stmfd sp!, {r4, lr} @ 2\n\
- mov r4, %2 @ 1\n\
- ldmia %0!, {r2, r3, ip, lr} @ 4\n\
-1: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
- stmia %1!, {r2, r3, ip, lr} @ 4\n\
- ldmia %0!, {r2, r3, ip, lr} @ 4+1\n\
- stmia %1!, {r2, r3, ip, lr} @ 4\n\
- ldmia %0!, {r2, r3, ip, lr} @ 4\n\
- mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
- stmia %1!, {r2, r3, ip, lr} @ 4\n\
- ldmia %0!, {r2, r3, ip, lr} @ 4\n\
- subs r4, r4, #1 @ 1\n\
- stmia %1!, {r2, r3, ip, lr} @ 4\n\
- ldmneia %0!, {r2, r3, ip, lr} @ 4\n\
- bne 1b @ 1\n\
- ldmfd sp!, {r4, pc} @ 3"
- :
- : "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
-}
-
-void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
-{
- spin_lock(&minicache_lock);
-
- set_pte(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
- flush_tlb_kernel_page(0xffff8000);
-
- mc_copy_user_page((void *)0xffff8000, kto);
-
- spin_unlock(&minicache_lock);
-}
-
-/*
- * ARMv4 optimised clear_user_page
- */
-void __attribute__((naked))
-v4_mc_clear_user_page(void *kaddr, unsigned long vaddr)
-{
- asm volatile(
- "str lr, [sp, #-4]!\n\
- mov r1, %0 @ 1\n\
- mov r2, #0 @ 1\n\
- mov r3, #0 @ 1\n\
- mov ip, #0 @ 1\n\
- mov lr, #0 @ 1\n\
-1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
- stmia r0!, {r2, r3, ip, lr} @ 4\n\
- stmia r0!, {r2, r3, ip, lr} @ 4\n\
- mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
- stmia r0!, {r2, r3, ip, lr} @ 4\n\
- stmia r0!, {r2, r3, ip, lr} @ 4\n\
- subs r1, r1, #1 @ 1\n\
- bne 1b @ 1\n\
- ldr pc, [sp], #4"
- :
- : "I" (PAGE_SIZE / 64));
-}
-
-struct cpu_user_fns v4_mc_user_fns __initdata = {
- .cpu_clear_user_page = v4_mc_clear_user_page,
- .cpu_copy_user_page = v4_mc_copy_user_page,
-};
diff --git a/trunk/arch/arm/mm/copypage-v6.c b/trunk/arch/arm/mm/copypage-v6.c
index a8c00236bd3d..694ac8208858 100644
--- a/trunk/arch/arm/mm/copypage-v6.c
+++ b/trunk/arch/arm/mm/copypage-v6.c
@@ -26,8 +26,8 @@
#define to_address (0xffffc000)
#define to_pgprot PAGE_KERNEL
-#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
-
+static pte_t *from_pte;
+static pte_t *to_pte;
static DEFINE_SPINLOCK(v6_lock);
#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
@@ -74,8 +74,8 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
*/
spin_lock(&v6_lock);
- set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
- set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
+ set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
+ set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
from = from_address + (offset << PAGE_SHIFT);
to = to_address + (offset << PAGE_SHIFT);
@@ -114,7 +114,7 @@ void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
*/
spin_lock(&v6_lock);
- set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
+ set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
flush_tlb_kernel_page(to);
clear_page((void *)to);
@@ -129,6 +129,21 @@ struct cpu_user_fns v6_user_fns __initdata = {
static int __init v6_userpage_init(void)
{
if (cache_is_vipt_aliasing()) {
+ pgd_t *pgd;
+ pmd_t *pmd;
+
+ pgd = pgd_offset_k(from_address);
+ pmd = pmd_alloc(&init_mm, pgd, from_address);
+ if (!pmd)
+ BUG();
+ from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
+ if (!from_pte)
+ BUG();
+
+ to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
+ if (!to_pte)
+ BUG();
+
cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
}
@@ -136,4 +151,5 @@ static int __init v6_userpage_init(void)
return 0;
}
-core_initcall(v6_userpage_init);
+__initcall(v6_userpage_init);
+
diff --git a/trunk/arch/arm/mm/flush.c b/trunk/arch/arm/mm/flush.c
index 4085ed983e46..c6de48d89503 100644
--- a/trunk/arch/arm/mm/flush.c
+++ b/trunk/arch/arm/mm/flush.c
@@ -13,29 +13,6 @@
#include
#include
-#include
-
-#ifdef CONFIG_CPU_CACHE_VIPT
-#define ALIAS_FLUSH_START 0xffff4000
-
-#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
-
-static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
-{
- unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
-
- set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
- flush_tlb_kernel_page(to);
-
- asm( "mcrr p15, 0, %1, %0, c14\n"
- " mcrr p15, 0, %1, %0, c5\n"
- :
- : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
- : "cc");
-}
-#else
-#define flush_pfn_alias(pfn,vaddr) do { } while (0)
-#endif
static void __flush_dcache_page(struct address_space *mapping, struct page *page)
{
@@ -59,18 +36,6 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
if (!mapping)
return;
- /*
- * This is a page cache page. If we have a VIPT cache, we
- * only need to do one flush - which would be at the relevant
- * userspace colour, which is congruent with page->index.
- */
- if (cache_is_vipt()) {
- if (cache_is_vipt_aliasing())
- flush_pfn_alias(page_to_pfn(page),
- page->index << PAGE_CACHE_SHIFT);
- return;
- }
-
/*
* There are possible user space mappings of this page:
* - VIVT cache: we need to also write back and invalidate all user
@@ -92,6 +57,8 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
continue;
offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
+ if (cache_is_vipt())
+ break;
}
flush_dcache_mmap_unlock(mapping);
}
diff --git a/trunk/arch/arm/mm/mm-armv.c b/trunk/arch/arm/mm/mm-armv.c
index 2c2b93d77d43..585dfb8e20b9 100644
--- a/trunk/arch/arm/mm/mm-armv.c
+++ b/trunk/arch/arm/mm/mm-armv.c
@@ -37,8 +37,6 @@ pgprot_t pgprot_kernel;
EXPORT_SYMBOL(pgprot_kernel);
-pmd_t *top_pmd;
-
struct cachepolicy {
const char policy[16];
unsigned int cr_mask;
@@ -144,16 +142,6 @@ __setup("noalign", noalign_setup);
#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
-{
- return pmd_offset(pgd, virt);
-}
-
-static inline pmd_t *pmd_off_k(unsigned long virt)
-{
- return pmd_off(pgd_offset_k(virt), virt);
-}
-
/*
* need to get a 16k page for level 1
*/
@@ -232,7 +220,7 @@ void free_pgd_slow(pgd_t *pgd)
return;
/* pgd is always present and good */
- pmd = pmd_off(pgd, 0);
+ pmd = (pmd_t *)pgd;
if (pmd_none(*pmd))
goto free;
if (pmd_bad(*pmd)) {
@@ -258,8 +246,9 @@ void free_pgd_slow(pgd_t *pgd)
static inline void
alloc_init_section(unsigned long virt, unsigned long phys, int prot)
{
- pmd_t *pmdp = pmd_off_k(virt);
+ pmd_t *pmdp;
+ pmdp = pmd_offset(pgd_offset_k(virt), virt);
if (virt & (1 << 20))
pmdp++;
@@ -294,9 +283,11 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
static inline void
alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
{
- pmd_t *pmdp = pmd_off_k(virt);
+ pmd_t *pmdp;
pte_t *ptep;
+ pmdp = pmd_offset(pgd_offset_k(virt), virt);
+
if (pmd_none(*pmdp)) {
unsigned long pmdval;
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
@@ -319,7 +310,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
*/
static inline void clear_mapping(unsigned long virt)
{
- pmd_clear(pmd_off_k(virt));
+ pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
}
struct mem_types {
@@ -587,7 +578,7 @@ void setup_mm_for_reboot(char mode)
PMD_TYPE_SECT;
if (cpu_arch <= CPU_ARCH_ARMv5)
pmdval |= PMD_BIT4;
- pmd = pmd_off(pgd, i << PGDIR_SHIFT);
+ pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
pmd[0] = __pmd(pmdval);
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
flush_pmd_entry(pmd);
@@ -684,8 +675,6 @@ void __init memtable_init(struct meminfo *mi)
flush_cache_all();
flush_tlb_all();
-
- top_pmd = pmd_off_k(0xffff0000);
}
/*
diff --git a/trunk/arch/h8300/kernel/process.c b/trunk/arch/h8300/kernel/process.c
index b5f83e9f04db..134aec1c6d19 100644
--- a/trunk/arch/h8300/kernel/process.c
+++ b/trunk/arch/h8300/kernel/process.c
@@ -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();
diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig
index dfd904f6883b..e382f32d435e 100644
--- a/trunk/arch/i386/Kconfig
+++ b/trunk/arch/i386/Kconfig
@@ -1163,7 +1163,7 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool
- depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
+ depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI))
select ACPI_BOOT
default y
diff --git a/trunk/arch/i386/kernel/cpu/amd.c b/trunk/arch/i386/kernel/cpu/amd.c
index 73aeaf5a9d4e..16dbc4151be4 100644
--- a/trunk/arch/i386/kernel/cpu/amd.c
+++ b/trunk/arch/i386/kernel/cpu/amd.c
@@ -24,6 +24,9 @@ __asm__(".align 4\nvide: ret");
static void __init init_amd(struct cpuinfo_x86 *c)
{
+#ifdef CONFIG_X86_SMP
+ int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
+#endif
u32 l, h;
int mbytes = num_physpages >> (20-PAGE_SHIFT);
int r;
@@ -195,19 +198,14 @@ static void __init init_amd(struct cpuinfo_x86 *c)
c->x86_num_cores = 1;
}
-#ifdef CONFIG_X86_HT
+#ifdef CONFIG_X86_SMP
/*
* On a AMD dual core setup the lower bits of the APIC id
* distingush the cores. Assumes number of cores is a power
* of two.
*/
if (c->x86_num_cores > 1) {
- int cpu = smp_processor_id();
- unsigned bits = 0;
- while ((1 << bits) < c->x86_num_cores)
- bits++;
- cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<>= bits;
+ cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
cpu, c->x86_num_cores, cpu_core_id[cpu]);
}
diff --git a/trunk/arch/i386/kernel/cpu/common.c b/trunk/arch/i386/kernel/cpu/common.c
index d199e525680a..6be0310e3cd3 100644
--- a/trunk/arch/i386/kernel/cpu/common.c
+++ b/trunk/arch/i386/kernel/cpu/common.c
@@ -243,10 +243,6 @@ static void __init early_cpu_detect(void)
}
early_intel_workaround(c);
-
-#ifdef CONFIG_X86_HT
- phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
-#endif
}
void __init generic_identify(struct cpuinfo_x86 * c)
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig b/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig
index 0f1eb507233b..f25ffd74235c 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
If in doubt, say N.
config ELAN_CPUFREQ
- tristate "AMD Elan SC400 and SC410"
+ tristate "AMD Elan"
select CPU_FREQ_TABLE
depends on X86_ELAN
---help---
@@ -38,18 +38,6 @@ 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 .
-
- If in doubt, say N.
-
-
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
select CPU_FREQ_TABLE
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/Makefile b/trunk/arch/i386/kernel/cpu/cpufreq/Makefile
index 2e894f1c8910..a922e97aeedd 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -3,7 +3,6 @@ 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
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 04e3563da4fe..ab0f9f5aac11 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,7 +29,6 @@
#include
#include
#include
-#include
#include
#include
@@ -120,13 +119,7 @@ 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:
@@ -144,58 +137,17 @@ static void do_powersaver(union msr_longhaul *longhaul,
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul->bits.EnableSoftBusRatio = 1;
longhaul->bits.RevisionKey = 0;
-
- 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();
+ local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+ local_irq_enable();
__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();
}
/**
@@ -626,7 +578,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
longhaul_setup_voltagescaling();
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- policy->cpuinfo.transition_latency = 200000; /* nsec */
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = calc_speed(longhaul_get_cpu_mult());
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 5c530064eb74..913f652623d9 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -23,7 +23,6 @@
#include
#include
-#include
#include
#include
#include
@@ -587,17 +586,13 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
- /* recalibrate cpu_khz */
- result = recalibrate_cpu_khz();
- if (result)
- return result;
-
- fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
+ /* A K7 with powernow technology is set to max frequency by BIOS */
+ fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
if (!fsb) {
printk(KERN_WARNING PFX "can not determine bus frequency\n");
return -EINVAL;
}
- dprintk("FSB: %3dMHz\n", fsb/1000);
+ dprintk("FSB: %3d.%03d MHz\n", fsb/1000, 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");
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 10cc096c0ade..a65ff7e32e5d 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -4,7 +4,7 @@
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
*
- * Support : mark.langsdorf@amd.com
+ * Support : paul.devriendt@amd.com
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -15,13 +15,12 @@
*
* 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
@@ -31,7 +30,6 @@
#include
#include
#include
-#include
#include
#include
@@ -44,7 +42,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.40.2"
+#define VERSION "version 1.00.09e"
#include "powernow-k8.h"
/* serialize freq changes */
@@ -52,10 +50,6 @@ 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)
{
@@ -280,18 +274,11 @@ 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);
@@ -299,8 +286,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 == maxvid) {
+ while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
+ if (data->currvid == 0) {
rvosteps = 0;
} else {
dprintk("ph1: changing vid for rvo, req 0x%x\n",
@@ -684,7 +671,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_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
+ printk(KERN_ERR PFX "BIOS error - no PSB\n");
return -ENODEV;
}
@@ -708,7 +695,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: bad ACPI data\n");
+ dprintk("register performance failed\n");
return -EIO;
}
@@ -759,23 +746,22 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
continue;
}
- /* 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 (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)) {
@@ -830,7 +816,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
{
u32 fid;
u32 vid;
- int res, i;
+ int res;
struct cpufreq_freqs freqs;
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
@@ -855,8 +841,7 @@ 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(KERN_ERR PFX
- "ignoring illegal change in lo freq table-%x to 0x%x\n",
+ printk("ignoring illegal change in lo freq table-%x to 0x%x\n",
data->currfid, fid);
return 1;
}
@@ -865,20 +850,18 @@ 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);
- for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
- freqs.cpu = i;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- }
+ 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);
- for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
- freqs.cpu = i;
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- }
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
return res;
}
@@ -891,7 +874,6 @@ 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;
@@ -920,41 +902,22 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
data->currfid, data->currvid);
if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
- 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);
+ 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);
}
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;
@@ -999,7 +962,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
*/
if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
- printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
+ printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
kfree(data);
return -ENODEV;
}
@@ -1040,7 +1003,6 @@ 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 */
@@ -1107,7 +1069,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
return 0;
}
preempt_disable();
-
+
if (query_current_values_with_pending_wait(data))
goto out;
@@ -1165,10 +1127,9 @@ static void __exit powernowk8_exit(void)
cpufreq_unregister_driver(&cpufreq_amd64_driver);
}
-MODULE_AUTHOR("Paul Devriendt and Mark Langsdorf ");
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
MODULE_LICENSE("GPL");
late_initcall(powernowk8_init);
module_exit(powernowk8_exit);
-
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 9ed5bf221cb7..63ebc8470f52 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -174,18 +174,3 @@ 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/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
deleted file mode 100644
index ef457d50f4ac..000000000000
--- a/trunk/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * sc520_freq.c: cpufreq driver for the AMD Elan sc520
- *
- * Copyright (C) 2005 Sean Young
- *
- * 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
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-
-#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 ");
-MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
-
-module_init(sc520_freq_init);
-module_exit(sc520_freq_exit);
-
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 7dcbf70fc16f..07d5612dc00f 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -54,8 +54,6 @@ enum {
CPU_DOTHAN_A1,
CPU_DOTHAN_A2,
CPU_DOTHAN_B0,
- CPU_MP4HT_D0,
- CPU_MP4HT_E0,
};
static const struct cpu_id cpu_ids[] = {
@@ -63,8 +61,6 @@ 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]))
@@ -230,8 +226,6 @@ 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, }
};
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index d368b3f5fce8..8ba430a9c3a2 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
if (!prev_speed)
return -EIO;
- dprintk("previous speed is %u\n", prev_speed);
+ dprintk("previous seped 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 speed is %u\n", *low_speed);
+ dprintk("low seped 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 speed is %u\n", *high_speed);
+ dprintk("high seped is %u\n", *high_speed);
if (*low_speed == *high_speed) {
ret = -ENODEV;
diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index b25fb6b635ae..79440b3f087e 100644
--- a/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/trunk/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -357,9 +357,6 @@ 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;
}
diff --git a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c
index a710dc4eb20e..aeb5b4ef8c8b 100644
--- a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -118,7 +118,7 @@ struct _cpuid4_info {
};
#define MAX_CACHE_LEAVES 4
-static unsigned short num_cache_leaves;
+static unsigned short __devinitdata num_cache_leaves;
static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
{
diff --git a/trunk/arch/i386/kernel/setup.c b/trunk/arch/i386/kernel/setup.c
index 2bfbddebdbf8..945ec73163c8 100644
--- a/trunk/arch/i386/kernel/setup.c
+++ b/trunk/arch/i386/kernel/setup.c
@@ -1502,13 +1502,11 @@ 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)
diff --git a/trunk/arch/i386/kernel/smpboot.c b/trunk/arch/i386/kernel/smpboot.c
index bc1bb6919e6a..cbea7ac582e5 100644
--- a/trunk/arch/i386/kernel/smpboot.c
+++ b/trunk/arch/i386/kernel/smpboot.c
@@ -888,7 +888,6 @@ void *xquad_portio;
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_core_map);
static void __init smp_boot_cpus(unsigned int max_cpus)
{
@@ -1074,10 +1073,8 @@ 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++) {
diff --git a/trunk/arch/i386/kernel/timers/common.c b/trunk/arch/i386/kernel/timers/common.c
index 8e201219f525..f7f90005e22e 100644
--- a/trunk/arch/i386/kernel/timers/common.c
+++ b/trunk/arch/i386/kernel/timers/common.c
@@ -6,7 +6,6 @@
#include
#include
#include
-#include
#include
#include
@@ -25,7 +24,7 @@
#define CALIBRATE_TIME (5 * 1000020/HZ)
-unsigned long calibrate_tsc(void)
+unsigned long __init calibrate_tsc(void)
{
mach_prepare_counter();
@@ -140,7 +139,7 @@ unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr)
#endif
/* calculate cpu_khz */
-void init_cpu_khz(void)
+void __init init_cpu_khz(void)
{
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
@@ -159,4 +158,3 @@ void init_cpu_khz(void)
}
}
}
-
diff --git a/trunk/arch/i386/kernel/timers/timer_tsc.c b/trunk/arch/i386/kernel/timers/timer_tsc.c
index 180444d87824..7926d967be00 100644
--- a/trunk/arch/i386/kernel/timers/timer_tsc.c
+++ b/trunk/arch/i386/kernel/timers/timer_tsc.c
@@ -320,26 +320,6 @@ 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;
diff --git a/trunk/arch/i386/mach-voyager/voyager_smp.c b/trunk/arch/i386/mach-voyager/voyager_smp.c
index a6e0ddd65bd0..903d739ca74a 100644
--- a/trunk/arch/i386/mach-voyager/voyager_smp.c
+++ b/trunk/arch/i386/mach-voyager/voyager_smp.c
@@ -97,6 +97,7 @@ static void ack_vic_irq(unsigned int irq);
static void vic_enable_cpi(void);
static void do_boot_cpu(__u8 cpuid);
static void do_quad_bootstrap(void);
+static inline void wrapper_smp_local_timer_interrupt(struct pt_regs *);
int hard_smp_processor_id(void);
@@ -124,14 +125,6 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi)
}
}
-static inline void
-wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
-{
- irq_enter();
- smp_local_timer_interrupt(regs);
- irq_exit();
-}
-
static inline void
send_one_CPI(__u8 cpu, __u8 cpi)
{
@@ -1256,6 +1249,14 @@ smp_vic_timer_interrupt(struct pt_regs *regs)
smp_local_timer_interrupt(regs);
}
+static inline void
+wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
+{
+ irq_enter();
+ smp_local_timer_interrupt(regs);
+ irq_exit();
+}
+
/* local (per CPU) timer interrupt. It does both profiling and
* process statistics/rescheduling.
*
diff --git a/trunk/arch/i386/mm/ioremap.c b/trunk/arch/i386/mm/ioremap.c
index ab542792b27b..db06f7399913 100644
--- a/trunk/arch/i386/mm/ioremap.c
+++ b/trunk/arch/i386/mm/ioremap.c
@@ -238,21 +238,19 @@ void iounmap(volatile void __iomem *addr)
addr < phys_to_virt(ISA_END_ADDRESS))
return;
- write_lock(&vmlist_lock);
- p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+ p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
if (!p) {
- printk("iounmap: bad address %p\n", addr);
- goto out_unlock;
+ printk("__iounmap: bad address %p\n", addr);
+ return;
}
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
+ /* p->size includes the guard page, but cpa doesn't like that */
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
global_flush_tlb();
}
-out_unlock:
- write_unlock(&vmlist_lock);
kfree(p);
}
diff --git a/trunk/arch/i386/pci/fixup.c b/trunk/arch/i386/pci/fixup.c
index 8e8e895e1b5a..be52c5ac4e05 100644
--- a/trunk/arch/i386/pci/fixup.c
+++ b/trunk/arch/i386/pci/fixup.c
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci
#define MAX_PCIEROOT 6
static int quirk_aspm_offset[MAX_PCIEROOT << 3];
-#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
+#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
diff --git a/trunk/arch/i386/pci/irq.c b/trunk/arch/i386/pci/irq.c
index da21b1d07c15..d6598da4b67b 100644
--- a/trunk/arch/i386/pci/irq.c
+++ b/trunk/arch/i386/pci/irq.c
@@ -1029,6 +1029,7 @@ void pcibios_penalize_isa_irq(int irq)
static int pirq_enable_irq(struct pci_dev *dev)
{
u8 pin;
+ extern int via_interrupt_line_quirk;
struct pci_dev *temp_dev;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
@@ -1083,6 +1084,10 @@ static int pirq_enable_irq(struct pci_dev *dev)
printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
'A' + pin, pci_name(dev), msg);
}
+ /* VIA bridges use interrupt line for apic/pci steering across
+ the V-Link */
+ else if (via_interrupt_line_quirk)
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
return 0;
}
diff --git a/trunk/arch/ia64/ia32/ia32_ioctl.c b/trunk/arch/ia64/ia32/ia32_ioctl.c
index 164b211f4174..9845dabe2613 100644
--- a/trunk/arch/ia64/ia32/ia32_ioctl.c
+++ b/trunk/arch/ia64/ia32/ia32_ioctl.c
@@ -13,6 +13,7 @@
#define INCLUDES
#include "compat_ioctl.c"
+#include
#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
diff --git a/trunk/arch/ia64/ia32/sys_ia32.c b/trunk/arch/ia64/ia32/sys_ia32.c
index c1e20d65dd6c..247a21c64aea 100644
--- a/trunk/arch/ia64/ia32/sys_ia32.c
+++ b/trunk/arch/ia64/ia32/sys_ia32.c
@@ -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 numevents, size;
+ int error, numevents, size;
int evt_idx;
int do_free_pages = 0;
diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S
index d99316c9be28..81c45d447394 100644
--- a/trunk/arch/ia64/kernel/entry.S
+++ b/trunk/arch/ia64/kernel/entry.S
@@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user)
;;
(pNonSys) mov out2=0 // out2==0 => not a syscall
.fframe 16
- .spillsp ar.unat, 16
+ .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
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
- .spillsp ar.unat, 16
+ .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
diff --git a/trunk/arch/ia64/kernel/mca.c b/trunk/arch/ia64/kernel/mca.c
index 736e328b5e61..4d6c7b8f667b 100644
--- a/trunk/arch/ia64/kernel/mca.c
+++ b/trunk/arch/ia64/kernel/mca.c
@@ -1103,6 +1103,8 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
return IRQ_HANDLED;
}
+#endif /* CONFIG_ACPI */
+
/*
* ia64_mca_cpe_poll
*
@@ -1120,8 +1122,6 @@ 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,7 +1390,8 @@ ia64_mca_init(void)
register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
#ifdef CONFIG_ACPI
- /* Setup the CPEI/P handler */
+ /* Setup the CPEI/P vector and handler */
+ cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
#endif
@@ -1435,7 +1436,6 @@ 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;
diff --git a/trunk/arch/ia64/kernel/minstate.h b/trunk/arch/ia64/kernel/minstate.h
index f6d8a010d99b..1dbc7b2497c9 100644
--- a/trunk/arch/ia64/kernel/minstate.h
+++ b/trunk/arch/ia64/kernel/minstate.h
@@ -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 r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
+(pKStk) addl sp=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,6 +50,7 @@
(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; \
diff --git a/trunk/arch/ia64/kernel/perfmon.c b/trunk/arch/ia64/kernel/perfmon.c
index 6407bff6bfd7..71c101601e3e 100644
--- a/trunk/arch/ia64/kernel/perfmon.c
+++ b/trunk/arch/ia64/kernel/perfmon.c
@@ -11,7 +11,7 @@
* Version Perfmon-2.x is a rewrite of perfmon-1.x
* by Stephane Eranian, Hewlett Packard Co.
*
- * Copyright (C) 1999-2005 Hewlett Packard Co
+ * Copyright (C) 1999-2003, 2005 Hewlett Packard Co
* Stephane Eranian
* David Mosberger-Tang
*
@@ -497,9 +497,6 @@ 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,};
@@ -609,7 +606,6 @@ 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 */
@@ -1329,7 +1325,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,
- cpu));
+ smp_processor_id()));
abort:
UNLOCK_PFS(flags);
@@ -5559,32 +5555,26 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
int ret;
this_cpu = get_cpu();
- 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;
+ 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;
- }
- }
- else {
- (*pfm_alt_intr_handler->handler)(irq, arg, regs);
+ pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
}
-
put_cpu_no_resched();
return IRQ_HANDLED;
}
@@ -6435,141 +6425,6 @@ 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
*/
diff --git a/trunk/arch/ia64/kernel/ptrace.c b/trunk/arch/ia64/kernel/ptrace.c
index 08c8a5eb25ab..907464ee7273 100644
--- a/trunk/arch/ia64/kernel/ptrace.c
+++ b/trunk/arch/ia64/kernel/ptrace.c
@@ -692,30 +692,16 @@ 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, sp, pr;
+ unsigned long ip, pr;
unw_init_from_blocked_task(&info, child);
while (1) {
prev_info = info;
if (unw_unwind(&info) < 0)
return;
-
- 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);
+ if (unw_get_rp(&info, &ip) < 0)
return;
- }
- if (unw_is_intr_frame(&info)
- && (pr & (1UL << PRED_USER_STACK)))
+ if (ip < FIXADDR_USER_END)
break;
}
diff --git a/trunk/arch/ia64/kernel/smpboot.c b/trunk/arch/ia64/kernel/smpboot.c
index 3865f088ffa2..0d5ee57c9865 100644
--- a/trunk/arch/ia64/kernel/smpboot.c
+++ b/trunk/arch/ia64/kernel/smpboot.c
@@ -624,7 +624,7 @@ static struct {
__u16 thread_id;
__u16 proc_fixed_addr;
__u8 valid;
-} mt_info[NR_CPUS] __devinitdata;
+}mt_info[NR_CPUS] __devinit;
#ifdef CONFIG_HOTPLUG_CPU
static inline void
diff --git a/trunk/arch/ia64/kernel/sys_ia64.c b/trunk/arch/ia64/kernel/sys_ia64.c
index 770fab37928e..a8cf6d8a509c 100644
--- a/trunk/arch/ia64/kernel/sys_ia64.c
+++ b/trunk/arch/ia64/kernel/sys_ia64.c
@@ -182,6 +182,13 @@ 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) {
diff --git a/trunk/arch/ia64/sn/kernel/setup.c b/trunk/arch/ia64/sn/kernel/setup.c
index e64cb8175f7a..4fb44984afe6 100644
--- a/trunk/arch/ia64/sn/kernel/setup.c
+++ b/trunk/arch/ia64/sn/kernel/setup.c
@@ -271,8 +271,6 @@ 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
diff --git a/trunk/arch/m68knommu/kernel/process.c b/trunk/arch/m68knommu/kernel/process.c
index c4a33f265dc0..2b6c9d32b7a6 100644
--- a/trunk/arch/m68knommu/kernel/process.c
+++ b/trunk/arch/m68knommu/kernel/process.c
@@ -45,13 +45,11 @@ asmlinkage void ret_from_fork(void);
*/
void default_idle(void)
{
- local_irq_disable();
- while (!need_resched()) {
- /* This stop will re-enable interrupts */
- __asm__("stop #0x2000" : : : "cc");
- local_irq_disable();
+ while(1) {
+ if (need_resched())
+ __asm__("stop #0x2000" : : : "cc");
+ schedule();
}
- local_irq_enable();
}
void (*idle)(void) = default_idle;
@@ -65,12 +63,7 @@ void (*idle)(void) = default_idle;
void cpu_idle(void)
{
/* endless idle loop with no priority at all */
- while (1) {
- idle();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
+ idle();
}
void machine_restart(char * __unused)
diff --git a/trunk/arch/mips/vr41xx/common/pmu.c b/trunk/arch/mips/vr41xx/common/pmu.c
index 53166f3598b2..c5f1043de938 100644
--- a/trunk/arch/mips/vr41xx/common/pmu.c
+++ b/trunk/arch/mips/vr41xx/common/pmu.c
@@ -1,7 +1,7 @@
/*
* pmu.c, Power Management Unit routines for NEC VR4100 series.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa
+ * Copyright (C) 2003-2004 Yoichi Yuasa
*
* 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
@@ -17,9 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include
#include
-#include
#include
#include
#include
@@ -29,31 +27,20 @@
#include
#include
-#define PMU_TYPE1_BASE 0x0b0000a0UL
-#define PMU_TYPE1_SIZE 0x0eUL
-
-#define PMU_TYPE2_BASE 0x0f0000c0UL
-#define PMU_TYPE2_SIZE 0x10UL
-
-#define PMUCNT2REG 0x06
+#define PMUCNT2REG KSEG1ADDR(0x0f0000c6)
#define SOFTRST 0x0010
-static void __iomem *pmu_base;
-
-#define pmu_read(offset) readw(pmu_base + (offset))
-#define pmu_write(offset, value) writew((value), pmu_base + (offset))
-
static inline void software_reset(void)
{
- uint16_t pmucnt2;
+ uint16_t val;
switch (current_cpu_data.cputype) {
case CPU_VR4122:
case CPU_VR4131:
case CPU_VR4133:
- pmucnt2 = pmu_read(PMUCNT2REG);
- pmucnt2 |= SOFTRST;
- pmu_write(PMUCNT2REG, pmucnt2);
+ val = readw(PMUCNT2REG);
+ val |= SOFTRST;
+ writew(val, PMUCNT2REG);
break;
default:
break;
@@ -84,34 +71,6 @@ static void vr41xx_power_off(void)
static int __init vr41xx_pmu_init(void)
{
- unsigned long start, size;
-
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- start = PMU_TYPE1_BASE;
- size = PMU_TYPE1_SIZE;
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- start = PMU_TYPE2_BASE;
- size = PMU_TYPE2_SIZE;
- break;
- default:
- printk("Unexpected CPU of NEC VR4100 series\n");
- return -ENODEV;
- }
-
- if (request_mem_region(start, size, "PMU") == NULL)
- return -EBUSY;
-
- pmu_base = ioremap(start, size);
- if (pmu_base == NULL) {
- release_mem_region(start, size);
- return -EBUSY;
- }
-
_machine_restart = vr41xx_restart;
_machine_halt = vr41xx_halt;
_machine_power_off = vr41xx_power_off;
@@ -119,4 +78,4 @@ static int __init vr41xx_pmu_init(void)
return 0;
}
-core_initcall(vr41xx_pmu_init);
+early_initcall(vr41xx_pmu_init);
diff --git a/trunk/arch/ppc/Kconfig b/trunk/arch/ppc/Kconfig
index 6e6377a69d5b..600f23d7fd33 100644
--- a/trunk/arch/ppc/Kconfig
+++ b/trunk/arch/ppc/Kconfig
@@ -1143,12 +1143,12 @@ config PCI_QSPAN
config PCI_8260
bool
- depends on PCI && 8260
+ depends on PCI && 8260 && !8272
default y
config 8260_PCI9
bool " Enable workaround for MPC826x erratum PCI 9"
- depends on PCI_8260 && !ADS8272
+ depends on PCI_8260
default y
choice
diff --git a/trunk/arch/ppc/boot/images/Makefile b/trunk/arch/ppc/boot/images/Makefile
index c9ac5f5fa9e4..f850fb0fb511 100644
--- a/trunk/arch/ppc/boot/images/Makefile
+++ b/trunk/arch/ppc/boot/images/Makefile
@@ -22,8 +22,7 @@ targets += uImage
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
$(call if_changed,uimage)
- @echo -n ' Image: $@ '
- @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
+ @echo ' Image: $@' $(if $(wildcard $@),'is ready','not made')
# Files generated that shall be removed upon make clean
clean-files := sImage vmapus vmlinux* miboot* zImage* uImage
diff --git a/trunk/arch/ppc/configs/mpc8555_cds_defconfig b/trunk/arch/ppc/configs/mpc8555_cds_defconfig
index 15abebf46b96..728bd9e1a8fa 100644
--- a/trunk/arch/ppc/configs/mpc8555_cds_defconfig
+++ b/trunk/arch/ppc/configs/mpc8555_cds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Tue May 17 11:56:01 2005
+# Linux kernel version: 2.6.11-rc1
+# Thu Jan 20 01:25:35 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
@@ -11,7 +11,6 @@ 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
@@ -19,7 +18,6 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -31,14 +29,12 @@ 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
@@ -48,7 +44,6 @@ 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
@@ -67,12 +62,10 @@ CONFIG_BASE_SMALL=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
@@ -83,7 +76,6 @@ 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
@@ -98,7 +90,6 @@ 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
@@ -113,6 +104,10 @@ CONFIG_PCI_NAMES=y
#
# CONFIG_PCCARD is not set
+#
+# PC-card bridges
+#
+
#
# Advanced setup
#
@@ -185,59 +180,7 @@ CONFIG_IOSCHED_CFQ=y
#
# ATA/ATAPI/MFM/RLL support
#
-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
+# CONFIG_IDE is not set
#
# SCSI device support
@@ -277,6 +220,7 @@ 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
@@ -425,6 +369,14 @@ 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
#
@@ -434,13 +386,6 @@ CONFIG_INPUT=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
#
@@ -461,7 +406,6 @@ 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
@@ -489,11 +433,6 @@ 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
#
@@ -517,11 +456,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
@@ -544,9 +483,7 @@ 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
@@ -557,11 +494,9 @@ 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
@@ -571,12 +506,10 @@ 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
@@ -605,6 +538,7 @@ CONFIG_I2C_MPC=y
# Graphics support
#
# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -614,9 +548,13 @@ CONFIG_I2C_MPC=y
#
# USB support
#
+# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -647,10 +585,6 @@ 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
@@ -712,6 +646,7 @@ 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
@@ -763,9 +698,7 @@ 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
diff --git a/trunk/arch/ppc/kernel/head_44x.S b/trunk/arch/ppc/kernel/head_44x.S
index 6c7ae6052464..9b6a8e513657 100644
--- a/trunk/arch/ppc/kernel/head_44x.S
+++ b/trunk/arch/ppc/kernel/head_44x.S
@@ -330,9 +330,8 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
+ andis. r11, r10, 0x8000
+ beq 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -465,9 +464,8 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
+ andis. r11, r10, 0x8000
+ beq 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -535,9 +533,8 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- lis r11, TASK_SIZE@h
- cmplw r10, r11
- blt+ 3f
+ andis. r11, r10, 0x8000
+ beq 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
diff --git a/trunk/arch/ppc/kernel/head_fsl_booke.S b/trunk/arch/ppc/kernel/head_fsl_booke.S
index ce36e88ba627..f22ddce36135 100644
--- a/trunk/arch/ppc/kernel/head_fsl_booke.S
+++ b/trunk/arch/ppc/kernel/head_fsl_booke.S
@@ -232,8 +232,7 @@ skpinv: addi r6,r6,1 /* Increment */
tlbwe
/* 7. Jump to KERNELBASE mapping */
- lis r7,MSR_KERNEL@h
- ori r7,r7,MSR_KERNEL@l
+ li r7,0
bl 1f /* Find our address */
1: mflr r9
rlwimi r6,r9,0,20,31
@@ -294,18 +293,6 @@ 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.
*/
diff --git a/trunk/arch/ppc/kernel/setup.c b/trunk/arch/ppc/kernel/setup.c
index 5c20266e3b1f..5dfb42f1a152 100644
--- a/trunk/arch/ppc/kernel/setup.c
+++ b/trunk/arch/ppc/kernel/setup.c
@@ -499,7 +499,7 @@ static int __init set_preferred_console(void)
{
struct device_node *prom_stdout;
char *name;
- int offset = 0;
+ int offset;
if (of_stdout_device == NULL)
return -ENODEV;
@@ -753,8 +753,6 @@ void __init setup_arch(char **cmdline_p)
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
*cmdline_p = cmd_line;
- parse_early_param();
-
/* set up the bootmem stuff with available memory */
do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
diff --git a/trunk/arch/ppc/kernel/traps.c b/trunk/arch/ppc/kernel/traps.c
index c65731e8bc65..f8e7e324a173 100644
--- a/trunk/arch/ppc/kernel/traps.c
+++ b/trunk/arch/ppc/kernel/traps.c
@@ -408,7 +408,12 @@ 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 ((rT == rA) || (rT == NB_RB))
+ 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))
return -EINVAL;
EA = (rA == 0) ? 0 : regs->gpr[rA];
diff --git a/trunk/arch/ppc/lib/string.S b/trunk/arch/ppc/lib/string.S
index 36c9b97fd92a..8d08a2eb225e 100644
--- a/trunk/arch/ppc/lib/string.S
+++ b/trunk/arch/ppc/lib/string.S
@@ -446,7 +446,6 @@ _GLOBAL(__copy_tofrom_user)
#ifdef CONFIG_8xx
/* Don't use prefetch on 8xx */
mtctr r0
- li r0,0
53: COPY_16_BYTES_WITHEX(0)
bdnz 53b
@@ -565,9 +564,7 @@ _GLOBAL(__copy_tofrom_user)
/* or write fault in cacheline loop */
105: li r9,1
92: li r3,LG_CACHELINE_BYTES
- mfctr r8
- add r0,r0,r8
- b 106f
+ b 99f
/* read fault in final word loop */
108: li r9,0
b 93f
@@ -588,7 +585,7 @@ _GLOBAL(__copy_tofrom_user)
* r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
*/
99: mfctr r0
-106: slw r3,r0,r3
+ slw r3,r0,r3
add. r3,r3,r5
beq 120f /* shouldn't happen */
cmpwi 0,r9,0
diff --git a/trunk/arch/ppc/mm/init.c b/trunk/arch/ppc/mm/init.c
index 363c157e3617..be02a7fec2b7 100644
--- a/trunk/arch/ppc/mm/init.c
+++ b/trunk/arch/ppc/mm/init.c
@@ -179,7 +179,6 @@ void free_initmem(void)
if (!have_of)
FREESEC(openfirmware);
printk("\n");
- ppc_md.progress = NULL;
#undef FREESEC
}
diff --git a/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c b/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c
index e6348b5a1ddc..b3b0f51979d2 100644
--- a/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -127,6 +127,7 @@ 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
diff --git a/trunk/arch/ppc/platforms/83xx/mpc834x_sys.h b/trunk/arch/ppc/platforms/83xx/mpc834x_sys.h
index a2f6e49d7151..f4d055ae19c1 100644
--- a/trunk/arch/ppc/platforms/83xx/mpc834x_sys.h
+++ b/trunk/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -26,14 +26,9 @@
#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
diff --git a/trunk/arch/ppc/platforms/85xx/mpc8540_ads.c b/trunk/arch/ppc/platforms/85xx/mpc8540_ads.c
index 583838ab02d8..4d857d6d633d 100644
--- a/trunk/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/trunk/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -210,9 +210,6 @@ 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);
diff --git a/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index e7cfa498568c..6c020d67ad70 100644
--- a/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -44,7 +44,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -182,7 +181,6 @@ 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;
@@ -200,15 +198,6 @@ 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();
@@ -242,7 +231,7 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
* interrupt on slot */
{
{ 0, 1, 2, 3 }, /* 16 - PMC */
- { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
+ { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */
{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
@@ -291,135 +280,13 @@ 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) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+ if (bus == 1)
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();
@@ -461,9 +328,6 @@ 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
@@ -595,9 +459,6 @@ 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);
diff --git a/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
index 12b292c6ae32..7627d77504bd 100644
--- a/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+++ b/trunk/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
@@ -77,7 +77,4 @@
#define MPC85XX_PCI2_IO_SIZE 0x01000000
-#define NR_8259_INTS 16
-#define CPM_IRQ_OFFSET NR_8259_INTS
-
#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/trunk/arch/ppc/platforms/85xx/sbc8560.c b/trunk/arch/ppc/platforms/85xx/sbc8560.c
index 7b9e1543e175..9ab05e590c3e 100644
--- a/trunk/arch/ppc/platforms/85xx/sbc8560.c
+++ b/trunk/arch/ppc/platforms/85xx/sbc8560.c
@@ -221,9 +221,6 @@ 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);
diff --git a/trunk/arch/ppc/platforms/pmac_cpufreq.c b/trunk/arch/ppc/platforms/pmac_cpufreq.c
index 937f46df711e..f7fb2786cd50 100644
--- a/trunk/arch/ppc/platforms/pmac_cpufreq.c
+++ b/trunk/arch/ppc/platforms/pmac_cpufreq.c
@@ -85,11 +85,14 @@ 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 0
-#define CPUFREQ_LOW 1
+#define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED
+#define CPUFREQ_LOW PMAC_CPU_LOW_SPEED
static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
{CPUFREQ_HIGH, 0},
@@ -97,11 +100,6 @@ 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)
@@ -271,8 +269,6 @@ 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);
@@ -347,8 +343,6 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
debug_calc_bogomips();
#endif
- pmu_resume();
-
preempt_enable();
return 0;
@@ -361,7 +355,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 == CPUFREQ_HIGH) ? hi_freq : low_freq;
+ freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
freqs.cpu = smp_processor_id();
if (freqs.old == freqs.new)
@@ -369,7 +363,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
if (notify)
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- if (speed_mode == CPUFREQ_LOW &&
+ if (speed_mode == PMAC_CPU_LOW_SPEED &&
cpu_has_feature(CPU_FTR_L3CR)) {
l3cr = _get_L3CR();
if (l3cr & L3CR_L3E) {
@@ -377,8 +371,8 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
_set_L3CR(0);
}
}
- set_speed_proc(speed_mode == CPUFREQ_LOW);
- if (speed_mode == CPUFREQ_HIGH &&
+ set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
+ if (speed_mode == PMAC_CPU_HIGH_SPEED &&
cpu_has_feature(CPU_FTR_L3CR)) {
l3cr = _get_L3CR();
if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
@@ -386,7 +380,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 == CPUFREQ_HIGH) ? hi_freq : low_freq;
+ cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
return 0;
}
@@ -429,8 +423,7 @@ static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = cur_freq;
- cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
- return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
+ return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]);
}
static u32 __pmac read_gpio(struct device_node *np)
@@ -464,7 +457,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(CPUFREQ_HIGH, 0);
+ do_set_cpu_speed(PMAC_CPU_HIGH_SPEED, 0);
return 0;
}
@@ -480,8 +473,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 ?
- CPUFREQ_LOW : CPUFREQ_HIGH, 0);
+ do_set_cpu_speed(sleep_freq == low_freq ? PMAC_CPU_LOW_SPEED
+ : PMAC_CPU_HIGH_SPEED, 0);
no_schedule = 0;
return 0;
@@ -495,7 +488,6 @@ 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,
};
diff --git a/trunk/arch/ppc/platforms/pq2ads.h b/trunk/arch/ppc/platforms/pq2ads.h
index 067d9a5aebc1..cf5e5dd06d63 100644
--- a/trunk/arch/ppc/platforms/pq2ads.h
+++ b/trunk/arch/ppc/platforms/pq2ads.h
@@ -49,10 +49,10 @@
/* PCI interrupt controller */
#define PCI_INT_STAT_REG 0xF8200000
#define PCI_INT_MASK_REG 0xF8200004
-#define PIRQA (NR_CPM_INTS + 0)
-#define PIRQB (NR_CPM_INTS + 1)
-#define PIRQC (NR_CPM_INTS + 2)
-#define PIRQD (NR_CPM_INTS + 3)
+#define PIRQA (NR_SIU_INTS + 0)
+#define PIRQB (NR_SIU_INTS + 1)
+#define PIRQC (NR_SIU_INTS + 2)
+#define PIRQD (NR_SIU_INTS + 3)
/*
* PCI memory map definitions for MPC8266ADS-PCI.
@@ -68,23 +68,28 @@
* 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory
*/
-/* 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 a PCI master to access MPC8266 memory */
+#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */
+#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */
-#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 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 */
-#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 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 */
+/* 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 */
diff --git a/trunk/arch/ppc/syslib/Makefile b/trunk/arch/ppc/syslib/Makefile
index 96acf85800d4..dd418ea3426c 100644
--- a/trunk/arch/ppc/syslib/Makefile
+++ b/trunk/arch/ppc/syslib/Makefile
@@ -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) += m82xx_pci.o indirect_pci.o pci_auto.o
+obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.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 i8259.o mpc85xx_sys.o \
+ ppc_sys.o mpc85xx_sys.o \
mpc85xx_devices.o
ifeq ($(CONFIG_85xx),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
diff --git a/trunk/arch/ppc/syslib/ipic.c b/trunk/arch/ppc/syslib/ipic.c
index 580ed658e872..acb2cde3171f 100644
--- a/trunk/arch/ppc/syslib/ipic.c
+++ b/trunk/arch/ppc/syslib/ipic.c
@@ -479,7 +479,7 @@ void __init ipic_init(phys_addr_t phys_addr,
temp = 0;
for (i = 0 ; i < senses_count ; i++) {
if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
- temp |= 1 << (15 - i);
+ temp |= 1 << (16 - i);
if (i != 0)
irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
else
diff --git a/trunk/arch/ppc/syslib/m8260_pci.c b/trunk/arch/ppc/syslib/m8260_pci.c
new file mode 100644
index 000000000000..057cc3f8ff37
--- /dev/null
+++ b/trunk/arch/ppc/syslib/m8260_pci.c
@@ -0,0 +1,193 @@
+/*
+ * (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
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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/trunk/arch/ppc/syslib/m8260_pci.h b/trunk/arch/ppc/syslib/m8260_pci.h
new file mode 100644
index 000000000000..d1352120acd7
--- /dev/null
+++ b/trunk/arch/ppc/syslib/m8260_pci.h
@@ -0,0 +1,76 @@
+
+#ifndef _PPC_KERNEL_M8260_PCI_H
+#define _PPC_KERNEL_M8260_PCI_H
+
+#include
+
+/*
+ * 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 */
diff --git a/trunk/arch/ppc/syslib/m8260_pci_erratum9.c b/trunk/arch/ppc/syslib/m8260_pci_erratum9.c
index 1dc7e4e1d491..9c0582d639e0 100644
--- a/trunk/arch/ppc/syslib/m8260_pci_erratum9.c
+++ b/trunk/arch/ppc/syslib/m8260_pci_erratum9.c
@@ -31,7 +31,7 @@
#include
#include
-#include "m82xx_pci.h"
+#include "m8260_pci.h"
#ifdef CONFIG_8260_PCI9
/*#include */ /* 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 >= M82xx_PCI_LOWER_MMIO &&
- addr <= M82xx_PCI_UPPER_MMIO)
+ if (addr >= MPC826x_PCI_LOWER_MMIO &&
+ addr <= MPC826x_PCI_UPPER_MMIO)
return 1;
- if (addr >= M82xx_PCI_LOWER_MEM &&
- addr <= M82xx_PCI_UPPER_MEM)
+ if (addr >= MPC826x_PCI_LOWER_MEM &&
+ addr <= MPC826x_PCI_UPPER_MEM)
return 1;
return 0;
}
diff --git a/trunk/arch/ppc/syslib/m8260_setup.c b/trunk/arch/ppc/syslib/m8260_setup.c
index fda75d79050c..23ea3f694de2 100644
--- a/trunk/arch/ppc/syslib/m8260_setup.c
+++ b/trunk/arch/ppc/syslib/m8260_setup.c
@@ -34,8 +34,7 @@
unsigned char __res[sizeof(bd_t)];
extern void cpm2_reset(void);
-extern void pq2_find_bridges(void);
-extern void pq2pci_init_irq(void);
+extern void m8260_find_bridges(void);
extern void idma_pci9_init(void);
/* Place-holder for board-specific init */
@@ -57,7 +56,7 @@ m8260_setup_arch(void)
idma_pci9_init();
#endif
#ifdef CONFIG_PCI_8260
- pq2_find_bridges();
+ m8260_find_bridges();
#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -174,12 +173,6 @@ 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/trunk/arch/ppc/syslib/m82xx_pci.c b/trunk/arch/ppc/syslib/m82xx_pci.c
deleted file mode 100644
index 5e7a7edcea74..000000000000
--- a/trunk/arch/ppc/syslib/m82xx_pci.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- *
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2004 Red Hat, Inc.
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug
- *
- * 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
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#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/trunk/arch/ppc/syslib/m82xx_pci.h b/trunk/arch/ppc/syslib/m82xx_pci.h
deleted file mode 100644
index 924f73f8e595..000000000000
--- a/trunk/arch/ppc/syslib/m82xx_pci.h
+++ /dev/null
@@ -1,92 +0,0 @@
-
-#ifndef _PPC_KERNEL_M82XX_PCI_H
-#define _PPC_KERNEL_M82XX_PCI_H
-
-#include
-/*
- * 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 */
diff --git a/trunk/arch/ppc/syslib/mpc83xx_devices.c b/trunk/arch/ppc/syslib/mpc83xx_devices.c
index 75c8e9834ae7..5c1a919eaabf 100644
--- a/trunk/arch/ppc/syslib/mpc83xx_devices.c
+++ b/trunk/arch/ppc/syslib/mpc83xx_devices.c
@@ -61,7 +61,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
- { },
};
struct platform_device ppc_sys_platform_devices[] = {
diff --git a/trunk/arch/ppc/syslib/mpc85xx_devices.c b/trunk/arch/ppc/syslib/mpc85xx_devices.c
index 1e658ef57e75..a231795ee26f 100644
--- a/trunk/arch/ppc/syslib/mpc85xx_devices.c
+++ b/trunk/arch/ppc/syslib/mpc85xx_devices.c
@@ -61,7 +61,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
},
- { },
};
struct platform_device ppc_sys_platform_devices[] = {
diff --git a/trunk/arch/ppc/syslib/open_pic.c b/trunk/arch/ppc/syslib/open_pic.c
index 000ba47c67cb..7619e16fccae 100644
--- a/trunk/arch/ppc/syslib/open_pic.c
+++ b/trunk/arch/ppc/syslib/open_pic.c
@@ -275,7 +275,7 @@ static void __init openpic_enable_sie(void)
}
#endif
-#if defined(CONFIG_EPIC_SERIAL_MODE)
+#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM)
static void openpic_reset(void)
{
openpic_setfield(&OpenPIC->Global.Global_Configuration0,
@@ -557,10 +557,12 @@ static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
*/
void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
{
+ cpumask_t phys;
DECL_THIS_CPU;
CHECK_THIS_CPU;
check_arg_ipi(ipi);
+ phys = physmask(cpumask);
openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
cpus_addr(physmask(cpumask))[0]);
}
@@ -993,6 +995,8 @@ 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);
diff --git a/trunk/arch/ppc/syslib/ppc83xx_setup.c b/trunk/arch/ppc/syslib/ppc83xx_setup.c
index 843cf8873e60..c28f9d679484 100644
--- a/trunk/arch/ppc/syslib/ppc83xx_setup.c
+++ b/trunk/arch/ppc/syslib/ppc83xx_setup.c
@@ -29,7 +29,6 @@
#include
#include
#include
-#include
#include
@@ -118,34 +117,7 @@ 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(;;);
}
diff --git a/trunk/arch/ppc/syslib/ppc85xx_setup.c b/trunk/arch/ppc/syslib/ppc85xx_setup.c
index f3277f469e78..152c3ef1312a 100644
--- a/trunk/arch/ppc/syslib/ppc85xx_setup.c
+++ b/trunk/arch/ppc/syslib/ppc85xx_setup.c
@@ -132,12 +132,6 @@ 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)
{
@@ -308,18 +302,8 @@ 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();
diff --git a/trunk/arch/ppc/syslib/prom_init.c b/trunk/arch/ppc/syslib/prom_init.c
index 7f15136830f4..2cee87137f2e 100644
--- a/trunk/arch/ppc/syslib/prom_init.c
+++ b/trunk/arch/ppc/syslib/prom_init.c
@@ -626,18 +626,8 @@ 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);
}
diff --git a/trunk/arch/ppc64/kernel/entry.S b/trunk/arch/ppc64/kernel/entry.S
index b61572eb2a71..d3604056e1a9 100644
--- a/trunk/arch/ppc64/kernel/entry.S
+++ b/trunk/arch/ppc64/kernel/entry.S
@@ -436,6 +436,15 @@ 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 */
diff --git a/trunk/arch/ppc64/kernel/head.S b/trunk/arch/ppc64/kernel/head.S
index 346dbf606b5d..92a744c31ab1 100644
--- a/trunk/arch/ppc64/kernel/head.S
+++ b/trunk/arch/ppc64/kernel/head.S
@@ -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,SPRN_CTRLF
- li r5,CTRL_RUNLATCH /* Turn off the run light */
+ mfspr r4,CTRLF
+ li r5,RUNLATCH /* Turn off the run light */
andc r4,r4,r5
- mtspr SPRN_CTRLT,r4
+ mtspr 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, SPRN_CTRLF
+ mfspr r4, CTRLF
oris r4, r4, 0x40
- mtspr SPRN_CTRLT, r4
+ mtspr CTRLT, r4
blr
#endif
diff --git a/trunk/arch/ppc64/kernel/iSeries_setup.c b/trunk/arch/ppc64/kernel/iSeries_setup.c
index 6d06eb550a3f..da20120f2261 100644
--- a/trunk/arch/ppc64/kernel/iSeries_setup.c
+++ b/trunk/arch/ppc64/kernel/iSeries_setup.c
@@ -852,28 +852,6 @@ 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();
diff --git a/trunk/arch/ppc64/kernel/idle.c b/trunk/arch/ppc64/kernel/idle.c
index f24ce2b87200..6abc621d3ba0 100644
--- a/trunk/arch/ppc64/kernel/idle.c
+++ b/trunk/arch/ppc64/kernel/idle.c
@@ -75,9 +75,13 @@ static int iSeries_idle(void)
{
struct paca_struct *lpaca;
long oldval;
+ unsigned long CTRL;
/* ensure iSeries run light will be out when idle */
- ppc64_runlatch_off();
+ clear_thread_flag(TIF_RUN_LIGHT);
+ CTRL = mfspr(CTRLF);
+ CTRL &= ~RUNLATCH;
+ mtspr(CTRLT, CTRL);
lpaca = get_paca();
@@ -107,9 +111,7 @@ static int iSeries_idle(void)
}
}
- ppc64_runlatch_on();
schedule();
- ppc64_runlatch_off();
}
return 0;
diff --git a/trunk/arch/ppc64/kernel/mf.c b/trunk/arch/ppc64/kernel/mf.c
index 5aca7e8005a8..1bd52ece497c 100644
--- a/trunk/arch/ppc64/kernel/mf.c
+++ b/trunk/arch/ppc64/kernel/mf.c
@@ -1,7 +1,7 @@
/*
* mf.c
* Copyright (C) 2001 Troy D. Armstrong IBM Corporation
- * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
+ * Copyright (C) 2004 Stephen Rothwell IBM Corporation
*
* This modules exists as an interface between a Linux secondary partition
* running on an iSeries and the primary partition's Virtual Service
@@ -36,12 +36,10 @@
#include
#include
-#include
#include
#include
#include
#include
-#include
/*
* This is the structure layout for the Machine Facilites LPAR event
@@ -698,23 +696,36 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
complete(&rtc->com);
}
-static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
+int mf_get_rtc(struct rtc_time *tm)
{
+ struct ce_msg_comp_data ce_complete;
+ struct rtc_time_data rtc_data;
+ int rc;
+
+ memset(&ce_complete, 0, sizeof(ce_complete));
+ memset(&rtc_data, 0, sizeof(rtc_data));
+ init_completion(&rtc_data.com);
+ ce_complete.handler = &get_rtc_time_complete;
+ ce_complete.token = &rtc_data;
+ rc = signal_ce_msg_simple(0x40, &ce_complete);
+ if (rc)
+ return rc;
+ wait_for_completion(&rtc_data.com);
tm->tm_wday = 0;
tm->tm_yday = 0;
tm->tm_isdst = 0;
- if (rc) {
+ if (rtc_data.rc) {
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 0;
tm->tm_mday = 15;
tm->tm_mon = 5;
tm->tm_year = 52;
- return rc;
+ return rtc_data.rc;
}
- if ((ce_msg[2] == 0xa9) ||
- (ce_msg[2] == 0xaf)) {
+ if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) ||
+ (rtc_data.ce_msg.ce_msg[2] == 0xaf)) {
/* TOD clock is not set */
tm->tm_sec = 1;
tm->tm_min = 1;
@@ -725,6 +736,7 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
mf_set_rtc(tm);
}
{
+ u8 *ce_msg = rtc_data.ce_msg.ce_msg;
u8 year = ce_msg[5];
u8 sec = ce_msg[6];
u8 min = ce_msg[7];
@@ -753,63 +765,6 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
return 0;
}
-int mf_get_rtc(struct rtc_time *tm)
-{
- struct ce_msg_comp_data ce_complete;
- struct rtc_time_data rtc_data;
- int rc;
-
- memset(&ce_complete, 0, sizeof(ce_complete));
- memset(&rtc_data, 0, sizeof(rtc_data));
- init_completion(&rtc_data.com);
- ce_complete.handler = &get_rtc_time_complete;
- ce_complete.token = &rtc_data;
- rc = signal_ce_msg_simple(0x40, &ce_complete);
- if (rc)
- return rc;
- wait_for_completion(&rtc_data.com);
- return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
-}
-
-struct boot_rtc_time_data {
- int busy;
- struct ce_msg_data ce_msg;
- int rc;
-};
-
-static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
-{
- struct boot_rtc_time_data *rtc = token;
-
- memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
- rtc->rc = 0;
- rtc->busy = 0;
-}
-
-int mf_get_boot_rtc(struct rtc_time *tm)
-{
- struct ce_msg_comp_data ce_complete;
- struct boot_rtc_time_data rtc_data;
- int rc;
-
- memset(&ce_complete, 0, sizeof(ce_complete));
- memset(&rtc_data, 0, sizeof(rtc_data));
- rtc_data.busy = 1;
- ce_complete.handler = &get_boot_rtc_time_complete;
- ce_complete.token = &rtc_data;
- rc = signal_ce_msg_simple(0x40, &ce_complete);
- if (rc)
- return rc;
- /* We need to poll here as we are not yet taking interrupts */
- while (rtc_data.busy) {
- extern unsigned long lpevent_count;
- struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
- if (lpq && ItLpQueue_isLpIntPending(lpq))
- lpevent_count += ItLpQueue_process(lpq, NULL);
- }
- return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
-}
-
int mf_set_rtc(struct rtc_time *tm)
{
char ce_time[12];
diff --git a/trunk/arch/ppc64/kernel/pSeries_reconfig.c b/trunk/arch/ppc64/kernel/pSeries_reconfig.c
index dc2a69d412a2..cb5443f2e49b 100644
--- a/trunk/arch/ppc64/kernel/pSeries_reconfig.c
+++ b/trunk/arch/ppc64/kernel/pSeries_reconfig.c
@@ -47,6 +47,14 @@ 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);
}
diff --git a/trunk/arch/ppc64/kernel/pmac_smp.c b/trunk/arch/ppc64/kernel/pmac_smp.c
index a23de37227bf..c27588ede2fe 100644
--- a/trunk/arch/ppc64/kernel/pmac_smp.c
+++ b/trunk/arch/ppc64/kernel/pmac_smp.c
@@ -68,7 +68,6 @@ extern struct smp_ops_t *smp_ops;
static void (*pmac_tb_freeze)(int freeze);
static struct device_node *pmac_tb_clock_chip_host;
-static u8 pmac_tb_pulsar_addr;
static DEFINE_SPINLOCK(timebase_lock);
static unsigned long timebase;
@@ -107,9 +106,12 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
u8 data;
int rc;
+ /* Strangely, the device-tree says address is 0xd2, but darwin
+ * accesses 0xd0 ...
+ */
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- pmac_tb_pulsar_addr | pmac_low_i2c_read,
+ 0xd4 | pmac_low_i2c_read,
0x2e, &data, 1);
if (rc != 0)
goto bail;
@@ -118,7 +120,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- pmac_tb_pulsar_addr | pmac_low_i2c_write,
+ 0xd4 | pmac_low_i2c_write,
0x2e, &data, 1);
bail:
if (rc != 0) {
@@ -183,12 +185,6 @@ static int __init smp_core99_probe(void)
if (ncpus <= 1)
return 1;
- /* HW sync only on these platforms */
- if (!machine_is_compatible("PowerMac7,2") &&
- !machine_is_compatible("PowerMac7,3") &&
- !machine_is_compatible("RackMac3,1"))
- goto nohwsync;
-
/* Look for the clock chip */
for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
struct device_node *p = of_get_parent(cc);
@@ -202,18 +198,11 @@ static int __init smp_core99_probe(void)
goto next;
switch (*reg) {
case 0xd2:
- if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
- pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
- pmac_tb_pulsar_addr = 0xd2;
- printk(KERN_INFO "Timebase clock is Pulsar chip\n");
- } else if (device_is_compatible(cc, "cy28508")) {
- pmac_tb_freeze = smp_core99_cypress_tb_freeze;
- printk(KERN_INFO "Timebase clock is Cypress chip\n");
- }
+ pmac_tb_freeze = smp_core99_cypress_tb_freeze;
+ printk(KERN_INFO "Timebase clock is Cypress chip\n");
break;
case 0xd4:
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
- pmac_tb_pulsar_addr = 0xd4;
printk(KERN_INFO "Timebase clock is Pulsar chip\n");
break;
}
@@ -221,15 +210,12 @@ static int __init smp_core99_probe(void)
pmac_tb_clock_chip_host = p;
smp_ops->give_timebase = smp_core99_give_timebase;
smp_ops->take_timebase = smp_core99_take_timebase;
- of_node_put(cc);
- of_node_put(p);
break;
}
next:
of_node_put(p);
}
- nohwsync:
mpic_request_ipis();
return ncpus;
diff --git a/trunk/arch/ppc64/kernel/process.c b/trunk/arch/ppc64/kernel/process.c
index cdfecbeb331f..8b0686122738 100644
--- a/trunk/arch/ppc64/kernel/process.c
+++ b/trunk/arch/ppc64/kernel/process.c
@@ -378,6 +378,9 @@ 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;
diff --git a/trunk/arch/ppc64/kernel/prom_init.c b/trunk/arch/ppc64/kernel/prom_init.c
index b7683abfbe6a..35ec42de962e 100644
--- a/trunk/arch/ppc64/kernel/prom_init.c
+++ b/trunk/arch/ppc64/kernel/prom_init.c
@@ -211,23 +211,13 @@ 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;
@@ -597,13 +587,14 @@ 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;
}
- call_prom("call-method", 3, 1, ADDR("process-elf-header"),
+ ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
elfloader, ADDR(&fake_elf));
call_prom("close", 1, 0, elfloader);
}
@@ -655,7 +646,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 (addr != PROM_ERROR)
+ if ((int)addr != PROM_ERROR)
break;
addr = 0;
if (align == 0)
@@ -717,7 +708,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 (addr != PROM_ERROR)
+ if ((int)addr != PROM_ERROR)
break;
addr = 0;
}
@@ -911,19 +902,18 @@ static void __init prom_instantiate_rtas(void)
{
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
- phandle rtas_node;
- ihandle rtas_inst;
+ phandle prom_rtas, rtas_node;
u32 base, entry = 0;
u32 size = 0;
prom_debug("prom_instantiate_rtas: start...\n");
- rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
- prom_debug("rtas_node: %x\n", rtas_node);
- if (!PHANDLE_VALID(rtas_node))
+ prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+ prom_debug("prom_rtas: %x\n", prom_rtas);
+ if (prom_rtas == (phandle) -1)
return;
- prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
+ prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
if (size == 0)
return;
@@ -932,18 +922,14 @@ static void __init prom_instantiate_rtas(void)
prom_printf("RTAS allocation failed !\n");
return;
}
+ prom_printf("instantiating rtas at 0x%x", base);
- 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);
+ rtas_node = call_prom("open", 1, 1, ADDR("/rtas"));
+ prom_printf("...");
if (call_prom("call-method", 3, 2,
ADDR("instantiate-rtas"),
- rtas_inst, base) != PROM_ERROR) {
+ rtas_node, base) != PROM_ERROR) {
entry = (long)_prom->args.rets[1];
}
if (entry == 0) {
@@ -954,8 +940,8 @@ static void __init prom_instantiate_rtas(void)
reserve_mem(base, size);
- prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
- prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
+ prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base));
+ prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry));
prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry);
@@ -1076,7 +1062,7 @@ static void __init prom_initialize_tce_table(void)
prom_printf("opening PHB %s", path);
phb_node = call_prom("open", 1, 1, path);
- if (phb_node == 0)
+ if ( (long)phb_node <= 0)
prom_printf("... failed\n");
else
prom_printf("... done\n");
@@ -1293,12 +1279,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 (!PHANDLE_VALID(_prom->chosen))
+ if ((long)_prom->chosen <= 0)
prom_panic("cannot find chosen"); /* msg won't be printed :( */
/* get device tree root */
_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
- if (!PHANDLE_VALID(_prom->root))
+ if ((long)_prom->root <= 0)
prom_panic("cannot find device tree root"); /* msg won't be printed :( */
}
@@ -1370,8 +1356,9 @@ 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 (PHANDLE_VALID(rtas)) {
- int x = prom_getproplen(rtas, "ibm,hypertas-functions");
+ if (rtas != (phandle) -1) {
+ unsigned long x;
+ x = prom_getproplen(rtas, "ibm,hypertas-functions");
if (x != PROM_ERROR) {
prom_printf("Hypertas detected, assuming LPAR !\n");
return PLATFORM_PSERIES_LPAR;
@@ -1439,13 +1426,12 @@ 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) == PROM_ERROR)
+ if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
continue;
prom_printf("found display : %s, opening ... ", path);
ih = call_prom("open", 1, 1, path);
- if (ih == 0) {
+ if (ih == (ihandle)0 || ih == (ihandle)-1) {
prom_printf("failed\n");
continue;
}
@@ -1528,12 +1514,6 @@ 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)
{
@@ -1547,12 +1527,10 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
/* get and store all property names */
prev_name = RELOC("");
for (;;) {
- 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) {
+
+ /* 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) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
@@ -1577,12 +1555,18 @@ 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, *p, *ep;
+ char *namep, *prev_name, *sstart;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
@@ -1604,14 +1588,6 @@ 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);
}
@@ -1623,10 +1599,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
prev_name = RELOC("");
sstart = (char *)RELOC(dt_string_start);
for (;;) {
- int rc;
-
- rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
- if (rc != 1)
+ if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
break;
/* find string offset */
@@ -1642,7 +1615,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 == PROM_ERROR)
+ if (l < 0)
continue;
if (l > MAX_PROPERTY_LENGTH) {
prom_printf("WARNING: ignoring large property ");
@@ -1777,45 +1750,7 @@ static void __init flatten_device_tree(void)
prom_printf("Device tree struct 0x%x -> 0x%x\n",
RELOC(dt_struct_start), RELOC(dt_struct_end));
-}
-
-
-static void __init fixup_device_tree(void)
-{
- unsigned long offset = reloc_offset();
- phandle u3, i2c, mpic;
- u32 u3_rev;
- u32 interrupts[2];
- u32 parent;
-
- /* Some G5s have a missing interrupt definition, fix it up here */
- u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
- if (!PHANDLE_VALID(u3))
- return;
- i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
- if (!PHANDLE_VALID(i2c))
- return;
- mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
- if (!PHANDLE_VALID(mpic))
- return;
-
- /* check if proper rev of u3 */
- if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
- == PROM_ERROR)
- return;
- if (u3_rev != 0x35)
- return;
- /* does it need fixup ? */
- if (prom_getproplen(i2c, "interrupts") > 0)
- return;
- /* interrupt on this revision of u3 is number 0 and level */
- interrupts[0] = 0;
- interrupts[1] = 1;
- prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
- parent = (u32)mpic;
- prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
-}
-
+ }
static void __init prom_find_boot_cpu(void)
{
@@ -1908,12 +1843,6 @@ 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
*/
@@ -1990,11 +1919,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
}
- /*
- * Fixup any known bugs in the device-tree
- */
- fixup_device_tree();
-
/*
* Now finally create the flattened device-tree
*/
diff --git a/trunk/arch/ppc64/kernel/rtc.c b/trunk/arch/ppc64/kernel/rtc.c
index 67989055a9fe..3e70b91375fc 100644
--- a/trunk/arch/ppc64/kernel/rtc.c
+++ b/trunk/arch/ppc64/kernel/rtc.c
@@ -292,10 +292,47 @@ int iSeries_set_rtc_time(struct rtc_time *tm)
void iSeries_get_boot_time(struct rtc_time *tm)
{
+ unsigned long time;
+ static unsigned long lastsec = 1;
+
+ u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart));
+ u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1);
+ int year = 1970;
+ int year1 = ( dataWord1 >> 24 ) & 0x000000FF;
+ int year2 = ( dataWord1 >> 16 ) & 0x000000FF;
+ int sec = ( dataWord1 >> 8 ) & 0x000000FF;
+ int min = dataWord1 & 0x000000FF;
+ int hour = ( dataWord2 >> 24 ) & 0x000000FF;
+ int day = ( dataWord2 >> 8 ) & 0x000000FF;
+ int mon = dataWord2 & 0x000000FF;
+
if ( piranha_simulator )
return;
- mf_get_boot_rtc(tm);
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year1);
+ BCD_TO_BIN(year2);
+ year = year1 * 100 + year2;
+
+ time = mktime(year, mon, day, hour, min, sec);
+ time += ( jiffies / HZ );
+
+ /* Now THIS is a nasty hack!
+ * It ensures that the first two calls get different answers.
+ * That way the loop in init_time (time.c) will not think
+ * the clock is stuck.
+ */
+ if ( lastsec ) {
+ time -= lastsec;
+ --lastsec;
+ }
+
+ to_tm(time, tm);
+ tm->tm_year -= 1900;
tm->tm_mon -= 1;
}
#endif
diff --git a/trunk/arch/ppc64/kernel/setup.c b/trunk/arch/ppc64/kernel/setup.c
index dce198d39328..21c57f539c29 100644
--- a/trunk/arch/ppc64/kernel/setup.c
+++ b/trunk/arch/ppc64/kernel/setup.c
@@ -103,6 +103,11 @@ 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;
@@ -1115,15 +1120,64 @@ 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; idefault_decr = tb_ticks_per_jiffy;
+ if ( decr_overclock_set && !decr_overclock_proc0_set )
+ decr_overclock_proc0 = decr_overclock;
+
+ lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
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.
diff --git a/trunk/arch/ppc64/kernel/smp.c b/trunk/arch/ppc64/kernel/smp.c
index 9ef5d36d6b25..3b906cd94037 100644
--- a/trunk/arch/ppc64/kernel/smp.c
+++ b/trunk/arch/ppc64/kernel/smp.c
@@ -334,6 +334,7 @@ void smp_call_function_interrupt(void)
}
}
+extern unsigned long decr_overclock;
extern struct gettimeofday_struct do_gtod;
struct thread_info *current_set[NR_CPUS];
@@ -490,7 +491,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;
+ paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
if (!cpu_has_feature(CPU_FTR_SLB)) {
void *tmp;
diff --git a/trunk/arch/ppc64/kernel/sysfs.c b/trunk/arch/ppc64/kernel/sysfs.c
index c8fa6569b2fd..0925694c3ce5 100644
--- a/trunk/arch/ppc64/kernel/sysfs.c
+++ b/trunk/arch/ppc64/kernel/sysfs.c
@@ -113,6 +113,7 @@ 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 */
@@ -166,8 +167,11 @@ 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))
- ppc64_runlatch_on();
+ if (cpu_has_feature(CPU_FTR_SMT)) {
+ ctrl = mfspr(CTRLF);
+ ctrl |= RUNLATCH;
+ mtspr(CTRLT, ctrl);
+ }
#endif /* CONFIG_PPC_PSERIES */
}
diff --git a/trunk/arch/ppc64/kernel/time.c b/trunk/arch/ppc64/kernel/time.c
index 33364a7d2cd2..772a465b49f9 100644
--- a/trunk/arch/ppc64/kernel/time.c
+++ b/trunk/arch/ppc64/kernel/time.c
@@ -325,7 +325,9 @@ 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;
@@ -513,7 +515,6 @@ void __init time_init(void)
do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
do_gtod.varp->tb_orig_stamp = tb_last_stamp;
- get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy;
do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
do_gtod.varp->tb_to_xs = tb_to_xs;
diff --git a/trunk/arch/sparc64/kernel/pci_iommu.c b/trunk/arch/sparc64/kernel/pci_iommu.c
index 2803bc7c2c79..292983413ae2 100644
--- a/trunk/arch/sparc64/kernel/pci_iommu.c
+++ b/trunk/arch/sparc64/kernel/pci_iommu.c
@@ -8,7 +8,6 @@
#include
#include
#include
-#include
#include
@@ -196,34 +195,6 @@ 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.
@@ -264,7 +235,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_alloc_ctx(iommu);
+ ctx = iommu->iommu_cur_ctx++;
first_page = __pa(first_page);
while (npages--) {
iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
@@ -345,8 +316,6 @@ 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);
@@ -390,7 +359,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_alloc_ctx(iommu);
+ ctx = iommu->iommu_cur_ctx++;
if (strbuf->strbuf_enabled)
iopte_protection = IOPTE_STREAMING(ctx);
else
@@ -410,70 +379,6 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
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, int direction)
-{
- int limit;
-
- if (strbuf->strbuf_ctxflush &&
- iommu->iommu_ctxflush) {
- unsigned long matchreg, flushreg;
- u64 val;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-
- pci_iommu_write(flushreg, ctx);
- 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;
- }
- val = pci_iommu_read(matchreg);
- if (unlikely(val)) {
- printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
- "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);
-
- limit = 100000;
- while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
- limit--;
- if (!limit)
- break;
- udelay(1);
- membar("#LoadLoad");
- }
- if (!limit)
- printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
- "vaddr[%08x] ctx[%lx] npages[%ld]\n",
- vaddr, ctx, npages);
-}
-
/* Unmap a single streaming mode DMA translation. */
void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
@@ -481,7 +386,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
iopte_t *base;
- unsigned long flags, npages, ctx;
+ unsigned long flags, npages, i, ctx;
if (direction == PCI_DMA_NONE)
BUG();
@@ -509,8 +414,29 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
/* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled)
- pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+ if (strbuf->strbuf_enabled) {
+ u32 vaddr = bus_addr;
+
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (strbuf->strbuf_ctxflush &&
+ iommu->iommu_ctxflush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while(((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+ }
+
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
+ }
/* Step 2: Clear out first TSB entry. */
iopte_make_dummy(iommu, base);
@@ -518,8 +444,6 @@ 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);
}
@@ -659,7 +583,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_alloc_ctx(iommu);
+ ctx = iommu->iommu_cur_ctx++;
/* Step 5: Create the mappings. */
if (strbuf->strbuf_enabled)
@@ -723,8 +647,29 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
/* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled)
- pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+ if (strbuf->strbuf_enabled) {
+ u32 vaddr = (u32) bus_addr;
+
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (strbuf->strbuf_ctxflush &&
+ iommu->iommu_ctxflush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while(((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+ }
+
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
+ }
/* Step 2: Clear out first TSB entry. */
iopte_make_dummy(iommu, base);
@@ -732,8 +677,6 @@ 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);
}
@@ -772,7 +715,28 @@ 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, direction);
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (iommu->iommu_ctxflush &&
+ strbuf->strbuf_ctxflush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while(((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ unsigned long i;
+
+ for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
+ }
+
+ /* Step 3: Perform flush synchronization sequence. */
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -785,8 +749,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
- unsigned long flags, ctx, npages, i;
- u32 bus_addr;
+ unsigned long flags, ctx;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
@@ -809,14 +772,36 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
}
/* Step 2: Kick data out of streaming buffers. */
- bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
- for(i = 1; i < nelems; i++)
- if (!sglist[i].dma_length)
- break;
- 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, direction);
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (iommu->iommu_ctxflush &&
+ strbuf->strbuf_ctxflush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while (((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ unsigned long i, npages;
+ u32 bus_addr;
+
+ bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
+
+ for(i = 1; i < nelems; i++)
+ if (!sglist[i].dma_length)
+ break;
+ i--;
+ npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
+ for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
+ }
+
+ /* Step 3: Perform flush synchronization sequence. */
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
spin_unlock_irqrestore(&iommu->lock, flags);
}
diff --git a/trunk/arch/sparc64/kernel/pci_psycho.c b/trunk/arch/sparc64/kernel/pci_psycho.c
index 534320ef0db2..3567fa879e1f 100644
--- a/trunk/arch/sparc64/kernel/pci_psycho.c
+++ b/trunk/arch/sparc64/kernel/pci_psycho.c
@@ -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->ctx_lowest_free = 1;
+ iommu->iommu_cur_ctx = 0;
/* Register addresses. */
iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
diff --git a/trunk/arch/sparc64/kernel/pci_sabre.c b/trunk/arch/sparc64/kernel/pci_sabre.c
index 53d333b4a4e8..5525d1ec4af8 100644
--- a/trunk/arch/sparc64/kernel/pci_sabre.c
+++ b/trunk/arch/sparc64/kernel/pci_sabre.c
@@ -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->ctx_lowest_free = 1;
+ iommu->iommu_cur_ctx = 0;
/* Register addresses. */
iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
diff --git a/trunk/arch/sparc64/kernel/pci_schizo.c b/trunk/arch/sparc64/kernel/pci_schizo.c
index 5753175b94e6..e93fcadc3722 100644
--- a/trunk/arch/sparc64/kernel/pci_schizo.c
+++ b/trunk/arch/sparc64/kernel/pci_schizo.c
@@ -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->ctx_lowest_free = 1;
+ iommu->iommu_cur_ctx = 0;
/* Register addresses, SCHIZO has iommu ctx flushing. */
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
diff --git a/trunk/arch/sparc64/kernel/sbus.c b/trunk/arch/sparc64/kernel/sbus.c
index 89f5e019f24c..14d9c3a21b9a 100644
--- a/trunk/arch/sparc64/kernel/sbus.c
+++ b/trunk/arch/sparc64/kernel/sbus.c
@@ -117,42 +117,19 @@ 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, int direction)
+static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
{
- unsigned long n;
- int limit;
-
- 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;
+ while (npages--)
+ upa_writeq(base + (npages << IO_PAGE_SHIFT),
+ iommu->strbuf_regs + STRBUF_PFLUSH);
/* Whoopee cushion! */
upa_writeq(__pa(&iommu->strbuf_flushflag),
iommu->strbuf_regs + STRBUF_FSYNC);
upa_readq(iommu->sbus_control_reg);
-
- limit = 100000;
- while (iommu->strbuf_flushflag == 0UL) {
- limit--;
- if (!limit)
- break;
- udelay(1);
+ while (iommu->strbuf_flushflag == 0UL)
membar("#LoadLoad");
- }
- if (!limit)
- printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
- "vaddr[%08x] npages[%ld]\n",
- base, npages);
}
static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
@@ -429,7 +406,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, direction);
+ strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -592,7 +569,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, direction);
+ strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -604,7 +581,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, direction);
+ strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -628,7 +605,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, direction);
+ strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
}
diff --git a/trunk/arch/sparc64/kernel/setup.c b/trunk/arch/sparc64/kernel/setup.c
index b7e6a91952b2..12c3d84b7460 100644
--- a/trunk/arch/sparc64/kernel/setup.c
+++ b/trunk/arch/sparc64/kernel/setup.c
@@ -383,17 +383,6 @@ static void __init process_switch(char c)
/* Use PROM debug console. */
register_console(&prom_debug_console);
break;
- case 'P':
- /* Force UltraSPARC-III P-Cache on. */
- if (tlb_type != cheetah) {
- printk("BOOT: Ignoring P-Cache force option.\n");
- break;
- }
- cheetah_pcache_forced_on = 1;
- add_taint(TAINT_MACHINE_CHECK);
- cheetah_enable_pcache();
- break;
-
default:
printk("Unknown boot switch (-%c)\n", c);
break;
diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c
index e5b9c7a27789..6dff06a44e76 100644
--- a/trunk/arch/sparc64/kernel/smp.c
+++ b/trunk/arch/sparc64/kernel/smp.c
@@ -123,9 +123,6 @@ void __init smp_callin(void)
smp_setup_percpu_timer();
- if (cheetah_pcache_forced_on)
- cheetah_enable_pcache();
-
local_irq_enable();
calibrate_delay();
diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c
index a9f4596d7c2b..56b203a2af69 100644
--- a/trunk/arch/sparc64/kernel/traps.c
+++ b/trunk/arch/sparc64/kernel/traps.c
@@ -421,25 +421,6 @@ asmlinkage void cee_log(unsigned long ce_status,
}
}
-int cheetah_pcache_forced_on;
-
-void cheetah_enable_pcache(void)
-{
- unsigned long dcr;
-
- printk("CHEETAH: Enabling P-Cache on cpu %d.\n",
- smp_processor_id());
-
- __asm__ __volatile__("ldxa [%%g0] %1, %0"
- : "=r" (dcr)
- : "i" (ASI_DCU_CONTROL_REG));
- dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL);
- __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
- "membar #Sync"
- : /* no outputs */
- : "r" (dcr), "i" (ASI_DCU_CONTROL_REG));
-}
-
/* Cheetah error trap handling. */
static unsigned long ecache_flush_physbase;
static unsigned long ecache_flush_linesize;
diff --git a/trunk/arch/um/Kconfig.debug b/trunk/arch/um/Kconfig.debug
index bd41e4286d0d..b89989de364d 100644
--- a/trunk/arch/um/Kconfig.debug
+++ b/trunk/arch/um/Kconfig.debug
@@ -2,6 +2,10 @@ 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
diff --git a/trunk/arch/um/Kconfig_x86_64 b/trunk/arch/um/Kconfig_x86_64
index f162f50f0b17..fd8d7e8982b1 100644
--- a/trunk/arch/um/Kconfig_x86_64
+++ b/trunk/arch/um/Kconfig_x86_64
@@ -6,10 +6,6 @@ config 64BIT
bool
default y
-config TOP_ADDR
- hex
- default 0x80000000
-
config 3_LEVEL_PGTABLES
bool
default y
diff --git a/trunk/arch/um/drivers/chan_kern.c b/trunk/arch/um/drivers/chan_kern.c
index 14a12d6b3df6..0150038af795 100644
--- a/trunk/arch/um/drivers/chan_kern.c
+++ b/trunk/arch/um/drivers/chan_kern.c
@@ -20,17 +20,9 @@
#include "os.h"
#ifdef CONFIG_NOCONFIG_CHAN
-
-/* The printk's here are wrong because we are complaining that there is no
- * output device, but printk is printing to that output device. The user will
- * never see the error. printf would be better, except it can't run on a
- * kernel stack because it will overflow it.
- * Use printk for now since that will avoid crashing.
- */
-
static void *not_configged_init(char *str, int device, struct chan_opts *opts)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(NULL);
}
@@ -38,27 +30,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
static int not_configged_open(int input, int output, int primary, void *data,
char **dev_out)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-ENODEV);
}
static void not_configged_close(int fd, void *data)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
}
static int not_configged_read(int fd, char *c_out, void *data)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
static int not_configged_write(int fd, const char *buf, int len, void *data)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
@@ -66,7 +58,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
static int not_configged_console_write(int fd, const char *buf, int len,
void *data)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
@@ -74,7 +66,7 @@ static int not_configged_console_write(int fd, const char *buf, int len,
static int not_configged_window_size(int fd, void *data, unsigned short *rows,
unsigned short *cols)
{
- printk(KERN_ERR "Using a channel type which is configured out of "
+ printf(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-ENODEV);
}
diff --git a/trunk/arch/um/drivers/mcast_kern.c b/trunk/arch/um/drivers/mcast_kern.c
index 217438cdef33..faf714e87b5b 100644
--- a/trunk/arch/um/drivers/mcast_kern.c
+++ b/trunk/arch/um/drivers/mcast_kern.c
@@ -73,6 +73,7 @@ int mcast_setup(char *str, char **mac_out, void *data)
struct mcast_init *init = data;
char *port_str = NULL, *ttl_str = NULL, *remain;
char *last;
+ int n;
*init = ((struct mcast_init)
{ .addr = "239.192.168.1",
@@ -88,12 +89,13 @@ int mcast_setup(char *str, char **mac_out, void *data)
}
if(port_str != NULL){
- init->port = simple_strtoul(port_str, &last, 10);
+ n = simple_strtoul(port_str, &last, 10);
if((*last != '\0') || (last == port_str)){
printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
port_str);
return(0);
}
+ init->port = htons(n);
}
if(ttl_str != NULL){
diff --git a/trunk/arch/um/drivers/mcast_user.c b/trunk/arch/um/drivers/mcast_user.c
index 7a0d115b29d0..0fe1d9fa9139 100644
--- a/trunk/arch/um/drivers/mcast_user.c
+++ b/trunk/arch/um/drivers/mcast_user.c
@@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
}
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = in_aton(addr);
- sin->sin_port = htons(port);
+ sin->sin_port = port;
return(sin);
}
@@ -55,25 +55,28 @@ static int mcast_open(void *data)
struct mcast_data *pri = data;
struct sockaddr_in *sin = pri->mcast_addr;
struct ip_mreq mreq;
- int fd = -EINVAL, yes = 1, err = -EINVAL;;
+ int fd, yes = 1;
- if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
+ fd = -EINVAL;
goto out;
+ }
fd = socket(AF_INET, SOCK_DGRAM, 0);
-
if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n",
errno);
- fd = -errno;
+ fd = -ENOMEM;
goto out;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno);
- goto out_close;
+ os_close_file(fd);
+ fd = -EINVAL;
+ goto out;
}
/* set ttl according to config */
@@ -81,20 +84,26 @@ static int mcast_open(void *data)
sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno);
- goto out_close;
+ os_close_file(fd);
+ fd = -EINVAL;
+ goto out;
}
/* set LOOP, so data does get fed back to local sockets */
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno);
- goto out_close;
+ os_close_file(fd);
+ fd = -EINVAL;
+ goto out;
}
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno);
- goto out_close;
+ os_close_file(fd);
+ fd = -EINVAL;
+ goto out;
}
/* subscribe to the multicast group */
@@ -108,15 +117,12 @@ static int mcast_open(void *data)
"interface on the host.\n");
printk("eth0 should be configured in order to use the "
"multicast transport.\n");
- goto out_close;
+ os_close_file(fd);
+ fd = -EINVAL;
}
out:
- return fd;
-
- out_close:
- os_close_file(fd);
- return err;
+ return(fd);
}
static void mcast_close(int fd, void *data)
@@ -158,3 +164,14 @@ struct net_user_info mcast_user_info = {
.delete_address = NULL,
.max_packet = MAX_PACKET - ETH_HEADER_OTHER
};
+
+/*
+ * 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/trunk/arch/um/drivers/random.c b/trunk/arch/um/drivers/random.c
index f9e22198e011..d43e9fab05a7 100644
--- a/trunk/arch/um/drivers/random.c
+++ b/trunk/arch/um/drivers/random.c
@@ -1,10 +1,5 @@
-/* Copyright (C) 2005 Jeff Dike */
-/* 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.
- */
+/* Much of this ripped from hw_random.c */
+
#include
#include
#include
@@ -17,6 +12,8 @@
*/
#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 */
@@ -101,7 +98,7 @@ static int __init rng_init (void)
err = misc_register (&rng_miscdev);
if (err) {
- printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
+ printk (KERN_ERR PFX "misc device register failed\n");
goto err_out_cleanup_hw;
}
@@ -123,6 +120,3 @@ 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");
diff --git a/trunk/arch/um/drivers/ssl.c b/trunk/arch/um/drivers/ssl.c
index b32a77010fbe..a2bac429f3d4 100644
--- a/trunk/arch/um/drivers/ssl.c
+++ b/trunk/arch/um/drivers/ssl.c
@@ -22,6 +22,7 @@
#include "init.h"
#include "irq_user.h"
#include "mconsole_kern.h"
+#include "2_5compat.h"
static int ssl_version = 1;
diff --git a/trunk/arch/um/drivers/stdio_console.c b/trunk/arch/um/drivers/stdio_console.c
index afbe1e71ed83..361d0be342b3 100644
--- a/trunk/arch/um/drivers/stdio_console.c
+++ b/trunk/arch/um/drivers/stdio_console.c
@@ -28,6 +28,7 @@
#include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h"
+#include "2_5compat.h"
#define MAX_TTYS (16)
diff --git a/trunk/arch/um/drivers/ubd_kern.c b/trunk/arch/um/drivers/ubd_kern.c
index 2a7f6892c55c..9a56ff94308d 100644
--- a/trunk/arch/um/drivers/ubd_kern.c
+++ b/trunk/arch/um/drivers/ubd_kern.c
@@ -49,12 +49,13 @@
#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"
#include "cow.h"
-enum ubd_req { UBD_READ, UBD_WRITE };
+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
struct io_thread_req {
enum ubd_req op;
@@ -67,6 +68,8 @@ struct io_thread_req {
unsigned long sector_mask;
unsigned long long cow_offset;
unsigned long bitmap_words[2];
+ int map_fd;
+ unsigned long long map_offset;
int error;
};
@@ -119,6 +122,10 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
#define MAX_DEV (8)
+/* Changed in early boot */
+static int ubd_do_mmap = 0;
+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
+
static struct block_device_operations ubd_blops = {
.owner = THIS_MODULE,
.open = ubd_open,
@@ -168,6 +175,12 @@ struct ubd {
int no_cow;
struct cow cow;
struct platform_device pdev;
+
+ int map_writes;
+ int map_reads;
+ int nomap_writes;
+ int nomap_reads;
+ int write_maps;
};
#define DEFAULT_COW { \
@@ -187,6 +200,11 @@ struct ubd {
.openflags = OPEN_FLAGS, \
.no_cow = 0, \
.cow = DEFAULT_COW, \
+ .map_writes = 0, \
+ .map_reads = 0, \
+ .nomap_writes = 0, \
+ .nomap_reads = 0, \
+ .write_maps = 0, \
}
struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -296,6 +314,13 @@ static int ubd_setup_common(char *str, int *index_out)
int major;
str++;
+ if(!strcmp(str, "mmap")){
+ CHOOSE_MODE(printk("mmap not supported by the ubd "
+ "driver in tt mode\n"),
+ ubd_do_mmap = 1);
+ return(0);
+ }
+
if(!strcmp(str, "sync")){
global_openflags = of_sync(global_openflags);
return(0);
@@ -439,9 +464,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"
-" 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"
+" 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"
" in the boot output.\n\n"
);
@@ -499,7 +524,7 @@ static void ubd_handler(void)
{
struct io_thread_req req;
struct request *rq = elv_next_request(ubd_queue);
- int n;
+ int n, err;
do_ubd = NULL;
intr_count++;
@@ -513,6 +538,19 @@ static void ubd_handler(void)
return;
}
+ if((req.op != UBD_MMAP) &&
+ ((req.offset != ((__u64) (rq->sector)) << 9) ||
+ (req.length != (rq->current_nr_sectors) << 9)))
+ panic("I/O op mismatch");
+
+ if(req.map_fd != -1){
+ err = physmem_subst_mapping(req.buffer, req.map_fd,
+ req.map_offset, 1);
+ if(err)
+ printk("ubd_handler - physmem_subst_mapping failed, "
+ "err = %d\n", -err);
+ }
+
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
@@ -545,10 +583,14 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
static void ubd_close(struct ubd *dev)
{
+ if(ubd_do_mmap)
+ physmem_forget_descriptor(dev->fd);
os_close_file(dev->fd);
if(dev->cow.file == NULL)
return;
+ if(ubd_do_mmap)
+ physmem_forget_descriptor(dev->cow.fd);
os_close_file(dev->cow.fd);
vfree(dev->cow.bitmap);
dev->cow.bitmap = NULL;
@@ -968,13 +1010,94 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
req->bitmap_words, bitmap_len);
}
+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
+{
+ __u64 sector;
+ unsigned char *bitmap;
+ int bit, i;
+
+ /* mmap must have been requested on the command line */
+ if(!ubd_do_mmap)
+ return(-1);
+
+ /* The buffer must be page aligned */
+ if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
+ return(-1);
+
+ /* The request must be a page long */
+ if((req->current_nr_sectors << 9) != PAGE_SIZE)
+ return(-1);
+
+ if(dev->cow.file == NULL)
+ return(dev->fd);
+
+ sector = offset >> 9;
+ bitmap = (unsigned char *) dev->cow.bitmap;
+ bit = ubd_test_bit(sector, bitmap);
+
+ for(i = 1; i < req->current_nr_sectors; i++){
+ if(ubd_test_bit(sector + i, bitmap) != bit)
+ return(-1);
+ }
+
+ if(bit || (rq_data_dir(req) == WRITE))
+ offset += dev->cow.data_offset;
+
+ /* The data on disk must be page aligned */
+ if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
+ return(-1);
+
+ return(bit ? dev->fd : dev->cow.fd);
+}
+
+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
+ struct request *req,
+ struct io_thread_req *io_req)
+{
+ int err;
+
+ if(rq_data_dir(req) == WRITE){
+ /* Writes are almost no-ops since the new data is already in the
+ * host page cache
+ */
+ dev->map_writes++;
+ if(dev->cow.file != NULL)
+ cowify_bitmap(io_req->offset, io_req->length,
+ &io_req->sector_mask, &io_req->cow_offset,
+ dev->cow.bitmap, dev->cow.bitmap_offset,
+ io_req->bitmap_words,
+ dev->cow.bitmap_len);
+ }
+ else {
+ int w;
+
+ if((dev->cow.file != NULL) && (fd == dev->cow.fd))
+ w = 0;
+ else w = dev->openflags.w;
+
+ if((dev->cow.file != NULL) && (fd == dev->fd))
+ offset += dev->cow.data_offset;
+
+ err = physmem_subst_mapping(req->buffer, fd, offset, w);
+ if(err){
+ printk("physmem_subst_mapping failed, err = %d\n",
+ -err);
+ return(1);
+ }
+ dev->map_reads++;
+ }
+ io_req->op = UBD_MMAP;
+ io_req->buffer = req->buffer;
+ return(0);
+}
+
/* Called with ubd_io_lock held */
static int prepare_request(struct request *req, struct io_thread_req *io_req)
{
struct gendisk *disk = req->rq_disk;
struct ubd *dev = disk->private_data;
__u64 offset;
- int len;
+ int len, fd;
if(req->rq_status == RQ_INACTIVE) return(1);
@@ -991,12 +1114,34 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
io_req->fds[1] = dev->fd;
+ io_req->map_fd = -1;
io_req->cow_offset = -1;
io_req->offset = offset;
io_req->length = len;
io_req->error = 0;
io_req->sector_mask = 0;
+ fd = mmap_fd(req, dev, io_req->offset);
+ if(fd > 0){
+ /* If mmapping is otherwise OK, but the first access to the
+ * page is a write, then it's not mapped in yet. So we have
+ * to write the data to disk first, then we can map the disk
+ * page in and continue normally from there.
+ */
+ if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
+ io_req->map_fd = dev->fd;
+ io_req->map_offset = io_req->offset +
+ dev->cow.data_offset;
+ dev->write_maps++;
+ }
+ else return(prepare_mmap_request(dev, fd, io_req->offset, req,
+ io_req));
+ }
+
+ if(rq_data_dir(req) == READ)
+ dev->nomap_reads++;
+ else dev->nomap_writes++;
+
io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
@@ -1084,6 +1229,143 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
return(-EINVAL);
}
+static int ubd_check_remapped(int fd, unsigned long address, int is_write,
+ __u64 offset)
+{
+ __u64 bitmap_offset;
+ unsigned long new_bitmap[2];
+ int i, err, n;
+
+ /* If it's not a write access, we can't do anything about it */
+ if(!is_write)
+ return(0);
+
+ /* We have a write */
+ for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
+ struct ubd *dev = &ubd_dev[i];
+
+ if((dev->fd != fd) && (dev->cow.fd != fd))
+ continue;
+
+ /* It's a write to a ubd device */
+
+ /* This should be impossible now */
+ if(!dev->openflags.w){
+ /* It's a write access on a read-only device - probably
+ * shouldn't happen. If the kernel is trying to change
+ * something with no intention of writing it back out,
+ * then this message will clue us in that this needs
+ * fixing
+ */
+ printk("Write access to mapped page from readonly ubd "
+ "device %d\n", i);
+ return(0);
+ }
+
+ /* It's a write to a writeable ubd device - it must be COWed
+ * because, otherwise, the page would have been mapped in
+ * writeable
+ */
+
+ if(!dev->cow.file)
+ panic("Write fault on writeable non-COW ubd device %d",
+ i);
+
+ /* It should also be an access to the backing file since the
+ * COW pages should be mapped in read-write
+ */
+
+ if(fd == dev->fd)
+ panic("Write fault on a backing page of ubd "
+ "device %d\n", i);
+
+ /* So, we do the write, copying the backing data to the COW
+ * file...
+ */
+
+ err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
+ if(err < 0)
+ panic("Couldn't seek to %lld in COW file of ubd "
+ "device %d, err = %d",
+ offset + dev->cow.data_offset, i, -err);
+
+ n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
+ if(n != PAGE_SIZE)
+ panic("Couldn't copy data to COW file of ubd "
+ "device %d, err = %d", i, -n);
+
+ /* ... updating the COW bitmap... */
+
+ cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
+ dev->cow.bitmap, dev->cow.bitmap_offset,
+ new_bitmap, dev->cow.bitmap_len);
+
+ err = os_seek_file(dev->fd, bitmap_offset);
+ if(err < 0)
+ panic("Couldn't seek to %lld in COW file of ubd "
+ "device %d, err = %d", bitmap_offset, i, -err);
+
+ n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
+ if(n != sizeof(new_bitmap))
+ panic("Couldn't update bitmap of ubd device %d, "
+ "err = %d", i, -n);
+
+ /* Maybe we can map the COW page in, and maybe we can't. If
+ * it is a pre-V3 COW file, we can't, since the alignment will
+ * be wrong. If it is a V3 or later COW file which has been
+ * moved to a system with a larger page size, then maybe we
+ * can't, depending on the exact location of the page.
+ */
+
+ offset += dev->cow.data_offset;
+
+ /* Remove the remapping, putting the original anonymous page
+ * back. If the COW file can be mapped in, that is done.
+ * Otherwise, the COW page is read in.
+ */
+
+ if(!physmem_remove_mapping((void *) address))
+ panic("Address 0x%lx not remapped by ubd device %d",
+ address, i);
+ if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
+ physmem_subst_mapping((void *) address, dev->fd,
+ offset, 1);
+ else {
+ err = os_seek_file(dev->fd, offset);
+ if(err < 0)
+ panic("Couldn't seek to %lld in COW file of "
+ "ubd device %d, err = %d", offset, i,
+ -err);
+
+ n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
+ if(n != PAGE_SIZE)
+ panic("Failed to read page from offset %llx of "
+ "COW file of ubd device %d, err = %d",
+ offset, i, -n);
+ }
+
+ return(1);
+ }
+
+ /* It's not a write on a ubd device */
+ return(0);
+}
+
+static struct remapper ubd_remapper = {
+ .list = LIST_HEAD_INIT(ubd_remapper.list),
+ .proc = ubd_check_remapped,
+};
+
+static int ubd_remapper_setup(void)
+{
+ if(ubd_do_mmap)
+ register_remapper(&ubd_remapper);
+
+ return(0);
+}
+
+__initcall(ubd_remapper_setup);
+
static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
{
struct uml_stat buf1, buf2;
@@ -1286,6 +1568,15 @@ void do_io(struct io_thread_req *req)
int err;
__u64 off;
+ if(req->op == UBD_MMAP){
+ /* Touch the page to force the host to do any necessary IO to
+ * get it into memory
+ */
+ n = *((volatile int *) req->buffer);
+ req->error = update_bitmap(req);
+ return;
+ }
+
nsectors = req->length / req->sectorsize;
start = 0;
do {
diff --git a/trunk/arch/um/include/2_5compat.h b/trunk/arch/um/include/2_5compat.h
new file mode 100644
index 000000000000..abdb015a4d71
--- /dev/null
+++ b/trunk/arch/um/include/2_5compat.h
@@ -0,0 +1,24 @@
+/*
+ * 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:
+ */
diff --git a/trunk/arch/um/include/sysdep-i386/ptrace.h b/trunk/arch/um/include/sysdep-i386/ptrace.h
index 6eaeb9919983..84ec7ff5cf8c 100644
--- a/trunk/arch/um/include/sysdep-i386/ptrace.h
+++ b/trunk/arch/um/include/sysdep-i386/ptrace.h
@@ -31,6 +31,7 @@ extern int sysemu_supported;
#ifdef UML_CONFIG_MODE_SKAS
#include "skas_ptregs.h"
+#include "sysdep/faultinfo.h"
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
@@ -58,7 +59,6 @@ extern int sysemu_supported;
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
-#include "sysdep/faultinfo.h"
#include "choose-mode.h"
union uml_pt_regs {
diff --git a/trunk/arch/um/include/sysdep-x86_64/checksum.h b/trunk/arch/um/include/sysdep-x86_64/checksum.h
index ea97005af694..572c6c19be33 100644
--- a/trunk/arch/um/include/sysdep-x86_64/checksum.h
+++ b/trunk/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,6 +9,8 @@
#include "linux/in6.h"
#include "asm/uaccess.h"
+extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
+ int sum, int *err_ptr);
extern unsigned csum_partial(const unsigned char *buff, unsigned len,
unsigned sum);
@@ -29,15 +31,10 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
}
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src,
- unsigned char *dst, int len, int sum,
- int *err_ptr)
+unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
+ int len, int sum, int *err_ptr)
{
- if(copy_from_user(dst, src, len)){
- *err_ptr = -EFAULT;
- return(-1);
- }
- return csum_partial(dst, len, sum);
+ return csum_partial_copy_from(src, dst, len, sum, err_ptr);
}
/**
@@ -140,6 +137,15 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
return a;
}
-extern unsigned short ip_compute_csum(unsigned char * buff, int len);
-
#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:
+ */
diff --git a/trunk/arch/um/include/sysdep-x86_64/ptrace.h b/trunk/arch/um/include/sysdep-x86_64/ptrace.h
index be8acd5efd97..348e8fcd513f 100644
--- a/trunk/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/trunk/arch/um/include/sysdep-x86_64/ptrace.h
@@ -135,7 +135,6 @@ extern int mode_tt;
__CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
#define UPT_SC(r) ((r)->tt.sc)
#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
-#define UPT_SYSCALL_RET(r) UPT_RAX(r)
extern int user_context(unsigned long sp);
@@ -197,32 +196,32 @@ struct syscall_args {
#define UPT_SET(regs, reg, val) \
- ({ unsigned long __upt_val = val; \
+ ({ unsigned long val; \
switch(reg){ \
- case R8: UPT_R8(regs) = __upt_val; break; \
- case R9: UPT_R9(regs) = __upt_val; break; \
- case R10: UPT_R10(regs) = __upt_val; break; \
- case R11: UPT_R11(regs) = __upt_val; break; \
- case R12: UPT_R12(regs) = __upt_val; break; \
- case R13: UPT_R13(regs) = __upt_val; break; \
- case R14: UPT_R14(regs) = __upt_val; break; \
- case R15: UPT_R15(regs) = __upt_val; break; \
- case RIP: UPT_IP(regs) = __upt_val; break; \
- case RSP: UPT_SP(regs) = __upt_val; break; \
- case RAX: UPT_RAX(regs) = __upt_val; break; \
- case RBX: UPT_RBX(regs) = __upt_val; break; \
- case RCX: UPT_RCX(regs) = __upt_val; break; \
- case RDX: UPT_RDX(regs) = __upt_val; break; \
- case RSI: UPT_RSI(regs) = __upt_val; break; \
- case RDI: UPT_RDI(regs) = __upt_val; break; \
- case RBP: UPT_RBP(regs) = __upt_val; break; \
- case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
- case CS: UPT_CS(regs) = __upt_val; break; \
- case DS: UPT_DS(regs) = __upt_val; break; \
- case ES: UPT_ES(regs) = __upt_val; break; \
- case FS: UPT_FS(regs) = __upt_val; break; \
- case GS: UPT_GS(regs) = __upt_val; break; \
- case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
+ case R8: UPT_R8(regs) = val; break; \
+ case R9: UPT_R9(regs) = val; break; \
+ case R10: UPT_R10(regs) = val; break; \
+ case R11: UPT_R11(regs) = val; break; \
+ case R12: UPT_R12(regs) = val; break; \
+ case R13: UPT_R13(regs) = val; break; \
+ case R14: UPT_R14(regs) = val; break; \
+ case R15: UPT_R15(regs) = val; break; \
+ case RIP: UPT_IP(regs) = val; break; \
+ case RSP: UPT_SP(regs) = val; break; \
+ case RAX: UPT_RAX(regs) = val; break; \
+ case RBX: UPT_RBX(regs) = val; break; \
+ case RCX: UPT_RCX(regs) = val; break; \
+ case RDX: UPT_RDX(regs) = val; break; \
+ case RSI: UPT_RSI(regs) = val; break; \
+ case RDI: UPT_RDI(regs) = val; break; \
+ case RBP: UPT_RBP(regs) = val; break; \
+ case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \
+ case CS: UPT_CS(regs) = val; break; \
+ case DS: UPT_DS(regs) = val; break; \
+ case ES: UPT_ES(regs) = val; break; \
+ case FS: UPT_FS(regs) = val; break; \
+ case GS: UPT_GS(regs) = val; break; \
+ case EFLAGS: UPT_EFLAGS(regs) = val; break; \
default : \
panic("Bad register in UPT_SET : %d\n", reg); \
break; \
@@ -246,3 +245,14 @@ struct syscall_args {
CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
#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:
+ */
diff --git a/trunk/arch/um/include/sysrq.h b/trunk/arch/um/include/sysrq.h
index c8d332b56b98..2ce9423460b3 100644
--- a/trunk/arch/um/include/sysrq.h
+++ b/trunk/arch/um/include/sysrq.h
@@ -1,7 +1,6 @@
#ifndef __UM_SYSRQ_H
#define __UM_SYSRQ_H
-struct task_struct;
-extern void show_trace(struct task_struct* task, unsigned long *stack);
+extern void show_trace(unsigned long *stack);
#endif
diff --git a/trunk/arch/um/kernel/Makefile b/trunk/arch/um/kernel/Makefile
index a8918e80df96..9736ca27c5f0 100644
--- a/trunk/arch/um/kernel/Makefile
+++ b/trunk/arch/um/kernel/Makefile
@@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \
tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
user_util.o
-obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
+obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
diff --git a/trunk/arch/um/kernel/checksum.c b/trunk/arch/um/kernel/checksum.c
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/trunk/arch/um/kernel/exec_kern.c b/trunk/arch/um/kernel/exec_kern.c
index efd222ffe20e..49ddabe69be7 100644
--- a/trunk/arch/um/kernel/exec_kern.c
+++ b/trunk/arch/um/kernel/exec_kern.c
@@ -16,6 +16,7 @@
#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/trunk/arch/um/kernel/initrd.c b/trunk/arch/um/kernel/initrd_kern.c
similarity index 75%
rename from trunk/arch/um/kernel/initrd.c
rename to trunk/arch/um/kernel/initrd_kern.c
index 82ecf904b09c..fc568af468b9 100644
--- a/trunk/arch/um/kernel/initrd.c
+++ b/trunk/arch/um/kernel/initrd_kern.c
@@ -41,31 +41,12 @@ static int __init uml_initrd_setup(char *line, int *add)
return 0;
}
-__uml_setup("initrd=", uml_initrd_setup,
+__uml_setup("initrd=", uml_initrd_setup,
"initrd=\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"
);
-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
diff --git a/trunk/arch/um/kernel/initrd_user.c b/trunk/arch/um/kernel/initrd_user.c
new file mode 100644
index 000000000000..cb90681e151c
--- /dev/null
+++ b/trunk/arch/um/kernel/initrd_user.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include
+#include
+#include
+#include
+
+#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:
+ */
diff --git a/trunk/arch/um/kernel/irq_user.c b/trunk/arch/um/kernel/irq_user.c
index b3074cbaa479..6d6f9484b884 100644
--- a/trunk/arch/um/kernel/irq_user.c
+++ b/trunk/arch/um/kernel/irq_user.c
@@ -236,15 +236,9 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
(*prev)->fd, pollfds[i].fd);
goto out;
}
-
+ memcpy(&pollfds[i], &pollfds[i + 1],
+ (pollfds_num - i - 1) * sizeof(pollfds[0]));
pollfds_num--;
-
- /* This moves the *whole* array after pollfds[i] (though
- * it doesn't spot as such)! */
-
- memmove(&pollfds[i], &pollfds[i + 1],
- (pollfds_num - i) * sizeof(pollfds[0]));
-
if(last_irq_ptr == &old_fd->next)
last_irq_ptr = prev;
*prev = (*prev)->next;
diff --git a/trunk/arch/um/kernel/ksyms.c b/trunk/arch/um/kernel/ksyms.c
index 99439fa15ef4..78d69dc74b26 100644
--- a/trunk/arch/um/kernel/ksyms.c
+++ b/trunk/arch/um/kernel/ksyms.c
@@ -57,7 +57,6 @@ EXPORT_SYMBOL(copy_to_user_tt);
EXPORT_SYMBOL(strncpy_from_user_skas);
EXPORT_SYMBOL(copy_to_user_skas);
EXPORT_SYMBOL(copy_from_user_skas);
-EXPORT_SYMBOL(clear_user_skas);
#endif
EXPORT_SYMBOL(uml_strdup);
diff --git a/trunk/arch/um/kernel/main.c b/trunk/arch/um/kernel/main.c
index e42e6364ca13..a17c49703f9b 100644
--- a/trunk/arch/um/kernel/main.c
+++ b/trunk/arch/um/kernel/main.c
@@ -71,7 +71,7 @@ static __init void do_uml_initcalls(void)
static void last_ditch_exit(int sig)
{
- kmalloc_ok = 0;
+ CHOOSE_MODE(kmalloc_ok = 0, (void) 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, err;
+ int ret, i;
/* Enable all signals except SIGIO - in some environments, we can
* enter with some signals blocked
@@ -160,29 +160,27 @@ int main(int argc, char **argv, char **envp)
*/
change_sig(SIGPROF, 0);
- /* 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.
- */
+ /* Reboot */
+ if(ret){
+ int err;
- /* stop timers and set SIG*ALRM to be ignored */
- disable_timer();
+ printf("\n");
- /* 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);
+ /* stop timers and set SIG*ALRM to be ignored */
+ disable_timer();
- /* 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();
+ /* 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();
- /* Reboot */
- if(ret){
- printf("\n");
execvp(new_argv[0], new_argv);
perror("Failed to exec kernel");
ret = 1;
diff --git a/trunk/arch/um/kernel/mem.c b/trunk/arch/um/kernel/mem.c
index c22825f13e40..f156661781cb 100644
--- a/trunk/arch/um/kernel/mem.c
+++ b/trunk/arch/um/kernel/mem.c
@@ -100,37 +100,12 @@ void mem_init(void)
#endif
}
-/*
- * Create a page table and place a pointer to it in a middle page
- * directory entry.
- */
-static void __init one_page_table_init(pmd_t *pmd)
-{
- if (pmd_none(*pmd)) {
- pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pmd(pmd, __pmd(_KERNPG_TABLE +
- (unsigned long) __pa(pte)));
- if (pte != pte_offset_kernel(pmd, 0))
- BUG();
- }
-}
-
-static void __init one_md_table_init(pud_t *pud)
-{
-#ifdef CONFIG_3_LEVEL_PGTABLES
- pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
- if (pmd_table != pmd_offset(pud, 0))
- BUG();
-#endif
-}
-
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
- pud_t *pud;
pmd_t *pmd;
+ pte_t *pte;
int i, j;
unsigned long vaddr;
@@ -140,12 +115,15 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
- pud = pud_offset(pgd, vaddr);
- if (pud_none(*pud))
- one_md_table_init(pud);
- pmd = pmd_offset(pud, vaddr);
+ pmd = (pmd_t *)pgd;
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
- one_page_table_init(pmd);
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
+ (unsigned long) __pa(pte)));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
vaddr += PMD_SIZE;
}
j = 0;
diff --git a/trunk/arch/um/kernel/process_kern.c b/trunk/arch/um/kernel/process_kern.c
index 804c6bbdf67c..c1adf7ba3fd1 100644
--- a/trunk/arch/um/kernel/process_kern.c
+++ b/trunk/arch/um/kernel/process_kern.c
@@ -43,6 +43,7 @@
#include "tlb.h"
#include "frame_kern.h"
#include "sigcontext.h"
+#include "2_5compat.h"
#include "os.h"
#include "mode.h"
#include "mode_kern.h"
@@ -54,6 +55,18 @@
*/
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;
@@ -176,6 +189,7 @@ 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
@@ -198,6 +212,11 @@ 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)
{
@@ -330,6 +349,11 @@ 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));
@@ -456,3 +480,15 @@ 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:
+ */
diff --git a/trunk/arch/um/kernel/ptrace.c b/trunk/arch/um/kernel/ptrace.c
index 71af4d503899..2b75d8d9ba73 100644
--- a/trunk/arch/um/kernel/ptrace.c
+++ b/trunk/arch/um/kernel/ptrace.c
@@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on)
child->thread.singlestep_syscall = 0;
#ifdef SUBARCH_SET_SINGLESTEPPING
- SUBARCH_SET_SINGLESTEPPING(child, on);
+ SUBARCH_SET_SINGLESTEPPING(child, on)
#endif
-}
+ }
/*
* Called by kernel/ptrace.c when detaching..
@@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
}
#ifdef SUBACH_PTRACE_SPECIAL
- SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
+ SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
#endif
ret = ptrace_check_attach(child, request == PTRACE_KILL);
@@ -322,9 +322,11 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
UPT_SYSCALL_ARG2(regs),
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
- else audit_syscall_exit(current,
- AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
- UPT_SYSCALL_RET(regs));
+ else {
+ int res = UPT_SYSCALL_RET(regs);
+ audit_syscall_exit(current, AUDITSC_RESULT(res),
+ res);
+ }
}
/* Fake a debug trap */
@@ -354,3 +356,14 @@ 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:
+ */
diff --git a/trunk/arch/um/kernel/sysrq.c b/trunk/arch/um/kernel/sysrq.c
index f80850091e79..e630438f9e73 100644
--- a/trunk/arch/um/kernel/sysrq.c
+++ b/trunk/arch/um/kernel/sysrq.c
@@ -3,7 +3,6 @@
* Licensed under the GPL
*/
-#include "linux/config.h"
#include "linux/sched.h"
#include "linux/kernel.h"
#include "linux/module.h"
@@ -13,14 +12,14 @@
#include "sysrq.h"
#include "user_util.h"
-/* Catch non-i386 SUBARCH's. */
-#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
-void show_trace(struct task_struct *task, unsigned long * stack)
+void show_trace(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);
}
@@ -36,7 +35,6 @@ void show_trace(struct task_struct *task, unsigned long * stack)
}
printk("\n");
}
-#endif
/*
* stack dumps generator - this is used by arch-independent code.
@@ -46,7 +44,7 @@ void dump_stack(void)
{
unsigned long stack;
- show_trace(current, &stack);
+ show_trace(&stack);
}
EXPORT_SYMBOL(dump_stack);
@@ -61,11 +59,7 @@ void show_stack(struct task_struct *task, unsigned long *esp)
int i;
if (esp == NULL) {
- 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).
- */
+ if (task != current) {
esp = (unsigned long *) KSTK_ESP(task);
/* Which one? No actual difference - just coding style.*/
//esp = (unsigned long *) PT_REGS_IP(&task->thread.regs);
@@ -83,6 +77,5 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("%08lx ", *stack++);
}
- printk("Call Trace: \n");
- show_trace(current, esp);
+ show_trace(esp);
}
diff --git a/trunk/arch/um/kernel/trap_kern.c b/trunk/arch/um/kernel/trap_kern.c
index c20aef120598..5fca2c61eb98 100644
--- a/trunk/arch/um/kernel/trap_kern.c
+++ b/trunk/arch/um/kernel/trap_kern.c
@@ -23,6 +23,7 @@
#include "kern.h"
#include "chan_kern.h"
#include "mconsole_kern.h"
+#include "2_5compat.h"
#include "mem.h"
#include "mem_kern.h"
@@ -56,11 +57,10 @@ int handle_page_fault(unsigned long address, unsigned long ip,
*code_out = SEGV_ACCERR;
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
-
- if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
- goto out;
-
page = address & PAGE_MASK;
+ pgd = pgd_offset(mm, page);
+ pud = pud_offset(pgd, page);
+ pmd = pmd_offset(pud, page);
do {
survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,6 +106,33 @@ int handle_page_fault(unsigned long address, unsigned long ip,
goto out;
}
+LIST_HEAD(physmem_remappers);
+
+void register_remapper(struct remapper *info)
+{
+ list_add(&info->list, &physmem_remappers);
+}
+
+static int check_remapped_addr(unsigned long address, int is_write)
+{
+ struct remapper *remapper;
+ struct list_head *ele;
+ __u64 offset;
+ int fd;
+
+ fd = phys_mapping(__pa(address), &offset);
+ if(fd == -1)
+ return(0);
+
+ list_for_each(ele, &physmem_remappers){
+ remapper = list_entry(ele, struct remapper, list);
+ if((*remapper->proc)(fd, address, is_write, offset))
+ return(1);
+ }
+
+ return(0);
+}
+
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
@@ -124,6 +151,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
flush_tlb_kernel_vm();
return(0);
}
+ else if(check_remapped_addr(address & PAGE_MASK, is_write))
+ return(0);
else if(current->mm == NULL)
panic("Segfault with no mm");
err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
diff --git a/trunk/arch/um/kernel/tt/ksyms.c b/trunk/arch/um/kernel/tt/ksyms.c
index 84a9385a8fef..92ec85d67c7c 100644
--- a/trunk/arch/um/kernel/tt/ksyms.c
+++ b/trunk/arch/um/kernel/tt/ksyms.c
@@ -12,7 +12,6 @@ EXPORT_SYMBOL(__do_copy_to_user);
EXPORT_SYMBOL(__do_strncpy_from_user);
EXPORT_SYMBOL(__do_strnlen_user);
EXPORT_SYMBOL(__do_clear_user);
-EXPORT_SYMBOL(clear_user_tt);
EXPORT_SYMBOL(tracing_pid);
EXPORT_SYMBOL(honeypot);
diff --git a/trunk/arch/um/kernel/tt/process_kern.c b/trunk/arch/um/kernel/tt/process_kern.c
index 776310fd5b8b..df810ca8fc12 100644
--- a/trunk/arch/um/kernel/tt/process_kern.c
+++ b/trunk/arch/um/kernel/tt/process_kern.c
@@ -32,6 +32,10 @@ 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;
@@ -55,11 +59,13 @@ 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);
- if(from->thread.mode.tt.switch_pipe[0] == -1)
+ reading = 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));
diff --git a/trunk/arch/um/kernel/um_arch.c b/trunk/arch/um/kernel/um_arch.c
index 418427107b29..4d10ec372a67 100644
--- a/trunk/arch/um/kernel/um_arch.c
+++ b/trunk/arch/um/kernel/um_arch.c
@@ -111,6 +111,12 @@ 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;
diff --git a/trunk/arch/um/kernel/uml.lds.S b/trunk/arch/um/kernel/uml.lds.S
index dd5355500bdc..76eadb309189 100644
--- a/trunk/arch/um/kernel/uml.lds.S
+++ b/trunk/arch/um/kernel/uml.lds.S
@@ -73,8 +73,6 @@ SECTIONS
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
- .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
- .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
diff --git a/trunk/arch/um/sys-i386/Makefile b/trunk/arch/um/sys-i386/Makefile
index 4351e5605506..fcd67c3414e4 100644
--- a/trunk/arch/um/sys-i386/Makefile
+++ b/trunk/arch/um/sys-i386/Makefile
@@ -9,11 +9,11 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
SYMLINKS = bitops.c semaphore.c highmem.c module.c
-include arch/um/scripts/Makefile.rules
-
bitops.c-dir = lib
semaphore.c-dir = kernel
highmem.c-dir = mm
module.c-dir = kernel
subdir- := util
+
+include arch/um/scripts/Makefile.rules
diff --git a/trunk/arch/um/sys-i386/delay.c b/trunk/arch/um/sys-i386/delay.c
index 2c11b9770e8b..e9892eef51ce 100644
--- a/trunk/arch/um/sys-i386/delay.c
+++ b/trunk/arch/um/sys-i386/delay.c
@@ -1,7 +1,5 @@
-#include
-#include
-#include
-#include
+#include "linux/delay.h"
+#include "asm/param.h"
void __delay(unsigned long time)
{
@@ -22,19 +20,13 @@ void __udelay(unsigned long usecs)
int i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i */
void show_regs(struct pt_regs *regs)
{
printk("\n");
@@ -34,80 +31,5 @@ void show_regs(struct pt_regs *regs)
0xffff & PT_REGS_DS(regs),
0xffff & PT_REGS_ES(regs));
- show_trace(NULL, (unsigned long *) ®s);
+ show_trace((unsigned long *) ®s);
}
-
-/* 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");
-}
-
diff --git a/trunk/arch/um/sys-ppc/sysrq.c b/trunk/arch/um/sys-ppc/sysrq.c
index 2f816f1a0ff4..82d6e9335bb6 100644
--- a/trunk/arch/um/sys-ppc/sysrq.c
+++ b/trunk/arch/um/sys-ppc/sysrq.c
@@ -27,5 +27,17 @@ void show_regs(struct pt_regs_subarch *regs)
0xffff & regs->xds, 0xffff & regs->xes);
#endif
- show_trace(current, ®s->gpr[1]);
+ show_trace(®s->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:
+ */
diff --git a/trunk/arch/um/sys-x86_64/Makefile b/trunk/arch/um/sys-x86_64/Makefile
index 608466ad6b22..3d7da911cc8c 100644
--- a/trunk/arch/um/sys-x86_64/Makefile
+++ b/trunk/arch/um/sys-x86_64/Makefile
@@ -14,11 +14,11 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
USER_OBJS := ptrace_user.o sigcontext.o
+include arch/um/scripts/Makefile.rules
+
SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
semaphore.c thunk.S module.c
-include arch/um/scripts/Makefile.rules
-
bitops.c-dir = lib
csum-copy.S-dir = lib
csum-partial.c-dir = lib
@@ -28,4 +28,6 @@ semaphore.c-dir = kernel
thunk.S-dir = lib
module.c-dir = kernel
+CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
+
subdir- := util
diff --git a/trunk/arch/um/sys-x86_64/delay.c b/trunk/arch/um/sys-x86_64/delay.c
index 137f4446b439..651332aeec22 100644
--- a/trunk/arch/um/sys-x86_64/delay.c
+++ b/trunk/arch/um/sys-x86_64/delay.c
@@ -5,37 +5,40 @@
* Licensed under the GPL
*/
-#include
-#include
-#include
-#include
+#include "linux/delay.h"
+#include "asm/processor.h"
+#include "asm/param.h"
void __delay(unsigned long loops)
{
unsigned long i;
- for(i = 0; i < loops; i++)
- cpu_relax();
+ for(i = 0; i < loops; i++) ;
}
void __udelay(unsigned long usecs)
{
- unsigned long i, n;
+ int i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i
-#include
-#include
-#include
-#include
+#include "asm/ptrace.h"
+#include "linux/sched.h"
+#include "linux/errno.h"
+#include "asm/elf.h"
/* XXX x86_64 */
unsigned long not_ss;
diff --git a/trunk/arch/um/sys-x86_64/syscalls.c b/trunk/arch/um/sys-x86_64/syscalls.c
index 6f44f40204ed..dd9914642b8e 100644
--- a/trunk/arch/um/sys-x86_64/syscalls.c
+++ b/trunk/arch/um/sys-x86_64/syscalls.c
@@ -15,7 +15,6 @@
#include "asm/unistd.h"
#include "asm/prctl.h" /* XXX This should get the constants from libc */
#include "choose-mode.h"
-#include "kern.h"
asmlinkage long sys_uname64(struct new_utsname __user * name)
{
@@ -133,27 +132,23 @@ 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_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_SET_FS:
+ current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
+ break;
case ARCH_GET_FS:
- ret = put_user(current->thread.regs.regs.skas.
- regs[FS_BASE / sizeof(unsigned long)],
- (unsigned long __user *)addr);
+ ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr);
break;
case ARCH_GET_GS:
- ret = put_user(current->thread.regs.regs.skas.
- regs[GS_BASE / sizeof(unsigned long)],
- (unsigned long __user *)addr);
+ ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \
+long)], &addr);
break;
default:
ret = -EINVAL;
diff --git a/trunk/arch/um/sys-x86_64/sysrq.c b/trunk/arch/um/sys-x86_64/sysrq.c
index d0a25af19a5b..ddf74691a610 100644
--- a/trunk/arch/um/sys-x86_64/sysrq.c
+++ b/trunk/arch/um/sys-x86_64/sysrq.c
@@ -36,5 +36,14 @@ void __show_regs(struct pt_regs * regs)
void show_regs(struct pt_regs *regs)
{
__show_regs(regs);
- show_trace(current, (unsigned long *) ®s);
+ show_trace((unsigned long *) ®s);
}
+
+/* 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/trunk/arch/um/sys-x86_64/user-offsets.c b/trunk/arch/um/sys-x86_64/user-offsets.c
index 513d17ceafd4..5e14792e4838 100644
--- a/trunk/arch/um/sys-x86_64/user-offsets.c
+++ b/trunk/arch/um/sys-x86_64/user-offsets.c
@@ -3,14 +3,6 @@
#include
#define __FRAME_OFFSETS
#include
-#include
-/* For some reason, x86_64 defines u64 and u32 only in , which I
- * refuse to include here, even though they're used throughout the headers.
- * These are used in asm/user.h, and that include can't be avoided because of
- * the sizeof(struct user_regs_struct) below.
- */
-typedef __u64 u64;
-typedef __u32 u32;
#include
#define DEFINE(sym, val) \
diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig
index 289f448ac89c..44ee7f6acf7b 100644
--- a/trunk/arch/x86_64/Kconfig
+++ b/trunk/arch/x86_64/Kconfig
@@ -303,21 +303,6 @@ config HPET_TIMER
as it is off-chip. You can find the HPET spec at
.
-config X86_PM_TIMER
- bool "PM timer"
- depends on ACPI
- default y
- help
- Support the ACPI PM timer for time keeping. This is slow,
- but is useful on some chipsets without HPET on systems with more
- than one CPU. On a single processor or single socket multi core
- system it is normally not required.
- When the PM timer is active 64bit vsyscalls are disabled
- and should not be enabled (/proc/sys/kernel/vsyscall64 should
- not be changed).
- The kernel selects the PM timer only as a last resort, so it is
- useful to enable just in case.
-
config HPET_EMULATE_RTC
bool "Provide RTC interrupt"
depends on HPET_TIMER && RTC=y
@@ -422,7 +407,7 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool "Support mmconfig PCI config space access"
- depends on PCI && ACPI
+ depends on PCI
select ACPI_BOOT
config UNORDERED_IO
diff --git a/trunk/arch/x86_64/defconfig b/trunk/arch/x86_64/defconfig
index 569595b74c7c..9ce51dee30b3 100644
--- a/trunk/arch/x86_64/defconfig
+++ b/trunk/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Fri May 13 06:39:11 2005
+# Linux kernel version: 2.6.11-bk7
+# Sat Mar 12 23:43:44 2005
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -11,6 +11,8 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_CMPXCHG=y
CONFIG_EARLY_PRINTK=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
@@ -20,7 +22,6 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -32,6 +33,7 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=18
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
@@ -41,11 +43,10 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
@@ -92,9 +93,6 @@ CONFIG_DISCONTIGMEM=y
CONFIG_NUMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_NR_CPUS=8
-CONFIG_HPET_TIMER=y
-CONFIG_X86_PM_TIMER=y
-CONFIG_HPET_EMULATE_RTC=y
CONFIG_GART_IOMMU=y
CONFIG_SWIOTLB=y
CONFIG_X86_MCE=y
@@ -102,7 +100,6 @@ CONFIG_X86_MCE_INTEL=y
CONFIG_SECCOMP=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ISA_DMA_API=y
#
# Power management options
@@ -132,7 +129,7 @@ CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_IBM is not set
CONFIG_ACPI_TOSHIBA=y
CONFIG_ACPI_BLACKLIST_YEAR=2001
-# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_DEBUG=y
CONFIG_ACPI_BUS=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
@@ -144,7 +141,6 @@ CONFIG_ACPI_SYSTEM=y
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
@@ -154,6 +150,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_TABLE=y
#
# CPUFreq processor drivers
@@ -167,7 +164,6 @@ CONFIG_X86_ACPI_CPUFREQ=y
# shared options
#
CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
-# CONFIG_X86_SPEEDSTEP_LIB is not set
#
# Bus options (PCI etc.)
@@ -176,17 +172,19 @@ CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_UNORDERED_IO=y
-# CONFIG_PCIEPORTBUS is not set
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
-# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
+#
+# PC-card bridges
+#
+
#
# PCI Hotplug Support
#
@@ -256,7 +254,7 @@ CONFIG_LBD=y
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
@@ -310,8 +308,7 @@ CONFIG_BLK_DEV_AMD74XX=y
CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-# CONFIG_PDC202XX_FORCE 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_SIS5513 is not set
@@ -356,7 +353,7 @@ CONFIG_BLK_DEV_SD=y
#
# SCSI low-level drivers
#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+CONFIG_BLK_DEV_3W_XXXX_RAID=y
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
@@ -387,6 +384,7 @@ CONFIG_SCSI_SATA_VIA=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -394,6 +392,7 @@ CONFIG_SCSI_SATA_VIA=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=y
@@ -402,7 +401,6 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -439,6 +437,7 @@ 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
@@ -503,7 +502,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
+# CONFIG_TUN is not set
#
# ARCnet devices
@@ -526,7 +525,8 @@ CONFIG_MII=y
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
+CONFIG_AMD8111_ETH=y
+# CONFIG_AMD8111E_NAPI is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
CONFIG_FORCEDETH=y
@@ -536,7 +536,7 @@ CONFIG_FORCEDETH=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
-CONFIG_8139CP=y
+CONFIG_8139CP=m
CONFIG_8139TOO=y
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set
@@ -671,7 +671,6 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -697,7 +696,6 @@ CONFIG_RTC=y
#
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
-CONFIG_AGP_INTEL=y
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y
@@ -705,7 +703,7 @@ CONFIG_HPET=y
# CONFIG_HPET_RTC_IRQ is not set
CONFIG_HPET_MMAP=y
CONFIG_MAX_RAW_DEVS=256
-# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_HANGCHECK_TIMER=y
#
# TPM devices
@@ -788,8 +786,6 @@ CONFIG_SOUND_ICH=y
#
# USB support
#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -801,6 +797,8 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -828,6 +826,7 @@ CONFIG_USB_PRINTER=y
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
@@ -966,7 +965,7 @@ CONFIG_AUTOFS_FS=y
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
+# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_UDF_FS is not set
@@ -1093,10 +1092,9 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
-# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_PRINTK_TIME is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/trunk/arch/x86_64/kernel/Makefile b/trunk/arch/x86_64/kernel/Makefile
index 5ca4a4598fda..0a3318e08ab6 100644
--- a/trunk/arch/x86_64/kernel/Makefile
+++ b/trunk/arch/x86_64/kernel/Makefile
@@ -28,7 +28,6 @@ obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o
obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/trunk/arch/x86_64/kernel/apic.c b/trunk/arch/x86_64/kernel/apic.c
index f8e6cc4fecd4..7e13545748e0 100644
--- a/trunk/arch/x86_64/kernel/apic.c
+++ b/trunk/arch/x86_64/kernel/apic.c
@@ -33,7 +33,6 @@
#include
#include
#include
-#include
int apic_verbosity;
@@ -926,7 +925,7 @@ __init int oem_force_hpet_timer(void)
unsigned id;
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
- bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
+ bitmap_empty(clustermap, NUM_APIC_CLUSTERS);
for (i = 0; i < NR_CPUS; i++) {
id = bios_cpu_apicid[i];
@@ -1057,7 +1056,7 @@ int __init APIC_init_uniprocessor (void)
nr_ioapics = 0;
#endif
setup_boot_APIC_clock();
- check_nmi_watchdog();
+
return 0;
}
diff --git a/trunk/arch/x86_64/kernel/entry.S b/trunk/arch/x86_64/kernel/entry.S
index 28817490fdc6..1086b5fcac21 100644
--- a/trunk/arch/x86_64/kernel/entry.S
+++ b/trunk/arch/x86_64/kernel/entry.S
@@ -220,18 +220,13 @@ sysret_careful:
jmp sysret_check
/* Handle a signal */
+ /* edx: work flags (arg3) */
sysret_signal:
sti
- testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
- jz 1f
-
- /* Really a signal */
- /* edx: work flags (arg3) */
leaq do_notify_resume(%rip),%rax
leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
-1: movl $_TIF_NEED_RESCHED,%edi
jmp sysret_check
/* Do syscall tracing */
@@ -489,8 +484,6 @@ retint_careful:
jmp retint_check
retint_signal:
- testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
- jz retint_swapgs
sti
SAVE_REST
movq $-1,ORIG_RAX(%rsp)
@@ -499,8 +492,8 @@ retint_signal:
call do_notify_resume
RESTORE_REST
cli
- movl $_TIF_NEED_RESCHED,%edi
GET_THREAD_INFO(%rcx)
+ movl $_TIF_WORK_MASK,%edi
jmp retint_check
#ifdef CONFIG_PREEMPT
diff --git a/trunk/arch/x86_64/kernel/io_apic.c b/trunk/arch/x86_64/kernel/io_apic.c
index afd87e64d0a8..60be58617eb9 100644
--- a/trunk/arch/x86_64/kernel/io_apic.c
+++ b/trunk/arch/x86_64/kernel/io_apic.c
@@ -37,14 +37,11 @@
#include
#include
#include
-#include
#define __apicdebuginit __init
int sis_apic_bug; /* not actually supported, dummy for compile */
-static int no_timer_check;
-
static DEFINE_SPINLOCK(ioapic_lock);
/*
@@ -1604,7 +1601,7 @@ static inline void check_timer(void)
* Ok, does IRQ0 through the IOAPIC work?
*/
unmask_IO_APIC_irq(0);
- if (!no_timer_check && timer_irq_works()) {
+ if (timer_irq_works()) {
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0);
@@ -1674,13 +1671,6 @@ static inline void check_timer(void)
panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
}
-static int __init notimercheck(char *s)
-{
- no_timer_check = 1;
- return 1;
-}
-__setup("no_timer_check", notimercheck);
-
/*
*
* IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1814,6 +1804,76 @@ device_initcall(ioapic_init_sysfs);
#define IO_APIC_MAX_ID 0xFE
+int __init io_apic_get_unique_id (int ioapic, int apic_id)
+{
+ union IO_APIC_reg_00 reg_00;
+ static physid_mask_t apic_id_map;
+ unsigned long flags;
+ int i = 0;
+
+ /*
+ * The P4 platform supports up to 256 APIC IDs on two separate APIC
+ * buses (one for LAPICs, one for IOAPICs), where predecessors only
+ * supports up to 16 on one shared APIC bus.
+ *
+ * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
+ * advantage of new APIC bus architecture.
+ */
+
+ if (physids_empty(apic_id_map))
+ apic_id_map = phys_cpu_present_map;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ reg_00.raw = io_apic_read(ioapic, 0);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ if (apic_id >= IO_APIC_MAX_ID) {
+ apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+ "%d\n", ioapic, apic_id, reg_00.bits.ID);
+ apic_id = reg_00.bits.ID;
+ }
+
+ /*
+ * Every APIC in a system must have a unique ID or we get lots of nice
+ * 'stuck on smp_invalidate_needed IPI wait' messages.
+ */
+ if (physid_isset(apic_id, apic_id_map)) {
+
+ for (i = 0; i < IO_APIC_MAX_ID; i++) {
+ if (!physid_isset(i, apic_id_map))
+ break;
+ }
+
+ if (i == IO_APIC_MAX_ID)
+ panic("Max apic_id exceeded!\n");
+
+ apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+ "trying %d\n", ioapic, apic_id, i);
+
+ apic_id = i;
+ }
+
+ physid_set(apic_id, apic_id_map);
+
+ if (reg_00.bits.ID != apic_id) {
+ reg_00.bits.ID = apic_id;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(ioapic, 0, reg_00.raw);
+ reg_00.raw = io_apic_read(ioapic, 0);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ /* Sanity check */
+ if (reg_00.bits.ID != apic_id)
+ panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
+ }
+
+ apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+
+ return apic_id;
+}
+
+
int __init io_apic_get_version (int ioapic)
{
union IO_APIC_reg_01 reg_01;
diff --git a/trunk/arch/x86_64/kernel/mpparse.c b/trunk/arch/x86_64/kernel/mpparse.c
index 61a63be6b294..7ec031c6ca10 100644
--- a/trunk/arch/x86_64/kernel/mpparse.c
+++ b/trunk/arch/x86_64/kernel/mpparse.c
@@ -30,7 +30,6 @@
#include
#include
#include
-#include
/* Have we found an MP table */
int smp_found_config;
@@ -108,7 +107,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static void __init MP_processor_info (struct mpc_config_processor *m)
{
int ver;
- static int found_bsp=0;
if (!(m->mpc_cpuflag & CPU_ENABLED))
return;
@@ -128,6 +126,11 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
" Processor ignored.\n", NR_CPUS);
return;
}
+ if (num_processors >= maxcpus) {
+ printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+ " Processor ignored.\n", maxcpus);
+ return;
+ }
num_processors++;
@@ -147,19 +150,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
ver = 0x10;
}
apic_version[m->mpc_apicid] = ver;
- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
- /*
- * bios_cpu_apicid is required to have processors listed
- * in same order as logical cpu numbers. Hence the first
- * entry is BSP, and so on.
- */
- bios_cpu_apicid[0] = m->mpc_apicid;
- x86_cpu_to_apicid[0] = m->mpc_apicid;
- found_bsp = 1;
- } else {
- bios_cpu_apicid[num_processors - found_bsp] = m->mpc_apicid;
- x86_cpu_to_apicid[num_processors - found_bsp] = m->mpc_apicid;
- }
+ bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -768,7 +759,7 @@ void __init mp_register_ioapic (
mp_ioapics[idx].mpc_apicaddr = address;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
- mp_ioapics[idx].mpc_apicid = id;
+ mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
/*
diff --git a/trunk/arch/x86_64/kernel/nmi.c b/trunk/arch/x86_64/kernel/nmi.c
index 31c0f2e6ac91..61de0b34a01e 100644
--- a/trunk/arch/x86_64/kernel/nmi.c
+++ b/trunk/arch/x86_64/kernel/nmi.c
@@ -33,7 +33,6 @@
#include
#include
#include
-#include
/*
* lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -60,8 +59,7 @@ int panic_on_timeout;
unsigned int nmi_watchdog = NMI_DEFAULT;
static unsigned int nmi_hz = HZ;
-static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
-static unsigned int nmi_p4_cccr_val;
+unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
/* Note that these events don't tick when the CPU idles. This means
the frequency varies with CPU load. */
@@ -73,87 +71,61 @@ static unsigned int nmi_p4_cccr_val;
#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-#define MSR_P4_MISC_ENABLE 0x1A0
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
-#define MSR_P4_PERFCTR0 0x300
-#define MSR_P4_CCCR0 0x360
-#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
-#define P4_ESCR_OS (1<<3)
-#define P4_ESCR_USR (1<<2)
-#define P4_CCCR_OVF_PMI0 (1<<26)
-#define P4_CCCR_OVF_PMI1 (1<<27)
-#define P4_CCCR_THRESHOLD(N) ((N)<<20)
-#define P4_CCCR_COMPLEMENT (1<<19)
-#define P4_CCCR_COMPARE (1<<18)
-#define P4_CCCR_REQUIRED (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE (1<<12)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
- CRU_ESCR0 (with any non-null event selector) through a complemented
- max threshold. [IA32-Vol3, Section 14.9.9] */
-#define MSR_P4_IQ_COUNTER0 0x30C
-#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
-#define P4_NMI_IQ_CCCR0 \
- (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
- P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
-
-static __init inline int nmi_known_cpu(void)
-{
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
- return boot_cpu_data.x86 == 15;
- case X86_VENDOR_INTEL:
- return boot_cpu_data.x86 == 15;
- }
- return 0;
-}
+#define P6_EVNTSEL0_ENABLE (1 << 22)
+#define P6_EVNTSEL_INT (1 << 20)
+#define P6_EVNTSEL_OS (1 << 17)
+#define P6_EVNTSEL_USR (1 << 16)
+#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
+#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED
/* Run after command line and cpu_init init, but before all other checks */
void __init nmi_watchdog_default(void)
{
if (nmi_watchdog != NMI_DEFAULT)
return;
- if (nmi_known_cpu())
- nmi_watchdog = NMI_LOCAL_APIC;
- else
+
+ /* For some reason the IO APIC watchdog doesn't work on the AMD
+ 8111 chipset. For now switch to local APIC mode using
+ perfctr0 there. On Intel CPUs we don't have code to handle
+ the perfctr and the IO-APIC seems to work, so use that. */
+
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+ nmi_watchdog = NMI_LOCAL_APIC;
+ printk(KERN_INFO
+ "Using local APIC NMI watchdog using perfctr0\n");
+ } else {
+ printk(KERN_INFO "Using IO APIC NMI watchdog\n");
nmi_watchdog = NMI_IO_APIC;
+ }
}
-#ifdef CONFIG_SMP
-/* The performance counters used by NMI_LOCAL_APIC don't trigger when
- * the CPU is idle. To make sure the NMI watchdog really ticks on all
- * CPUs during the test make them busy.
- */
-static __init void nmi_cpu_busy(void *data)
+/* Why is there no CPUID flag for this? */
+static __init int cpu_has_lapic(void)
{
- volatile int *endflag = data;
- local_irq_enable();
- /* Intentionally don't use cpu_relax here. This is
- to make sure that the performance counter really ticks,
- even if there is a simulator or similar that catches the
- pause instruction. On a real HT machine this is fine because
- all other CPUs are busy with "useless" delay loops and don't
- care if they get somewhat less cycles. */
- while (*endflag == 0)
- barrier();
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_INTEL:
+ case X86_VENDOR_AMD:
+ return boot_cpu_data.x86 >= 6;
+ /* .... add more cpus here or find a different way to figure this out. */
+ default:
+ return 0;
+ }
}
-#endif
-int __init check_nmi_watchdog (void)
+static int __init check_nmi_watchdog (void)
{
- volatile int endflag = 0;
- int *counts;
+ int counts[NR_CPUS];
int cpu;
- counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
- if (!counts)
- return -1;
+ if (nmi_watchdog == NMI_NONE)
+ return 0;
- printk(KERN_INFO "testing NMI watchdog ... ");
+ if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic()) {
+ nmi_watchdog = NMI_NONE;
+ return -1;
+ }
- if (nmi_watchdog == NMI_LOCAL_APIC)
- smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
+ printk(KERN_INFO "Testing NMI watchdog ... ");
for (cpu = 0; cpu < NR_CPUS; cpu++)
counts[cpu] = cpu_pda[cpu].__nmi_count;
@@ -161,22 +133,15 @@ int __init check_nmi_watchdog (void)
mdelay((10*1000)/nmi_hz); // wait 10 ticks
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- if (!cpu_online(cpu))
- continue;
if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) {
- endflag = 1;
- printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
+ printk("CPU#%d: NMI appears to be stuck (%d)!\n",
cpu,
- counts[cpu],
cpu_pda[cpu].__nmi_count);
nmi_active = 0;
lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
- nmi_perfctr_msr = 0;
- kfree(counts);
return -1;
}
}
- endflag = 1;
printk("OK.\n");
/* now that we know it works we can reduce NMI frequency to
@@ -184,9 +149,10 @@ int __init check_nmi_watchdog (void)
if (nmi_watchdog == NMI_LOCAL_APIC)
nmi_hz = 1;
- kfree(counts);
return 0;
}
+/* Have this called later during boot so counters are updating */
+late_initcall(check_nmi_watchdog);
int __init setup_nmi_watchdog(char *str)
{
@@ -204,7 +170,7 @@ int __init setup_nmi_watchdog(char *str)
if (nmi >= NMI_INVALID)
return 0;
- nmi_watchdog = nmi;
+ nmi_watchdog = nmi;
return 1;
}
@@ -219,10 +185,7 @@ static void disable_lapic_nmi_watchdog(void)
wrmsr(MSR_K7_EVNTSEL0, 0, 0);
break;
case X86_VENDOR_INTEL:
- if (boot_cpu_data.x86 == 15) {
- wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
- wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
- }
+ wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
break;
}
nmi_active = -1;
@@ -290,7 +253,7 @@ void enable_timer_nmi_watchdog(void)
static int nmi_pm_active; /* nmi_active before suspend */
-static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
+static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
{
nmi_pm_active = nmi_active;
disable_lapic_nmi_watchdog();
@@ -337,27 +300,22 @@ late_initcall(init_lapic_nmi_sysfs);
* Original code written by Keith Owens.
*/
-static void clear_msr_range(unsigned int base, unsigned int n)
-{
- unsigned int i;
-
- for(i = 0; i < n; ++i)
- wrmsr(base+i, 0, 0);
-}
-
static void setup_k7_watchdog(void)
{
int i;
unsigned int evntsel;
+ /* No check, so can start with slow frequency */
+ nmi_hz = 1;
+
+ /* XXX should check these in EFER */
+
nmi_perfctr_msr = MSR_K7_PERFCTR0;
for(i = 0; i < 4; ++i) {
/* Simulator may not support it */
- if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
- nmi_perfctr_msr = 0;
+ if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL))
return;
- }
wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
}
@@ -367,54 +325,12 @@ static void setup_k7_watchdog(void)
| K7_NMI_EVENT;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+ wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz*1000) / nmi_hz);
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
}
-
-static int setup_p4_watchdog(void)
-{
- unsigned int misc_enable, dummy;
-
- rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
- if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
- return 0;
-
- nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
- nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
-#ifdef CONFIG_SMP
- if (smp_num_siblings == 2)
- nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
-#endif
-
- if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
- clear_msr_range(0x3F1, 2);
- /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
- docs doesn't fully define it, so leave it alone for now. */
- if (boot_cpu_data.x86_model >= 0x3) {
- /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
- clear_msr_range(0x3A0, 26);
- clear_msr_range(0x3BC, 3);
- } else {
- clear_msr_range(0x3A0, 31);
- }
- clear_msr_range(0x3C0, 6);
- clear_msr_range(0x3C8, 6);
- clear_msr_range(0x3E0, 2);
- clear_msr_range(MSR_P4_CCCR0, 18);
- clear_msr_range(MSR_P4_PERFCTR0, 18);
-
- wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
- wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
- Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
- wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
- apic_write(APIC_LVTPC, APIC_DM_NMI);
- wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
- return 1;
-}
-
void setup_apic_nmi_watchdog(void)
{
switch (boot_cpu_data.x86_vendor) {
@@ -425,13 +341,6 @@ void setup_apic_nmi_watchdog(void)
return;
setup_k7_watchdog();
break;
- case X86_VENDOR_INTEL:
- if (boot_cpu_data.x86 != 15)
- return;
- if (!setup_p4_watchdog())
- return;
- break;
-
default:
return;
}
@@ -446,67 +355,56 @@ void setup_apic_nmi_watchdog(void)
*
* as these watchdog NMI IRQs are generated on every CPU, we only
* have to check the current processor.
+ *
+ * since NMIs don't listen to _any_ locks, we have to be extremely
+ * careful not to rely on unsafe variables. The printk might lock
+ * up though, so we have to break up any console locks first ...
+ * [when there will be more tty-related locks, break them up
+ * here too!]
*/
-static DEFINE_PER_CPU(unsigned, last_irq_sum);
-static DEFINE_PER_CPU(local_t, alert_counter);
-static DEFINE_PER_CPU(int, nmi_touch);
+static unsigned int
+ last_irq_sums [NR_CPUS],
+ alert_counter [NR_CPUS];
void touch_nmi_watchdog (void)
{
int i;
/*
- * Tell other CPUs to reset their alert counters. We cannot
- * do it ourselves because the alert count increase is not
- * atomic.
+ * Just reset the alert counters, (other CPUs might be
+ * spinning on locks we hold):
*/
for (i = 0; i < NR_CPUS; i++)
- per_cpu(nmi_touch, i) = 1;
+ alert_counter[i] = 0;
}
void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
{
- int sum;
- int touched = 0;
+ int sum, cpu;
+ cpu = safe_smp_processor_id();
sum = read_pda(apic_timer_irqs);
- if (__get_cpu_var(nmi_touch)) {
- __get_cpu_var(nmi_touch) = 0;
- touched = 1;
- }
- if (!touched && __get_cpu_var(last_irq_sum) == sum) {
+ if (last_irq_sums[cpu] == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
* wait a few IRQs (5 seconds) before doing the oops ...
*/
- local_inc(&__get_cpu_var(alert_counter));
- if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
+ alert_counter[cpu]++;
+ if (alert_counter[cpu] == 5*nmi_hz) {
if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
== NOTIFY_STOP) {
- local_set(&__get_cpu_var(alert_counter), 0);
+ alert_counter[cpu] = 0;
return;
}
die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
}
} else {
- __get_cpu_var(last_irq_sum) = sum;
- local_set(&__get_cpu_var(alert_counter), 0);
+ last_irq_sums[cpu] = sum;
+ alert_counter[cpu] = 0;
}
- if (nmi_perfctr_msr) {
- if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
- /*
- * P4 quirks:
- * - An overflown perfctr will assert its interrupt
- * until the OVF flag in its CCCR is cleared.
- * - LVTPC is masked on interrupt and must be
- * unmasked by the LVTPC handler.
- */
- wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
- apic_write(APIC_LVTPC, APIC_DM_NMI);
- }
+ if (nmi_perfctr_msr)
wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
- }
}
static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
diff --git a/trunk/arch/x86_64/kernel/pmtimer.c b/trunk/arch/x86_64/kernel/pmtimer.c
deleted file mode 100644
index feb5f108dd26..000000000000
--- a/trunk/arch/x86_64/kernel/pmtimer.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Ported over from i386 by AK, original copyright was:
- *
- * (C) Dominik Brodowski 2003
- *
- * Driver to use the Power Management Timer (PMTMR) available in some
- * southbridges as primary timing source for the Linux kernel.
- *
- * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
- * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
- *
- * This file is licensed under the GPL v2.
- *
- * Dropped all the hardware bug workarounds for now. Hopefully they
- * are not needed on 64bit chipsets.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* The I/O port the PMTMR resides at.
- * The location is detected during setup_arch(),
- * in arch/i386/kernel/acpi/boot.c */
-u32 pmtmr_ioport;
-
-/* value of the Power timer at last timer interrupt */
-static u32 offset_delay;
-static u32 last_pmtmr_tick;
-
-#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
-
-static inline u32 cyc2us(u32 cycles)
-{
- /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
- * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
- *
- * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
- * easily be multiplied with 286 (=0x11E) without having to fear
- * u32 overflows.
- */
- cycles *= 286;
- return (cycles >> 10);
-}
-
-int pmtimer_mark_offset(void)
-{
- static int first_run = 1;
- unsigned long tsc;
- u32 lost;
-
- u32 tick = inl(pmtmr_ioport);
- u32 delta;
-
- delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
-
- last_pmtmr_tick = tick;
- monotonic_base += delta * NSEC_PER_USEC;
-
- delta += offset_delay;
-
- lost = delta / (USEC_PER_SEC / HZ);
- offset_delay = delta % (USEC_PER_SEC / HZ);
-
- rdtscll(tsc);
- vxtime.last_tsc = tsc - offset_delay * cpu_khz;
-
- /* don't calculate delay for first run,
- or if we've got less then a tick */
- if (first_run || (lost < 1)) {
- first_run = 0;
- offset_delay = 0;
- }
-
- return lost - 1;
-}
-
-unsigned int do_gettimeoffset_pm(void)
-{
- u32 now, offset, delta = 0;
-
- offset = last_pmtmr_tick;
- now = inl(pmtmr_ioport);
- delta = (now - offset) & ACPI_PM_MASK;
-
- return offset_delay + cyc2us(delta);
-}
-
-
-static int __init nopmtimer_setup(char *s)
-{
- pmtmr_ioport = 0;
- return 0;
-}
-
-__setup("nopmtimer", nopmtimer_setup);
diff --git a/trunk/arch/x86_64/kernel/ptrace.c b/trunk/arch/x86_64/kernel/ptrace.c
index 525f6a128a27..e26e86bb56fe 100644
--- a/trunk/arch/x86_64/kernel/ptrace.c
+++ b/trunk/arch/x86_64/kernel/ptrace.c
@@ -257,13 +257,13 @@ static int putreg(struct task_struct *child,
value &= 0xffff;
return 0;
case offsetof(struct user_regs_struct,fs_base):
- if (value >= TASK_SIZE)
- return -EIO;
+ if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+ return -EIO;
child->thread.fs = value;
return 0;
case offsetof(struct user_regs_struct,gs_base):
- if (value >= TASK_SIZE)
- return -EIO;
+ if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+ return -EIO;
child->thread.gs = value;
return 0;
case offsetof(struct user_regs_struct, eflags):
@@ -277,11 +277,6 @@ static int putreg(struct task_struct *child,
return -EIO;
value &= 0xffff;
break;
- case offsetof(struct user_regs_struct, rip):
- /* Check if the new RIP address is canonical */
- if (value >= TASK_SIZE)
- return -EIO;
- break;
}
put_stack_long(child, regno - sizeof(struct pt_regs), value);
return 0;
@@ -380,7 +375,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
switch (addr) {
- case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
+ case 0 ... sizeof(struct user_regs_struct):
tmp = getreg(child, addr);
break;
case offsetof(struct user, u_debugreg[0]):
@@ -425,7 +420,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
switch (addr) {
- case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
+ case 0 ... sizeof(struct user_regs_struct):
ret = putreg(child, addr, data);
break;
/* Disallows to set a breakpoint into the vsyscall */
diff --git a/trunk/arch/x86_64/kernel/setup.c b/trunk/arch/x86_64/kernel/setup.c
index 99f038ede23c..2129cf9ba6b2 100644
--- a/trunk/arch/x86_64/kernel/setup.c
+++ b/trunk/arch/x86_64/kernel/setup.c
@@ -719,6 +719,7 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
}
}
+#ifdef CONFIG_SMP
/*
* On a AMD dual core setup the lower bits of the APIC id distingush the cores.
* Assumes number of cores is a power of two.
@@ -726,26 +727,17 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
- int cpu = smp_processor_id();
+ int cpu = c->x86_apicid;
int node = 0;
- unsigned bits;
if (c->x86_num_cores == 1)
return;
-
- bits = 0;
- while ((1 << bits) < c->x86_num_cores)
- bits++;
-
- /* Low order bits define the core id (index of core in socket) */
- cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
- /* Convert the APIC ID into the socket ID */
- phys_proc_id[cpu] >>= bits;
+ cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
#ifdef CONFIG_NUMA
/* When an ACPI SRAT table is available use the mappings from SRAT
instead. */
if (acpi_numa <= 0) {
- node = phys_proc_id[cpu];
+ node = cpu_core_id[cpu];
if (!node_online(node))
node = first_node(node_online_map);
cpu_to_node[cpu] = node;
@@ -753,11 +745,15 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
node = cpu_to_node[cpu];
}
#endif
-
printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
#endif
}
+#else
+static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
+{
+}
+#endif
static int __init init_amd(struct cpuinfo_x86 *c)
{
@@ -929,6 +925,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
c->x86_clflush_size = 64;
c->x86_cache_alignment = c->x86_clflush_size;
c->x86_num_cores = 1;
+ c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
c->extended_cpuid_level = 0;
memset(&c->x86_capability, 0, sizeof c->x86_capability);
@@ -957,14 +954,11 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
}
if (c->x86_capability[0] & (1<<19))
c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ c->x86_apicid = misc >> 24;
} else {
/* Have CPUID level 0 only - unheard of */
c->x86 = 4;
}
-
-#ifdef CONFIG_SMP
- phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
-#endif
}
/*
@@ -1094,7 +1088,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Other (Linux-defined) */
- "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
+ "cxmmx", NULL, "cyrix_arr", "centaur_mcr", "k8c+",
"constant_tsc", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/trunk/arch/x86_64/kernel/signal.c b/trunk/arch/x86_64/kernel/signal.c
index 429c0269dc4e..d439ced150c6 100644
--- a/trunk/arch/x86_64/kernel/signal.c
+++ b/trunk/arch/x86_64/kernel/signal.c
@@ -28,7 +28,6 @@
#include
#include
#include
-#include
/* #define DEBUG_SIG 1 */
@@ -453,9 +452,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->rip -= 2;
}
if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
- regs->rax = test_thread_flag(TIF_IA32) ?
- __NR_ia32_restart_syscall :
- __NR_restart_syscall;
+ regs->rax = __NR_restart_syscall;
regs->rip -= 2;
}
}
diff --git a/trunk/arch/x86_64/kernel/smpboot.c b/trunk/arch/x86_64/kernel/smpboot.c
index f1ec0f345941..73f7e8b9543a 100644
--- a/trunk/arch/x86_64/kernel/smpboot.c
+++ b/trunk/arch/x86_64/kernel/smpboot.c
@@ -56,7 +56,6 @@
#include
#include
#include
-#include
/* Change for real CPU hotplug. Note other files need to be fixed
first too. */
@@ -94,7 +93,6 @@ int smp_threads_ready;
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_core_map);
/*
* Trampoline 80x86 program as an array.
@@ -127,210 +125,96 @@ static void __cpuinit smp_store_cpu_info(int id)
*c = boot_cpu_data;
identify_cpu(c);
- print_cpu_info(c);
}
/*
- * New Funky TSC sync algorithm borrowed from IA64.
- * Main advantage is that it doesn't reset the TSCs fully and
- * in general looks more robust and it works better than my earlier
- * attempts. I believe it was written by David Mosberger. Some minor
- * adjustments for x86-64 by me -AK
+ * Synchronize TSCs of CPUs
*
- * Original comment reproduced below.
- *
- * Synchronize TSC of the current (slave) CPU with the TSC of the
- * MASTER CPU (normally the time-keeper CPU). We use a closed loop to
- * eliminate the possibility of unaccounted-for errors (such as
- * getting a machine check in the middle of a calibration step). The
- * basic idea is for the slave to ask the master what itc value it has
- * and to read its own itc before and after the master responds. Each
- * iteration gives us three timestamps:
- *
- * slave master
- *
- * t0 ---\
- * ---\
- * --->
- * tm
- * /---
- * /---
- * t1 <---
- *
- *
- * The goal is to adjust the slave's TSC such that tm falls exactly
- * half-way between t0 and t1. If we achieve this, the clocks are
- * synchronized provided the interconnect between the slave and the
- * master is symmetric. Even if the interconnect were asymmetric, we
- * would still know that the synchronization error is smaller than the
- * roundtrip latency (t0 - t1).
- *
- * When the interconnect is quiet and symmetric, this lets us
- * synchronize the TSC to within one or two cycles. However, we can
- * only *guarantee* that the synchronization is accurate to within a
- * round-trip time, which is typically in the range of several hundred
- * cycles (e.g., ~500 cycles). In practice, this means that the TSCs
- * are usually almost perfectly synchronized, but we shouldn't assume
- * that the accuracy is much better than half a micro second or so.
- *
- * [there are other errors like the latency of RDTSC and of the
- * WRMSR. These can also account to hundreds of cycles. So it's
- * probably worse. It claims 153 cycles error on a dual Opteron,
- * but I suspect the numbers are actually somewhat worse -AK]
+ * This new algorithm is less accurate than the old "zero TSCs"
+ * one, but we cannot zero TSCs anymore in the new hotplug CPU
+ * model.
*/
-#define MASTER 0
-#define SLAVE (SMP_CACHE_BYTES/8)
-
-/* Intentionally don't use cpu_relax() while TSC synchronization
- because we don't want to go into funky power save modi or cause
- hypervisors to schedule us away. Going to sleep would likely affect
- latency and low latency is the primary objective here. -AK */
-#define no_cpu_relax() barrier()
-
+static atomic_t __cpuinitdata tsc_flag;
static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
-static volatile __cpuinitdata unsigned long go[SLAVE + 1];
-static int notscsync __cpuinitdata;
-
-#undef DEBUG_TSC_SYNC
+static unsigned long long __cpuinitdata bp_tsc, ap_tsc;
-#define NUM_ROUNDS 64 /* magic value */
-#define NUM_ITERS 5 /* likewise */
+#define NR_LOOPS 5
-/* Callback on boot CPU */
-static __cpuinit void sync_master(void *arg)
+static void __cpuinit sync_tsc_bp_init(int init)
{
- unsigned long flags, i;
-
- if (smp_processor_id() != boot_cpu_id)
- return;
-
- go[MASTER] = 0;
-
- local_irq_save(flags);
- {
- for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
- while (!go[MASTER])
- no_cpu_relax();
- go[MASTER] = 0;
- rdtscll(go[SLAVE]);
- }
- }
- local_irq_restore(flags);
+ if (init)
+ _raw_spin_lock(&tsc_sync_lock);
+ else
+ _raw_spin_unlock(&tsc_sync_lock);
+ atomic_set(&tsc_flag, 0);
}
/*
- * Return the number of cycles by which our tsc differs from the tsc
- * on the master (time-keeper) CPU. A positive number indicates our
- * tsc is ahead of the master, negative that it is behind.
+ * Synchronize TSC on AP with BP.
*/
-static inline long
-get_delta(long *rt, long *master)
+static void __cpuinit __sync_tsc_ap(void)
{
- unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
- unsigned long tcenter, t0, t1, tm;
- int i;
-
- for (i = 0; i < NUM_ITERS; ++i) {
- rdtscll(t0);
- go[MASTER] = 1;
- while (!(tm = go[SLAVE]))
- no_cpu_relax();
- go[SLAVE] = 0;
- rdtscll(t1);
-
- if (t1 - t0 < best_t1 - best_t0)
- best_t0 = t0, best_t1 = t1, best_tm = tm;
- }
-
- *rt = best_t1 - best_t0;
- *master = best_tm - best_t0;
+ if (!cpu_has_tsc)
+ return;
+ Dprintk("AP %d syncing TSC\n", smp_processor_id());
- /* average best_t0 and best_t1 without overflow: */
- tcenter = (best_t0/2 + best_t1/2);
- if (best_t0 % 2 + best_t1 % 2 == 2)
- ++tcenter;
- return tcenter - best_tm;
+ while (atomic_read(&tsc_flag) != 0)
+ cpu_relax();
+ atomic_inc(&tsc_flag);
+ mb();
+ _raw_spin_lock(&tsc_sync_lock);
+ wrmsrl(MSR_IA32_TSC, bp_tsc);
+ _raw_spin_unlock(&tsc_sync_lock);
+ rdtscll(ap_tsc);
+ mb();
+ atomic_inc(&tsc_flag);
+ mb();
}
-static __cpuinit void sync_tsc(void)
+static void __cpuinit sync_tsc_ap(void)
{
- int i, done = 0;
- long delta, adj, adjust_latency = 0;
- unsigned long flags, rt, master_time_stamp, bound;
-#if DEBUG_TSC_SYNC
- static struct syncdebug {
- long rt; /* roundtrip time */
- long master; /* master's timestamp */
- long diff; /* difference between midpoint and master's timestamp */
- long lat; /* estimate of tsc adjustment latency */
- } t[NUM_ROUNDS] __cpuinitdata;
-#endif
-
- go[MASTER] = 1;
-
- smp_call_function(sync_master, NULL, 1, 0);
-
- while (go[MASTER]) /* wait for master to be ready */
- no_cpu_relax();
-
- spin_lock_irqsave(&tsc_sync_lock, flags);
- {
- for (i = 0; i < NUM_ROUNDS; ++i) {
- delta = get_delta(&rt, &master_time_stamp);
- if (delta == 0) {
- done = 1; /* let's lock on to this... */
- bound = rt;
- }
-
- if (!done) {
- unsigned long t;
- if (i > 0) {
- adjust_latency += -delta;
- adj = -delta + adjust_latency/4;
- } else
- adj = -delta;
-
- rdtscll(t);
- wrmsrl(MSR_IA32_TSC, t + adj);
- }
-#if DEBUG_TSC_SYNC
- t[i].rt = rt;
- t[i].master = master_time_stamp;
- t[i].diff = delta;
- t[i].lat = adjust_latency/4;
-#endif
- }
- }
- spin_unlock_irqrestore(&tsc_sync_lock, flags);
-
-#if DEBUG_TSC_SYNC
- for (i = 0; i < NUM_ROUNDS; ++i)
- printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
- t[i].rt, t[i].master, t[i].diff, t[i].lat);
-#endif
-
- printk(KERN_INFO
- "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
- "maxerr %lu cycles)\n",
- smp_processor_id(), boot_cpu_id, delta, rt);
+ int i;
+ for (i = 0; i < NR_LOOPS; i++)
+ __sync_tsc_ap();
}
-static void __cpuinit tsc_sync_wait(void)
+/*
+ * Synchronize TSC from BP to AP.
+ */
+static void __cpuinit __sync_tsc_bp(int cpu)
{
- if (notscsync || !cpu_has_tsc)
+ if (!cpu_has_tsc)
return;
- printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(),
- boot_cpu_id);
- sync_tsc();
+
+ /* Wait for AP */
+ while (atomic_read(&tsc_flag) == 0)
+ cpu_relax();
+ /* Save BPs TSC */
+ sync_core();
+ rdtscll(bp_tsc);
+ /* Don't do the sync core here to avoid too much latency. */
+ mb();
+ /* Start the AP */
+ _raw_spin_unlock(&tsc_sync_lock);
+ /* Wait for AP again */
+ while (atomic_read(&tsc_flag) < 2)
+ cpu_relax();
+ rdtscl(bp_tsc);
+ barrier();
}
-static __init int notscsync_setup(char *s)
+static void __cpuinit sync_tsc_bp(int cpu)
{
- notscsync = 1;
- return 0;
+ int i;
+ for (i = 0; i < NR_LOOPS - 1; i++) {
+ __sync_tsc_bp(cpu);
+ sync_tsc_bp_init(1);
+ }
+ __sync_tsc_bp(cpu);
+ printk(KERN_INFO "Synced TSC of CPU %d difference %Ld\n",
+ cpu, ap_tsc - bp_tsc);
}
-__setup("notscsync", notscsync_setup);
static atomic_t init_deasserted __cpuinitdata;
@@ -431,6 +315,11 @@ void __cpuinit start_secondary(void)
cpu_init();
smp_callin();
+ /*
+ * Synchronize the TSC with the BP
+ */
+ sync_tsc_ap();
+
/* otherwise gcc will move up the smp_processor_id before the cpu_init */
barrier();
@@ -445,6 +334,7 @@ void __cpuinit start_secondary(void)
enable_8259A_irq(0);
}
+
enable_APIC_timer();
/*
@@ -453,11 +343,6 @@ void __cpuinit start_secondary(void)
cpu_set(smp_processor_id(), cpu_online_map);
mb();
- /* Wait for TSC sync to not schedule things before.
- We still process interrupts, which could see an inconsistent
- time in that window unfortunately. */
- tsc_sync_wait();
-
cpu_idle();
}
@@ -646,6 +531,7 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
printk("failed fork for CPU %d\n", cpu);
return PTR_ERR(idle);
}
+ x86_cpu_to_apicid[cpu] = apicid;
cpu_pda[cpu].pcurrent = idle;
@@ -714,6 +600,8 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
if (cpu_isset(cpu, cpu_callin_map)) {
/* number CPUs logically, starting from 1 (BSP is 0) */
+ Dprintk("OK.\n");
+ print_cpu_info(&cpu_data[cpu]);
Dprintk("CPU has booted.\n");
} else {
boot_error = 1;
@@ -954,6 +842,7 @@ void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
/* Or can we switch back to PIC here? */
}
+ x86_cpu_to_apicid[0] = boot_cpu_id;
/*
* Now start the IO-APICs
@@ -1000,14 +889,18 @@ int __cpuinit __cpu_up(unsigned int cpu)
printk("__cpu_up: bad cpu %d\n", cpu);
return -EINVAL;
}
+ sync_tsc_bp_init(1);
/* Boot it! */
err = do_boot_cpu(cpu, apicid);
if (err < 0) {
+ sync_tsc_bp_init(0);
Dprintk("do_boot_cpu failed %d\n", err);
return err;
}
+ sync_tsc_bp(cpu);
+
/* Unleash the CPU! */
Dprintk("waiting for cpu %d\n", cpu);
@@ -1030,6 +923,4 @@ void __cpuinit smp_cpus_done(unsigned int max_cpus)
detect_siblings();
time_init_gtod();
-
- check_nmi_watchdog();
}
diff --git a/trunk/arch/x86_64/kernel/time.c b/trunk/arch/x86_64/kernel/time.c
index fb8c809b4cd9..0e3b60e1ac5b 100644
--- a/trunk/arch/x86_64/kernel/time.c
+++ b/trunk/arch/x86_64/kernel/time.c
@@ -26,10 +26,6 @@
#include
#include
#include
-#include
-#ifdef CONFIG_ACPI
-#include /* for PM timer frequency */
-#endif
#include
#include
#include
@@ -400,10 +396,6 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
(offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
vxtime.last = offset;
-#ifdef CONFIG_X86_PM_TIMER
- } else if (vxtime.mode == VXTIME_PMTMR) {
- lost = pmtimer_mark_offset();
-#endif
} else {
offset = (((tsc - vxtime.last_tsc) *
vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
@@ -906,13 +898,6 @@ void __init time_init(void)
hpet_period;
cpu_khz = hpet_calibrate_tsc();
timename = "HPET";
-#ifdef CONFIG_X86_PM_TIMER
- } else if (pmtmr_ioport) {
- vxtime_hz = PM_TIMER_FREQUENCY;
- timename = "PM";
- pit_init();
- cpu_khz = pit_calibrate_tsc();
-#endif
} else {
pit_init();
cpu_khz = pit_calibrate_tsc();
@@ -937,27 +922,6 @@ void __init time_init(void)
#endif
}
-/*
- * Make an educated guess if the TSC is trustworthy and synchronized
- * over all CPUs.
- */
-static __init int unsynchronized_tsc(void)
-{
-#ifdef CONFIG_SMP
- if (oem_force_hpet_timer())
- return 1;
- /* Intel systems are normally all synchronized. Exceptions
- are handled in the OEM check above. */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
- return 0;
- /* All in a single socket - should be synchronized */
- if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
- return 0;
-#endif
- /* Assume multi socket systems are not synchronized */
- return num_online_cpus() > 1;
-}
-
/*
* Decide after all CPUs are booted what mode gettimeofday should use.
*/
@@ -965,23 +929,29 @@ void __init time_init_gtod(void)
{
char *timetype;
- if (unsynchronized_tsc())
+ /*
+ * AMD systems with more than one CPU don't have fully synchronized
+ * TSCs. Always use HPET gettimeofday for these, although it is slower.
+ * Intel SMP systems usually have synchronized TSCs, so use always
+ * the TSC.
+ *
+ * Exceptions:
+ * IBM Summit2 checked by oem_force_hpet_timer().
+ * AMD dual core may also not need HPET. Check me.
+ *
+ * Can be turned off with "notsc".
+ */
+ if (num_online_cpus() > 1 &&
+ boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ notsc = 1;
+ /* Some systems will want to disable TSC and use HPET. */
+ if (oem_force_hpet_timer())
notsc = 1;
if (vxtime.hpet_address && notsc) {
timetype = "HPET";
vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
vxtime.mode = VXTIME_HPET;
do_gettimeoffset = do_gettimeoffset_hpet;
-#ifdef CONFIG_X86_PM_TIMER
- /* Using PM for gettimeofday is quite slow, but we have no other
- choice because the TSC is too unreliable on some systems. */
- } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
- timetype = "PM";
- do_gettimeoffset = do_gettimeoffset_pm;
- vxtime.mode = VXTIME_PMTMR;
- sysctl_vsyscall = 0;
- printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
-#endif
} else {
timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
vxtime.mode = VXTIME_TSC;
diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c
index 3dfec8fdabcd..65a37f52c56e 100644
--- a/trunk/arch/x86_64/kernel/traps.c
+++ b/trunk/arch/x86_64/kernel/traps.c
@@ -332,12 +332,10 @@ void handle_BUG(struct pt_regs *regs)
printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
}
-#ifdef CONFIG_BUG
void out_of_line_bug(void)
{
BUG();
}
-#endif
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
diff --git a/trunk/arch/x86_64/kernel/vsyscall.c b/trunk/arch/x86_64/kernel/vsyscall.c
index 2e5734425949..b4b8dc59663a 100644
--- a/trunk/arch/x86_64/kernel/vsyscall.c
+++ b/trunk/arch/x86_64/kernel/vsyscall.c
@@ -65,7 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
usec = (__xtime.tv_nsec / 1000) +
(__jiffies - __wall_jiffies) * (1000000 / HZ);
- if (__vxtime.mode != VXTIME_HPET) {
+ if (__vxtime.mode == VXTIME_TSC) {
sync_core();
rdtscll(t);
if (t < __vxtime.last_tsc)
@@ -217,9 +217,8 @@ static int __init vsyscall_init(void)
BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
map_vsyscall();
-#ifdef CONFIG_SYSCTL
+ sysctl_vsyscall = 1;
register_sysctl_table(kernel_root_table2, 0);
-#endif
return 0;
}
diff --git a/trunk/arch/x86_64/kernel/x8664_ksyms.c b/trunk/arch/x86_64/kernel/x8664_ksyms.c
index 68ec03070e5a..a43dedb58fa2 100644
--- a/trunk/arch/x86_64/kernel/x8664_ksyms.c
+++ b/trunk/arch/x86_64/kernel/x8664_ksyms.c
@@ -193,9 +193,8 @@ EXPORT_SYMBOL(smp_num_siblings);
extern void do_softirq_thunk(void);
EXPORT_SYMBOL(do_softirq_thunk);
-#ifdef CONFIG_BUG
+void out_of_line_bug(void);
EXPORT_SYMBOL(out_of_line_bug);
-#endif
EXPORT_SYMBOL(init_level4_pgt);
diff --git a/trunk/arch/x86_64/mm/fault.c b/trunk/arch/x86_64/mm/fault.c
index 5d6b2114cc9a..e03309216764 100644
--- a/trunk/arch/x86_64/mm/fault.c
+++ b/trunk/arch/x86_64/mm/fault.c
@@ -234,8 +234,6 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
/*
* Handle a fault on the vmalloc or module mapping area
- *
- * This assumes no large pages in there.
*/
static int vmalloc_fault(unsigned long address)
{
@@ -274,10 +272,7 @@ static int vmalloc_fault(unsigned long address)
if (!pte_present(*pte_ref))
return -1;
pte = pte_offset_kernel(pmd, address);
- /* Don't use pte_page here, because the mappings can point
- outside mem_map, and the NUMA hash lookup cannot handle
- that. */
- if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
+ if (!pte_present(*pte) || pte_page(*pte) != pte_page(*pte_ref))
BUG();
__flush_tlb_all();
return 0;
@@ -351,9 +346,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* protection error (error_code & 1) == 0.
*/
if (unlikely(address >= TASK_SIZE)) {
- if (!(error_code & 5) &&
- ((address >= VMALLOC_START && address < VMALLOC_END) ||
- (address >= MODULES_VADDR && address < MODULES_END))) {
+ if (!(error_code & 5)) {
if (vmalloc_fault(address) < 0)
goto bad_area_nosemaphore;
return;
diff --git a/trunk/arch/x86_64/mm/ioremap.c b/trunk/arch/x86_64/mm/ioremap.c
index 58aac23760ef..74ec8554b195 100644
--- a/trunk/arch/x86_64/mm/ioremap.c
+++ b/trunk/arch/x86_64/mm/ioremap.c
@@ -133,7 +133,7 @@ ioremap_change_attr(unsigned long phys_addr, unsigned long size,
unsigned long flags)
{
int err = 0;
- if (phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
+ if (flags && phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long vaddr = (unsigned long) __va(phys_addr);
@@ -214,7 +214,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
return NULL;
}
- if (flags && ioremap_change_attr(phys_addr, size, flags) < 0) {
+ if (ioremap_change_attr(phys_addr, size, flags) < 0) {
area->flags &= 0xffffff;
vunmap(addr);
return NULL;
@@ -251,7 +251,7 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
void iounmap(volatile void __iomem *addr)
{
- struct vm_struct *p;
+ struct vm_struct *p, **pprev;
if (addr <= high_memory)
return;
@@ -260,11 +260,24 @@ void iounmap(volatile void __iomem *addr)
return;
write_lock(&vmlist_lock);
- p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK));
- if (!p)
- printk("iounmap: bad address %p\n", addr);
- else if (p->flags >> 20)
- ioremap_change_attr(p->phys_addr, p->size, 0);
+ for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = *pprev)
+ if (p->addr == (void *)(PAGE_MASK & (unsigned long)addr))
+ break;
+ if (!p) {
+ printk("__iounmap: bad address %p\n", addr);
+ goto out_unlock;
+ }
+ *pprev = p->next;
+ unmap_vm_area(p);
+ if ((p->flags >> 20) &&
+ p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
+ /* p->size includes the guard page, but cpa doesn't like that */
+ change_page_attr(virt_to_page(__va(p->phys_addr)),
+ p->size >> PAGE_SHIFT,
+ PAGE_KERNEL);
+ global_flush_tlb();
+ }
+out_unlock:
write_unlock(&vmlist_lock);
kfree(p);
}
diff --git a/trunk/crypto/crypto_null.c b/trunk/crypto/crypto_null.c
index 3fcf6e887e87..f691d31fa9ee 100644
--- a/trunk/crypto/crypto_null.c
+++ b/trunk/crypto/crypto_null.c
@@ -21,7 +21,6 @@
#include
#include
#include
-#include
#define NULL_KEY_SIZE 0
#define NULL_BLOCK_SIZE 1
@@ -29,13 +28,11 @@
static int null_compress(void *ctx, const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen)
-{
- if (slen > *dlen)
- return -EINVAL;
- memcpy(dst, src, slen);
- *dlen = slen;
- return 0;
-}
+{ return 0; }
+
+static int null_decompress(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{ return 0; }
static void null_init(void *ctx)
{ }
@@ -50,10 +47,11 @@ static int null_setkey(void *ctx, const u8 *key,
unsigned int keylen, u32 *flags)
{ return 0; }
-static void null_crypt(void *ctx, u8 *dst, const u8 *src)
-{
- memcpy(dst, src, NULL_BLOCK_SIZE);
-}
+static void null_encrypt(void *ctx, u8 *dst, const u8 *src)
+{ }
+
+static void null_decrypt(void *ctx, u8 *dst, const u8 *src)
+{ }
static struct crypto_alg compress_null = {
.cra_name = "compress_null",
@@ -64,7 +62,7 @@ static struct crypto_alg compress_null = {
.cra_list = LIST_HEAD_INIT(compress_null.cra_list),
.cra_u = { .compress = {
.coa_compress = null_compress,
- .coa_decompress = null_compress } }
+ .coa_decompress = null_decompress } }
};
static struct crypto_alg digest_null = {
@@ -92,8 +90,8 @@ static struct crypto_alg cipher_null = {
.cia_min_keysize = NULL_KEY_SIZE,
.cia_max_keysize = NULL_KEY_SIZE,
.cia_setkey = null_setkey,
- .cia_encrypt = null_crypt,
- .cia_decrypt = null_crypt } }
+ .cia_encrypt = null_encrypt,
+ .cia_decrypt = null_decrypt } }
};
MODULE_ALIAS("compress_null");
diff --git a/trunk/crypto/internal.h b/trunk/crypto/internal.h
index 964b9a60ca24..e68e43886d3c 100644
--- a/trunk/crypto/internal.h
+++ b/trunk/crypto/internal.h
@@ -38,7 +38,7 @@ static inline void crypto_kunmap(void *vaddr, int out)
static inline void crypto_yield(struct crypto_tfm *tfm)
{
- if (!in_atomic())
+ if (!in_softirq())
cond_resched();
}
diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig
index 670fdb5142d1..0400a52d5085 100644
--- a/trunk/drivers/acpi/Kconfig
+++ b/trunk/drivers/acpi/Kconfig
@@ -40,12 +40,13 @@ config ACPI
available at:
-if ACPI
-
config ACPI_BOOT
bool
+ depends on ACPI || X86_HT
default y
+if ACPI
+
config ACPI_INTERPRETER
bool
depends on !IA64_SGI_SN
diff --git a/trunk/drivers/acpi/pci_irq.c b/trunk/drivers/acpi/pci_irq.c
index 8093f2e00321..12b0eea63407 100644
--- a/trunk/drivers/acpi/pci_irq.c
+++ b/trunk/drivers/acpi/pci_irq.c
@@ -391,6 +391,7 @@ acpi_pci_irq_enable (
u8 pin = 0;
int edge_level = ACPI_LEVEL_SENSITIVE;
int active_high_low = ACPI_ACTIVE_LOW;
+ extern int via_interrupt_line_quirk;
char *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
@@ -443,6 +444,9 @@ acpi_pci_irq_enable (
}
}
+ if (via_interrupt_line_quirk)
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15);
+
dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
diff --git a/trunk/drivers/atm/Makefile b/trunk/drivers/atm/Makefile
index 5b77188527a9..d1dcd8eae3c9 100644
--- a/trunk/drivers/atm/Makefile
+++ b/trunk/drivers/atm/Makefile
@@ -39,8 +39,7 @@ 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)
- 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)
+ 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)
endif
endif
diff --git a/trunk/drivers/atm/fore200e.c b/trunk/drivers/atm/fore200e.c
index 5f702199543a..9e65bfb85ba3 100644
--- a/trunk/drivers/atm/fore200e.c
+++ b/trunk/drivers/atm/fore200e.c
@@ -383,7 +383,8 @@ fore200e_shutdown(struct fore200e* fore200e)
switch(fore200e->state) {
case FORE200E_STATE_COMPLETE:
- kfree(fore200e->stats);
+ if (fore200e->stats)
+ kfree(fore200e->stats);
case FORE200E_STATE_IRQ:
free_irq(fore200e->irq, fore200e->atm_dev);
@@ -962,7 +963,8 @@ fore200e_tx_irq(struct fore200e* fore200e)
entry, txq->tail, entry->vc_map, entry->skb);
/* free copy of misaligned data */
- kfree(entry->data);
+ if (entry->data)
+ kfree(entry->data);
/* remove DMA mapping */
fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
diff --git a/trunk/drivers/atm/he.c b/trunk/drivers/atm/he.c
index df2c83fd5496..3022c548a132 100644
--- a/trunk/drivers/atm/he.c
+++ b/trunk/drivers/atm/he.c
@@ -412,7 +412,8 @@ 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);
- kfree(he_dev);
+ if (he_dev)
+ kfree(he_dev);
pci_disable_device(pci_dev);
return err;
}
@@ -2533,7 +2534,8 @@ he_open(struct atm_vcc *vcc)
open_failed:
if (err) {
- kfree(he_vcc);
+ if (he_vcc)
+ kfree(he_vcc);
clear_bit(ATM_VF_ADDR, &vcc->flags);
}
else
diff --git a/trunk/drivers/atm/nicstar.c b/trunk/drivers/atm/nicstar.c
index b2a7b754fd14..85bf5c8442b0 100644
--- a/trunk/drivers/atm/nicstar.c
+++ b/trunk/drivers/atm/nicstar.c
@@ -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 = NULL;
- card->scq2 = NULL;
+ card->scq1 = (scq_info *) NULL;
+ card->scq2 = (scq_info *) NULL;
card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);
- if (card->scq0 == NULL)
+ if (card->scq0 == (scq_info *) 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 NULL;
+ return (scq_info *) NULL;
scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
- if (scq == NULL)
- return NULL;
+ if (scq == (scq_info *) NULL)
+ return (scq_info *) NULL;
scq->org = kmalloc(2 * size, GFP_KERNEL);
if (scq->org == NULL)
{
kfree(scq);
- return NULL;
+ return (scq_info *) NULL;
}
scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
(size / NS_SCQE_SIZE), GFP_KERNEL);
- if (scq->skb == NULL)
+ if (scq->skb == (struct sk_buff **) NULL)
{
kfree(scq->org);
kfree(scq);
- return NULL;
+ return (scq_info *) 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 == NULL)
+ if (scq == (scq_info *) NULL)
{
PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);
card->scd2vc[frscdi] = NULL;
diff --git a/trunk/drivers/atm/zatm.c b/trunk/drivers/atm/zatm.c
index 8d5e65cb9755..47a800519ad0 100644
--- a/trunk/drivers/atm/zatm.c
+++ b/trunk/drivers/atm/zatm.c
@@ -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);
}
- kfree(zatm_vcc->ring);
+ if (zatm_vcc->ring) kfree(zatm_vcc->ring);
}
@@ -1339,9 +1339,12 @@ static int __init zatm_start(struct atm_dev *dev)
return 0;
out:
for (i = 0; i < NR_MBX; i++)
- kfree(zatm_dev->mbx_start[i]);
- kfree(zatm_dev->rx_map);
- kfree(zatm_dev->tx_map);
+ 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);
free_irq(zatm_dev->irq, dev);
return error;
}
diff --git a/trunk/drivers/base/Makefile b/trunk/drivers/base/Makefile
index a47928a2e575..6662b545e0a9 100644
--- a/trunk/drivers/base/Makefile
+++ b/trunk/drivers/base/Makefile
@@ -1,6 +1,6 @@
# Makefile for the Linux device tree
-obj-y := core.o sys.o bus.o \
+obj-y := core.o sys.o interface.o bus.o \
driver.o class.o class_simple.o platform.o \
cpu.o firmware.o init.o map.o dmapool.o \
attribute_container.o transport_class.o
diff --git a/trunk/drivers/base/bus.c b/trunk/drivers/base/bus.c
index 3cb04bb04c2b..2b3902c867da 100644
--- a/trunk/drivers/base/bus.c
+++ b/trunk/drivers/base/bus.c
@@ -390,6 +390,7 @@ void device_release_driver(struct device * dev)
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
sysfs_remove_link(&dev->kobj, "driver");
list_del_init(&dev->driver_list);
+ device_detach_shutdown(dev);
if (drv->remove)
drv->remove(dev);
dev->driver = NULL;
diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c
index fbc223486f81..268a9c8d168b 100644
--- a/trunk/drivers/base/core.c
+++ b/trunk/drivers/base/core.c
@@ -31,6 +31,8 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
#define to_dev(obj) container_of(obj, struct device, kobj)
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
+extern struct attribute * dev_default_attrs[];
+
static ssize_t
dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
@@ -87,6 +89,7 @@ static void device_release(struct kobject * kobj)
static struct kobj_type ktype_device = {
.release = device_release,
.sysfs_ops = &dev_sysfs_ops,
+ .default_attrs = dev_default_attrs,
};
@@ -245,7 +248,6 @@ int device_add(struct device *dev)
if ((error = kobject_add(&dev->kobj)))
goto Error;
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
@@ -258,13 +260,14 @@ int device_add(struct device *dev)
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
+
+ kobject_hotplug(&dev->kobj, KOBJ_ADD);
Done:
put_device(dev);
return error;
BusError:
device_pm_remove(dev);
PMError:
- kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
Error:
if (parent)
diff --git a/trunk/drivers/base/interface.c b/trunk/drivers/base/interface.c
new file mode 100644
index 000000000000..bd515843a0cb
--- /dev/null
+++ b/trunk/drivers/base/interface.c
@@ -0,0 +1,51 @@
+/*
+ * drivers/base/interface.c - common driverfs interface that's exported to
+ * the world for all devices.
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+/**
+ * detach_state - control the default power state for the device.
+ *
+ * This is the state the device enters when it's driver module is
+ * unloaded. The value is an unsigned integer, in the range of 0-4.
+ * '0' indicates 'On', so no action will be taken when the driver is
+ * unloaded. This is the default behavior.
+ * '4' indicates 'Off', meaning the driver core will call the driver's
+ * shutdown method to quiesce the device.
+ * 1-3 indicate a low-power state for the device to enter via the
+ * driver's suspend method.
+ */
+
+static ssize_t detach_show(struct device * dev, char * buf)
+{
+ return sprintf(buf, "%u\n", dev->detach_state);
+}
+
+static ssize_t detach_store(struct device * dev, const char * buf, size_t n)
+{
+ u32 state;
+ state = simple_strtoul(buf, NULL, 10);
+ if (state > 4)
+ return -EINVAL;
+ dev->detach_state = state;
+ return n;
+}
+
+static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store);
+
+
+struct attribute * dev_default_attrs[] = {
+ &dev_attr_detach_state.attr,
+ NULL,
+};
diff --git a/trunk/drivers/base/power/power.h b/trunk/drivers/base/power/power.h
index 2e700d795cf1..e5eda746f2a6 100644
--- a/trunk/drivers/base/power/power.h
+++ b/trunk/drivers/base/power/power.h
@@ -1,7 +1,18 @@
+
+
+enum {
+ DEVICE_PM_ON,
+ DEVICE_PM1,
+ DEVICE_PM2,
+ DEVICE_PM3,
+ DEVICE_PM_OFF,
+};
+
/*
* shutdown.c
*/
+extern int device_detach_shutdown(struct device *);
extern void device_shutdown(void);
diff --git a/trunk/drivers/base/power/resume.c b/trunk/drivers/base/power/resume.c
index 26468971ef5a..f8f5055754d6 100644
--- a/trunk/drivers/base/power/resume.c
+++ b/trunk/drivers/base/power/resume.c
@@ -22,17 +22,8 @@ extern int sysdev_resume(void);
int resume_device(struct device * dev)
{
- if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state) {
- dev_err(dev, "PM: resume from %d, parent %s still %d\n",
- dev->power.power_state,
- dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state);
- }
- if (dev->bus && dev->bus->resume) {
- dev_dbg(dev,"resuming\n");
+ if (dev->bus && dev->bus->resume)
return dev->bus->resume(dev);
- }
return 0;
}
diff --git a/trunk/drivers/base/power/shutdown.c b/trunk/drivers/base/power/shutdown.c
index f50a08be424b..d1e023fbe169 100644
--- a/trunk/drivers/base/power/shutdown.c
+++ b/trunk/drivers/base/power/shutdown.c
@@ -19,6 +19,20 @@
extern struct subsystem devices_subsys;
+int device_detach_shutdown(struct device * dev)
+{
+ if (!dev->detach_state)
+ return 0;
+
+ if (dev->detach_state == DEVICE_PM_OFF) {
+ if (dev->driver && dev->driver->shutdown)
+ dev->driver->shutdown(dev);
+ return 0;
+ }
+ return dpm_runtime_suspend(dev, dev->detach_state);
+}
+
+
/**
* We handle system devices differently - we suspend and shut them
* down last and resume them first. That way, we don't do anything stupid like
@@ -38,12 +52,13 @@ void device_shutdown(void)
struct device * dev;
down_write(&devices_subsys.rwsem);
- list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
- kobj.entry) {
+ list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) {
+ pr_debug("shutting down %s: ", dev->bus_id);
if (dev->driver && dev->driver->shutdown) {
- dev_dbg(dev, "shutdown\n");
+ pr_debug("Ok\n");
dev->driver->shutdown(dev);
- }
+ } else
+ pr_debug("Ignored.\n");
}
up_write(&devices_subsys.rwsem);
diff --git a/trunk/drivers/base/power/suspend.c b/trunk/drivers/base/power/suspend.c
index 0ec44ef840be..a0b5cf689e63 100644
--- a/trunk/drivers/base/power/suspend.c
+++ b/trunk/drivers/base/power/suspend.c
@@ -39,25 +39,12 @@ int suspend_device(struct device * dev, pm_message_t state)
{
int error = 0;
- if (dev->power.power_state) {
- dev_dbg(dev, "PM: suspend %d-->%d\n",
- dev->power.power_state, state);
- }
- if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state) {
- dev_err(dev,
- "PM: suspend %d->%d, parent %s already %d\n",
- dev->power.power_state, state,
- dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state);
- }
+ dev_dbg(dev, "suspending\n");
dev->power.prev_state = dev->power.power_state;
- if (dev->bus && dev->bus->suspend && !dev->power.power_state) {
- dev_dbg(dev, "suspending\n");
+ if (dev->bus && dev->bus->suspend && !dev->power.power_state)
error = dev->bus->suspend(dev, state);
- }
return error;
}
diff --git a/trunk/drivers/block/ioctl.c b/trunk/drivers/block/ioctl.c
index 6d7bcc9da9e7..5e03f5157ef9 100644
--- a/trunk/drivers/block/ioctl.c
+++ b/trunk/drivers/block/ioctl.c
@@ -237,5 +237,3 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
return ret;
}
-
-EXPORT_SYMBOL_GPL(blkdev_ioctl);
diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c
index bc56770bcc90..1a1fa3ccb913 100644
--- a/trunk/drivers/block/pktcdvd.c
+++ b/trunk/drivers/block/pktcdvd.c
@@ -914,10 +914,8 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
bio = node->bio;
zone = ZONE(bio->bi_sector, pd);
list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
- if (p->sector == zone) {
- bio = NULL;
+ if (p->sector == zone)
goto try_next_bio;
- }
}
break;
try_next_bio:
@@ -2021,13 +2019,7 @@ static int pkt_open(struct inode *inode, struct file *file)
BUG_ON(pd->refcnt < 0);
pd->refcnt++;
- if (pd->refcnt > 1) {
- if ((file->f_mode & FMODE_WRITE) &&
- !test_bit(PACKET_WRITABLE, &pd->flags)) {
- ret = -EBUSY;
- goto out_dec;
- }
- } else {
+ if (pd->refcnt == 1) {
if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) {
ret = -EIO;
goto out_dec;
@@ -2414,7 +2406,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
case CDROM_LAST_WRITTEN:
case CDROM_SEND_PACKET:
case SCSI_IOCTL_SEND_COMMAND:
- return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+ return ioctl_by_bdev(pd->bdev, cmd, arg);
case CDROMEJECT:
/*
@@ -2422,7 +2414,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
* have to unlock it or else the eject command fails.
*/
pkt_lock_door(pd, 0);
- return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+ return ioctl_by_bdev(pd->bdev, cmd, arg);
default:
printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
diff --git a/trunk/drivers/block/ub.c b/trunk/drivers/block/ub.c
index adc4dcc306f4..ce42889f98fb 100644
--- a/trunk/drivers/block/ub.c
+++ b/trunk/drivers/block/ub.c
@@ -8,12 +8,13 @@
* 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
@@ -48,14 +49,7 @@
#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 */
@@ -71,7 +65,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 */
+ u8 Lun; /* LUN normally 0 */
u8 Length; /* of of the CDB */
u8 CDB[UB_MAX_CDB_SIZE]; /* max command */
};
@@ -174,7 +168,6 @@ 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;
};
@@ -259,47 +252,25 @@ struct ub_scsi_cmd_queue {
};
/*
- * 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.
+ * The UB 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;
- char name[12];
+ int changed; /* Media was changed */
+ int removable;
+ int readonly;
+ int first_open; /* Kludge. See ub_bd_open. */
+ char name[8];
struct usb_device *dev;
struct usb_interface *intf;
- struct list_head luns;
+ struct ub_capacity capacity;
+ struct gendisk *disk;
unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe;
@@ -308,6 +279,10 @@ 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];
@@ -326,9 +301,9 @@ struct ub_dev {
/*
*/
static void ub_cleanup(struct ub_dev *sc);
-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_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_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);
@@ -345,10 +320,8 @@ 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, 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);
+static int ub_sync_tur(struct ub_dev *sc);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
/*
*/
@@ -369,7 +342,6 @@ 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 */
/*
@@ -434,8 +406,6 @@ 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;
@@ -451,15 +421,9 @@ 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\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);
- }
+ "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);
if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
for (j = 0; j < SCMD_TRACE_SZ; j++) {
@@ -559,63 +523,53 @@ 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;
- while (!list_empty(&sc->luns)) {
- p = sc->luns.next;
- lun = list_entry(p, struct ub_lun, link);
- list_del(p);
-
- /* 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;
+ /* I don't think queue can be NULL. But... Stolen from sx8.c */
+ if ((q = sc->disk->queue) != NULL)
+ blk_cleanup_queue(q);
- ub_id_put(lun->id);
- kfree(lun);
- }
+ /*
+ * 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;
+ ub_id_put(sc->id);
kfree(sc);
}
/*
* The "command allocator".
*/
-static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun)
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
{
struct ub_scsi_cmd *ret;
- if (lun->cmda[0])
+ if (sc->cmda[0])
return NULL;
- ret = &lun->cmdv[0];
- lun->cmda[0] = 1;
+ ret = &sc->cmdv[0];
+ sc->cmda[0] = 1;
return ret;
}
-static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd)
+static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
- if (cmd != &lun->cmdv[0]) {
+ if (cmd != &sc->cmdv[0]) {
printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
- lun->name, cmd);
+ sc->name, cmd);
return;
}
- if (!lun->cmda[0]) {
- printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name);
+ if (!sc->cmda[0]) {
+ printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
return;
}
- lun->cmda[0] = 0;
+ sc->cmda[0] = 0;
}
/*
@@ -676,30 +630,29 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
static void ub_bd_rq_fn(request_queue_t *q)
{
- struct ub_lun *lun = q->queuedata;
+ struct ub_dev *sc = q->queuedata;
struct request *rq;
while ((rq = elv_next_request(q)) != NULL) {
- if (ub_bd_rq_fn_1(lun, rq) != 0) {
+ if (ub_bd_rq_fn_1(sc, rq) != 0) {
blk_stop_queue(q);
break;
}
}
}
-static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
+static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
{
- struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
int rc;
- if (atomic_read(&sc->poison) || lun->changed) {
+ if (atomic_read(&sc->poison) || sc->changed) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, 0);
return 0;
}
- if ((cmd = ub_get_cmd(lun)) == NULL)
+ if ((cmd = ub_get_cmd(sc)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
@@ -708,30 +661,32 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
if (blk_pc_request(rq)) {
rc = ub_cmd_build_packet(sc, cmd, rq);
} else {
- rc = ub_cmd_build_block(sc, lun, cmd, rq);
+ rc = ub_cmd_build_block(sc, cmd, rq);
}
if (rc != 0) {
- ub_put_cmd(lun, cmd);
+ ub_put_cmd(sc, 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(lun, cmd);
+ ub_put_cmd(sc, 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_lun *lun,
- struct ub_scsi_cmd *cmd, struct request *rq)
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+ struct request *rq)
{
int ub_dir;
#if 0 /* We use rq->buffer for now */
@@ -752,7 +707,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
sg = &cmd->sgv[0];
n_elem = blk_rq_map_sg(q, rq, sg);
if (n_elem <= 0) {
- ub_put_cmd(lun, cmd);
+ ub_put_cmd(sc, cmd);
ub_end_rq(rq, 0);
blk_start_queue(q);
return 0; /* request with no s/g entries? */
@@ -761,7 +716,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
if (n_elem != 1) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
- ub_put_cmd(lun, cmd);
+ ub_put_cmd(sc, cmd);
ub_end_rq(rq, 0);
blk_start_queue(q);
return 0;
@@ -793,8 +748,8 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
* 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 >> lun->capacity.bshift;
- nblks = rq->nr_sectors >> lun->capacity.bshift;
+ block = rq->sector >> sc->capacity.bshift;
+ nblks = rq->nr_sectors >> sc->capacity.bshift;
cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
@@ -848,8 +803,7 @@ 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 ub_lun *lun = cmd->lun;
- struct gendisk *disk = lun->disk;
+ struct gendisk *disk = sc->disk;
request_queue_t *q = disk->queue;
int uptodate;
@@ -864,7 +818,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
else
uptodate = 0;
- ub_put_cmd(lun, cmd);
+ ub_put_cmd(sc, cmd);
ub_end_rq(rq, uptodate);
blk_start_queue(q);
}
@@ -933,7 +887,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 = (cmd->lun != NULL) ? cmd->lun->num : 0;
+ bcb->Lun = 0; /* No multi-LUN yet */
bcb->Length = cmd->cdb_len;
/* copy the command payload */
@@ -1048,8 +1002,9 @@ 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\n",
- sc->name);
+ printk(KERN_NOTICE "%s: "
+ "stall on control pipe for device %u\n",
+ sc->name, sc->dev->devnum);
goto Bad_End;
}
@@ -1070,8 +1025,9 @@ 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\n",
- sc->name);
+ printk(KERN_NOTICE "%s: "
+ "stall on control pipe for device %u\n",
+ sc->name, sc->dev->devnum);
goto Bad_End;
}
@@ -1090,8 +1046,9 @@ 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 (%d)\n",
- sc->name, rc);
+ "unable to submit clear for device %u"
+ " (code %d)\n",
+ sc->name, sc->dev->devnum, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1150,8 +1107,9 @@ 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 (%d)\n",
- sc->name, rc);
+ "unable to submit clear for device %u"
+ " (code %d)\n",
+ sc->name, sc->dev->devnum, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1182,8 +1140,9 @@ 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 (%d)\n",
- sc->name, rc);
+ "unable to submit clear for device %u"
+ " (code %d)\n",
+ sc->name, sc->dev->devnum, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1205,8 +1164,9 @@ 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\n",
- sc->name);
+ printk(KERN_NOTICE "%s: "
+ "unable to get CSW on device %u\n",
+ sc->name, sc->dev->devnum);
goto Bad_End;
}
__ub_state_stat(sc, cmd);
@@ -1247,8 +1207,10 @@ 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\n",
- sc->name, cmd->tag, bcs->Tag);
+ "tag mismatch orig 0x%x reply 0x%x "
+ "on device %u\n",
+ sc->name, cmd->tag, bcs->Tag,
+ sc->dev->devnum);
goto Bad_End;
}
__ub_state_stat(sc, cmd);
@@ -1282,8 +1244,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\n",
- sc->name, cmd->state);
+ "wrong command state %d on device %u\n",
+ sc->name, cmd->state, sc->dev->devnum);
goto Bad_End;
}
return;
@@ -1326,6 +1288,7 @@ 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;
@@ -1370,7 +1333,6 @@ 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;
@@ -1449,14 +1411,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\n",
- sc->name, cmd->tag);
+ "sense done for wrong command 0x%x on device %u\n",
+ sc->name, cmd->tag, sc->dev->devnum);
return;
}
if (cmd->state != UB_CMDST_SENSE) {
printk(KERN_WARNING "%s: "
- "sense done with bad cmd state %d\n",
- sc->name, cmd->state);
+ "sense done with bad cmd state %d on device %u\n",
+ sc->name, cmd->state, sc->dev->devnum);
return;
}
@@ -1467,32 +1429,68 @@ 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 < 0) {
+ usb_stor_clear_halt(us, us->recv_bulk_pipe);
+ usb_stor_clear_halt(us, us->send_bulk_pipe);
+ }
+
+ US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
+ result, us->iobuf[0]);
+
+ /* if we have a successful request, return the result */
+ if (result == 1)
+ return us->iobuf[0];
+
+ /* return the default -- no LUNs */
+ return 0;
+}
+#endif
+
/*
* This is called from a process context.
*/
-static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
+static void ub_revalidate(struct ub_dev *sc)
{
- lun->readonly = 0; /* XXX Query this from the device */
+ sc->readonly = 0; /* XXX Query this from the device */
- lun->capacity.nsec = 0;
- lun->capacity.bsize = 512;
- lun->capacity.bshift = 0;
+ sc->capacity.nsec = 0;
+ sc->capacity.bsize = 512;
+ sc->capacity.bshift = 0;
- if (ub_sync_tur(sc, lun) != 0)
+ if (ub_sync_tur(sc) != 0)
return; /* Not ready */
- lun->changed = 0;
+ sc->changed = 0;
- if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
+ if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
/*
* The retry here means something is wrong, either with the
* device, with the transport, or with our code.
* We keep this because sd.c has retries for capacity.
*/
- if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
- lun->capacity.nsec = 0;
- lun->capacity.bsize = 512;
- lun->capacity.bshift = 0;
+ if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+ sc->capacity.nsec = 0;
+ sc->capacity.bsize = 512;
+ sc->capacity.bshift = 0;
}
}
}
@@ -1505,15 +1503,12 @@ static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
static int ub_bd_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ub_lun *lun;
struct ub_dev *sc;
unsigned long flags;
int rc;
- if ((lun = disk->private_data) == NULL)
+ if ((sc = disk->private_data) == NULL)
return -ENXIO;
- sc = lun->udev;
-
spin_lock_irqsave(&ub_lock, flags);
if (atomic_read(&sc->poison)) {
spin_unlock_irqrestore(&ub_lock, flags);
@@ -1534,15 +1529,15 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
* The bottom line is, Al Viro says that we should not allow
* bdev->bd_invalidated to be set when doing add_disk no matter what.
*/
- if (lun->first_open) {
- lun->first_open = 0;
- if (lun->changed) {
+ if (sc->first_open) {
+ if (sc->changed) {
+ sc->first_open = 0;
rc = -ENOMEDIUM;
goto err_open;
}
}
- if (lun->removable || lun->readonly)
+ if (sc->removable || sc->readonly)
check_disk_change(inode->i_bdev);
/*
@@ -1550,12 +1545,12 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
* under some pretty murky conditions (a failure of READ CAPACITY).
* We may need it one day.
*/
- if (lun->removable && lun->changed && !(filp->f_flags & O_NDELAY)) {
+ if (sc->removable && sc->changed && !(filp->f_flags & O_NDELAY)) {
rc = -ENOMEDIUM;
goto err_open;
}
- if (lun->readonly && (filp->f_mode & FMODE_WRITE)) {
+ if (sc->readonly && (filp->f_mode & FMODE_WRITE)) {
rc = -EROFS;
goto err_open;
}
@@ -1572,8 +1567,7 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
static int ub_bd_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ub_lun *lun = disk->private_data;
- struct ub_dev *sc = lun->udev;
+ struct ub_dev *sc = disk->private_data;
ub_put(sc);
return 0;
@@ -1603,14 +1597,20 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
*/
static int ub_bd_revalidate(struct gendisk *disk)
{
- struct ub_lun *lun = disk->private_data;
-
- ub_revalidate(lun->udev, lun);
+ struct ub_dev *sc = disk->private_data;
+
+ ub_revalidate(sc);
+ /* This is pretty much a long term P3 */
+ if (!atomic_read(&sc->poison)) { /* Cover sc->dev */
+ printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
+ sc->name, sc->dev->devnum,
+ sc->capacity.nsec, sc->capacity.bsize);
+ }
/* XXX Support sector size switching like in sr.c */
- blk_queue_hardsect_size(disk->queue, lun->capacity.bsize);
- set_capacity(disk, lun->capacity.nsec);
- // set_disk_ro(sdkp->disk, lun->readonly);
+ blk_queue_hardsect_size(disk->queue, sc->capacity.bsize);
+ set_capacity(disk, sc->capacity.nsec);
+ // set_disk_ro(sdkp->disk, sc->readonly);
return 0;
}
@@ -1626,9 +1626,9 @@ static int ub_bd_revalidate(struct gendisk *disk)
*/
static int ub_bd_media_changed(struct gendisk *disk)
{
- struct ub_lun *lun = disk->private_data;
+ struct ub_dev *sc = disk->private_data;
- if (!lun->removable)
+ if (!sc->removable)
return 0;
/*
@@ -1640,12 +1640,12 @@ static int ub_bd_media_changed(struct gendisk *disk)
* will fail, then block layer discards the data. Since we never
* spin drives up, such devices simply cannot be used with ub anyway.
*/
- if (ub_sync_tur(lun->udev, lun) != 0) {
- lun->changed = 1;
+ if (ub_sync_tur(sc) != 0) {
+ sc->changed = 1;
return 1;
}
- return lun->changed;
+ return sc->changed;
}
static struct block_device_operations ub_bd_fops = {
@@ -1669,7 +1669,7 @@ static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
/*
* Test if the device has a check condition on it, synchronously.
*/
-static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
+static int ub_sync_tur(struct ub_dev *sc)
{
struct ub_scsi_cmd *cmd;
enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
@@ -1688,7 +1688,6 @@ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
cmd->cdb_len = 6;
cmd->dir = UB_DIR_NONE;
cmd->state = UB_CMDST_INIT;
- cmd->lun = lun; /* This may be NULL, but that's ok */
cmd->done = ub_probe_done;
cmd->back = &compl;
@@ -1719,8 +1718,7 @@ static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
/*
* Read the SCSI capacity synchronously (for probing).
*/
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
- struct ub_capacity *ret)
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
{
struct ub_scsi_cmd *cmd;
char *p;
@@ -1745,7 +1743,6 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
cmd->state = UB_CMDST_INIT;
cmd->data = p;
cmd->len = 8;
- cmd->lun = lun;
cmd->done = ub_probe_done;
cmd->back = &compl;
@@ -1814,90 +1811,6 @@ static void ub_probe_timeout(unsigned long arg)
complete(cop);
}
-/*
- * Get number of LUNs by the way of Bulk GetMaxLUN command.
- */
-static int ub_sync_getmaxlun(struct ub_dev *sc)
-{
- int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
- unsigned char *p;
- enum { ALLOC_SIZE = 1 };
- struct usb_ctrlrequest *cr;
- struct completion compl;
- struct timer_list timer;
- int nluns;
- int rc;
-
- init_completion(&compl);
-
- rc = -ENOMEM;
- if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
- goto err_alloc;
- *p = 55;
-
- cr = &sc->work_cr;
- cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- cr->bRequest = US_BULK_GET_MAX_LUN;
- cr->wValue = cpu_to_le16(0);
- cr->wIndex = cpu_to_le16(ifnum);
- cr->wLength = cpu_to_le16(1);
-
- usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
- (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
- sc->work_urb.transfer_flags = 0;
- sc->work_urb.actual_length = 0;
- sc->work_urb.error_count = 0;
- sc->work_urb.status = 0;
-
- if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
- if (rc == -EPIPE) {
- printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
- sc->name); /* P3 */
- } else {
- printk(KERN_WARNING
- "%s: Unable to submit GetMaxLUN (%d)\n",
- sc->name, rc);
- }
- goto err_submit;
- }
-
- init_timer(&timer);
- timer.function = ub_probe_timeout;
- timer.data = (unsigned long) &compl;
- timer.expires = jiffies + UB_CTRL_TIMEOUT;
- add_timer(&timer);
-
- wait_for_completion(&compl);
-
- del_timer_sync(&timer);
- usb_kill_urb(&sc->work_urb);
-
- if (sc->work_urb.actual_length != 1) {
- printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
- sc->work_urb.actual_length); /* P3 */
- nluns = 0;
- } else {
- if ((nluns = *p) == 55) {
- nluns = 0;
- } else {
- /* GetMaxLUN returns the maximum LUN number */
- nluns += 1;
- if (nluns > UB_MAX_LUNS)
- nluns = UB_MAX_LUNS;
- }
- printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name,
- *p, nluns); /* P3 */
- }
-
- kfree(p);
- return nluns;
-
-err_submit:
- kfree(p);
-err_alloc:
- return rc;
-}
-
/*
* Clear initial stalls.
*/
@@ -1984,8 +1897,8 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
}
if (ep_in == NULL || ep_out == NULL) {
- printk(KERN_NOTICE "%s: failed endpoint check\n",
- sc->name);
+ printk(KERN_NOTICE "%s: device %u failed endpoint check\n",
+ sc->name, sc->dev->devnum);
return -EIO;
}
@@ -2008,7 +1921,8 @@ static int ub_probe(struct usb_interface *intf,
const struct usb_device_id *dev_id)
{
struct ub_dev *sc;
- int nluns;
+ request_queue_t *q;
+ struct gendisk *disk;
int rc;
int i;
@@ -2017,7 +1931,6 @@ static int ub_probe(struct usb_interface *intf,
goto err_core;
memset(sc, 0, sizeof(struct ub_dev));
spin_lock_init(&sc->lock);
- INIT_LIST_HEAD(&sc->luns);
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
@@ -2029,16 +1942,19 @@ static int ub_probe(struct usb_interface *intf,
ub_init_completion(&sc->work_done);
sc->work_done.done = 1; /* A little yuk, but oh well... */
+ rc = -ENOSR;
+ if ((sc->id = ub_id_get()) == -1)
+ goto err_id;
+ snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');
+
sc->dev = interface_to_usbdev(intf);
sc->intf = intf;
// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
usb_set_intfdata(intf, sc);
usb_get_dev(sc->dev);
// usb_get_intf(sc->intf); /* Do we need this? */
- snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
- sc->dev->bus->busnum, sc->dev->devnum);
-
/* XXX Verify that we can handle the device (from descriptors) */
ub_get_pipes(sc, sc->dev, intf);
@@ -2076,88 +1992,35 @@ static int ub_probe(struct usb_interface *intf,
* In any case it's not our business how revaliadation is implemented.
*/
for (i = 0; i < 3; i++) { /* Retries for benh's key */
- if ((rc = ub_sync_tur(sc, NULL)) <= 0) break;
+ if ((rc = ub_sync_tur(sc)) <= 0) break;
if (rc != 0x6) break;
msleep(10);
}
- nluns = 1;
- for (i = 0; i < 3; i++) {
- if ((rc = ub_sync_getmaxlun(sc)) < 0) {
- /*
- * Some devices (i.e. Iomega Zip100) need this --
- * apparently the bulk pipes get STALLed when the
- * GetMaxLUN request is processed.
- * XXX I have a ZIP-100, verify it does this.
- */
- if (rc == -EPIPE) {
- ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
- ub_probe_clear_stall(sc, sc->send_bulk_pipe);
- }
- break;
- }
- if (rc != 0) {
- nluns = rc;
- break;
- }
- mdelay(100);
- }
+ sc->removable = 1; /* XXX Query this from the device */
+ sc->changed = 1; /* ub_revalidate clears only */
+ sc->first_open = 1;
- for (i = 0; i < nluns; i++) {
- ub_probe_lun(sc, i);
- }
- return 0;
-
- /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
-err_diag:
- usb_set_intfdata(intf, NULL);
- // usb_put_intf(sc->intf);
- usb_put_dev(sc->dev);
- kfree(sc);
-err_core:
- return rc;
-}
-
-static int ub_probe_lun(struct ub_dev *sc, int lnum)
-{
- struct ub_lun *lun;
- request_queue_t *q;
- struct gendisk *disk;
- int rc;
-
- rc = -ENOMEM;
- if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL)
- goto err_alloc;
- memset(lun, 0, sizeof(struct ub_lun));
- lun->num = lnum;
-
- rc = -ENOSR;
- if ((lun->id = ub_id_get()) == -1)
- goto err_id;
-
- lun->udev = sc;
- list_add(&lun->link, &sc->luns);
-
- snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)",
- lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num);
-
- lun->removable = 1; /* XXX Query this from the device */
- lun->changed = 1; /* ub_revalidate clears only */
- lun->first_open = 1;
- ub_revalidate(sc, lun);
+ ub_revalidate(sc);
+ /* This is pretty much a long term P3 */
+ printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
+ sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+ /*
+ * Just one disk per sc currently, but maybe more.
+ */
rc = -ENOMEM;
if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
goto err_diskalloc;
- lun->disk = disk;
- sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
- sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
+ sc->disk = disk;
+ sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');
+ sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');
disk->major = UB_MAJOR;
- disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
+ disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;
disk->fops = &ub_bd_fops;
- disk->private_data = lun;
- disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */
+ disk->private_data = sc;
+ disk->driverfs_dev = &intf->dev;
rc = -ENOMEM;
if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
@@ -2165,17 +2028,28 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
disk->queue = q;
- blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
+ // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);
blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
- blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */
+ // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
blk_queue_max_sectors(q, UB_MAX_SECTORS);
- blk_queue_hardsect_size(q, lun->capacity.bsize);
+ blk_queue_hardsect_size(q, sc->capacity.bsize);
+
+ /*
+ * This is a serious infraction, caused by a deficiency in the
+ * USB sg interface (usb_sg_wait()). We plan to remove this once
+ * we get mileage on the driver and can justify a change to USB API.
+ * See blk_queue_bounce_limit() to understand this part.
+ *
+ * XXX And I still need to be aware of the DMA mask in the HC.
+ */
+ q->bounce_pfn = blk_max_low_pfn;
+ q->bounce_gfp = GFP_NOIO;
- q->queuedata = lun;
+ q->queuedata = sc;
- set_capacity(disk, lun->capacity.nsec);
- if (lun->removable)
+ set_capacity(disk, sc->capacity.nsec);
+ if (sc->removable)
disk->flags |= GENHD_FL_REMOVABLE;
add_disk(disk);
@@ -2185,20 +2059,22 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
err_blkqinit:
put_disk(disk);
err_diskalloc:
- list_del(&lun->link);
- ub_id_put(lun->id);
+ device_remove_file(&sc->intf->dev, &dev_attr_diag);
+err_diag:
+ usb_set_intfdata(intf, NULL);
+ // usb_put_intf(sc->intf);
+ usb_put_dev(sc->dev);
+ ub_id_put(sc->id);
err_id:
- kfree(lun);
-err_alloc:
+ kfree(sc);
+err_core:
return rc;
}
static void ub_disconnect(struct usb_interface *intf)
{
struct ub_dev *sc = usb_get_intfdata(intf);
- struct list_head *p;
- struct ub_lun *lun;
- struct gendisk *disk;
+ struct gendisk *disk = sc->disk;
unsigned long flags;
/*
@@ -2248,18 +2124,14 @@ static void ub_disconnect(struct usb_interface *intf)
/*
* Unregister the upper layer.
*/
- list_for_each (p, &sc->luns) {
- lun = list_entry(p, struct ub_lun, link);
- disk = lun->disk;
- if (disk->flags & GENHD_FL_UP)
- del_gendisk(disk);
- /*
- * I wish I could do:
- * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
- * As it is, we rely on our internal poisoning and let
- * the upper levels to spin furiously failing all the I/O.
- */
- }
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ /*
+ * I wish I could do:
+ * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+ * As it is, we rely on our internal poisoning and let
+ * the upper levels to spin furiously failing all the I/O.
+ */
/*
* Taking a lock on a structure which is about to be freed
@@ -2310,8 +2182,8 @@ static int __init ub_init(void)
{
int rc;
- /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n",
- sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun));
+ /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",
+ sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));
if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
goto err_regblkdev;
diff --git a/trunk/drivers/cdrom/viocd.c b/trunk/drivers/cdrom/viocd.c
index 38dd9ffbe8bc..fcca26c89bbc 100644
--- a/trunk/drivers/cdrom/viocd.c
+++ b/trunk/drivers/cdrom/viocd.c
@@ -488,20 +488,6 @@ static int viocd_packet(struct cdrom_device_info *cdi,
& (CDC_DVD_RAM | CDC_RAM)) != 0;
}
break;
- case GPCMD_GET_CONFIGURATION:
- if (cgc->cmd[3] == CDF_RWRT) {
- struct rwrt_feature_desc *rfd = (struct rwrt_feature_desc *)(cgc->buffer + sizeof(struct feature_header));
-
- if ((buflen >=
- (sizeof(struct feature_header) + sizeof(*rfd))) &&
- (cdi->ops->capability & ~cdi->mask
- & (CDC_DVD_RAM | CDC_RAM))) {
- rfd->feature_code = cpu_to_be16(CDF_RWRT);
- rfd->curr = 1;
- ret = 0;
- }
- }
- break;
default:
if (cgc->sense) {
/* indicate Unknown code */
diff --git a/trunk/drivers/char/ipmi/ipmi_devintf.c b/trunk/drivers/char/ipmi/ipmi_devintf.c
index 6dc765dc5413..49d67f5384a2 100644
--- a/trunk/drivers/char/ipmi/ipmi_devintf.c
+++ b/trunk/drivers/char/ipmi/ipmi_devintf.c
@@ -44,7 +44,6 @@
#include
#include
#include
-#include
#define IPMI_DEVINTF_VERSION "v33"
@@ -520,21 +519,15 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
" interface. Other values will set the major device number"
" to that value.");
-static struct class_simple *ipmi_class;
-
static void ipmi_new_smi(int if_num)
{
- dev_t dev = MKDEV(ipmi_major, if_num);
-
- devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
+ devfs_mk_cdev(MKDEV(ipmi_major, if_num),
+ S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
-
- class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num);
}
static void ipmi_smi_gone(int if_num)
{
- class_simple_device_remove(MKDEV(ipmi_major, if_num));
devfs_remove("ipmidev/%d", if_num);
}
@@ -555,15 +548,8 @@ static __init int init_ipmi_devintf(void)
printk(KERN_INFO "ipmi device interface version "
IPMI_DEVINTF_VERSION "\n");
- ipmi_class = class_simple_create(THIS_MODULE, "ipmi");
- if (IS_ERR(ipmi_class)) {
- printk(KERN_ERR "ipmi: can't register device class\n");
- return PTR_ERR(ipmi_class);
- }
-
rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
if (rv < 0) {
- class_simple_destroy(ipmi_class);
printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
return rv;
}
@@ -577,7 +563,6 @@ static __init int init_ipmi_devintf(void)
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
unregister_chrdev(ipmi_major, DEVICE_NAME);
- class_simple_destroy(ipmi_class);
printk(KERN_WARNING "ipmi: can't register smi watcher\n");
return rv;
}
@@ -588,7 +573,6 @@ module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
{
- class_simple_destroy(ipmi_class);
ipmi_smi_watcher_unregister(&smi_watcher);
devfs_remove(DEVICE_NAME);
unregister_chrdev(ipmi_major, DEVICE_NAME);
diff --git a/trunk/drivers/char/raw.c b/trunk/drivers/char/raw.c
index ca5f42bcaad9..a2e33ec79615 100644
--- a/trunk/drivers/char/raw.c
+++ b/trunk/drivers/char/raw.c
@@ -122,7 +122,7 @@ raw_ioctl(struct inode *inode, struct file *filp,
{
struct block_device *bdev = filp->private_data;
- return blkdev_ioctl(bdev->bd_inode, NULL, command, arg);
+ return ioctl_by_bdev(bdev, command, arg);
}
static void bind_device(struct raw_config_request *rq)
diff --git a/trunk/drivers/char/watchdog/i8xx_tco.c b/trunk/drivers/char/watchdog/i8xx_tco.c
index b14d642439ed..c337978dc966 100644
--- a/trunk/drivers/char/watchdog/i8xx_tco.c
+++ b/trunk/drivers/char/watchdog/i8xx_tco.c
@@ -382,7 +382,6 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl);
diff --git a/trunk/drivers/cpufreq/Kconfig b/trunk/drivers/cpufreq/Kconfig
index 60c9be99c6d9..95882bb1950e 100644
--- a/trunk/drivers/cpufreq/Kconfig
+++ b/trunk/drivers/cpufreq/Kconfig
@@ -46,10 +46,6 @@ config CPU_FREQ_STAT_DETAILS
This will show detail CPU frequency translation table in sysfs file
system
-# Note that it is not currently possible to set the other governors (such as ondemand)
-# as the default, since if they fail to initialise, cpufreq will be
-# left in an undefined state.
-
choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
@@ -119,24 +115,4 @@ config CPU_FREQ_GOV_ONDEMAND
If in doubt, say N.
-config CPU_FREQ_GOV_CONSERVATIVE
- tristate "'conservative' cpufreq governor"
- depends on CPU_FREQ
- help
- 'conservative' - this driver is rather similar to the 'ondemand'
- governor both in its source code and its purpose, the difference is
- its optimisation for better suitability in a battery powered
- environment. The frequency is gracefully increased and decreased
- rather than jumping to 100% when speed is required.
-
- If you have a desktop machine then you should really be considering
- the 'ondemand' governor instead, however if you are using a laptop,
- PDA or even an AMD64 based computer (due to the unacceptable
- step-by-step latency issues between the minimum and maximum frequency
- transitions in the CPU) you will probably want to use this governor.
-
- For details, take a look at linux/Documentation/cpu-freq.
-
- If in doubt, say N.
-
endif # CPU_FREQ
diff --git a/trunk/drivers/cpufreq/Makefile b/trunk/drivers/cpufreq/Makefile
index 71fc3b4173f1..67b16e5a41a7 100644
--- a/trunk/drivers/cpufreq/Makefile
+++ b/trunk/drivers/cpufreq/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
-obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c
index 03b5fb2ddcf4..8e561313d094 100644
--- a/trunk/drivers/cpufreq/cpufreq.c
+++ b/trunk/drivers/cpufreq/cpufreq.c
@@ -258,7 +258,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
(likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
(unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
{
- dprintk(KERN_WARNING "Warning: CPU frequency is %u, "
+ printk(KERN_WARNING "Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
}
@@ -814,7 +814,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
{
struct cpufreq_freqs freqs;
- dprintk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
+ printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
"core thinks of %u, is %u kHz.\n", old_freq, new_freq);
freqs.cpu = cpu;
@@ -923,7 +923,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, u32 state)
struct cpufreq_freqs freqs;
if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
- dprintk(KERN_DEBUG "Warning: CPU frequency is %u, "
+ printk(KERN_DEBUG "Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.\n",
cur_freq, cpu_policy->cur);
@@ -1004,7 +1004,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
struct cpufreq_freqs freqs;
if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
- dprintk(KERN_WARNING "Warning: CPU frequency"
+ printk(KERN_WARNING "Warning: CPU frequency"
"is %u, cpufreq assumed %u kHz.\n",
cur_freq, cpu_policy->cur);
diff --git a/trunk/drivers/cpufreq/cpufreq_conservative.c b/trunk/drivers/cpufreq/cpufreq_conservative.c
deleted file mode 100644
index e1df376e709e..000000000000
--- a/trunk/drivers/cpufreq/cpufreq_conservative.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * drivers/cpufreq/cpufreq_conservative.c
- *
- * Copyright (C) 2001 Russell King
- * (C) 2003 Venkatesh Pallipadi .
- * Jun Nakajima
- * (C) 2004 Alexander Clouter
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
-
-#define DEF_FREQUENCY_UP_THRESHOLD (80)
-#define MIN_FREQUENCY_UP_THRESHOLD (0)
-#define MAX_FREQUENCY_UP_THRESHOLD (100)
-
-#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
-#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
-#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
-
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-static unsigned int def_sampling_rate;
-#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
-#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000)
-#define DEF_SAMPLING_DOWN_FACTOR (5)
-#define TRANSITION_LATENCY_LIMIT (10 * 1000)
-
-static void do_dbs_timer(void *data);
-
-struct cpu_dbs_info_s {
- struct cpufreq_policy *cur_policy;
- unsigned int prev_cpu_idle_up;
- unsigned int prev_cpu_idle_down;
- unsigned int enable;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
-
-static unsigned int dbs_enable; /* number of CPUs using this policy */
-
-static DECLARE_MUTEX (dbs_sem);
-static DECLARE_WORK (dbs_work, do_dbs_timer, NULL);
-
-struct dbs_tuners {
- unsigned int sampling_rate;
- unsigned int sampling_down_factor;
- unsigned int up_threshold;
- unsigned int down_threshold;
- unsigned int ignore_nice;
- unsigned int freq_step;
-};
-
-static struct dbs_tuners dbs_tuners_ins = {
- .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
- .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
- .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
-};
-
-static inline unsigned int get_cpu_idle_time(unsigned int cpu)
-{
- return kstat_cpu(cpu).cpustat.idle +
- kstat_cpu(cpu).cpustat.iowait +
- ( !dbs_tuners_ins.ignore_nice ?
- kstat_cpu(cpu).cpustat.nice :
- 0);
-}
-
-/************************** sysfs interface ************************/
-static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
-{
- return sprintf (buf, "%u\n", MAX_SAMPLING_RATE);
-}
-
-static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
-{
- return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
-}
-
-#define define_one_ro(_name) \
-static struct freq_attr _name = \
-__ATTR(_name, 0444, show_##_name, NULL)
-
-define_one_ro(sampling_rate_max);
-define_one_ro(sampling_rate_min);
-
-/* cpufreq_conservative Governor Tunables */
-#define show_one(file_name, object) \
-static ssize_t show_##file_name \
-(struct cpufreq_policy *unused, char *buf) \
-{ \
- return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
-}
-show_one(sampling_rate, sampling_rate);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(up_threshold, up_threshold);
-show_one(down_threshold, down_threshold);
-show_one(ignore_nice, ignore_nice);
-show_one(freq_step, freq_step);
-
-static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf (buf, "%u", &input);
- if (ret != 1 )
- return -EINVAL;
-
- down(&dbs_sem);
- dbs_tuners_ins.sampling_down_factor = input;
- up(&dbs_sem);
-
- return count;
-}
-
-static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf (buf, "%u", &input);
-
- down(&dbs_sem);
- if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
- up(&dbs_sem);
- return -EINVAL;
- }
-
- dbs_tuners_ins.sampling_rate = input;
- up(&dbs_sem);
-
- return count;
-}
-
-static ssize_t store_up_threshold(struct cpufreq_policy *unused,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf (buf, "%u", &input);
-
- down(&dbs_sem);
- if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
- input < MIN_FREQUENCY_UP_THRESHOLD ||
- input <= dbs_tuners_ins.down_threshold) {
- up(&dbs_sem);
- return -EINVAL;
- }
-
- dbs_tuners_ins.up_threshold = input;
- up(&dbs_sem);
-
- return count;
-}
-
-static ssize_t store_down_threshold(struct cpufreq_policy *unused,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf (buf, "%u", &input);
-
- down(&dbs_sem);
- if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
- input < MIN_FREQUENCY_DOWN_THRESHOLD ||
- input >= dbs_tuners_ins.up_threshold) {
- up(&dbs_sem);
- return -EINVAL;
- }
-
- dbs_tuners_ins.down_threshold = input;
- up(&dbs_sem);
-
- return count;
-}
-
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
-
- unsigned int j;
-
- ret = sscanf (buf, "%u", &input);
- if ( ret != 1 )
- return -EINVAL;
-
- if ( input > 1 )
- input = 1;
-
- down(&dbs_sem);
- if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
- up(&dbs_sem);
- return count;
- }
- dbs_tuners_ins.ignore_nice = input;
-
- /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
- for_each_online_cpu(j) {
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
- j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
- }
- up(&dbs_sem);
-
- return count;
-}
-
-static ssize_t store_freq_step(struct cpufreq_policy *policy,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
-
- ret = sscanf (buf, "%u", &input);
-
- if ( ret != 1 )
- return -EINVAL;
-
- if ( input > 100 )
- input = 100;
-
- /* no need to test here if freq_step is zero as the user might actually
- * want this, they would be crazy though :) */
- down(&dbs_sem);
- dbs_tuners_ins.freq_step = input;
- up(&dbs_sem);
-
- return count;
-}
-
-#define define_one_rw(_name) \
-static struct freq_attr _name = \
-__ATTR(_name, 0644, show_##_name, store_##_name)
-
-define_one_rw(sampling_rate);
-define_one_rw(sampling_down_factor);
-define_one_rw(up_threshold);
-define_one_rw(down_threshold);
-define_one_rw(ignore_nice);
-define_one_rw(freq_step);
-
-static struct attribute * dbs_attributes[] = {
- &sampling_rate_max.attr,
- &sampling_rate_min.attr,
- &sampling_rate.attr,
- &sampling_down_factor.attr,
- &up_threshold.attr,
- &down_threshold.attr,
- &ignore_nice.attr,
- &freq_step.attr,
- NULL
-};
-
-static struct attribute_group dbs_attr_group = {
- .attrs = dbs_attributes,
- .name = "conservative",
-};
-
-/************************** sysfs end ************************/
-
-static void dbs_check_cpu(int cpu)
-{
- unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
- unsigned int freq_step;
- unsigned int freq_down_sampling_rate;
- static int down_skip[NR_CPUS];
- static int requested_freq[NR_CPUS];
- static unsigned short init_flag = 0;
- struct cpu_dbs_info_s *this_dbs_info;
- struct cpu_dbs_info_s *dbs_info;
-
- struct cpufreq_policy *policy;
- unsigned int j;
-
- this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
- if (!this_dbs_info->enable)
- return;
-
- policy = this_dbs_info->cur_policy;
-
- if ( init_flag == 0 ) {
- for ( /* NULL */; init_flag < NR_CPUS; init_flag++ ) {
- dbs_info = &per_cpu(cpu_dbs_info, init_flag);
- requested_freq[cpu] = dbs_info->cur_policy->cur;
- }
- init_flag = 1;
- }
-
- /*
- * The default safe range is 20% to 80%
- * Every sampling_rate, we check
- * - If current idle time is less than 20%, then we try to
- * increase frequency
- * Every sampling_rate*sampling_down_factor, we check
- * - If current idle time is more than 80%, then we try to
- * decrease frequency
- *
- * Any frequency increase takes it to the maximum frequency.
- * Frequency reduction happens at minimum steps of
- * 5% (default) of max_frequency
- */
-
- /* Check for frequency increase */
-
- idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
- struct cpu_dbs_info_s *j_dbs_info;
-
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- /* Check for frequency increase */
- total_idle_ticks = get_cpu_idle_time(j);
- tmp_idle_ticks = total_idle_ticks -
- j_dbs_info->prev_cpu_idle_up;
- j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
-
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
- }
-
- /* Scale idle ticks by 100 and compare with up and down ticks */
- idle_ticks *= 100;
- up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
- if (idle_ticks < up_idle_ticks) {
- down_skip[cpu] = 0;
- for_each_cpu_mask(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
-
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_down =
- j_dbs_info->prev_cpu_idle_up;
- }
- /* if we are already at full speed then break out early */
- if (requested_freq[cpu] == policy->max)
- return;
-
- freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
- /* max freq cannot be less than 100. But who knows.... */
- if (unlikely(freq_step == 0))
- freq_step = 5;
-
- requested_freq[cpu] += freq_step;
- if (requested_freq[cpu] > policy->max)
- requested_freq[cpu] = policy->max;
-
- __cpufreq_driver_target(policy, requested_freq[cpu],
- CPUFREQ_RELATION_H);
- return;
- }
-
- /* Check for frequency decrease */
- down_skip[cpu]++;
- if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
- return;
-
- idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
- struct cpu_dbs_info_s *j_dbs_info;
-
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- total_idle_ticks = j_dbs_info->prev_cpu_idle_up;
- tmp_idle_ticks = total_idle_ticks -
- j_dbs_info->prev_cpu_idle_down;
- j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
-
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
- }
-
- /* Scale idle ticks by 100 and compare with up and down ticks */
- idle_ticks *= 100;
- down_skip[cpu] = 0;
-
- freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
- dbs_tuners_ins.sampling_down_factor;
- down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
- usecs_to_jiffies(freq_down_sampling_rate);
-
- if (idle_ticks > down_idle_ticks) {
- /* if we are already at the lowest speed then break out early
- * or if we 'cannot' reduce the speed as the user might want
- * freq_step to be zero */
- if (requested_freq[cpu] == policy->min
- || dbs_tuners_ins.freq_step == 0)
- return;
-
- freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
- /* max freq cannot be less than 100. But who knows.... */
- if (unlikely(freq_step == 0))
- freq_step = 5;
-
- requested_freq[cpu] -= freq_step;
- if (requested_freq[cpu] < policy->min)
- requested_freq[cpu] = policy->min;
-
- __cpufreq_driver_target(policy,
- requested_freq[cpu],
- CPUFREQ_RELATION_H);
- return;
- }
-}
-
-static void do_dbs_timer(void *data)
-{
- int i;
- down(&dbs_sem);
- for_each_online_cpu(i)
- dbs_check_cpu(i);
- schedule_delayed_work(&dbs_work,
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
- up(&dbs_sem);
-}
-
-static inline void dbs_timer_init(void)
-{
- INIT_WORK(&dbs_work, do_dbs_timer, NULL);
- schedule_delayed_work(&dbs_work,
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
- return;
-}
-
-static inline void dbs_timer_exit(void)
-{
- cancel_delayed_work(&dbs_work);
- return;
-}
-
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
- unsigned int event)
-{
- unsigned int cpu = policy->cpu;
- struct cpu_dbs_info_s *this_dbs_info;
- unsigned int j;
-
- this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
-
- switch (event) {
- case CPUFREQ_GOV_START:
- if ((!cpu_online(cpu)) ||
- (!policy->cur))
- return -EINVAL;
-
- if (policy->cpuinfo.transition_latency >
- (TRANSITION_LATENCY_LIMIT * 1000))
- return -EINVAL;
- if (this_dbs_info->enable) /* Already enabled */
- break;
-
- down(&dbs_sem);
- for_each_cpu_mask(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->cur_policy = policy;
-
- j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
- j_dbs_info->prev_cpu_idle_down
- = j_dbs_info->prev_cpu_idle_up;
- }
- this_dbs_info->enable = 1;
- sysfs_create_group(&policy->kobj, &dbs_attr_group);
- dbs_enable++;
- /*
- * Start the timerschedule work, when this governor
- * is used for first time
- */
- if (dbs_enable == 1) {
- unsigned int latency;
- /* policy latency is in nS. Convert it to uS first */
-
- latency = policy->cpuinfo.transition_latency;
- if (latency < 1000)
- latency = 1000;
-
- def_sampling_rate = (latency / 1000) *
- DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
- dbs_tuners_ins.sampling_rate = def_sampling_rate;
- dbs_tuners_ins.ignore_nice = 0;
- dbs_tuners_ins.freq_step = 5;
-
- dbs_timer_init();
- }
-
- up(&dbs_sem);
- break;
-
- case CPUFREQ_GOV_STOP:
- down(&dbs_sem);
- this_dbs_info->enable = 0;
- sysfs_remove_group(&policy->kobj, &dbs_attr_group);
- dbs_enable--;
- /*
- * Stop the timerschedule work, when this governor
- * is used for first time
- */
- if (dbs_enable == 0)
- dbs_timer_exit();
-
- up(&dbs_sem);
-
- break;
-
- case CPUFREQ_GOV_LIMITS:
- down(&dbs_sem);
- if (policy->max < this_dbs_info->cur_policy->cur)
- __cpufreq_driver_target(
- this_dbs_info->cur_policy,
- policy->max, CPUFREQ_RELATION_H);
- else if (policy->min > this_dbs_info->cur_policy->cur)
- __cpufreq_driver_target(
- this_dbs_info->cur_policy,
- policy->min, CPUFREQ_RELATION_L);
- up(&dbs_sem);
- break;
- }
- return 0;
-}
-
-static struct cpufreq_governor cpufreq_gov_dbs = {
- .name = "conservative",
- .governor = cpufreq_governor_dbs,
- .owner = THIS_MODULE,
-};
-
-static int __init cpufreq_gov_dbs_init(void)
-{
- return cpufreq_register_governor(&cpufreq_gov_dbs);
-}
-
-static void __exit cpufreq_gov_dbs_exit(void)
-{
- /* Make sure that the scheduled work is indeed not running */
- flush_scheduled_work();
-
- cpufreq_unregister_governor(&cpufreq_gov_dbs);
-}
-
-
-MODULE_AUTHOR ("Alexander Clouter ");
-MODULE_DESCRIPTION ("'cpufreq_conservative' - A dynamic cpufreq governor for "
- "Low Latency Frequency Transition capable processors "
- "optimised for use in a battery environment");
-MODULE_LICENSE ("GPL");
-
-module_init(cpufreq_gov_dbs_init);
-module_exit(cpufreq_gov_dbs_exit);
diff --git a/trunk/drivers/cpufreq/cpufreq_ondemand.c b/trunk/drivers/cpufreq/cpufreq_ondemand.c
index c1fc9c62bb51..8d83a21c6477 100644
--- a/trunk/drivers/cpufreq/cpufreq_ondemand.c
+++ b/trunk/drivers/cpufreq/cpufreq_ondemand.c
@@ -34,9 +34,13 @@
*/
#define DEF_FREQUENCY_UP_THRESHOLD (80)
-#define MIN_FREQUENCY_UP_THRESHOLD (11)
+#define MIN_FREQUENCY_UP_THRESHOLD (0)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
+#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
+#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
+#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
+
/*
* The polling frequency of this governor depends on the capability of
* the processor. Default polling frequency is 1000 times the transition
@@ -51,9 +55,9 @@ static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
-#define DEF_SAMPLING_DOWN_FACTOR (1)
-#define MAX_SAMPLING_DOWN_FACTOR (10)
+#define DEF_SAMPLING_DOWN_FACTOR (10)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
+#define sampling_rate_in_HZ(x) (((x * HZ) < (1000 * 1000))?1:((x * HZ) / (1000 * 1000)))
static void do_dbs_timer(void *data);
@@ -74,23 +78,15 @@ struct dbs_tuners {
unsigned int sampling_rate;
unsigned int sampling_down_factor;
unsigned int up_threshold;
- unsigned int ignore_nice;
+ unsigned int down_threshold;
};
static struct dbs_tuners dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+ .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
};
-static inline unsigned int get_cpu_idle_time(unsigned int cpu)
-{
- return kstat_cpu(cpu).cpustat.idle +
- kstat_cpu(cpu).cpustat.iowait +
- ( !dbs_tuners_ins.ignore_nice ?
- kstat_cpu(cpu).cpustat.nice :
- 0);
-}
-
/************************** sysfs interface ************************/
static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
{
@@ -119,7 +115,7 @@ static ssize_t show_##file_name \
show_one(sampling_rate, sampling_rate);
show_one(sampling_down_factor, sampling_down_factor);
show_one(up_threshold, up_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(down_threshold, down_threshold);
static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
const char *buf, size_t count)
@@ -130,9 +126,6 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
if (ret != 1 )
return -EINVAL;
- if (input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
- return -EINVAL;
-
down(&dbs_sem);
dbs_tuners_ins.sampling_down_factor = input;
up(&dbs_sem);
@@ -168,7 +161,8 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
down(&dbs_sem);
if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
- input < MIN_FREQUENCY_UP_THRESHOLD) {
+ input < MIN_FREQUENCY_UP_THRESHOLD ||
+ input <= dbs_tuners_ins.down_threshold) {
up(&dbs_sem);
return -EINVAL;
}
@@ -179,35 +173,22 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_down_threshold(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
int ret;
-
- unsigned int j;
-
ret = sscanf (buf, "%u", &input);
- if ( ret != 1 )
- return -EINVAL;
- if ( input > 1 )
- input = 1;
-
down(&dbs_sem);
- if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
+ if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
+ input < MIN_FREQUENCY_DOWN_THRESHOLD ||
+ input >= dbs_tuners_ins.up_threshold) {
up(&dbs_sem);
- return count;
+ return -EINVAL;
}
- dbs_tuners_ins.ignore_nice = input;
- /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
- for_each_online_cpu(j) {
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
- j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
- }
+ dbs_tuners_ins.down_threshold = input;
up(&dbs_sem);
return count;
@@ -220,7 +201,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
define_one_rw(sampling_rate);
define_one_rw(sampling_down_factor);
define_one_rw(up_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(down_threshold);
static struct attribute * dbs_attributes[] = {
&sampling_rate_max.attr,
@@ -228,7 +209,7 @@ static struct attribute * dbs_attributes[] = {
&sampling_rate.attr,
&sampling_down_factor.attr,
&up_threshold.attr,
- &ignore_nice.attr,
+ &down_threshold.attr,
NULL
};
@@ -241,8 +222,9 @@ static struct attribute_group dbs_attr_group = {
static void dbs_check_cpu(int cpu)
{
- unsigned int idle_ticks, up_idle_ticks, total_ticks;
- unsigned int freq_next;
+ unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
+ unsigned int total_idle_ticks;
+ unsigned int freq_down_step;
unsigned int freq_down_sampling_rate;
static int down_skip[NR_CPUS];
struct cpu_dbs_info_s *this_dbs_info;
@@ -256,25 +238,38 @@ static void dbs_check_cpu(int cpu)
policy = this_dbs_info->cur_policy;
/*
- * Every sampling_rate, we check, if current idle time is less
- * than 20% (default), then we try to increase frequency
- * Every sampling_rate*sampling_down_factor, we look for a the lowest
- * frequency which can sustain the load while keeping idle time over
- * 30%. If such a frequency exist, we try to decrease to this frequency.
+ * The default safe range is 20% to 80%
+ * Every sampling_rate, we check
+ * - If current idle time is less than 20%, then we try to
+ * increase frequency
+ * Every sampling_rate*sampling_down_factor, we check
+ * - If current idle time is more than 80%, then we try to
+ * decrease frequency
*
* Any frequency increase takes it to the maximum frequency.
* Frequency reduction happens at minimum steps of
- * 5% (default) of current frequency
+ * 5% of max_frequency
*/
/* Check for frequency increase */
- idle_ticks = UINT_MAX;
+ total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
+ kstat_cpu(cpu).cpustat.iowait;
+ idle_ticks = total_idle_ticks -
+ this_dbs_info->prev_cpu_idle_up;
+ this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+
for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
+ unsigned int tmp_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
+ if (j == cpu)
+ continue;
+
j_dbs_info = &per_cpu(cpu_dbs_info, j);
- total_idle_ticks = get_cpu_idle_time(j);
+ /* Check for frequency increase */
+ total_idle_ticks = kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
tmp_idle_ticks = total_idle_ticks -
j_dbs_info->prev_cpu_idle_up;
j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
@@ -286,23 +281,13 @@ static void dbs_check_cpu(int cpu)
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+ sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate);
if (idle_ticks < up_idle_ticks) {
- down_skip[cpu] = 0;
- for_each_cpu_mask(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
-
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_down =
- j_dbs_info->prev_cpu_idle_up;
- }
- /* if we are already at full speed then break out early */
- if (policy->cur == policy->max)
- return;
-
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
+ down_skip[cpu] = 0;
+ this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
return;
}
@@ -311,14 +296,23 @@ static void dbs_check_cpu(int cpu)
if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
return;
- idle_ticks = UINT_MAX;
+ total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
+ kstat_cpu(cpu).cpustat.iowait;
+ idle_ticks = total_idle_ticks -
+ this_dbs_info->prev_cpu_idle_down;
+ this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+
for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
+ unsigned int tmp_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
+ if (j == cpu)
+ continue;
+
j_dbs_info = &per_cpu(cpu_dbs_info, j);
- /* Check for frequency decrease */
- total_idle_ticks = j_dbs_info->prev_cpu_idle_up;
+ /* Check for frequency increase */
+ total_idle_ticks = kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
tmp_idle_ticks = total_idle_ticks -
j_dbs_info->prev_cpu_idle_down;
j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
@@ -327,37 +321,38 @@ static void dbs_check_cpu(int cpu)
idle_ticks = tmp_idle_ticks;
}
+ /* Scale idle ticks by 100 and compare with up and down ticks */
+ idle_ticks *= 100;
down_skip[cpu] = 0;
- /* if we cannot reduce the frequency anymore, break out early */
- if (policy->cur == policy->min)
- return;
- /* Compute how many ticks there are between two measurements */
freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
dbs_tuners_ins.sampling_down_factor;
- total_ticks = usecs_to_jiffies(freq_down_sampling_rate);
+ down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
+ sampling_rate_in_HZ(freq_down_sampling_rate);
- /*
- * The optimal frequency is the frequency that is the lowest that
- * can support the current CPU usage without triggering the up
- * policy. To be safe, we focus 10 points under the threshold.
- */
- freq_next = ((total_ticks - idle_ticks) * 100) / total_ticks;
- freq_next = (freq_next * policy->cur) /
- (dbs_tuners_ins.up_threshold - 10);
+ if (idle_ticks > down_idle_ticks ) {
+ freq_down_step = (5 * policy->max) / 100;
+
+ /* max freq cannot be less than 100. But who knows.... */
+ if (unlikely(freq_down_step == 0))
+ freq_down_step = 5;
- if (freq_next <= ((policy->cur * 95) / 100))
- __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
+ __cpufreq_driver_target(policy,
+ policy->cur - freq_down_step,
+ CPUFREQ_RELATION_H);
+ return;
+ }
}
static void do_dbs_timer(void *data)
{
int i;
down(&dbs_sem);
- for_each_online_cpu(i)
- dbs_check_cpu(i);
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ dbs_check_cpu(i);
schedule_delayed_work(&dbs_work,
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+ sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
up(&dbs_sem);
}
@@ -365,7 +360,7 @@ static inline void dbs_timer_init(void)
{
INIT_WORK(&dbs_work, do_dbs_timer, NULL);
schedule_delayed_work(&dbs_work,
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+ sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
return;
}
@@ -402,9 +397,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
- j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
- j_dbs_info->prev_cpu_idle_down
- = j_dbs_info->prev_cpu_idle_up;
+ j_dbs_info->prev_cpu_idle_up =
+ kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
+ j_dbs_info->prev_cpu_idle_down =
+ kstat_cpu(j).cpustat.idle +
+ kstat_cpu(j).cpustat.iowait;
}
this_dbs_info->enable = 1;
sysfs_create_group(&policy->kobj, &dbs_attr_group);
@@ -424,7 +422,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
def_sampling_rate = (latency / 1000) *
DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
dbs_tuners_ins.sampling_rate = def_sampling_rate;
- dbs_tuners_ins.ignore_nice = 0;
dbs_timer_init();
}
@@ -464,11 +461,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return 0;
}
-static struct cpufreq_governor cpufreq_gov_dbs = {
+struct cpufreq_governor cpufreq_gov_dbs = {
.name = "ondemand",
.governor = cpufreq_governor_dbs,
.owner = THIS_MODULE,
};
+EXPORT_SYMBOL(cpufreq_gov_dbs);
static int __init cpufreq_gov_dbs_init(void)
{
diff --git a/trunk/drivers/cpufreq/cpufreq_stats.c b/trunk/drivers/cpufreq/cpufreq_stats.c
index 741b6b191e6a..2084593937c6 100644
--- a/trunk/drivers/cpufreq/cpufreq_stats.c
+++ b/trunk/drivers/cpufreq/cpufreq_stats.c
@@ -19,7 +19,6 @@
#include
#include
#include
-#include
static spinlock_t cpufreq_stats_lock;
@@ -30,14 +29,20 @@ static struct freq_attr _attr_##_name = {\
.show = _show,\
};
+static unsigned long
+delta_time(unsigned long old, unsigned long new)
+{
+ return (old > new) ? (old - new): (new + ~old + 1);
+}
+
struct cpufreq_stats {
unsigned int cpu;
unsigned int total_trans;
- unsigned long long last_time;
+ unsigned long long last_time;
unsigned int max_state;
unsigned int state_num;
unsigned int last_index;
- cputime64_t *time_in_state;
+ unsigned long long *time_in_state;
unsigned int *freq_table;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
unsigned int *trans_table;
@@ -55,16 +60,12 @@ static int
cpufreq_stats_update (unsigned int cpu)
{
struct cpufreq_stats *stat;
- unsigned long long cur_time;
-
- cur_time = get_jiffies_64();
spin_lock(&cpufreq_stats_lock);
stat = cpufreq_stats_table[cpu];
if (stat->time_in_state)
- stat->time_in_state[stat->last_index] =
- cputime64_add(stat->time_in_state[stat->last_index],
- cputime_sub(cur_time, stat->last_time));
- stat->last_time = cur_time;
+ stat->time_in_state[stat->last_index] +=
+ delta_time(stat->last_time, jiffies);
+ stat->last_time = jiffies;
spin_unlock(&cpufreq_stats_lock);
return 0;
}
@@ -89,8 +90,8 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf)
return 0;
cpufreq_stats_update(stat->cpu);
for (i = 0; i < stat->state_num; i++) {
- len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i],
- (unsigned long long)cputime64_to_clock_t(stat->time_in_state[i]));
+ len += sprintf(buf + len, "%u %llu\n",
+ stat->freq_table[i], stat->time_in_state[i]);
}
return len;
}
@@ -106,30 +107,16 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
if(!stat)
return 0;
cpufreq_stats_update(stat->cpu);
- len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
- len += snprintf(buf + len, PAGE_SIZE - len, " : ");
- for (i = 0; i < stat->state_num; i++) {
- if (len >= PAGE_SIZE)
- break;
- len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
- stat->freq_table[i]);
- }
- if (len >= PAGE_SIZE)
- return len;
-
- len += snprintf(buf + len, PAGE_SIZE - len, "\n");
-
for (i = 0; i < stat->state_num; i++) {
if (len >= PAGE_SIZE)
break;
-
- len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ",
+ len += snprintf(buf + len, PAGE_SIZE - len, "%9u:\t",
stat->freq_table[i]);
for (j = 0; j < stat->state_num; j++) {
if (len >= PAGE_SIZE)
break;
- len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
+ len += snprintf(buf + len, PAGE_SIZE - len, "%u\t",
stat->trans_table[i*stat->max_state+j]);
}
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
@@ -210,7 +197,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
count++;
}
- alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
+ alloc_size = count * sizeof(int) + count * sizeof(long long);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
alloc_size += count * count * sizeof(int);
@@ -237,7 +224,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
}
stat->state_num = j;
spin_lock(&cpufreq_stats_lock);
- stat->last_time = get_jiffies_64();
+ stat->last_time = jiffies;
stat->last_index = freq_table_get_index(stat, policy->cur);
spin_unlock(&cpufreq_stats_lock);
cpufreq_cpu_put(data);
diff --git a/trunk/drivers/firmware/pcdp.c b/trunk/drivers/firmware/pcdp.c
index df1b721154d2..6d5df6c2efa2 100644
--- a/trunk/drivers/firmware/pcdp.c
+++ b/trunk/drivers/firmware/pcdp.c
@@ -11,7 +11,6 @@
* published by the Free Software Foundation.
*/
-#include
#include
#include
#include
diff --git a/trunk/drivers/i2c/busses/i2c-ali1563.c b/trunk/drivers/i2c/busses/i2c-ali1563.c
index fdd881aee618..35710818fe47 100644
--- a/trunk/drivers/i2c/busses/i2c-ali1563.c
+++ b/trunk/drivers/i2c/busses/i2c-ali1563.c
@@ -2,7 +2,6 @@
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
*
* Copyright (C) 2004 Patrick Mochel
- * 2005 Rudolf Marek
*
* The 1563 southbridge is deceptively similar to the 1533, with a
* few notable exceptions. One of those happens to be the fact they
@@ -58,11 +57,10 @@
#define HST_CNTL2_BLOCK 0x05
-#define HST_CNTL2_SIZEMASK 0x38
static unsigned short ali1563_smba;
-static int ali1563_transaction(struct i2c_adapter * a, int size)
+static int ali1563_transaction(struct i2c_adapter * a)
{
u32 data;
int timeout;
@@ -75,7 +73,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD) {
- dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
+ dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
outb_p(data | HST_STS_BAD,SMB_HST_STS);
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD)
@@ -96,31 +94,19 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
if (timeout && !(data & HST_STS_BAD))
return 0;
+ dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
+ timeout ? "Timeout " : "",
+ data & HST_STS_FAIL ? "Transaction Failed " : "",
+ data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
+ data & HST_STS_DEVERR ? "Device Error " : "",
+ !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
- if (!timeout) {
- dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
+ if (!(data & HST_STS_DONE))
/* Issue 'kill' to host controller */
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
- data = inb_p(SMB_HST_STS);
- }
-
- /* device error - no response, ignore the autodetection case */
- if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
- dev_err(&a->dev, "Device error!\n");
- }
-
- /* bus collision */
- if (data & HST_STS_BUSERR) {
- dev_err(&a->dev, "Bus collision!\n");
- /* Issue timeout, hoping it helps */
+ else
+ /* Issue timeout to reset all devices on bus */
outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
- }
-
- if (data & HST_STS_FAIL) {
- dev_err(&a->dev, "Cleaning fail after KILL!\n");
- outb_p(0x0,SMB_HST_CNTL2);
- }
-
return -1;
}
@@ -163,7 +149,7 @@ static int ali1563_block_start(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD))
return 0;
- dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
+ dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
timeout ? "Timeout " : "",
data & HST_STS_FAIL ? "Transaction Failed " : "",
data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
@@ -256,15 +242,13 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
}
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
- outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
+ outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2);
/* Write the command register */
-
switch(size) {
case HST_CNTL2_BYTE:
if (rw== I2C_SMBUS_WRITE)
- /* Beware it uses DAT0 register and not CMD! */
- outb_p(cmd, SMB_HST_DAT0);
+ outb_p(cmd, SMB_HST_CMD);
break;
case HST_CNTL2_BYTE_DATA:
outb_p(cmd, SMB_HST_CMD);
@@ -284,7 +268,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
goto Done;
}
- if ((error = ali1563_transaction(a, size)))
+ if ((error = ali1563_transaction(a)))
goto Done;
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
diff --git a/trunk/drivers/i2c/busses/i2c-keywest.c b/trunk/drivers/i2c/busses/i2c-keywest.c
index 867d443e7133..dd0d4c463146 100644
--- a/trunk/drivers/i2c/busses/i2c-keywest.c
+++ b/trunk/drivers/i2c/busses/i2c-keywest.c
@@ -516,11 +516,6 @@ create_iface(struct device_node *np, struct device *dev)
u32 *psteps, *prate;
int rc;
- if (np->n_intrs < 1 || np->n_addrs < 1) {
- printk(KERN_ERR "%s: Missing interrupt or address !\n",
- np->full_name);
- return -ENODEV;
- }
if (pmac_low_i2c_lock(np))
return -ENODEV;
diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c
index 39f3e9101ed4..33a020faeabd 100644
--- a/trunk/drivers/ide/ide-cd.c
+++ b/trunk/drivers/ide/ide-cd.c
@@ -1932,11 +1932,8 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
/*
* check if dma is safe
- *
- * NOTE! The "len" and "addr" checks should possibly have
- * separate masks.
*/
- if ((rq->data_len & 15) || (addr & mask))
+ if ((rq->data_len & mask) || (addr & mask))
info->dma = 0;
}
@@ -3258,12 +3255,16 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
return capacity * sectors_per_frame;
}
-static int ide_cd_remove(struct device *dev)
+static
+int ide_cdrom_cleanup(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info = drive->driver_data;
- ide_unregister_subdriver(drive, info->driver);
+ if (ide_unregister_subdriver(drive)) {
+ printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
+ __FUNCTION__, drive->name);
+ return 1;
+ }
del_gendisk(info->disk);
@@ -3296,7 +3297,7 @@ static void ide_cd_release(struct kref *kref)
kfree(info);
}
-static int ide_cd_probe(struct device *);
+static int ide_cdrom_attach (ide_drive_t *drive);
#ifdef CONFIG_PROC_FS
static int proc_idecd_read_capacity
@@ -3319,20 +3320,19 @@ static ide_proc_entry_t idecd_proc[] = {
static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
- .gen_driver = {
- .name = "ide-cdrom",
- .bus = &ide_bus_type,
- .probe = ide_cd_probe,
- .remove = ide_cd_remove,
- },
+ .name = "ide-cdrom",
.version = IDECD_VERSION,
.media = ide_cdrom,
+ .busy = 0,
.supports_dsc_overlap = 1,
+ .cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom,
.end_request = ide_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idecd_proc,
+ .attach = ide_cdrom_attach,
+ .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
};
static int idecd_open(struct inode * inode, struct file * file)
@@ -3418,9 +3418,8 @@ static char *ignore = NULL;
module_param(ignore, charp, 0400);
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
-static int ide_cd_probe(struct device *dev)
+static int ide_cdrom_attach (ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info;
struct gendisk *g;
struct request_sense sense;
@@ -3454,8 +3453,11 @@ static int ide_cd_probe(struct device *dev)
ide_init_disk(g, drive);
- ide_register_subdriver(drive, &ide_cdrom_driver);
-
+ if (ide_register_subdriver(drive, &ide_cdrom_driver)) {
+ printk(KERN_ERR "%s: Failed to register the driver with ide.c\n",
+ drive->name);
+ goto out_put_disk;
+ }
memset(info, 0, sizeof (struct cdrom_info));
kref_init(&info->kref);
@@ -3468,6 +3470,7 @@ static int ide_cd_probe(struct device *dev)
drive->driver_data = info;
+ DRIVER(drive)->busy++;
g->minors = 1;
snprintf(g->devfs_name, sizeof(g->devfs_name),
"%s/cd", drive->devfs_name);
@@ -3475,7 +3478,8 @@ static int ide_cd_probe(struct device *dev)
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
if (ide_cdrom_setup(drive)) {
struct cdrom_device_info *devinfo = &info->devinfo;
- ide_unregister_subdriver(drive, &ide_cdrom_driver);
+ DRIVER(drive)->busy--;
+ ide_unregister_subdriver(drive);
if (info->buffer != NULL)
kfree(info->buffer);
if (info->toc != NULL)
@@ -3488,6 +3492,7 @@ static int ide_cd_probe(struct device *dev)
drive->driver_data = NULL;
goto failed;
}
+ DRIVER(drive)->busy--;
cdrom_read_toc(drive, &sense);
g->fops = &idecd_ops;
@@ -3495,20 +3500,23 @@ static int ide_cd_probe(struct device *dev)
add_disk(g);
return 0;
+out_put_disk:
+ put_disk(g);
out_free_cd:
kfree(info);
failed:
- return -ENODEV;
+ return 1;
}
static void __exit ide_cdrom_exit(void)
{
- driver_unregister(&ide_cdrom_driver.gen_driver);
+ ide_unregister_driver(&ide_cdrom_driver);
}
static int ide_cdrom_init(void)
{
- return driver_register(&ide_cdrom_driver.gen_driver);
+ ide_register_driver(&ide_cdrom_driver);
+ return 0;
}
module_init(ide_cdrom_init);
diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c
index 3302cd8eab4c..5d54f7756100 100644
--- a/trunk/drivers/ide/ide-disk.c
+++ b/trunk/drivers/ide/ide-disk.c
@@ -1024,16 +1024,14 @@ static void ide_cacheflush_p(ide_drive_t *drive)
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
}
-static int ide_disk_remove(struct device *dev)
+static int idedisk_cleanup (ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp = drive->driver_data;
struct gendisk *g = idkp->disk;
ide_cacheflush_p(drive);
-
- ide_unregister_subdriver(drive, idkp->driver);
-
+ if (ide_unregister_subdriver(drive))
+ return 1;
del_gendisk(g);
ide_disk_put(idkp);
@@ -1054,7 +1052,7 @@ static void ide_disk_release(struct kref *kref)
kfree(idkp);
}
-static int ide_disk_probe(struct device *dev);
+static int idedisk_attach(ide_drive_t *drive);
static void ide_device_shutdown(struct device *dev)
{
@@ -1084,23 +1082,27 @@ static void ide_device_shutdown(struct device *dev)
dev->bus->suspend(dev, PMSG_SUSPEND);
}
+/*
+ * IDE subdriver functions, registered with ide.c
+ */
static ide_driver_t idedisk_driver = {
.owner = THIS_MODULE,
.gen_driver = {
- .name = "ide-disk",
- .bus = &ide_bus_type,
- .probe = ide_disk_probe,
- .remove = ide_disk_remove,
.shutdown = ide_device_shutdown,
},
+ .name = "ide-disk",
.version = IDEDISK_VERSION,
.media = ide_disk,
+ .busy = 0,
.supports_dsc_overlap = 0,
+ .cleanup = idedisk_cleanup,
.do_request = ide_do_rw_disk,
.end_request = ide_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idedisk_proc,
+ .attach = idedisk_attach,
+ .drives = LIST_HEAD_INIT(idedisk_driver.drives),
};
static int idedisk_open(struct inode *inode, struct file *filp)
@@ -1197,9 +1199,8 @@ static struct block_device_operations idedisk_ops = {
MODULE_DESCRIPTION("ATA DISK Driver");
-static int ide_disk_probe(struct device *dev)
+static int idedisk_attach(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp;
struct gendisk *g;
@@ -1221,7 +1222,10 @@ static int ide_disk_probe(struct device *dev)
ide_init_disk(g, drive);
- ide_register_subdriver(drive, &idedisk_driver);
+ if (ide_register_subdriver(drive, &idedisk_driver)) {
+ printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
+ goto out_put_disk;
+ }
memset(idkp, 0, sizeof(*idkp));
@@ -1235,6 +1239,7 @@ static int ide_disk_probe(struct device *dev)
drive->driver_data = idkp;
+ DRIVER(drive)->busy++;
idedisk_setup(drive);
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
@@ -1242,7 +1247,7 @@ static int ide_disk_probe(struct device *dev)
drive->attach = 0;
} else
drive->attach = 1;
-
+ DRIVER(drive)->busy--;
g->minors = 1 << PARTN_BITS;
strcpy(g->devfs_name, drive->devfs_name);
g->driverfs_dev = &drive->gendev;
@@ -1252,20 +1257,22 @@ static int ide_disk_probe(struct device *dev)
add_disk(g);
return 0;
+out_put_disk:
+ put_disk(g);
out_free_idkp:
kfree(idkp);
failed:
- return -ENODEV;
+ return 1;
}
static void __exit idedisk_exit (void)
{
- driver_unregister(&idedisk_driver.gen_driver);
+ ide_unregister_driver(&idedisk_driver);
}
static int idedisk_init (void)
{
- return driver_register(&idedisk_driver.gen_driver);
+ return ide_register_driver(&idedisk_driver);
}
module_init(idedisk_init);
diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c
index c949e98df4b6..36c0b74a4e45 100644
--- a/trunk/drivers/ide/ide-floppy.c
+++ b/trunk/drivers/ide/ide-floppy.c
@@ -1865,13 +1865,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
idefloppy_add_settings(drive);
}
-static int ide_floppy_remove(struct device *dev)
+static int idefloppy_cleanup (ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy = drive->driver_data;
struct gendisk *g = floppy->disk;
- ide_unregister_subdriver(drive, floppy->driver);
+ if (ide_unregister_subdriver(drive))
+ return 1;
del_gendisk(g);
@@ -1916,24 +1916,26 @@ static ide_proc_entry_t idefloppy_proc[] = {
#endif /* CONFIG_PROC_FS */
-static int ide_floppy_probe(struct device *);
+static int idefloppy_attach(ide_drive_t *drive);
+/*
+ * IDE subdriver functions, registered with ide.c
+ */
static ide_driver_t idefloppy_driver = {
.owner = THIS_MODULE,
- .gen_driver = {
- .name = "ide-floppy",
- .bus = &ide_bus_type,
- .probe = ide_floppy_probe,
- .remove = ide_floppy_remove,
- },
+ .name = "ide-floppy",
.version = IDEFLOPPY_VERSION,
.media = ide_floppy,
+ .busy = 0,
.supports_dsc_overlap = 0,
+ .cleanup = idefloppy_cleanup,
.do_request = idefloppy_do_request,
.end_request = idefloppy_do_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idefloppy_proc,
+ .attach = idefloppy_attach,
+ .drives = LIST_HEAD_INIT(idefloppy_driver.drives),
};
static int idefloppy_open(struct inode *inode, struct file *filp)
@@ -2120,9 +2122,8 @@ static struct block_device_operations idefloppy_ops = {
.revalidate_disk= idefloppy_revalidate_disk
};
-static int ide_floppy_probe(struct device *dev)
+static int idefloppy_attach (ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy;
struct gendisk *g;
@@ -2151,7 +2152,10 @@ static int ide_floppy_probe(struct device *dev)
ide_init_disk(g, drive);
- ide_register_subdriver(drive, &idefloppy_driver);
+ if (ide_register_subdriver(drive, &idefloppy_driver)) {
+ printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
+ goto out_put_disk;
+ }
memset(floppy, 0, sizeof(*floppy));
@@ -2165,8 +2169,9 @@ static int ide_floppy_probe(struct device *dev)
drive->driver_data = floppy;
+ DRIVER(drive)->busy++;
idefloppy_setup (drive, floppy);
-
+ DRIVER(drive)->busy--;
g->minors = 1 << PARTN_BITS;
g->driverfs_dev = &drive->gendev;
strcpy(g->devfs_name, drive->devfs_name);
@@ -2176,17 +2181,19 @@ static int ide_floppy_probe(struct device *dev)
add_disk(g);
return 0;
+out_put_disk:
+ put_disk(g);
out_free_floppy:
kfree(floppy);
failed:
- return -ENODEV;
+ return 1;
}
MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
static void __exit idefloppy_exit (void)
{
- driver_unregister(&idefloppy_driver.gen_driver);
+ ide_unregister_driver(&idefloppy_driver);
}
/*
@@ -2195,7 +2202,8 @@ static void __exit idefloppy_exit (void)
static int idefloppy_init (void)
{
printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
- return driver_register(&idefloppy_driver.gen_driver);
+ ide_register_driver(&idefloppy_driver);
+ return 0;
}
module_init(idefloppy_init);
diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c
index 5d876f53c697..554473a95cf7 100644
--- a/trunk/drivers/ide/ide-probe.c
+++ b/trunk/drivers/ide/ide-probe.c
@@ -47,7 +47,6 @@
#include
#include