Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
9fb3c5ca
Commit
9fb3c5ca
authored
Oct 25, 2008
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'i7300_idle' into release
parents
438f8de4
f371be63
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
114 additions
and
92 deletions
+114
-92
drivers/dma/ioat_dma.c
drivers/dma/ioat_dma.c
+5
-2
drivers/idle/Kconfig
drivers/idle/Kconfig
+6
-5
drivers/idle/i7300_idle.c
drivers/idle/i7300_idle.c
+20
-85
include/linux/i7300_idle.h
include/linux/i7300_idle.h
+83
-0
No files found.
drivers/dma/ioat_dma.c
View file @
9fb3c5ca
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
#include <linux/workqueue.h>
#include <linux/i7300_idle.h>
#include "ioatdma.h"
#include "ioatdma.h"
#include "ioatdma_registers.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
#include "ioatdma_hw.h"
...
@@ -171,8 +172,10 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
...
@@ -171,8 +172,10 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
xfercap_scale
=
readb
(
device
->
reg_base
+
IOAT_XFERCAP_OFFSET
);
xfercap_scale
=
readb
(
device
->
reg_base
+
IOAT_XFERCAP_OFFSET
);
xfercap
=
(
xfercap_scale
==
0
?
-
1
:
(
1UL
<<
xfercap_scale
));
xfercap
=
(
xfercap_scale
==
0
?
-
1
:
(
1UL
<<
xfercap_scale
));
#if CONFIG_I7300_IDLE_IOAT_CHANNEL
#ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL
device
->
common
.
chancnt
--
;
if
(
i7300_idle_platform_probe
(
NULL
,
NULL
)
==
0
)
{
device
->
common
.
chancnt
--
;
}
#endif
#endif
for
(
i
=
0
;
i
<
device
->
common
.
chancnt
;
i
++
)
{
for
(
i
=
0
;
i
<
device
->
common
.
chancnt
;
i
++
)
{
ioat_chan
=
kzalloc
(
sizeof
(
*
ioat_chan
),
GFP_KERNEL
);
ioat_chan
=
kzalloc
(
sizeof
(
*
ioat_chan
),
GFP_KERNEL
);
...
...
drivers/idle/Kconfig
View file @
9fb3c5ca
...
@@ -5,12 +5,13 @@ config I7300_IDLE_IOAT_CHANNEL
...
@@ -5,12 +5,13 @@ config I7300_IDLE_IOAT_CHANNEL
bool
bool
config I7300_IDLE
config I7300_IDLE
tristate "Intel chipset idle power saving driver"
tristate "Intel chipset idle
memory
power saving driver"
select I7300_IDLE_IOAT_CHANNEL
select I7300_IDLE_IOAT_CHANNEL
depends on X86_64
depends on X86_64
&& EXPERIMENTAL
help
help
Enable idle power savings with certain Intel server chipsets.
Enable memory power savings when idle with certain Intel server
The chipset must have I/O AT support, such as the Intel 7300.
chipsets. The chipset must have I/O AT support, such as the
The power savings depends on the type and quantity of DRAM devices.
Intel 7300. The power savings depends on the type and quantity of
DRAM devices.
endmenu
endmenu
drivers/idle/i7300_idle.c
View file @
9fb3c5ca
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/debugfs.h>
#include <linux/stop_machine.h>
#include <linux/stop_machine.h>
#include <linux/i7300_idle.h>
#include <asm/idle.h>
#include <asm/idle.h>
...
@@ -34,6 +35,8 @@
...
@@ -34,6 +35,8 @@
#define I7300_IDLE_DRIVER_VERSION "1.55"
#define I7300_IDLE_DRIVER_VERSION "1.55"
#define I7300_PRINT "i7300_idle:"
#define I7300_PRINT "i7300_idle:"
#define MAX_STOP_RETRIES 10
static
int
debug
;
static
int
debug
;
module_param_named
(
debug
,
debug
,
uint
,
0644
);
module_param_named
(
debug
,
debug
,
uint
,
0644
);
MODULE_PARM_DESC
(
debug
,
"Enable debug printks in this driver"
);
MODULE_PARM_DESC
(
debug
,
"Enable debug printks in this driver"
);
...
@@ -46,12 +49,12 @@ MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
...
@@ -46,12 +49,12 @@ MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
* 0 = No throttling
* 0 = No throttling
* 1 = Throttle when > 4 activations per eval window (Maximum throttling)
* 1 = Throttle when > 4 activations per eval window (Maximum throttling)
* 2 = Throttle when > 8 activations
* 2 = Throttle when > 8 activations
* 168 = Throttle when >
168
activations (Minimum throttling)
* 168 = Throttle when >
672
activations (Minimum throttling)
*/
*/
#define MAX_THR
TLW
LIMIT 168
#define MAX_THR
OTTLE_LOW_
LIMIT 168
static
uint
i7300_idle_thrtlowlm
=
1
;
static
uint
throttle_low_limit
=
1
;
module_param_named
(
thr
tlwlimit
,
i7300_idle_thrtlowlm
,
uint
,
0644
);
module_param_named
(
thr
ottle_low_limit
,
throttle_low_limit
,
uint
,
0644
);
MODULE_PARM_DESC
(
thr
tlw
limit
,
MODULE_PARM_DESC
(
thr
ottle_low_
limit
,
"Value for THRTLOWLM activation field "
"Value for THRTLOWLM activation field "
"(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)"
);
"(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)"
);
...
@@ -110,9 +113,9 @@ static int i7300_idle_ioat_start(void)
...
@@ -110,9 +113,9 @@ static int i7300_idle_ioat_start(void)
static
void
i7300_idle_ioat_stop
(
void
)
static
void
i7300_idle_ioat_stop
(
void
)
{
{
int
i
;
int
i
;
u
8
sts
;
u
64
sts
;
for
(
i
=
0
;
i
<
5
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_STOP_RETRIES
;
i
++
)
{
writeb
(
IOAT_CHANCMD_RESET
,
writeb
(
IOAT_CHANCMD_RESET
,
ioat_chanbase
+
IOAT1_CHANCMD_OFFSET
);
ioat_chanbase
+
IOAT1_CHANCMD_OFFSET
);
...
@@ -126,9 +129,10 @@ static void i7300_idle_ioat_stop(void)
...
@@ -126,9 +129,10 @@ static void i7300_idle_ioat_stop(void)
}
}
if
(
i
==
5
)
if
(
i
==
MAX_STOP_RETRIES
)
{
dprintk
(
"failed to suspend+reset I/O AT after 5 retries
\n
"
);
dprintk
(
"failed to stop I/O AT after %d retries
\n
"
,
MAX_STOP_RETRIES
);
}
}
}
/* Test I/O AT by copying 1024 byte from 2k to 1k */
/* Test I/O AT by copying 1024 byte from 2k to 1k */
...
@@ -275,7 +279,7 @@ static void __exit i7300_idle_ioat_exit(void)
...
@@ -275,7 +279,7 @@ static void __exit i7300_idle_ioat_exit(void)
i7300_idle_ioat_stop
();
i7300_idle_ioat_stop
();
/* Wait for a while for the channel to halt before releasing */
/* Wait for a while for the channel to halt before releasing */
for
(
i
=
0
;
i
<
10
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_STOP_RETRIES
;
i
++
)
{
writeb
(
IOAT_CHANCMD_RESET
,
writeb
(
IOAT_CHANCMD_RESET
,
ioat_chanbase
+
IOAT1_CHANCMD_OFFSET
);
ioat_chanbase
+
IOAT1_CHANCMD_OFFSET
);
...
@@ -389,9 +393,9 @@ static void i7300_idle_start(void)
...
@@ -389,9 +393,9 @@ static void i7300_idle_start(void)
new_ctl
=
i7300_idle_thrtctl_saved
&
~
DIMM_THRTCTL_THRMHUNT
;
new_ctl
=
i7300_idle_thrtctl_saved
&
~
DIMM_THRTCTL_THRMHUNT
;
pci_write_config_byte
(
fbd_dev
,
DIMM_THRTCTL
,
new_ctl
);
pci_write_config_byte
(
fbd_dev
,
DIMM_THRTCTL
,
new_ctl
);
limit
=
i7300_idle_thrtlowlm
;
limit
=
throttle_low_limit
;
if
(
unlikely
(
limit
>
MAX_THR
TLW
LIMIT
))
if
(
unlikely
(
limit
>
MAX_THR
OTTLE_LOW_
LIMIT
))
limit
=
MAX_THR
TLW
LIMIT
;
limit
=
MAX_THR
OTTLE_LOW_
LIMIT
;
pci_write_config_byte
(
fbd_dev
,
DIMM_THRTLOW
,
limit
);
pci_write_config_byte
(
fbd_dev
,
DIMM_THRTLOW
,
limit
);
...
@@ -440,7 +444,7 @@ static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
...
@@ -440,7 +444,7 @@ static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
static
ktime_t
idle_begin_time
;
static
ktime_t
idle_begin_time
;
static
int
time_init
=
1
;
static
int
time_init
=
1
;
if
(
!
i7300_idle_thrtlowlm
)
if
(
!
throttle_low_limit
)
return
0
;
return
0
;
if
(
unlikely
(
time_init
))
{
if
(
unlikely
(
time_init
))
{
...
@@ -505,77 +509,8 @@ static struct notifier_block i7300_idle_nb = {
...
@@ -505,77 +509,8 @@ static struct notifier_block i7300_idle_nb = {
.
notifier_call
=
i7300_idle_notifier
,
.
notifier_call
=
i7300_idle_notifier
,
};
};
/*
* I/O AT controls (PCI bus 0 device 8 function 0)
* DIMM controls (PCI bus 0 device 16 function 1)
*/
#define IOAT_BUS 0
#define IOAT_DEVFN PCI_DEVFN(8, 0)
#define MEMCTL_BUS 0
#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
struct
fbd_ioat
{
unsigned
int
vendor
;
unsigned
int
ioat_dev
;
};
/*
* The i5000 chip-set has the same hooks as the i7300
* but support is disabled by default because this driver
* has not been validated on that platform.
*/
#define SUPPORT_I5000 0
static
const
struct
fbd_ioat
fbd_ioat_list
[]
=
{
{
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_IOAT_CNB
},
#if SUPPORT_I5000
{
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_IOAT
},
#endif
{
0
,
0
}
};
/* table of devices that work with this driver */
static
const
struct
pci_device_id
pci_tbl
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_FBD_CNB
)
},
#if SUPPORT_I5000
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_5000_ERR
)
},
#endif
{
}
/* Terminating entry */
};
MODULE_DEVICE_TABLE
(
pci
,
pci_tbl
);
MODULE_DEVICE_TABLE
(
pci
,
pci_tbl
);
/* Check for known platforms with I/O-AT */
static
int
__init
i7300_idle_platform_probe
(
void
)
{
int
i
;
fbd_dev
=
pci_get_bus_and_slot
(
MEMCTL_BUS
,
MEMCTL_DEVFN
);
if
(
!
fbd_dev
)
return
-
ENODEV
;
for
(
i
=
0
;
pci_tbl
[
i
].
vendor
!=
0
;
i
++
)
{
if
(
fbd_dev
->
vendor
==
pci_tbl
[
i
].
vendor
&&
fbd_dev
->
device
==
pci_tbl
[
i
].
device
)
{
break
;
}
}
if
(
pci_tbl
[
i
].
vendor
==
0
)
return
-
ENODEV
;
ioat_dev
=
pci_get_bus_and_slot
(
IOAT_BUS
,
IOAT_DEVFN
);
if
(
!
ioat_dev
)
return
-
ENODEV
;
for
(
i
=
0
;
fbd_ioat_list
[
i
].
vendor
!=
0
;
i
++
)
{
if
(
ioat_dev
->
vendor
==
fbd_ioat_list
[
i
].
vendor
&&
ioat_dev
->
device
==
fbd_ioat_list
[
i
].
ioat_dev
)
{
return
0
;
}
}
return
-
ENODEV
;
}
int
stats_open_generic
(
struct
inode
*
inode
,
struct
file
*
fp
)
int
stats_open_generic
(
struct
inode
*
inode
,
struct
file
*
fp
)
{
{
fp
->
private_data
=
inode
->
i_private
;
fp
->
private_data
=
inode
->
i_private
;
...
@@ -617,7 +552,7 @@ static int __init i7300_idle_init(void)
...
@@ -617,7 +552,7 @@ static int __init i7300_idle_init(void)
cpus_clear
(
idle_cpumask
);
cpus_clear
(
idle_cpumask
);
total_us
=
0
;
total_us
=
0
;
if
(
i7300_idle_platform_probe
())
if
(
i7300_idle_platform_probe
(
&
fbd_dev
,
&
ioat_dev
))
return
-
ENODEV
;
return
-
ENODEV
;
if
(
i7300_idle_thrt_save
())
if
(
i7300_idle_thrt_save
())
...
...
include/linux/i7300_idle.h
0 → 100644
View file @
9fb3c5ca
#ifndef I7300_IDLE_H
#define I7300_IDLE_H
#include <linux/pci.h>
/*
* I/O AT controls (PCI bus 0 device 8 function 0)
* DIMM controls (PCI bus 0 device 16 function 1)
*/
#define IOAT_BUS 0
#define IOAT_DEVFN PCI_DEVFN(8, 0)
#define MEMCTL_BUS 0
#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
struct
fbd_ioat
{
unsigned
int
vendor
;
unsigned
int
ioat_dev
;
};
/*
* The i5000 chip-set has the same hooks as the i7300
* but support is disabled by default because this driver
* has not been validated on that platform.
*/
#define SUPPORT_I5000 0
static
const
struct
fbd_ioat
fbd_ioat_list
[]
=
{
{
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_IOAT_CNB
},
#if SUPPORT_I5000
{
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_IOAT
},
#endif
{
0
,
0
}
};
/* table of devices that work with this driver */
static
const
struct
pci_device_id
pci_tbl
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_FBD_CNB
)
},
#if SUPPORT_I5000
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_5000_ERR
)
},
#endif
{
}
/* Terminating entry */
};
/* Check for known platforms with I/O-AT */
static
inline
int
i7300_idle_platform_probe
(
struct
pci_dev
**
fbd_dev
,
struct
pci_dev
**
ioat_dev
)
{
int
i
;
struct
pci_dev
*
memdev
,
*
dmadev
;
memdev
=
pci_get_bus_and_slot
(
MEMCTL_BUS
,
MEMCTL_DEVFN
);
if
(
!
memdev
)
return
-
ENODEV
;
for
(
i
=
0
;
pci_tbl
[
i
].
vendor
!=
0
;
i
++
)
{
if
(
memdev
->
vendor
==
pci_tbl
[
i
].
vendor
&&
memdev
->
device
==
pci_tbl
[
i
].
device
)
{
break
;
}
}
if
(
pci_tbl
[
i
].
vendor
==
0
)
return
-
ENODEV
;
dmadev
=
pci_get_bus_and_slot
(
IOAT_BUS
,
IOAT_DEVFN
);
if
(
!
dmadev
)
return
-
ENODEV
;
for
(
i
=
0
;
fbd_ioat_list
[
i
].
vendor
!=
0
;
i
++
)
{
if
(
dmadev
->
vendor
==
fbd_ioat_list
[
i
].
vendor
&&
dmadev
->
device
==
fbd_ioat_list
[
i
].
ioat_dev
)
{
if
(
fbd_dev
)
*
fbd_dev
=
memdev
;
if
(
ioat_dev
)
*
ioat_dev
=
dmadev
;
return
0
;
}
}
return
-
ENODEV
;
}
#endif
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