S: USA
N: Randy Dunlap
-E: rddunlap@osdl.org
+E: rdunlap@xenotime.net
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: 12725 SW Millikan Way, Suite 400
-S: Beaverton, Oregon 97005
+S: (ask for current address)
S: USA
N: Bob Dunlop
</authorgroup>
<copyright>
- <year>2003</year>
+ <year>2003-2005</year>
<holder>Jeff Garzik</holder>
</copyright>
<toc></toc>
- <chapter id="libataThanks">
- <title>Thanks</title>
+ <chapter id="libataIntroduction">
+ <title>Introduction</title>
<para>
- The bulk of the ATA knowledge comes thanks to long conversations with
- Andre Hedrick (www.linux-ide.org).
+ libATA is a library used inside the Linux kernel to support ATA host
+ controllers and devices. libATA provides an ATA driver API, class
+ transports for ATA and ATAPI devices, and SCSI<->ATA translation
+ for ATA devices according to the T10 SAT specification.
</para>
<para>
- Thanks to Alan Cox for pointing out similarities
- between SATA and SCSI, and in general for motivation to hack on
- libata.
- </para>
- <para>
- libata's device detection
- method, ata_pio_devchk, and in general all the early probing was
- based on extensive study of Hale Landis's probe/reset code in his
- ATADRVR driver (www.ata-atapi.com).
+ This Guide documents the libATA driver API, library functions, library
+ internals, and a couple sample ATA low-level drivers.
</para>
</chapter>
<chapter id="libataDriverApi">
<title>libata Driver API</title>
+ <para>
+ struct ata_port_operations is defined for every low-level libata
+ hardware driver, and it controls how the low-level driver
+ interfaces with the ATA and SCSI layers.
+ </para>
+ <para>
+ FIS-based drivers will hook into the system with ->qc_prep() and
+ ->qc_issue() high-level hooks. Hardware which behaves in a manner
+ similar to PCI IDE hardware may utilize several generic helpers,
+ defining at a bare minimum the bus I/O addresses of the ATA shadow
+ register blocks.
+ </para>
<sect1>
<title>struct ata_port_operations</title>
+ <sect2><title>Disable ATA port</title>
<programlisting>
void (*port_disable) (struct ata_port *);
</programlisting>
unplug).
</para>
+ </sect2>
+
+ <sect2><title>Post-IDENTIFY device configuration</title>
<programlisting>
void (*dev_config) (struct ata_port *, struct ata_device *);
</programlisting>
issue of SET FEATURES - XFER MODE, and prior to operation.
</para>
+ </sect2>
+
+ <sect2><title>Set PIO/DMA mode</title>
<programlisting>
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
->set_dma_mode() is only called if DMA is possible.
</para>
+ </sect2>
+
+ <sect2><title>Taskfile read/write</title>
<programlisting>
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
taskfile register values.
</para>
+ </sect2>
+
+ <sect2><title>ATA command execute</title>
<programlisting>
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
</programlisting>
->tf_load(), to be initiated in hardware.
</para>
+ </sect2>
+
+ <sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
+ <programlisting>
+int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+ </programlisting>
+
+ <para>
+Allow low-level driver to filter ATA PACKET commands, returning a status
+indicating whether or not it is OK to use DMA for the supplied PACKET
+command.
+ </para>
+
+ </sect2>
+
+ <sect2><title>Read specific ATA shadow registers</title>
<programlisting>
u8 (*check_status)(struct ata_port *ap);
-void (*dev_select)(struct ata_port *ap, unsigned int device);
+u8 (*check_altstatus)(struct ata_port *ap);
+u8 (*check_err)(struct ata_port *ap);
</programlisting>
<para>
- Reads the Status ATA shadow register from hardware. On some
- hardware, this has the side effect of clearing the interrupt
- condition.
+ Reads the Status/AltStatus/Error ATA shadow register from
+ hardware. On some hardware, reading the Status register has
+ the side effect of clearing the interrupt condition.
</para>
+ </sect2>
+
+ <sect2><title>Select ATA device on bus</title>
<programlisting>
void (*dev_select)(struct ata_port *ap, unsigned int device);
</programlisting>
<para>
Issues the low-level hardware command(s) that causes one of N
hardware devices to be considered 'selected' (active and
- available for use) on the ATA bus.
+ available for use) on the ATA bus. This generally has no
+meaning on FIS-based devices.
</para>
+ </sect2>
+
+ <sect2><title>Reset ATA bus</title>
<programlisting>
void (*phy_reset) (struct ata_port *ap);
</programlisting>
functions ata_bus_reset() or sata_phy_reset() for this hook.
</para>
+ </sect2>
+
+ <sect2><title>Control PCI IDE BMDMA engine</title>
<programlisting>
void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc);
+void (*bmdma_stop) (struct ata_port *ap);
+u8 (*bmdma_status) (struct ata_port *ap);
</programlisting>
<para>
- When setting up an IDE BMDMA transaction, these hooks arm
- (->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
- engine.
+When setting up an IDE BMDMA transaction, these hooks arm
+(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
+the hardware's DMA engine. ->bmdma_status is used to read the standard
+PCI IDE DMA Status register.
</para>
+ <para>
+These hooks are typically either no-ops, or simply not implemented, in
+FIS-based drivers.
+ </para>
+
+ </sect2>
+
+ <sect2><title>High-level taskfile hooks</title>
<programlisting>
void (*qc_prep) (struct ata_queued_cmd *qc);
int (*qc_issue) (struct ata_queued_cmd *qc);
->qc_issue is used to make a command active, once the hardware
and S/G tables have been prepared. IDE BMDMA drivers use the
helper function ata_qc_issue_prot() for taskfile protocol-based
- dispatch. More advanced drivers roll their own ->qc_issue
- implementation, using this as the "issue new ATA command to
- hardware" hook.
+ dispatch. More advanced drivers implement their own ->qc_issue.
</para>
+ </sect2>
+
+ <sect2><title>Timeout (error) handling</title>
<programlisting>
void (*eng_timeout) (struct ata_port *ap);
</programlisting>
<para>
- This is a high level error handling function, called from the
- error handling thread, when a command times out.
+This is a high level error handling function, called from the
+error handling thread, when a command times out. Most newer
+hardware will implement its own error handling code here. IDE BMDMA
+drivers may use the helper function ata_eng_timeout().
</para>
+ </sect2>
+
+ <sect2><title>Hardware interrupt handling</title>
<programlisting>
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *);
is quiet.
</para>
+ </sect2>
+
+ <sect2><title>SATA phy read/write</title>
<programlisting>
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
if ->phy_reset hook called the sata_phy_reset() helper function.
</para>
+ </sect2>
+
+ <sect2><title>Init and shutdown</title>
<programlisting>
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
tasks.
</para>
<para>
- ->host_stop() is called when the rmmod or hot unplug process
- begins. The hook must stop all hardware interrupts, DMA
- engines, etc.
- </para>
- <para>
->port_stop() is called after ->host_stop(). It's sole function
is to release DMA/memory resources, now that they are no longer
actively being used.
</para>
+ <para>
+ ->host_stop() is called after all ->port_stop() calls
+have completed. The hook must finalize hardware shutdown, release DMA
+and other resources, etc.
+ </para>
+
+ </sect2>
</sect1>
</chapter>
!Idrivers/scsi/sata_sil.c
</chapter>
+ <chapter id="libataThanks">
+ <title>Thanks</title>
+ <para>
+ The bulk of the ATA knowledge comes thanks to long conversations with
+ Andre Hedrick (www.linux-ide.org), and long hours pondering the ATA
+ and SCSI specifications.
+ </para>
+ <para>
+ Thanks to Alan Cox for pointing out similarities
+ between SATA and SCSI, and in general for motivation to hack on
+ libata.
+ </para>
+ <para>
+ libata's device detection
+ method, ata_pio_devchk, and in general all the early probing was
+ based on extensive study of Hale Landis's probe/reset code in his
+ ATADRVR driver (www.ata-atapi.com).
+ </para>
+ </chapter>
+
</book>
--- /dev/null
+
+ CPU frequency and voltage scaling statictics in the Linux(TM) kernel
+
+
+ L i n u x c p u f r e q - s t a t s d r i v e r
+
+ - information for users -
+
+
+ Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+Contents
+1. Introduction
+2. Statistics Provided (with example)
+3. Configuring cpufreq-stats
+
+
+1. Introduction
+
+cpufreq-stats is a driver that provices CPU frequency statistics for each CPU.
+This statistics is provided in /sysfs as a bunch of read_only interfaces. This
+interface (when configured) will appear in a seperate directory under cpufreq
+in /sysfs (<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU.
+Various statistics will form read_only files under this directory.
+
+This driver is designed to be independent of any particular cpufreq_driver
+that may be running on your CPU. So, it will work with any cpufreq_driver.
+
+
+2. Statistics Provided (with example)
+
+cpufreq stats provides following statistics (explained in detail below).
+- time_in_state
+- total_trans
+- trans_table
+
+All the statistics will be from the time the stats driver has been inserted
+to the time when a read of a particular statistic is done. Obviously, stats
+driver will not have any information about the the frequcny transitions before
+the stats driver insertion.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # ls -l
+total 0
+drwxr-xr-x 2 root root 0 May 14 16:06 .
+drwxr-xr-x 3 root root 0 May 14 15:58 ..
+-r--r--r-- 1 root root 4096 May 14 16:06 time_in_state
+-r--r--r-- 1 root root 4096 May 14 16:06 total_trans
+-r--r--r-- 1 root root 4096 May 14 16:06 trans_table
+--------------------------------------------------------------------------------
+
+- time_in_state
+This gives the amount of time spent in each of the frequencies supported by
+this CPU. The cat output will have "<frequency> <time>" pair in each line, which
+will mean this CPU spent <time> usertime units of time at <frequency>. Output
+will have one line for each of the supported freuencies. usertime units here
+is 10mS (similar to other time exported in /proc).
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat time_in_state
+3600000 2089
+3400000 136
+3200000 34
+3000000 67
+2800000 172488
+--------------------------------------------------------------------------------
+
+
+- total_trans
+This gives the total number of frequency transitions on this CPU. The cat
+output will have a single count which is the total number of frequency
+transitions.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat total_trans
+20
+--------------------------------------------------------------------------------
+
+- trans_table
+This will give a fine grained information about all the CPU frequency
+transitions. The cat output here is a two dimensional matrix, where an entry
+<i,j> (row i, column j) represents the count of number of transitions from
+Freq_i to Freq_j. Freq_i is in descending order with increasing rows and
+Freq_j is in descending order with increasing columns. The output here also
+contains the actual freq values for each row and column for better readability.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat trans_table
+ From : To
+ : 3600000 3400000 3200000 3000000 2800000
+ 3600000: 0 5 0 0 0
+ 3400000: 4 0 2 0 0
+ 3200000: 0 1 0 2 0
+ 3000000: 0 0 1 0 3
+ 2800000: 0 0 0 2 0
+--------------------------------------------------------------------------------
+
+
+3. Configuring cpufreq-stats
+
+To configure cpufreq-stats in your kernel
+Config Main Menu
+ Power management options (ACPI, APM) --->
+ CPU Frequency scaling --->
+ [*] CPU Frequency scaling
+ <*> CPU frequency translation statistics
+ [*] CPU frequency translation statistics details
+
+
+"CPU Frequency scaling" (CONFIG_CPU_FREQ) should be enabled to configure
+cpufreq-stats.
+
+"CPU frequency translation statistics" (CONFIG_CPU_FREQ_STAT) provides the
+basic statistics which includes time_in_state and total_trans.
+
+"CPU frequency translation statistics details" (CONFIG_CPU_FREQ_STAT_DETAILS)
+provides fine grained cpufreq stats by trans_table. The reason for having a
+seperate config option for trans_table is:
+- trans_table goes against the traditional /sysfs rule of one value per
+ interface. It provides a whole bunch of value in a 2 dimensional matrix
+ form.
+
+Once these two options are enabled and your CPU supports cpufrequency, you
+will be able to see the CPU frequency statistics in /sysfs.
+
+
+
+
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 with the online CPUs of the
-nearest parent cpuset that still has some CPUs online. When memory
+tasks attached to CPUs in that cpuset to allow all CPUs. 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
--- /dev/null
+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
+<empty field> = 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.
"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. 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).
+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.
3a) Nebula / Pinnacle PCTV
--------------------------
- $ modprobe bttv i2c_hw=1 card=0x68
- $ modprobe dvb-bt8xx
-
-For Nebula cards use the "nxt6000" frontend driver:
- $ modprobe nxt6000
+ $ modprobe bttv (normally bttv is being loaded automatically by kmod)
+ $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
-For Pinnacle PCTV cards use the "cx24110" frontend driver:
- $ modprobe cx24110
-3b) TwinHan
------------
+3b) TwinHan and Clones
+--------------------------
$ 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 DVB 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
+mailing list.
-The DST module takes a couple of useful parameters, in case the
-dst drivers fails to detect your type of card correctly.
+The DST module takes a couple of useful parameters.
-dst_type takes values 0 (satellite), 1 (terrestial TV), 2 (cable).
+verbose takes values 0 to 5. These values control the verbosity level.
-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.)
+debug takes values 0 and 1. You can either disable or enable debugging.
-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)
+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.
-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
+The autodected values are determined bythe cards 'response
string' which you can see in your logs e.g.
-dst_check_ci: recognize DST-MOT
-
-or
+dst_get_device_id: Recognise [DSTMCI]
-dst_check_ci: unable to recognize DSTXCI or STXCI
--
-Authors: Richard Walker, Jamie Honan, Michael Hunold
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
--- /dev/null
+* 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.
sub tda10046 {
my $sourcefile = "tt_budget_217g.zip";
my $url = "http://www.technotrend.de/new/217g/$sourcefile";
- my $hash = "a25b579e37109af60f4a36c37893957c";
+ my $hash = "6a7e1e2f2644b162ff0502367553c72d";
my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
- extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, "$tmpdir/fwtmp");
+ extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp");
verify("$tmpdir/fwtmp", $hash);
copy("$tmpdir/fwtmp", $outfile);
people, who might be using implementations that I am not aware
of, to adjust to this upcoming change.
Who: Paul E. McKenney <paulmck@us.ibm.com>
+
+---------------------------
+
+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 <scjody@steamballoon.com>
+
+---------------------------
+
+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 <scjody@steamballoon.com>
|-- 0000:17:00.0
| |-- class
| |-- config
- | |-- detach_state
| |-- device
| |-- irq
| |-- local_cpus
| |-- 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).
---- --------
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)
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.
\ No newline at end of file
+pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
Generic HDLC layer
Krzysztof Halasa <khc@pm.waw.pl>
-January, 2003
Generic HDLC layer currently supports:
-- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
- Normal (routed) and Ethernet-bridged (Ethernet device emulation)
- interfaces can share a single PVC.
-- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
-- Cisco HDLC,
-- PPP (uses syncppp.c),
-- X.25 (uses X.25 routines).
-
-There are hardware drivers for the following cards:
-- C101 by Moxa Technologies Co., Ltd.
-- RISCom/N2 by SDL Communications Inc.
-- and others, some not in the official kernel.
+1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
+ - Normal (routed) and Ethernet-bridged (Ethernet device emulation)
+ interfaces can share a single PVC.
+ - ARP support (no InARP support in the kernel - there is an
+ experimental InARP user-space daemon available on:
+ http://www.kernel.org/pub/linux/utils/net/hdlc/).
+2. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
+3. Cisco HDLC.
+4. PPP (uses syncppp.c).
+5. X.25 (uses X.25 routines).
+
+Generic HDLC is a protocol driver only - it needs a low-level driver
+for your particular hardware.
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
Make sure the hdlc.o and the hardware driver are loaded. It should
create a number of "hdlc" (hdlc0 etc) network devices, one for each
WAN port. You'll need the "sethdlc" utility, get it from:
- http://hq.pm.waw.pl/hdlc/
+ http://www.kernel.org/pub/linux/utils/net/hdlc/
Compile sethdlc.c utility:
gcc -O2 -Wall -o sethdlc sethdlc.c
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
if the card has software-selectable interfaces
loopback - activate hardware loopback (for testing only)
-* clock ext - external clock (uses DTE RX and TX clock)
-* clock int - internal clock (provides clock signal on DCE clock output)
-* clock txint - TX internal, RX external (provides TX clock on DCE output)
-* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
-* rate - sets clock rate in bps (not required for external clock or
- for txfromrx)
+* clock ext - both RX clock and TX clock external
+* clock int - both RX clock and TX clock internal
+* clock txint - RX clock external, TX clock internal
+* clock txfromrx - RX clock external, TX clock derived from RX clock
+* rate - sets clock rate in bps (for "int" or "txint" clock only)
+
Setting protocol:
* x25 - sets X.25 mode
* fr - Frame Relay mode
- lmi ansi / ccitt / none - LMI (link management) type
+ lmi ansi / ccitt / cisco / none - LMI (link management) type
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
It has nothing to do with clocks!
t391 - link integrity verification polling timer (in seconds) - user
-If you have a problem with N2 or C101 card, you can issue the "private"
-command to see port's packet descriptor rings (in kernel logs):
+If you have a problem with N2, C101 or PLX200SYN card, you can issue the
+"private" command to see port's packet descriptor rings (in kernel logs):
sethdlc hdlc0 private
-The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS.
+The hardware driver has to be build with #define DEBUG_RINGS.
Attaching this info to bug reports would be helpful. Anyway, let me know
if you have problems using this.
-For patches and other info look at http://hq.pm.waw.pl/hdlc/
+For patches and other info look at:
+<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
ni65 YES YES YES Software(#)
seeq NO NO NO N/A
sgiseek <------------------ Buggy ------------------>
-sk_g16 NO NO YES N/A
smc-ultra YES YES YES Hardware
sunlance YES YES YES Hardware
tulip YES YES YES Hardware
seeq8005.c: *Not modularized*
(Probes ports: 0x300, 0x320, 0x340, 0x360)
-sk_g16.c: *Not modularized*
- (Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
-
skeleton.c: *Skeleton*
slhc.c:
#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
looks like the following:
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
- . current_vty devspec name partner_vtys
- .. detach_state index partner_clcs vterm_state
+ . current_vty devspec name partner_vtys
+ .. 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
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
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
S: Maintained
SN-IA64 (Itanium) SUB-PLATFORM
-P: Jesse Barnes
-M: jbarnes@sgi.com
+P: Greg Edwards
+M: edwardsg@sgi.com
L: linux-altix@sgi.com
L: linux-ia64@vger.kernel.org
W: http://www.sgi.com/altix
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 12
-EXTRAVERSION =-rc4
+EXTRAVERSION =-rc5
NAME=Woozy Numbat
# *DOCUMENTATION*
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
if (get_tv32(&tmp, sleep))
goto fault;
- ticks = tmp.tv_usec;
- ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
- ticks += tmp.tv_sec * HZ;
+ ticks = timeval_to_jiffies(&tmp);
current->state = TASK_INTERRUPTIBLE;
ticks = schedule_timeout(ticks);
if (remain) {
- tmp.tv_sec = ticks / HZ;
- tmp.tv_usec = ticks % HZ;
+ jiffies_to_timeval(ticks, &tmp);
if (put_tv32(remain, &tmp))
goto fault;
}
{
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
- s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
+ s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
print_mhz(s3c2440_clk_upll.rate));
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_i2c.name = "s3c2440-i2c";
+ s3c_device_nand.name = "s3c2440-nand";
/* change irq for watchdog */
break;
case S3C2440_CLKDIVN_HDIVN_2:
- hdiv = 1;
+ hdiv = 2;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
config TLS_REG_EMUL
bool
- default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+ default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
help
- 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.
+ 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.
config HAS_TLS_REG
bool
- depends on CPU_32v6
- default y if !TLS_REG_EMUL
+ depends on !TLS_REG_EMUL
+ default y if SMP || CPU_32v7
help
This selects support for the CP15 thread register.
- 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.
+ 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.
+++ /dev/null
-/*
- * 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 <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/constants.h>
-
- .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
--- /dev/null
+/*
+ * 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 <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * 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,
+};
#define to_address (0xffffc000)
#define to_pgprot PAGE_KERNEL
-static pte_t *from_pte;
-static pte_t *to_pte;
+#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
+
static DEFINE_SPINLOCK(v6_lock);
#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
*/
spin_lock(&v6_lock);
- 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));
+ 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));
from = from_address + (offset << PAGE_SHIFT);
to = to_address + (offset << PAGE_SHIFT);
*/
spin_lock(&v6_lock);
- set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
+ set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
flush_tlb_kernel_page(to);
clear_page((void *)to);
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;
}
return 0;
}
-__initcall(v6_userpage_init);
-
+core_initcall(v6_userpage_init);
#include <asm/cacheflush.h>
#include <asm/system.h>
+#include <asm/tlbflush.h>
+
+#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)
{
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
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);
}
EXPORT_SYMBOL(pgprot_kernel);
+pmd_t *top_pmd;
+
struct cachepolicy {
const char policy[16];
unsigned int cr_mask;
#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
*/
return;
/* pgd is always present and good */
- pmd = (pmd_t *)pgd;
+ pmd = pmd_off(pgd, 0);
if (pmd_none(*pmd))
goto free;
if (pmd_bad(*pmd)) {
static inline void
alloc_init_section(unsigned long virt, unsigned long phys, int prot)
{
- pmd_t *pmdp;
+ pmd_t *pmdp = pmd_off_k(virt);
- pmdp = pmd_offset(pgd_offset_k(virt), virt);
if (virt & (1 << 20))
pmdp++;
static inline void
alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
{
- pmd_t *pmdp;
+ pmd_t *pmdp = pmd_off_k(virt);
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 *
*/
static inline void clear_mapping(unsigned long virt)
{
- pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
+ pmd_clear(pmd_off_k(virt));
}
struct mem_types {
PMD_TYPE_SECT;
if (cpu_arch <= CPU_ARCH_ARMv5)
pmdval |= PMD_BIT4;
- pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
+ pmd = pmd_off(pgd, i << PGDIR_SHIFT);
pmd[0] = __pmd(pmdval);
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
flush_pmd_entry(pmd);
flush_cache_all();
flush_tlb_all();
+
+ top_pmd = pmd_off_k(0xffff0000);
}
/*
void default_idle(void)
{
while(1) {
- if (need_resched()) {
+ if (!need_resched()) {
local_irq_enable();
__asm__("sleep");
local_irq_disable();
config PCI_MMCONFIG
bool
- depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI))
+ depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
select ACPI_BOOT
default y
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;
c->x86_num_cores = 1;
}
-#ifdef CONFIG_X86_SMP
+#ifdef CONFIG_X86_HT
/*
* 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) {
- cpu_core_id[cpu] = cpu >> hweight32(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)-1);
+ phys_proc_id[cpu] >>= bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
cpu, c->x86_num_cores, cpu_core_id[cpu]);
}
}
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)
If in doubt, say N.
config ELAN_CPUFREQ
- tristate "AMD Elan"
+ tristate "AMD Elan SC400 and SC410"
select CPU_FREQ_TABLE
depends on X86_ELAN
---help---
If in doubt, say N.
+config SC520_CPUFREQ
+ tristate "AMD Elan SC520"
+ select CPU_FREQ_TABLE
+ depends on X86_ELAN
+ ---help---
+ This adds the CPUFreq driver for AMD Elan SC520 processor.
+
+ For details, take a look at <file:Documentation/cpu-freq/>.
+
+ If in doubt, say N.
+
+
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
select CPU_FREQ_TABLE
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
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/pci.h>
#include <asm/msr.h>
#include <asm/timex.h>
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:
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul->bits.EnableSoftBusRatio = 1;
longhaul->bits.RevisionKey = 0;
- local_irq_disable();
- wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+
+ preempt_disable();
+ local_irq_save(flags);
+
+ /*
+ * get current pci bus master state for all devices
+ * and clear bus master bit
+ */
+ dev = NULL;
+ i = 0;
+ do {
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+ if (dev != NULL) {
+ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+ cmd_state[i++] = pci_cmd;
+ pci_cmd &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+ }
+ } while (dev != NULL);
+
+ tmp_mask=inb(0x21); /* works on C3. save mask. */
+ outb(0xFE,0x21); /* TMR0 only */
+ outb(0xFF,0x80); /* delay */
+
local_irq_enable();
+
+ __hlt();
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
__hlt();
+ local_irq_disable();
+
+ outb(tmp_mask,0x21); /* restore mask */
+
+ /* restore pci bus master state for all devices */
+ dev = NULL;
+ i = 0;
+ do {
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+ if (dev != NULL) {
+ pci_cmd = cmd_state[i++];
+ pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
+ }
+ } while (dev != NULL);
+ local_irq_restore(flags);
+ preempt_enable();
+
+ /* disable bus ratio bit */
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
longhaul->bits.EnableSoftBusRatio = 0;
longhaul->bits.RevisionKey = version;
- local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- local_irq_enable();
}
/**
longhaul_setup_voltagescaling();
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ policy->cpuinfo.transition_latency = 200000; /* nsec */
policy->cur = calc_speed(longhaul_get_cpu_mult());
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
#include <linux/dmi.h>
#include <asm/msr.h>
+#include <asm/timer.h>
#include <asm/timex.h>
#include <asm/io.h>
#include <asm/system.h>
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
- /* A K7 with powernow technology is set to max frequency by BIOS */
- fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
+ /* recalibrate cpu_khz */
+ result = recalibrate_cpu_khz();
+ if (result)
+ return result;
+
+ fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
if (!fsb) {
printk(KERN_WARNING PFX "can not determine bus frequency\n");
return -EINVAL;
}
- dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
+ dprintk("FSB: %3dMHz\n", fsb/1000);
if (dmi_check_system(powernow_dmi_table) || acpi_force) {
printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
*
- * Support : paul.devriendt@amd.com
+ * Support : mark.langsdorf@amd.com
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
*
* Valuable input gratefully received from Dave Jones, Pavel Machek,
* Dominik Brodowski, and others.
+ * Originally developed by Paul Devriendt.
* Processor information obtained from Chapter 9 (Power and Thermal Management)
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
* Opteron Processors" available for download from www.amd.com
*
* Tables for specific CPUs can be infrerred from
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
*/
#include <linux/kernel.h>
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/cpumask.h>
#include <asm/msr.h>
#include <asm/io.h>
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.00.09e"
+#define VERSION "version 1.40.2"
#include "powernow-k8.h"
/* serialize freq changes */
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)
{
{
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);
return 1;
}
- while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
- if (data->currvid == 0) {
+ while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
+ if (data->currvid == maxvid) {
rvosteps = 0;
} else {
dprintk("ph1: changing vid for rvo, req 0x%x\n",
* BIOS and Kernel Developer's Guide, which is available on
* www.amd.com
*/
- printk(KERN_ERR PFX "BIOS error - no PSB\n");
+ printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
return -ENODEV;
}
struct cpufreq_frequency_table *powernow_table;
if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
- dprintk("register performance failed\n");
+ dprintk("register performance failed: bad ACPI data\n");
return -EIO;
}
continue;
}
- if (fid < HI_FID_TABLE_BOTTOM) {
- if (cntlofreq) {
- /* if both entries are the same, ignore this
- * one...
- */
- if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
- (powernow_table[i].index != powernow_table[cntlofreq].index)) {
- printk(KERN_ERR PFX "Too many lo freq table entries\n");
- goto err_out_mem;
- }
-
- dprintk("double low frequency table entry, ignoring it.\n");
- powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
- continue;
- } else
- cntlofreq = i;
+ /* verify only 1 entry from the lo frequency table */
+ if (fid < HI_FID_TABLE_BOTTOM) {
+ if (cntlofreq) {
+ /* if both entries are the same, ignore this
+ * one...
+ */
+ if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
+ (powernow_table[i].index != powernow_table[cntlofreq].index)) {
+ printk(KERN_ERR PFX "Too many lo freq table entries\n");
+ goto err_out_mem;
+ }
+
+ dprintk("double low frequency table entry, ignoring it.\n");
+ powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+ continue;
+ } else
+ cntlofreq = i;
}
if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
{
u32 fid;
u32 vid;
- int res;
+ int res, i;
struct cpufreq_freqs freqs;
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
}
if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
- printk("ignoring illegal change in lo freq table-%x to 0x%x\n",
+ printk(KERN_ERR PFX
+ "ignoring illegal change in lo freq table-%x to 0x%x\n",
data->currfid, fid);
return 1;
}
smp_processor_id(), fid, vid);
freqs.cpu = data->cpu;
-
freqs.old = find_khz_freq_from_fid(data->currfid);
freqs.new = find_khz_freq_from_fid(fid);
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
- down(&fidvid_sem);
res = transition_fid_vid(data, fid, vid);
- up(&fidvid_sem);
freqs.new = find_khz_freq_from_fid(data->currfid);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
+ for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
return res;
}
u32 checkvid = data->currvid;
unsigned int newstate;
int ret = -EIO;
+ int i;
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
data->currfid, data->currvid);
if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
- printk(KERN_ERR PFX
- "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
- checkfid, data->currfid, checkvid, data->currvid);
+ printk(KERN_INFO PFX
+ "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
+ checkfid, data->currfid, checkvid, data->currvid);
}
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
goto err_out;
+ down(&fidvid_sem);
+
+ for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+ /* make sure the sibling is initialized */
+ if (!powernow_data[i]) {
+ ret = 0;
+ up(&fidvid_sem);
+ goto err_out;
+ }
+ }
+
powernow_k8_acpi_pst_values(data, newstate);
if (transition_frequency(data, newstate)) {
printk(KERN_ERR PFX "transition frequency failed\n");
ret = 1;
+ up(&fidvid_sem);
goto err_out;
}
+ /* Update all the fid/vids of our siblings */
+ for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+ powernow_data[i]->currvid = data->currvid;
+ powernow_data[i]->currfid = data->currfid;
+ }
+ up(&fidvid_sem);
+
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
*/
if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
- printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
+ printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
kfree(data);
return -ENODEV;
}
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 */
return 0;
}
preempt_disable();
-
+
if (query_current_values_with_pending_wait(data))
goto out;
cpufreq_unregister_driver(&cpufreq_amd64_driver);
}
-MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
+MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
MODULE_LICENSE("GPL");
late_initcall(powernowk8_init);
module_exit(powernowk8_exit);
+
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
--- /dev/null
+/*
+ * sc520_freq.c: cpufreq driver for the AMD Elan sc520
+ *
+ * Copyright (C) 2005 Sean Young <sean@mess.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Based on elanfreq.c
+ *
+ * 2005-03-30: - initial revision
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/delay.h>
+#include <linux/cpufreq.h>
+
+#include <asm/msr.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+
+#define MMCR_BASE 0xfffef000 /* The default base address */
+#define OFFS_CPUCTL 0x2 /* CPU Control Register */
+
+static __u8 __iomem *cpuctl;
+
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg)
+
+static struct cpufreq_frequency_table sc520_freq_table[] = {
+ {0x01, 100000},
+ {0x02, 133000},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
+{
+ u8 clockspeed_reg = *cpuctl;
+
+ switch (clockspeed_reg & 0x03) {
+ default:
+ printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg);
+ case 0x01:
+ return 100000;
+ case 0x02:
+ return 133000;
+ }
+}
+
+static void sc520_freq_set_cpu_state (unsigned int state)
+{
+
+ struct cpufreq_freqs freqs;
+ u8 clockspeed_reg;
+
+ freqs.old = sc520_freq_get_cpu_frequency(0);
+ freqs.new = sc520_freq_table[state].frequency;
+ freqs.cpu = 0; /* AMD Elan is UP */
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ dprintk("attempting to set frequency to %i kHz\n",
+ sc520_freq_table[state].frequency);
+
+ local_irq_disable();
+
+ clockspeed_reg = *cpuctl & ~0x03;
+ *cpuctl = clockspeed_reg | sc520_freq_table[state].index;
+
+ local_irq_enable();
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+};
+
+static int sc520_freq_verify (struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
+}
+
+static int sc520_freq_target (struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int newstate = 0;
+
+ if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate))
+ return -EINVAL;
+
+ sc520_freq_set_cpu_state(newstate);
+
+ return 0;
+}
+
+
+/*
+ * Module init and exit code
+ */
+
+static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
+{
+ struct cpuinfo_x86 *c = cpu_data;
+ int result;
+
+ /* capability check */
+ if (c->x86_vendor != X86_VENDOR_AMD ||
+ c->x86 != 4 || c->x86_model != 9)
+ return -ENODEV;
+
+ /* cpuinfo and default policy values */
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.transition_latency = 1000000; /* 1ms */
+ policy->cur = sc520_freq_get_cpu_frequency(0);
+
+ result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
+ if (result)
+ return (result);
+
+ cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
+
+ return 0;
+}
+
+
+static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+
+static struct freq_attr* sc520_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+
+static struct cpufreq_driver sc520_freq_driver = {
+ .get = sc520_freq_get_cpu_frequency,
+ .verify = sc520_freq_verify,
+ .target = sc520_freq_target,
+ .init = sc520_freq_cpu_init,
+ .exit = sc520_freq_cpu_exit,
+ .name = "sc520_freq",
+ .owner = THIS_MODULE,
+ .attr = sc520_freq_attr,
+};
+
+
+static int __init sc520_freq_init(void)
+{
+ struct cpuinfo_x86 *c = cpu_data;
+
+ /* Test if we have the right hardware */
+ if(c->x86_vendor != X86_VENDOR_AMD ||
+ c->x86 != 4 || c->x86_model != 9) {
+ dprintk("no Elan SC520 processor found!\n");
+ return -ENODEV;
+ }
+ cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
+ if(!cpuctl) {
+ printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
+ return -ENOMEM;
+ }
+
+ return cpufreq_register_driver(&sc520_freq_driver);
+}
+
+
+static void __exit sc520_freq_exit(void)
+{
+ cpufreq_unregister_driver(&sc520_freq_driver);
+ iounmap(cpuctl);
+}
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
+
+module_init(sc520_freq_init);
+module_exit(sc520_freq_exit);
+
CPU_DOTHAN_A1,
CPU_DOTHAN_A2,
CPU_DOTHAN_B0,
+ CPU_MP4HT_D0,
+ CPU_MP4HT_E0,
};
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]))
{ &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, }
};
if (!prev_speed)
return -EIO;
- dprintk("previous seped is %u\n", prev_speed);
+ dprintk("previous speed is %u\n", prev_speed);
local_irq_save(flags);
goto out;
}
- dprintk("low seped is %u\n", *low_speed);
+ dprintk("low speed is %u\n", *low_speed);
/* switch to high state */
set_state(SPEEDSTEP_HIGH);
goto out;
}
- dprintk("high seped is %u\n", *high_speed);
+ dprintk("high speed is %u\n", *high_speed);
if (*low_speed == *high_speed) {
ret = -ENODEV;
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;
}
};
#define MAX_CACHE_LEAVES 4
-static unsigned short __devinitdata num_cache_leaves;
+static unsigned short num_cache_leaves;
static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
{
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)
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)
{
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++) {
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/jiffies.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/timer.h>
#define CALIBRATE_TIME (5 * 1000020/HZ)
-unsigned long __init calibrate_tsc(void)
+unsigned long calibrate_tsc(void)
{
mach_prepare_counter();
#endif
/* calculate cpu_khz */
-void __init init_cpu_khz(void)
+void init_cpu_khz(void)
{
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
}
}
}
+
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;
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);
}
}
+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)
{
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.
*
addr < phys_to_virt(ISA_END_ADDRESS))
return;
- p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+ write_lock(&vmlist_lock);
+ p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
if (!p) {
- printk("__iounmap: bad address %p\n", addr);
- return;
+ printk("iounmap: bad address %p\n", addr);
+ goto out_unlock;
}
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);
}
#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)
+#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
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);
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;
}
#define INCLUDES
#include "compat_ioctl.c"
-#include <asm/ioctl32.h>
#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
{
struct epoll_event *events64 = NULL;
mm_segment_t old_fs = get_fs();
- int error, numevents, size;
+ int numevents, size;
int evt_idx;
int do_free_pages = 0;
;;
(pNonSys) mov out2=0 // out2==0 => not a syscall
.fframe 16
- .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
+ .spillsp ar.unat, 16
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
.body
adds out2=8,sp // out2=&sigscratch->ar_pfs
;;
.fframe 16
- .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
+ .spillsp ar.unat, 16
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
return IRQ_HANDLED;
}
-#endif /* CONFIG_ACPI */
-
/*
* ia64_mca_cpe_poll
*
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
*
register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
#ifdef CONFIG_ACPI
- /* Setup the CPEI/P vector and handler */
- cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
+ /* Setup the CPEI/P handler */
register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
#endif
#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;
(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \
(pKStk) ld8 r3 = [r3];; \
(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \
-(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
+(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \
;; \
(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; \
* Version Perfmon-2.x is a rewrite of perfmon-1.x
* by Stephane Eranian, Hewlett Packard Co.
*
- * Copyright (C) 1999-2003, 2005 Hewlett Packard Co
+ * Copyright (C) 1999-2005 Hewlett Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
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,};
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 */
error_conflict:
DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",
pfm_sessions.pfs_sys_session[cpu]->pid,
- smp_processor_id()));
+ cpu));
abort:
UNLOCK_PFS(flags);
int ret;
this_cpu = get_cpu();
- min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
- max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
+ if (likely(!pfm_alt_intr_handler)) {
+ min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
+ max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
- start_cycles = ia64_get_itc();
+ start_cycles = ia64_get_itc();
- ret = pfm_do_interrupt_handler(irq, arg, regs);
+ ret = pfm_do_interrupt_handler(irq, arg, regs);
- total_cycles = ia64_get_itc();
+ total_cycles = ia64_get_itc();
- /*
- * don't measure spurious interrupts
- */
- if (likely(ret == 0)) {
- total_cycles -= start_cycles;
+ /*
+ * don't measure spurious interrupts
+ */
+ if (likely(ret == 0)) {
+ total_cycles -= start_cycles;
- if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
- if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
+ if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
+ if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
- pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
+ pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
+ }
+ }
+ else {
+ (*pfm_alt_intr_handler->handler)(irq, arg, regs);
}
+
put_cpu_no_resched();
return IRQ_HANDLED;
}
.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
*/
unsigned long cfm)
{
struct unw_frame_info info, prev_info;
- unsigned long ip, pr;
+ unsigned long ip, sp, pr;
unw_init_from_blocked_task(&info, child);
while (1) {
prev_info = info;
if (unw_unwind(&info) < 0)
return;
- if (unw_get_rp(&info, &ip) < 0)
+
+ unw_get_sp(&info, &sp);
+ if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
+ < IA64_PT_REGS_SIZE) {
+ dprintk("ptrace.%s: ran off the top of the kernel "
+ "stack\n", __FUNCTION__);
+ return;
+ }
+ if (unw_get_pr (&prev_info, &pr) < 0) {
+ unw_get_rp(&prev_info, &ip);
+ dprintk("ptrace.%s: failed to read "
+ "predicate register (ip=0x%lx)\n",
+ __FUNCTION__, ip);
return;
- if (ip < FIXADDR_USER_END)
+ }
+ if (unw_is_intr_frame(&info)
+ && (pr & (1UL << PRED_USER_STACK)))
break;
}
__u16 thread_id;
__u16 proc_fixed_addr;
__u8 valid;
-}mt_info[NR_CPUS] __devinit;
+} mt_info[NR_CPUS] __devinitdata;
#ifdef CONFIG_HOTPLUG_CPU
static inline void
}
}
- /*
- * 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) {
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
*/
void default_idle(void)
{
- while(1) {
- if (need_resched())
- __asm__("stop #0x2000" : : : "cc");
- schedule();
+ local_irq_disable();
+ while (!need_resched()) {
+ /* This stop will re-enable interrupts */
+ __asm__("stop #0x2000" : : : "cc");
+ local_irq_disable();
}
+ local_irq_enable();
}
void (*idle)(void) = default_idle;
void cpu_idle(void)
{
/* endless idle loop with no priority at all */
- idle();
+ while (1) {
+ idle();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
}
void machine_restart(char * __unused)
/*
* pmu.c, Power Management Unit routines for NEC VR4100 series.
*
- * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/types.h>
#include <asm/reboot.h>
#include <asm/system.h>
-#define PMUCNT2REG KSEG1ADDR(0x0f0000c6)
+#define PMU_TYPE1_BASE 0x0b0000a0UL
+#define PMU_TYPE1_SIZE 0x0eUL
+
+#define PMU_TYPE2_BASE 0x0f0000c0UL
+#define PMU_TYPE2_SIZE 0x10UL
+
+#define PMUCNT2REG 0x06
#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 val;
+ uint16_t pmucnt2;
switch (current_cpu_data.cputype) {
case CPU_VR4122:
case CPU_VR4131:
case CPU_VR4133:
- val = readw(PMUCNT2REG);
- val |= SOFTRST;
- writew(val, PMUCNT2REG);
+ pmucnt2 = pmu_read(PMUCNT2REG);
+ pmucnt2 |= SOFTRST;
+ pmu_write(PMUCNT2REG, pmucnt2);
break;
default:
break;
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;
return 0;
}
-early_initcall(vr41xx_pmu_init);
+core_initcall(vr41xx_pmu_init);
config PCI_8260
bool
- depends on PCI && 8260 && !8272
+ depends on PCI && 8260
default y
config 8260_PCI9
bool " Enable workaround for MPC826x erratum PCI 9"
- depends on PCI_8260
+ depends on PCI_8260 && !ADS8272
default y
choice
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
$(call if_changed,uimage)
- @echo ' Image: $@' $(if $(wildcard $@),'is ready','not made')
+ @echo -n ' Image: $@ '
+ @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
# Files generated that shall be removed upon make clean
clean-files := sImage vmapus vmlinux* miboot* zImage* uImage
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc1
-# Thu Jan 20 01:25:35 2005
+# Linux kernel version: 2.6.12-rc4
+# Tue May 17 11:56:01 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC=y
CONFIG_PPC32=y
CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
#
# Code maturity level options
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
# 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
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
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
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
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
#
# Bus options
#
# CONFIG_PCCARD is not set
-#
-# PC-card bridges
-#
-
#
# Advanced setup
#
#
# ATA/ATAPI/MFM/RLL support
#
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
#
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
# 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
#
# 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
#
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
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
#
# I2C support
#
# 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
# 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
# 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
#
# 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
# Graphics support
#
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
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
# 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
#
# 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
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
tlbwe
/* 7. Jump to KERNELBASE mapping */
- li r7,0
+ lis r7,MSR_KERNEL@h
+ ori r7,r7,MSR_KERNEL@l
bl 1f /* Find our address */
1: mflr r9
rlwimi r6,r9,0,20,31
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.
*/
{
struct device_node *prom_stdout;
char *name;
- int offset;
+ int offset = 0;
if (of_stdout_device == NULL)
return -ENODEV;
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);
/* Early out if we are an invalid form of lswx */
if ((instword & INST_STRING_MASK) == INST_LSWX)
- if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB))
- return -EINVAL;
-
- /* Early out if we are an invalid form of lswi */
- if ((instword & INST_STRING_MASK) == INST_LSWI)
- if ((rA >= rT) || (rT == rA))
+ if ((rT == rA) || (rT == NB_RB))
return -EINVAL;
EA = (rA == 0) ? 0 : regs->gpr[rA];
#ifdef CONFIG_8xx
/* Don't use prefetch on 8xx */
mtctr r0
+ li r0,0
53: COPY_16_BYTES_WITHEX(0)
bdnz 53b
/* or write fault in cacheline loop */
105: li r9,1
92: li r3,LG_CACHELINE_BYTES
- b 99f
+ mfctr r8
+ add r0,r0,r8
+ b 106f
/* read fault in final word loop */
108: li r9,0
b 93f
* r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
*/
99: mfctr r0
- slw r3,r0,r3
+106: slw r3,r0,r3
add. r3,r3,r5
beq 120f /* shouldn't happen */
cmpwi 0,r9,0
if (!have_of)
FREESEC(openfirmware);
printk("\n");
+ ppc_md.progress = NULL;
#undef FREESEC
}
{
/* 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
#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