Skip to content

Commit

Permalink
Merge branch 'i7300_idle' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
lenb committed Oct 25, 2008
2 parents 438f8de + f371be6 commit 9fb3c5c
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 92 deletions.
7 changes: 5 additions & 2 deletions drivers/dma/ioat_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
#include <linux/i7300_idle.h>
#include "ioatdma.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
Expand Down Expand Up @@ -171,8 +172,10 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));

#if CONFIG_I7300_IDLE_IOAT_CHANNEL
device->common.chancnt--;
#ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL
if (i7300_idle_platform_probe(NULL, NULL) == 0) {
device->common.chancnt--;
}
#endif
for (i = 0; i < device->common.chancnt; i++) {
ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
Expand Down
11 changes: 6 additions & 5 deletions drivers/idle/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ config I7300_IDLE_IOAT_CHANNEL
bool

config I7300_IDLE
tristate "Intel chipset idle power saving driver"
tristate "Intel chipset idle memory power saving driver"
select I7300_IDLE_IOAT_CHANNEL
depends on X86_64
depends on X86_64 && EXPERIMENTAL
help
Enable idle power savings with certain Intel server chipsets.
The chipset must have I/O AT support, such as the Intel 7300.
The power savings depends on the type and quantity of DRAM devices.
Enable memory power savings when idle with certain Intel server
chipsets. The chipset must have I/O AT support, such as the
Intel 7300. The power savings depends on the type and quantity of
DRAM devices.

endmenu
105 changes: 20 additions & 85 deletions drivers/idle/i7300_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/debugfs.h>
#include <linux/stop_machine.h>
#include <linux/i7300_idle.h>

#include <asm/idle.h>

Expand All @@ -34,6 +35,8 @@
#define I7300_IDLE_DRIVER_VERSION "1.55"
#define I7300_PRINT "i7300_idle:"

#define MAX_STOP_RETRIES 10

static int debug;
module_param_named(debug, debug, uint, 0644);
MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
Expand All @@ -46,12 +49,12 @@ MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
* 0 = No throttling
* 1 = Throttle when > 4 activations per eval window (Maximum throttling)
* 2 = Throttle when > 8 activations
* 168 = Throttle when > 168 activations (Minimum throttling)
* 168 = Throttle when > 672 activations (Minimum throttling)
*/
#define MAX_THRTLWLIMIT 168
static uint i7300_idle_thrtlowlm = 1;
module_param_named(thrtlwlimit, i7300_idle_thrtlowlm, uint, 0644);
MODULE_PARM_DESC(thrtlwlimit,
#define MAX_THROTTLE_LOW_LIMIT 168
static uint throttle_low_limit = 1;
module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644);
MODULE_PARM_DESC(throttle_low_limit,
"Value for THRTLOWLM activation field "
"(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");

Expand Down Expand Up @@ -110,9 +113,9 @@ static int i7300_idle_ioat_start(void)
static void i7300_idle_ioat_stop(void)
{
int i;
u8 sts;
u64 sts;

for (i = 0; i < 5; i++) {
for (i = 0; i < MAX_STOP_RETRIES; i++) {
writeb(IOAT_CHANCMD_RESET,
ioat_chanbase + IOAT1_CHANCMD_OFFSET);

Expand All @@ -126,9 +129,10 @@ static void i7300_idle_ioat_stop(void)

}

if (i == 5)
dprintk("failed to suspend+reset I/O AT after 5 retries\n");

if (i == MAX_STOP_RETRIES) {
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 */
Expand Down Expand Up @@ -275,7 +279,7 @@ static void __exit i7300_idle_ioat_exit(void)
i7300_idle_ioat_stop();

/* 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,
ioat_chanbase + IOAT1_CHANCMD_OFFSET);

Expand Down Expand Up @@ -389,9 +393,9 @@ static void i7300_idle_start(void)
new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);

limit = i7300_idle_thrtlowlm;
if (unlikely(limit > MAX_THRTLWLIMIT))
limit = MAX_THRTLWLIMIT;
limit = throttle_low_limit;
if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT))
limit = MAX_THROTTLE_LOW_LIMIT;

pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);

Expand Down Expand Up @@ -440,7 +444,7 @@ static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
static ktime_t idle_begin_time;
static int time_init = 1;

if (!i7300_idle_thrtlowlm)
if (!throttle_low_limit)
return 0;

if (unlikely(time_init)) {
Expand Down Expand Up @@ -505,77 +509,8 @@ static struct notifier_block i7300_idle_nb = {
.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);

/* 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)
{
fp->private_data = inode->i_private;
Expand Down Expand Up @@ -617,7 +552,7 @@ static int __init i7300_idle_init(void)
cpus_clear(idle_cpumask);
total_us = 0;

if (i7300_idle_platform_probe())
if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev))
return -ENODEV;

if (i7300_idle_thrt_save())
Expand Down
83 changes: 83 additions & 0 deletions include/linux/i7300_idle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

#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

0 comments on commit 9fb3c5c

Please sign in to comment.