Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci-2.6.23
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci-2.6.23
Commits
12725675
Commit
12725675
authored
Jun 01, 2005
by
Steve French
Browse files
Options
Browse Files
Download
Plain Diff
Merge with
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
parents
af6f5e32
eff910a9
Changes
50
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
2118 additions
and
600 deletions
+2118
-600
Documentation/cpu-freq/cpufreq-stats.txt
Documentation/cpu-freq/cpufreq-stats.txt
+128
-0
MAINTAINERS
MAINTAINERS
+6
-0
arch/h8300/kernel/process.c
arch/h8300/kernel/process.c
+1
-1
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/Kconfig
+13
-1
arch/i386/kernel/cpu/cpufreq/Makefile
arch/i386/kernel/cpu/cpufreq/Makefile
+1
-0
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
+53
-5
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+8
-3
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+76
-37
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+15
-0
arch/i386/kernel/cpu/cpufreq/sc520_freq.c
arch/i386/kernel/cpu/cpufreq/sc520_freq.c
+186
-0
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+6
-0
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+3
-3
arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+3
-0
arch/i386/kernel/setup.c
arch/i386/kernel/setup.c
+2
-0
arch/i386/kernel/timers/common.c
arch/i386/kernel/timers/common.c
+4
-2
arch/i386/kernel/timers/timer_tsc.c
arch/i386/kernel/timers/timer_tsc.c
+20
-0
arch/ppc/syslib/prom_init.c
arch/ppc/syslib/prom_init.c
+10
-0
arch/ppc64/kernel/pSeries_reconfig.c
arch/ppc64/kernel/pSeries_reconfig.c
+0
-8
arch/ppc64/kernel/prom_init.c
arch/ppc64/kernel/prom_init.c
+9
-1
arch/ppc64/kernel/time.c
arch/ppc64/kernel/time.c
+0
-2
arch/x86_64/Kconfig
arch/x86_64/Kconfig
+1
-0
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/io_apic.c
+1
-0
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/mpparse.c
+1
-0
arch/x86_64/kernel/time.c
arch/x86_64/kernel/time.c
+2
-0
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig
+24
-0
drivers/cpufreq/Makefile
drivers/cpufreq/Makefile
+1
-0
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq.c
+4
-4
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_conservative.c
+586
-0
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_ondemand.c
+91
-89
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/cpufreq_stats.c
+30
-17
drivers/firmware/pcdp.c
drivers/firmware/pcdp.c
+1
-0
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali1563.c
+31
-15
drivers/ide/pci/amd74xx.c
drivers/ide/pci/amd74xx.c
+3
-0
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpci_hotplug_core.c
+138
-164
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/cpci_hotplug_pci.c
+54
-90
drivers/pci/hotplug/shpchprm_acpi.c
drivers/pci/hotplug/shpchprm_acpi.c
+2
-2
drivers/usb/host/Kconfig
drivers/usb/host/Kconfig
+11
-0
drivers/usb/host/Makefile
drivers/usb/host/Makefile
+1
-0
drivers/usb/host/sl811-hcd.c
drivers/usb/host/sl811-hcd.c
+81
-65
drivers/usb/host/sl811_cs.c
drivers/usb/host/sl811_cs.c
+442
-0
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.c
+3
-0
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ftdi_sio.h
+2
-0
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb-serial.c
+10
-10
fs/proc/proc_devtree.c
fs/proc/proc_devtree.c
+38
-67
fs/udf/udftime.c
fs/udf/udftime.c
+1
-1
include/asm-i386/timer.h
include/asm-i386/timer.h
+1
-0
include/asm-ppc64/prom.h
include/asm-ppc64/prom.h
+1
-12
include/linux/cpufreq.h
include/linux/cpufreq.h
+1
-1
include/linux/pci_ids.h
include/linux/pci_ids.h
+6
-0
kernel/module.c
kernel/module.c
+6
-0
No files found.
Documentation/cpu-freq/cpufreq-stats.txt
0 → 100644
View file @
12725675
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.
MAINTAINERS
View file @
12725675
...
...
@@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-usb.org/SpeedTouch/
S: Maintained
ALI1563 I2C DRIVER
P: Rudolf Marek
M: r.marek@sh.cvut.cz
L: sensors@stimpy.netroedge.com
S: Maintained
ALPHA PORT
P: Richard Henderson
M: rth@twiddle.net
...
...
arch/h8300/kernel/process.c
View file @
12725675
...
...
@@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void);
void
default_idle
(
void
)
{
while
(
1
)
{
if
(
need_resched
())
{
if
(
!
need_resched
())
{
local_irq_enable
();
__asm__
(
"sleep"
);
local_irq_disable
();
...
...
arch/i386/kernel/cpu/cpufreq/Kconfig
View file @
12725675
...
...
@@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
If in doubt, say N.
config ELAN_CPUFREQ
tristate "AMD Elan"
tristate "AMD Elan
SC400 and SC410
"
select CPU_FREQ_TABLE
depends on X86_ELAN
---help---
...
...
@@ -38,6 +38,18 @@ config ELAN_CPUFREQ
If in doubt, say N.
config SC520_CPUFREQ
tristate "AMD Elan SC520"
select CPU_FREQ_TABLE
depends on X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC520 processor.
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
select CPU_FREQ_TABLE
...
...
arch/i386/kernel/cpu/cpufreq/Makefile
View file @
12725675
...
...
@@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
obj-$(CONFIG_X86_POWERNOW_K8)
+=
powernow-k8.o
obj-$(CONFIG_X86_LONGHAUL)
+=
longhaul.o
obj-$(CONFIG_ELAN_CPUFREQ)
+=
elanfreq.o
obj-$(CONFIG_SC520_CPUFREQ)
+=
sc520_freq.o
obj-$(CONFIG_X86_LONGRUN)
+=
longrun.o
obj-$(CONFIG_X86_GX_SUSPMOD)
+=
gx-suspmod.o
obj-$(CONFIG_X86_SPEEDSTEP_ICH)
+=
speedstep-ich.o
...
...
arch/i386/kernel/cpu/cpufreq/longhaul.c
View file @
12725675
...
...
@@ -29,6 +29,7 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <asm/msr.h>
#include <asm/timex.h>
...
...
@@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
static
void
do_powersaver
(
union
msr_longhaul
*
longhaul
,
unsigned
int
clock_ratio_index
)
{
struct
pci_dev
*
dev
;
unsigned
long
flags
;
unsigned
int
tmp_mask
;
int
version
;
int
i
;
u16
pci_cmd
;
u16
cmd_state
[
64
];
switch
(
cpu_model
)
{
case
CPU_EZRA_T
:
...
...
@@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul,
longhaul
->
bits
.
SoftBusRatio4
=
(
clock_ratio_index
&
0x10
)
>>
4
;
longhaul
->
bits
.
EnableSoftBusRatio
=
1
;
longhaul
->
bits
.
RevisionKey
=
0
;
local_irq_disable
();
wrmsrl
(
MSR_VIA_LONGHAUL
,
longhaul
->
val
);
preempt_disable
();
local_irq_save
(
flags
);
/*
* get current pci bus master state for all devices
* and clear bus master bit
*/
dev
=
NULL
;
i
=
0
;
do
{
dev
=
pci_get_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
dev
);
if
(
dev
!=
NULL
)
{
pci_read_config_word
(
dev
,
PCI_COMMAND
,
&
pci_cmd
);
cmd_state
[
i
++
]
=
pci_cmd
;
pci_cmd
&=
~
PCI_COMMAND_MASTER
;
pci_write_config_word
(
dev
,
PCI_COMMAND
,
pci_cmd
);
}
}
while
(
dev
!=
NULL
);
tmp_mask
=
inb
(
0x21
);
/* works on C3. save mask. */
outb
(
0xFE
,
0x21
);
/* TMR0 only */
outb
(
0xFF
,
0x80
);
/* delay */
local_irq_enable
();
__hlt
();
wrmsrl
(
MSR_VIA_LONGHAUL
,
longhaul
->
val
);
__hlt
();
local_irq_disable
();
outb
(
tmp_mask
,
0x21
);
/* restore mask */
/* restore pci bus master state for all devices */
dev
=
NULL
;
i
=
0
;
do
{
dev
=
pci_get_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
dev
);
if
(
dev
!=
NULL
)
{
pci_cmd
=
cmd_state
[
i
++
];
pci_write_config_byte
(
dev
,
PCI_COMMAND
,
pci_cmd
);
}
}
while
(
dev
!=
NULL
);
local_irq_restore
(
flags
);
preempt_enable
();
/* disable bus ratio bit */
rdmsrl
(
MSR_VIA_LONGHAUL
,
longhaul
->
val
);
longhaul
->
bits
.
EnableSoftBusRatio
=
0
;
longhaul
->
bits
.
RevisionKey
=
version
;
local_irq_disable
();
wrmsrl
(
MSR_VIA_LONGHAUL
,
longhaul
->
val
);
local_irq_enable
();
}
/**
...
...
@@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
longhaul_setup_voltagescaling
();
policy
->
governor
=
CPUFREQ_DEFAULT_GOVERNOR
;
policy
->
cpuinfo
.
transition_latency
=
CPUFREQ_ETERNAL
;
policy
->
cpuinfo
.
transition_latency
=
200000
;
/* nsec */
policy
->
cur
=
calc_speed
(
longhaul_get_cpu_mult
());
ret
=
cpufreq_frequency_table_cpuinfo
(
policy
,
longhaul_table
);
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
View file @
12725675
...
...
@@ -23,6 +23,7 @@
#include <linux/dmi.h>
#include <asm/msr.h>
#include <asm/timer.h>
#include <asm/timex.h>
#include <asm/io.h>
#include <asm/system.h>
...
...
@@ -586,13 +587,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
rdmsrl
(
MSR_K7_FID_VID_STATUS
,
fidvidstatus
.
val
);
/* A K7 with powernow technology is set to max frequency by BIOS */
fsb
=
(
10
*
cpu_khz
)
/
fid_codes
[
fidvidstatus
.
bits
.
MFID
];
/* recalibrate cpu_khz */
result
=
recalibrate_cpu_khz
();
if
(
result
)
return
result
;
fsb
=
(
10
*
cpu_khz
)
/
fid_codes
[
fidvidstatus
.
bits
.
CFID
];
if
(
!
fsb
)
{
printk
(
KERN_WARNING
PFX
"can not determine bus frequency
\n
"
);
return
-
EINVAL
;
}
dprintk
(
"FSB: %3d
.%03d MHz
\n
"
,
fsb
/
1000
,
fsb
%
1000
);
dprintk
(
"FSB: %3d
MHz
\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
"
);
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
View file @
12725675
...
...
@@ -4,7 +4,7 @@
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
*
* Support :
paul.devriendt
@amd.com
* Support :
mark.langsdorf
@amd.com
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
...
...
@@ -15,12 +15,13 @@
*
* Valuable input gratefully received from Dave Jones, Pavel Machek,
* Dominik Brodowski, and others.
* Originally developed by Paul Devriendt.
* Processor information obtained from Chapter 9 (Power and Thermal Management)
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
* Opteron Processors" available for download from www.amd.com
*
* Tables for specific CPUs can be infrerred from
*
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
*
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
*/
#include <linux/kernel.h>
...
...
@@ -30,6 +31,7 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/cpumask.h>
#include <asm/msr.h>
#include <asm/io.h>
...
...
@@ -42,7 +44,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
#define VERSION "version 1.
00.09e
"
#define VERSION "version 1.
40.2
"
#include "powernow-k8.h"
/* serialize freq changes */
...
...
@@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem);
static
struct
powernow_k8_data
*
powernow_data
[
NR_CPUS
];
#ifndef CONFIG_SMP
static
cpumask_t
cpu_core_map
[
1
];
#endif
/* Return a frequency in MHz, given an input fid */
static
u32
find_freq_from_fid
(
u32
fid
)
{
...
...
@@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
{
u32
rvosteps
=
data
->
rvo
;
u32
savefid
=
data
->
currfid
;
u32
maxvid
,
lo
;
dprintk
(
"ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x
\n
"
,
smp_processor_id
(),
data
->
currfid
,
data
->
currvid
,
reqvid
,
data
->
rvo
);
rdmsr
(
MSR_FIDVID_STATUS
,
lo
,
maxvid
);
maxvid
=
0x1f
&
(
maxvid
>>
16
);
dprintk
(
"ph1 maxvid=0x%x
\n
"
,
maxvid
);
if
(
reqvid
<
maxvid
)
/* lower numbers are higher voltages */
reqvid
=
maxvid
;
while
(
data
->
currvid
>
reqvid
)
{
dprintk
(
"ph1: curr 0x%x, req vid 0x%x
\n
"
,
data
->
currvid
,
reqvid
);
...
...
@@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
return
1
;
}
while
((
rvosteps
>
0
)
&&
((
data
->
rvo
+
data
->
currvid
)
>
reqvid
))
{
if
(
data
->
currvid
==
0
)
{
while
((
rvosteps
>
0
)
&&
((
data
->
rvo
+
data
->
currvid
)
>
reqvid
))
{
if
(
data
->
currvid
==
maxvid
)
{
rvosteps
=
0
;
}
else
{
dprintk
(
"ph1: changing vid for rvo, req 0x%x
\n
"
,
...
...
@@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data)
* BIOS and Kernel Developer's Guide, which is available on
* www.amd.com
*/
printk
(
KERN_
ERR
PFX
"BIOS error - no PSB
\n
"
);
printk
(
KERN_
INFO
PFX
"BIOS error - no PSB or ACPI _PSS objects
\n
"
);
return
-
ENODEV
;
}
...
...
@@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
struct
cpufreq_frequency_table
*
powernow_table
;
if
(
acpi_processor_register_performance
(
&
data
->
acpi_data
,
data
->
cpu
))
{
dprintk
(
"register performance failed
\n
"
);
dprintk
(
"register performance failed
: bad ACPI data
\n
"
);
return
-
EIO
;
}
...
...
@@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
continue
;
}
if
(
fid
<
HI_FID_TABLE_BOTTOM
)
{
if
(
cntlofreq
)
{
/* if both entries are the same, ignore this
* one...
*/
if
((
powernow_table
[
i
].
frequency
!=
powernow_table
[
cntlofreq
].
frequency
)
||
(
powernow_table
[
i
].
index
!=
powernow_table
[
cntlofreq
].
index
))
{
printk
(
KERN_ERR
PFX
"Too many lo freq table entries
\n
"
);
goto
err_out_mem
;
}
dprintk
(
"double low frequency table entry, ignoring it.
\n
"
);
powernow_table
[
i
].
frequency
=
CPUFREQ_ENTRY_INVALID
;
continue
;
}
else
cntlofreq
=
i
;
/* verify only 1 entry from the lo frequency table */
if
(
fid
<
HI_FID_TABLE_BOTTOM
)
{
if
(
cntlofreq
)
{
/* if both entries are the same, ignore this
* one...
*/
if
((
powernow_table
[
i
].
frequency
!=
powernow_table
[
cntlofreq
].
frequency
)
||
(
powernow_table
[
i
].
index
!=
powernow_table
[
cntlofreq
].
index
))
{
printk
(
KERN_ERR
PFX
"Too many lo freq table entries
\n
"
);
goto
err_out_mem
;
}
dprintk
(
"double low frequency table entry, ignoring it.
\n
"
);
powernow_table
[
i
].
frequency
=
CPUFREQ_ENTRY_INVALID
;
continue
;
}
else
cntlofreq
=
i
;
}
if
(
powernow_table
[
i
].
frequency
!=
(
data
->
acpi_data
.
states
[
i
].
core_frequency
*
1000
))
{
...
...
@@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
{
u32
fid
;
u32
vid
;
int
res
;
int
res
,
i
;
struct
cpufreq_freqs
freqs
;
dprintk
(
"cpu %d transition to index %u
\n
"
,
smp_processor_id
(),
index
);
...
...
@@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
}
if
((
fid
<
HI_FID_TABLE_BOTTOM
)
&&
(
data
->
currfid
<
HI_FID_TABLE_BOTTOM
))
{
printk
(
"ignoring illegal change in lo freq table-%x to 0x%x
\n
"
,
printk
(
KERN_ERR
PFX
"ignoring illegal change in lo freq table-%x to 0x%x
\n
"
,
data
->
currfid
,
fid
);
return
1
;
}
...
...
@@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
smp_processor_id
(),
fid
,
vid
);
freqs
.
cpu
=
data
->
cpu
;
freqs
.
old
=
find_khz_freq_from_fid
(
data
->
currfid
);
freqs
.
new
=
find_khz_freq_from_fid
(
fid
);
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_PRECHANGE
);
for_each_cpu_mask
(
i
,
cpu_core_map
[
data
->
cpu
])
{
freqs
.
cpu
=
i
;
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_PRECHANGE
);
}
down
(
&
fidvid_sem
);
res
=
transition_fid_vid
(
data
,
fid
,
vid
);
up
(
&
fidvid_sem
);
freqs
.
new
=
find_khz_freq_from_fid
(
data
->
currfid
);
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_POSTCHANGE
);
for_each_cpu_mask
(
i
,
cpu_core_map
[
data
->
cpu
])
{
freqs
.
cpu
=
i
;
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_POSTCHANGE
);
}
return
res
;
}
...
...
@@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
u32
checkvid
=
data
->
currvid
;
unsigned
int
newstate
;
int
ret
=
-
EIO
;
int
i
;
/* only run on specific CPU from here on */
oldmask
=
current
->
cpus_allowed
;
...
...
@@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
data
->
currfid
,
data
->
currvid
);
if
((
checkvid
!=
data
->
currvid
)
||
(
checkfid
!=
data
->
currfid
))
{
printk
(
KERN_
ERR
PFX
"error - out of sync, fid
0x%x 0x%x, vid 0x%x 0x%x
\n
"
,
checkfid
,
data
->
currfid
,
checkvid
,
data
->
currvid
);
printk
(
KERN_
INFO
PFX
"error - out of sync, fix
0x%x 0x%x, vid 0x%x 0x%x
\n
"
,
checkfid
,
data
->
currfid
,
checkvid
,
data
->
currvid
);
}
if
(
cpufreq_frequency_table_target
(
pol
,
data
->
powernow_table
,
targfreq
,
relation
,
&
newstate
))
goto
err_out
;
down
(
&
fidvid_sem
);
for_each_cpu_mask
(
i
,
cpu_core_map
[
pol
->
cpu
])
{
/* make sure the sibling is initialized */
if
(
!
powernow_data
[
i
])
{
ret
=
0
;
up
(
&
fidvid_sem
);
goto
err_out
;
}
}
powernow_k8_acpi_pst_values
(
data
,
newstate
);
if
(
transition_frequency
(
data
,
newstate
))
{
printk
(
KERN_ERR
PFX
"transition frequency failed
\n
"
);
ret
=
1
;
up
(
&
fidvid_sem
);
goto
err_out
;
}
/* Update all the fid/vids of our siblings */
for_each_cpu_mask
(
i
,
cpu_core_map
[
pol
->
cpu
])
{
powernow_data
[
i
]
->
currvid
=
data
->
currvid
;
powernow_data
[
i
]
->
currfid
=
data
->
currfid
;
}
up
(
&
fidvid_sem
);
pol
->
cur
=
find_khz_freq_from_fid
(
data
->
currfid
);
ret
=
0
;
...
...
@@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
*/
if
((
num_online_cpus
()
!=
1
)
||
(
num_possible_cpus
()
!=
1
))
{
printk
(
KERN_
INFO
PFX
"MP systems not supported by PSB BIOS structure
\n
"
);
printk
(
KERN_
ERR
PFX
"MP systems not supported by PSB BIOS structure
\n
"
);
kfree
(
data
);
return
-
ENODEV
;
}
...
...
@@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
schedule
();
pol
->
governor
=
CPUFREQ_DEFAULT_GOVERNOR
;
pol
->
cpus
=
cpu_core_map
[
pol
->
cpu
];
/* Take a crude guess here.
* That guess was in microseconds, so multiply with 1000 */
...
...
@@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
return
0
;
}
preempt_disable
();
if
(
query_current_values_with_pending_wait
(
data
))
goto
out
;
...
...
@@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void)
cpufreq_unregister_driver
(
&
cpufreq_amd64_driver
);
}
MODULE_AUTHOR
(
"Paul Devriendt <paul.devriendt@amd.com>"
);
MODULE_AUTHOR
(
"Paul Devriendt <paul.devriendt@amd.com>
and Mark Langsdorf <mark.langsdorf@amd.com.
"
);
MODULE_DESCRIPTION
(
"AMD Athlon 64 and Opteron processor frequency driver."
);
MODULE_LICENSE
(
"GPL"
);
late_initcall
(
powernowk8_init
);
module_exit
(
powernowk8_exit
);
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
View file @
12725675
...
...
@@ -174,3 +174,18 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
static
int
core_frequency_transition
(
struct
powernow_k8_data
*
data
,
u32
reqfid
);
static
void
powernow_k8_acpi_pst_values
(
struct
powernow_k8_data
*
data
,
unsigned
int
index
);
#ifndef for_each_cpu_mask
#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
#endif
#ifdef CONFIG_SMP
static
inline
void
define_siblings
(
int
cpu
,
cpumask_t
cpu_sharedcore_mask
[])
{
}
#else
static
inline
void
define_siblings
(
int
cpu
,
cpumask_t
cpu_sharedcore_mask
[])
{
cpu_set
(
0
,
cpu_sharedcore_mask
[
0
]);
}
#endif
arch/i386/kernel/cpu/cpufreq/sc520_freq.c
0 → 100644
View file @
12725675
/*
* 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
);
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
View file @
12725675
...
...
@@ -54,6 +54,8 @@ enum {
CPU_DOTHAN_A1
,
CPU_DOTHAN_A2
,
CPU_DOTHAN_B0
,
CPU_MP4HT_D0
,
CPU_MP4HT_E0
,
};
static
const
struct
cpu_id
cpu_ids
[]
=
{
...
...
@@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = {
[
CPU_DOTHAN_A1
]
=
{
6
,
13
,
1
},
[
CPU_DOTHAN_A2
]
=
{
6
,
13
,
2
},
[
CPU_DOTHAN_B0
]
=
{
6
,
13
,
6
},
[
CPU_MP4HT_D0
]
=
{
15
,
3
,
4
},
[
CPU_MP4HT_E0
]
=
{
15
,
4
,
1
},
};
#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
...
...
@@ -226,6 +230,8 @@ static struct cpu_model models[] =
{
&
cpu_ids
[
CPU_DOTHAN_A1
],
NULL
,
0
,
NULL
},
{
&
cpu_ids
[
CPU_DOTHAN_A2
],
NULL
,
0
,
NULL
},
{
&
cpu_ids
[
CPU_DOTHAN_B0
],
NULL
,
0
,
NULL
},
{
&
cpu_ids
[
CPU_MP4HT_D0
],
NULL
,
0
,
NULL
},
{
&
cpu_ids
[
CPU_MP4HT_E0
],
NULL
,
0
,
NULL
},
{
NULL
,
}
};
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
View file @
12725675
...
...
@@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
if
(
!
prev_speed
)
return
-
EIO
;
dprintk
(
"previous s
ep
ed is %u
\n
"
,
prev_speed
);
dprintk
(
"previous s
pe
ed is %u
\n
"
,
prev_speed
);
local_irq_save
(
flags
);
...
...
@@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
goto
out
;
}
dprintk
(
"low s
ep
ed is %u
\n
"
,
*
low_speed
);
dprintk
(
"low s
pe
ed is %u
\n
"
,
*
low_speed
);
/* switch to high state */
set_state
(
SPEEDSTEP_HIGH
);
...
...
@@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
goto
out
;
}
dprintk
(
"high s
ep
ed is %u
\n
"
,
*
high_speed
);
dprintk
(
"high s
pe
ed is %u
\n
"
,
*
high_speed
);
if
(
*
low_speed
==
*
high_speed
)
{
ret
=
-
ENODEV
;
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
View file @
12725675
...
...
@@ -357,6 +357,9 @@ static int __init speedstep_init(void)
case
SPEEDSTEP_PROCESSOR_PIII_C
:
case
SPEEDSTEP_PROCESSOR_PIII_C_EARLY
:
break
;
case
SPEEDSTEP_PROCESSOR_P4M
:
printk
(
KERN_INFO
"speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.
\n
"
);
break
;
default:
speedstep_processor
=
0
;
}
...
...
arch/i386/kernel/setup.c
View file @
12725675
...
...
@@ -1502,11 +1502,13 @@ void __init setup_arch(char **cmdline_p)
if
(
efi_enabled
)
efi_map_memmap
();
#ifdef CONFIG_ACPI_BOOT
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
acpi_boot_table_init
();
acpi_boot_init
();
#endif
#ifdef CONFIG_X86_LOCAL_APIC
if
(
smp_found_config
)
...
...
arch/i386/kernel/timers/common.c
View file @
12725675
...
...
@@ -6,6 +6,7 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/timer.h>
...
...
@@ -24,7 +25,7 @@
#define CALIBRATE_TIME (5 * 1000020/HZ)
unsigned
long
__init
calibrate_tsc
(
void
)
unsigned
long
calibrate_tsc
(
void
)
{
mach_prepare_counter
();
...
...
@@ -139,7 +140,7 @@ bad_calibration:
#endif
/* calculate cpu_khz */
void
__init
init_cpu_khz
(
void
)
void
init_cpu_khz
(
void
)
{
if
(
cpu_has_tsc
)
{
unsigned
long
tsc_quotient
=
calibrate_tsc
();
...
...
@@ -158,3 +159,4 @@ void __init init_cpu_khz(void)
}
}
}
arch/i386/kernel/timers/timer_tsc.c
View file @
12725675
...
...
@@ -320,6 +320,26 @@ core_initcall(cpufreq_tsc);
static
inline
void
cpufreq_delayed_get
(
void
)
{
return
;
}
#endif
int
recalibrate_cpu_khz
(
void
)
{
#ifndef CONFIG_SMP
unsigned
long
cpu_khz_old
=
cpu_khz
;
if
(
cpu_has_tsc
)
{
init_cpu_khz
();
cpu_data
[
0
].
loops_per_jiffy
=
cpufreq_scale
(
cpu_data
[
0
].
loops_per_jiffy
,
cpu_khz_old
,
cpu_khz
);
return
0
;
}
else
return
-
ENODEV
;
#else
return
-
ENODEV
;
#endif
}
EXPORT_SYMBOL
(
recalibrate_cpu_khz
);
static
void
mark_offset_tsc
(
void
)
{
unsigned
long
lost
,
delay
;
...
...
arch/ppc/syslib/prom_init.c
View file @
12725675
...
...
@@ -626,8 +626,18 @@ inspect_node(phandle node, struct device_node *dad,
l
=
call_prom
(
"package-to-path"
,
3
,
1
,
node
,
mem_start
,
mem_end
-
mem_start
);
if
(
l
>=
0
)
{
char
*
p
,
*
ep
;
np
->
full_name
=
PTRUNRELOC
((
char
*
)
mem_start
);
*
(
char
*
)(
mem_start
+
l
)
=
0
;
/* Fixup an Apple bug where they have bogus \0 chars in the
* middle of the path in some properties
*/
for
(
p
=
(
char
*
)
mem_start
,
ep
=
p
+
l
;
p
<
ep
;
p
++
)
if
((
*
p
)
==
'\0'
)
{
memmove
(
p
,
p
+
1
,
ep
-
p
);
ep
--
;
}
mem_start
=
ALIGNUL
(
mem_start
+
l
+
1
);
}
...
...
arch/ppc64/kernel/pSeries_reconfig.c
View file @
12725675
...
...
@@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np)
remove_proc_entry
(
pp
->
name
,
np
->
pde
);
pp
=
pp
->
next
;
}
/* Assuming that symlinks have the same parent directory as
* np->pde.
*/
if
(
np
->
name_link
)
remove_proc_entry
(
np
->
name_link
->
name
,
parent
->
pde
);
if
(
np
->
addr_link
)
remove_proc_entry
(
np
->
addr_link
->
name
,
parent
->
pde
);
if
(
np
->
pde
)
remove_proc_entry
(
np
->
pde
->
name
,
parent
->
pde
);
}
...
...
arch/ppc64/kernel/prom_init.c
View file @
12725675
...
...
@@ -1566,7 +1566,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
{
int
l
,
align
;
phandle
child
;
char
*
namep
,
*
prev_name
,
*
sstart
;
char
*
namep
,
*
prev_name
,
*
sstart
,
*
p
,
*
ep
;
unsigned
long
soff
;
unsigned
char
*
valp
;
unsigned
long
offset
=
reloc_offset
();
...
...
@@ -1588,6 +1588,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
call_prom
(
"package-to-path"
,
3
,
1
,
node
,
namep
,
l
);
}
namep
[
l
]
=
'\0'
;
/* Fixup an Apple bug where they have bogus \0 chars in the
* middle of the path in some properties
*/
for
(
p
=
namep
,
ep
=
namep
+
l
;
p
<
ep
;
p
++
)
if
(
*
p
==
'\0'
)
{
memmove
(
p
,
p
+
1
,
ep
-
p
);
ep
--
;
l
--
;
}
*
mem_start
=
_ALIGN
(((
unsigned
long
)
namep
)
+
strlen
(
namep
)
+
1
,
4
);
}
...
...
arch/ppc64/kernel/time.c
View file @
12725675
...
...
@@ -325,9 +325,7 @@ int timer_interrupt(struct pt_regs * regs)
irq_enter
();
#ifndef CONFIG_PPC_ISERIES
profile_tick
(
CPU_PROFILING
,
regs
);
#endif
lpaca
->
lppaca
.
int_dword
.
fields
.
decr_int
=
0
;
...
...
arch/x86_64/Kconfig
View file @
12725675
...
...
@@ -305,6 +305,7 @@ config HPET_TIMER
config X86_PM_TIMER
bool "PM timer"
depends on ACPI
default y
help
Support the ACPI PM timer for time keeping. This is slow,
...
...
arch/x86_64/kernel/io_apic.c
View file @
12725675
...
...
@@ -37,6 +37,7 @@
#include <asm/desc.h>
#include <asm/proto.h>
#include <asm/mach_apic.h>
#include <asm/acpi.h>
#define __apicdebuginit __init
...
...
arch/x86_64/kernel/mpparse.c
View file @
12725675
...
...
@@ -30,6 +30,7 @@
#include <asm/pgalloc.h>
#include <asm/io_apic.h>
#include <asm/proto.h>
#include <asm/acpi.h>
/* Have we found an MP table */
int
smp_found_config
;
...
...
arch/x86_64/kernel/time.c
View file @
12725675
...
...
@@ -27,7 +27,9 @@
#include <linux/bcd.h>
#include <linux/kallsyms.h>
#include <linux/acpi.h>
#ifdef CONFIG_ACPI
#include <acpi/achware.h>
/* for PM timer frequency */
#endif
#include <asm/8253pit.h>
#include <asm/pgtable.h>
#include <asm/vsyscall.h>
...
...
drivers/cpufreq/Kconfig
View file @
12725675
...
...
@@ -46,6 +46,10 @@ config CPU_FREQ_STAT_DETAILS
This will show detail CPU frequency translation table in sysfs file
system
# Note that it is not currently possible to set the other governors (such as ondemand)
# as the default, since if they fail to initialise, cpufreq will be
# left in an undefined state.
choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
...
...
@@ -115,4 +119,24 @@ config CPU_FREQ_GOV_ONDEMAND
If in doubt, say N.
config CPU_FREQ_GOV_CONSERVATIVE
tristate "'conservative' cpufreq governor"
depends on CPU_FREQ
help
'conservative' - this driver is rather similar to the 'ondemand'
governor both in its source code and its purpose, the difference is
its optimisation for better suitability in a battery powered
environment. The frequency is gracefully increased and decreased
rather than jumping to 100% when speed is required.
If you have a desktop machine then you should really be considering
the 'ondemand' governor instead, however if you are using a laptop,
PDA or even an AMD64 based computer (due to the unacceptable
step-by-step latency issues between the minimum and maximum frequency
transitions in the CPU) you will probably want to use this governor.
For details, take a look at linux/Documentation/cpu-freq.
If in doubt, say N.
endif # CPU_FREQ
drivers/cpufreq/Makefile
View file @
12725675
...
...
@@ -8,6 +8,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)
+=
cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)
+=
cpufreq_userspace.o
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)
+=
cpufreq_ondemand.o
obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)
+=
cpufreq_conservative.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE)
+=
freq_table.o
...
...
drivers/cpufreq/cpufreq.c
View file @
12725675
...
...
@@ -258,7 +258,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
(
likely
(
cpufreq_cpu_data
[
freqs
->
cpu
]
->
cur
))
&&
(
unlikely
(
freqs
->
old
!=
cpufreq_cpu_data
[
freqs
->
cpu
]
->
cur
)))
{
printk
(
KERN_WARNING
"Warning: CPU frequency is %u, "
d
printk
(
KERN_WARNING
"Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.
\n
"
,
freqs
->
old
,
cpufreq_cpu_data
[
freqs
->
cpu
]
->
cur
);
freqs
->
old
=
cpufreq_cpu_data
[
freqs
->
cpu
]
->
cur
;
}
...
...
@@ -814,7 +814,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
{
struct
cpufreq_freqs
freqs
;
printk
(
KERN_WARNING
"Warning: CPU frequency out of sync: cpufreq and timing "
d
printk
(
KERN_WARNING
"Warning: CPU frequency out of sync: cpufreq and timing "
"core thinks of %u, is %u kHz.
\n
"
,
old_freq
,
new_freq
);
freqs
.
cpu
=
cpu
;
...
...
@@ -923,7 +923,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, u32 state)
struct
cpufreq_freqs
freqs
;
if
(
!
(
cpufreq_driver
->
flags
&
CPUFREQ_PM_NO_WARN
))
printk
(
KERN_DEBUG
"Warning: CPU frequency is %u, "
d
printk
(
KERN_DEBUG
"Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.
\n
"
,
cur_freq
,
cpu_policy
->
cur
);
...
...
@@ -1004,7 +1004,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
struct
cpufreq_freqs
freqs
;
if
(
!
(
cpufreq_driver
->
flags
&
CPUFREQ_PM_NO_WARN
))
printk
(
KERN_WARNING
"Warning: CPU frequency"
d
printk
(
KERN_WARNING
"Warning: CPU frequency"
"is %u, cpufreq assumed %u kHz.
\n
"
,
cur_freq
,
cpu_policy
->
cur
);
...
...
drivers/cpufreq/cpufreq_conservative.c
0 → 100644
View file @
12725675
/*
* drivers/cpufreq/cpufreq_conservative.c
*
* Copyright (C) 2001 Russell King
* (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
* Jun Nakajima <jun.nakajima@intel.com>
* (C) 2004 Alexander Clouter <alex-kernel@digriz.org.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ctype.h>
#include <linux/cpufreq.h>
#include <linux/sysctl.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/sched.h>
#include <linux/kmod.h>
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <linux/kernel_stat.h>
#include <linux/percpu.h>
/*
* dbs is used in this file as a shortform for demandbased switching
* It helps to keep variable names smaller, simpler
*/
#define DEF_FREQUENCY_UP_THRESHOLD (80)
#define MIN_FREQUENCY_UP_THRESHOLD (0)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
/*
* The polling frequency of this governor depends on the capability of
* the processor. Default polling frequency is 1000 times the transition
* latency of the processor. The governor will work on any processor with
* transition latency <= 10mS, using appropriate sampling
* rate.
* For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
* this governor will not work.
* All times here are in uS.
*/
static
unsigned
int
def_sampling_rate
;
#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000)
#define DEF_SAMPLING_DOWN_FACTOR (5)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
static
void
do_dbs_timer
(
void
*
data
);
struct
cpu_dbs_info_s
{
struct
cpufreq_policy
*
cur_policy
;
unsigned
int
prev_cpu_idle_up
;
unsigned
int
prev_cpu_idle_down
;
unsigned
int
enable
;
};
static
DEFINE_PER_CPU
(
struct
cpu_dbs_info_s
,
cpu_dbs_info
);
static
unsigned
int
dbs_enable
;
/* number of CPUs using this policy */
static
DECLARE_MUTEX
(
dbs_sem
);
static
DECLARE_WORK
(
dbs_work
,
do_dbs_timer
,
NULL
);
struct
dbs_tuners
{
unsigned
int
sampling_rate
;
unsigned
int
sampling_down_factor
;
unsigned
int
up_threshold
;
unsigned
int
down_threshold
;
unsigned
int
ignore_nice
;
unsigned
int
freq_step
;
};
static
struct
dbs_tuners
dbs_tuners_ins
=
{
.
up_threshold
=
DEF_FREQUENCY_UP_THRESHOLD
,
.
down_threshold
=
DEF_FREQUENCY_DOWN_THRESHOLD
,
.
sampling_down_factor
=
DEF_SAMPLING_DOWN_FACTOR
,
};
static
inline
unsigned
int
get_cpu_idle_time
(
unsigned
int
cpu
)
{
return
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
+
(
!
dbs_tuners_ins
.
ignore_nice
?
kstat_cpu
(
cpu
).
cpustat
.
nice
:
0
);
}
/************************** sysfs interface ************************/
static
ssize_t
show_sampling_rate_max
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
return
sprintf
(
buf
,
"%u
\n
"
,
MAX_SAMPLING_RATE
);
}
static
ssize_t
show_sampling_rate_min
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
return
sprintf
(
buf
,
"%u
\n
"
,
MIN_SAMPLING_RATE
);
}
#define define_one_ro(_name) \
static struct freq_attr _name = \
__ATTR(_name, 0444, show_##_name, NULL)
define_one_ro
(
sampling_rate_max
);
define_one_ro
(
sampling_rate_min
);
/* cpufreq_conservative Governor Tunables */
#define show_one(file_name, object) \
static ssize_t show_##file_name \
(struct cpufreq_policy *unused, char *buf) \
{ \
return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
}
show_one
(
sampling_rate
,
sampling_rate
);
show_one
(
sampling_down_factor
,
sampling_down_factor
);
show_one
(
up_threshold
,
up_threshold
);
show_one
(
down_threshold
,
down_threshold
);
show_one
(
ignore_nice
,
ignore_nice
);
show_one
(
freq_step
,
freq_step
);
static
ssize_t
store_sampling_down_factor
(
struct
cpufreq_policy
*
unused
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
down
(
&
dbs_sem
);
dbs_tuners_ins
.
sampling_down_factor
=
input
;
up
(
&
dbs_sem
);
return
count
;
}
static
ssize_t
store_sampling_rate
(
struct
cpufreq_policy
*
unused
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
down
(
&
dbs_sem
);
if
(
ret
!=
1
||
input
>
MAX_SAMPLING_RATE
||
input
<
MIN_SAMPLING_RATE
)
{
up
(
&
dbs_sem
);
return
-
EINVAL
;
}
dbs_tuners_ins
.
sampling_rate
=
input
;
up
(
&
dbs_sem
);
return
count
;
}
static
ssize_t
store_up_threshold
(
struct
cpufreq_policy
*
unused
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
down
(
&
dbs_sem
);
if
(
ret
!=
1
||
input
>
MAX_FREQUENCY_UP_THRESHOLD
||
input
<
MIN_FREQUENCY_UP_THRESHOLD
||
input
<=
dbs_tuners_ins
.
down_threshold
)
{
up
(
&
dbs_sem
);
return
-
EINVAL
;
}
dbs_tuners_ins
.
up_threshold
=
input
;
up
(
&
dbs_sem
);
return
count
;
}
static
ssize_t
store_down_threshold
(
struct
cpufreq_policy
*
unused
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
down
(
&
dbs_sem
);
if
(
ret
!=
1
||
input
>
MAX_FREQUENCY_DOWN_THRESHOLD
||
input
<
MIN_FREQUENCY_DOWN_THRESHOLD
||
input
>=
dbs_tuners_ins
.
up_threshold
)
{
up
(
&
dbs_sem
);
return
-
EINVAL
;
}
dbs_tuners_ins
.
down_threshold
=
input
;
up
(
&
dbs_sem
);
return
count
;
}
static
ssize_t
store_ignore_nice
(
struct
cpufreq_policy
*
policy
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
unsigned
int
j
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
if
(
input
>
1
)
input
=
1
;
down
(
&
dbs_sem
);
if
(
input
==
dbs_tuners_ins
.
ignore_nice
)
{
/* nothing to do */
up
(
&
dbs_sem
);
return
count
;
}
dbs_tuners_ins
.
ignore_nice
=
input
;
/* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
for_each_online_cpu
(
j
)
{
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
prev_cpu_idle_up
=
get_cpu_idle_time
(
j
);
j_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_up
;
}
up
(
&
dbs_sem
);
return
count
;
}
static
ssize_t
store_freq_step
(
struct
cpufreq_policy
*
policy
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
if
(
input
>
100
)
input
=
100
;
/* no need to test here if freq_step is zero as the user might actually
* want this, they would be crazy though :) */
down
(
&
dbs_sem
);
dbs_tuners_ins
.
freq_step
=
input
;
up
(
&
dbs_sem
);
return
count
;
}
#define define_one_rw(_name) \
static struct freq_attr _name = \
__ATTR(_name, 0644, show_##_name, store_##_name)
define_one_rw
(
sampling_rate
);
define_one_rw
(
sampling_down_factor
);
define_one_rw
(
up_threshold
);
define_one_rw
(
down_threshold
);
define_one_rw
(
ignore_nice
);
define_one_rw
(
freq_step
);
static
struct
attribute
*
dbs_attributes
[]
=
{
&
sampling_rate_max
.
attr
,
&
sampling_rate_min
.
attr
,
&
sampling_rate
.
attr
,
&
sampling_down_factor
.
attr
,
&
up_threshold
.
attr
,
&
down_threshold
.
attr
,
&
ignore_nice
.
attr
,
&
freq_step
.
attr
,
NULL
};
static
struct
attribute_group
dbs_attr_group
=
{
.
attrs
=
dbs_attributes
,
.
name
=
"conservative"
,
};
/************************** sysfs end ************************/
static
void
dbs_check_cpu
(
int
cpu
)
{
unsigned
int
idle_ticks
,
up_idle_ticks
,
down_idle_ticks
;
unsigned
int
freq_step
;
unsigned
int
freq_down_sampling_rate
;
static
int
down_skip
[
NR_CPUS
];
static
int
requested_freq
[
NR_CPUS
];
static
unsigned
short
init_flag
=
0
;
struct
cpu_dbs_info_s
*
this_dbs_info
;
struct
cpu_dbs_info_s
*
dbs_info
;
struct
cpufreq_policy
*
policy
;
unsigned
int
j
;
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
if
(
!
this_dbs_info
->
enable
)
return
;
policy
=
this_dbs_info
->
cur_policy
;
if
(
init_flag
==
0
)
{
for
(
/* NULL */
;
init_flag
<
NR_CPUS
;
init_flag
++
)
{
dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
init_flag
);
requested_freq
[
cpu
]
=
dbs_info
->
cur_policy
->
cur
;
}
init_flag
=
1
;
}
/*
* The default safe range is 20% to 80%
* Every sampling_rate, we check
* - If current idle time is less than 20%, then we try to
* increase frequency
* Every sampling_rate*sampling_down_factor, we check
* - If current idle time is more than 80%, then we try to
* decrease frequency
*
* Any frequency increase takes it to the maximum frequency.
* Frequency reduction happens at minimum steps of
* 5% (default) of max_frequency
*/
/* Check for frequency increase */
idle_ticks
=
UINT_MAX
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
unsigned
int
tmp_idle_ticks
,
total_idle_ticks
;
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
/* Check for frequency increase */
total_idle_ticks
=
get_cpu_idle_time
(
j
);
tmp_idle_ticks
=
total_idle_ticks
-
j_dbs_info
->
prev_cpu_idle_up
;
j_dbs_info
->
prev_cpu_idle_up
=
total_idle_ticks
;
if
(
tmp_idle_ticks
<
idle_ticks
)
idle_ticks
=
tmp_idle_ticks
;
}
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks
*=
100
;
up_idle_ticks
=
(
100
-
dbs_tuners_ins
.
up_threshold
)
*
usecs_to_jiffies
(
dbs_tuners_ins
.
sampling_rate
);
if
(
idle_ticks
<
up_idle_ticks
)
{
down_skip
[
cpu
]
=
0
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_up
;
}
/* if we are already at full speed then break out early */
if
(
requested_freq
[
cpu
]
==
policy
->
max
)
return
;
freq_step
=
(
dbs_tuners_ins
.
freq_step
*
policy
->
max
)
/
100
;
/* max freq cannot be less than 100. But who knows.... */
if
(
unlikely
(
freq_step
==
0
))
freq_step
=
5
;
requested_freq
[
cpu
]
+=
freq_step
;
if
(
requested_freq
[
cpu
]
>
policy
->
max
)
requested_freq
[
cpu
]
=
policy
->
max
;
__cpufreq_driver_target
(
policy
,
requested_freq
[
cpu
],
CPUFREQ_RELATION_H
);
return
;
}
/* Check for frequency decrease */
down_skip
[
cpu
]
++
;
if
(
down_skip
[
cpu
]
<
dbs_tuners_ins
.
sampling_down_factor
)
return
;
idle_ticks
=
UINT_MAX
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
unsigned
int
tmp_idle_ticks
,
total_idle_ticks
;
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
total_idle_ticks
=
j_dbs_info
->
prev_cpu_idle_up
;
tmp_idle_ticks
=
total_idle_ticks
-
j_dbs_info
->
prev_cpu_idle_down
;
j_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
if
(
tmp_idle_ticks
<
idle_ticks
)
idle_ticks
=
tmp_idle_ticks
;
}
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks
*=
100
;
down_skip
[
cpu
]
=
0
;
freq_down_sampling_rate
=
dbs_tuners_ins
.
sampling_rate
*
dbs_tuners_ins
.
sampling_down_factor
;
down_idle_ticks
=
(
100
-
dbs_tuners_ins
.
down_threshold
)
*
usecs_to_jiffies
(
freq_down_sampling_rate
);
if
(
idle_ticks
>
down_idle_ticks
)
{
/* if we are already at the lowest speed then break out early
* or if we 'cannot' reduce the speed as the user might want
* freq_step to be zero */
if
(
requested_freq
[
cpu
]
==
policy
->
min
||
dbs_tuners_ins
.
freq_step
==
0
)
return
;
freq_step
=
(
dbs_tuners_ins
.
freq_step
*
policy
->
max
)
/
100
;
/* max freq cannot be less than 100. But who knows.... */
if
(
unlikely
(
freq_step
==
0
))
freq_step
=
5
;
requested_freq
[
cpu
]
-=
freq_step
;
if
(
requested_freq
[
cpu
]
<
policy
->
min
)
requested_freq
[
cpu
]
=
policy
->
min
;
__cpufreq_driver_target
(
policy
,
requested_freq
[
cpu
],
CPUFREQ_RELATION_H
);
return
;
}
}
static
void
do_dbs_timer
(
void
*
data
)
{
int
i
;
down
(
&
dbs_sem
);
for_each_online_cpu
(
i
)
dbs_check_cpu
(
i
);
schedule_delayed_work
(
&
dbs_work
,
usecs_to_jiffies
(
dbs_tuners_ins
.
sampling_rate
));
up
(
&
dbs_sem
);
}
static
inline
void
dbs_timer_init
(
void
)
{
INIT_WORK
(
&
dbs_work
,
do_dbs_timer
,
NULL
);
schedule_delayed_work
(
&
dbs_work
,
usecs_to_jiffies
(
dbs_tuners_ins
.
sampling_rate
));
return
;
}
static
inline
void
dbs_timer_exit
(
void
)
{
cancel_delayed_work
(
&
dbs_work
);
return
;
}
static
int
cpufreq_governor_dbs
(
struct
cpufreq_policy
*
policy
,
unsigned
int
event
)
{
unsigned
int
cpu
=
policy
->
cpu
;
struct
cpu_dbs_info_s
*
this_dbs_info
;
unsigned
int
j
;
this_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
cpu
);
switch
(
event
)
{
case
CPUFREQ_GOV_START
:
if
((
!
cpu_online
(
cpu
))
||
(
!
policy
->
cur
))
return
-
EINVAL
;
if
(
policy
->
cpuinfo
.
transition_latency
>
(
TRANSITION_LATENCY_LIMIT
*
1000
))
return
-
EINVAL
;
if
(
this_dbs_info
->
enable
)
/* Already enabled */
break
;
down
(
&
dbs_sem
);
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
cur_policy
=
policy
;
j_dbs_info
->
prev_cpu_idle_up
=
get_cpu_idle_time
(
j
);
j_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_up
;
}
this_dbs_info
->
enable
=
1
;
sysfs_create_group
(
&
policy
->
kobj
,
&
dbs_attr_group
);
dbs_enable
++
;
/*
* Start the timerschedule work, when this governor
* is used for first time
*/
if
(
dbs_enable
==
1
)
{
unsigned
int
latency
;
/* policy latency is in nS. Convert it to uS first */
latency
=
policy
->
cpuinfo
.
transition_latency
;
if
(
latency
<
1000
)
latency
=
1000
;
def_sampling_rate
=
(
latency
/
1000
)
*
DEF_SAMPLING_RATE_LATENCY_MULTIPLIER
;
dbs_tuners_ins
.
sampling_rate
=
def_sampling_rate
;
dbs_tuners_ins
.
ignore_nice
=
0
;
dbs_tuners_ins
.
freq_step
=
5
;
dbs_timer_init
();
}
up
(
&
dbs_sem
);
break
;
case
CPUFREQ_GOV_STOP
:
down
(
&
dbs_sem
);
this_dbs_info
->
enable
=
0
;
sysfs_remove_group
(
&
policy
->
kobj
,
&
dbs_attr_group
);
dbs_enable
--
;
/*
* Stop the timerschedule work, when this governor
* is used for first time
*/
if
(
dbs_enable
==
0
)
dbs_timer_exit
();
up
(
&
dbs_sem
);
break
;
case
CPUFREQ_GOV_LIMITS
:
down
(
&
dbs_sem
);
if
(
policy
->
max
<
this_dbs_info
->
cur_policy
->
cur
)
__cpufreq_driver_target
(
this_dbs_info
->
cur_policy
,
policy
->
max
,
CPUFREQ_RELATION_H
);
else
if
(
policy
->
min
>
this_dbs_info
->
cur_policy
->
cur
)
__cpufreq_driver_target
(
this_dbs_info
->
cur_policy
,
policy
->
min
,
CPUFREQ_RELATION_L
);
up
(
&
dbs_sem
);
break
;
}
return
0
;
}
static
struct
cpufreq_governor
cpufreq_gov_dbs
=
{
.
name
=
"conservative"
,
.
governor
=
cpufreq_governor_dbs
,
.
owner
=
THIS_MODULE
,
};
static
int
__init
cpufreq_gov_dbs_init
(
void
)
{
return
cpufreq_register_governor
(
&
cpufreq_gov_dbs
);
}
static
void
__exit
cpufreq_gov_dbs_exit
(
void
)
{
/* Make sure that the scheduled work is indeed not running */
flush_scheduled_work
();
cpufreq_unregister_governor
(
&
cpufreq_gov_dbs
);
}
MODULE_AUTHOR
(
"Alexander Clouter <alex-kernel@digriz.org.uk>"
);
MODULE_DESCRIPTION
(
"'cpufreq_conservative' - A dynamic cpufreq governor for "
"Low Latency Frequency Transition capable processors "
"optimised for use in a battery environment"
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
cpufreq_gov_dbs_init
);
module_exit
(
cpufreq_gov_dbs_exit
);
drivers/cpufreq/cpufreq_ondemand.c
View file @
12725675
...
...
@@ -34,13 +34,9 @@
*/
#define DEF_FREQUENCY_UP_THRESHOLD (80)
#define MIN_FREQUENCY_UP_THRESHOLD (
0
)
#define MIN_FREQUENCY_UP_THRESHOLD (
11
)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
/*
* The polling frequency of this governor depends on the capability of
* the processor. Default polling frequency is 1000 times the transition
...
...
@@ -55,9 +51,9 @@ static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
#define DEF_SAMPLING_DOWN_FACTOR (10)
#define DEF_SAMPLING_DOWN_FACTOR (1)
#define MAX_SAMPLING_DOWN_FACTOR (10)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
#define sampling_rate_in_HZ(x) (((x * HZ) < (1000 * 1000))?1:((x * HZ) / (1000 * 1000)))
static
void
do_dbs_timer
(
void
*
data
);
...
...
@@ -78,15 +74,23 @@ struct dbs_tuners {
unsigned
int
sampling_rate
;
unsigned
int
sampling_down_factor
;
unsigned
int
up_threshold
;
unsigned
int
down_threshold
;
unsigned
int
ignore_nice
;
};
static
struct
dbs_tuners
dbs_tuners_ins
=
{
.
up_threshold
=
DEF_FREQUENCY_UP_THRESHOLD
,
.
down_threshold
=
DEF_FREQUENCY_DOWN_THRESHOLD
,
.
sampling_down_factor
=
DEF_SAMPLING_DOWN_FACTOR
,
};
static
inline
unsigned
int
get_cpu_idle_time
(
unsigned
int
cpu
)
{
return
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
+
(
!
dbs_tuners_ins
.
ignore_nice
?
kstat_cpu
(
cpu
).
cpustat
.
nice
:
0
);
}
/************************** sysfs interface ************************/
static
ssize_t
show_sampling_rate_max
(
struct
cpufreq_policy
*
policy
,
char
*
buf
)
{
...
...
@@ -115,7 +119,7 @@ static ssize_t show_##file_name \
show_one
(
sampling_rate
,
sampling_rate
);
show_one
(
sampling_down_factor
,
sampling_down_factor
);
show_one
(
up_threshold
,
up_threshold
);
show_one
(
down_threshold
,
down_threshold
);
show_one
(
ignore_nice
,
ignore_nice
);
static
ssize_t
store_sampling_down_factor
(
struct
cpufreq_policy
*
unused
,
const
char
*
buf
,
size_t
count
)
...
...
@@ -126,6 +130,9 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
if
(
ret
!=
1
)
return
-
EINVAL
;
if
(
input
>
MAX_SAMPLING_DOWN_FACTOR
||
input
<
1
)
return
-
EINVAL
;
down
(
&
dbs_sem
);
dbs_tuners_ins
.
sampling_down_factor
=
input
;
up
(
&
dbs_sem
);
...
...
@@ -161,8 +168,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
down
(
&
dbs_sem
);
if
(
ret
!=
1
||
input
>
MAX_FREQUENCY_UP_THRESHOLD
||
input
<
MIN_FREQUENCY_UP_THRESHOLD
||
input
<=
dbs_tuners_ins
.
down_threshold
)
{
input
<
MIN_FREQUENCY_UP_THRESHOLD
)
{
up
(
&
dbs_sem
);
return
-
EINVAL
;
}
...
...
@@ -173,22 +179,35 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
return
count
;
}
static
ssize_t
store_
down_threshold
(
struct
cpufreq_policy
*
unused
,
static
ssize_t
store_
ignore_nice
(
struct
cpufreq_policy
*
policy
,
const
char
*
buf
,
size_t
count
)
{
unsigned
int
input
;
int
ret
;
unsigned
int
j
;
ret
=
sscanf
(
buf
,
"%u"
,
&
input
);
if
(
ret
!=
1
)
return
-
EINVAL
;
if
(
input
>
1
)
input
=
1
;
down
(
&
dbs_sem
);
if
(
ret
!=
1
||
input
>
MAX_FREQUENCY_DOWN_THRESHOLD
||
input
<
MIN_FREQUENCY_DOWN_THRESHOLD
||
input
>=
dbs_tuners_ins
.
up_threshold
)
{
if
(
input
==
dbs_tuners_ins
.
ignore_nice
)
{
/* nothing to do */
up
(
&
dbs_sem
);
return
-
EINVAL
;
return
count
;
}
dbs_tuners_ins
.
ignore_nice
=
input
;
dbs_tuners_ins
.
down_threshold
=
input
;
/* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
for_each_online_cpu
(
j
)
{
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
prev_cpu_idle_up
=
get_cpu_idle_time
(
j
);
j_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_up
;
}
up
(
&
dbs_sem
);
return
count
;
...
...
@@ -201,7 +220,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
define_one_rw
(
sampling_rate
);
define_one_rw
(
sampling_down_factor
);
define_one_rw
(
up_threshold
);
define_one_rw
(
down_threshold
);
define_one_rw
(
ignore_nice
);
static
struct
attribute
*
dbs_attributes
[]
=
{
&
sampling_rate_max
.
attr
,
...
...
@@ -209,7 +228,7 @@ static struct attribute * dbs_attributes[] = {
&
sampling_rate
.
attr
,
&
sampling_down_factor
.
attr
,
&
up_threshold
.
attr
,
&
down_threshold
.
attr
,
&
ignore_nice
.
attr
,
NULL
};
...
...
@@ -222,9 +241,8 @@ static struct attribute_group dbs_attr_group = {
static
void
dbs_check_cpu
(
int
cpu
)
{
unsigned
int
idle_ticks
,
up_idle_ticks
,
down_idle_ticks
;
unsigned
int
total_idle_ticks
;
unsigned
int
freq_down_step
;
unsigned
int
idle_ticks
,
up_idle_ticks
,
total_ticks
;
unsigned
int
freq_next
;
unsigned
int
freq_down_sampling_rate
;
static
int
down_skip
[
NR_CPUS
];
struct
cpu_dbs_info_s
*
this_dbs_info
;
...
...
@@ -238,38 +256,25 @@ static void dbs_check_cpu(int cpu)
policy
=
this_dbs_info
->
cur_policy
;
/*
* The default safe range is 20% to 80%
* Every sampling_rate, we check
* - If current idle time is less than 20%, then we try to
* increase frequency
* Every sampling_rate*sampling_down_factor, we check
* - If current idle time is more than 80%, then we try to
* decrease frequency
* Every sampling_rate, we check, if current idle time is less
* than 20% (default), then we try to increase frequency
* Every sampling_rate*sampling_down_factor, we look for a the lowest
* frequency which can sustain the load while keeping idle time over
* 30%. If such a frequency exist, we try to decrease to this frequency.
*
* Any frequency increase takes it to the maximum frequency.
* Frequency reduction happens at minimum steps of
* 5%
of max_
frequency
* 5%
(default) of current
frequency
*/
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
idle_ticks
=
total_idle_ticks
-
this_dbs_info
->
prev_cpu_idle_up
;
this_dbs_info
->
prev_cpu_idle_up
=
total_idle_ticks
;
idle_ticks
=
UINT_MAX
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
unsigned
int
tmp_idle_ticks
;
unsigned
int
tmp_idle_ticks
,
total_idle_ticks
;
struct
cpu_dbs_info_s
*
j_dbs_info
;
if
(
j
==
cpu
)
continue
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
total_idle_ticks
=
get_cpu_idle_time
(
j
);
tmp_idle_ticks
=
total_idle_ticks
-
j_dbs_info
->
prev_cpu_idle_up
;
j_dbs_info
->
prev_cpu_idle_up
=
total_idle_ticks
;
...
...
@@ -281,13 +286,23 @@ static void dbs_check_cpu(int cpu)
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks
*=
100
;
up_idle_ticks
=
(
100
-
dbs_tuners_ins
.
up_threshold
)
*
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
);
usecs_to_jiffies
(
dbs_tuners_ins
.
sampling_rate
);
if
(
idle_ticks
<
up_idle_ticks
)
{
down_skip
[
cpu
]
=
0
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
struct
cpu_dbs_info_s
*
j_dbs_info
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_up
;
}
/* if we are already at full speed then break out early */
if
(
policy
->
cur
==
policy
->
max
)
return
;
__cpufreq_driver_target
(
policy
,
policy
->
max
,
CPUFREQ_RELATION_H
);
down_skip
[
cpu
]
=
0
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
return
;
}
...
...
@@ -296,23 +311,14 @@ static void dbs_check_cpu(int cpu)
if
(
down_skip
[
cpu
]
<
dbs_tuners_ins
.
sampling_down_factor
)
return
;
total_idle_ticks
=
kstat_cpu
(
cpu
).
cpustat
.
idle
+
kstat_cpu
(
cpu
).
cpustat
.
iowait
;
idle_ticks
=
total_idle_ticks
-
this_dbs_info
->
prev_cpu_idle_down
;
this_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
idle_ticks
=
UINT_MAX
;
for_each_cpu_mask
(
j
,
policy
->
cpus
)
{
unsigned
int
tmp_idle_ticks
;
unsigned
int
tmp_idle_ticks
,
total_idle_ticks
;
struct
cpu_dbs_info_s
*
j_dbs_info
;
if
(
j
==
cpu
)
continue
;
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
/* Check for frequency increase */
total_idle_ticks
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
/* Check for frequency decrease */
total_idle_ticks
=
j_dbs_info
->
prev_cpu_idle_up
;
tmp_idle_ticks
=
total_idle_ticks
-
j_dbs_info
->
prev_cpu_idle_down
;
j_dbs_info
->
prev_cpu_idle_down
=
total_idle_ticks
;
...
...
@@ -321,38 +327,37 @@ static void dbs_check_cpu(int cpu)
idle_ticks
=
tmp_idle_ticks
;
}
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks
*=
100
;
down_skip
[
cpu
]
=
0
;
/* if we cannot reduce the frequency anymore, break out early */
if
(
policy
->
cur
==
policy
->
min
)
return
;
/* Compute how many ticks there are between two measurements */
freq_down_sampling_rate
=
dbs_tuners_ins
.
sampling_rate
*
dbs_tuners_ins
.
sampling_down_factor
;
down_idle_ticks
=
(
100
-
dbs_tuners_ins
.
down_threshold
)
*
sampling_rate_in_HZ
(
freq_down_sampling_rate
);
total_ticks
=
usecs_to_jiffies
(
freq_down_sampling_rate
);
if
(
idle_ticks
>
down_idle_ticks
)
{
freq_down_step
=
(
5
*
policy
->
max
)
/
100
;
/* max freq cannot be less than 100. But who knows.... */
if
(
unlikely
(
freq_down_step
==
0
))
freq_down_step
=
5
;
/*
* The optimal frequency is the frequency that is the lowest that
* can support the current CPU usage without triggering the up
* policy. To be safe, we focus 10 points under the threshold.
*/
freq_next
=
((
total_ticks
-
idle_ticks
)
*
100
)
/
total_ticks
;
freq_next
=
(
freq_next
*
policy
->
cur
)
/
(
dbs_tuners_ins
.
up_threshold
-
10
);
__cpufreq_driver_target
(
policy
,
policy
->
cur
-
freq_down_step
,
CPUFREQ_RELATION_H
);
return
;
}
if
(
freq_next
<=
((
policy
->
cur
*
95
)
/
100
))
__cpufreq_driver_target
(
policy
,
freq_next
,
CPUFREQ_RELATION_L
);
}
static
void
do_dbs_timer
(
void
*
data
)
{
int
i
;
down
(
&
dbs_sem
);
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
if
(
cpu_online
(
i
))
dbs_check_cpu
(
i
);
for_each_online_cpu
(
i
)
dbs_check_cpu
(
i
);
schedule_delayed_work
(
&
dbs_work
,
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
));
usecs_to_jiffies
(
dbs_tuners_ins
.
sampling_rate
));
up
(
&
dbs_sem
);
}
...
...
@@ -360,7 +365,7 @@ static inline void dbs_timer_init(void)
{
INIT_WORK
(
&
dbs_work
,
do_dbs_timer
,
NULL
);
schedule_delayed_work
(
&
dbs_work
,
sampling_rate_in_HZ
(
dbs_tuners_ins
.
sampling_rate
));
usecs_to_jiffies
(
dbs_tuners_ins
.
sampling_rate
));
return
;
}
...
...
@@ -397,12 +402,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info
=
&
per_cpu
(
cpu_dbs_info
,
j
);
j_dbs_info
->
cur_policy
=
policy
;
j_dbs_info
->
prev_cpu_idle_up
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
j_dbs_info
->
prev_cpu_idle_down
=
kstat_cpu
(
j
).
cpustat
.
idle
+
kstat_cpu
(
j
).
cpustat
.
iowait
;
j_dbs_info
->
prev_cpu_idle_up
=
get_cpu_idle_time
(
j
);
j_dbs_info
->
prev_cpu_idle_down
=
j_dbs_info
->
prev_cpu_idle_up
;
}
this_dbs_info
->
enable
=
1
;
sysfs_create_group
(
&
policy
->
kobj
,
&
dbs_attr_group
);
...
...
@@ -422,6 +424,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
def_sampling_rate
=
(
latency
/
1000
)
*
DEF_SAMPLING_RATE_LATENCY_MULTIPLIER
;
dbs_tuners_ins
.
sampling_rate
=
def_sampling_rate
;
dbs_tuners_ins
.
ignore_nice
=
0
;
dbs_timer_init
();
}
...
...
@@ -461,12 +464,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return
0
;
}
struct
cpufreq_governor
cpufreq_gov_dbs
=
{
st
atic
st
ruct
cpufreq_governor
cpufreq_gov_dbs
=
{
.
name
=
"ondemand"
,
.
governor
=
cpufreq_governor_dbs
,
.
owner
=
THIS_MODULE
,
};
EXPORT_SYMBOL
(
cpufreq_gov_dbs
);
static
int
__init
cpufreq_gov_dbs_init
(
void
)
{
...
...
drivers/cpufreq/cpufreq_stats.c
View file @
12725675
...
...
@@ -19,6 +19,7 @@
#include <linux/percpu.h>
#include <linux/kobject.h>
#include <linux/spinlock.h>
#include <asm/cputime.h>
static
spinlock_t
cpufreq_stats_lock
;
...
...
@@ -29,20 +30,14 @@ static struct freq_attr _attr_##_name = {\
.show = _show,\
};
static
unsigned
long
delta_time
(
unsigned
long
old
,
unsigned
long
new
)
{
return
(
old
>
new
)
?
(
old
-
new
)
:
(
new
+
~
old
+
1
);
}
struct
cpufreq_stats
{
unsigned
int
cpu
;
unsigned
int
total_trans
;
unsigned
long
long
last_time
;
unsigned
long
long
last_time
;
unsigned
int
max_state
;
unsigned
int
state_num
;
unsigned
int
last_index
;
unsigned
long
long
*
time_in_state
;
cputime64_t
*
time_in_state
;
unsigned
int
*
freq_table
;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
unsigned
int
*
trans_table
;
...
...
@@ -60,12 +55,16 @@ static int
cpufreq_stats_update
(
unsigned
int
cpu
)
{
struct
cpufreq_stats
*
stat
;
unsigned
long
long
cur_time
;
cur_time
=
get_jiffies_64
();
spin_lock
(
&
cpufreq_stats_lock
);
stat
=
cpufreq_stats_table
[
cpu
];
if
(
stat
->
time_in_state
)
stat
->
time_in_state
[
stat
->
last_index
]
+=
delta_time
(
stat
->
last_time
,
jiffies
);
stat
->
last_time
=
jiffies
;
stat
->
time_in_state
[
stat
->
last_index
]
=
cputime64_add
(
stat
->
time_in_state
[
stat
->
last_index
],
cputime_sub
(
cur_time
,
stat
->
last_time
));
stat
->
last_time
=
cur_time
;
spin_unlock
(
&
cpufreq_stats_lock
);
return
0
;
}
...
...
@@ -90,8 +89,8 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf)
return
0
;
cpufreq_stats_update
(
stat
->
cpu
);
for
(
i
=
0
;
i
<
stat
->
state_num
;
i
++
)
{
len
+=
sprintf
(
buf
+
len
,
"%u %llu
\n
"
,
stat
->
freq_table
[
i
],
stat
->
time_in_state
[
i
]
);
len
+=
sprintf
(
buf
+
len
,
"%u %llu
\n
"
,
stat
->
freq_table
[
i
],
(
unsigned
long
long
)
cputime64_to_clock_t
(
stat
->
time_in_state
[
i
])
);
}
return
len
;
}
...
...
@@ -107,16 +106,30 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
if
(
!
stat
)
return
0
;
cpufreq_stats_update
(
stat
->
cpu
);
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
" From : To
\n
"
);
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
" : "
);
for
(
i
=
0
;
i
<
stat
->
state_num
;
i
++
)
{
if
(
len
>=
PAGE_SIZE
)
break
;
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%9u "
,
stat
->
freq_table
[
i
]);
}
if
(
len
>=
PAGE_SIZE
)
return
len
;
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"
\n
"
);
for
(
i
=
0
;
i
<
stat
->
state_num
;
i
++
)
{
if
(
len
>=
PAGE_SIZE
)
break
;
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%9u:
\t
"
,
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%9u: "
,
stat
->
freq_table
[
i
]);
for
(
j
=
0
;
j
<
stat
->
state_num
;
j
++
)
{
if
(
len
>=
PAGE_SIZE
)
break
;
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%
u
\t
"
,
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"%
9u
"
,
stat
->
trans_table
[
i
*
stat
->
max_state
+
j
]);
}
len
+=
snprintf
(
buf
+
len
,
PAGE_SIZE
-
len
,
"
\n
"
);
...
...
@@ -197,7 +210,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
count
++
;
}
alloc_size
=
count
*
sizeof
(
int
)
+
count
*
sizeof
(
long
long
);
alloc_size
=
count
*
sizeof
(
int
)
+
count
*
sizeof
(
cputime64_t
);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
alloc_size
+=
count
*
count
*
sizeof
(
int
);
...
...
@@ -224,7 +237,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
}
stat
->
state_num
=
j
;
spin_lock
(
&
cpufreq_stats_lock
);
stat
->
last_time
=
jiffies
;
stat
->
last_time
=
get_jiffies_64
()
;
stat
->
last_index
=
freq_table_get_index
(
stat
,
policy
->
cur
);
spin_unlock
(
&
cpufreq_stats_lock
);
cpufreq_cpu_put
(
data
);
...
...
drivers/firmware/pcdp.c
View file @
12725675
...
...
@@ -11,6 +11,7 @@
* published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/acpi.h>
#include <linux/console.h>
#include <linux/efi.h>
...
...
drivers/i2c/busses/i2c-ali1563.c
View file @
12725675
...
...
@@ -2,6 +2,7 @@
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
*
* Copyright (C) 2004 Patrick Mochel
* 2005 Rudolf Marek <r.marek@sh.cvut.cz>
*
* The 1563 southbridge is deceptively similar to the 1533, with a
* few notable exceptions. One of those happens to be the fact they
...
...
@@ -57,10 +58,11 @@
#define HST_CNTL2_BLOCK 0x05
#define HST_CNTL2_SIZEMASK 0x38
static
unsigned
short
ali1563_smba
;
static
int
ali1563_transaction
(
struct
i2c_adapter
*
a
)
static
int
ali1563_transaction
(
struct
i2c_adapter
*
a
,
int
size
)
{
u32
data
;
int
timeout
;
...
...
@@ -73,7 +75,7 @@ static int ali1563_transaction(struct i2c_adapter * a)
data
=
inb_p
(
SMB_HST_STS
);
if
(
data
&
HST_STS_BAD
)
{
dev_
warn
(
&
a
->
dev
,
"ali1563: Trying to reset busy device
\n
"
);
dev_
err
(
&
a
->
dev
,
"ali1563: Trying to reset busy device
\n
"
);
outb_p
(
data
|
HST_STS_BAD
,
SMB_HST_STS
);
data
=
inb_p
(
SMB_HST_STS
);
if
(
data
&
HST_STS_BAD
)
...
...
@@ -94,19 +96,31 @@ static int ali1563_transaction(struct i2c_adapter * a)
if
(
timeout
&&
!
(
data
&
HST_STS_BAD
))
return
0
;
dev_warn
(
&
a
->
dev
,
"SMBus Error: %s%s%s%s%s
\n
"
,
timeout
?
"Timeout "
:
""
,
data
&
HST_STS_FAIL
?
"Transaction Failed "
:
""
,
data
&
HST_STS_BUSERR
?
"No response or Bus Collision "
:
""
,
data
&
HST_STS_DEVERR
?
"Device Error "
:
""
,
!
(
data
&
HST_STS_DONE
)
?
"Transaction Never Finished "
:
""
);
if
(
!
(
data
&
HST_STS_DONE
))
if
(
!
timeout
)
{
dev_err
(
&
a
->
dev
,
"Timeout - Trying to KILL transaction!
\n
"
);
/* Issue 'kill' to host controller */
outb_p
(
HST_CNTL2_KILL
,
SMB_HST_CNTL2
);
else
/* Issue timeout to reset all devices on bus */
data
=
inb_p
(
SMB_HST_STS
);
}
/* device error - no response, ignore the autodetection case */
if
((
data
&
HST_STS_DEVERR
)
&&
(
size
!=
HST_CNTL2_QUICK
))
{
dev_err
(
&
a
->
dev
,
"Device error!
\n
"
);
}
/* bus collision */
if
(
data
&
HST_STS_BUSERR
)
{
dev_err
(
&
a
->
dev
,
"Bus collision!
\n
"
);
/* Issue timeout, hoping it helps */
outb_p
(
HST_CNTL1_TIMEOUT
,
SMB_HST_CNTL1
);
}
if
(
data
&
HST_STS_FAIL
)
{
dev_err
(
&
a
->
dev
,
"Cleaning fail after KILL!
\n
"
);
outb_p
(
0x0
,
SMB_HST_CNTL2
);
}
return
-
1
;
}
...
...
@@ -149,7 +163,7 @@ static int ali1563_block_start(struct i2c_adapter * a)
if
(
timeout
&&
!
(
data
&
HST_STS_BAD
))
return
0
;
dev_
warn
(
&
a
->
dev
,
"SMBus Error: %s%s%s%s%s
\n
"
,
dev_
err
(
&
a
->
dev
,
"SMBus Error: %s%s%s%s%s
\n
"
,
timeout
?
"Timeout "
:
""
,
data
&
HST_STS_FAIL
?
"Transaction Failed "
:
""
,
data
&
HST_STS_BUSERR
?
"No response or Bus Collision "
:
""
,
...
...
@@ -242,13 +256,15 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
}
outb_p
(((
addr
&
0x7f
)
<<
1
)
|
(
rw
&
0x01
),
SMB_HST_ADD
);
outb_p
(
inb_p
(
SMB_HST_CNTL2
)
|
(
size
<<
3
),
SMB_HST_CNTL2
);
outb_p
(
(
inb_p
(
SMB_HST_CNTL2
)
&
~
HST_CNTL2_SIZEMASK
)
|
(
size
<<
3
),
SMB_HST_CNTL2
);
/* Write the command register */
switch
(
size
)
{
case
HST_CNTL2_BYTE
:
if
(
rw
==
I2C_SMBUS_WRITE
)
outb_p
(
cmd
,
SMB_HST_CMD
);
/* Beware it uses DAT0 register and not CMD! */
outb_p
(
cmd
,
SMB_HST_DAT0
);
break
;
case
HST_CNTL2_BYTE_DATA
:
outb_p
(
cmd
,
SMB_HST_CMD
);
...
...
@@ -268,7 +284,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
goto
Done
;
}
if
((
error
=
ali1563_transaction
(
a
)))
if
((
error
=
ali1563_transaction
(
a
,
size
)))
goto
Done
;
if
((
rw
==
I2C_SMBUS_WRITE
)
||
(
size
==
HST_CNTL2_QUICK
))
...
...
drivers/ide/pci/amd74xx.c
View file @
12725675
...
...
@@ -72,6 +72,7 @@ static struct amd_ide_chip {
{
PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2
,
0x50
,
AMD_UDMA_133
},
{
PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE
,
0x50
,
AMD_UDMA_133
},
{
PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE
,
0x50
,
AMD_UDMA_133
},
{
PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE
,
0x50
,
AMD_UDMA_133
},
{
0
}
};
...
...
@@ -487,6 +488,7 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
/* 12 */
DECLARE_NV_DEV
(
"NFORCE3-250-SATA2"
),
/* 13 */
DECLARE_NV_DEV
(
"NFORCE-CK804"
),
/* 14 */
DECLARE_NV_DEV
(
"NFORCE-MCP04"
),
/* 15 */
DECLARE_NV_DEV
(
"NFORCE-MCP51"
),
};
static
int
__devinit
amd74xx_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
...
...
@@ -521,6 +523,7 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
#endif
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
13
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
14
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
15
},
{
0
,
},
};
MODULE_DEVICE_TABLE
(
pci
,
amd74xx_pci_tbl
);
...
...
drivers/pci/hotplug/cpci_hotplug_core.c
View file @
12725675
/*
* CompactPCI Hot Plug Driver
*
* Copyright (C) 2002 SOMA Networks, Inc.
* Copyright (C) 2002
,2005
SOMA Networks, Inc.
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
*
...
...
@@ -45,10 +45,10 @@
#define dbg(format, arg...) \
do { \
if(cpci_debug) \
if
(cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
} while
(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
...
...
@@ -111,10 +111,8 @@ enable_slot(struct hotplug_slot *hotplug_slot)
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
if
(
controller
->
ops
->
set_power
)
{
if
(
controller
->
ops
->
set_power
)
retval
=
controller
->
ops
->
set_power
(
slot
,
1
);
}
return
retval
;
}
...
...
@@ -126,37 +124,41 @@ disable_slot(struct hotplug_slot *hotplug_slot)
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
down_write
(
&
list_rwsem
);
/* Unconfigure device */
dbg
(
"%s - unconfiguring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
((
retval
=
cpci_unconfigure_slot
(
slot
)))
{
if
((
retval
=
cpci_unconfigure_slot
(
slot
)))
{
err
(
"%s - could not unconfigure slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
return
retval
;
goto
disable_error
;
}
dbg
(
"%s - finished unconfiguring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
/* Clear EXT (by setting it) */
if
(
cpci_clear_ext
(
slot
))
{
if
(
cpci_clear_ext
(
slot
))
{
err
(
"%s - could not clear EXT for slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
retval
=
-
ENODEV
;
goto
disable_error
;
}
cpci_led_on
(
slot
);
if
(
controller
->
ops
->
set_power
)
{
retval
=
controller
->
ops
->
set_power
(
slot
,
0
);
}
if
(
controller
->
ops
->
set_power
)
if
((
retval
=
controller
->
ops
->
set_power
(
slot
,
0
)))
goto
disable_error
;
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
{
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
warn
(
"failure to update adapter file"
);
}
if
(
slot
->
extracting
)
{
if
(
slot
->
extracting
)
{
slot
->
extracting
=
0
;
atomic_dec
(
&
extracting
);
}
disable_error:
up_write
(
&
list_rwsem
);
return
retval
;
}
...
...
@@ -165,9 +167,8 @@ cpci_get_power_status(struct slot *slot)
{
u8
power
=
1
;
if
(
controller
->
ops
->
get_power
)
{
if
(
controller
->
ops
->
get_power
)
power
=
controller
->
ops
->
get_power
(
slot
);
}
return
power
;
}
...
...
@@ -237,9 +238,8 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
int
status
=
-
ENOMEM
;
int
i
;
if
(
!
(
controller
&&
bus
))
{
if
(
!
(
controller
&&
bus
))
return
-
ENODEV
;
}
/*
* Create a structure for each slot, and register that slot
...
...
@@ -316,32 +316,30 @@ int
cpci_hp_unregister_bus
(
struct
pci_bus
*
bus
)
{
struct
slot
*
slot
;
struct
list_head
*
tmp
;
struct
list_head
*
next
;
int
status
;
struct
slot
*
tmp
;
int
status
=
0
;
down_write
(
&
list_rwsem
);
if
(
!
slots
)
{
if
(
!
slots
)
{
up_write
(
&
list_rwsem
);
return
-
1
;
}
list_for_each_safe
(
tmp
,
next
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
if
(
slot
->
bus
==
bus
)
{
list_for_each_entry_safe
(
slot
,
tmp
,
&
slot_list
,
slot_list
)
{
if
(
slot
->
bus
==
bus
)
{
list_del
(
&
slot
->
slot_list
);
slots
--
;
dbg
(
"deregistering slot %s"
,
slot
->
hotplug_slot
->
name
);
status
=
pci_hp_deregister
(
slot
->
hotplug_slot
);
if
(
status
)
{
if
(
status
)
{
err
(
"pci_hp_deregister failed with error %d"
,
status
);
return
status
;
break
;
}
list_del
(
&
slot
->
slot_list
);
slots
--
;
}
}
up_write
(
&
list_rwsem
);
return
0
;
return
status
;
}
/* This is the interrupt mode interrupt handler */
...
...
@@ -351,7 +349,7 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
dbg
(
"entered cpci_hp_intr"
);
/* Check to see if it was our interrupt */
if
((
controller
->
irq_flags
&
SA_SHIRQ
)
&&
if
((
controller
->
irq_flags
&
SA_SHIRQ
)
&&
!
controller
->
ops
->
check_irq
(
controller
->
dev_id
))
{
dbg
(
"exited cpci_hp_intr, not our interrupt"
);
return
IRQ_NONE
;
...
...
@@ -373,38 +371,30 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
* INS bits of the cold-inserted devices.
*/
static
int
init_slots
(
void
)
init_slots
(
int
clear_ins
)
{
struct
slot
*
slot
;
struct
list_head
*
tmp
;
struct
pci_dev
*
dev
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
down_read
(
&
list_rwsem
);
if
(
!
slots
)
{
if
(
!
slots
)
{
up_read
(
&
list_rwsem
);
return
-
1
;
}
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
list_for_each_entry
(
slot
,
&
slot_list
,
slot_list
)
{
dbg
(
"%s - looking at slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_check_and_clear_ins
(
slot
))
{
if
(
clear_ins
&&
cpci_check_and_clear_ins
(
slot
))
dbg
(
"%s - cleared INS for slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
dev
=
pci_find_slot
(
slot
->
bus
->
number
,
PCI_DEVFN
(
slot
->
number
,
0
));
if
(
dev
)
{
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
1
))
{
warn
(
"failure to update adapter file"
);
}
if
(
update_latch_status
(
slot
->
hotplug_slot
,
1
))
{
warn
(
"failure to update latch file"
);
}
slot
->
dev
=
dev
;
}
else
{
err
(
"%s - no driver attached to device in slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
}
dev
=
pci_get_slot
(
slot
->
bus
,
PCI_DEVFN
(
slot
->
number
,
0
));
if
(
dev
)
{
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
1
))
warn
(
"failure to update adapter file"
);
if
(
update_latch_status
(
slot
->
hotplug_slot
,
1
))
warn
(
"failure to update latch file"
);
slot
->
dev
=
dev
;
}
}
up_read
(
&
list_rwsem
);
...
...
@@ -416,26 +406,28 @@ static int
check_slots
(
void
)
{
struct
slot
*
slot
;
struct
list_head
*
tmp
;
int
extracted
;
int
inserted
;
u16
hs_csr
;
down_read
(
&
list_rwsem
);
if
(
!
slots
)
{
if
(
!
slots
)
{
up_read
(
&
list_rwsem
);
err
(
"no slots registered, shutting down"
);
return
-
1
;
}
extracted
=
inserted
=
0
;
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
list_for_each_entry
(
slot
,
&
slot_list
,
slot_list
)
{
dbg
(
"%s - looking at slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_check_and_clear_ins
(
slot
))
{
/* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
if
(
slot
->
dev
)
{
warn
(
"slot %s already inserted"
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_check_and_clear_ins
(
slot
))
{
/*
* Some broken hardware (e.g. PLX 9054AB) asserts
* ENUM# twice...
*/
if
(
slot
->
dev
)
{
warn
(
"slot %s already inserted"
,
slot
->
hotplug_slot
->
name
);
inserted
++
;
continue
;
}
...
...
@@ -452,7 +444,7 @@ check_slots(void)
/* Configure device */
dbg
(
"%s - configuring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_configure_slot
(
slot
))
{
if
(
cpci_configure_slot
(
slot
))
{
err
(
"%s - could not configure slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
continue
;
...
...
@@ -465,13 +457,11 @@ check_slots(void)
dbg
(
"%s - slot %s HS_CSR (2) = %04x"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
if
(
update_latch_status
(
slot
->
hotplug_slot
,
1
))
{
if
(
update_latch_status
(
slot
->
hotplug_slot
,
1
))
warn
(
"failure to update latch file"
);
}
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
1
))
{
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
1
))
warn
(
"failure to update adapter file"
);
}
cpci_led_off
(
slot
);
...
...
@@ -481,7 +471,7 @@ check_slots(void)
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
inserted
++
;
}
else
if
(
cpci_check_ext
(
slot
))
{
}
else
if
(
cpci_check_ext
(
slot
))
{
/* Process extraction request */
dbg
(
"%s - slot %s extracted"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
...
...
@@ -491,27 +481,25 @@ check_slots(void)
dbg
(
"%s - slot %s HS_CSR = %04x"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
if
(
!
slot
->
extracting
)
{
if
(
update_latch_status
(
slot
->
hotplug_slot
,
0
))
{
if
(
!
slot
->
extracting
)
{
if
(
update_latch_status
(
slot
->
hotplug_slot
,
0
))
{
warn
(
"failure to update latch file"
);
}
atomic_inc
(
&
extracting
);
slot
->
extracting
=
1
;
atomic_inc
(
&
extracting
);
}
extracted
++
;
}
else
if
(
slot
->
extracting
)
{
}
else
if
(
slot
->
extracting
)
{
hs_csr
=
cpci_get_hs_csr
(
slot
);
if
(
hs_csr
==
0xffff
)
{
if
(
hs_csr
==
0xffff
)
{
/*
* Hmmm, we're likely hosed at this point, should we
* bother trying to tell the driver or not?
*/
err
(
"card in slot %s was improperly removed"
,
slot
->
hotplug_slot
->
name
);
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
{
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
warn
(
"failure to update adapter file"
);
}
slot
->
extracting
=
0
;
atomic_dec
(
&
extracting
);
}
...
...
@@ -520,10 +508,9 @@ check_slots(void)
up_read
(
&
list_rwsem
);
dbg
(
"inserted=%d, extracted=%d, extracting=%d"
,
inserted
,
extracted
,
atomic_read
(
&
extracting
));
if
(
inserted
||
extracted
)
{
if
(
inserted
||
extracted
)
return
extracted
;
}
else
if
(
!
atomic_read
(
&
extracting
))
{
else
if
(
!
atomic_read
(
&
extracting
))
{
err
(
"cannot find ENUM# source, shutting down"
);
return
-
1
;
}
...
...
@@ -541,12 +528,12 @@ event_thread(void *data)
unlock_kernel
();
dbg
(
"%s - event thread started"
,
__FUNCTION__
);
while
(
1
)
{
while
(
1
)
{
dbg
(
"event thread sleeping"
);
down_interruptible
(
&
event_semaphore
);
dbg
(
"event thread woken, thread_finished = %d"
,
thread_finished
);
if
(
thread_finished
||
signal_pending
(
current
))
if
(
thread_finished
||
signal_pending
(
current
))
break
;
do
{
rc
=
check_slots
();
...
...
@@ -558,7 +545,9 @@ event_thread(void *data)
thread_finished
=
1
;
break
;
}
}
while
(
atomic_read
(
&
extracting
)
!=
0
);
}
while
(
atomic_read
(
&
extracting
)
&&
!
thread_finished
);
if
(
thread_finished
)
break
;
/* Re-enable ENUM# interrupt */
dbg
(
"%s - re-enabling irq"
,
__FUNCTION__
);
...
...
@@ -579,21 +568,21 @@ poll_thread(void *data)
daemonize
(
"cpci_hp_polld"
);
unlock_kernel
();
while
(
1
)
{
if
(
thread_finished
||
signal_pending
(
current
))
while
(
1
)
{
if
(
thread_finished
||
signal_pending
(
current
))
break
;
if
(
controller
->
ops
->
query_enum
())
{
if
(
controller
->
ops
->
query_enum
())
{
do
{
rc
=
check_slots
();
if
(
rc
>
0
)
{
if
(
rc
>
0
)
{
/* Give userspace a chance to handle extraction */
msleep
(
500
);
}
else
if
(
rc
<
0
)
{
}
else
if
(
rc
<
0
)
{
dbg
(
"%s - error checking slots"
,
__FUNCTION__
);
thread_finished
=
1
;
break
;
}
}
while
(
atomic_read
(
&
extracting
)
!=
0
);
}
while
(
atomic_read
(
&
extracting
)
&&
!
thread_finished
);
}
msleep
(
100
);
}
...
...
@@ -612,12 +601,11 @@ cpci_start_thread(void)
init_MUTEX_LOCKED
(
&
thread_exit
);
thread_finished
=
0
;
if
(
controller
->
irq
)
{
if
(
controller
->
irq
)
pid
=
kernel_thread
(
event_thread
,
NULL
,
0
);
}
else
{
else
pid
=
kernel_thread
(
poll_thread
,
NULL
,
0
);
}
if
(
pid
<
0
)
{
if
(
pid
<
0
)
{
err
(
"Can't start up our thread"
);
return
-
1
;
}
...
...
@@ -630,9 +618,8 @@ cpci_stop_thread(void)
{
thread_finished
=
1
;
dbg
(
"thread finish command given"
);
if
(
controller
->
irq
)
{
if
(
controller
->
irq
)
up
(
&
event_semaphore
);
}
dbg
(
"wait for thread to exit"
);
down
(
&
thread_exit
);
}
...
...
@@ -642,45 +629,67 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
{
int
status
=
0
;
if
(
!
controller
)
{
controller
=
new_controller
;
if
(
controller
->
irq
)
{
if
(
request_irq
(
controller
->
irq
,
cpci_hp_intr
,
controller
->
irq_flags
,
MY_NAME
,
controller
->
dev_id
))
{
err
(
"Can't get irq %d for the hotplug cPCI controller"
,
controller
->
irq
);
status
=
-
ENODEV
;
}
dbg
(
"%s - acquired controller irq %d"
,
__FUNCTION__
,
controller
->
irq
);
if
(
controller
)
return
-
1
;
if
(
!
(
new_controller
&&
new_controller
->
ops
))
return
-
EINVAL
;
if
(
new_controller
->
irq
)
{
if
(
!
(
new_controller
->
ops
->
enable_irq
&&
new_controller
->
ops
->
disable_irq
))
status
=
-
EINVAL
;
if
(
request_irq
(
new_controller
->
irq
,
cpci_hp_intr
,
new_controller
->
irq_flags
,
MY_NAME
,
new_controller
->
dev_id
))
{
err
(
"Can't get irq %d for the hotplug cPCI controller"
,
new_controller
->
irq
);
status
=
-
ENODEV
;
}
}
else
{
err
(
"cPCI hotplug controller already registered"
);
status
=
-
1
;
dbg
(
"%s - acquired controller irq %d"
,
__FUNCTION__
,
new_controller
->
irq
);
}
if
(
!
status
)
controller
=
new_controller
;
return
status
;
}
static
void
cleanup_slots
(
void
)
{
struct
slot
*
slot
;
struct
slot
*
tmp
;
/*
* Unregister all of our slots with the pci_hotplug subsystem,
* and free up all memory that we had allocated.
*/
down_write
(
&
list_rwsem
);
if
(
!
slots
)
goto
cleanup_null
;
list_for_each_entry_safe
(
slot
,
tmp
,
&
slot_list
,
slot_list
)
{
list_del
(
&
slot
->
slot_list
);
pci_hp_deregister
(
slot
->
hotplug_slot
);
}
cleanup_null:
up_write
(
&
list_rwsem
);
return
;
}
int
cpci_hp_unregister_controller
(
struct
cpci_hp_controller
*
old_controller
)
{
int
status
=
0
;
if
(
controller
)
{
if
(
atomic_read
(
&
extracting
)
!=
0
)
{
return
-
EBUSY
;
}
if
(
!
thread_finished
)
{
if
(
controller
)
{
if
(
!
thread_finished
)
cpci_stop_thread
();
}
if
(
controller
->
irq
)
{
if
(
controller
->
irq
)
free_irq
(
controller
->
irq
,
controller
->
dev_id
);
}
controller
=
NULL
;
}
else
{
cleanup_slots
();
}
else
status
=
-
ENODEV
;
}
return
status
;
}
...
...
@@ -691,32 +700,28 @@ cpci_hp_start(void)
int
status
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
!
controller
)
{
if
(
!
controller
)
return
-
ENODEV
;
}
down_read
(
&
list_rwsem
);
if
(
list_empty
(
&
slot_list
))
{
if
(
list_empty
(
&
slot_list
))
{
up_read
(
&
list_rwsem
);
return
-
ENODEV
;
}
up_read
(
&
list_rwsem
);
if
(
first
)
{
status
=
init_slots
();
if
(
status
)
{
return
status
;
}
status
=
init_slots
(
first
);
if
(
first
)
first
=
0
;
}
if
(
status
)
return
status
;
status
=
cpci_start_thread
();
if
(
status
)
{
if
(
status
)
return
status
;
}
dbg
(
"%s - thread started"
,
__FUNCTION__
);
if
(
controller
->
irq
)
{
if
(
controller
->
irq
)
{
/* Start enum interrupt processing */
dbg
(
"%s - enabling irq"
,
__FUNCTION__
);
controller
->
ops
->
enable_irq
();
...
...
@@ -728,13 +733,9 @@ cpci_hp_start(void)
int
cpci_hp_stop
(
void
)
{
if
(
!
controller
)
{
if
(
!
controller
)
return
-
ENODEV
;
}
if
(
atomic_read
(
&
extracting
)
!=
0
)
{
return
-
EBUSY
;
}
if
(
controller
->
irq
)
{
if
(
controller
->
irq
)
{
/* Stop enum interrupt processing */
dbg
(
"%s - disabling irq"
,
__FUNCTION__
);
controller
->
ops
->
disable_irq
();
...
...
@@ -743,34 +744,6 @@ cpci_hp_stop(void)
return
0
;
}
static
void
__exit
cleanup_slots
(
void
)
{
struct
list_head
*
tmp
;
struct
slot
*
slot
;
/*
* Unregister all of our slots with the pci_hotplug subsystem,
* and free up all memory that we had allocated.
*/
down_write
(
&
list_rwsem
);
if
(
!
slots
)
{
goto
null_cleanup
;
}
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
list_del
(
&
slot
->
slot_list
);
pci_hp_deregister
(
slot
->
hotplug_slot
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
}
null_cleanup:
up_write
(
&
list_rwsem
);
return
;
}
int
__init
cpci_hotplug_init
(
int
debug
)
{
...
...
@@ -784,7 +757,8 @@ cpci_hotplug_exit(void)
/*
* Clean everything up.
*/
cleanup_slots
();
cpci_hp_stop
();
cpci_hp_unregister_controller
(
controller
);
}
EXPORT_SYMBOL_GPL
(
cpci_hp_register_controller
);
...
...
drivers/pci/hotplug/cpci_hotplug_pci.c
View file @
12725675
/*
* CompactPCI Hot Plug Driver PCI functions
*
* Copyright (C) 2002 by SOMA Networks, Inc.
* Copyright (C) 2002
,2005
by SOMA Networks, Inc.
*
* All rights reserved.
*
...
...
@@ -38,10 +38,10 @@ extern int cpci_debug;
#define dbg(format, arg...) \
do { \
if(cpci_debug) \
if
(cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
} while
(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
...
...
@@ -57,16 +57,15 @@ u8 cpci_get_attention_status(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
0
;
}
return
hs_csr
&
0x0008
?
1
:
0
;
}
...
...
@@ -78,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
0
;
}
if
(
status
)
{
if
(
status
)
hs_csr
|=
HS_CSR_LOO
;
}
else
{
else
hs_csr
&=
~
HS_CSR_LOO
;
}
if
(
pci_bus_write_config_word
(
slot
->
bus
,
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
hs_csr
))
return
0
;
}
return
1
;
}
...
...
@@ -110,16 +104,13 @@ u16 cpci_get_hs_csr(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
0xFFFF
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
0xFFFF
;
}
return
hs_csr
;
}
...
...
@@ -132,24 +123,22 @@ int cpci_check_and_clear_ins(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
0
;
}
if
(
hs_csr
&
HS_CSR_INS
)
{
if
(
hs_csr
&
HS_CSR_INS
)
{
/* Clear INS (by setting it) */
if
(
pci_bus_write_config_word
(
slot
->
bus
,
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
hs_csr
))
ins
=
0
;
}
ins
=
1
;
else
ins
=
1
;
}
return
ins
;
}
...
...
@@ -163,18 +152,15 @@ int cpci_check_ext(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
0
;
}
if
(
hs_csr
&
HS_CSR_EXT
)
{
if
(
hs_csr
&
HS_CSR_EXT
)
ext
=
1
;
}
return
ext
;
}
...
...
@@ -186,23 +172,20 @@ int cpci_clear_ext(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
-
ENODEV
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
-
ENODEV
;
}
if
(
hs_csr
&
HS_CSR_EXT
)
{
if
(
hs_csr
&
HS_CSR_EXT
)
{
/* Clear EXT (by setting it) */
if
(
pci_bus_write_config_word
(
slot
->
bus
,
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
hs_csr
))
return
-
ENODEV
;
}
}
return
0
;
}
...
...
@@ -215,18 +198,16 @@ int cpci_led_on(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
-
ENODEV
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
-
ENODEV
;
}
if
((
hs_csr
&
HS_CSR_LOO
)
!=
HS_CSR_LOO
)
{
if
((
hs_csr
&
HS_CSR_LOO
)
!=
HS_CSR_LOO
)
{
hs_csr
|=
HS_CSR_LOO
;
if
(
pci_bus_write_config_word
(
slot
->
bus
,
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
...
...
@@ -246,18 +227,16 @@ int cpci_led_off(struct slot* slot)
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
if
(
!
hs_cap
)
return
-
ENODEV
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
&
hs_csr
))
return
-
ENODEV
;
}
if
(
hs_csr
&
HS_CSR_LOO
)
{
if
(
hs_csr
&
HS_CSR_LOO
)
{
hs_csr
&=
~
HS_CSR_LOO
;
if
(
pci_bus_write_config_word
(
slot
->
bus
,
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
...
...
@@ -274,19 +253,6 @@ int cpci_led_off(struct slot* slot)
* Device configuration functions
*/
static
void
cpci_enable_device
(
struct
pci_dev
*
dev
)
{
struct
pci_bus
*
bus
;
pci_enable_device
(
dev
);
if
(
dev
->
hdr_type
==
PCI_HEADER_TYPE_BRIDGE
)
{
bus
=
dev
->
subordinate
;
list_for_each_entry
(
dev
,
&
bus
->
devices
,
bus_list
)
{
cpci_enable_device
(
dev
);
}
}
}
int
cpci_configure_slot
(
struct
slot
*
slot
)
{
unsigned
char
busnr
;
...
...
@@ -294,14 +260,14 @@ int cpci_configure_slot(struct slot* slot)
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
slot
->
dev
==
NULL
)
{
if
(
slot
->
dev
==
NULL
)
{
dbg
(
"pci_dev null, finding %02x:%02x:%x"
,
slot
->
bus
->
number
,
PCI_SLOT
(
slot
->
devfn
),
PCI_FUNC
(
slot
->
devfn
));
slot
->
dev
=
pci_
find_slot
(
slot
->
bus
->
number
,
slot
->
devfn
);
slot
->
dev
=
pci_
get_slot
(
slot
->
bus
,
slot
->
devfn
);
}
/* Still NULL? Well then scan for it! */
if
(
slot
->
dev
==
NULL
)
{
if
(
slot
->
dev
==
NULL
)
{
int
n
;
dbg
(
"pci_dev still null"
);
...
...
@@ -311,10 +277,10 @@ int cpci_configure_slot(struct slot* slot)
*/
n
=
pci_scan_slot
(
slot
->
bus
,
slot
->
devfn
);
dbg
(
"%s: pci_scan_slot returned %d"
,
__FUNCTION__
,
n
);
if
(
n
>
0
)
if
(
n
>
0
)
pci_bus_add_devices
(
slot
->
bus
);
slot
->
dev
=
pci_
find_slot
(
slot
->
bus
->
number
,
slot
->
devfn
);
if
(
slot
->
dev
==
NULL
)
{
slot
->
dev
=
pci_
get_slot
(
slot
->
bus
,
slot
->
devfn
);
if
(
slot
->
dev
==
NULL
)
{
err
(
"Could not find PCI device for slot %02x"
,
slot
->
number
);
return
1
;
}
...
...
@@ -329,8 +295,6 @@ int cpci_configure_slot(struct slot* slot)
pci_bus_assign_resources
(
slot
->
dev
->
bus
);
cpci_enable_device
(
slot
->
dev
);
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
...
...
@@ -341,15 +305,15 @@ int cpci_unconfigure_slot(struct slot* slot)
struct
pci_dev
*
dev
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
!
slot
->
dev
)
{
if
(
!
slot
->
dev
)
{
err
(
"No device for slot %02x
\n
"
,
slot
->
number
);
return
-
ENODEV
;
}
for
(
i
=
0
;
i
<
8
;
i
++
)
{
dev
=
pci_
find_slot
(
slot
->
bus
->
number
,
dev
=
pci_
get_slot
(
slot
->
bus
,
PCI_DEVFN
(
PCI_SLOT
(
slot
->
devfn
),
i
));
if
(
dev
)
{
if
(
dev
)
{
pci_remove_bus_device
(
dev
);
slot
->
dev
=
NULL
;
}
...
...
drivers/pci/hotplug/shpchprm_acpi.c
View file @
12725675
...
...
@@ -1626,7 +1626,7 @@ int shpchprm_set_hpp(
pci_bus
->
number
=
func
->
bus
;
devfn
=
PCI_DEVFN
(
func
->
device
,
func
->
function
);
ab
=
find_acpi_bridge_by_bus
(
acpi_bridges_head
,
ctrl
->
seg
,
ctrl
->
bus
);
ab
=
find_acpi_bridge_by_bus
(
acpi_bridges_head
,
ctrl
->
seg
,
ctrl
->
slot_
bus
);
if
(
ab
)
{
if
(
ab
->
_hpp
)
{
...
...
@@ -1681,7 +1681,7 @@ void shpchprm_enable_card(
|
PCI_COMMAND_IO
|
PCI_COMMAND_MEMORY
;
bcmd
=
bcommand
=
bcommand
|
PCI_BRIDGE_CTL_NO_ISA
;
ab
=
find_acpi_bridge_by_bus
(
acpi_bridges_head
,
ctrl
->
seg
,
ctrl
->
bus
);
ab
=
find_acpi_bridge_by_bus
(
acpi_bridges_head
,
ctrl
->
seg
,
ctrl
->
slot_
bus
);
if
(
ab
)
{
if
(
ab
->
_hpp
)
{
if
(
ab
->
_hpp
->
enable_perr
)
{
...
...
drivers/usb/host/Kconfig
View file @
12725675
...
...
@@ -124,3 +124,14 @@ config USB_SL811_HCD
To compile this driver as a module, choose M here: the
module will be called sl811-hcd.
config USB_SL811_CS
tristate "CF/PCMCIA support for SL811HS HCD"
depends on USB_SL811_HCD && PCMCIA
default N
help
Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC
REX-CFU1U CF card (often used with PDAs). If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called "sl811_cs".
drivers/usb/host/Makefile
View file @
12725675
...
...
@@ -7,4 +7,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_OHCI_HCD)
+=
ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD)
+=
uhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD)
+=
sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS)
+=
sl811_cs.o
obj-$(CONFIG_ETRAX_ARCH_V10)
+=
hc_crisv10.o
drivers/usb/host/sl811-hcd.c
View file @
12725675
...
...
@@ -2,8 +2,8 @@
* SL811HS HCD (Host Controller Driver) for USB.
*
* Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
* Copyright (C) 2004 David Brownell
*
* Copyright (C) 2004
-2005
David Brownell
*
* Periodic scheduling is based on Roman's OHCI code
* Copyright (C) 1999 Roman Weissgaerber
*
...
...
@@ -15,7 +15,7 @@
* For documentation, see the SL811HS spec and the "SL811HS Embedded Host"
* document (providing significant pieces missing from that spec); plus
* the SL811S spec if you want peripheral side info.
*/
*/
/*
* Status: Passed basic stress testing, works with hubs, mice, keyboards,
...
...
@@ -67,7 +67,7 @@
MODULE_DESCRIPTION
(
"SL811HS USB Host Controller Driver"
);
MODULE_LICENSE
(
"GPL"
);
#define DRIVER_VERSION "1
5 Dec 2004
"
#define DRIVER_VERSION "1
9 May 2005
"
#ifndef DEBUG
...
...
@@ -121,6 +121,10 @@ static void port_power(struct sl811 *sl811, int is_on)
/* reset as thoroughly as we can */
if
(
sl811
->
board
&&
sl811
->
board
->
reset
)
sl811
->
board
->
reset
(
hcd
->
self
.
controller
);
else
{
sl811_write
(
sl811
,
SL11H_CTLREG1
,
SL11H_CTL1MASK_SE0
);
mdelay
(
20
);
}
sl811_write
(
sl811
,
SL11H_IRQ_ENABLE
,
0
);
sl811_write
(
sl811
,
SL11H_CTLREG1
,
sl811
->
ctrl1
);
...
...
@@ -443,6 +447,7 @@ static void finish_request(
spin_lock
(
&
urb
->
lock
);
if
(
urb
->
status
==
-
EINPROGRESS
)
urb
->
status
=
status
;
urb
->
hcpriv
=
NULL
;
spin_unlock
(
&
urb
->
lock
);
spin_unlock
(
&
sl811
->
lock
);
...
...
@@ -472,7 +477,7 @@ static void finish_request(
if
(
*
prev
)
*
prev
=
ep
->
next
;
sl811
->
load
[
i
]
-=
ep
->
load
;
}
}
ep
->
branch
=
PERIODIC_SIZE
;
sl811
->
periodic_count
--
;
sl811_to_hcd
(
sl811
)
->
self
.
bandwidth_allocated
...
...
@@ -661,9 +666,9 @@ retry:
#ifdef QUIRK2
/* this may no longer be necessary ... */
if
(
irqstat
==
0
&&
ret
==
IRQ_NONE
)
{
if
(
irqstat
==
0
)
{
irqstat
=
checkdone
(
sl811
);
if
(
irqstat
/* && irq != ~0 */
)
if
(
irqstat
)
sl811
->
stat_lost
++
;
}
#endif
...
...
@@ -722,7 +727,8 @@ retry:
if
(
sl811
->
active_a
)
{
sl811_write
(
sl811
,
SL811_EP_A
(
SL11H_HOSTCTLREG
),
0
);
finish_request
(
sl811
,
sl811
->
active_a
,
container_of
(
sl811
->
active_a
->
hep
->
urb_list
.
next
,
container_of
(
sl811
->
active_a
->
hep
->
urb_list
.
next
,
struct
urb
,
urb_list
),
NULL
,
-
ESHUTDOWN
);
sl811
->
active_a
=
NULL
;
...
...
@@ -731,7 +737,8 @@ retry:
if
(
sl811
->
active_b
)
{
sl811_write
(
sl811
,
SL811_EP_B
(
SL11H_HOSTCTLREG
),
0
);
finish_request
(
sl811
,
sl811
->
active_b
,
container_of
(
sl811
->
active_b
->
hep
->
urb_list
.
next
,
container_of
(
sl811
->
active_b
->
hep
->
urb_list
.
next
,
struct
urb
,
urb_list
),
NULL
,
-
ESHUTDOWN
);
sl811
->
active_b
=
NULL
;
...
...
@@ -761,7 +768,7 @@ retry:
goto
retry
;
}
if
(
sl811
->
periodic_count
==
0
&&
list_empty
(
&
sl811
->
async
))
if
(
sl811
->
periodic_count
==
0
&&
list_empty
(
&
sl811
->
async
))
sofirq_off
(
sl811
);
sl811_write
(
sl811
,
SL11H_IRQ_ENABLE
,
sl811
->
irq_enable
);
...
...
@@ -796,7 +803,7 @@ static int balance(struct sl811 *sl811, u16 period, u16 load)
}
if
(
j
<
PERIODIC_SIZE
)
continue
;
branch
=
i
;
branch
=
i
;
}
}
return
branch
;
...
...
@@ -890,6 +897,7 @@ static int sl811h_urb_enqueue(
break
;
}
ep
->
hep
=
hep
;
hep
->
hcpriv
=
ep
;
}
...
...
@@ -961,15 +969,16 @@ fail:
static
int
sl811h_urb_dequeue
(
struct
usb_hcd
*
hcd
,
struct
urb
*
urb
)
{
struct
sl811
*
sl811
=
hcd_to_sl811
(
hcd
);
struct
usb_host_endpoint
*
hep
=
urb
->
hcpriv
;
struct
usb_host_endpoint
*
hep
;
unsigned
long
flags
;
struct
sl811h_ep
*
ep
;
int
retval
=
0
;
spin_lock_irqsave
(
&
sl811
->
lock
,
flags
);
hep
=
urb
->
hcpriv
;
if
(
!
hep
)
return
-
EINVAL
;
goto
fail
;
spin_lock_irqsave
(
&
sl811
->
lock
,
flags
);
ep
=
hep
->
hcpriv
;
if
(
ep
)
{
/* finish right away if this urb can't be active ...
...
...
@@ -1017,6 +1026,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
VDBG
(
"dequeue, urb %p active %s; wait4irq
\n
"
,
urb
,
(
sl811
->
active_a
==
ep
)
?
"A"
:
"B"
);
}
else
fail:
retval
=
-
EINVAL
;
spin_unlock_irqrestore
(
&
sl811
->
lock
,
flags
);
return
retval
;
...
...
@@ -1576,6 +1586,9 @@ sl811h_start(struct usb_hcd *hcd)
if
(
sl811
->
board
&&
sl811
->
board
->
power
)
hub_set_power_budget
(
udev
,
sl811
->
board
->
power
*
2
);
/* enable power and interupts */
port_power
(
sl811
,
1
);
return
0
;
}
...
...
@@ -1618,7 +1631,7 @@ static struct hc_driver sl811h_hc_driver = {
/*-------------------------------------------------------------------------*/
static
int
__
init_or_module
static
int
__
devexit
sl811h_remove
(
struct
device
*
dev
)
{
struct
usb_hcd
*
hcd
=
dev_get_drvdata
(
dev
);
...
...
@@ -1631,21 +1644,20 @@ sl811h_remove(struct device *dev)
remove_debug_file
(
sl811
);
usb_remove_hcd
(
hcd
);
iounmap
(
sl811
->
data_reg
);
/* some platforms may use IORESOURCE_IO */
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
1
);
release_mem_region
(
res
->
start
,
1
);
if
(
res
)
iounmap
(
sl811
->
data_reg
);
iounmap
(
sl811
->
addr_reg
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
release_mem_region
(
res
->
start
,
1
);
if
(
res
)
iounmap
(
sl811
->
addr_reg
);
usb_put_hcd
(
hcd
);
return
0
;
}
#define resource_len(r) (((r)->end - (r)->start) + 1)
static
int
__init
static
int
__devinit
sl811h_probe
(
struct
device
*
dev
)
{
struct
usb_hcd
*
hcd
;
...
...
@@ -1656,7 +1668,7 @@ sl811h_probe(struct device *dev)
void
__iomem
*
addr_reg
;
void
__iomem
*
data_reg
;
int
retval
;
u8
tmp
;
u8
tmp
,
ioaddr
=
0
;
/* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board
...
...
@@ -1664,13 +1676,8 @@ sl811h_probe(struct device *dev)
* minimal sanity checking.
*/
pdev
=
container_of
(
dev
,
struct
platform_device
,
dev
);
if
(
pdev
->
num_resources
<
3
)
return
-
ENODEV
;
addr
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
data
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
1
);
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
!
addr
||
!
data
||
irq
<
0
)
if
(
pdev
->
num_resources
<
3
||
irq
<
0
)
return
-
ENODEV
;
/* refuse to confuse usbcore */
...
...
@@ -1679,24 +1686,31 @@ sl811h_probe(struct device *dev)
return
-
EINVAL
;
}
if
(
!
request_mem_region
(
addr
->
start
,
1
,
hcd_name
))
{
retval
=
-
EBUSY
;
goto
err1
;
}
addr_reg
=
ioremap
(
addr
->
start
,
resource_len
(
addr
));
if
(
addr_reg
==
NULL
)
{
retval
=
-
ENOMEM
;
goto
err2
;
}
/* the chip may be wired for either kind of addressing */
addr
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
data
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
1
);
retval
=
-
EBUSY
;
if
(
!
addr
||
!
data
)
{
addr
=
platform_get_resource
(
pdev
,
IORESOURCE_IO
,
0
);
data
=
platform_get_resource
(
pdev
,
IORESOURCE_IO
,
1
);
if
(
!
addr
||
!
data
)
return
-
ENODEV
;
ioaddr
=
1
;
addr_reg
=
(
void
__iomem
*
)
addr
->
start
;
data_reg
=
(
void
__iomem
*
)
data
->
start
;
}
else
{
addr_reg
=
ioremap
(
addr
->
start
,
1
);
if
(
addr_reg
==
NULL
)
{
retval
=
-
ENOMEM
;
goto
err2
;
}
if
(
!
request_mem_region
(
data
->
start
,
1
,
hcd_name
))
{
retval
=
-
EBUSY
;
goto
err3
;
}
data_reg
=
ioremap
(
data
->
start
,
resource_len
(
addr
));
if
(
data_reg
==
NULL
)
{
retval
=
-
ENOMEM
;
goto
err4
;
data_reg
=
ioremap
(
data
->
start
,
1
);
if
(
data_reg
==
NULL
)
{
retval
=
-
ENOMEM
;
goto
err4
;
}
}
/* allocate and initialize hcd */
...
...
@@ -1737,12 +1751,14 @@ sl811h_probe(struct device *dev)
goto
err6
;
}
/* sl811s would need a different handler for this irq */
#ifdef CONFIG_ARM
/* Cypress docs say the IRQ is IRQT_HIGH ... */
set_irq_type
(
irq
,
IRQT_RISING
);
#endif
retval
=
usb_add_hcd
(
hcd
,
irq
,
SA_INTERRUPT
);
/* The chip's IRQ is level triggered, active high. A requirement
* for platform device setup is to cope with things like signal
* inverters (e.g. CF is active low) or working only with edge
* triggers (e.g. most ARM CPUs). Initial driver stress testing
* was on a system with single edge triggering, so most sorts of
* triggering arrangement should work.
*/
retval
=
usb_add_hcd
(
hcd
,
irq
,
SA_INTERRUPT
|
SA_SHIRQ
);
if
(
retval
!=
0
)
goto
err6
;
...
...
@@ -1752,14 +1768,12 @@ sl811h_probe(struct device *dev)
err6:
usb_put_hcd
(
hcd
);
err5:
iounmap
(
data_reg
);
if
(
!
ioaddr
)
iounmap
(
data_reg
);
err4:
release_mem_region
(
data
->
start
,
1
);
err3:
iounmap
(
addr_reg
);
if
(
!
ioaddr
)
iounmap
(
addr_reg
);
err2:
release_mem_region
(
addr
->
start
,
1
);
err1:
DBG
(
"init error, %d
\n
"
,
retval
);
return
retval
;
}
...
...
@@ -1767,7 +1781,7 @@ sl811h_probe(struct device *dev)
#ifdef CONFIG_PM
/* for this device there's no useful distinction between the controller
* and its root hub, except that the root hub only gets direct PM calls
* and its root hub, except that the root hub only gets direct PM calls
* when CONFIG_USB_SUSPEND is enabled.
*/
...
...
@@ -1821,20 +1835,22 @@ sl811h_resume(struct device *dev, u32 phase)
#endif
static
struct
device_driver
sl811h_driver
=
{
/* this driver is exported so sl811_cs can depend on it */
struct
device_driver
sl811h_driver
=
{
.
name
=
(
char
*
)
hcd_name
,
.
bus
=
&
platform_bus_type
,
.
probe
=
sl811h_probe
,
.
remove
=
sl811h_remove
,
.
remove
=
__devexit_p
(
sl811h_remove
)
,
.
suspend
=
sl811h_suspend
,
.
resume
=
sl811h_resume
,
};
EXPORT_SYMBOL
(
sl811h_driver
);
/*-------------------------------------------------------------------------*/
static
int
__init
sl811h_init
(
void
)
static
int
__init
sl811h_init
(
void
)
{
if
(
usb_disabled
())
return
-
ENODEV
;
...
...
@@ -1844,8 +1860,8 @@ static int __init sl811h_init(void)
}
module_init
(
sl811h_init
);
static
void
__exit
sl811h_cleanup
(
void
)
{
static
void
__exit
sl811h_cleanup
(
void
)
{
driver_unregister
(
&
sl811h_driver
);
}
module_exit
(
sl811h_cleanup
);
drivers/usb/host/sl811_cs.c
0 → 100644
View file @
12725675
/*
* PCMCIA driver for SL811HS (as found in REX-CFU1U)
* Filename: sl811_cs.c
* Author: Yukio Yamamoto
*
* Port to sl811-hcd and 2.6.x by
* Botond Botyanszki <boti@rocketmail.com>
* Simon Pickering
*
* Last update: 2005-05-12
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
#include <linux/usb_sl811.h>
MODULE_AUTHOR
(
"Botond Botyanszki"
);
MODULE_DESCRIPTION
(
"REX-CFU1U PCMCIA driver for 2.6"
);
MODULE_LICENSE
(
"GPL"
);
/*====================================================================*/
/* MACROS */
/*====================================================================*/
#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
static
int
pc_debug
=
0
;
module_param
(
pc_debug
,
int
,
0644
);
#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args)
#else
#define DBG(n, args...) do{}while(0)
#endif
/* no debugging */
#define INFO(args...) printk(KERN_INFO "sl811_cs: " args)
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
#define CS_CHECK(fn, ret) \
do { \
last_fn = (fn); \
if ((last_ret = (ret)) != 0) \
goto cs_failed; \
} while (0)
/*====================================================================*/
/* VARIABLES */
/*====================================================================*/
static
const
char
driver_name
[
DEV_NAME_LEN
]
=
"sl811_cs"
;
static
dev_link_t
*
dev_list
=
NULL
;
static
int
irq_list
[
4
]
=
{
-
1
};
static
int
irq_list_count
;
module_param_array
(
irq_list
,
int
,
&
irq_list_count
,
0444
);
INT_MODULE_PARM
(
irq_mask
,
0xdeb8
);
typedef
struct
local_info_t
{
dev_link_t
link
;
dev_node_t
node
;
}
local_info_t
;
/*====================================================================*/
static
void
release_platform_dev
(
struct
device
*
dev
)
{
DBG
(
0
,
"sl811_cs platform_dev release
\n
"
);
dev
->
parent
=
NULL
;
}
static
struct
sl811_platform_data
platform_data
=
{
.
potpg
=
100
,
.
power
=
50
,
/* == 100mA */
// .reset = ... FIXME: invoke CF reset on the card
};
static
struct
resource
resources
[]
=
{
[
0
]
=
{
.
flags
=
IORESOURCE_IRQ
,
},
[
1
]
=
{
// .name = "address",
.
flags
=
IORESOURCE_IO
,
},
[
2
]
=
{
// .name = "data",
.
flags
=
IORESOURCE_IO
,
},
};
extern
struct
device_driver
sl811h_driver
;
static
struct
platform_device
platform_dev
=
{
.
id
=
-
1
,
.
dev
=
{
.
platform_data
=
&
platform_data
,
.
release
=
release_platform_dev
,
},
.
resource
=
resources
,
.
num_resources
=
ARRAY_SIZE
(
resources
),
};
static
int
sl811_hc_init
(
struct
device
*
parent
,
ioaddr_t
base_addr
,
int
irq
)
{
if
(
platform_dev
.
dev
.
parent
)
return
-
EBUSY
;
platform_dev
.
dev
.
parent
=
parent
;
/* finish seting up the platform device */
resources
[
0
].
start
=
irq
;
resources
[
1
].
start
=
base_addr
;
resources
[
1
].
end
=
base_addr
;
resources
[
2
].
start
=
base_addr
+
1
;
resources
[
2
].
end
=
base_addr
+
1
;
/* The driver core will probe for us. We know sl811-hcd has been
* initialized already because of the link order dependency.
*/
platform_dev
.
name
=
sl811h_driver
.
name
;
return
platform_device_register
(
&
platform_dev
);
}
/*====================================================================*/
static
void
sl811_cs_detach
(
dev_link_t
*
link
)
{
dev_link_t
**
linkp
;
DBG
(
0
,
"sl811_cs_detach(0x%p)
\n
"
,
link
);
/* Locate device structure */
for
(
linkp
=
&
dev_list
;
*
linkp
;
linkp
=
&
(
*
linkp
)
->
next
)
{
if
(
*
linkp
==
link
)
break
;
}
if
(
*
linkp
==
NULL
)
return
;
/* Break the link with Card Services */
if
(
link
->
handle
)
pcmcia_deregister_client
(
link
->
handle
);
/* Unlink device structure, and free it */
*
linkp
=
link
->
next
;
/* This points to the parent local_info_t struct */
kfree
(
link
->
priv
);
}
static
void
sl811_cs_release
(
dev_link_t
*
link
)
{
DBG
(
0
,
"sl811_cs_release(0x%p)
\n
"
,
link
);
if
(
link
->
open
)
{
DBG
(
1
,
"sl811_cs: release postponed, '%s' still open
\n
"
,
link
->
dev
->
dev_name
);
link
->
state
|=
DEV_STALE_CONFIG
;
return
;
}
/* Unlink the device chain */
link
->
dev
=
NULL
;
platform_device_unregister
(
&
platform_dev
);
pcmcia_release_configuration
(
link
->
handle
);
if
(
link
->
io
.
NumPorts1
)
pcmcia_release_io
(
link
->
handle
,
&
link
->
io
);
if
(
link
->
irq
.
AssignedIRQ
)
pcmcia_release_irq
(
link
->
handle
,
&
link
->
irq
);
link
->
state
&=
~
DEV_CONFIG
;
if
(
link
->
state
&
DEV_STALE_LINK
)
sl811_cs_detach
(
link
);
}
static
void
sl811_cs_config
(
dev_link_t
*
link
)
{
client_handle_t
handle
=
link
->
handle
;
struct
device
*
parent
=
&
handle_to_dev
(
handle
);
local_info_t
*
dev
=
link
->
priv
;
tuple_t
tuple
;
cisparse_t
parse
;
int
last_fn
,
last_ret
;
u_char
buf
[
64
];
config_info_t
conf
;
cistpl_cftable_entry_t
dflt
=
{
0
};
DBG
(
0
,
"sl811_cs_config(0x%p)
\n
"
,
link
);
tuple
.
DesiredTuple
=
CISTPL_CONFIG
;
tuple
.
Attributes
=
0
;
tuple
.
TupleData
=
buf
;
tuple
.
TupleDataMax
=
sizeof
(
buf
);
tuple
.
TupleOffset
=
0
;
CS_CHECK
(
GetFirstTuple
,
pcmcia_get_first_tuple
(
handle
,
&
tuple
));
CS_CHECK
(
GetTupleData
,
pcmcia_get_tuple_data
(
handle
,
&
tuple
));
CS_CHECK
(
ParseTuple
,
pcmcia_parse_tuple
(
handle
,
&
tuple
,
&
parse
));
link
->
conf
.
ConfigBase
=
parse
.
config
.
base
;
link
->
conf
.
Present
=
parse
.
config
.
rmask
[
0
];
/* Configure card */
link
->
state
|=
DEV_CONFIG
;
/* Look up the current Vcc */
CS_CHECK
(
GetConfigurationInfo
,
pcmcia_get_configuration_info
(
handle
,
&
conf
));
link
->
conf
.
Vcc
=
conf
.
Vcc
;
tuple
.
DesiredTuple
=
CISTPL_CFTABLE_ENTRY
;
CS_CHECK
(
GetFirstTuple
,
pcmcia_get_first_tuple
(
handle
,
&
tuple
));
while
(
1
)
{
cistpl_cftable_entry_t
*
cfg
=
&
(
parse
.
cftable_entry
);
if
(
pcmcia_get_tuple_data
(
handle
,
&
tuple
)
!=
0
||
pcmcia_parse_tuple
(
handle
,
&
tuple
,
&
parse
)
!=
0
)
goto
next_entry
;
if
(
cfg
->
flags
&
CISTPL_CFTABLE_DEFAULT
)
{
dflt
=
*
cfg
;
}
if
(
cfg
->
index
==
0
)
goto
next_entry
;
link
->
conf
.
ConfigIndex
=
cfg
->
index
;
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if
(
cfg
->
vcc
.
present
&
(
1
<<
CISTPL_POWER_VNOM
))
{
if
(
cfg
->
vcc
.
param
[
CISTPL_POWER_VNOM
]
/
10000
!=
conf
.
Vcc
)
goto
next_entry
;
}
else
if
(
dflt
.
vcc
.
present
&
(
1
<<
CISTPL_POWER_VNOM
))
{
if
(
dflt
.
vcc
.
param
[
CISTPL_POWER_VNOM
]
/
10000
!=
conf
.
Vcc
)
goto
next_entry
;
}
if
(
cfg
->
vpp1
.
present
&
(
1
<<
CISTPL_POWER_VNOM
))
link
->
conf
.
Vpp1
=
link
->
conf
.
Vpp2
=
cfg
->
vpp1
.
param
[
CISTPL_POWER_VNOM
]
/
10000
;
else
if
(
dflt
.
vpp1
.
present
&
(
1
<<
CISTPL_POWER_VNOM
))
link
->
conf
.
Vpp1
=
link
->
conf
.
Vpp2
=
dflt
.
vpp1
.
param
[
CISTPL_POWER_VNOM
]
/
10000
;
/* we need an interrupt */
if
(
cfg
->
irq
.
IRQInfo1
||
dflt
.
irq
.
IRQInfo1
)
link
->
conf
.
Attributes
|=
CONF_ENABLE_IRQ
;
/* IO window settings */
link
->
io
.
NumPorts1
=
link
->
io
.
NumPorts2
=
0
;
if
((
cfg
->
io
.
nwin
>
0
)
||
(
dflt
.
io
.
nwin
>
0
))
{
cistpl_io_t
*
io
=
(
cfg
->
io
.
nwin
)
?
&
cfg
->
io
:
&
dflt
.
io
;
link
->
io
.
Attributes1
=
IO_DATA_PATH_WIDTH_8
;
link
->
io
.
IOAddrLines
=
io
->
flags
&
CISTPL_IO_LINES_MASK
;
link
->
io
.
BasePort1
=
io
->
win
[
0
].
base
;
link
->
io
.
NumPorts1
=
io
->
win
[
0
].
len
;
if
(
pcmcia_request_io
(
link
->
handle
,
&
link
->
io
)
!=
0
)
goto
next_entry
;
}
break
;
next_entry:
if
(
link
->
io
.
NumPorts1
)
pcmcia_release_io
(
link
->
handle
,
&
link
->
io
);
last_ret
=
pcmcia_get_next_tuple
(
handle
,
&
tuple
);
}
/* require an IRQ and two registers */
if
(
!
link
->
io
.
NumPorts1
||
link
->
io
.
NumPorts1
<
2
)
goto
cs_failed
;
if
(
link
->
conf
.
Attributes
&
CONF_ENABLE_IRQ
)
CS_CHECK
(
RequestIRQ
,
pcmcia_request_irq
(
link
->
handle
,
&
link
->
irq
));
else
goto
cs_failed
;
CS_CHECK
(
RequestConfiguration
,
pcmcia_request_configuration
(
link
->
handle
,
&
link
->
conf
));
sprintf
(
dev
->
node
.
dev_name
,
driver_name
);
dev
->
node
.
major
=
dev
->
node
.
minor
=
0
;
link
->
dev
=
&
dev
->
node
;
printk
(
KERN_INFO
"%s: index 0x%02x: Vcc %d.%d"
,
dev
->
node
.
dev_name
,
link
->
conf
.
ConfigIndex
,
link
->
conf
.
Vcc
/
10
,
link
->
conf
.
Vcc
%
10
);
if
(
link
->
conf
.
Vpp1
)
printk
(
", Vpp %d.%d"
,
link
->
conf
.
Vpp1
/
10
,
link
->
conf
.
Vpp1
%
10
);
printk
(
", irq %d"
,
link
->
irq
.
AssignedIRQ
);
printk
(
", io 0x%04x-0x%04x"
,
link
->
io
.
BasePort1
,
link
->
io
.
BasePort1
+
link
->
io
.
NumPorts1
-
1
);
printk
(
"
\n
"
);
link
->
state
&=
~
DEV_CONFIG_PENDING
;
if
(
sl811_hc_init
(
parent
,
link
->
io
.
BasePort1
,
link
->
irq
.
AssignedIRQ
)
<
0
)
{
cs_failed:
printk
(
"sl811_cs_config failed
\n
"
);
cs_error
(
link
->
handle
,
last_fn
,
last_ret
);
sl811_cs_release
(
link
);
link
->
state
&=
~
DEV_CONFIG_PENDING
;
}
}
static
int
sl811_cs_event
(
event_t
event
,
int
priority
,
event_callback_args_t
*
args
)
{
dev_link_t
*
link
=
args
->
client_data
;
DBG
(
1
,
"sl811_cs_event(0x%06x)
\n
"
,
event
);
switch
(
event
)
{
case
CS_EVENT_CARD_REMOVAL
:
link
->
state
&=
~
DEV_PRESENT
;
if
(
link
->
state
&
DEV_CONFIG
)
sl811_cs_release
(
link
);
break
;
case
CS_EVENT_CARD_INSERTION
:
link
->
state
|=
DEV_PRESENT
|
DEV_CONFIG_PENDING
;
sl811_cs_config
(
link
);
break
;
case
CS_EVENT_PM_SUSPEND
:
link
->
state
|=
DEV_SUSPEND
;
/* Fall through... */
case
CS_EVENT_RESET_PHYSICAL
:
if
(
link
->
state
&
DEV_CONFIG
)
pcmcia_release_configuration
(
link
->
handle
);
break
;
case
CS_EVENT_PM_RESUME
:
link
->
state
&=
~
DEV_SUSPEND
;
/* Fall through... */
case
CS_EVENT_CARD_RESET
:
if
(
link
->
state
&
DEV_CONFIG
)
pcmcia_request_configuration
(
link
->
handle
,
&
link
->
conf
);
DBG
(
0
,
"reset sl811-hcd here?
\n
"
);
break
;
}
return
0
;
}
static
dev_link_t
*
sl811_cs_attach
(
void
)
{
local_info_t
*
local
;
dev_link_t
*
link
;
client_reg_t
client_reg
;
int
ret
,
i
;
local
=
kmalloc
(
sizeof
(
local_info_t
),
GFP_KERNEL
);
if
(
!
local
)
return
NULL
;
memset
(
local
,
0
,
sizeof
(
local_info_t
));
link
=
&
local
->
link
;
link
->
priv
=
local
;
/* Initialize */
link
->
irq
.
Attributes
=
IRQ_TYPE_EXCLUSIVE
;
link
->
irq
.
IRQInfo1
=
IRQ_INFO2_VALID
|
IRQ_LEVEL_ID
;
if
(
irq_list
[
0
]
==
-
1
)
link
->
irq
.
IRQInfo2
=
irq_mask
;
else
for
(
i
=
0
;
i
<
irq_list_count
;
i
++
)
link
->
irq
.
IRQInfo2
|=
1
<<
irq_list
[
i
];
link
->
irq
.
Handler
=
NULL
;
link
->
conf
.
Attributes
=
0
;
link
->
conf
.
Vcc
=
33
;
link
->
conf
.
IntType
=
INT_MEMORY_AND_IO
;
/* Register with Card Services */
link
->
next
=
dev_list
;
dev_list
=
link
;
client_reg
.
dev_info
=
(
dev_info_t
*
)
&
driver_name
;
client_reg
.
Attributes
=
INFO_IO_CLIENT
|
INFO_CARD_SHARE
;
client_reg
.
EventMask
=
CS_EVENT_CARD_INSERTION
|
CS_EVENT_CARD_REMOVAL
|
CS_EVENT_RESET_PHYSICAL
|
CS_EVENT_CARD_RESET
|
CS_EVENT_PM_SUSPEND
|
CS_EVENT_PM_RESUME
;
client_reg
.
event_handler
=
&
sl811_cs_event
;
client_reg
.
Version
=
0x0210
;
client_reg
.
event_callback_args
.
client_data
=
link
;
ret
=
pcmcia_register_client
(
&
link
->
handle
,
&
client_reg
);
if
(
ret
!=
CS_SUCCESS
)
{
cs_error
(
link
->
handle
,
RegisterClient
,
ret
);
sl811_cs_detach
(
link
);
return
NULL
;
}
return
link
;
}
static
struct
pcmcia_driver
sl811_cs_driver
=
{
.
owner
=
THIS_MODULE
,
.
drv
=
{
.
name
=
(
char
*
)
driver_name
,
},
.
attach
=
sl811_cs_attach
,
.
detach
=
sl811_cs_detach
,
};
/*====================================================================*/
static
int
__init
init_sl811_cs
(
void
)
{
return
pcmcia_register_driver
(
&
sl811_cs_driver
);
}
module_init
(
init_sl811_cs
);
static
void
__exit
exit_sl811_cs
(
void
)
{
pcmcia_unregister_driver
(
&
sl811_cs_driver
);
}
module_exit
(
exit_sl811_cs
);
drivers/usb/serial/ftdi_sio.c
View file @
12725675
...
...
@@ -364,6 +364,7 @@ static struct usb_device_id id_table_8U232AM [] = {
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_SPECIAL_3
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_SPECIAL_4
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_ELV_UO100_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_ELV_UM100_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
INSIDE_ACCESSO
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
INTREPID_VID
,
INTREPID_VALUECAN_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
INTREPID_VID
,
INTREPID_NEOVI_PID
,
0
,
0x3ff
)
},
...
...
@@ -475,6 +476,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_GUDEADS_E88E_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_GUDEADS_E88F_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_ELV_UO100_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_ELV_UM100_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
LINX_SDMUSBQSS_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
LINX_MASTERDEVEL2_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
LINX_FUTURE_0_PID
,
0x400
,
0xffff
)
},
...
...
@@ -618,6 +620,7 @@ static struct usb_device_id id_table_combined [] = {
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_GUDEADS_E88E_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_GUDEADS_E88F_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_ELV_UO100_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_ELV_UM100_PID
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
LINX_SDMUSBQSS_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
LINX_MASTERDEVEL2_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
LINX_FUTURE_0_PID
,
0x400
,
0xffff
)
},
...
...
drivers/usb/serial/ftdi_sio.h
View file @
12725675
...
...
@@ -144,6 +144,8 @@
/* ELV USB Module UO100 (PID sent by Stefan Frings) */
#define FTDI_ELV_UO100_PID 0xFB58
/* Product Id */
/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */
#define FTDI_ELV_UM100_PID 0xFB5A
/* Product Id */
/*
* Definitions for ID TECH (www.idt-net.com) devices
...
...
drivers/usb/serial/usb-serial.c
View file @
12725675
...
...
@@ -1297,13 +1297,6 @@ static int __init usb_serial_init(void)
goto
exit_bus
;
}
/* register the generic driver, if we should */
result
=
usb_serial_generic_register
(
debug
);
if
(
result
<
0
)
{
err
(
"%s - registering generic driver failed"
,
__FUNCTION__
);
goto
exit_generic
;
}
usb_serial_tty_driver
->
owner
=
THIS_MODULE
;
usb_serial_tty_driver
->
driver_name
=
"usbserial"
;
usb_serial_tty_driver
->
devfs_name
=
"usb/tts/"
;
...
...
@@ -1329,17 +1322,24 @@ static int __init usb_serial_init(void)
goto
exit_tty
;
}
/* register the generic driver, if we should */
result
=
usb_serial_generic_register
(
debug
);
if
(
result
<
0
)
{
err
(
"%s - registering generic driver failed"
,
__FUNCTION__
);
goto
exit_generic
;
}
info
(
DRIVER_DESC
" "
DRIVER_VERSION
);
return
result
;
exit_generic:
usb_deregister
(
&
usb_serial_driver
);
exit_tty:
tty_unregister_driver
(
usb_serial_tty_driver
);
exit_reg_driver:
usb_serial_generic_deregister
();
exit_generic:
bus_unregister
(
&
usb_serial_bus_type
);
exit_bus:
...
...
fs/proc/proc_devtree.c
View file @
12725675
...
...
@@ -12,15 +12,8 @@
#include <asm/uaccess.h>
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
static
inline
void
set_node_proc_entry
(
struct
device_node
*
np
,
struct
proc_dir_entry
*
de
)
{
}
static
void
inline
set_node_name_link
(
struct
device_node
*
np
,
struct
proc_dir_entry
*
de
)
{
}
static
void
inline
set_node_addr_link
(
struct
device_node
*
np
,
struct
proc_dir_entry
*
de
)
static
inline
void
set_node_proc_entry
(
struct
device_node
*
np
,
struct
proc_dir_entry
*
de
)
{
}
#endif
...
...
@@ -58,89 +51,67 @@ static int property_read_proc(char *page, char **start, off_t off,
/*
* Process a node, adding entries for its children and its properties.
*/
void
proc_device_tree_add_node
(
struct
device_node
*
np
,
struct
proc_dir_entry
*
de
)
void
proc_device_tree_add_node
(
struct
device_node
*
np
,
struct
proc_dir_entry
*
de
)
{
struct
property
*
pp
;
struct
proc_dir_entry
*
ent
;
struct
device_node
*
child
,
*
sib
;
const
char
*
p
,
*
at
;
int
l
;
struct
proc_dir_entry
*
list
,
**
lastp
,
*
al
;
struct
device_node
*
child
;
struct
proc_dir_entry
*
list
=
NULL
,
**
lastp
;
const
char
*
p
;
set_node_proc_entry
(
np
,
de
);
lastp
=
&
list
;
for
(
pp
=
np
->
properties
;
pp
!=
0
;
pp
=
pp
->
next
)
{
/*
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
ent
=
create_proc_read_entry
(
pp
->
name
,
strncmp
(
pp
->
name
,
"security-"
,
9
)
?
S_IRUGO
:
S_IRUSR
,
de
,
property_read_proc
,
pp
);
if
(
ent
==
0
)
break
;
if
(
!
strncmp
(
pp
->
name
,
"security-"
,
9
))
ent
->
size
=
0
;
/* don't leak number of password chars */
else
ent
->
size
=
pp
->
length
;
*
lastp
=
ent
;
lastp
=
&
ent
->
next
;
}
child
=
NULL
;
while
((
child
=
of_get_next_child
(
np
,
child
)))
{
for
(
child
=
NULL
;
(
child
=
of_get_next_child
(
np
,
child
));)
{
p
=
strrchr
(
child
->
full_name
,
'/'
);
if
(
!
p
)
p
=
child
->
full_name
;
else
++
p
;
/* chop off '@0' if the name ends with that */
l
=
strlen
(
p
);
if
(
l
>
2
&&
p
[
l
-
2
]
==
'@'
&&
p
[
l
-
1
]
==
'0'
)
l
-=
2
;
ent
=
proc_mkdir
(
p
,
de
);
if
(
ent
==
0
)
break
;
*
lastp
=
ent
;
ent
->
next
=
NULL
;
lastp
=
&
ent
->
next
;
proc_device_tree_add_node
(
child
,
ent
);
/*
* If we left the address part on the name, consider
* adding symlinks from the name and address parts.
*/
if
(
p
[
l
]
!=
0
||
(
at
=
strchr
(
p
,
'@'
))
==
0
)
continue
;
}
of_node_put
(
child
);
for
(
pp
=
np
->
properties
;
pp
!=
0
;
pp
=
pp
->
next
)
{
/*
* If this is the first node with a given name property,
* add a symlink with the name property as its name.
* Yet another Apple device-tree bogosity: on some machines,
* they have properties & nodes with the same name. Those
* properties are quite unimportant for us though, thus we
* simply "skip" them here, but we do have to check.
*/
sib
=
NULL
;
while
((
sib
=
of_get_next_child
(
np
,
sib
))
&&
sib
!=
child
)
if
(
sib
->
name
&&
strcmp
(
sib
->
name
,
child
->
name
)
==
0
)
break
;
if
(
sib
==
child
&&
strncmp
(
p
,
child
->
name
,
l
)
!=
0
)
{
al
=
proc_symlink
(
child
->
name
,
de
,
ent
->
name
);
if
(
al
==
0
)
{
of_node_put
(
sib
);
for
(
ent
=
list
;
ent
!=
NULL
;
ent
=
ent
->
next
)
if
(
!
strcmp
(
ent
->
name
,
pp
->
name
))
break
;
}
set_node_name_link
(
child
,
al
);
*
lastp
=
al
;
lastp
=
&
al
->
next
;
if
(
ent
!=
NULL
)
{
printk
(
KERN_WARNING
"device-tree: property
\"
%s
\"
name"
" conflicts with node in %s
\n
"
,
pp
->
name
,
np
->
full_name
);
continue
;
}
of_node_put
(
sib
);
/*
* Add another directory with the @address part as its name.
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
al
=
proc_symlink
(
at
,
de
,
ent
->
name
);
if
(
al
==
0
)
ent
=
create_proc_read_entry
(
pp
->
name
,
strncmp
(
pp
->
name
,
"security-"
,
9
)
?
S_IRUGO
:
S_IRUSR
,
de
,
property_read_proc
,
pp
);
if
(
ent
==
0
)
break
;
set_node_addr_link
(
child
,
al
);
*
lastp
=
al
;
lastp
=
&
al
->
next
;
if
(
!
strncmp
(
pp
->
name
,
"security-"
,
9
))
ent
->
size
=
0
;
/* don't leak number of password chars */
else
ent
->
size
=
pp
->
length
;
ent
->
next
=
NULL
;
*
lastp
=
ent
;
lastp
=
&
ent
->
next
;
}
of_node_put
(
child
);
*
lastp
=
NULL
;
de
->
subdir
=
list
;
}
...
...
fs/udf/udftime.c
View file @
12725675
...
...
@@ -46,7 +46,7 @@
#endif
/* How many days come before each month (0-12). */
const
unsigned
short
int
__mon_yday
[
2
][
13
]
=
static
const
unsigned
short
int
__mon_yday
[
2
][
13
]
=
{
/* Normal years. */
{
0
,
31
,
59
,
90
,
120
,
151
,
181
,
212
,
243
,
273
,
304
,
334
,
365
},
...
...
include/asm-i386/timer.h
View file @
12725675
...
...
@@ -53,6 +53,7 @@ extern struct init_timer_opts timer_cyclone_init;
extern
unsigned
long
calibrate_tsc
(
void
);
extern
void
init_cpu_khz
(
void
);
extern
int
recalibrate_cpu_khz
(
void
);
#ifdef CONFIG_HPET_TIMER
extern
struct
init_timer_opts
timer_hpet_init
;
extern
unsigned
long
calibrate_tsc_hpet
(
unsigned
long
*
tsc_hpet_quotient_ptr
);
...
...
include/asm-ppc64/prom.h
View file @
12725675
...
...
@@ -147,9 +147,7 @@ struct device_node {
struct
device_node
*
sibling
;
struct
device_node
*
next
;
/* next device of same type */
struct
device_node
*
allnext
;
/* next in list of all nodes */
struct
proc_dir_entry
*
pde
;
/* this node's proc directory */
struct
proc_dir_entry
*
name_link
;
/* name symlink */
struct
proc_dir_entry
*
addr_link
;
/* addr symlink */
struct
proc_dir_entry
*
pde
;
/* this node's proc directory */
struct
kref
kref
;
unsigned
long
_flags
;
};
...
...
@@ -174,15 +172,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
dn
->
pde
=
de
;
}
static
void
inline
set_node_name_link
(
struct
device_node
*
dn
,
struct
proc_dir_entry
*
de
)
{
dn
->
name_link
=
de
;
}
static
void
inline
set_node_addr_link
(
struct
device_node
*
dn
,
struct
proc_dir_entry
*
de
)
{
dn
->
addr_link
=
de
;
}
/* OBSOLETE: Old stlye node lookup */
extern
struct
device_node
*
find_devices
(
const
char
*
name
);
...
...
include/linux/cpufreq.h
View file @
12725675
...
...
@@ -49,7 +49,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
/* Frequency values here are CPU kHz so that hardware which doesn't run
* with some frequencies can complain without having to guess what per
* cent / per mille means.
* Maximum transition latency is in
micr
oseconds - if it's unknown,
* Maximum transition latency is in
nan
oseconds - if it's unknown,
* CPUFREQ_ETERNAL shall be used.
*/
...
...
include/linux/pci_ids.h
View file @
12725675
...
...
@@ -1230,6 +1230,12 @@
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267
#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268
#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269
#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282
...
...
kernel/module.c
View file @
12725675
...
...
@@ -1758,6 +1758,7 @@ sys_init_module(void __user *umod,
const
char
__user
*
uargs
)
{
struct
module
*
mod
;
mm_segment_t
old_fs
=
get_fs
();
int
ret
=
0
;
/* Must have permission */
...
...
@@ -1775,6 +1776,9 @@ sys_init_module(void __user *umod,
return
PTR_ERR
(
mod
);
}
/* flush the icache in correct context */
set_fs
(
KERNEL_DS
);
/* Flush the instruction cache, since we've played with text */
if
(
mod
->
module_init
)
flush_icache_range
((
unsigned
long
)
mod
->
module_init
,
...
...
@@ -1783,6 +1787,8 @@ sys_init_module(void __user *umod,
flush_icache_range
((
unsigned
long
)
mod
->
module_core
,
(
unsigned
long
)
mod
->
module_core
+
mod
->
core_size
);
set_fs
(
old_fs
);
/* Now sew it into the lists. They won't access us, since
strong_try_module_get() will fail. */
stop_machine_run
(
__link_module
,
mod
,
NR_CPUS
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment